From 18499e46a49b8ccf4346686d1cf626ada33935b8 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 23 Nov 2020 19:48:34 +0100 Subject: 2020-11-23 18:39:00 --- .../context/lexers/data/scite-context-data-tex.lua | 2 +- .../context/scite-context-data-tex.properties | 59 +- .../context/data/scite-context-data-tex.lua | 2 +- .../context/syntaxes/context-syntax-tex.json | 2 +- .../general/manuals/lowlevel-grouping.pdf | Bin 30758 -> 30762 bytes doc/context/documents/general/qrcs/setup-en.pdf | Bin 959252 -> 964271 bytes doc/context/documents/general/qrcs/setup-fr.pdf | Bin 949812 -> 961139 bytes doc/context/documents/general/qrcs/setup-it.pdf | Bin 951836 -> 958795 bytes .../documents/general/qrcs/setup-mapping-en.pdf | Bin 352487 -> 353944 bytes .../documents/general/qrcs/setup-mapping-fr.pdf | Bin 354769 -> 357670 bytes .../documents/general/qrcs/setup-mapping-it.pdf | Bin 353445 -> 356064 bytes .../manuals/lowlevel/lowlevel-expansion.tex | 19 + .../general/manuals/lowlevel/lowlevel-security.tex | 6 + metapost/context/base/mpiv/metafun.mpxl | 46 - metapost/context/base/mpiv/minifun.mpxl | 35 - metapost/context/base/mpiv/mp-cont.mpxl | 158 - metapost/context/base/mpiv/mp-lmtx.mpxl | 2281 ------- metapost/context/base/mpiv/mp-luas.mpxl | 250 - metapost/context/base/mpiv/mp-math.mpxl | 161 - metapost/context/base/mpiv/mp-page.mpxl | 243 - metapost/context/base/mpxl/metafun.mpxl | 46 + metapost/context/base/mpxl/minifun.mpxl | 35 + metapost/context/base/mpxl/mp-cont.mpxl | 158 + metapost/context/base/mpxl/mp-lmtx.mpxl | 2281 +++++++ metapost/context/base/mpxl/mp-luas.mpxl | 250 + metapost/context/base/mpxl/mp-math.mpxl | 161 + metapost/context/base/mpxl/mp-page.mpxl | 243 + scripts/context/lua/mtx-context.lua | 6 + tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkii/mult-de.mkii | 5 +- tex/context/base/mkiv/anch-bar.mkxl | 220 - tex/context/base/mkiv/anch-bck.mklx | 747 --- tex/context/base/mkiv/anch-pgr.mkxl | 445 -- tex/context/base/mkiv/anch-pos.lmt | 1633 ----- tex/context/base/mkiv/anch-pos.mkxl | 504 -- tex/context/base/mkiv/anch-snc.mkxl | 160 - tex/context/base/mkiv/anch-tab.mkxl | 382 -- tex/context/base/mkiv/attr-col.mkxl | 22 - tex/context/base/mkiv/attr-eff.mkxl | 60 - tex/context/base/mkiv/attr-ini.mkxl | 143 - tex/context/base/mkiv/attr-lay.lmt | 311 - tex/context/base/mkiv/attr-lay.mkxl | 105 - tex/context/base/mkiv/attr-mkr.mkxl | 25 - tex/context/base/mkiv/attr-neg.mkxl | 28 - tex/context/base/mkiv/back-exp.mkxl | 356 -- tex/context/base/mkiv/back-ini.mkxl | 80 - tex/context/base/mkiv/back-lua.lmt | 366 -- tex/context/base/mkiv/back-lua.mkxl | 16 - tex/context/base/mkiv/back-mps.lmt | 210 - tex/context/base/mkiv/back-mps.mkxl | 16 - tex/context/base/mkiv/back-out.lmt | 255 - tex/context/base/mkiv/back-out.mkxl | 22 - tex/context/base/mkiv/back-pdf.mkxl | 157 - tex/context/base/mkiv/back-res.mkxl | 34 - tex/context/base/mkiv/back-trf.mkxl | 79 - tex/context/base/mkiv/bibl-bib.mkxl | 982 --- tex/context/base/mkiv/bibl-tra.mkxl | 1509 ----- tex/context/base/mkiv/blob-ini.lmt | 210 - tex/context/base/mkiv/blob-ini.mkxl | 56 - tex/context/base/mkiv/buff-ver.mkxl | 998 --- tex/context/base/mkiv/catc-act.mkxl | 51 - tex/context/base/mkiv/catc-ctx.mkxl | 162 - tex/context/base/mkiv/catc-def.mkxl | 147 - tex/context/base/mkiv/catc-ini.mkxl | 329 - tex/context/base/mkiv/catc-sym.mkxl | 95 - tex/context/base/mkiv/char-act.mkxl | 99 - tex/context/base/mkiv/char-def.lua | 1 + tex/context/base/mkiv/char-enc.mkxl | 18 - tex/context/base/mkiv/char-ini.mkxl | 130 - tex/context/base/mkiv/char-tex.lua | 6 +- tex/context/base/mkiv/char-utf.mkxl | 44 - tex/context/base/mkiv/chem-ini.mkxl | 53 - tex/context/base/mkiv/chem-str.mkxl | 749 --- tex/context/base/mkiv/cldf-bas.mkxl | 19 - tex/context/base/mkiv/cldf-com.mkxl | 19 - tex/context/base/mkiv/cldf-ini.mkxl | 45 - tex/context/base/mkiv/cldf-int.lmt | 252 - tex/context/base/mkiv/cldf-int.mkxl | 34 - tex/context/base/mkiv/cldf-lmt.lmt | 949 --- tex/context/base/mkiv/cldf-ver.mkxl | 18 - tex/context/base/mkiv/colo-ext.mkxl | 99 - tex/context/base/mkiv/colo-grp.mkxl | 163 - tex/context/base/mkiv/colo-ini.mkxl | 1370 ---- tex/context/base/mkiv/cont-cs.mkxl | 21 - tex/context/base/mkiv/cont-de.mkxl | 21 - tex/context/base/mkiv/cont-en.mkxl | 21 - tex/context/base/mkiv/cont-fil.mkiv | 5 - tex/context/base/mkiv/cont-fr.mkxl | 21 - tex/context/base/mkiv/cont-gb.mkxl | 21 - tex/context/base/mkiv/cont-it.mkxl | 21 - tex/context/base/mkiv/cont-new.mkiv | 12 +- tex/context/base/mkiv/cont-nl.mkxl | 21 - tex/context/base/mkiv/cont-pe.mkxl | 22 - tex/context/base/mkiv/cont-ro.mkxl | 21 - tex/context/base/mkiv/cont-run.mkiv | 18 +- tex/context/base/mkiv/cont-yes.mkiv | 85 +- tex/context/base/mkiv/context.mkiv | 4 +- tex/context/base/mkiv/context.mkxl | 618 -- tex/context/base/mkiv/core-con.mkxl | 1013 --- tex/context/base/mkiv/core-ctx.mkxl | 29 - tex/context/base/mkiv/core-dat.mkxl | 110 - tex/context/base/mkiv/core-def.mkxl | 182 - tex/context/base/mkiv/core-env.lmt | 213 - tex/context/base/mkiv/core-env.mkxl | 770 --- tex/context/base/mkiv/core-ini.mkxl | 224 - tex/context/base/mkiv/core-lmt.lmt | 95 - tex/context/base/mkiv/core-lmt.mkxl | 28 - tex/context/base/mkiv/core-sys.lmt | 91 - tex/context/base/mkiv/core-sys.mkxl | 446 -- tex/context/base/mkiv/core-two.mkxl | 109 - tex/context/base/mkiv/core-uti.mkxl | 35 - tex/context/base/mkiv/driv-ini.mkxl | 20 - tex/context/base/mkiv/driv-shp.lmt | 1360 ---- tex/context/base/mkiv/driv-shp.mkxl | 18 - tex/context/base/mkiv/enco-ini.mkxl | 570 -- tex/context/base/mkiv/file-ini.mklx | 231 - tex/context/base/mkiv/file-job.lmt | 1283 ---- tex/context/base/mkiv/file-job.mklx | 348 - tex/context/base/mkiv/file-lib.mkxl | 20 - tex/context/base/mkiv/file-mod.mklx | 289 - tex/context/base/mkiv/file-res.mklx | 145 - tex/context/base/mkiv/file-syn.mklx | 61 - tex/context/base/mkiv/font-aux.mklx | 26 - tex/context/base/mkiv/font-chk.mkxl | 29 - tex/context/base/mkiv/font-col.mklx | 148 - tex/context/base/mkiv/font-emp.mklx | 256 - tex/context/base/mkiv/font-fea.mklx | 382 -- tex/context/base/mkiv/font-fil.mklx | 385 -- tex/context/base/mkiv/font-ini.mklx | 2512 -------- tex/context/base/mkiv/font-lib.mkvi | 18 +- tex/context/base/mkiv/font-mat.mklx | 490 -- tex/context/base/mkiv/font-ogr.lmt | 673 -- tex/context/base/mkiv/font-pre.mkxl | 999 --- tex/context/base/mkiv/font-sol.mklx | 131 - tex/context/base/mkiv/font-sty.mklx | 441 -- tex/context/base/mkiv/font-sym.mklx | 246 - tex/context/base/mkiv/font-tra.mkxl | 343 - tex/context/base/mkiv/grph-epd.mkxl | 91 - tex/context/base/mkiv/grph-fig.mkxl | 357 -- tex/context/base/mkiv/grph-inc.mkxl | 1076 ---- tex/context/base/mkiv/grph-pat.mkxl | 119 - tex/context/base/mkiv/grph-raw.mkxl | 64 - tex/context/base/mkiv/grph-rul.mkxl | 89 - tex/context/base/mkiv/grph-trf.mkxl | 1011 --- tex/context/base/mkiv/hand-ini.mkxl | 113 - tex/context/base/mkiv/java-ini.mkxl | 157 - tex/context/base/mkiv/lang-dis.lmt | 222 - tex/context/base/mkiv/lang-hyp.lmt | 1806 ------ tex/context/base/mkiv/lang-ini.lmt | 670 -- tex/context/base/mkiv/lang-ini.mkxl | 766 --- tex/context/base/mkiv/lang-lab.mkxl | 364 -- tex/context/base/mkiv/lang-mis.mkxl | 586 -- tex/context/base/mkiv/lang-url.mkxl | 167 - tex/context/base/mkiv/layo-ini.mkxl | 30 - tex/context/base/mkiv/libs-imp-curl.lmt | 296 - tex/context/base/mkiv/libs-imp-ghostscript.lmt | 111 - tex/context/base/mkiv/libs-imp-graphicsmagick.lmt | 77 - tex/context/base/mkiv/libs-imp-kpse.lmt | 58 - tex/context/base/mkiv/libs-imp-kpse.mkxl | 38 - tex/context/base/mkiv/libs-imp-mujs.lmt | 126 - tex/context/base/mkiv/libs-imp-mujs.mkxl | 121 - tex/context/base/mkiv/libs-imp-mysql.lmt | 220 - tex/context/base/mkiv/libs-imp-postgress.lmt | 200 - tex/context/base/mkiv/libs-imp-sqlite.lmt | 187 - tex/context/base/mkiv/libs-imp-zint.lmt | 161 - tex/context/base/mkiv/libs-imp-zint.mkxl | 64 - tex/context/base/mkiv/libs-ini.mkxl | 32 - tex/context/base/mkiv/lpdf-emb.lmt | 2236 ------- tex/context/base/mkiv/lpdf-img.lmt | 1341 ---- tex/context/base/mkiv/lpdf-lmt.lmt | 2840 --------- tex/context/base/mkiv/lpdf-vfc.lmt | 40 - tex/context/base/mkiv/luat-cod.lmt | 304 - tex/context/base/mkiv/luat-cod.mkxl | 45 - tex/context/base/mkiv/luat-fio.lmt | 107 - tex/context/base/mkiv/luat-ini.mkiv | 1 - tex/context/base/mkiv/luat-lib.mkiv | 14 +- tex/context/base/mkiv/luat-log.lmt | 739 --- tex/context/base/mkiv/lxml-css.mkxl | 76 - tex/context/base/mkiv/lxml-ctx.mkxl | 58 - tex/context/base/mkiv/lxml-ini.mkxl | 544 -- tex/context/base/mkiv/lxml-sor.mkxl | 99 - tex/context/base/mkiv/m-mkivmkxl.mkxl | 3 - tex/context/base/mkiv/math-ali.mkxl | 1898 ------ tex/context/base/mkiv/math-fen.mkxl | 829 --- tex/context/base/mkiv/math-frc.mkxl | 833 --- tex/context/base/mkiv/math-ini.lua | 35 +- tex/context/base/mkiv/math-ini.mkxl | 3032 --------- tex/context/base/mkiv/math-noa.lmt | 2399 ------- tex/context/base/mkiv/math-pln.mkxl | 245 - tex/context/base/mkiv/math-stc.mklx | 1390 ---- tex/context/base/mkiv/math-tag.lmt | 596 -- tex/context/base/mkiv/math-toy.mkxl | 54 - tex/context/base/mkiv/meta-imp-experiments.mkxl | 358 -- tex/context/base/mkiv/meta-imp-gamesymbols.mkxl | 349 - tex/context/base/mkiv/meta-imp-symbols.mkxl | 99 - tex/context/base/mkiv/meta-imp-threesix.mkxl | 246 - tex/context/base/mkiv/meta-ini.mkxl | 1385 ---- tex/context/base/mkiv/meta-mac.mkxl | 45 - tex/context/base/mkiv/meta-pag.mkxl | 26 - tex/context/base/mkiv/mlib-cnt.lmt | 2022 ------ tex/context/base/mkiv/mlib-ctx.mkxl | 32 - tex/context/base/mkiv/mlib-fio.lmt | 191 - tex/context/base/mkiv/mlib-int.lmt | 135 - tex/context/base/mkiv/mlib-lmp.lmt | 70 - tex/context/base/mkiv/mlib-lmt.lmt | 153 - tex/context/base/mkiv/mlib-lua.lmt | 168 - tex/context/base/mkiv/mlib-mat.lmt | 139 - tex/context/base/mkiv/mlib-pdf.mkxl | 162 - tex/context/base/mkiv/mlib-pps.mkxl | 215 - tex/context/base/mkiv/mlib-ran.lmt | 237 - tex/context/base/mkiv/mlib-scn.lmt | 780 --- tex/context/base/mkiv/mlib-svg.lmt | 3277 ---------- tex/context/base/mkiv/mult-aux.mkxl | 1177 ---- tex/context/base/mkiv/mult-def.lua | 8 +- tex/context/base/mkiv/mult-def.mkxl | 32 - tex/context/base/mkiv/mult-dim.mklx | 156 - tex/context/base/mkiv/mult-ini.mkxl | 805 --- tex/context/base/mkiv/mult-prm.lua | 4 + tex/context/base/mkiv/mult-prm.mkxl | 117 - tex/context/base/mkiv/mult-sys.mkxl | 602 -- tex/context/base/mkiv/node-aux.lmt | 396 -- tex/context/base/mkiv/node-bck.mkxl | 92 - tex/context/base/mkiv/node-cmp.lmt | 237 - tex/context/base/mkiv/node-fin.mkxl | 78 - tex/context/base/mkiv/node-gcm.lmt | 112 - tex/context/base/mkiv/node-ini.lmt | 280 - tex/context/base/mkiv/node-ini.mkxl | 56 - tex/context/base/mkiv/node-mig.lmt | 134 - tex/context/base/mkiv/node-mig.mkxl | 44 - tex/context/base/mkiv/node-nut.lmt | 579 -- tex/context/base/mkiv/node-par.lmt | 48 - tex/context/base/mkiv/node-ref.lua | 5 + tex/context/base/mkiv/node-rul.mkxl | 618 -- tex/context/base/mkiv/node-ser.lmt | 285 - tex/context/base/mkiv/node-snp.lmt | 69 - tex/context/base/mkiv/node-tex.lmt | 39 - tex/context/base/mkiv/norm-ctx.mkxl | 87 - tex/context/base/mkiv/pack-bar.mkxl | 94 - tex/context/base/mkiv/pack-bck.mklx | 245 - tex/context/base/mkiv/pack-box.mkxl | 1114 ---- tex/context/base/mkiv/pack-com.mkxl | 949 --- tex/context/base/mkiv/pack-lyr.mkxl | 772 --- tex/context/base/mkiv/pack-mrl.mkxl | 850 --- tex/context/base/mkiv/pack-ori.lmt | 70 - tex/context/base/mkiv/pack-ori.mkxl | 97 - tex/context/base/mkiv/pack-rul.mkxl | 3014 --------- tex/context/base/mkiv/page-bck.mkxl | 715 --- tex/context/base/mkiv/page-imp.mkiv | 6 +- tex/context/base/mkiv/page-ini.mkxl | 376 -- tex/context/base/mkiv/page-ins.mkiv | 9 +- tex/context/base/mkiv/page-lay.mkxl | 1623 ----- tex/context/base/mkiv/page-mcl.mkxl | 543 -- tex/context/base/mkiv/page-mix.mkxl | 1092 ---- tex/context/base/mkiv/page-not.mkxl | 32 - tex/context/base/mkiv/page-one.mkxl | 709 --- tex/context/base/mkiv/page-otr.mklx | 335 - tex/context/base/mkiv/page-spr.mkxl | 131 - tex/context/base/mkiv/page-txt.mklx | 950 --- tex/context/base/mkiv/phys-dim.mkxl | 808 --- tex/context/base/mkiv/prop-ini.mkiv | 64 - tex/context/base/mkiv/publ-inc.mkxl | 63 - tex/context/base/mkiv/publ-ini.mkxl | 2029 ------ tex/context/base/mkiv/publ-tra.mkxl | 84 - tex/context/base/mkiv/publ-xml.mkxl | 111 - tex/context/base/mkiv/regi-ini.mkxl | 37 - tex/context/base/mkiv/scrn-ini.mklx | 254 - tex/context/base/mkiv/scrn-pag.mklx | 310 - tex/context/base/mkiv/scrp-ini.mkiv | 4 +- tex/context/base/mkiv/spac-ali.mkxl | 1243 ---- tex/context/base/mkiv/spac-chr.lua | 3 +- tex/context/base/mkiv/spac-chr.mkxl | 103 - tex/context/base/mkiv/spac-grd.mkxl | 375 -- tex/context/base/mkiv/spac-hor.mkxl | 1259 ---- tex/context/base/mkiv/spac-par.lmt | 80 - tex/context/base/mkiv/spac-par.mkxl | 446 -- tex/context/base/mkiv/spac-ver.lmt | 2527 -------- tex/context/base/mkiv/spac-ver.mkxl | 2468 ------- tex/context/base/mkiv/status-files.pdf | Bin 29907 -> 26166 bytes tex/context/base/mkiv/status-lua.pdf | Bin 256345 -> 256281 bytes tex/context/base/mkiv/strc-bkm.mkxl | 182 - tex/context/base/mkiv/strc-blk.mkxl | 171 - tex/context/base/mkiv/strc-con.mklx | 1158 ---- tex/context/base/mkiv/strc-des.mklx | 194 - tex/context/base/mkiv/strc-doc.mkxl | 45 - tex/context/base/mkiv/strc-enu.mklx | 371 -- tex/context/base/mkiv/strc-flt.mklx | 2599 -------- tex/context/base/mkiv/strc-ind.mkxl | 128 - tex/context/base/mkiv/strc-ini.mklx | 81 - tex/context/base/mkiv/strc-itm.mklx | 1886 ------ tex/context/base/mkiv/strc-lab.mkxl | 198 - tex/context/base/mkiv/strc-lev.mklx | 101 - tex/context/base/mkiv/strc-lev.mkvi | 32 +- tex/context/base/mkiv/strc-lnt.mklx | 359 -- tex/context/base/mkiv/strc-lst.mklx | 1566 ----- tex/context/base/mkiv/strc-mar.mkxl | 135 - tex/context/base/mkiv/strc-mat.mkxl | 1308 ---- tex/context/base/mkiv/strc-not.mklx | 1972 ------ tex/context/base/mkiv/strc-num.mkxl | 687 -- tex/context/base/mkiv/strc-pag.mkxl | 497 -- tex/context/base/mkiv/strc-ref.mklx | 2196 ------- tex/context/base/mkiv/strc-reg.mkxl | 1210 ---- tex/context/base/mkiv/strc-ren.mkxl | 817 --- tex/context/base/mkiv/strc-sbe.mkxl | 139 - tex/context/base/mkiv/strc-sec.mkxl | 1321 ---- tex/context/base/mkiv/strc-syn.mkxl | 658 -- tex/context/base/mkiv/strc-tag.lmt | 615 -- tex/context/base/mkiv/strc-tag.mkxl | 531 -- tex/context/base/mkiv/strc-tnt.mkxl | 117 - tex/context/base/mkiv/strc-usr.mkxl | 169 - tex/context/base/mkiv/supp-box.lmt | 1335 ---- tex/context/base/mkiv/supp-box.mkxl | 2901 --------- tex/context/base/mkiv/supp-dir.mkxl | 54 - tex/context/base/mkiv/supp-mat.mkxl | 180 - tex/context/base/mkiv/symb-emj.mkxl | 26 - tex/context/base/mkiv/symb-ini.mkxl | 341 - tex/context/base/mkiv/syst-aux.lmt | 747 --- tex/context/base/mkiv/syst-aux.mkxl | 6678 ------------------- tex/context/base/mkiv/syst-con.mkxl | 88 - tex/context/base/mkiv/syst-fnt.mkxl | 47 - tex/context/base/mkiv/syst-ini.mkiv | 11 + tex/context/base/mkiv/syst-ini.mkxl | 1096 ---- tex/context/base/mkiv/syst-lua.lmt | 434 -- tex/context/base/mkiv/syst-lua.mkxl | 100 - tex/context/base/mkiv/syst-mac.lmt | 117 - tex/context/base/mkiv/tabl-com.mkxl | 92 - tex/context/base/mkiv/tabl-frm.mkxl | 261 - tex/context/base/mkiv/tabl-ltb.mkxl | 813 --- tex/context/base/mkiv/tabl-mis.mkxl | 294 - tex/context/base/mkiv/tabl-ntb.mkxl | 2172 ------- tex/context/base/mkiv/tabl-nte.mkxl | 107 - tex/context/base/mkiv/tabl-tab.mkxl | 2230 ------- tex/context/base/mkiv/tabl-tbl.mkxl | 2929 --------- tex/context/base/mkiv/tabl-tsp.mkxl | 575 -- tex/context/base/mkiv/tabl-xnt.mklx | 142 - tex/context/base/mkiv/tabl-xtb.mklx | 976 --- tex/context/base/mkiv/task-ini.mkxl | 22 - tex/context/base/mkiv/toks-aux.lmt | 183 - tex/context/base/mkiv/toks-aux.mkiv | 17 - tex/context/base/mkiv/toks-ini.lmt | 332 - tex/context/base/mkiv/toks-ini.mkxl | 20 - tex/context/base/mkiv/toks-scn.lmt | 592 -- tex/context/base/mkiv/toks-scn.mkxl | 26 - tex/context/base/mkiv/trac-ctx.mkxl | 58 - tex/context/base/mkiv/trac-deb.lmt | 419 -- tex/context/base/mkiv/trac-deb.mkxl | 48 - tex/context/base/mkiv/trac-inf.lmt | 425 -- tex/context/base/mkiv/trac-jus.mkxl | 24 - tex/context/base/mkiv/trac-tex.mkxl | 69 - tex/context/base/mkiv/trac-tim.lmt | 178 - tex/context/base/mkiv/trac-vis.lmt | 1700 ----- tex/context/base/mkiv/trac-vis.mkxl | 219 - tex/context/base/mkiv/type-ini.mklx | 708 --- tex/context/base/mkiv/typo-brk.mkxl | 94 - tex/context/base/mkiv/typo-cap.mkxl | 269 - tex/context/base/mkiv/typo-cln.mkxl | 32 - tex/context/base/mkiv/typo-del.mkxl | 927 --- tex/context/base/mkiv/typo-dir.mkxl | 207 - tex/context/base/mkiv/typo-ini.mkxl | 49 - tex/context/base/mkiv/typo-inj.mkxl | 75 - tex/context/base/mkiv/typo-itc.mklx | 60 - tex/context/base/mkiv/typo-krn.mkxl | 143 - tex/context/base/mkiv/typo-lan.mkxl | 64 - tex/context/base/mkiv/typo-lig.mkxl | 23 - tex/context/base/mkiv/typo-lin.lmt | 475 -- tex/context/base/mkiv/typo-lin.mkxl | 25 - tex/context/base/mkiv/typo-mar.mkxl | 471 -- tex/context/base/mkiv/typo-pnc.mkxl | 55 - tex/context/base/mkiv/typo-scr.mkxl | 266 - tex/context/base/mkiv/unic-ini.mkxl | 36 - tex/context/base/mkxl/anch-bar.mkxl | 220 + tex/context/base/mkxl/anch-bck.mklx | 754 +++ tex/context/base/mkxl/anch-pgr.mkxl | 460 ++ tex/context/base/mkxl/anch-pos.lmt | 1633 +++++ tex/context/base/mkxl/anch-pos.mkxl | 503 ++ tex/context/base/mkxl/anch-snc.mkxl | 157 + tex/context/base/mkxl/anch-tab.mkxl | 382 ++ tex/context/base/mkxl/attr-col.mkxl | 22 + tex/context/base/mkxl/attr-eff.mkxl | 60 + tex/context/base/mkxl/attr-ini.mkxl | 143 + tex/context/base/mkxl/attr-lay.lmt | 311 + tex/context/base/mkxl/attr-lay.mkxl | 105 + tex/context/base/mkxl/attr-mkr.mkxl | 25 + tex/context/base/mkxl/attr-neg.mkxl | 28 + tex/context/base/mkxl/back-exp.mkxl | 356 ++ tex/context/base/mkxl/back-ini.mkxl | 80 + tex/context/base/mkxl/back-lua.lmt | 366 ++ tex/context/base/mkxl/back-lua.mkxl | 16 + tex/context/base/mkxl/back-mps.lmt | 210 + tex/context/base/mkxl/back-mps.mkxl | 16 + tex/context/base/mkxl/back-out.lmt | 255 + tex/context/base/mkxl/back-out.mkxl | 22 + tex/context/base/mkxl/back-pdf.mkxl | 157 + tex/context/base/mkxl/back-res.mkxl | 34 + tex/context/base/mkxl/back-trf.mkxl | 81 + tex/context/base/mkxl/back-u3d.mkxl | 158 + tex/context/base/mkxl/bibl-bib.mkxl | 982 +++ tex/context/base/mkxl/bibl-tra.mkxl | 1504 +++++ tex/context/base/mkxl/blob-ini.lmt | 210 + tex/context/base/mkxl/blob-ini.mkxl | 56 + tex/context/base/mkxl/buff-ini.mkxl | 232 + tex/context/base/mkxl/buff-par.mklx | 180 + tex/context/base/mkxl/buff-ver.mkxl | 998 +++ tex/context/base/mkxl/catc-act.mkxl | 51 + tex/context/base/mkxl/catc-ctx.mkxl | 162 + tex/context/base/mkxl/catc-def.mkxl | 147 + tex/context/base/mkxl/catc-ini.mkxl | 329 + tex/context/base/mkxl/catc-sym.mkxl | 96 + tex/context/base/mkxl/char-act.mkxl | 99 + tex/context/base/mkxl/char-enc.mkxl | 18 + tex/context/base/mkxl/char-ini.mkxl | 130 + tex/context/base/mkxl/char-utf.mkxl | 44 + tex/context/base/mkxl/chem-ini.mkxl | 53 + tex/context/base/mkxl/chem-str.mkxl | 741 +++ tex/context/base/mkxl/cldf-bas.mkxl | 19 + tex/context/base/mkxl/cldf-com.mkxl | 19 + tex/context/base/mkxl/cldf-ini.mkxl | 45 + tex/context/base/mkxl/cldf-int.lmt | 252 + tex/context/base/mkxl/cldf-int.mkxl | 34 + tex/context/base/mkxl/cldf-lmt.lmt | 949 +++ tex/context/base/mkxl/cldf-ver.mkxl | 18 + tex/context/base/mkxl/colo-ext.mkxl | 99 + tex/context/base/mkxl/colo-grp.mkxl | 163 + tex/context/base/mkxl/colo-ini.mkxl | 1383 ++++ tex/context/base/mkxl/cont-cs.mkxl | 21 + tex/context/base/mkxl/cont-de.mkxl | 21 + tex/context/base/mkxl/cont-en.mkxl | 21 + tex/context/base/mkxl/cont-fil.mkxl | 152 + tex/context/base/mkxl/cont-fr.mkxl | 21 + tex/context/base/mkxl/cont-gb.mkxl | 21 + tex/context/base/mkxl/cont-it.mkxl | 21 + tex/context/base/mkxl/cont-log.mkxl | 298 + tex/context/base/mkxl/cont-new.mkxl | 50 + tex/context/base/mkxl/cont-nl.mkxl | 21 + tex/context/base/mkxl/cont-pe.mkxl | 22 + tex/context/base/mkxl/cont-ro.mkxl | 21 + tex/context/base/mkxl/cont-run.mkxl | 59 + tex/context/base/mkxl/context.mkxl | 615 ++ tex/context/base/mkxl/core-con.mkxl | 1010 +++ tex/context/base/mkxl/core-ctx.mkxl | 29 + tex/context/base/mkxl/core-dat.mkxl | 110 + tex/context/base/mkxl/core-def.mkxl | 182 + tex/context/base/mkxl/core-env.lmt | 213 + tex/context/base/mkxl/core-env.mkxl | 770 +++ tex/context/base/mkxl/core-ini.mkxl | 224 + tex/context/base/mkxl/core-lmt.lmt | 95 + tex/context/base/mkxl/core-lmt.mkxl | 28 + tex/context/base/mkxl/core-sys.lmt | 91 + tex/context/base/mkxl/core-sys.mkxl | 445 ++ tex/context/base/mkxl/core-two.mkxl | 109 + tex/context/base/mkxl/core-uti.lua | 470 ++ tex/context/base/mkxl/core-uti.mkxl | 35 + tex/context/base/mkxl/driv-ini.mkxl | 20 + tex/context/base/mkxl/driv-shp.lmt | 1360 ++++ tex/context/base/mkxl/driv-shp.mkxl | 18 + tex/context/base/mkxl/enco-ini.mkxl | 510 ++ tex/context/base/mkxl/file-ini.mklx | 231 + tex/context/base/mkxl/file-job.lmt | 1283 ++++ tex/context/base/mkxl/file-job.mklx | 349 + tex/context/base/mkxl/file-lib.mkxl | 20 + tex/context/base/mkxl/file-mod.mklx | 277 + tex/context/base/mkxl/file-res.mklx | 145 + tex/context/base/mkxl/file-syn.mklx | 61 + tex/context/base/mkxl/font-aux.mklx | 26 + tex/context/base/mkxl/font-chk.mkxl | 29 + tex/context/base/mkxl/font-col.mklx | 148 + tex/context/base/mkxl/font-emp.mklx | 256 + tex/context/base/mkxl/font-fea.mklx | 382 ++ tex/context/base/mkxl/font-fil.mklx | 385 ++ tex/context/base/mkxl/font-gds.mklx | 97 + tex/context/base/mkxl/font-ini.mklx | 2512 ++++++++ tex/context/base/mkxl/font-lib.mklx | 170 + tex/context/base/mkxl/font-mat.mklx | 489 ++ tex/context/base/mkxl/font-ogr.lmt | 673 ++ tex/context/base/mkxl/font-pre.mkxl | 999 +++ tex/context/base/mkxl/font-sel.mklx | 276 + tex/context/base/mkxl/font-set.mklx | 159 + tex/context/base/mkxl/font-sol.mklx | 131 + tex/context/base/mkxl/font-sty.mklx | 441 ++ tex/context/base/mkxl/font-sym.mklx | 246 + tex/context/base/mkxl/font-tra.mkxl | 343 + tex/context/base/mkxl/font-uni.mkxl | 27 + tex/context/base/mkxl/font-unk.mkxl | 150 + tex/context/base/mkxl/font-var.mklx | 57 + tex/context/base/mkxl/grph-epd.mkxl | 91 + tex/context/base/mkxl/grph-fig.mkxl | 362 ++ tex/context/base/mkxl/grph-inc.mkxl | 1076 ++++ tex/context/base/mkxl/grph-pat.mkxl | 119 + tex/context/base/mkxl/grph-raw.mkxl | 64 + tex/context/base/mkxl/grph-rul.mkxl | 89 + tex/context/base/mkxl/grph-trf.mkxl | 1011 +++ tex/context/base/mkxl/hand-ini.mkxl | 113 + tex/context/base/mkxl/java-ini.mkxl | 157 + tex/context/base/mkxl/lang-def.mkxl | 800 +++ tex/context/base/mkxl/lang-dis.lmt | 222 + tex/context/base/mkxl/lang-frd.mkxl | 143 + tex/context/base/mkxl/lang-frq.mkxl | 234 + tex/context/base/mkxl/lang-hyp.lmt | 1806 ++++++ tex/context/base/mkxl/lang-hyp.mkxl | 262 + tex/context/base/mkxl/lang-ini.lmt | 670 ++ tex/context/base/mkxl/lang-ini.mkxl | 766 +++ tex/context/base/mkxl/lang-lab.mkxl | 364 ++ tex/context/base/mkxl/lang-mis.mkxl | 586 ++ tex/context/base/mkxl/lang-rep.mkxl | 74 + tex/context/base/mkxl/lang-spa.mkxl | 74 + tex/context/base/mkxl/lang-tra.mkxl | 95 + tex/context/base/mkxl/lang-url.mkxl | 167 + tex/context/base/mkxl/lang-wrd.mkxl | 67 + tex/context/base/mkxl/layo-ini.mkxl | 30 + tex/context/base/mkxl/libs-imp-curl.lmt | 296 + tex/context/base/mkxl/libs-imp-ghostscript.lmt | 111 + tex/context/base/mkxl/libs-imp-graphicsmagick.lmt | 77 + tex/context/base/mkxl/libs-imp-kpse.lmt | 58 + tex/context/base/mkxl/libs-imp-kpse.mkxl | 38 + tex/context/base/mkxl/libs-imp-mujs.lmt | 126 + tex/context/base/mkxl/libs-imp-mujs.mkxl | 121 + tex/context/base/mkxl/libs-imp-mysql.lmt | 220 + tex/context/base/mkxl/libs-imp-postgress.lmt | 200 + tex/context/base/mkxl/libs-imp-sqlite.lmt | 187 + tex/context/base/mkxl/libs-imp-zint.lmt | 161 + tex/context/base/mkxl/libs-imp-zint.mkxl | 64 + tex/context/base/mkxl/libs-ini.mkxl | 32 + tex/context/base/mkxl/lpdf-emb.lmt | 2236 +++++++ tex/context/base/mkxl/lpdf-img.lmt | 1341 ++++ tex/context/base/mkxl/lpdf-lmt.lmt | 2840 +++++++++ tex/context/base/mkxl/lpdf-vfc.lmt | 40 + tex/context/base/mkxl/luat-bas.mkxl | 52 + tex/context/base/mkxl/luat-cod.lmt | 304 + tex/context/base/mkxl/luat-cod.mkxl | 45 + tex/context/base/mkxl/luat-fio.lmt | 107 + tex/context/base/mkxl/luat-ini.mkxl | 296 + tex/context/base/mkxl/luat-lib.mkxl | 104 + tex/context/base/mkxl/luat-log.lmt | 739 +++ tex/context/base/mkxl/luat-soc.mkxl | 52 + tex/context/base/mkxl/luat-usr.mkxl | 119 + tex/context/base/mkxl/lxml-css.mkxl | 76 + tex/context/base/mkxl/lxml-ctx.mkxl | 58 + tex/context/base/mkxl/lxml-ini.mkxl | 544 ++ tex/context/base/mkxl/lxml-sor.mkxl | 99 + tex/context/base/mkxl/m-mkivmkxl.mkxl | 3 + tex/context/base/mkxl/math-acc.mklx | 151 + tex/context/base/mkxl/math-ali.mkxl | 1902 ++++++ tex/context/base/mkxl/math-def.mkxl | 171 + tex/context/base/mkxl/math-del.mkxl | 164 + tex/context/base/mkxl/math-dis.mkxl | 20 + tex/context/base/mkxl/math-fen.mkxl | 829 +++ tex/context/base/mkxl/math-for.mkxl | 47 + tex/context/base/mkxl/math-frc.mkxl | 833 +++ tex/context/base/mkxl/math-inc.mkxl | 69 + tex/context/base/mkxl/math-ini.mkxl | 3006 +++++++++ tex/context/base/mkxl/math-inl.mkxl | 22 + tex/context/base/mkxl/math-int.mkxl | 141 + tex/context/base/mkxl/math-mis.mkxl | 60 + tex/context/base/mkxl/math-noa.lmt | 2399 +++++++ tex/context/base/mkxl/math-pln.mkxl | 245 + tex/context/base/mkxl/math-rad.mklx | 269 + tex/context/base/mkxl/math-scr.mkxl | 58 + tex/context/base/mkxl/math-stc.mklx | 1377 ++++ tex/context/base/mkxl/math-tag.lmt | 596 ++ tex/context/base/mkxl/math-toy.mkxl | 54 + tex/context/base/mkxl/meta-blb.mkxl | 53 + tex/context/base/mkxl/meta-fig.mkxl | 71 + tex/context/base/mkxl/meta-fnt.mkxl | 33 + tex/context/base/mkxl/meta-fun.mkxl | 25 + tex/context/base/mkxl/meta-grd.mkxl | 105 + tex/context/base/mkxl/meta-imp-experiments.mkxl | 358 ++ tex/context/base/mkxl/meta-imp-gamesymbols.mkxl | 349 + tex/context/base/mkxl/meta-imp-symbols.mkxl | 99 + tex/context/base/mkxl/meta-imp-threesix.mkxl | 246 + tex/context/base/mkxl/meta-ini.mkxl | 1387 ++++ tex/context/base/mkxl/meta-lua.mkxl | 95 + tex/context/base/mkxl/meta-mac.mkxl | 45 + tex/context/base/mkxl/meta-nod.mkxl | 241 + tex/context/base/mkxl/meta-pag.mkxl | 26 + tex/context/base/mkxl/meta-pdf.mkxl | 95 + tex/context/base/mkxl/meta-pdh.mkxl | 717 +++ tex/context/base/mkxl/meta-tex.mkxl | 239 + tex/context/base/mkxl/meta-xml.mkxl | 20 + tex/context/base/mkxl/mlib-cnt.lmt | 2022 ++++++ tex/context/base/mkxl/mlib-ctx.mkxl | 32 + tex/context/base/mkxl/mlib-fio.lmt | 191 + tex/context/base/mkxl/mlib-int.lmt | 135 + tex/context/base/mkxl/mlib-lmp.lmt | 70 + tex/context/base/mkxl/mlib-lmt.lmt | 153 + tex/context/base/mkxl/mlib-lua.lmt | 168 + tex/context/base/mkxl/mlib-mat.lmt | 139 + tex/context/base/mkxl/mlib-pdf.mkxl | 162 + tex/context/base/mkxl/mlib-pps.mkxl | 215 + tex/context/base/mkxl/mlib-ran.lmt | 237 + tex/context/base/mkxl/mlib-scn.lmt | 780 +++ tex/context/base/mkxl/mlib-svg.lmt | 3277 ++++++++++ tex/context/base/mkxl/mult-aux.mkxl | 1177 ++++ tex/context/base/mkxl/mult-def.mkxl | 32 + tex/context/base/mkxl/mult-dim.mklx | 156 + tex/context/base/mkxl/mult-ini.mkxl | 805 +++ tex/context/base/mkxl/mult-prm.mkxl | 117 + tex/context/base/mkxl/mult-sys.mkxl | 602 ++ tex/context/base/mkxl/node-aux.lmt | 396 ++ tex/context/base/mkxl/node-bck.mkxl | 92 + tex/context/base/mkxl/node-cmp.lmt | 237 + tex/context/base/mkxl/node-fin.mkxl | 78 + tex/context/base/mkxl/node-gcm.lmt | 112 + tex/context/base/mkxl/node-ini.lmt | 280 + tex/context/base/mkxl/node-ini.mkxl | 56 + tex/context/base/mkxl/node-mig.lmt | 134 + tex/context/base/mkxl/node-mig.mkxl | 44 + tex/context/base/mkxl/node-nut.lmt | 579 ++ tex/context/base/mkxl/node-par.lmt | 48 + tex/context/base/mkxl/node-rul.mkxl | 611 ++ tex/context/base/mkxl/node-ser.lmt | 285 + tex/context/base/mkxl/node-snp.lmt | 69 + tex/context/base/mkxl/node-tex.lmt | 39 + tex/context/base/mkxl/norm-ctx.mkxl | 87 + tex/context/base/mkxl/pack-bar.mkxl | 94 + tex/context/base/mkxl/pack-bck.mklx | 245 + tex/context/base/mkxl/pack-box.mkxl | 1114 ++++ tex/context/base/mkxl/pack-com.mkxl | 954 +++ tex/context/base/mkxl/pack-cut.mkxl | 164 + tex/context/base/mkxl/pack-fen.mkxl | 97 + tex/context/base/mkxl/pack-lyr.mkxl | 772 +++ tex/context/base/mkxl/pack-mis.mklx | 112 + tex/context/base/mkxl/pack-mrl.mkxl | 844 +++ tex/context/base/mkxl/pack-obj.lmt | 305 + tex/context/base/mkxl/pack-obj.mkxl | 168 + tex/context/base/mkxl/pack-ori.lmt | 70 + tex/context/base/mkxl/pack-ori.mkxl | 97 + tex/context/base/mkxl/pack-pos.mkxl | 160 + tex/context/base/mkxl/pack-rul.lmt | 248 + tex/context/base/mkxl/pack-rul.mkxl | 3001 +++++++++ tex/context/base/mkxl/page-app.mkxl | 205 + tex/context/base/mkxl/page-bck.mkxl | 703 ++ tex/context/base/mkxl/page-box.mklx | 289 + tex/context/base/mkxl/page-brk.mkxl | 483 ++ tex/context/base/mkxl/page-col.mkxl | 163 + tex/context/base/mkxl/page-com.mkxl | 180 + tex/context/base/mkxl/page-cst.mkxl | 789 +++ tex/context/base/mkxl/page-fac.mkxl | 87 + tex/context/base/mkxl/page-ffl.mkxl | 247 + tex/context/base/mkxl/page-flt.mkxl | 326 + tex/context/base/mkxl/page-flw.mkxl | 178 + tex/context/base/mkxl/page-imp.mkxl | 1410 ++++ tex/context/base/mkxl/page-inf.mkxl | 124 + tex/context/base/mkxl/page-ini.mkxl | 376 ++ tex/context/base/mkxl/page-inj.mklx | 228 + tex/context/base/mkxl/page-ins.mkxl | 209 + tex/context/base/mkxl/page-lay.mkxl | 1623 +++++ tex/context/base/mkxl/page-mak.mklx | 280 + tex/context/base/mkxl/page-mbk.mklx | 243 + tex/context/base/mkxl/page-mcl.mkxl | 545 ++ tex/context/base/mkxl/page-mix.mkxl | 1086 ++++ tex/context/base/mkxl/page-mrk.mkxl | 238 + tex/context/base/mkxl/page-not.mkxl | 32 + tex/context/base/mkxl/page-one.mkxl | 709 +++ tex/context/base/mkxl/page-otr.mklx | 335 + tex/context/base/mkxl/page-par.mkxl | 73 + tex/context/base/mkxl/page-pcl.mkxl | 857 +++ tex/context/base/mkxl/page-plg.mkxl | 213 + tex/context/base/mkxl/page-pst.mkxl | 110 + tex/context/base/mkxl/page-sel.mklx | 417 ++ tex/context/base/mkxl/page-sid.mkxl | 1019 +++ tex/context/base/mkxl/page-smp.mkxl | 56 + tex/context/base/mkxl/page-spr.mkxl | 129 + tex/context/base/mkxl/page-str.mkxl | 128 + tex/context/base/mkxl/page-txt.mklx | 950 +++ tex/context/base/mkxl/page-var.mkxl | 20 + tex/context/base/mkxl/phys-dim.mkxl | 808 +++ tex/context/base/mkxl/publ-inc.mkxl | 63 + tex/context/base/mkxl/publ-ini.mkxl | 2027 ++++++ tex/context/base/mkxl/publ-old.mkxl | 22 + tex/context/base/mkxl/publ-tra.mkxl | 84 + tex/context/base/mkxl/publ-xml.mkxl | 111 + tex/context/base/mkxl/regi-ini.mkxl | 37 + tex/context/base/mkxl/scrn-bar.mklx | 402 ++ tex/context/base/mkxl/scrn-but.mklx | 1031 +++ tex/context/base/mkxl/scrn-fld.mklx | 1013 +++ tex/context/base/mkxl/scrn-hlp.mklx | 162 + tex/context/base/mkxl/scrn-ini.mklx | 254 + tex/context/base/mkxl/scrn-pag.mklx | 310 + tex/context/base/mkxl/scrn-ref.mklx | 102 + tex/context/base/mkxl/scrn-wid.mklx | 744 +++ tex/context/base/mkxl/scrp-ini.mkxl | 109 + tex/context/base/mkxl/sort-ini.mkxl | 19 + tex/context/base/mkxl/spac-ali.mkxl | 1243 ++++ tex/context/base/mkxl/spac-chr.mkxl | 78 + tex/context/base/mkxl/spac-def.mkxl | 91 + tex/context/base/mkxl/spac-flr.mkxl | 194 + tex/context/base/mkxl/spac-grd.mkxl | 375 ++ tex/context/base/mkxl/spac-hor.mkxl | 1237 ++++ tex/context/base/mkxl/spac-lin.mkxl | 211 + tex/context/base/mkxl/spac-pag.mkxl | 182 + tex/context/base/mkxl/spac-par.lmt | 80 + tex/context/base/mkxl/spac-par.mkxl | 446 ++ tex/context/base/mkxl/spac-prf.mklx | 113 + tex/context/base/mkxl/spac-ver.lmt | 2527 ++++++++ tex/context/base/mkxl/spac-ver.mkxl | 2452 +++++++ tex/context/base/mkxl/strc-bkm.mkxl | 182 + tex/context/base/mkxl/strc-blk.mkxl | 171 + tex/context/base/mkxl/strc-con.mklx | 1158 ++++ tex/context/base/mkxl/strc-def.mkxl | 338 + tex/context/base/mkxl/strc-des.mklx | 194 + tex/context/base/mkxl/strc-doc.mkxl | 45 + tex/context/base/mkxl/strc-enu.mklx | 371 ++ tex/context/base/mkxl/strc-flt.mklx | 2580 ++++++++ tex/context/base/mkxl/strc-ind.mkxl | 128 + tex/context/base/mkxl/strc-ini.mklx | 81 + tex/context/base/mkxl/strc-itm.mklx | 1907 ++++++ tex/context/base/mkxl/strc-lab.mkxl | 198 + tex/context/base/mkxl/strc-lev.mklx | 98 + tex/context/base/mkxl/strc-lnt.mklx | 359 ++ tex/context/base/mkxl/strc-lst.mklx | 1571 +++++ tex/context/base/mkxl/strc-mar.mkxl | 136 + tex/context/base/mkxl/strc-mat.mkxl | 1311 ++++ tex/context/base/mkxl/strc-not.mklx | 1972 ++++++ tex/context/base/mkxl/strc-num.mkxl | 687 ++ tex/context/base/mkxl/strc-pag.mkxl | 497 ++ tex/context/base/mkxl/strc-ref.mklx | 2193 +++++++ tex/context/base/mkxl/strc-reg.mkxl | 1211 ++++ tex/context/base/mkxl/strc-ren.mkxl | 817 +++ tex/context/base/mkxl/strc-sbe.mkxl | 137 + tex/context/base/mkxl/strc-sec.mkxl | 1321 ++++ tex/context/base/mkxl/strc-syn.mkxl | 658 ++ tex/context/base/mkxl/strc-tag.lmt | 615 ++ tex/context/base/mkxl/strc-tag.mkxl | 531 ++ tex/context/base/mkxl/strc-tnt.mkxl | 117 + tex/context/base/mkxl/strc-usr.mkxl | 169 + tex/context/base/mkxl/supp-box.lmt | 1335 ++++ tex/context/base/mkxl/supp-box.mkxl | 2872 +++++++++ tex/context/base/mkxl/supp-dir.mkxl | 44 + tex/context/base/mkxl/supp-mat.mkxl | 180 + tex/context/base/mkxl/supp-ran.mkxl | 49 + tex/context/base/mkxl/symb-emj.mkxl | 26 + tex/context/base/mkxl/symb-ini.mkxl | 340 + tex/context/base/mkxl/syst-aux.lmt | 747 +++ tex/context/base/mkxl/syst-aux.mkxl | 6704 ++++++++++++++++++++ tex/context/base/mkxl/syst-cmp.mkxl | 22 + tex/context/base/mkxl/syst-con.mkxl | 88 + tex/context/base/mkxl/syst-fnt.mkxl | 47 + tex/context/base/mkxl/syst-ini.mkxl | 1107 ++++ tex/context/base/mkxl/syst-lua.lmt | 434 ++ tex/context/base/mkxl/syst-lua.mkxl | 104 + tex/context/base/mkxl/syst-mac.lmt | 117 + tex/context/base/mkxl/syst-mes.mkxl | 20 + tex/context/base/mkxl/syst-pln.mkxl | 119 + tex/context/base/mkxl/syst-rtp.mkxl | 18 + tex/context/base/mkxl/tabl-com.mkxl | 92 + tex/context/base/mkxl/tabl-frm.mkxl | 261 + tex/context/base/mkxl/tabl-ltb.mkxl | 797 +++ tex/context/base/mkxl/tabl-mis.mkxl | 294 + tex/context/base/mkxl/tabl-ntb.mkxl | 2172 +++++++ tex/context/base/mkxl/tabl-nte.mkxl | 107 + tex/context/base/mkxl/tabl-tab.mkxl | 2232 +++++++ tex/context/base/mkxl/tabl-tbl.mkxl | 2929 +++++++++ tex/context/base/mkxl/tabl-tsp.mkxl | 575 ++ tex/context/base/mkxl/tabl-xnt.mklx | 142 + tex/context/base/mkxl/tabl-xtb.mklx | 976 +++ tex/context/base/mkxl/task-ini.mkxl | 22 + tex/context/base/mkxl/toks-aux.lmt | 183 + tex/context/base/mkxl/toks-aux.mkxl | 68 + tex/context/base/mkxl/toks-ini.lmt | 332 + tex/context/base/mkxl/toks-ini.mkxl | 20 + tex/context/base/mkxl/toks-scn.lmt | 592 ++ tex/context/base/mkxl/toks-scn.mkxl | 26 + tex/context/base/mkxl/trac-ctx.mkxl | 58 + tex/context/base/mkxl/trac-deb.lmt | 419 ++ tex/context/base/mkxl/trac-deb.mkxl | 48 + tex/context/base/mkxl/trac-inf.lmt | 425 ++ tex/context/base/mkxl/trac-jus.mkxl | 24 + tex/context/base/mkxl/trac-tex.mkxl | 69 + tex/context/base/mkxl/trac-tim.lmt | 178 + tex/context/base/mkxl/trac-vis.lmt | 1700 +++++ tex/context/base/mkxl/trac-vis.mkxl | 219 + tex/context/base/mkxl/type-def.mkxl | 48 + tex/context/base/mkxl/type-fbk.mkxl | 70 + tex/context/base/mkxl/type-ini.mklx | 615 ++ tex/context/base/mkxl/type-lua.mkxl | 86 + tex/context/base/mkxl/type-set.mkxl | 139 + tex/context/base/mkxl/type-siz.mkxl | 169 + tex/context/base/mkxl/typo-bld.mkxl | 62 + tex/context/base/mkxl/typo-brk.mkxl | 94 + tex/context/base/mkxl/typo-cap.mkxl | 269 + tex/context/base/mkxl/typo-chr.mkxl | 87 + tex/context/base/mkxl/typo-cln.mkxl | 32 + tex/context/base/mkxl/typo-del.mkxl | 922 +++ tex/context/base/mkxl/typo-dig.mkxl | 58 + tex/context/base/mkxl/typo-dir.mkxl | 202 + tex/context/base/mkxl/typo-drp.mkxl | 129 + tex/context/base/mkxl/typo-fkr.mkxl | 38 + tex/context/base/mkxl/typo-fln.mkxl | 109 + tex/context/base/mkxl/typo-ini.mkxl | 49 + tex/context/base/mkxl/typo-inj.mkxl | 75 + tex/context/base/mkxl/typo-itc.mklx | 60 + tex/context/base/mkxl/typo-itm.mkxl | 270 + tex/context/base/mkxl/typo-krn.mkxl | 143 + tex/context/base/mkxl/typo-lan.mkxl | 64 + tex/context/base/mkxl/typo-lig.mkxl | 23 + tex/context/base/mkxl/typo-lin.lmt | 475 ++ tex/context/base/mkxl/typo-lin.mkxl | 25 + tex/context/base/mkxl/typo-mar.mkxl | 471 ++ tex/context/base/mkxl/typo-ovl.mkxl | 116 + tex/context/base/mkxl/typo-pag.mkxl | 20 + tex/context/base/mkxl/typo-par.mkxl | 30 + tex/context/base/mkxl/typo-plc.mkxl | 39 + tex/context/base/mkxl/typo-pnc.mkxl | 55 + tex/context/base/mkxl/typo-prc.mklx | 99 + tex/context/base/mkxl/typo-rep.mkxl | 42 + tex/context/base/mkxl/typo-rub.mkxl | 173 + tex/context/base/mkxl/typo-scr.mkxl | 266 + tex/context/base/mkxl/typo-spa.mkxl | 78 + tex/context/base/mkxl/typo-sus.mkxl | 51 + tex/context/base/mkxl/typo-tal.mkxl | 303 + tex/context/base/mkxl/typo-txt.mklx | 240 + tex/context/base/mkxl/typo-wrp.mkxl | 58 + tex/context/base/mkxl/unic-ini.mkxl | 36 + tex/context/interface/mkii/keys-de.xml | 5 +- tex/context/interface/mkiv/context-en.xml | 624 +- tex/context/interface/mkiv/i-boxes.xml | 6 + tex/context/interface/mkiv/i-catcodes.xml | 2 +- tex/context/interface/mkiv/i-columns.xml | 108 +- tex/context/interface/mkiv/i-common-argument.xml | 11 + tex/context/interface/mkiv/i-common-instance.xml | 5 + tex/context/interface/mkiv/i-context.pdf | Bin 959252 -> 964271 bytes tex/context/interface/mkiv/i-context.xml | 3 +- tex/context/interface/mkiv/i-counter.xml | 3 + tex/context/interface/mkiv/i-document.xml | 22 + tex/context/interface/mkiv/i-filler.xml | 94 - tex/context/interface/mkiv/i-fonts.xml | 2 - tex/context/interface/mkiv/i-framed.xml | 7 + tex/context/interface/mkiv/i-hspace.xml | 28 +- tex/context/interface/mkiv/i-hyphenation.xml | 12 + tex/context/interface/mkiv/i-itemgroup.xml | 4 + tex/context/interface/mkiv/i-linefiller.xml | 30 +- tex/context/interface/mkiv/i-lua.xml | 47 + tex/context/interface/mkiv/i-marking.xml | 5 +- tex/context/interface/mkiv/i-mathmatrix.xml | 10 +- tex/context/interface/mkiv/i-note.xml | 2 +- tex/context/interface/mkiv/i-pagenumber.xml | 1 + tex/context/interface/mkiv/i-parwrapper.xml | 80 + tex/context/interface/mkiv/i-readme.pdf | Bin 24972 -> 24996 bytes tex/context/interface/mkiv/i-replacement.xml | 4 +- tex/context/interface/mkiv/i-setup.xml | 6 + tex/context/interface/mkiv/i-synonym.xml | 4 + tex/context/interface/mkiv/i-system.xml | 14 +- tex/context/interface/mkiv/i-vspace.xml | 12 + tex/context/interface/mkiv/i-xml.xml | 11 +- tex/context/modules/mkiv/m-chart.mkvi | 2 +- tex/context/modules/mkiv/m-gnuplot.mkxl | 2 +- tex/context/modules/mkiv/m-timing.mkxl | 14 +- tex/context/modules/mkiv/s-system-macros.mkxl | 31 +- tex/context/modules/mkiv/s-system-tokens.mkxl | 3 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 2 +- 850 files changed, 184920 insertions(+), 160155 deletions(-) delete mode 100644 metapost/context/base/mpiv/metafun.mpxl delete mode 100644 metapost/context/base/mpiv/minifun.mpxl delete mode 100644 metapost/context/base/mpiv/mp-cont.mpxl delete mode 100644 metapost/context/base/mpiv/mp-lmtx.mpxl delete mode 100644 metapost/context/base/mpiv/mp-luas.mpxl delete mode 100644 metapost/context/base/mpiv/mp-math.mpxl delete mode 100644 metapost/context/base/mpiv/mp-page.mpxl create mode 100644 metapost/context/base/mpxl/metafun.mpxl create mode 100644 metapost/context/base/mpxl/minifun.mpxl create mode 100644 metapost/context/base/mpxl/mp-cont.mpxl create mode 100644 metapost/context/base/mpxl/mp-lmtx.mpxl create mode 100644 metapost/context/base/mpxl/mp-luas.mpxl create mode 100644 metapost/context/base/mpxl/mp-math.mpxl create mode 100644 metapost/context/base/mpxl/mp-page.mpxl delete mode 100644 tex/context/base/mkiv/anch-bar.mkxl delete mode 100644 tex/context/base/mkiv/anch-bck.mklx delete mode 100644 tex/context/base/mkiv/anch-pgr.mkxl delete mode 100644 tex/context/base/mkiv/anch-pos.lmt delete mode 100644 tex/context/base/mkiv/anch-pos.mkxl delete mode 100644 tex/context/base/mkiv/anch-snc.mkxl delete mode 100644 tex/context/base/mkiv/anch-tab.mkxl delete mode 100644 tex/context/base/mkiv/attr-col.mkxl delete mode 100644 tex/context/base/mkiv/attr-eff.mkxl delete mode 100644 tex/context/base/mkiv/attr-ini.mkxl delete mode 100644 tex/context/base/mkiv/attr-lay.lmt delete mode 100644 tex/context/base/mkiv/attr-lay.mkxl delete mode 100644 tex/context/base/mkiv/attr-mkr.mkxl delete mode 100644 tex/context/base/mkiv/attr-neg.mkxl delete mode 100644 tex/context/base/mkiv/back-exp.mkxl delete mode 100644 tex/context/base/mkiv/back-ini.mkxl delete mode 100644 tex/context/base/mkiv/back-lua.lmt delete mode 100644 tex/context/base/mkiv/back-lua.mkxl delete mode 100644 tex/context/base/mkiv/back-mps.lmt delete mode 100644 tex/context/base/mkiv/back-mps.mkxl delete mode 100644 tex/context/base/mkiv/back-out.lmt delete mode 100644 tex/context/base/mkiv/back-out.mkxl delete mode 100644 tex/context/base/mkiv/back-pdf.mkxl delete mode 100644 tex/context/base/mkiv/back-res.mkxl delete mode 100644 tex/context/base/mkiv/back-trf.mkxl delete mode 100644 tex/context/base/mkiv/bibl-bib.mkxl delete mode 100644 tex/context/base/mkiv/bibl-tra.mkxl delete mode 100644 tex/context/base/mkiv/blob-ini.lmt delete mode 100644 tex/context/base/mkiv/blob-ini.mkxl delete mode 100644 tex/context/base/mkiv/buff-ver.mkxl delete mode 100644 tex/context/base/mkiv/catc-act.mkxl delete mode 100644 tex/context/base/mkiv/catc-ctx.mkxl delete mode 100644 tex/context/base/mkiv/catc-def.mkxl delete mode 100644 tex/context/base/mkiv/catc-ini.mkxl delete mode 100644 tex/context/base/mkiv/catc-sym.mkxl delete mode 100644 tex/context/base/mkiv/char-act.mkxl delete mode 100644 tex/context/base/mkiv/char-enc.mkxl delete mode 100644 tex/context/base/mkiv/char-ini.mkxl delete mode 100644 tex/context/base/mkiv/char-utf.mkxl delete mode 100644 tex/context/base/mkiv/chem-ini.mkxl delete mode 100644 tex/context/base/mkiv/chem-str.mkxl delete mode 100644 tex/context/base/mkiv/cldf-bas.mkxl delete mode 100644 tex/context/base/mkiv/cldf-com.mkxl delete mode 100644 tex/context/base/mkiv/cldf-ini.mkxl delete mode 100644 tex/context/base/mkiv/cldf-int.lmt delete mode 100644 tex/context/base/mkiv/cldf-int.mkxl delete mode 100644 tex/context/base/mkiv/cldf-lmt.lmt delete mode 100644 tex/context/base/mkiv/cldf-ver.mkxl delete mode 100644 tex/context/base/mkiv/colo-ext.mkxl delete mode 100644 tex/context/base/mkiv/colo-grp.mkxl delete mode 100644 tex/context/base/mkiv/colo-ini.mkxl delete mode 100644 tex/context/base/mkiv/cont-cs.mkxl delete mode 100644 tex/context/base/mkiv/cont-de.mkxl delete mode 100644 tex/context/base/mkiv/cont-en.mkxl delete mode 100644 tex/context/base/mkiv/cont-fr.mkxl delete mode 100644 tex/context/base/mkiv/cont-gb.mkxl delete mode 100644 tex/context/base/mkiv/cont-it.mkxl delete mode 100644 tex/context/base/mkiv/cont-nl.mkxl delete mode 100644 tex/context/base/mkiv/cont-pe.mkxl delete mode 100644 tex/context/base/mkiv/cont-ro.mkxl delete mode 100644 tex/context/base/mkiv/context.mkxl delete mode 100644 tex/context/base/mkiv/core-con.mkxl delete mode 100644 tex/context/base/mkiv/core-ctx.mkxl delete mode 100644 tex/context/base/mkiv/core-dat.mkxl delete mode 100644 tex/context/base/mkiv/core-def.mkxl delete mode 100644 tex/context/base/mkiv/core-env.lmt delete mode 100644 tex/context/base/mkiv/core-env.mkxl delete mode 100644 tex/context/base/mkiv/core-ini.mkxl delete mode 100644 tex/context/base/mkiv/core-lmt.lmt delete mode 100644 tex/context/base/mkiv/core-lmt.mkxl delete mode 100644 tex/context/base/mkiv/core-sys.lmt delete mode 100644 tex/context/base/mkiv/core-sys.mkxl delete mode 100644 tex/context/base/mkiv/core-two.mkxl delete mode 100644 tex/context/base/mkiv/core-uti.mkxl delete mode 100644 tex/context/base/mkiv/driv-ini.mkxl delete mode 100644 tex/context/base/mkiv/driv-shp.lmt delete mode 100644 tex/context/base/mkiv/driv-shp.mkxl delete mode 100644 tex/context/base/mkiv/enco-ini.mkxl delete mode 100644 tex/context/base/mkiv/file-ini.mklx delete mode 100644 tex/context/base/mkiv/file-job.lmt delete mode 100644 tex/context/base/mkiv/file-job.mklx delete mode 100644 tex/context/base/mkiv/file-lib.mkxl delete mode 100644 tex/context/base/mkiv/file-mod.mklx delete mode 100644 tex/context/base/mkiv/file-res.mklx delete mode 100644 tex/context/base/mkiv/file-syn.mklx delete mode 100644 tex/context/base/mkiv/font-aux.mklx delete mode 100644 tex/context/base/mkiv/font-chk.mkxl delete mode 100644 tex/context/base/mkiv/font-col.mklx delete mode 100644 tex/context/base/mkiv/font-emp.mklx delete mode 100644 tex/context/base/mkiv/font-fea.mklx delete mode 100644 tex/context/base/mkiv/font-fil.mklx delete mode 100644 tex/context/base/mkiv/font-ini.mklx delete mode 100644 tex/context/base/mkiv/font-mat.mklx delete mode 100644 tex/context/base/mkiv/font-ogr.lmt delete mode 100644 tex/context/base/mkiv/font-pre.mkxl delete mode 100644 tex/context/base/mkiv/font-sol.mklx delete mode 100644 tex/context/base/mkiv/font-sty.mklx delete mode 100644 tex/context/base/mkiv/font-sym.mklx delete mode 100644 tex/context/base/mkiv/font-tra.mkxl delete mode 100644 tex/context/base/mkiv/grph-epd.mkxl delete mode 100644 tex/context/base/mkiv/grph-fig.mkxl delete mode 100644 tex/context/base/mkiv/grph-inc.mkxl delete mode 100644 tex/context/base/mkiv/grph-pat.mkxl delete mode 100644 tex/context/base/mkiv/grph-raw.mkxl delete mode 100644 tex/context/base/mkiv/grph-rul.mkxl delete mode 100644 tex/context/base/mkiv/grph-trf.mkxl delete mode 100644 tex/context/base/mkiv/hand-ini.mkxl delete mode 100644 tex/context/base/mkiv/java-ini.mkxl delete mode 100644 tex/context/base/mkiv/lang-dis.lmt delete mode 100644 tex/context/base/mkiv/lang-hyp.lmt delete mode 100644 tex/context/base/mkiv/lang-ini.lmt delete mode 100644 tex/context/base/mkiv/lang-ini.mkxl delete mode 100644 tex/context/base/mkiv/lang-lab.mkxl delete mode 100644 tex/context/base/mkiv/lang-mis.mkxl delete mode 100644 tex/context/base/mkiv/lang-url.mkxl delete mode 100644 tex/context/base/mkiv/layo-ini.mkxl delete mode 100644 tex/context/base/mkiv/libs-imp-curl.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-ghostscript.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-graphicsmagick.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-kpse.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-kpse.mkxl delete mode 100644 tex/context/base/mkiv/libs-imp-mujs.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-mujs.mkxl delete mode 100644 tex/context/base/mkiv/libs-imp-mysql.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-postgress.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-sqlite.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-zint.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-zint.mkxl delete mode 100644 tex/context/base/mkiv/libs-ini.mkxl delete mode 100644 tex/context/base/mkiv/lpdf-emb.lmt delete mode 100644 tex/context/base/mkiv/lpdf-img.lmt delete mode 100644 tex/context/base/mkiv/lpdf-lmt.lmt delete mode 100644 tex/context/base/mkiv/lpdf-vfc.lmt delete mode 100644 tex/context/base/mkiv/luat-cod.lmt delete mode 100644 tex/context/base/mkiv/luat-cod.mkxl delete mode 100644 tex/context/base/mkiv/luat-fio.lmt delete mode 100644 tex/context/base/mkiv/luat-log.lmt delete mode 100644 tex/context/base/mkiv/lxml-css.mkxl delete mode 100644 tex/context/base/mkiv/lxml-ctx.mkxl delete mode 100644 tex/context/base/mkiv/lxml-ini.mkxl delete mode 100644 tex/context/base/mkiv/lxml-sor.mkxl delete mode 100644 tex/context/base/mkiv/m-mkivmkxl.mkxl delete mode 100644 tex/context/base/mkiv/math-ali.mkxl delete mode 100644 tex/context/base/mkiv/math-fen.mkxl delete mode 100644 tex/context/base/mkiv/math-frc.mkxl delete mode 100644 tex/context/base/mkiv/math-ini.mkxl delete mode 100644 tex/context/base/mkiv/math-noa.lmt delete mode 100644 tex/context/base/mkiv/math-pln.mkxl delete mode 100644 tex/context/base/mkiv/math-stc.mklx delete mode 100644 tex/context/base/mkiv/math-tag.lmt delete mode 100644 tex/context/base/mkiv/math-toy.mkxl delete mode 100644 tex/context/base/mkiv/meta-imp-experiments.mkxl delete mode 100644 tex/context/base/mkiv/meta-imp-gamesymbols.mkxl delete mode 100644 tex/context/base/mkiv/meta-imp-symbols.mkxl delete mode 100644 tex/context/base/mkiv/meta-imp-threesix.mkxl delete mode 100644 tex/context/base/mkiv/meta-ini.mkxl delete mode 100644 tex/context/base/mkiv/meta-mac.mkxl delete mode 100644 tex/context/base/mkiv/meta-pag.mkxl delete mode 100644 tex/context/base/mkiv/mlib-cnt.lmt delete mode 100644 tex/context/base/mkiv/mlib-ctx.mkxl delete mode 100644 tex/context/base/mkiv/mlib-fio.lmt delete mode 100644 tex/context/base/mkiv/mlib-int.lmt delete mode 100644 tex/context/base/mkiv/mlib-lmp.lmt delete mode 100644 tex/context/base/mkiv/mlib-lmt.lmt delete mode 100644 tex/context/base/mkiv/mlib-lua.lmt delete mode 100644 tex/context/base/mkiv/mlib-mat.lmt delete mode 100644 tex/context/base/mkiv/mlib-pdf.mkxl delete mode 100644 tex/context/base/mkiv/mlib-pps.mkxl delete mode 100644 tex/context/base/mkiv/mlib-ran.lmt delete mode 100644 tex/context/base/mkiv/mlib-scn.lmt delete mode 100644 tex/context/base/mkiv/mlib-svg.lmt delete mode 100644 tex/context/base/mkiv/mult-aux.mkxl delete mode 100644 tex/context/base/mkiv/mult-def.mkxl delete mode 100644 tex/context/base/mkiv/mult-dim.mklx delete mode 100644 tex/context/base/mkiv/mult-ini.mkxl delete mode 100644 tex/context/base/mkiv/mult-prm.mkxl delete mode 100644 tex/context/base/mkiv/mult-sys.mkxl delete mode 100644 tex/context/base/mkiv/node-aux.lmt delete mode 100644 tex/context/base/mkiv/node-bck.mkxl delete mode 100644 tex/context/base/mkiv/node-cmp.lmt delete mode 100644 tex/context/base/mkiv/node-fin.mkxl delete mode 100644 tex/context/base/mkiv/node-gcm.lmt delete mode 100644 tex/context/base/mkiv/node-ini.lmt delete mode 100644 tex/context/base/mkiv/node-ini.mkxl delete mode 100644 tex/context/base/mkiv/node-mig.lmt delete mode 100644 tex/context/base/mkiv/node-mig.mkxl delete mode 100644 tex/context/base/mkiv/node-nut.lmt delete mode 100644 tex/context/base/mkiv/node-par.lmt delete mode 100644 tex/context/base/mkiv/node-rul.mkxl delete mode 100644 tex/context/base/mkiv/node-ser.lmt delete mode 100644 tex/context/base/mkiv/node-snp.lmt delete mode 100644 tex/context/base/mkiv/node-tex.lmt delete mode 100644 tex/context/base/mkiv/norm-ctx.mkxl delete mode 100644 tex/context/base/mkiv/pack-bar.mkxl delete mode 100644 tex/context/base/mkiv/pack-bck.mklx delete mode 100644 tex/context/base/mkiv/pack-box.mkxl delete mode 100644 tex/context/base/mkiv/pack-com.mkxl delete mode 100644 tex/context/base/mkiv/pack-lyr.mkxl delete mode 100644 tex/context/base/mkiv/pack-mrl.mkxl delete mode 100644 tex/context/base/mkiv/pack-ori.lmt delete mode 100644 tex/context/base/mkiv/pack-ori.mkxl delete mode 100644 tex/context/base/mkiv/pack-rul.mkxl delete mode 100644 tex/context/base/mkiv/page-bck.mkxl delete mode 100644 tex/context/base/mkiv/page-ini.mkxl delete mode 100644 tex/context/base/mkiv/page-lay.mkxl delete mode 100644 tex/context/base/mkiv/page-mcl.mkxl delete mode 100644 tex/context/base/mkiv/page-mix.mkxl delete mode 100644 tex/context/base/mkiv/page-not.mkxl delete mode 100644 tex/context/base/mkiv/page-one.mkxl delete mode 100644 tex/context/base/mkiv/page-otr.mklx delete mode 100644 tex/context/base/mkiv/page-spr.mkxl delete mode 100644 tex/context/base/mkiv/page-txt.mklx delete mode 100644 tex/context/base/mkiv/phys-dim.mkxl delete mode 100644 tex/context/base/mkiv/prop-ini.mkiv delete mode 100644 tex/context/base/mkiv/publ-inc.mkxl delete mode 100644 tex/context/base/mkiv/publ-ini.mkxl delete mode 100644 tex/context/base/mkiv/publ-tra.mkxl delete mode 100644 tex/context/base/mkiv/publ-xml.mkxl delete mode 100644 tex/context/base/mkiv/regi-ini.mkxl delete mode 100644 tex/context/base/mkiv/scrn-ini.mklx delete mode 100644 tex/context/base/mkiv/scrn-pag.mklx delete mode 100644 tex/context/base/mkiv/spac-ali.mkxl delete mode 100644 tex/context/base/mkiv/spac-chr.mkxl delete mode 100644 tex/context/base/mkiv/spac-grd.mkxl delete mode 100644 tex/context/base/mkiv/spac-hor.mkxl delete mode 100644 tex/context/base/mkiv/spac-par.lmt delete mode 100644 tex/context/base/mkiv/spac-par.mkxl delete mode 100644 tex/context/base/mkiv/spac-ver.lmt delete mode 100644 tex/context/base/mkiv/spac-ver.mkxl delete mode 100644 tex/context/base/mkiv/strc-bkm.mkxl delete mode 100644 tex/context/base/mkiv/strc-blk.mkxl delete mode 100644 tex/context/base/mkiv/strc-con.mklx delete mode 100644 tex/context/base/mkiv/strc-des.mklx delete mode 100644 tex/context/base/mkiv/strc-doc.mkxl delete mode 100644 tex/context/base/mkiv/strc-enu.mklx delete mode 100644 tex/context/base/mkiv/strc-flt.mklx delete mode 100644 tex/context/base/mkiv/strc-ind.mkxl delete mode 100644 tex/context/base/mkiv/strc-ini.mklx delete mode 100644 tex/context/base/mkiv/strc-itm.mklx delete mode 100644 tex/context/base/mkiv/strc-lab.mkxl delete mode 100644 tex/context/base/mkiv/strc-lev.mklx delete mode 100644 tex/context/base/mkiv/strc-lnt.mklx delete mode 100644 tex/context/base/mkiv/strc-lst.mklx delete mode 100644 tex/context/base/mkiv/strc-mar.mkxl delete mode 100644 tex/context/base/mkiv/strc-mat.mkxl delete mode 100644 tex/context/base/mkiv/strc-not.mklx delete mode 100644 tex/context/base/mkiv/strc-num.mkxl delete mode 100644 tex/context/base/mkiv/strc-pag.mkxl delete mode 100644 tex/context/base/mkiv/strc-ref.mklx delete mode 100644 tex/context/base/mkiv/strc-reg.mkxl delete mode 100644 tex/context/base/mkiv/strc-ren.mkxl delete mode 100644 tex/context/base/mkiv/strc-sbe.mkxl delete mode 100644 tex/context/base/mkiv/strc-sec.mkxl delete mode 100644 tex/context/base/mkiv/strc-syn.mkxl delete mode 100644 tex/context/base/mkiv/strc-tag.lmt delete mode 100644 tex/context/base/mkiv/strc-tag.mkxl delete mode 100644 tex/context/base/mkiv/strc-tnt.mkxl delete mode 100644 tex/context/base/mkiv/strc-usr.mkxl delete mode 100644 tex/context/base/mkiv/supp-box.lmt delete mode 100644 tex/context/base/mkiv/supp-box.mkxl delete mode 100644 tex/context/base/mkiv/supp-dir.mkxl delete mode 100644 tex/context/base/mkiv/supp-mat.mkxl delete mode 100644 tex/context/base/mkiv/symb-emj.mkxl delete mode 100644 tex/context/base/mkiv/symb-ini.mkxl delete mode 100644 tex/context/base/mkiv/syst-aux.lmt delete mode 100644 tex/context/base/mkiv/syst-aux.mkxl delete mode 100644 tex/context/base/mkiv/syst-con.mkxl delete mode 100644 tex/context/base/mkiv/syst-fnt.mkxl delete mode 100644 tex/context/base/mkiv/syst-ini.mkxl delete mode 100644 tex/context/base/mkiv/syst-lua.lmt delete mode 100644 tex/context/base/mkiv/syst-lua.mkxl delete mode 100644 tex/context/base/mkiv/syst-mac.lmt delete mode 100644 tex/context/base/mkiv/tabl-com.mkxl delete mode 100644 tex/context/base/mkiv/tabl-frm.mkxl delete mode 100644 tex/context/base/mkiv/tabl-ltb.mkxl delete mode 100644 tex/context/base/mkiv/tabl-mis.mkxl delete mode 100644 tex/context/base/mkiv/tabl-ntb.mkxl delete mode 100644 tex/context/base/mkiv/tabl-nte.mkxl delete mode 100644 tex/context/base/mkiv/tabl-tab.mkxl delete mode 100644 tex/context/base/mkiv/tabl-tbl.mkxl delete mode 100644 tex/context/base/mkiv/tabl-tsp.mkxl delete mode 100644 tex/context/base/mkiv/tabl-xnt.mklx delete mode 100644 tex/context/base/mkiv/tabl-xtb.mklx delete mode 100644 tex/context/base/mkiv/task-ini.mkxl delete mode 100644 tex/context/base/mkiv/toks-aux.lmt delete mode 100644 tex/context/base/mkiv/toks-ini.lmt delete mode 100644 tex/context/base/mkiv/toks-ini.mkxl delete mode 100644 tex/context/base/mkiv/toks-scn.lmt delete mode 100644 tex/context/base/mkiv/toks-scn.mkxl delete mode 100644 tex/context/base/mkiv/trac-ctx.mkxl delete mode 100644 tex/context/base/mkiv/trac-deb.lmt delete mode 100644 tex/context/base/mkiv/trac-deb.mkxl delete mode 100644 tex/context/base/mkiv/trac-inf.lmt delete mode 100644 tex/context/base/mkiv/trac-jus.mkxl delete mode 100644 tex/context/base/mkiv/trac-tex.mkxl delete mode 100644 tex/context/base/mkiv/trac-tim.lmt delete mode 100644 tex/context/base/mkiv/trac-vis.lmt delete mode 100644 tex/context/base/mkiv/trac-vis.mkxl delete mode 100644 tex/context/base/mkiv/type-ini.mklx delete mode 100644 tex/context/base/mkiv/typo-brk.mkxl delete mode 100644 tex/context/base/mkiv/typo-cap.mkxl delete mode 100644 tex/context/base/mkiv/typo-cln.mkxl delete mode 100644 tex/context/base/mkiv/typo-del.mkxl delete mode 100644 tex/context/base/mkiv/typo-dir.mkxl delete mode 100644 tex/context/base/mkiv/typo-ini.mkxl delete mode 100644 tex/context/base/mkiv/typo-inj.mkxl delete mode 100644 tex/context/base/mkiv/typo-itc.mklx delete mode 100644 tex/context/base/mkiv/typo-krn.mkxl delete mode 100644 tex/context/base/mkiv/typo-lan.mkxl delete mode 100644 tex/context/base/mkiv/typo-lig.mkxl delete mode 100644 tex/context/base/mkiv/typo-lin.lmt delete mode 100644 tex/context/base/mkiv/typo-lin.mkxl delete mode 100644 tex/context/base/mkiv/typo-mar.mkxl delete mode 100644 tex/context/base/mkiv/typo-pnc.mkxl delete mode 100644 tex/context/base/mkiv/typo-scr.mkxl delete mode 100644 tex/context/base/mkiv/unic-ini.mkxl create mode 100644 tex/context/base/mkxl/anch-bar.mkxl create mode 100644 tex/context/base/mkxl/anch-bck.mklx create mode 100644 tex/context/base/mkxl/anch-pgr.mkxl create mode 100644 tex/context/base/mkxl/anch-pos.lmt create mode 100644 tex/context/base/mkxl/anch-pos.mkxl create mode 100644 tex/context/base/mkxl/anch-snc.mkxl create mode 100644 tex/context/base/mkxl/anch-tab.mkxl create mode 100644 tex/context/base/mkxl/attr-col.mkxl create mode 100644 tex/context/base/mkxl/attr-eff.mkxl create mode 100644 tex/context/base/mkxl/attr-ini.mkxl create mode 100644 tex/context/base/mkxl/attr-lay.lmt create mode 100644 tex/context/base/mkxl/attr-lay.mkxl create mode 100644 tex/context/base/mkxl/attr-mkr.mkxl create mode 100644 tex/context/base/mkxl/attr-neg.mkxl create mode 100644 tex/context/base/mkxl/back-exp.mkxl create mode 100644 tex/context/base/mkxl/back-ini.mkxl create mode 100644 tex/context/base/mkxl/back-lua.lmt create mode 100644 tex/context/base/mkxl/back-lua.mkxl create mode 100644 tex/context/base/mkxl/back-mps.lmt create mode 100644 tex/context/base/mkxl/back-mps.mkxl create mode 100644 tex/context/base/mkxl/back-out.lmt create mode 100644 tex/context/base/mkxl/back-out.mkxl create mode 100644 tex/context/base/mkxl/back-pdf.mkxl create mode 100644 tex/context/base/mkxl/back-res.mkxl create mode 100644 tex/context/base/mkxl/back-trf.mkxl create mode 100644 tex/context/base/mkxl/back-u3d.mkxl create mode 100644 tex/context/base/mkxl/bibl-bib.mkxl create mode 100644 tex/context/base/mkxl/bibl-tra.mkxl create mode 100644 tex/context/base/mkxl/blob-ini.lmt create mode 100644 tex/context/base/mkxl/blob-ini.mkxl create mode 100644 tex/context/base/mkxl/buff-ini.mkxl create mode 100644 tex/context/base/mkxl/buff-par.mklx create mode 100644 tex/context/base/mkxl/buff-ver.mkxl create mode 100644 tex/context/base/mkxl/catc-act.mkxl create mode 100644 tex/context/base/mkxl/catc-ctx.mkxl create mode 100644 tex/context/base/mkxl/catc-def.mkxl create mode 100644 tex/context/base/mkxl/catc-ini.mkxl create mode 100644 tex/context/base/mkxl/catc-sym.mkxl create mode 100644 tex/context/base/mkxl/char-act.mkxl create mode 100644 tex/context/base/mkxl/char-enc.mkxl create mode 100644 tex/context/base/mkxl/char-ini.mkxl create mode 100644 tex/context/base/mkxl/char-utf.mkxl create mode 100644 tex/context/base/mkxl/chem-ini.mkxl create mode 100644 tex/context/base/mkxl/chem-str.mkxl create mode 100644 tex/context/base/mkxl/cldf-bas.mkxl create mode 100644 tex/context/base/mkxl/cldf-com.mkxl create mode 100644 tex/context/base/mkxl/cldf-ini.mkxl create mode 100644 tex/context/base/mkxl/cldf-int.lmt create mode 100644 tex/context/base/mkxl/cldf-int.mkxl create mode 100644 tex/context/base/mkxl/cldf-lmt.lmt create mode 100644 tex/context/base/mkxl/cldf-ver.mkxl create mode 100644 tex/context/base/mkxl/colo-ext.mkxl create mode 100644 tex/context/base/mkxl/colo-grp.mkxl create mode 100644 tex/context/base/mkxl/colo-ini.mkxl create mode 100644 tex/context/base/mkxl/cont-cs.mkxl create mode 100644 tex/context/base/mkxl/cont-de.mkxl create mode 100644 tex/context/base/mkxl/cont-en.mkxl create mode 100644 tex/context/base/mkxl/cont-fil.mkxl create mode 100644 tex/context/base/mkxl/cont-fr.mkxl create mode 100644 tex/context/base/mkxl/cont-gb.mkxl create mode 100644 tex/context/base/mkxl/cont-it.mkxl create mode 100644 tex/context/base/mkxl/cont-log.mkxl create mode 100644 tex/context/base/mkxl/cont-new.mkxl create mode 100644 tex/context/base/mkxl/cont-nl.mkxl create mode 100644 tex/context/base/mkxl/cont-pe.mkxl create mode 100644 tex/context/base/mkxl/cont-ro.mkxl create mode 100644 tex/context/base/mkxl/cont-run.mkxl create mode 100644 tex/context/base/mkxl/context.mkxl create mode 100644 tex/context/base/mkxl/core-con.mkxl create mode 100644 tex/context/base/mkxl/core-ctx.mkxl create mode 100644 tex/context/base/mkxl/core-dat.mkxl create mode 100644 tex/context/base/mkxl/core-def.mkxl create mode 100644 tex/context/base/mkxl/core-env.lmt create mode 100644 tex/context/base/mkxl/core-env.mkxl create mode 100644 tex/context/base/mkxl/core-ini.mkxl create mode 100644 tex/context/base/mkxl/core-lmt.lmt create mode 100644 tex/context/base/mkxl/core-lmt.mkxl create mode 100644 tex/context/base/mkxl/core-sys.lmt create mode 100644 tex/context/base/mkxl/core-sys.mkxl create mode 100644 tex/context/base/mkxl/core-two.mkxl create mode 100644 tex/context/base/mkxl/core-uti.lua create mode 100644 tex/context/base/mkxl/core-uti.mkxl create mode 100644 tex/context/base/mkxl/driv-ini.mkxl create mode 100644 tex/context/base/mkxl/driv-shp.lmt create mode 100644 tex/context/base/mkxl/driv-shp.mkxl create mode 100644 tex/context/base/mkxl/enco-ini.mkxl create mode 100644 tex/context/base/mkxl/file-ini.mklx create mode 100644 tex/context/base/mkxl/file-job.lmt create mode 100644 tex/context/base/mkxl/file-job.mklx create mode 100644 tex/context/base/mkxl/file-lib.mkxl create mode 100644 tex/context/base/mkxl/file-mod.mklx create mode 100644 tex/context/base/mkxl/file-res.mklx create mode 100644 tex/context/base/mkxl/file-syn.mklx create mode 100644 tex/context/base/mkxl/font-aux.mklx create mode 100644 tex/context/base/mkxl/font-chk.mkxl create mode 100644 tex/context/base/mkxl/font-col.mklx create mode 100644 tex/context/base/mkxl/font-emp.mklx create mode 100644 tex/context/base/mkxl/font-fea.mklx create mode 100644 tex/context/base/mkxl/font-fil.mklx create mode 100644 tex/context/base/mkxl/font-gds.mklx create mode 100644 tex/context/base/mkxl/font-ini.mklx create mode 100644 tex/context/base/mkxl/font-lib.mklx create mode 100644 tex/context/base/mkxl/font-mat.mklx create mode 100644 tex/context/base/mkxl/font-ogr.lmt create mode 100644 tex/context/base/mkxl/font-pre.mkxl create mode 100644 tex/context/base/mkxl/font-sel.mklx create mode 100644 tex/context/base/mkxl/font-set.mklx create mode 100644 tex/context/base/mkxl/font-sol.mklx create mode 100644 tex/context/base/mkxl/font-sty.mklx create mode 100644 tex/context/base/mkxl/font-sym.mklx create mode 100644 tex/context/base/mkxl/font-tra.mkxl create mode 100644 tex/context/base/mkxl/font-uni.mkxl create mode 100644 tex/context/base/mkxl/font-unk.mkxl create mode 100644 tex/context/base/mkxl/font-var.mklx create mode 100644 tex/context/base/mkxl/grph-epd.mkxl create mode 100644 tex/context/base/mkxl/grph-fig.mkxl create mode 100644 tex/context/base/mkxl/grph-inc.mkxl create mode 100644 tex/context/base/mkxl/grph-pat.mkxl create mode 100644 tex/context/base/mkxl/grph-raw.mkxl create mode 100644 tex/context/base/mkxl/grph-rul.mkxl create mode 100644 tex/context/base/mkxl/grph-trf.mkxl create mode 100644 tex/context/base/mkxl/hand-ini.mkxl create mode 100644 tex/context/base/mkxl/java-ini.mkxl create mode 100644 tex/context/base/mkxl/lang-def.mkxl create mode 100644 tex/context/base/mkxl/lang-dis.lmt create mode 100644 tex/context/base/mkxl/lang-frd.mkxl create mode 100644 tex/context/base/mkxl/lang-frq.mkxl create mode 100644 tex/context/base/mkxl/lang-hyp.lmt create mode 100644 tex/context/base/mkxl/lang-hyp.mkxl create mode 100644 tex/context/base/mkxl/lang-ini.lmt create mode 100644 tex/context/base/mkxl/lang-ini.mkxl create mode 100644 tex/context/base/mkxl/lang-lab.mkxl create mode 100644 tex/context/base/mkxl/lang-mis.mkxl create mode 100644 tex/context/base/mkxl/lang-rep.mkxl create mode 100644 tex/context/base/mkxl/lang-spa.mkxl create mode 100644 tex/context/base/mkxl/lang-tra.mkxl create mode 100644 tex/context/base/mkxl/lang-url.mkxl create mode 100644 tex/context/base/mkxl/lang-wrd.mkxl create mode 100644 tex/context/base/mkxl/layo-ini.mkxl create mode 100644 tex/context/base/mkxl/libs-imp-curl.lmt create mode 100644 tex/context/base/mkxl/libs-imp-ghostscript.lmt create mode 100644 tex/context/base/mkxl/libs-imp-graphicsmagick.lmt create mode 100644 tex/context/base/mkxl/libs-imp-kpse.lmt create mode 100644 tex/context/base/mkxl/libs-imp-kpse.mkxl create mode 100644 tex/context/base/mkxl/libs-imp-mujs.lmt create mode 100644 tex/context/base/mkxl/libs-imp-mujs.mkxl create mode 100644 tex/context/base/mkxl/libs-imp-mysql.lmt create mode 100644 tex/context/base/mkxl/libs-imp-postgress.lmt create mode 100644 tex/context/base/mkxl/libs-imp-sqlite.lmt create mode 100644 tex/context/base/mkxl/libs-imp-zint.lmt create mode 100644 tex/context/base/mkxl/libs-imp-zint.mkxl create mode 100644 tex/context/base/mkxl/libs-ini.mkxl create mode 100644 tex/context/base/mkxl/lpdf-emb.lmt create mode 100644 tex/context/base/mkxl/lpdf-img.lmt create mode 100644 tex/context/base/mkxl/lpdf-lmt.lmt create mode 100644 tex/context/base/mkxl/lpdf-vfc.lmt create mode 100644 tex/context/base/mkxl/luat-bas.mkxl create mode 100644 tex/context/base/mkxl/luat-cod.lmt create mode 100644 tex/context/base/mkxl/luat-cod.mkxl create mode 100644 tex/context/base/mkxl/luat-fio.lmt create mode 100644 tex/context/base/mkxl/luat-ini.mkxl create mode 100644 tex/context/base/mkxl/luat-lib.mkxl create mode 100644 tex/context/base/mkxl/luat-log.lmt create mode 100644 tex/context/base/mkxl/luat-soc.mkxl create mode 100644 tex/context/base/mkxl/luat-usr.mkxl create mode 100644 tex/context/base/mkxl/lxml-css.mkxl create mode 100644 tex/context/base/mkxl/lxml-ctx.mkxl create mode 100644 tex/context/base/mkxl/lxml-ini.mkxl create mode 100644 tex/context/base/mkxl/lxml-sor.mkxl create mode 100644 tex/context/base/mkxl/m-mkivmkxl.mkxl create mode 100644 tex/context/base/mkxl/math-acc.mklx create mode 100644 tex/context/base/mkxl/math-ali.mkxl create mode 100644 tex/context/base/mkxl/math-def.mkxl create mode 100644 tex/context/base/mkxl/math-del.mkxl create mode 100644 tex/context/base/mkxl/math-dis.mkxl create mode 100644 tex/context/base/mkxl/math-fen.mkxl create mode 100644 tex/context/base/mkxl/math-for.mkxl create mode 100644 tex/context/base/mkxl/math-frc.mkxl create mode 100644 tex/context/base/mkxl/math-inc.mkxl create mode 100644 tex/context/base/mkxl/math-ini.mkxl create mode 100644 tex/context/base/mkxl/math-inl.mkxl create mode 100644 tex/context/base/mkxl/math-int.mkxl create mode 100644 tex/context/base/mkxl/math-mis.mkxl create mode 100644 tex/context/base/mkxl/math-noa.lmt create mode 100644 tex/context/base/mkxl/math-pln.mkxl create mode 100644 tex/context/base/mkxl/math-rad.mklx create mode 100644 tex/context/base/mkxl/math-scr.mkxl create mode 100644 tex/context/base/mkxl/math-stc.mklx create mode 100644 tex/context/base/mkxl/math-tag.lmt create mode 100644 tex/context/base/mkxl/math-toy.mkxl create mode 100644 tex/context/base/mkxl/meta-blb.mkxl create mode 100644 tex/context/base/mkxl/meta-fig.mkxl create mode 100644 tex/context/base/mkxl/meta-fnt.mkxl create mode 100644 tex/context/base/mkxl/meta-fun.mkxl create mode 100644 tex/context/base/mkxl/meta-grd.mkxl create mode 100644 tex/context/base/mkxl/meta-imp-experiments.mkxl create mode 100644 tex/context/base/mkxl/meta-imp-gamesymbols.mkxl create mode 100644 tex/context/base/mkxl/meta-imp-symbols.mkxl create mode 100644 tex/context/base/mkxl/meta-imp-threesix.mkxl create mode 100644 tex/context/base/mkxl/meta-ini.mkxl create mode 100644 tex/context/base/mkxl/meta-lua.mkxl create mode 100644 tex/context/base/mkxl/meta-mac.mkxl create mode 100644 tex/context/base/mkxl/meta-nod.mkxl create mode 100644 tex/context/base/mkxl/meta-pag.mkxl create mode 100644 tex/context/base/mkxl/meta-pdf.mkxl create mode 100644 tex/context/base/mkxl/meta-pdh.mkxl create mode 100644 tex/context/base/mkxl/meta-tex.mkxl create mode 100644 tex/context/base/mkxl/meta-xml.mkxl create mode 100644 tex/context/base/mkxl/mlib-cnt.lmt create mode 100644 tex/context/base/mkxl/mlib-ctx.mkxl create mode 100644 tex/context/base/mkxl/mlib-fio.lmt create mode 100644 tex/context/base/mkxl/mlib-int.lmt create mode 100644 tex/context/base/mkxl/mlib-lmp.lmt create mode 100644 tex/context/base/mkxl/mlib-lmt.lmt create mode 100644 tex/context/base/mkxl/mlib-lua.lmt create mode 100644 tex/context/base/mkxl/mlib-mat.lmt create mode 100644 tex/context/base/mkxl/mlib-pdf.mkxl create mode 100644 tex/context/base/mkxl/mlib-pps.mkxl create mode 100644 tex/context/base/mkxl/mlib-ran.lmt create mode 100644 tex/context/base/mkxl/mlib-scn.lmt create mode 100644 tex/context/base/mkxl/mlib-svg.lmt create mode 100644 tex/context/base/mkxl/mult-aux.mkxl create mode 100644 tex/context/base/mkxl/mult-def.mkxl create mode 100644 tex/context/base/mkxl/mult-dim.mklx create mode 100644 tex/context/base/mkxl/mult-ini.mkxl create mode 100644 tex/context/base/mkxl/mult-prm.mkxl create mode 100644 tex/context/base/mkxl/mult-sys.mkxl create mode 100644 tex/context/base/mkxl/node-aux.lmt create mode 100644 tex/context/base/mkxl/node-bck.mkxl create mode 100644 tex/context/base/mkxl/node-cmp.lmt create mode 100644 tex/context/base/mkxl/node-fin.mkxl create mode 100644 tex/context/base/mkxl/node-gcm.lmt create mode 100644 tex/context/base/mkxl/node-ini.lmt create mode 100644 tex/context/base/mkxl/node-ini.mkxl create mode 100644 tex/context/base/mkxl/node-mig.lmt create mode 100644 tex/context/base/mkxl/node-mig.mkxl create mode 100644 tex/context/base/mkxl/node-nut.lmt create mode 100644 tex/context/base/mkxl/node-par.lmt create mode 100644 tex/context/base/mkxl/node-rul.mkxl create mode 100644 tex/context/base/mkxl/node-ser.lmt create mode 100644 tex/context/base/mkxl/node-snp.lmt create mode 100644 tex/context/base/mkxl/node-tex.lmt create mode 100644 tex/context/base/mkxl/norm-ctx.mkxl create mode 100644 tex/context/base/mkxl/pack-bar.mkxl create mode 100644 tex/context/base/mkxl/pack-bck.mklx create mode 100644 tex/context/base/mkxl/pack-box.mkxl create mode 100644 tex/context/base/mkxl/pack-com.mkxl create mode 100644 tex/context/base/mkxl/pack-cut.mkxl create mode 100644 tex/context/base/mkxl/pack-fen.mkxl create mode 100644 tex/context/base/mkxl/pack-lyr.mkxl create mode 100644 tex/context/base/mkxl/pack-mis.mklx create mode 100644 tex/context/base/mkxl/pack-mrl.mkxl create mode 100644 tex/context/base/mkxl/pack-obj.lmt create mode 100644 tex/context/base/mkxl/pack-obj.mkxl create mode 100644 tex/context/base/mkxl/pack-ori.lmt create mode 100644 tex/context/base/mkxl/pack-ori.mkxl create mode 100644 tex/context/base/mkxl/pack-pos.mkxl create mode 100644 tex/context/base/mkxl/pack-rul.lmt create mode 100644 tex/context/base/mkxl/pack-rul.mkxl create mode 100644 tex/context/base/mkxl/page-app.mkxl create mode 100644 tex/context/base/mkxl/page-bck.mkxl create mode 100644 tex/context/base/mkxl/page-box.mklx create mode 100644 tex/context/base/mkxl/page-brk.mkxl create mode 100644 tex/context/base/mkxl/page-col.mkxl create mode 100644 tex/context/base/mkxl/page-com.mkxl create mode 100644 tex/context/base/mkxl/page-cst.mkxl create mode 100644 tex/context/base/mkxl/page-fac.mkxl create mode 100644 tex/context/base/mkxl/page-ffl.mkxl create mode 100644 tex/context/base/mkxl/page-flt.mkxl create mode 100644 tex/context/base/mkxl/page-flw.mkxl create mode 100644 tex/context/base/mkxl/page-imp.mkxl create mode 100644 tex/context/base/mkxl/page-inf.mkxl create mode 100644 tex/context/base/mkxl/page-ini.mkxl create mode 100644 tex/context/base/mkxl/page-inj.mklx create mode 100644 tex/context/base/mkxl/page-ins.mkxl create mode 100644 tex/context/base/mkxl/page-lay.mkxl create mode 100644 tex/context/base/mkxl/page-mak.mklx create mode 100644 tex/context/base/mkxl/page-mbk.mklx create mode 100644 tex/context/base/mkxl/page-mcl.mkxl create mode 100644 tex/context/base/mkxl/page-mix.mkxl create mode 100644 tex/context/base/mkxl/page-mrk.mkxl create mode 100644 tex/context/base/mkxl/page-not.mkxl create mode 100644 tex/context/base/mkxl/page-one.mkxl create mode 100644 tex/context/base/mkxl/page-otr.mklx create mode 100644 tex/context/base/mkxl/page-par.mkxl create mode 100644 tex/context/base/mkxl/page-pcl.mkxl create mode 100644 tex/context/base/mkxl/page-plg.mkxl create mode 100644 tex/context/base/mkxl/page-pst.mkxl create mode 100644 tex/context/base/mkxl/page-sel.mklx create mode 100644 tex/context/base/mkxl/page-sid.mkxl create mode 100644 tex/context/base/mkxl/page-smp.mkxl create mode 100644 tex/context/base/mkxl/page-spr.mkxl create mode 100644 tex/context/base/mkxl/page-str.mkxl create mode 100644 tex/context/base/mkxl/page-txt.mklx create mode 100644 tex/context/base/mkxl/page-var.mkxl create mode 100644 tex/context/base/mkxl/phys-dim.mkxl create mode 100644 tex/context/base/mkxl/publ-inc.mkxl create mode 100644 tex/context/base/mkxl/publ-ini.mkxl create mode 100644 tex/context/base/mkxl/publ-old.mkxl create mode 100644 tex/context/base/mkxl/publ-tra.mkxl create mode 100644 tex/context/base/mkxl/publ-xml.mkxl create mode 100644 tex/context/base/mkxl/regi-ini.mkxl create mode 100644 tex/context/base/mkxl/scrn-bar.mklx create mode 100644 tex/context/base/mkxl/scrn-but.mklx create mode 100644 tex/context/base/mkxl/scrn-fld.mklx create mode 100644 tex/context/base/mkxl/scrn-hlp.mklx create mode 100644 tex/context/base/mkxl/scrn-ini.mklx create mode 100644 tex/context/base/mkxl/scrn-pag.mklx create mode 100644 tex/context/base/mkxl/scrn-ref.mklx create mode 100644 tex/context/base/mkxl/scrn-wid.mklx create mode 100644 tex/context/base/mkxl/scrp-ini.mkxl create mode 100644 tex/context/base/mkxl/sort-ini.mkxl create mode 100644 tex/context/base/mkxl/spac-ali.mkxl create mode 100644 tex/context/base/mkxl/spac-chr.mkxl create mode 100644 tex/context/base/mkxl/spac-def.mkxl create mode 100644 tex/context/base/mkxl/spac-flr.mkxl create mode 100644 tex/context/base/mkxl/spac-grd.mkxl create mode 100644 tex/context/base/mkxl/spac-hor.mkxl create mode 100644 tex/context/base/mkxl/spac-lin.mkxl create mode 100644 tex/context/base/mkxl/spac-pag.mkxl create mode 100644 tex/context/base/mkxl/spac-par.lmt create mode 100644 tex/context/base/mkxl/spac-par.mkxl create mode 100644 tex/context/base/mkxl/spac-prf.mklx create mode 100644 tex/context/base/mkxl/spac-ver.lmt create mode 100644 tex/context/base/mkxl/spac-ver.mkxl create mode 100644 tex/context/base/mkxl/strc-bkm.mkxl create mode 100644 tex/context/base/mkxl/strc-blk.mkxl create mode 100644 tex/context/base/mkxl/strc-con.mklx create mode 100644 tex/context/base/mkxl/strc-def.mkxl create mode 100644 tex/context/base/mkxl/strc-des.mklx create mode 100644 tex/context/base/mkxl/strc-doc.mkxl create mode 100644 tex/context/base/mkxl/strc-enu.mklx create mode 100644 tex/context/base/mkxl/strc-flt.mklx create mode 100644 tex/context/base/mkxl/strc-ind.mkxl create mode 100644 tex/context/base/mkxl/strc-ini.mklx create mode 100644 tex/context/base/mkxl/strc-itm.mklx create mode 100644 tex/context/base/mkxl/strc-lab.mkxl create mode 100644 tex/context/base/mkxl/strc-lev.mklx create mode 100644 tex/context/base/mkxl/strc-lnt.mklx create mode 100644 tex/context/base/mkxl/strc-lst.mklx create mode 100644 tex/context/base/mkxl/strc-mar.mkxl create mode 100644 tex/context/base/mkxl/strc-mat.mkxl create mode 100644 tex/context/base/mkxl/strc-not.mklx create mode 100644 tex/context/base/mkxl/strc-num.mkxl create mode 100644 tex/context/base/mkxl/strc-pag.mkxl create mode 100644 tex/context/base/mkxl/strc-ref.mklx create mode 100644 tex/context/base/mkxl/strc-reg.mkxl create mode 100644 tex/context/base/mkxl/strc-ren.mkxl create mode 100644 tex/context/base/mkxl/strc-sbe.mkxl create mode 100644 tex/context/base/mkxl/strc-sec.mkxl create mode 100644 tex/context/base/mkxl/strc-syn.mkxl create mode 100644 tex/context/base/mkxl/strc-tag.lmt create mode 100644 tex/context/base/mkxl/strc-tag.mkxl create mode 100644 tex/context/base/mkxl/strc-tnt.mkxl create mode 100644 tex/context/base/mkxl/strc-usr.mkxl create mode 100644 tex/context/base/mkxl/supp-box.lmt create mode 100644 tex/context/base/mkxl/supp-box.mkxl create mode 100644 tex/context/base/mkxl/supp-dir.mkxl create mode 100644 tex/context/base/mkxl/supp-mat.mkxl create mode 100644 tex/context/base/mkxl/supp-ran.mkxl create mode 100644 tex/context/base/mkxl/symb-emj.mkxl create mode 100644 tex/context/base/mkxl/symb-ini.mkxl create mode 100644 tex/context/base/mkxl/syst-aux.lmt create mode 100644 tex/context/base/mkxl/syst-aux.mkxl create mode 100644 tex/context/base/mkxl/syst-cmp.mkxl create mode 100644 tex/context/base/mkxl/syst-con.mkxl create mode 100644 tex/context/base/mkxl/syst-fnt.mkxl create mode 100644 tex/context/base/mkxl/syst-ini.mkxl create mode 100644 tex/context/base/mkxl/syst-lua.lmt create mode 100644 tex/context/base/mkxl/syst-lua.mkxl create mode 100644 tex/context/base/mkxl/syst-mac.lmt create mode 100644 tex/context/base/mkxl/syst-mes.mkxl create mode 100644 tex/context/base/mkxl/syst-pln.mkxl create mode 100644 tex/context/base/mkxl/syst-rtp.mkxl create mode 100644 tex/context/base/mkxl/tabl-com.mkxl create mode 100644 tex/context/base/mkxl/tabl-frm.mkxl create mode 100644 tex/context/base/mkxl/tabl-ltb.mkxl create mode 100644 tex/context/base/mkxl/tabl-mis.mkxl create mode 100644 tex/context/base/mkxl/tabl-ntb.mkxl create mode 100644 tex/context/base/mkxl/tabl-nte.mkxl create mode 100644 tex/context/base/mkxl/tabl-tab.mkxl create mode 100644 tex/context/base/mkxl/tabl-tbl.mkxl create mode 100644 tex/context/base/mkxl/tabl-tsp.mkxl create mode 100644 tex/context/base/mkxl/tabl-xnt.mklx create mode 100644 tex/context/base/mkxl/tabl-xtb.mklx create mode 100644 tex/context/base/mkxl/task-ini.mkxl create mode 100644 tex/context/base/mkxl/toks-aux.lmt create mode 100644 tex/context/base/mkxl/toks-aux.mkxl create mode 100644 tex/context/base/mkxl/toks-ini.lmt create mode 100644 tex/context/base/mkxl/toks-ini.mkxl create mode 100644 tex/context/base/mkxl/toks-scn.lmt create mode 100644 tex/context/base/mkxl/toks-scn.mkxl create mode 100644 tex/context/base/mkxl/trac-ctx.mkxl create mode 100644 tex/context/base/mkxl/trac-deb.lmt create mode 100644 tex/context/base/mkxl/trac-deb.mkxl create mode 100644 tex/context/base/mkxl/trac-inf.lmt create mode 100644 tex/context/base/mkxl/trac-jus.mkxl create mode 100644 tex/context/base/mkxl/trac-tex.mkxl create mode 100644 tex/context/base/mkxl/trac-tim.lmt create mode 100644 tex/context/base/mkxl/trac-vis.lmt create mode 100644 tex/context/base/mkxl/trac-vis.mkxl create mode 100644 tex/context/base/mkxl/type-def.mkxl create mode 100644 tex/context/base/mkxl/type-fbk.mkxl create mode 100644 tex/context/base/mkxl/type-ini.mklx create mode 100644 tex/context/base/mkxl/type-lua.mkxl create mode 100644 tex/context/base/mkxl/type-set.mkxl create mode 100644 tex/context/base/mkxl/type-siz.mkxl create mode 100644 tex/context/base/mkxl/typo-bld.mkxl create mode 100644 tex/context/base/mkxl/typo-brk.mkxl create mode 100644 tex/context/base/mkxl/typo-cap.mkxl create mode 100644 tex/context/base/mkxl/typo-chr.mkxl create mode 100644 tex/context/base/mkxl/typo-cln.mkxl create mode 100644 tex/context/base/mkxl/typo-del.mkxl create mode 100644 tex/context/base/mkxl/typo-dig.mkxl create mode 100644 tex/context/base/mkxl/typo-dir.mkxl create mode 100644 tex/context/base/mkxl/typo-drp.mkxl create mode 100644 tex/context/base/mkxl/typo-fkr.mkxl create mode 100644 tex/context/base/mkxl/typo-fln.mkxl create mode 100644 tex/context/base/mkxl/typo-ini.mkxl create mode 100644 tex/context/base/mkxl/typo-inj.mkxl create mode 100644 tex/context/base/mkxl/typo-itc.mklx create mode 100644 tex/context/base/mkxl/typo-itm.mkxl create mode 100644 tex/context/base/mkxl/typo-krn.mkxl create mode 100644 tex/context/base/mkxl/typo-lan.mkxl create mode 100644 tex/context/base/mkxl/typo-lig.mkxl create mode 100644 tex/context/base/mkxl/typo-lin.lmt create mode 100644 tex/context/base/mkxl/typo-lin.mkxl create mode 100644 tex/context/base/mkxl/typo-mar.mkxl create mode 100644 tex/context/base/mkxl/typo-ovl.mkxl create mode 100644 tex/context/base/mkxl/typo-pag.mkxl create mode 100644 tex/context/base/mkxl/typo-par.mkxl create mode 100644 tex/context/base/mkxl/typo-plc.mkxl create mode 100644 tex/context/base/mkxl/typo-pnc.mkxl create mode 100644 tex/context/base/mkxl/typo-prc.mklx create mode 100644 tex/context/base/mkxl/typo-rep.mkxl create mode 100644 tex/context/base/mkxl/typo-rub.mkxl create mode 100644 tex/context/base/mkxl/typo-scr.mkxl create mode 100644 tex/context/base/mkxl/typo-spa.mkxl create mode 100644 tex/context/base/mkxl/typo-sus.mkxl create mode 100644 tex/context/base/mkxl/typo-tal.mkxl create mode 100644 tex/context/base/mkxl/typo-txt.mklx create mode 100644 tex/context/base/mkxl/typo-wrp.mkxl create mode 100644 tex/context/base/mkxl/unic-ini.mkxl create mode 100644 tex/context/interface/mkiv/i-parwrapper.xml diff --git a/context/data/scite/context/lexers/data/scite-context-data-tex.lua b/context/data/scite/context/lexers/data/scite-context-data-tex.lua index 502483461..62f9ef47d 100644 --- a/context/data/scite/context/lexers/data/scite-context-data-tex.lua +++ b/context/data/scite/context/lexers/data/scite-context-data-tex.lua @@ -1,7 +1,7 @@ return { ["aleph"]={ "Alephminorversion", "Alephrevision", "Alephversion" }, ["etex"]={ "botmarks", "clubpenalties", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "detokenize", "dimexpr", "displaywidowpenalties", "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", "savinghyphcodes", "savingvdiscards", "scantokens", "showgroups", "showifs", "showtokens", "splitbotmarks", "splitdiscards", "splitfirstmarks", "topmarks", "tracingalignments", "tracingassigns", "tracinggroups", "tracingifs", "tracingnesting", "unexpanded", "unless", "widowpenalties" }, - ["luatex"]={ "UUskewed", "UUskewedwithdelims", "Uabove", "Uabovewithdelims", "Uatop", "Uatopwithdelims", "Uchar", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Uhextensible", "Uleft", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathcharclass", "Umathchardef", "Umathcharfam", "Umathcharnum", "Umathcharnumdef", "Umathcharslot", "Umathclass", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathnolimitsubfactor", "Umathnolimitsupfactor", "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", "Umathspacebeforescript", "Umathspacingmode", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Umiddle", "Unosubprescript", "Unosubscript", "Unosuperprescript", "Unosuperscript", "Uover", "Uoverdelimiter", "Uoverwithdelims", "Uradical", "Uright", "Uroot", "Uskewed", "Uskewedwithdelims", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Ustyle", "Usubprescript", "Usubscript", "Usuperprescript", "Usuperscript", "Uunderdelimiter", "Uvextensible", "adjustspacing", "adjustspacingshrink", "adjustspacingstep", "adjustspacingstretch", "afterassigned", "aftergrouped", "aliased", "alignmark", "aligntab", "atendofgroup", "atendofgrouped", "attribute", "attributedef", "automaticdiscretionary", "automatichyphenpenalty", "automigrationmode", "begincsname", "beginlocalcontrol", "boundary", "boxattribute", "boxdirection", "boxorientation", "boxtotal", "boxxmove", "boxxoffset", "boxymove", "boxyoffset", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "csstring", "defcsname", "dimensiondef", "directlua", "edefcsname", "efcode", "endlocalcontrol", "enforced", "etoksapp", "etokspre", "everytab", "exceptionpenalty", "expand", "expandafterpars", "expandafterspaces", "expandcstoken", "expanded", "expandtoken", "explicitdiscretionary", "explicithyphenpenalty", "firstvalidlanguage", "fontid", "fontspecifiedsize", "formatname", "frozen", "futuredef", "futureexpand", "futureexpandis", "futureexpandisap", "gleaders", "glet", "glyphdatafield", "glyphdimensionsmode", "glyphoptions", "glyphscriptfield", "glyphstatefield", "gtoksapp", "gtokspre", "hjcode", "hpack", "hyphenationmin", "hyphenationmode", "ifabsdim", "ifabsnum", "ifarguments", "ifboolean", "ifchkdim", "ifchknum", "ifcmpdim", "ifcmpnum", "ifcondition", "ifcstok", "ifdimval", "ifempty", "ifflags", "ifhastok", "ifhastoks", "ifhasxtoks", "ifincsname", "ifmathparameter", "ifmathstyle", "ifnumval", "ifparameter", "ifparameters", "iftok", "ignorearguments", "ignorepars", "immediate", "immutable", "initcatcodetable", "insertheights", "insertht", "instance", "integerdef", "lastarguments", "lastnamedcs", "lastnodesubtype", "leftmarginkern", "letcharcode", "letcsname", "letfrozen", "letprotected", "linedirection", "linepar", "localbrokenpenalty", "localcontrol", "localcontrolled", "localinterlinepenalty", "localleftbox", "localrightbox", "lpcode", "luabytecode", "luabytecodecall", "luacopyinputnodes", "luadef", "luaescapestring", "luafunction", "luafunctioncall", "luatexbanner", "luatexrevision", "luatexversion", "mathdelimitersmode", "mathdirection", "mathdisplayskipmode", "matheqnogapstep", "mathflattenmode", "mathitalicsmode", "mathnolimitsmode", "matholdmode", "mathpenaltiesmode", "mathrulesfam", "mathrulesmode", "mathrulethicknessmode", "mathscriptboxmode", "mathscriptcharmode", "mathscriptsmode", "mathstyle", "mathsurroundmode", "mathsurroundskip", "mutable", "noaligned", "noboundary", "nohrule", "normalizelinemode", "nospaces", "novrule", "orelse", "orunless", "outputbox", "overloaded", "overloadmode", "parametercount", "parattr", "pardirection", "permanent", "postexhyphenchar", "posthyphenchar", "prebinoppenalty", "predisplaygapfactor", "preexhyphenchar", "prehyphenchar", "prerelpenalty", "protrudechars", "protrusionboundary", "pxdimen", "quitvmode", "rightmarginkern", "rpcode", "savecatcodetable", "scantextokens", "setfontid", "snapshotpar", "supmarkmode", "swapcsvalues", "textdirection", "thewithoutunit", "tokenized", "toksapp", "tokspre", "tolerant", "tpack", "tracingfonts", "tracingmath", "unletfrozen", "unletprotected", "vpack", "wordboundary", "wrapuppar", "xtoksapp", "xtokspre" }, + ["luatex"]={ "UUskewed", "UUskewedwithdelims", "Uabove", "Uabovewithdelims", "Uatop", "Uatopwithdelims", "Uchar", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Uhextensible", "Uleft", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathcharclass", "Umathchardef", "Umathcharfam", "Umathcharnum", "Umathcharnumdef", "Umathcharslot", "Umathclass", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathnolimitsubfactor", "Umathnolimitsupfactor", "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", "Umathspacebeforescript", "Umathspacingmode", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Umiddle", "Unosubprescript", "Unosubscript", "Unosuperprescript", "Unosuperscript", "Uover", "Uoverdelimiter", "Uoverwithdelims", "Uradical", "Uright", "Uroot", "Uskewed", "Uskewedwithdelims", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Ustyle", "Usubprescript", "Usubscript", "Usuperprescript", "Usuperscript", "Uunderdelimiter", "Uvextensible", "adjustspacing", "adjustspacingshrink", "adjustspacingstep", "adjustspacingstretch", "afterassigned", "aftergrouped", "aliased", "alignmark", "aligntab", "atendofgroup", "atendofgrouped", "attribute", "attributedef", "automaticdiscretionary", "automatichyphenpenalty", "automigrationmode", "begincsname", "beginlocalcontrol", "boundary", "boxattribute", "boxdirection", "boxorientation", "boxtotal", "boxxmove", "boxxoffset", "boxymove", "boxyoffset", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "csstring", "defcsname", "dimensiondef", "directlua", "edefcsname", "efcode", "endlocalcontrol", "enforced", "etoksapp", "etokspre", "everytab", "exceptionpenalty", "expand", "expandafterpars", "expandafterspaces", "expandcstoken", "expanded", "expandtoken", "explicitdiscretionary", "explicithyphenpenalty", "firstvalidlanguage", "fontid", "fontspecifiedsize", "formatname", "frozen", "futuredef", "futureexpand", "futureexpandis", "futureexpandisap", "gdefcsname", "gleaders", "glet", "gletcsname", "glyphdatafield", "glyphdimensionsmode", "glyphoptions", "glyphscriptfield", "glyphstatefield", "gtoksapp", "gtokspre", "hjcode", "hpack", "hyphenationmin", "hyphenationmode", "ifabsdim", "ifabsnum", "ifarguments", "ifboolean", "ifchkdim", "ifchknum", "ifcmpdim", "ifcmpnum", "ifcondition", "ifcstok", "ifdimval", "ifempty", "ifflags", "ifhastok", "ifhastoks", "ifhasxtoks", "ifincsname", "ifmathparameter", "ifmathstyle", "ifnumval", "ifparameter", "ifparameters", "iftok", "ignorearguments", "ignorepars", "immediate", "immutable", "initcatcodetable", "insertheights", "insertht", "instance", "integerdef", "lastarguments", "lastnamedcs", "lastnodesubtype", "leftmarginkern", "letcharcode", "letcsname", "letfrozen", "letprotected", "linedirection", "linepar", "localbrokenpenalty", "localcontrol", "localcontrolled", "localinterlinepenalty", "localleftbox", "localrightbox", "lpcode", "luabytecode", "luabytecodecall", "luacopyinputnodes", "luadef", "luaescapestring", "luafunction", "luafunctioncall", "luatexbanner", "luatexrevision", "luatexversion", "mathdelimitersmode", "mathdirection", "mathdisplayskipmode", "matheqnogapstep", "mathflattenmode", "mathitalicsmode", "mathnolimitsmode", "matholdmode", "mathpenaltiesmode", "mathrulesfam", "mathrulesmode", "mathrulethicknessmode", "mathscriptboxmode", "mathscriptcharmode", "mathscriptsmode", "mathstyle", "mathsurroundmode", "mathsurroundskip", "mutable", "noaligned", "noboundary", "nohrule", "normalizelinemode", "nospaces", "novrule", "orelse", "orunless", "outputbox", "overloaded", "overloadmode", "parametercount", "parattr", "pardirection", "permanent", "postexhyphenchar", "posthyphenchar", "prebinoppenalty", "predisplaygapfactor", "preexhyphenchar", "prehyphenchar", "prerelpenalty", "protrudechars", "protrusionboundary", "pxdimen", "quitvmode", "rightmarginkern", "rpcode", "savecatcodetable", "scantextokens", "setfontid", "snapshotpar", "supmarkmode", "swapcsvalues", "textdirection", "thewithoutunit", "tokenized", "toksapp", "tokspre", "tolerant", "tpack", "tracingfonts", "tracingmath", "undent", "unletfrozen", "unletprotected", "vpack", "wordboundary", "wrapuppar", "xdefcsname", "xtoksapp", "xtokspre" }, ["omega"]={ "Omegaminorversion", "Omegarevision", "Omegaversion" }, ["pdftex"]={ "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfignoreunknownimages", "pdfimageaddfilename", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinfoomitdate", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmajorversion", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfomitcharset", "pdfomitcidset", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrecompress", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdfsuppressoptionalinfo", "pdfsuppressptexinfo", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage" }, ["tex"]={ " ", "-", "/", "above", "abovedisplayshortskip", "abovedisplayskip", "abovewithdelims", "accent", "adjdemerits", "advance", "afterassignment", "aftergroup", "atop", "atopwithdelims", "badness", "baselineskip", "batchmode", "begingroup", "belowdisplayshortskip", "belowdisplayskip", "binoppenalty", "botmark", "box", "boxmaxdepth", "brokenpenalty", "catcode", "char", "chardef", "cleaders", "clubpenalty", "copy", "count", "countdef", "cr", "crcr", "csname", "day", "deadcycles", "def", "defaulthyphenchar", "defaultskewchar", "delcode", "delimiter", "delimiterfactor", "delimitershortfall", "dimen", "dimendef", "discretionary", "displayindent", "displaylimits", "displaystyle", "displaywidowpenalty", "displaywidth", "divide", "doublehyphendemerits", "dp", "dump", "edef", "else", "emergencystretch", "end", "endcsname", "endgroup", "endinput", "endlinechar", "eqno", "errhelp", "errmessage", "errorcontextlines", "errorstopmode", "escapechar", "everycr", "everydisplay", "everyhbox", "everyjob", "everymath", "everypar", "everyvbox", "exhyphenchar", "exhyphenpenalty", "expandafter", "fam", "fi", "finalhyphendemerits", "firstmark", "floatingpenalty", "font", "fontdimen", "fontname", "fontspecifiedname", "futurelet", "gdef", "global", "globaldefs", "halign", "hangafter", "hangindent", "hbadness", "hbox", "hfil", "hfill", "hfilneg", "hfuzz", "holdinginserts", "hrule", "hsize", "hskip", "hss", "ht", "hyphenation", "hyphenchar", "hyphenpenalty", "if", "ifcase", "ifcat", "ifdim", "iffalse", "ifhbox", "ifhmode", "ifinner", "ifmmode", "ifnum", "ifodd", "iftrue", "ifvbox", "ifvmode", "ifvoid", "ifx", "ignorespaces", "indent", "input", "inputlineno", "insert", "insertpenalties", "interlinepenalty", "jobname", "kern", "language", "lastbox", "lastkern", "lastpenalty", "lastskip", "lccode", "leaders", "left", "lefthyphenmin", "leftskip", "leqno", "let", "limits", "linepenalty", "lineskip", "lineskiplimit", "long", "looseness", "lower", "lowercase", "mark", "mathaccent", "mathbin", "mathchar", "mathchardef", "mathchoice", "mathclose", "mathcode", "mathinner", "mathop", "mathopen", "mathord", "mathpunct", "mathrel", "mathsurround", "maxdeadcycles", "maxdepth", "meaning", "meaningfull", "meaningless", "medmuskip", "message", "middle", "mkern", "month", "moveleft", "moveright", "mskip", "multiply", "muskip", "muskipdef", "newlinechar", "noalign", "noexpand", "noindent", "nolimits", "nonscript", "nonstopmode", "nulldelimiterspace", "nullfont", "number", "omit", "or", "ordlimits", "outer", "output", "outputpenalty", "over", "overfullrule", "overline", "overshoot", "overwithdelims", "pagedepth", "pagefilllstretch", "pagefillstretch", "pagefilstretch", "pagegoal", "pageshrink", "pagestretch", "pagetotal", "par", "parfillleftskip", "parfillskip", "parindent", "parshape", "parskip", "patterns", "pausing", "penalty", "postdisplaypenalty", "predisplaypenalty", "predisplaysize", "pretolerance", "prevdepth", "prevgraf", "radical", "raise", "relax", "relpenalty", "right", "righthyphenmin", "rightskip", "romannumeral", "scriptfont", "scriptscriptfont", "scriptscriptstyle", "scriptspace", "scriptstyle", "scrollmode", "setbox", "setlanguage", "sfcode", "shipout", "show", "showbox", "showboxbreadth", "showboxdepth", "showlists", "shownodedetails", "showthe", "skewchar", "skip", "skipdef", "spacefactor", "spaceskip", "span", "splitbotmark", "splitfirstmark", "splitmaxdepth", "splittopskip", "string", "tabskip", "textfont", "textstyle", "the", "thickmuskip", "thinmuskip", "time", "todimension", "tointeger", "toks", "toksdef", "tolerance", "topmark", "topskip", "toscaled", "tracingcommands", "tracinglostchars", "tracingmacros", "tracingonline", "tracingoutput", "tracingpages", "tracingparagraphs", "tracingrestores", "tracingstats", "uccode", "uchyph", "underline", "unhbox", "unhcopy", "unhpack", "unkern", "unpenalty", "unskip", "unvbox", "unvcopy", "unvpack", "uppercase", "vadjust", "valign", "vbadness", "vbox", "vcenter", "vfil", "vfill", "vfilneg", "vfuzz", "vrule", "vsize", "vskip", "vsplit", "vss", "vtop", "wd", "widowpenalty", "xdef", "xleaders", "xspaceskip", "year" }, diff --git a/context/data/scite/context/scite-context-data-tex.properties b/context/data/scite/context/scite-context-data-tex.properties index e62fca3c6..c81f865d4 100644 --- a/context/data/scite/context/scite-context-data-tex.properties +++ b/context/data/scite/context/scite-context-data-tex.properties @@ -61,35 +61,36 @@ endlocalcontrol enforced etoksapp etokspre everytab \ exceptionpenalty expand expandafterpars expandafterspaces expandcstoken \ expanded expandtoken explicitdiscretionary explicithyphenpenalty firstvalidlanguage \ fontid fontspecifiedsize formatname frozen futuredef \ -futureexpand futureexpandis futureexpandisap gleaders glet \ -glyphdatafield glyphdimensionsmode glyphoptions glyphscriptfield glyphstatefield \ -gtoksapp gtokspre hjcode hpack hyphenationmin \ -hyphenationmode ifabsdim ifabsnum ifarguments ifboolean \ -ifchkdim ifchknum ifcmpdim ifcmpnum ifcondition \ -ifcstok ifdimval ifempty ifflags ifhastok \ -ifhastoks ifhasxtoks ifincsname ifmathparameter ifmathstyle \ -ifnumval ifparameter ifparameters iftok ignorearguments \ -ignorepars immediate immutable initcatcodetable insertheights \ -insertht instance integerdef lastarguments lastnamedcs \ -lastnodesubtype leftmarginkern letcharcode letcsname letfrozen \ -letprotected linedirection linepar localbrokenpenalty localcontrol \ -localcontrolled localinterlinepenalty localleftbox localrightbox lpcode \ -luabytecode luabytecodecall luacopyinputnodes luadef luaescapestring \ -luafunction luafunctioncall luatexbanner luatexrevision luatexversion \ -mathdelimitersmode mathdirection mathdisplayskipmode matheqnogapstep mathflattenmode \ -mathitalicsmode mathnolimitsmode matholdmode mathpenaltiesmode mathrulesfam \ -mathrulesmode mathrulethicknessmode mathscriptboxmode mathscriptcharmode mathscriptsmode \ -mathstyle mathsurroundmode mathsurroundskip mutable noaligned \ -noboundary nohrule normalizelinemode nospaces novrule \ -orelse orunless outputbox overloaded overloadmode \ -parametercount parattr pardirection permanent postexhyphenchar \ -posthyphenchar prebinoppenalty predisplaygapfactor preexhyphenchar prehyphenchar \ -prerelpenalty protrudechars protrusionboundary pxdimen quitvmode \ -rightmarginkern rpcode savecatcodetable scantextokens setfontid \ -snapshotpar supmarkmode swapcsvalues textdirection thewithoutunit \ -tokenized toksapp tokspre tolerant tpack \ -tracingfonts tracingmath unletfrozen unletprotected vpack \ -wordboundary wrapuppar xtoksapp xtokspre +futureexpand futureexpandis futureexpandisap gdefcsname gleaders \ +glet gletcsname glyphdatafield glyphdimensionsmode glyphoptions \ +glyphscriptfield glyphstatefield gtoksapp gtokspre hjcode \ +hpack hyphenationmin hyphenationmode ifabsdim ifabsnum \ +ifarguments ifboolean ifchkdim ifchknum ifcmpdim \ +ifcmpnum ifcondition ifcstok ifdimval ifempty \ +ifflags ifhastok ifhastoks ifhasxtoks ifincsname \ +ifmathparameter ifmathstyle ifnumval ifparameter ifparameters \ +iftok ignorearguments ignorepars immediate immutable \ +initcatcodetable insertheights insertht instance integerdef \ +lastarguments lastnamedcs lastnodesubtype leftmarginkern letcharcode \ +letcsname letfrozen letprotected linedirection linepar \ +localbrokenpenalty localcontrol localcontrolled localinterlinepenalty localleftbox \ +localrightbox lpcode luabytecode luabytecodecall luacopyinputnodes \ +luadef luaescapestring luafunction luafunctioncall luatexbanner \ +luatexrevision luatexversion mathdelimitersmode mathdirection mathdisplayskipmode \ +matheqnogapstep mathflattenmode mathitalicsmode mathnolimitsmode matholdmode \ +mathpenaltiesmode mathrulesfam mathrulesmode mathrulethicknessmode mathscriptboxmode \ +mathscriptcharmode mathscriptsmode mathstyle mathsurroundmode mathsurroundskip \ +mutable noaligned noboundary nohrule normalizelinemode \ +nospaces novrule orelse orunless outputbox \ +overloaded overloadmode parametercount parattr pardirection \ +permanent postexhyphenchar posthyphenchar prebinoppenalty predisplaygapfactor \ +preexhyphenchar prehyphenchar prerelpenalty protrudechars protrusionboundary \ +pxdimen quitvmode rightmarginkern rpcode savecatcodetable \ +scantextokens setfontid snapshotpar supmarkmode swapcsvalues \ +textdirection thewithoutunit tokenized toksapp tokspre \ +tolerant tpack tracingfonts tracingmath undent \ +unletfrozen unletprotected vpack wordboundary wrapuppar \ +xdefcsname xtoksapp xtokspre keywordclass.tex.omega=\ Omegaminorversion Omegarevision Omegaversion diff --git a/context/data/textadept/context/data/scite-context-data-tex.lua b/context/data/textadept/context/data/scite-context-data-tex.lua index 502483461..62f9ef47d 100644 --- a/context/data/textadept/context/data/scite-context-data-tex.lua +++ b/context/data/textadept/context/data/scite-context-data-tex.lua @@ -1,7 +1,7 @@ return { ["aleph"]={ "Alephminorversion", "Alephrevision", "Alephversion" }, ["etex"]={ "botmarks", "clubpenalties", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "detokenize", "dimexpr", "displaywidowpenalties", "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", "savinghyphcodes", "savingvdiscards", "scantokens", "showgroups", "showifs", "showtokens", "splitbotmarks", "splitdiscards", "splitfirstmarks", "topmarks", "tracingalignments", "tracingassigns", "tracinggroups", "tracingifs", "tracingnesting", "unexpanded", "unless", "widowpenalties" }, - ["luatex"]={ "UUskewed", "UUskewedwithdelims", "Uabove", "Uabovewithdelims", "Uatop", "Uatopwithdelims", "Uchar", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Uhextensible", "Uleft", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathcharclass", "Umathchardef", "Umathcharfam", "Umathcharnum", "Umathcharnumdef", "Umathcharslot", "Umathclass", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathnolimitsubfactor", "Umathnolimitsupfactor", "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", "Umathspacebeforescript", "Umathspacingmode", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Umiddle", "Unosubprescript", "Unosubscript", "Unosuperprescript", "Unosuperscript", "Uover", "Uoverdelimiter", "Uoverwithdelims", "Uradical", "Uright", "Uroot", "Uskewed", "Uskewedwithdelims", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Ustyle", "Usubprescript", "Usubscript", "Usuperprescript", "Usuperscript", "Uunderdelimiter", "Uvextensible", "adjustspacing", "adjustspacingshrink", "adjustspacingstep", "adjustspacingstretch", "afterassigned", "aftergrouped", "aliased", "alignmark", "aligntab", "atendofgroup", "atendofgrouped", "attribute", "attributedef", "automaticdiscretionary", "automatichyphenpenalty", "automigrationmode", "begincsname", "beginlocalcontrol", "boundary", "boxattribute", "boxdirection", "boxorientation", "boxtotal", "boxxmove", "boxxoffset", "boxymove", "boxyoffset", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "csstring", "defcsname", "dimensiondef", "directlua", "edefcsname", "efcode", "endlocalcontrol", "enforced", "etoksapp", "etokspre", "everytab", "exceptionpenalty", "expand", "expandafterpars", "expandafterspaces", "expandcstoken", "expanded", "expandtoken", "explicitdiscretionary", "explicithyphenpenalty", "firstvalidlanguage", "fontid", "fontspecifiedsize", "formatname", "frozen", "futuredef", "futureexpand", "futureexpandis", "futureexpandisap", "gleaders", "glet", "glyphdatafield", "glyphdimensionsmode", "glyphoptions", "glyphscriptfield", "glyphstatefield", "gtoksapp", "gtokspre", "hjcode", "hpack", "hyphenationmin", "hyphenationmode", "ifabsdim", "ifabsnum", "ifarguments", "ifboolean", "ifchkdim", "ifchknum", "ifcmpdim", "ifcmpnum", "ifcondition", "ifcstok", "ifdimval", "ifempty", "ifflags", "ifhastok", "ifhastoks", "ifhasxtoks", "ifincsname", "ifmathparameter", "ifmathstyle", "ifnumval", "ifparameter", "ifparameters", "iftok", "ignorearguments", "ignorepars", "immediate", "immutable", "initcatcodetable", "insertheights", "insertht", "instance", "integerdef", "lastarguments", "lastnamedcs", "lastnodesubtype", "leftmarginkern", "letcharcode", "letcsname", "letfrozen", "letprotected", "linedirection", "linepar", "localbrokenpenalty", "localcontrol", "localcontrolled", "localinterlinepenalty", "localleftbox", "localrightbox", "lpcode", "luabytecode", "luabytecodecall", "luacopyinputnodes", "luadef", "luaescapestring", "luafunction", "luafunctioncall", "luatexbanner", "luatexrevision", "luatexversion", "mathdelimitersmode", "mathdirection", "mathdisplayskipmode", "matheqnogapstep", "mathflattenmode", "mathitalicsmode", "mathnolimitsmode", "matholdmode", "mathpenaltiesmode", "mathrulesfam", "mathrulesmode", "mathrulethicknessmode", "mathscriptboxmode", "mathscriptcharmode", "mathscriptsmode", "mathstyle", "mathsurroundmode", "mathsurroundskip", "mutable", "noaligned", "noboundary", "nohrule", "normalizelinemode", "nospaces", "novrule", "orelse", "orunless", "outputbox", "overloaded", "overloadmode", "parametercount", "parattr", "pardirection", "permanent", "postexhyphenchar", "posthyphenchar", "prebinoppenalty", "predisplaygapfactor", "preexhyphenchar", "prehyphenchar", "prerelpenalty", "protrudechars", "protrusionboundary", "pxdimen", "quitvmode", "rightmarginkern", "rpcode", "savecatcodetable", "scantextokens", "setfontid", "snapshotpar", "supmarkmode", "swapcsvalues", "textdirection", "thewithoutunit", "tokenized", "toksapp", "tokspre", "tolerant", "tpack", "tracingfonts", "tracingmath", "unletfrozen", "unletprotected", "vpack", "wordboundary", "wrapuppar", "xtoksapp", "xtokspre" }, + ["luatex"]={ "UUskewed", "UUskewedwithdelims", "Uabove", "Uabovewithdelims", "Uatop", "Uatopwithdelims", "Uchar", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Uhextensible", "Uleft", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathcharclass", "Umathchardef", "Umathcharfam", "Umathcharnum", "Umathcharnumdef", "Umathcharslot", "Umathclass", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathnolimitsubfactor", "Umathnolimitsupfactor", "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", "Umathspacebeforescript", "Umathspacingmode", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Umiddle", "Unosubprescript", "Unosubscript", "Unosuperprescript", "Unosuperscript", "Uover", "Uoverdelimiter", "Uoverwithdelims", "Uradical", "Uright", "Uroot", "Uskewed", "Uskewedwithdelims", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Ustyle", "Usubprescript", "Usubscript", "Usuperprescript", "Usuperscript", "Uunderdelimiter", "Uvextensible", "adjustspacing", "adjustspacingshrink", "adjustspacingstep", "adjustspacingstretch", "afterassigned", "aftergrouped", "aliased", "alignmark", "aligntab", "atendofgroup", "atendofgrouped", "attribute", "attributedef", "automaticdiscretionary", "automatichyphenpenalty", "automigrationmode", "begincsname", "beginlocalcontrol", "boundary", "boxattribute", "boxdirection", "boxorientation", "boxtotal", "boxxmove", "boxxoffset", "boxymove", "boxyoffset", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "csstring", "defcsname", "dimensiondef", "directlua", "edefcsname", "efcode", "endlocalcontrol", "enforced", "etoksapp", "etokspre", "everytab", "exceptionpenalty", "expand", "expandafterpars", "expandafterspaces", "expandcstoken", "expanded", "expandtoken", "explicitdiscretionary", "explicithyphenpenalty", "firstvalidlanguage", "fontid", "fontspecifiedsize", "formatname", "frozen", "futuredef", "futureexpand", "futureexpandis", "futureexpandisap", "gdefcsname", "gleaders", "glet", "gletcsname", "glyphdatafield", "glyphdimensionsmode", "glyphoptions", "glyphscriptfield", "glyphstatefield", "gtoksapp", "gtokspre", "hjcode", "hpack", "hyphenationmin", "hyphenationmode", "ifabsdim", "ifabsnum", "ifarguments", "ifboolean", "ifchkdim", "ifchknum", "ifcmpdim", "ifcmpnum", "ifcondition", "ifcstok", "ifdimval", "ifempty", "ifflags", "ifhastok", "ifhastoks", "ifhasxtoks", "ifincsname", "ifmathparameter", "ifmathstyle", "ifnumval", "ifparameter", "ifparameters", "iftok", "ignorearguments", "ignorepars", "immediate", "immutable", "initcatcodetable", "insertheights", "insertht", "instance", "integerdef", "lastarguments", "lastnamedcs", "lastnodesubtype", "leftmarginkern", "letcharcode", "letcsname", "letfrozen", "letprotected", "linedirection", "linepar", "localbrokenpenalty", "localcontrol", "localcontrolled", "localinterlinepenalty", "localleftbox", "localrightbox", "lpcode", "luabytecode", "luabytecodecall", "luacopyinputnodes", "luadef", "luaescapestring", "luafunction", "luafunctioncall", "luatexbanner", "luatexrevision", "luatexversion", "mathdelimitersmode", "mathdirection", "mathdisplayskipmode", "matheqnogapstep", "mathflattenmode", "mathitalicsmode", "mathnolimitsmode", "matholdmode", "mathpenaltiesmode", "mathrulesfam", "mathrulesmode", "mathrulethicknessmode", "mathscriptboxmode", "mathscriptcharmode", "mathscriptsmode", "mathstyle", "mathsurroundmode", "mathsurroundskip", "mutable", "noaligned", "noboundary", "nohrule", "normalizelinemode", "nospaces", "novrule", "orelse", "orunless", "outputbox", "overloaded", "overloadmode", "parametercount", "parattr", "pardirection", "permanent", "postexhyphenchar", "posthyphenchar", "prebinoppenalty", "predisplaygapfactor", "preexhyphenchar", "prehyphenchar", "prerelpenalty", "protrudechars", "protrusionboundary", "pxdimen", "quitvmode", "rightmarginkern", "rpcode", "savecatcodetable", "scantextokens", "setfontid", "snapshotpar", "supmarkmode", "swapcsvalues", "textdirection", "thewithoutunit", "tokenized", "toksapp", "tokspre", "tolerant", "tpack", "tracingfonts", "tracingmath", "undent", "unletfrozen", "unletprotected", "vpack", "wordboundary", "wrapuppar", "xdefcsname", "xtoksapp", "xtokspre" }, ["omega"]={ "Omegaminorversion", "Omegarevision", "Omegaversion" }, ["pdftex"]={ "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfignoreunknownimages", "pdfimageaddfilename", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinfoomitdate", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmajorversion", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfomitcharset", "pdfomitcidset", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrecompress", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdfsuppressoptionalinfo", "pdfsuppressptexinfo", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage" }, ["tex"]={ " ", "-", "/", "above", "abovedisplayshortskip", "abovedisplayskip", "abovewithdelims", "accent", "adjdemerits", "advance", "afterassignment", "aftergroup", "atop", "atopwithdelims", "badness", "baselineskip", "batchmode", "begingroup", "belowdisplayshortskip", "belowdisplayskip", "binoppenalty", "botmark", "box", "boxmaxdepth", "brokenpenalty", "catcode", "char", "chardef", "cleaders", "clubpenalty", "copy", "count", "countdef", "cr", "crcr", "csname", "day", "deadcycles", "def", "defaulthyphenchar", "defaultskewchar", "delcode", "delimiter", "delimiterfactor", "delimitershortfall", "dimen", "dimendef", "discretionary", "displayindent", "displaylimits", "displaystyle", "displaywidowpenalty", "displaywidth", "divide", "doublehyphendemerits", "dp", "dump", "edef", "else", "emergencystretch", "end", "endcsname", "endgroup", "endinput", "endlinechar", "eqno", "errhelp", "errmessage", "errorcontextlines", "errorstopmode", "escapechar", "everycr", "everydisplay", "everyhbox", "everyjob", "everymath", "everypar", "everyvbox", "exhyphenchar", "exhyphenpenalty", "expandafter", "fam", "fi", "finalhyphendemerits", "firstmark", "floatingpenalty", "font", "fontdimen", "fontname", "fontspecifiedname", "futurelet", "gdef", "global", "globaldefs", "halign", "hangafter", "hangindent", "hbadness", "hbox", "hfil", "hfill", "hfilneg", "hfuzz", "holdinginserts", "hrule", "hsize", "hskip", "hss", "ht", "hyphenation", "hyphenchar", "hyphenpenalty", "if", "ifcase", "ifcat", "ifdim", "iffalse", "ifhbox", "ifhmode", "ifinner", "ifmmode", "ifnum", "ifodd", "iftrue", "ifvbox", "ifvmode", "ifvoid", "ifx", "ignorespaces", "indent", "input", "inputlineno", "insert", "insertpenalties", "interlinepenalty", "jobname", "kern", "language", "lastbox", "lastkern", "lastpenalty", "lastskip", "lccode", "leaders", "left", "lefthyphenmin", "leftskip", "leqno", "let", "limits", "linepenalty", "lineskip", "lineskiplimit", "long", "looseness", "lower", "lowercase", "mark", "mathaccent", "mathbin", "mathchar", "mathchardef", "mathchoice", "mathclose", "mathcode", "mathinner", "mathop", "mathopen", "mathord", "mathpunct", "mathrel", "mathsurround", "maxdeadcycles", "maxdepth", "meaning", "meaningfull", "meaningless", "medmuskip", "message", "middle", "mkern", "month", "moveleft", "moveright", "mskip", "multiply", "muskip", "muskipdef", "newlinechar", "noalign", "noexpand", "noindent", "nolimits", "nonscript", "nonstopmode", "nulldelimiterspace", "nullfont", "number", "omit", "or", "ordlimits", "outer", "output", "outputpenalty", "over", "overfullrule", "overline", "overshoot", "overwithdelims", "pagedepth", "pagefilllstretch", "pagefillstretch", "pagefilstretch", "pagegoal", "pageshrink", "pagestretch", "pagetotal", "par", "parfillleftskip", "parfillskip", "parindent", "parshape", "parskip", "patterns", "pausing", "penalty", "postdisplaypenalty", "predisplaypenalty", "predisplaysize", "pretolerance", "prevdepth", "prevgraf", "radical", "raise", "relax", "relpenalty", "right", "righthyphenmin", "rightskip", "romannumeral", "scriptfont", "scriptscriptfont", "scriptscriptstyle", "scriptspace", "scriptstyle", "scrollmode", "setbox", "setlanguage", "sfcode", "shipout", "show", "showbox", "showboxbreadth", "showboxdepth", "showlists", "shownodedetails", "showthe", "skewchar", "skip", "skipdef", "spacefactor", "spaceskip", "span", "splitbotmark", "splitfirstmark", "splitmaxdepth", "splittopskip", "string", "tabskip", "textfont", "textstyle", "the", "thickmuskip", "thinmuskip", "time", "todimension", "tointeger", "toks", "toksdef", "tolerance", "topmark", "topskip", "toscaled", "tracingcommands", "tracinglostchars", "tracingmacros", "tracingonline", "tracingoutput", "tracingpages", "tracingparagraphs", "tracingrestores", "tracingstats", "uccode", "uchyph", "underline", "unhbox", "unhcopy", "unhpack", "unkern", "unpenalty", "unskip", "unvbox", "unvcopy", "unvpack", "uppercase", "vadjust", "valign", "vbadness", "vbox", "vcenter", "vfil", "vfill", "vfilneg", "vfuzz", "vrule", "vsize", "vskip", "vsplit", "vss", "vtop", "wd", "widowpenalty", "xdef", "xleaders", "xspaceskip", "year" }, diff --git a/context/data/vscode/extensions/context/syntaxes/context-syntax-tex.json b/context/data/vscode/extensions/context/syntaxes/context-syntax-tex.json index ac6e6b3c7..bab8b8853 100644 --- a/context/data/vscode/extensions/context/syntaxes/context-syntax-tex.json +++ b/context/data/vscode/extensions/context/syntaxes/context-syntax-tex.json @@ -215,7 +215,7 @@ ] }, "primitive" : { - "match" : "\u005C\u005C(year|xtokspre|xtoksapp|xspaceskip|xleaders|xdef|wrapuppar|wordboundary|widowpenalty|widowpenalties|wd|vtop|vss|vsplit|vskip|vsize|vrule|vpack|vfuzz|vfilneg|vfill|vfil|vcenter|vbox|vbadness|valign|vadjust|uppercase|unvpack|unvcopy|unvbox|unskip|unpenalty|unletprotected|unletfrozen|unless|unkern|unhpack|unhcopy|unhbox|underline|uchyph|uccode|tracingstats|tracingrestores|tracingparagraphs|tracingpages|tracingoutput|tracingonline|tracingnesting|tracingmath|tracingmacros|tracinglostchars|tracingifs|tracinggroups|tracingfonts|tracingcommands|tracingassigns|tracingalignments|tpack|toscaled|topskip|topmarks|topmark|tolerant|tolerance|tokspre|toksdef|toksapp|toks|tokenized|tointeger|todimension|time|thinmuskip|thickmuskip|thewithoutunit|the|textstyle|textfont|textdirection|tabskip|swapcsvalues|supmarkmode|string|splittopskip|splitmaxdepth|splitfirstmarks|splitfirstmark|splitdiscards|splitbotmarks|splitbotmark|span|spaceskip|spacefactor|snapshotpar|skipdef|skip|skewchar|showtokens|showthe|shownodedetails|showlists|showifs|showgroups|showboxdepth|showboxbreadth|showbox|show|shipout|sfcode|setlanguage|setfontid|setbox|scrollmode|scriptstyle|scriptspace|scriptscriptstyle|scriptscriptfont|scriptfont|scantokens|scantextokens|savingvdiscards|savinghyphcodes|savecatcodetable|rpcode|romannumeral|rightskip|rightmarginkern|righthyphenmin|right|relpenalty|relax|raise|radical|quitvmode|pxdimen|protrusionboundary|protrudechars|protected|prevgraf|prevdepth|pretolerance|prerelpenalty|prehyphenchar|preexhyphenchar|predisplaysize|predisplaypenalty|predisplaygapfactor|predisplaydirection|prebinoppenalty|posthyphenchar|postexhyphenchar|postdisplaypenalty|permanent|penalty|pdfximage|pdfxformresources|pdfxformname|pdfxformmargin|pdfxformattr|pdfxform|pdfvorigin|pdfuniqueresname|pdfuniformdeviate|pdftrailerid|pdftrailer|pdftracingfonts|pdfthreadmargin|pdfthread|pdftexversion|pdftexrevision|pdftexbanner|pdfsuppressptexinfo|pdfsuppressoptionalinfo|pdfstartthread|pdfstartlink|pdfsetrandomseed|pdfsetmatrix|pdfsavepos|pdfsave|pdfretval|pdfrestore|pdfreplacefont|pdfrefximage|pdfrefxform|pdfrefobj|pdfrecompress|pdfrandomseed|pdfpxdimen|pdfprotrudechars|pdfprimitive|pdfpkresolution|pdfpkmode|pdfpkfixeddpi|pdfpagewidth|pdfpagesattr|pdfpageresources|pdfpageref|pdfpageheight|pdfpagebox|pdfpageattr|pdfoutput|pdfoutline|pdfomitcidset|pdfomitcharset|pdfobjcompresslevel|pdfobj|pdfnormaldeviate|pdfnoligatures|pdfnames|pdfminorversion|pdfmapline|pdfmapfile|pdfmajorversion|pdfliteral|pdflinkmargin|pdflastypos|pdflastxpos|pdflastximagepages|pdflastximage|pdflastxform|pdflastobj|pdflastlink|pdflastlinedepth|pdflastannot|pdfinsertht|pdfinfoomitdate|pdfinfo|pdfinclusionerrorlevel|pdfinclusioncopyfonts|pdfincludechars|pdfimageresolution|pdfimagehicolor|pdfimagegamma|pdfimageapplygamma|pdfimageaddfilename|pdfignoreunknownimages|pdfignoreddimen|pdfhorigin|pdfglyphtounicode|pdfgentounicode|pdfgamma|pdffontsize|pdffontobjnum|pdffontname|pdffontexpand|pdffontattr|pdffirstlineheight|pdfendthread|pdfendlink|pdfeachlineheight|pdfeachlinedepth|pdfdraftmode|pdfdestmargin|pdfdest|pdfdecimaldigits|pdfcreationdate|pdfcopyfont|pdfcompresslevel|pdfcolorstackinit|pdfcolorstack|pdfcatalog|pdfannot|pdfadjustspacing|pausing|patterns|parskip|parshapelength|parshapeindent|parshapedimen|parshape|parindent|parfillskip|pardirection|parattr|parametercount|par|pagetotal|pagestretch|pageshrink|pagegoal|pagefilstretch|pagefillstretch|pagefilllstretch|pagediscards|pagedepth|overwithdelims|overshoot|overloadmode|overloaded|overline|overfullrule|over|outputpenalty|outputbox|output|outer|orunless|orelse|ordlimits|or|omit|numexpr|number|nullfont|nulldelimiterspace|novrule|nospaces|normalyear|normalxtokspre|normalxtoksapp|normalxspaceskip|normalxleaders|normalxdef|normalwrapuppar|normalwordboundary|normalwidowpenalty|normalwidowpenalties|normalwd|normalvtop|normalvss|normalvsplit|normalvskip|normalvsize|normalvrule|normalvpack|normalvfuzz|normalvfilneg|normalvfill|normalvfil|normalvcenter|normalvbox|normalvbadness|normalvalign|normalvadjust|normaluppercase|normalunvpack|normalunvcopy|normalunvbox|normalunskip|normalunpenalty|normalunletprotected|normalunletfrozen|normalunless|normalunkern|normalunhpack|normalunhcopy|normalunhbox|normalunexpanded|normalunderline|normaluchyph|normaluccode|normaltracingstats|normaltracingrestores|normaltracingparagraphs|normaltracingpages|normaltracingoutput|normaltracingonline|normaltracingnesting|normaltracingmath|normaltracingmacros|normaltracinglostchars|normaltracingifs|normaltracinggroups|normaltracingfonts|normaltracingcommands|normaltracingassigns|normaltracingalignments|normaltpack|normaltoscaled|normaltopskip|normaltopmarks|normaltopmark|normaltolerant|normaltolerance|normaltokspre|normaltoksdef|normaltoksapp|normaltoks|normaltokenized|normaltointeger|normaltodimension|normaltime|normalthinmuskip|normalthickmuskip|normalthewithoutunit|normalthe|normaltextstyle|normaltextfont|normaltextdirection|normaltabskip|normalswapcsvalues|normalsupmarkmode|normalstring|normalsplittopskip|normalsplitmaxdepth|normalsplitfirstmarks|normalsplitfirstmark|normalsplitdiscards|normalsplitbotmarks|normalsplitbotmark|normalspan|normalspaceskip|normalspacefactor|normalsnapshotpar|normalskipdef|normalskip|normalskewchar|normalshowtokens|normalshowthe|normalshownodedetails|normalshowlists|normalshowifs|normalshowgroups|normalshowboxdepth|normalshowboxbreadth|normalshowbox|normalshow|normalshipout|normalsfcode|normalsetlanguage|normalsetfontid|normalsetbox|normalscrollmode|normalscriptstyle|normalscriptspace|normalscriptscriptstyle|normalscriptscriptfont|normalscriptfont|normalscantokens|normalscantextokens|normalsavingvdiscards|normalsavinghyphcodes|normalsavecatcodetable|normalrpcode|normalromannumeral|normalrightskip|normalrightmarginkern|normalrighthyphenmin|normalright|normalrelpenalty|normalrelax|normalraise|normalradical|normalquitvmode|normalpxdimen|normalprotrusionboundary|normalprotrudechars|normalprotected|normalprevgraf|normalprevdepth|normalpretolerance|normalprerelpenalty|normalprehyphenchar|normalpreexhyphenchar|normalpredisplaysize|normalpredisplaypenalty|normalpredisplaygapfactor|normalpredisplaydirection|normalprebinoppenalty|normalposthyphenchar|normalpostexhyphenchar|normalpostdisplaypenalty|normalpermanent|normalpenalty|normalpdfximage|normalpdfxformresources|normalpdfxformname|normalpdfxformmargin|normalpdfxformattr|normalpdfxform|normalpdfvorigin|normalpdfuniqueresname|normalpdfuniformdeviate|normalpdftrailerid|normalpdftrailer|normalpdftracingfonts|normalpdfthreadmargin|normalpdfthread|normalpdftexversion|normalpdftexrevision|normalpdftexbanner|normalpdfsuppressptexinfo|normalpdfsuppressoptionalinfo|normalpdfstartthread|normalpdfstartlink|normalpdfsetrandomseed|normalpdfsetmatrix|normalpdfsavepos|normalpdfsave|normalpdfretval|normalpdfrestore|normalpdfreplacefont|normalpdfrefximage|normalpdfrefxform|normalpdfrefobj|normalpdfrecompress|normalpdfrandomseed|normalpdfpxdimen|normalpdfprotrudechars|normalpdfprimitive|normalpdfpkresolution|normalpdfpkmode|normalpdfpkfixeddpi|normalpdfpagewidth|normalpdfpagesattr|normalpdfpageresources|normalpdfpageref|normalpdfpageheight|normalpdfpagebox|normalpdfpageattr|normalpdfoutput|normalpdfoutline|normalpdfomitcidset|normalpdfomitcharset|normalpdfobjcompresslevel|normalpdfobj|normalpdfnormaldeviate|normalpdfnoligatures|normalpdfnames|normalpdfminorversion|normalpdfmapline|normalpdfmapfile|normalpdfmajorversion|normalpdfliteral|normalpdflinkmargin|normalpdflastypos|normalpdflastxpos|normalpdflastximagepages|normalpdflastximage|normalpdflastxform|normalpdflastobj|normalpdflastlink|normalpdflastlinedepth|normalpdflastannot|normalpdfinsertht|normalpdfinfoomitdate|normalpdfinfo|normalpdfinclusionerrorlevel|normalpdfinclusioncopyfonts|normalpdfincludechars|normalpdfimageresolution|normalpdfimagehicolor|normalpdfimagegamma|normalpdfimageapplygamma|normalpdfimageaddfilename|normalpdfignoreunknownimages|normalpdfignoreddimen|normalpdfhorigin|normalpdfglyphtounicode|normalpdfgentounicode|normalpdfgamma|normalpdffontsize|normalpdffontobjnum|normalpdffontname|normalpdffontexpand|normalpdffontattr|normalpdffirstlineheight|normalpdfendthread|normalpdfendlink|normalpdfeachlineheight|normalpdfeachlinedepth|normalpdfdraftmode|normalpdfdestmargin|normalpdfdest|normalpdfdecimaldigits|normalpdfcreationdate|normalpdfcopyfont|normalpdfcompresslevel|normalpdfcolorstackinit|normalpdfcolorstack|normalpdfcatalog|normalpdfannot|normalpdfadjustspacing|normalpausing|normalpatterns|normalparskip|normalparshapelength|normalparshapeindent|normalparshapedimen|normalparshape|normalparindent|normalparfillskip|normalparfillleftskip|normalpardirection|normalparattr|normalparametercount|normalpar|normalpagetotal|normalpagestretch|normalpageshrink|normalpagegoal|normalpagefilstretch|normalpagefillstretch|normalpagefilllstretch|normalpagediscards|normalpagedepth|normaloverwithdelims|normalovershoot|normaloverloadmode|normaloverloaded|normaloverline|normaloverfullrule|normalover|normaloutputpenalty|normaloutputbox|normaloutput|normalouter|normalorunless|normalorelse|normalordlimits|normalor|normalomit|normalnumexpr|normalnumber|normalnullfont|normalnulldelimiterspace|normalnovrule|normalnospaces|normalnormalizelinemode|normalnonstopmode|normalnonscript|normalnolimits|normalnoindent|normalnohrule|normalnoexpand|normalnoboundary|normalnoaligned|normalnoalign|normalnewlinechar|normalmutoglue|normalmutable|normalmuskipdef|normalmuskip|normalmultiply|normalmuexpr|normalmskip|normalmoveright|normalmoveleft|normalmonth|normalmkern|normalmiddle|normalmessage|normalmedmuskip|normalmeaningless|normalmeaningfull|normalmeaning|normalmaxdepth|normalmaxdeadcycles|normalmathsurroundskip|normalmathsurroundmode|normalmathsurround|normalmathstyle|normalmathscriptsmode|normalmathscriptcharmode|normalmathscriptboxmode|normalmathrulethicknessmode|normalmathrulesmode|normalmathrulesfam|normalmathrel|normalmathpunct|normalmathpenaltiesmode|normalmathord|normalmathopen|normalmathop|normalmatholdmode|normalmathnolimitsmode|normalmathitalicsmode|normalmathinner|normalmathflattenmode|normalmatheqnogapstep|normalmathdisplayskipmode|normalmathdirection|normalmathdelimitersmode|normalmathcode|normalmathclose|normalmathchoice|normalmathchardef|normalmathchar|normalmathbin|normalmathaccent|normalmarks|normalmark|normalluatexversion|normalluatexrevision|normalluatexbanner|normalluafunctioncall|normalluafunction|normalluaescapestring|normalluadef|normalluacopyinputnodes|normalluabytecodecall|normalluabytecode|normallpcode|normallowercase|normallower|normallooseness|normallong|normallocalrightbox|normallocalleftbox|normallocalinterlinepenalty|normallocalcontrolled|normallocalcontrol|normallocalbrokenpenalty|normallineskiplimit|normallineskip|normallinepenalty|normallinepar|normallinedirection|normallimits|normalletprotected|normalletfrozen|normalletcsname|normalletcharcode|normallet|normalleqno|normalleftskip|normalleftmarginkern|normallefthyphenmin|normalleft|normalleaders|normallccode|normallastskip|normallastpenalty|normallastnodetype|normallastnodesubtype|normallastnamedcs|normallastlinefit|normallastkern|normallastbox|normallastarguments|normallanguage|normalkern|normaljobname|normalizelinemode|normalinterlinepenalty|normalinterlinepenalties|normalinteractionmode|normalintegerdef|normalinstance|normalinsertpenalties|normalinsertht|normalinsertheights|normalinsert|normalinputlineno|normalinput|normalinitcatcodetable|normalindent|normalimmutable|normalimmediate|normalignorespaces|normalignorepars|normalignorearguments|normalifx|normalifvoid|normalifvmode|normalifvbox|normaliftrue|normaliftok|normalifpdfprimitive|normalifpdfabsnum|normalifpdfabsdim|normalifparameters|normalifparameter|normalifodd|normalifnumval|normalifnum|normalifmmode|normalifmathstyle|normalifmathparameter|normalifinner|normalifincsname|normalifhmode|normalifhbox|normalifhasxtoks|normalifhastoks|normalifhastok|normaliffontchar|normalifflags|normaliffalse|normalifempty|normalifdimval|normalifdim|normalifdefined|normalifcstok|normalifcsname|normalifcondition|normalifcmpnum|normalifcmpdim|normalifchknum|normalifchkdim|normalifcat|normalifcase|normalifboolean|normalifarguments|normalifabsnum|normalifabsdim|normalif|normalhyphenpenalty|normalhyphenchar|normalhyphenationmode|normalhyphenationmin|normalhyphenation|normalht|normalhss|normalhskip|normalhsize|normalhrule|normalhpack|normalholdinginserts|normalhjcode|normalhfuzz|normalhfilneg|normalhfill|normalhfil|normalhbox|normalhbadness|normalhangindent|normalhangafter|normalhalign|normalgtokspre|normalgtoksapp|normalglyphstatefield|normalglyphscriptfield|normalglyphoptions|normalglyphdimensionsmode|normalglyphdatafield|normalgluetomu|normalgluestretchorder|normalgluestretch|normalglueshrinkorder|normalglueshrink|normalglueexpr|normalglobaldefs|normalglobal|normalglet|normalgleaders|normalgdef|normalfuturelet|normalfutureexpandisap|normalfutureexpandis|normalfutureexpand|normalfuturedef|normalfrozen|normalformatname|normalfontspecifiedsize|normalfontspecifiedname|normalfontname|normalfontid|normalfontdimen|normalfontcharwd|normalfontcharic|normalfontcharht|normalfontchardp|normalfont|normalfloatingpenalty|normalfirstvalidlanguage|normalfirstmarks|normalfirstmark|normalfinalhyphendemerits|normalfi|normalfam|normalexplicithyphenpenalty|normalexplicitdiscretionary|normalexpandtoken|normalexpanded|normalexpandcstoken|normalexpandafterspaces|normalexpandafterpars|normalexpandafter|normalexpand|normalexhyphenpenalty|normalexhyphenchar|normalexceptionpenalty|normaleveryvbox|normaleverytab|normaleverypar|normaleverymath|normaleveryjob|normaleveryhbox|normaleveryeof|normaleverydisplay|normaleverycr|normaletokspre|normaletoksapp|normalescapechar|normalerrorstopmode|normalerrorcontextlines|normalerrmessage|normalerrhelp|normaleqno|normalenforced|normalendlocalcontrol|normalendlinechar|normalendinput|normalendgroup|normalendcsname|normalend|normalemergencystretch|normalelse|normalefcode|normaledefcsname|normaledef|normaldump|normaldp|normaldoublehyphendemerits|normaldivide|normaldisplaywidth|normaldisplaywidowpenalty|normaldisplaywidowpenalties|normaldisplaystyle|normaldisplaylimits|normaldisplayindent|normaldiscretionary|normaldirectlua|normaldimexpr|normaldimensiondef|normaldimendef|normaldimen|normaldetokenize|normaldelimitershortfall|normaldelimiterfactor|normaldelimiter|normaldelcode|normaldefcsname|normaldefaultskewchar|normaldefaulthyphenchar|normaldef|normaldeadcycles|normalday|normalcurrentiftype|normalcurrentiflevel|normalcurrentifbranch|normalcurrentgrouptype|normalcurrentgrouplevel|normalcsstring|normalcsname|normalcrcr|normalcrampedtextstyle|normalcrampedscriptstyle|normalcrampedscriptscriptstyle|normalcrampeddisplaystyle|normalcr|normalcountdef|normalcount|normalcopy|normalclubpenalty|normalclubpenalties|normalclearmarks|normalcleaders|normalchardef|normalchar|normalcatcodetable|normalcatcode|normalbrokenpenalty|normalboxyoffset|normalboxymove|normalboxxoffset|normalboxxmove|normalboxtotal|normalboxorientation|normalboxmaxdepth|normalboxdirection|normalboxattribute|normalbox|normalboundary|normalbotmarks|normalbotmark|normalbinoppenalty|normalbelowdisplayskip|normalbelowdisplayshortskip|normalbeginlocalcontrol|normalbegingroup|normalbegincsname|normalbatchmode|normalbaselineskip|normalbadness|normalautomigrationmode|normalautomatichyphenpenalty|normalautomaticdiscretionary|normalattributedef|normalattribute|normalatopwithdelims|normalatop|normalatendofgrouped|normalatendofgroup|normalaligntab|normalalignmark|normalaliased|normalaftergrouped|normalaftergroup|normalafterassignment|normalafterassigned|normaladvance|normaladjustspacingstretch|normaladjustspacingstep|normaladjustspacingshrink|normaladjustspacing|normaladjdemerits|normalaccent|normalabovewithdelims|normalabovedisplayskip|normalabovedisplayshortskip|normalabove|normalXeTeXversion|normalUvextensible|normalUunderdelimiter|normalUsuperscript|normalUsuperprescript|normalUsubscript|normalUsubprescript|normalUstyle|normalUstopmath|normalUstopdisplaymath|normalUstartmath|normalUstartdisplaymath|normalUstack|normalUskewedwithdelims|normalUskewed|normalUroot|normalUright|normalUradical|normalUoverwithdelims|normalUoverdelimiter|normalUover|normalUnosuperscript|normalUnosuperprescript|normalUnosubscript|normalUnosubprescript|normalUmiddle|normalUmathunderdelimitervgap|normalUmathunderdelimiterbgap|normalUmathunderbarvgap|normalUmathunderbarrule|normalUmathunderbarkern|normalUmathsupsubbottommax|normalUmathsupshiftup|normalUmathsupshiftdrop|normalUmathsupbottommin|normalUmathsubtopmax|normalUmathsubsupvgap|normalUmathsubsupshiftdown|normalUmathsubshiftdrop|normalUmathsubshiftdown|normalUmathstackvgap|normalUmathstacknumup|normalUmathstackdenomdown|normalUmathspacingmode|normalUmathspacebeforescript|normalUmathspaceafterscript|normalUmathskewedfractionvgap|normalUmathskewedfractionhgap|normalUmathrelrelspacing|normalUmathrelpunctspacing|normalUmathrelordspacing|normalUmathrelopspacing|normalUmathrelopenspacing|normalUmathrelinnerspacing|normalUmathrelclosespacing|normalUmathrelbinspacing|normalUmathradicalvgap|normalUmathradicalrule|normalUmathradicalkern|normalUmathradicaldegreeraise|normalUmathradicaldegreebefore|normalUmathradicaldegreeafter|normalUmathquad|normalUmathpunctrelspacing|normalUmathpunctpunctspacing|normalUmathpunctordspacing|normalUmathpunctopspacing|normalUmathpunctopenspacing|normalUmathpunctinnerspacing|normalUmathpunctclosespacing|normalUmathpunctbinspacing|normalUmathoverdelimitervgap|normalUmathoverdelimiterbgap|normalUmathoverbarvgap|normalUmathoverbarrule|normalUmathoverbarkern|normalUmathordrelspacing|normalUmathordpunctspacing|normalUmathordordspacing|normalUmathordopspacing|normalUmathordopenspacing|normalUmathordinnerspacing|normalUmathordclosespacing|normalUmathordbinspacing|normalUmathoprelspacing|normalUmathoppunctspacing|normalUmathopordspacing|normalUmathopopspacing|normalUmathopopenspacing|normalUmathopinnerspacing|normalUmathoperatorsize|normalUmathopenrelspacing|normalUmathopenpunctspacing|normalUmathopenordspacing|normalUmathopenopspacing|normalUmathopenopenspacing|normalUmathopeninnerspacing|normalUmathopenclosespacing|normalUmathopenbinspacing|normalUmathopclosespacing|normalUmathopbinspacing|normalUmathnolimitsupfactor|normalUmathnolimitsubfactor|normalUmathlimitbelowvgap|normalUmathlimitbelowkern|normalUmathlimitbelowbgap|normalUmathlimitabovevgap|normalUmathlimitabovekern|normalUmathlimitabovebgap|normalUmathinnerrelspacing|normalUmathinnerpunctspacing|normalUmathinnerordspacing|normalUmathinneropspacing|normalUmathinneropenspacing|normalUmathinnerinnerspacing|normalUmathinnerclosespacing|normalUmathinnerbinspacing|normalUmathfractionrule|normalUmathfractionnumvgap|normalUmathfractionnumup|normalUmathfractiondenomvgap|normalUmathfractiondenomdown|normalUmathfractiondelsize|normalUmathconnectoroverlapmin|normalUmathcodenum|normalUmathcode|normalUmathcloserelspacing|normalUmathclosepunctspacing|normalUmathcloseordspacing|normalUmathcloseopspacing|normalUmathcloseopenspacing|normalUmathcloseinnerspacing|normalUmathcloseclosespacing|normalUmathclosebinspacing|normalUmathclass|normalUmathcharslot|normalUmathcharnumdef|normalUmathcharnum|normalUmathcharfam|normalUmathchardef|normalUmathcharclass|normalUmathchar|normalUmathbinrelspacing|normalUmathbinpunctspacing|normalUmathbinordspacing|normalUmathbinopspacing|normalUmathbinopenspacing|normalUmathbininnerspacing|normalUmathbinclosespacing|normalUmathbinbinspacing|normalUmathaxis|normalUmathaccent|normalUleft|normalUhextensible|normalUdelimiterunder|normalUdelimiterover|normalUdelimiter|normalUdelcodenum|normalUdelcode|normalUchar|normalUatopwithdelims|normalUatop|normalUabovewithdelims|normalUabove|normalUUskewedwithdelims|normalUUskewed|normalOmegaversion|normalOmegarevision|normalOmegaminorversion|normalAlephversion|normalAlephrevision|normalAlephminorversion|normal |nonstopmode|nonscript|nolimits|noindent|nohrule|noexpand|noboundary|noaligned|noalign|newlinechar|mutoglue|mutable|muskipdef|muskip|multiply|muexpr|mskip|moveright|moveleft|month|mkern|middle|message|medmuskip|meaningless|meaningfull|meaning|maxdepth|maxdeadcycles|mathsurroundskip|mathsurroundmode|mathsurround|mathstyle|mathscriptsmode|mathscriptcharmode|mathscriptboxmode|mathrulethicknessmode|mathrulesmode|mathrulesfam|mathrel|mathpunct|mathpenaltiesmode|mathord|mathopen|mathop|matholdmode|mathnolimitsmode|mathitalicsmode|mathinner|mathflattenmode|matheqnogapstep|mathdisplayskipmode|mathdirection|mathdelimitersmode|mathcode|mathclose|mathchoice|mathchardef|mathchar|mathbin|mathaccent|marks|mark|luatexversion|luatexrevision|luatexbanner|luafunctioncall|luafunction|luaescapestring|luadef|luacopyinputnodes|luabytecodecall|luabytecode|lpcode|lowercase|lower|looseness|long|localrightbox|localleftbox|localinterlinepenalty|localcontrolled|localcontrol|localbrokenpenalty|lineskiplimit|lineskip|linepenalty|linepar|linedirection|limits|letprotected|letfrozen|letcsname|letcharcode|let|leqno|leftskip|leftmarginkern|lefthyphenmin|left|leaders|lccode|lastskip|lastpenalty|lastnodetype|lastnodesubtype|lastnamedcs|lastlinefit|lastkern|lastbox|lastarguments|language|kern|jobname|interlinepenalty|interlinepenalties|interactionmode|integerdef|instance|insertpenalties|insertht|insertheights|insert|inputlineno|input|initcatcodetable|indent|immutable|immediate|ignorespaces|ignorepars|ignorearguments|ifx|ifvoid|ifvmode|ifvbox|iftrue|iftok|ifpdfprimitive|ifpdfabsnum|ifpdfabsdim|ifparameters|ifparameter|ifodd|ifnumval|ifnum|ifmmode|ifmathstyle|ifmathparameter|ifinner|ifincsname|ifhmode|ifhbox|ifhasxtoks|ifhastoks|ifhastok|iffontchar|ifflags|iffalse|ifempty|ifdimval|ifdim|ifdefined|ifcstok|ifcsname|ifcondition|ifcmpnum|ifcmpdim|ifchknum|ifchkdim|ifcat|ifcase|ifboolean|ifarguments|ifabsnum|ifabsdim|if|hyphenpenalty|hyphenchar|hyphenationmode|hyphenationmin|hyphenation|ht|hss|hskip|hsize|hrule|hpack|holdinginserts|hjcode|hfuzz|hfilneg|hfill|hfil|hbox|hbadness|hangindent|hangafter|halign|gtokspre|gtoksapp|glyphstatefield|glyphscriptfield|glyphoptions|glyphdimensionsmode|glyphdatafield|gluetomu|gluestretchorder|gluestretch|glueshrinkorder|glueshrink|glueexpr|globaldefs|global|gleaders|gdef|futurelet|futureexpandisap|futureexpandis|futureexpand|futuredef|frozen|formatname|fontspecifiedsize|fontspecifiedname|fontname|fontid|fontdimen|fontcharwd|fontcharic|fontcharht|fontchardp|font|floatingpenalty|firstvalidlanguage|firstmarks|firstmark|finalhyphendemerits|fi|fam|explicithyphenpenalty|explicitdiscretionary|expandtoken|expandcstoken|expandafterspaces|expandafterpars|expandafter|expand|exhyphenpenalty|exhyphenchar|exceptionpenalty|everyvbox|everytab|everypar|everymath|everyjob|everyhbox|everyeof|everydisplay|everycr|etokspre|etoksapp|escapechar|errorstopmode|errorcontextlines|errmessage|errhelp|eqno|enforced|endlocalcontrol|endlinechar|endinput|endgroup|endcsname|end|emergencystretch|else|efcode|edefcsname|edef|dump|dp|doublehyphendemerits|divide|displaywidth|displaywidowpenalty|displaywidowpenalties|displaystyle|displaylimits|displayindent|discretionary|directlua|dimexpr|dimensiondef|dimendef|dimen|detokenize|delimitershortfall|delimiterfactor|delimiter|delcode|defcsname|defaultskewchar|defaulthyphenchar|def|deadcycles|day|currentiftype|currentiflevel|currentifbranch|currentgrouptype|currentgrouplevel|csstring|csname|crcr|crampedtextstyle|crampedscriptstyle|crampedscriptscriptstyle|crampeddisplaystyle|cr|countdef|count|copy|clubpenalty|clubpenalties|clearmarks|cleaders|chardef|char|catcodetable|catcode|brokenpenalty|boxyoffset|boxymove|boxxoffset|boxxmove|boxtotal|boxorientation|boxmaxdepth|boxdirection|boxattribute|box|boundary|botmarks|botmark|binoppenalty|belowdisplayskip|belowdisplayshortskip|beginlocalcontrol|begingroup|begincsname|batchmode|baselineskip|badness|automigrationmode|automatichyphenpenalty|automaticdiscretionary|attributedef|attribute|atopwithdelims|atop|atendofgrouped|atendofgroup|aligntab|alignmark|aliased|aftergrouped|aftergroup|afterassignment|afterassigned|advance|adjustspacingstretch|adjustspacingstep|adjustspacingshrink|adjustspacing|adjdemerits|accent|abovewithdelims|abovedisplayskip|abovedisplayshortskip|above|XeTeXversion|Uvextensible|Uunderdelimiter|Usuperscript|Usuperprescript|Usubscript|Usubprescript|Ustyle|Ustopmath|Ustopdisplaymath|Ustartmath|Ustartdisplaymath|Ustack|Uskewedwithdelims|Uskewed|Uroot|Uright|Uradical|Uoverwithdelims|Uoverdelimiter|Uover|Unosuperscript|Unosuperprescript|Unosubscript|Unosubprescript|Umiddle|Umathunderdelimitervgap|Umathunderdelimiterbgap|Umathunderbarvgap|Umathunderbarrule|Umathunderbarkern|Umathsupsubbottommax|Umathsupshiftup|Umathsupshiftdrop|Umathsupbottommin|Umathsubtopmax|Umathsubsupvgap|Umathsubsupshiftdown|Umathsubshiftdrop|Umathsubshiftdown|Umathstackvgap|Umathstacknumup|Umathstackdenomdown|Umathspacingmode|Umathspacebeforescript|Umathspaceafterscript|Umathskewedfractionvgap|Umathskewedfractionhgap|Umathrelrelspacing|Umathrelpunctspacing|Umathrelordspacing|Umathrelopspacing|Umathrelopenspacing|Umathrelinnerspacing|Umathrelclosespacing|Umathrelbinspacing|Umathradicalvgap|Umathradicalrule|Umathradicalkern|Umathradicaldegreeraise|Umathradicaldegreebefore|Umathradicaldegreeafter|Umathquad|Umathpunctrelspacing|Umathpunctpunctspacing|Umathpunctordspacing|Umathpunctopspacing|Umathpunctopenspacing|Umathpunctinnerspacing|Umathpunctclosespacing|Umathpunctbinspacing|Umathoverdelimitervgap|Umathoverdelimiterbgap|Umathoverbarvgap|Umathoverbarrule|Umathoverbarkern|Umathordrelspacing|Umathordpunctspacing|Umathordordspacing|Umathordopspacing|Umathordopenspacing|Umathordinnerspacing|Umathordclosespacing|Umathordbinspacing|Umathoprelspacing|Umathoppunctspacing|Umathopordspacing|Umathopopspacing|Umathopopenspacing|Umathopinnerspacing|Umathoperatorsize|Umathopenrelspacing|Umathopenpunctspacing|Umathopenordspacing|Umathopenopspacing|Umathopenopenspacing|Umathopeninnerspacing|Umathopenclosespacing|Umathopenbinspacing|Umathopclosespacing|Umathopbinspacing|Umathnolimitsupfactor|Umathnolimitsubfactor|Umathlimitbelowvgap|Umathlimitbelowkern|Umathlimitbelowbgap|Umathlimitabovevgap|Umathlimitabovekern|Umathlimitabovebgap|Umathinnerrelspacing|Umathinnerpunctspacing|Umathinnerordspacing|Umathinneropspacing|Umathinneropenspacing|Umathinnerinnerspacing|Umathinnerclosespacing|Umathinnerbinspacing|Umathfractionrule|Umathfractionnumvgap|Umathfractionnumup|Umathfractiondenomvgap|Umathfractiondenomdown|Umathfractiondelsize|Umathconnectoroverlapmin|Umathcodenum|Umathcode|Umathcloserelspacing|Umathclosepunctspacing|Umathcloseordspacing|Umathcloseopspacing|Umathcloseopenspacing|Umathcloseinnerspacing|Umathcloseclosespacing|Umathclosebinspacing|Umathclass|Umathcharslot|Umathcharnumdef|Umathcharnum|Umathcharfam|Umathchardef|Umathcharclass|Umathchar|Umathbinrelspacing|Umathbinpunctspacing|Umathbinordspacing|Umathbinopspacing|Umathbinopenspacing|Umathbininnerspacing|Umathbinclosespacing|Umathbinbinspacing|Umathaxis|Umathaccent|Uleft|Uhextensible|Udelimiterunder|Udelimiterover|Udelimiter|Udelcodenum|Udelcode|Uchar|Uatopwithdelims|Uatop|Uabovewithdelims|Uabove|UUskewedwithdelims|UUskewed|Omegaversion|Omegarevision|Omegaminorversion|Alephversion|Alephrevision|Alephminorversion| )(?=[^a-zA-Z])", + "match" : "\u005C\u005C(year|xtokspre|xtoksapp|xspaceskip|xleaders|xdefcsname|xdef|wrapuppar|wordboundary|widowpenalty|widowpenalties|wd|vtop|vss|vsplit|vskip|vsize|vrule|vpack|vfuzz|vfilneg|vfill|vfil|vcenter|vbox|vbadness|valign|vadjust|uppercase|unvpack|unvcopy|unvbox|unskip|unpenalty|unletprotected|unletfrozen|unless|unkern|unhpack|unhcopy|unhbox|underline|undent|uchyph|uccode|tracingstats|tracingrestores|tracingparagraphs|tracingpages|tracingoutput|tracingonline|tracingnesting|tracingmath|tracingmacros|tracinglostchars|tracingifs|tracinggroups|tracingfonts|tracingcommands|tracingassigns|tracingalignments|tpack|toscaled|topskip|topmarks|topmark|tolerant|tolerance|tokspre|toksdef|toksapp|toks|tokenized|tointeger|todimension|time|thinmuskip|thickmuskip|thewithoutunit|the|textstyle|textfont|textdirection|tabskip|swapcsvalues|supmarkmode|string|splittopskip|splitmaxdepth|splitfirstmarks|splitfirstmark|splitdiscards|splitbotmarks|splitbotmark|span|spaceskip|spacefactor|snapshotpar|skipdef|skip|skewchar|showtokens|showthe|shownodedetails|showlists|showifs|showgroups|showboxdepth|showboxbreadth|showbox|show|shipout|sfcode|setlanguage|setfontid|setbox|scrollmode|scriptstyle|scriptspace|scriptscriptstyle|scriptscriptfont|scriptfont|scantokens|scantextokens|savingvdiscards|savinghyphcodes|savecatcodetable|rpcode|romannumeral|rightskip|rightmarginkern|righthyphenmin|right|relpenalty|relax|raise|radical|quitvmode|pxdimen|protrusionboundary|protrudechars|protected|prevgraf|prevdepth|pretolerance|prerelpenalty|prehyphenchar|preexhyphenchar|predisplaysize|predisplaypenalty|predisplaygapfactor|predisplaydirection|prebinoppenalty|posthyphenchar|postexhyphenchar|postdisplaypenalty|permanent|penalty|pdfximage|pdfxformresources|pdfxformname|pdfxformmargin|pdfxformattr|pdfxform|pdfvorigin|pdfuniqueresname|pdfuniformdeviate|pdftrailerid|pdftrailer|pdftracingfonts|pdfthreadmargin|pdfthread|pdftexversion|pdftexrevision|pdftexbanner|pdfsuppressptexinfo|pdfsuppressoptionalinfo|pdfstartthread|pdfstartlink|pdfsetrandomseed|pdfsetmatrix|pdfsavepos|pdfsave|pdfretval|pdfrestore|pdfreplacefont|pdfrefximage|pdfrefxform|pdfrefobj|pdfrecompress|pdfrandomseed|pdfpxdimen|pdfprotrudechars|pdfprimitive|pdfpkresolution|pdfpkmode|pdfpkfixeddpi|pdfpagewidth|pdfpagesattr|pdfpageresources|pdfpageref|pdfpageheight|pdfpagebox|pdfpageattr|pdfoutput|pdfoutline|pdfomitcidset|pdfomitcharset|pdfobjcompresslevel|pdfobj|pdfnormaldeviate|pdfnoligatures|pdfnames|pdfminorversion|pdfmapline|pdfmapfile|pdfmajorversion|pdfliteral|pdflinkmargin|pdflastypos|pdflastxpos|pdflastximagepages|pdflastximage|pdflastxform|pdflastobj|pdflastlink|pdflastlinedepth|pdflastannot|pdfinsertht|pdfinfoomitdate|pdfinfo|pdfinclusionerrorlevel|pdfinclusioncopyfonts|pdfincludechars|pdfimageresolution|pdfimagehicolor|pdfimagegamma|pdfimageapplygamma|pdfimageaddfilename|pdfignoreunknownimages|pdfignoreddimen|pdfhorigin|pdfglyphtounicode|pdfgentounicode|pdfgamma|pdffontsize|pdffontobjnum|pdffontname|pdffontexpand|pdffontattr|pdffirstlineheight|pdfendthread|pdfendlink|pdfeachlineheight|pdfeachlinedepth|pdfdraftmode|pdfdestmargin|pdfdest|pdfdecimaldigits|pdfcreationdate|pdfcopyfont|pdfcompresslevel|pdfcolorstackinit|pdfcolorstack|pdfcatalog|pdfannot|pdfadjustspacing|pausing|patterns|parskip|parshapelength|parshapeindent|parshapedimen|parshape|parindent|parfillskip|pardirection|parattr|parametercount|par|pagetotal|pagestretch|pageshrink|pagegoal|pagefilstretch|pagefillstretch|pagefilllstretch|pagediscards|pagedepth|overwithdelims|overshoot|overloadmode|overloaded|overline|overfullrule|over|outputpenalty|outputbox|output|outer|orunless|orelse|ordlimits|or|omit|numexpr|number|nullfont|nulldelimiterspace|novrule|nospaces|normalyear|normalxtokspre|normalxtoksapp|normalxspaceskip|normalxleaders|normalxdefcsname|normalxdef|normalwrapuppar|normalwordboundary|normalwidowpenalty|normalwidowpenalties|normalwd|normalvtop|normalvss|normalvsplit|normalvskip|normalvsize|normalvrule|normalvpack|normalvfuzz|normalvfilneg|normalvfill|normalvfil|normalvcenter|normalvbox|normalvbadness|normalvalign|normalvadjust|normaluppercase|normalunvpack|normalunvcopy|normalunvbox|normalunskip|normalunpenalty|normalunletprotected|normalunletfrozen|normalunless|normalunkern|normalunhpack|normalunhcopy|normalunhbox|normalunexpanded|normalunderline|normalundent|normaluchyph|normaluccode|normaltracingstats|normaltracingrestores|normaltracingparagraphs|normaltracingpages|normaltracingoutput|normaltracingonline|normaltracingnesting|normaltracingmath|normaltracingmacros|normaltracinglostchars|normaltracingifs|normaltracinggroups|normaltracingfonts|normaltracingcommands|normaltracingassigns|normaltracingalignments|normaltpack|normaltoscaled|normaltopskip|normaltopmarks|normaltopmark|normaltolerant|normaltolerance|normaltokspre|normaltoksdef|normaltoksapp|normaltoks|normaltokenized|normaltointeger|normaltodimension|normaltime|normalthinmuskip|normalthickmuskip|normalthewithoutunit|normalthe|normaltextstyle|normaltextfont|normaltextdirection|normaltabskip|normalswapcsvalues|normalsupmarkmode|normalstring|normalsplittopskip|normalsplitmaxdepth|normalsplitfirstmarks|normalsplitfirstmark|normalsplitdiscards|normalsplitbotmarks|normalsplitbotmark|normalspan|normalspaceskip|normalspacefactor|normalsnapshotpar|normalskipdef|normalskip|normalskewchar|normalshowtokens|normalshowthe|normalshownodedetails|normalshowlists|normalshowifs|normalshowgroups|normalshowboxdepth|normalshowboxbreadth|normalshowbox|normalshow|normalshipout|normalsfcode|normalsetlanguage|normalsetfontid|normalsetbox|normalscrollmode|normalscriptstyle|normalscriptspace|normalscriptscriptstyle|normalscriptscriptfont|normalscriptfont|normalscantokens|normalscantextokens|normalsavingvdiscards|normalsavinghyphcodes|normalsavecatcodetable|normalrpcode|normalromannumeral|normalrightskip|normalrightmarginkern|normalrighthyphenmin|normalright|normalrelpenalty|normalrelax|normalraise|normalradical|normalquitvmode|normalpxdimen|normalprotrusionboundary|normalprotrudechars|normalprotected|normalprevgraf|normalprevdepth|normalpretolerance|normalprerelpenalty|normalprehyphenchar|normalpreexhyphenchar|normalpredisplaysize|normalpredisplaypenalty|normalpredisplaygapfactor|normalpredisplaydirection|normalprebinoppenalty|normalposthyphenchar|normalpostexhyphenchar|normalpostdisplaypenalty|normalpermanent|normalpenalty|normalpdfximage|normalpdfxformresources|normalpdfxformname|normalpdfxformmargin|normalpdfxformattr|normalpdfxform|normalpdfvorigin|normalpdfuniqueresname|normalpdfuniformdeviate|normalpdftrailerid|normalpdftrailer|normalpdftracingfonts|normalpdfthreadmargin|normalpdfthread|normalpdftexversion|normalpdftexrevision|normalpdftexbanner|normalpdfsuppressptexinfo|normalpdfsuppressoptionalinfo|normalpdfstartthread|normalpdfstartlink|normalpdfsetrandomseed|normalpdfsetmatrix|normalpdfsavepos|normalpdfsave|normalpdfretval|normalpdfrestore|normalpdfreplacefont|normalpdfrefximage|normalpdfrefxform|normalpdfrefobj|normalpdfrecompress|normalpdfrandomseed|normalpdfpxdimen|normalpdfprotrudechars|normalpdfprimitive|normalpdfpkresolution|normalpdfpkmode|normalpdfpkfixeddpi|normalpdfpagewidth|normalpdfpagesattr|normalpdfpageresources|normalpdfpageref|normalpdfpageheight|normalpdfpagebox|normalpdfpageattr|normalpdfoutput|normalpdfoutline|normalpdfomitcidset|normalpdfomitcharset|normalpdfobjcompresslevel|normalpdfobj|normalpdfnormaldeviate|normalpdfnoligatures|normalpdfnames|normalpdfminorversion|normalpdfmapline|normalpdfmapfile|normalpdfmajorversion|normalpdfliteral|normalpdflinkmargin|normalpdflastypos|normalpdflastxpos|normalpdflastximagepages|normalpdflastximage|normalpdflastxform|normalpdflastobj|normalpdflastlink|normalpdflastlinedepth|normalpdflastannot|normalpdfinsertht|normalpdfinfoomitdate|normalpdfinfo|normalpdfinclusionerrorlevel|normalpdfinclusioncopyfonts|normalpdfincludechars|normalpdfimageresolution|normalpdfimagehicolor|normalpdfimagegamma|normalpdfimageapplygamma|normalpdfimageaddfilename|normalpdfignoreunknownimages|normalpdfignoreddimen|normalpdfhorigin|normalpdfglyphtounicode|normalpdfgentounicode|normalpdfgamma|normalpdffontsize|normalpdffontobjnum|normalpdffontname|normalpdffontexpand|normalpdffontattr|normalpdffirstlineheight|normalpdfendthread|normalpdfendlink|normalpdfeachlineheight|normalpdfeachlinedepth|normalpdfdraftmode|normalpdfdestmargin|normalpdfdest|normalpdfdecimaldigits|normalpdfcreationdate|normalpdfcopyfont|normalpdfcompresslevel|normalpdfcolorstackinit|normalpdfcolorstack|normalpdfcatalog|normalpdfannot|normalpdfadjustspacing|normalpausing|normalpatterns|normalparskip|normalparshapelength|normalparshapeindent|normalparshapedimen|normalparshape|normalparindent|normalparfillskip|normalparfillleftskip|normalpardirection|normalparattr|normalparametercount|normalpar|normalpagetotal|normalpagestretch|normalpageshrink|normalpagegoal|normalpagefilstretch|normalpagefillstretch|normalpagefilllstretch|normalpagediscards|normalpagedepth|normaloverwithdelims|normalovershoot|normaloverloadmode|normaloverloaded|normaloverline|normaloverfullrule|normalover|normaloutputpenalty|normaloutputbox|normaloutput|normalouter|normalorunless|normalorelse|normalordlimits|normalor|normalomit|normalnumexpr|normalnumber|normalnullfont|normalnulldelimiterspace|normalnovrule|normalnospaces|normalnormalizelinemode|normalnonstopmode|normalnonscript|normalnolimits|normalnoindent|normalnohrule|normalnoexpand|normalnoboundary|normalnoaligned|normalnoalign|normalnewlinechar|normalmutoglue|normalmutable|normalmuskipdef|normalmuskip|normalmultiply|normalmuexpr|normalmskip|normalmoveright|normalmoveleft|normalmonth|normalmkern|normalmiddle|normalmessage|normalmedmuskip|normalmeaningless|normalmeaningfull|normalmeaning|normalmaxdepth|normalmaxdeadcycles|normalmathsurroundskip|normalmathsurroundmode|normalmathsurround|normalmathstyle|normalmathscriptsmode|normalmathscriptcharmode|normalmathscriptboxmode|normalmathrulethicknessmode|normalmathrulesmode|normalmathrulesfam|normalmathrel|normalmathpunct|normalmathpenaltiesmode|normalmathord|normalmathopen|normalmathop|normalmatholdmode|normalmathnolimitsmode|normalmathitalicsmode|normalmathinner|normalmathflattenmode|normalmatheqnogapstep|normalmathdisplayskipmode|normalmathdirection|normalmathdelimitersmode|normalmathcode|normalmathclose|normalmathchoice|normalmathchardef|normalmathchar|normalmathbin|normalmathaccent|normalmarks|normalmark|normalluatexversion|normalluatexrevision|normalluatexbanner|normalluafunctioncall|normalluafunction|normalluaescapestring|normalluadef|normalluacopyinputnodes|normalluabytecodecall|normalluabytecode|normallpcode|normallowercase|normallower|normallooseness|normallong|normallocalrightbox|normallocalleftbox|normallocalinterlinepenalty|normallocalcontrolled|normallocalcontrol|normallocalbrokenpenalty|normallineskiplimit|normallineskip|normallinepenalty|normallinepar|normallinedirection|normallimits|normalletprotected|normalletfrozen|normalletcsname|normalletcharcode|normallet|normalleqno|normalleftskip|normalleftmarginkern|normallefthyphenmin|normalleft|normalleaders|normallccode|normallastskip|normallastpenalty|normallastnodetype|normallastnodesubtype|normallastnamedcs|normallastlinefit|normallastkern|normallastbox|normallastarguments|normallanguage|normalkern|normaljobname|normalizelinemode|normalinterlinepenalty|normalinterlinepenalties|normalinteractionmode|normalintegerdef|normalinstance|normalinsertpenalties|normalinsertht|normalinsertheights|normalinsert|normalinputlineno|normalinput|normalinitcatcodetable|normalindent|normalimmutable|normalimmediate|normalignorespaces|normalignorepars|normalignorearguments|normalifx|normalifvoid|normalifvmode|normalifvbox|normaliftrue|normaliftok|normalifpdfprimitive|normalifpdfabsnum|normalifpdfabsdim|normalifparameters|normalifparameter|normalifodd|normalifnumval|normalifnum|normalifmmode|normalifmathstyle|normalifmathparameter|normalifinner|normalifincsname|normalifhmode|normalifhbox|normalifhasxtoks|normalifhastoks|normalifhastok|normaliffontchar|normalifflags|normaliffalse|normalifempty|normalifdimval|normalifdim|normalifdefined|normalifcstok|normalifcsname|normalifcondition|normalifcmpnum|normalifcmpdim|normalifchknum|normalifchkdim|normalifcat|normalifcase|normalifboolean|normalifarguments|normalifabsnum|normalifabsdim|normalif|normalhyphenpenalty|normalhyphenchar|normalhyphenationmode|normalhyphenationmin|normalhyphenation|normalht|normalhss|normalhskip|normalhsize|normalhrule|normalhpack|normalholdinginserts|normalhjcode|normalhfuzz|normalhfilneg|normalhfill|normalhfil|normalhbox|normalhbadness|normalhangindent|normalhangafter|normalhalign|normalgtokspre|normalgtoksapp|normalglyphstatefield|normalglyphscriptfield|normalglyphoptions|normalglyphdimensionsmode|normalglyphdatafield|normalgluetomu|normalgluestretchorder|normalgluestretch|normalglueshrinkorder|normalglueshrink|normalglueexpr|normalglobaldefs|normalglobal|normalgletcsname|normalglet|normalgleaders|normalgdefcsname|normalgdef|normalfuturelet|normalfutureexpandisap|normalfutureexpandis|normalfutureexpand|normalfuturedef|normalfrozen|normalformatname|normalfontspecifiedsize|normalfontspecifiedname|normalfontname|normalfontid|normalfontdimen|normalfontcharwd|normalfontcharic|normalfontcharht|normalfontchardp|normalfont|normalfloatingpenalty|normalfirstvalidlanguage|normalfirstmarks|normalfirstmark|normalfinalhyphendemerits|normalfi|normalfam|normalexplicithyphenpenalty|normalexplicitdiscretionary|normalexpandtoken|normalexpanded|normalexpandcstoken|normalexpandafterspaces|normalexpandafterpars|normalexpandafter|normalexpand|normalexhyphenpenalty|normalexhyphenchar|normalexceptionpenalty|normaleveryvbox|normaleverytab|normaleverypar|normaleverymath|normaleveryjob|normaleveryhbox|normaleveryeof|normaleverydisplay|normaleverycr|normaletokspre|normaletoksapp|normalescapechar|normalerrorstopmode|normalerrorcontextlines|normalerrmessage|normalerrhelp|normaleqno|normalenforced|normalendlocalcontrol|normalendlinechar|normalendinput|normalendgroup|normalendcsname|normalend|normalemergencystretch|normalelse|normalefcode|normaledefcsname|normaledef|normaldump|normaldp|normaldoublehyphendemerits|normaldivide|normaldisplaywidth|normaldisplaywidowpenalty|normaldisplaywidowpenalties|normaldisplaystyle|normaldisplaylimits|normaldisplayindent|normaldiscretionary|normaldirectlua|normaldimexpr|normaldimensiondef|normaldimendef|normaldimen|normaldetokenize|normaldelimitershortfall|normaldelimiterfactor|normaldelimiter|normaldelcode|normaldefcsname|normaldefaultskewchar|normaldefaulthyphenchar|normaldef|normaldeadcycles|normalday|normalcurrentiftype|normalcurrentiflevel|normalcurrentifbranch|normalcurrentgrouptype|normalcurrentgrouplevel|normalcsstring|normalcsname|normalcrcr|normalcrampedtextstyle|normalcrampedscriptstyle|normalcrampedscriptscriptstyle|normalcrampeddisplaystyle|normalcr|normalcountdef|normalcount|normalcopy|normalclubpenalty|normalclubpenalties|normalclearmarks|normalcleaders|normalchardef|normalchar|normalcatcodetable|normalcatcode|normalbrokenpenalty|normalboxyoffset|normalboxymove|normalboxxoffset|normalboxxmove|normalboxtotal|normalboxorientation|normalboxmaxdepth|normalboxdirection|normalboxattribute|normalbox|normalboundary|normalbotmarks|normalbotmark|normalbinoppenalty|normalbelowdisplayskip|normalbelowdisplayshortskip|normalbeginlocalcontrol|normalbegingroup|normalbegincsname|normalbatchmode|normalbaselineskip|normalbadness|normalautomigrationmode|normalautomatichyphenpenalty|normalautomaticdiscretionary|normalattributedef|normalattribute|normalatopwithdelims|normalatop|normalatendofgrouped|normalatendofgroup|normalaligntab|normalalignmark|normalaliased|normalaftergrouped|normalaftergroup|normalafterassignment|normalafterassigned|normaladvance|normaladjustspacingstretch|normaladjustspacingstep|normaladjustspacingshrink|normaladjustspacing|normaladjdemerits|normalaccent|normalabovewithdelims|normalabovedisplayskip|normalabovedisplayshortskip|normalabove|normalXeTeXversion|normalUvextensible|normalUunderdelimiter|normalUsuperscript|normalUsuperprescript|normalUsubscript|normalUsubprescript|normalUstyle|normalUstopmath|normalUstopdisplaymath|normalUstartmath|normalUstartdisplaymath|normalUstack|normalUskewedwithdelims|normalUskewed|normalUroot|normalUright|normalUradical|normalUoverwithdelims|normalUoverdelimiter|normalUover|normalUnosuperscript|normalUnosuperprescript|normalUnosubscript|normalUnosubprescript|normalUmiddle|normalUmathunderdelimitervgap|normalUmathunderdelimiterbgap|normalUmathunderbarvgap|normalUmathunderbarrule|normalUmathunderbarkern|normalUmathsupsubbottommax|normalUmathsupshiftup|normalUmathsupshiftdrop|normalUmathsupbottommin|normalUmathsubtopmax|normalUmathsubsupvgap|normalUmathsubsupshiftdown|normalUmathsubshiftdrop|normalUmathsubshiftdown|normalUmathstackvgap|normalUmathstacknumup|normalUmathstackdenomdown|normalUmathspacingmode|normalUmathspacebeforescript|normalUmathspaceafterscript|normalUmathskewedfractionvgap|normalUmathskewedfractionhgap|normalUmathrelrelspacing|normalUmathrelpunctspacing|normalUmathrelordspacing|normalUmathrelopspacing|normalUmathrelopenspacing|normalUmathrelinnerspacing|normalUmathrelclosespacing|normalUmathrelbinspacing|normalUmathradicalvgap|normalUmathradicalrule|normalUmathradicalkern|normalUmathradicaldegreeraise|normalUmathradicaldegreebefore|normalUmathradicaldegreeafter|normalUmathquad|normalUmathpunctrelspacing|normalUmathpunctpunctspacing|normalUmathpunctordspacing|normalUmathpunctopspacing|normalUmathpunctopenspacing|normalUmathpunctinnerspacing|normalUmathpunctclosespacing|normalUmathpunctbinspacing|normalUmathoverdelimitervgap|normalUmathoverdelimiterbgap|normalUmathoverbarvgap|normalUmathoverbarrule|normalUmathoverbarkern|normalUmathordrelspacing|normalUmathordpunctspacing|normalUmathordordspacing|normalUmathordopspacing|normalUmathordopenspacing|normalUmathordinnerspacing|normalUmathordclosespacing|normalUmathordbinspacing|normalUmathoprelspacing|normalUmathoppunctspacing|normalUmathopordspacing|normalUmathopopspacing|normalUmathopopenspacing|normalUmathopinnerspacing|normalUmathoperatorsize|normalUmathopenrelspacing|normalUmathopenpunctspacing|normalUmathopenordspacing|normalUmathopenopspacing|normalUmathopenopenspacing|normalUmathopeninnerspacing|normalUmathopenclosespacing|normalUmathopenbinspacing|normalUmathopclosespacing|normalUmathopbinspacing|normalUmathnolimitsupfactor|normalUmathnolimitsubfactor|normalUmathlimitbelowvgap|normalUmathlimitbelowkern|normalUmathlimitbelowbgap|normalUmathlimitabovevgap|normalUmathlimitabovekern|normalUmathlimitabovebgap|normalUmathinnerrelspacing|normalUmathinnerpunctspacing|normalUmathinnerordspacing|normalUmathinneropspacing|normalUmathinneropenspacing|normalUmathinnerinnerspacing|normalUmathinnerclosespacing|normalUmathinnerbinspacing|normalUmathfractionrule|normalUmathfractionnumvgap|normalUmathfractionnumup|normalUmathfractiondenomvgap|normalUmathfractiondenomdown|normalUmathfractiondelsize|normalUmathconnectoroverlapmin|normalUmathcodenum|normalUmathcode|normalUmathcloserelspacing|normalUmathclosepunctspacing|normalUmathcloseordspacing|normalUmathcloseopspacing|normalUmathcloseopenspacing|normalUmathcloseinnerspacing|normalUmathcloseclosespacing|normalUmathclosebinspacing|normalUmathclass|normalUmathcharslot|normalUmathcharnumdef|normalUmathcharnum|normalUmathcharfam|normalUmathchardef|normalUmathcharclass|normalUmathchar|normalUmathbinrelspacing|normalUmathbinpunctspacing|normalUmathbinordspacing|normalUmathbinopspacing|normalUmathbinopenspacing|normalUmathbininnerspacing|normalUmathbinclosespacing|normalUmathbinbinspacing|normalUmathaxis|normalUmathaccent|normalUleft|normalUhextensible|normalUdelimiterunder|normalUdelimiterover|normalUdelimiter|normalUdelcodenum|normalUdelcode|normalUchar|normalUatopwithdelims|normalUatop|normalUabovewithdelims|normalUabove|normalUUskewedwithdelims|normalUUskewed|normalOmegaversion|normalOmegarevision|normalOmegaminorversion|normalAlephversion|normalAlephrevision|normalAlephminorversion|normal |nonstopmode|nonscript|nolimits|noindent|nohrule|noexpand|noboundary|noaligned|noalign|newlinechar|mutoglue|mutable|muskipdef|muskip|multiply|muexpr|mskip|moveright|moveleft|month|mkern|middle|message|medmuskip|meaningless|meaningfull|meaning|maxdepth|maxdeadcycles|mathsurroundskip|mathsurroundmode|mathsurround|mathstyle|mathscriptsmode|mathscriptcharmode|mathscriptboxmode|mathrulethicknessmode|mathrulesmode|mathrulesfam|mathrel|mathpunct|mathpenaltiesmode|mathord|mathopen|mathop|matholdmode|mathnolimitsmode|mathitalicsmode|mathinner|mathflattenmode|matheqnogapstep|mathdisplayskipmode|mathdirection|mathdelimitersmode|mathcode|mathclose|mathchoice|mathchardef|mathchar|mathbin|mathaccent|marks|mark|luatexversion|luatexrevision|luatexbanner|luafunctioncall|luafunction|luaescapestring|luadef|luacopyinputnodes|luabytecodecall|luabytecode|lpcode|lowercase|lower|looseness|long|localrightbox|localleftbox|localinterlinepenalty|localcontrolled|localcontrol|localbrokenpenalty|lineskiplimit|lineskip|linepenalty|linepar|linedirection|limits|letprotected|letfrozen|letcsname|letcharcode|let|leqno|leftskip|leftmarginkern|lefthyphenmin|left|leaders|lccode|lastskip|lastpenalty|lastnodetype|lastnodesubtype|lastnamedcs|lastlinefit|lastkern|lastbox|lastarguments|language|kern|jobname|interlinepenalty|interlinepenalties|interactionmode|integerdef|instance|insertpenalties|insertht|insertheights|insert|inputlineno|input|initcatcodetable|indent|immutable|immediate|ignorespaces|ignorepars|ignorearguments|ifx|ifvoid|ifvmode|ifvbox|iftrue|iftok|ifpdfprimitive|ifpdfabsnum|ifpdfabsdim|ifparameters|ifparameter|ifodd|ifnumval|ifnum|ifmmode|ifmathstyle|ifmathparameter|ifinner|ifincsname|ifhmode|ifhbox|ifhasxtoks|ifhastoks|ifhastok|iffontchar|ifflags|iffalse|ifempty|ifdimval|ifdim|ifdefined|ifcstok|ifcsname|ifcondition|ifcmpnum|ifcmpdim|ifchknum|ifchkdim|ifcat|ifcase|ifboolean|ifarguments|ifabsnum|ifabsdim|if|hyphenpenalty|hyphenchar|hyphenationmode|hyphenationmin|hyphenation|ht|hss|hskip|hsize|hrule|hpack|holdinginserts|hjcode|hfuzz|hfilneg|hfill|hfil|hbox|hbadness|hangindent|hangafter|halign|gtokspre|gtoksapp|glyphstatefield|glyphscriptfield|glyphoptions|glyphdimensionsmode|glyphdatafield|gluetomu|gluestretchorder|gluestretch|glueshrinkorder|glueshrink|glueexpr|globaldefs|global|gletcsname|gleaders|gdefcsname|gdef|futurelet|futureexpandisap|futureexpandis|futureexpand|futuredef|frozen|formatname|fontspecifiedsize|fontspecifiedname|fontname|fontid|fontdimen|fontcharwd|fontcharic|fontcharht|fontchardp|font|floatingpenalty|firstvalidlanguage|firstmarks|firstmark|finalhyphendemerits|fi|fam|explicithyphenpenalty|explicitdiscretionary|expandtoken|expandcstoken|expandafterspaces|expandafterpars|expandafter|expand|exhyphenpenalty|exhyphenchar|exceptionpenalty|everyvbox|everytab|everypar|everymath|everyjob|everyhbox|everyeof|everydisplay|everycr|etokspre|etoksapp|escapechar|errorstopmode|errorcontextlines|errmessage|errhelp|eqno|enforced|endlocalcontrol|endlinechar|endinput|endgroup|endcsname|end|emergencystretch|else|efcode|edefcsname|edef|dump|dp|doublehyphendemerits|divide|displaywidth|displaywidowpenalty|displaywidowpenalties|displaystyle|displaylimits|displayindent|discretionary|directlua|dimexpr|dimensiondef|dimendef|dimen|detokenize|delimitershortfall|delimiterfactor|delimiter|delcode|defcsname|defaultskewchar|defaulthyphenchar|def|deadcycles|day|currentiftype|currentiflevel|currentifbranch|currentgrouptype|currentgrouplevel|csstring|csname|crcr|crampedtextstyle|crampedscriptstyle|crampedscriptscriptstyle|crampeddisplaystyle|cr|countdef|count|copy|clubpenalty|clubpenalties|clearmarks|cleaders|chardef|char|catcodetable|catcode|brokenpenalty|boxyoffset|boxymove|boxxoffset|boxxmove|boxtotal|boxorientation|boxmaxdepth|boxdirection|boxattribute|box|boundary|botmarks|botmark|binoppenalty|belowdisplayskip|belowdisplayshortskip|beginlocalcontrol|begingroup|begincsname|batchmode|baselineskip|badness|automigrationmode|automatichyphenpenalty|automaticdiscretionary|attributedef|attribute|atopwithdelims|atop|atendofgrouped|atendofgroup|aligntab|alignmark|aliased|aftergrouped|aftergroup|afterassignment|afterassigned|advance|adjustspacingstretch|adjustspacingstep|adjustspacingshrink|adjustspacing|adjdemerits|accent|abovewithdelims|abovedisplayskip|abovedisplayshortskip|above|XeTeXversion|Uvextensible|Uunderdelimiter|Usuperscript|Usuperprescript|Usubscript|Usubprescript|Ustyle|Ustopmath|Ustopdisplaymath|Ustartmath|Ustartdisplaymath|Ustack|Uskewedwithdelims|Uskewed|Uroot|Uright|Uradical|Uoverwithdelims|Uoverdelimiter|Uover|Unosuperscript|Unosuperprescript|Unosubscript|Unosubprescript|Umiddle|Umathunderdelimitervgap|Umathunderdelimiterbgap|Umathunderbarvgap|Umathunderbarrule|Umathunderbarkern|Umathsupsubbottommax|Umathsupshiftup|Umathsupshiftdrop|Umathsupbottommin|Umathsubtopmax|Umathsubsupvgap|Umathsubsupshiftdown|Umathsubshiftdrop|Umathsubshiftdown|Umathstackvgap|Umathstacknumup|Umathstackdenomdown|Umathspacingmode|Umathspacebeforescript|Umathspaceafterscript|Umathskewedfractionvgap|Umathskewedfractionhgap|Umathrelrelspacing|Umathrelpunctspacing|Umathrelordspacing|Umathrelopspacing|Umathrelopenspacing|Umathrelinnerspacing|Umathrelclosespacing|Umathrelbinspacing|Umathradicalvgap|Umathradicalrule|Umathradicalkern|Umathradicaldegreeraise|Umathradicaldegreebefore|Umathradicaldegreeafter|Umathquad|Umathpunctrelspacing|Umathpunctpunctspacing|Umathpunctordspacing|Umathpunctopspacing|Umathpunctopenspacing|Umathpunctinnerspacing|Umathpunctclosespacing|Umathpunctbinspacing|Umathoverdelimitervgap|Umathoverdelimiterbgap|Umathoverbarvgap|Umathoverbarrule|Umathoverbarkern|Umathordrelspacing|Umathordpunctspacing|Umathordordspacing|Umathordopspacing|Umathordopenspacing|Umathordinnerspacing|Umathordclosespacing|Umathordbinspacing|Umathoprelspacing|Umathoppunctspacing|Umathopordspacing|Umathopopspacing|Umathopopenspacing|Umathopinnerspacing|Umathoperatorsize|Umathopenrelspacing|Umathopenpunctspacing|Umathopenordspacing|Umathopenopspacing|Umathopenopenspacing|Umathopeninnerspacing|Umathopenclosespacing|Umathopenbinspacing|Umathopclosespacing|Umathopbinspacing|Umathnolimitsupfactor|Umathnolimitsubfactor|Umathlimitbelowvgap|Umathlimitbelowkern|Umathlimitbelowbgap|Umathlimitabovevgap|Umathlimitabovekern|Umathlimitabovebgap|Umathinnerrelspacing|Umathinnerpunctspacing|Umathinnerordspacing|Umathinneropspacing|Umathinneropenspacing|Umathinnerinnerspacing|Umathinnerclosespacing|Umathinnerbinspacing|Umathfractionrule|Umathfractionnumvgap|Umathfractionnumup|Umathfractiondenomvgap|Umathfractiondenomdown|Umathfractiondelsize|Umathconnectoroverlapmin|Umathcodenum|Umathcode|Umathcloserelspacing|Umathclosepunctspacing|Umathcloseordspacing|Umathcloseopspacing|Umathcloseopenspacing|Umathcloseinnerspacing|Umathcloseclosespacing|Umathclosebinspacing|Umathclass|Umathcharslot|Umathcharnumdef|Umathcharnum|Umathcharfam|Umathchardef|Umathcharclass|Umathchar|Umathbinrelspacing|Umathbinpunctspacing|Umathbinordspacing|Umathbinopspacing|Umathbinopenspacing|Umathbininnerspacing|Umathbinclosespacing|Umathbinbinspacing|Umathaxis|Umathaccent|Uleft|Uhextensible|Udelimiterunder|Udelimiterover|Udelimiter|Udelcodenum|Udelcode|Uchar|Uatopwithdelims|Uatop|Uabovewithdelims|Uabove|UUskewedwithdelims|UUskewed|Omegaversion|Omegarevision|Omegaminorversion|Alephversion|Alephrevision|Alephminorversion| )(?=[^a-zA-Z])", "name" : "context.primitive.commands.primitive.tex" }, "reserved" : { diff --git a/doc/context/documents/general/manuals/lowlevel-grouping.pdf b/doc/context/documents/general/manuals/lowlevel-grouping.pdf index 5439f29e5..a8d103236 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-grouping.pdf and b/doc/context/documents/general/manuals/lowlevel-grouping.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-en.pdf b/doc/context/documents/general/qrcs/setup-en.pdf index 7950faf9f..f1ee11be3 100644 Binary files a/doc/context/documents/general/qrcs/setup-en.pdf and b/doc/context/documents/general/qrcs/setup-en.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-fr.pdf b/doc/context/documents/general/qrcs/setup-fr.pdf index 1bae860e4..908d9f916 100644 Binary files a/doc/context/documents/general/qrcs/setup-fr.pdf and b/doc/context/documents/general/qrcs/setup-fr.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-it.pdf b/doc/context/documents/general/qrcs/setup-it.pdf index 9c2baed48..6f4bf9cf8 100644 Binary files a/doc/context/documents/general/qrcs/setup-it.pdf and b/doc/context/documents/general/qrcs/setup-it.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-mapping-en.pdf b/doc/context/documents/general/qrcs/setup-mapping-en.pdf index 759035542..8c3046f9b 100644 Binary files a/doc/context/documents/general/qrcs/setup-mapping-en.pdf and b/doc/context/documents/general/qrcs/setup-mapping-en.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf index 5438ca5d9..3550ea7ba 100644 Binary files a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf and b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf differ diff --git a/doc/context/documents/general/qrcs/setup-mapping-it.pdf b/doc/context/documents/general/qrcs/setup-mapping-it.pdf index 9529cef0c..bdaf74432 100644 Binary files a/doc/context/documents/general/qrcs/setup-mapping-it.pdf and b/doc/context/documents/general/qrcs/setup-mapping-it.pdf differ diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel-expansion.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel-expansion.tex index 19c5efe12..15faa802d 100644 --- a/doc/context/sources/general/manuals/lowlevel/lowlevel-expansion.tex +++ b/doc/context/sources/general/manuals/lowlevel/lowlevel-expansion.tex @@ -453,6 +453,25 @@ And maybe also here: % \aftergroups % \aftergrouped +And: + +\starttyping + \def\foo{foo} +\protected\def\oof{oof} + +\csname foo\endcsname +\csname oof\endcsname +\csname \foo\endcsname +% \csname \oof\endcsname % error in luametatex + +\ifcsname foo\endcsname yes\else nop\fi +\ifcsname oof\endcsname yes\else nop\fi +\ifcsname \foo\endcsname yes\else nop\fi +\ifcsname \oof\endcsname yes\else nop\fi % nop in luametatex +\stoptyping + +\stoptext + \stopsection \stopdocument diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel-security.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel-security.tex index 4bb0c19d8..4f705e37c 100644 --- a/doc/context/sources/general/manuals/lowlevel/lowlevel-security.tex +++ b/doc/context/sources/general/manuals/lowlevel/lowlevel-security.tex @@ -6,6 +6,12 @@ % (youtube movie) but that doesn't mean I should not aim for perfection. But as % with drumming, it takes practising and that is what I did on a subset of sources % when writing the engine code. +% +% It tooks a few weeks but November 21 2020 the last of the core files was turned +% \LMTX, not that the work was done (checking to be done (thanks Wolfgang!), imp +% files to be checked, many \LUA\ files to be updated) but it's a start. This time +% the musical timestamp is listening to Nikola Cvetkovic (piano) and history +% podcasts. \usemodule[system-tokens] diff --git a/metapost/context/base/mpiv/metafun.mpxl b/metapost/context/base/mpiv/metafun.mpxl deleted file mode 100644 index a6160ef3e..000000000 --- a/metapost/context/base/mpiv/metafun.mpxl +++ /dev/null @@ -1,46 +0,0 @@ -%D \module -%D [ file=metafun.mp, -%D version=2000.07.15, -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=format generation file, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D First we input John Hobby's metapost plain file. However, because we want to -%D prevent dependency problems and in the end even may use a patched version, -%D we prefer to use a copy. - -boolean contextlmtxmode ; contextlmtxmode := if known fontmaking : false else: true fi; - -input "mp-base.mpiv" ; -input "mp-tool.mpiv" ; -input "mp-mlib.mpiv" ; -input "mp-luas.mpxl" ; -input "mp-math.mpxl" ; -input "mp-cont.mpxl" ; -input "mp-page.mpxl" ; -input "mp-butt.mpiv" ; -input "mp-shap.mpiv" ; -input "mp-grph.mpiv" ; -input "mp-grid.mpiv" ; -input "mp-form.mpiv" ; -input "mp-figs.mpiv" ; -input "mp-func.mpiv" ; -input "mp-node.mpiv" ; -input "mp-apos.mpiv" ; -input "mp-abck.mpiv" ; -input "mp-blob.mpiv" ; - -input "mp-lmtx.mpxl" ; % playground, not official - -string metafunversion ; metafunversion = "metafun xl " & mfun_timestamp; - -let normalend = end ; - -def end = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; -def bye = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; diff --git a/metapost/context/base/mpiv/minifun.mpxl b/metapost/context/base/mpiv/minifun.mpxl deleted file mode 100644 index 6769d26e4..000000000 --- a/metapost/context/base/mpiv/minifun.mpxl +++ /dev/null @@ -1,35 +0,0 @@ -%D \module -%D [ file=minifun.mp, -%D version=2018.06.02, -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=format generation file, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This is a minimal \METAFUN\ instance which can be handy for isolated -%D subruns. - -boolean contextlmtxmode ; contextlmtxmode := if known fontmaking : false else: true fi; - -prologues := 0 ; -mpprocset := 1 ; - -input "mp-base.mpiv" ; -input "mp-tool.mpiv" ; -input "mp-mlib.mpiv" ; -input "mp-luas.mpxl" ; -input "mp-math.mpxl" ; -input "mp-cont.mpxl" ; -input "mp-page.mpiv" ; - -string minifunversion ; minifunversion = "minifun xl " & mfun_timestamp; - -let normalend = end ; - -def end = ; message "" ; message minifunversion ; message "" ; endinput ; enddef ; -def bye = ; message "" ; message minifunversion ; message "" ; endinput ; enddef ; diff --git a/metapost/context/base/mpiv/mp-cont.mpxl b/metapost/context/base/mpiv/mp-cont.mpxl deleted file mode 100644 index bc318d4b9..000000000 --- a/metapost/context/base/mpiv/mp-cont.mpxl +++ /dev/null @@ -1,158 +0,0 @@ -%D \module -%D [ file=mp-cont.mpiv, -%D version=1999.03.10, -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=Interfaces, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This module is rather preliminary and subjected to changes. - -if known context_cont : endinput ; fi ; - -boolean context_cont ; context_cont := true ; - -string CurrentLayout ; CurrentLayout := "default" ; - -boolean mfun_swapped ; - -def SwapPageState = - mfun_swapped := true ; % eventually this will go ! -enddef ; - -extra_beginfig := extra_beginfig & "mfun_swapped := false ;" ; - -newinternal mfid_PaperHeight ; mfid_PaperHeight := scriptindex "PaperHeight" ; vardef PaperHeight = runscript mfid_PaperHeight enddef ; -newinternal mfid_PaperWidth ; mfid_PaperWidth := scriptindex "PaperWidth" ; vardef PaperWidth = runscript mfid_PaperWidth enddef ; -newinternal mfid_PrintPaperHeight ; mfid_PrintPaperHeight := scriptindex "PrintPaperHeight" ; vardef PrintPaperHeight = runscript mfid_PrintPaperHeight enddef ; -newinternal mfid_PrintPaperWidth ; mfid_PrintPaperWidth := scriptindex "PrintPaperWidth" ; vardef PrintPaperWidth = runscript mfid_PrintPaperWidth enddef ; -newinternal mfid_TopSpace ; mfid_TopSpace := scriptindex "TopSpace" ; vardef TopSpace = runscript mfid_TopSpace enddef ; -newinternal mfid_BottomSpace ; mfid_BottomSpace := scriptindex "BottomSpace" ; vardef BottomSpace = runscript mfid_BottomSpace enddef ; -newinternal mfid_BackSpace ; mfid_BackSpace := scriptindex "BackSpace" ; vardef BackSpace = runscript mfid_BackSpace enddef ; -newinternal mfid_CutSpace ; mfid_CutSpace := scriptindex "CutSpace" ; vardef CutSpace = runscript mfid_CutSpace enddef ; -newinternal mfid_MakeupHeight ; mfid_MakeupHeight := scriptindex "MakeupHeight" ; vardef MakeupHeight = runscript mfid_MakeupHeight enddef ; -newinternal mfid_MakeupWidth ; mfid_MakeupWidth := scriptindex "MakeupWidth" ; vardef MakeupWidth = runscript mfid_MakeupWidth enddef ; -newinternal mfid_TopHeight ; mfid_TopHeight := scriptindex "TopHeight" ; vardef TopHeight = runscript mfid_TopHeight enddef ; -newinternal mfid_TopDistance ; mfid_TopDistance := scriptindex "TopDistance" ; vardef TopDistance = runscript mfid_TopDistance enddef ; -newinternal mfid_HeaderHeight ; mfid_HeaderHeight := scriptindex "HeaderHeight" ; vardef HeaderHeight = runscript mfid_HeaderHeight enddef ; -newinternal mfid_HeaderDistance ; mfid_HeaderDistance := scriptindex "HeaderDistance" ; vardef HeaderDistance = runscript mfid_HeaderDistance enddef ; -newinternal mfid_TextHeight ; mfid_TextHeight := scriptindex "TextHeight" ; vardef TextHeight = runscript mfid_TextHeight enddef ; -newinternal mfid_FooterDistance ; mfid_FooterDistance := scriptindex "FooterDistance" ; vardef FooterDistance = runscript mfid_FooterDistance enddef ; -newinternal mfid_FooterHeight ; mfid_FooterHeight := scriptindex "FooterHeight" ; vardef FooterHeight = runscript mfid_FooterHeight enddef ; -newinternal mfid_BottomDistance ; mfid_BottomDistance := scriptindex "BottomDistance" ; vardef BottomDistance = runscript mfid_BottomDistance enddef ; -newinternal mfid_BottomHeight ; mfid_BottomHeight := scriptindex "BottomHeight" ; vardef BottomHeight = runscript mfid_BottomHeight enddef ; -newinternal mfid_LeftEdgeWidth ; mfid_LeftEdgeWidth := scriptindex "LeftEdgeWidth" ; vardef LeftEdgeWidth = runscript mfid_LeftEdgeWidth enddef ; -newinternal mfid_LeftEdgeDistance ; mfid_LeftEdgeDistance := scriptindex "LeftEdgeDistance" ; vardef LeftEdgeDistance = runscript mfid_LeftEdgeDistance enddef ; -newinternal mfid_LeftMarginWidth ; mfid_LeftMarginWidth := scriptindex "LeftMarginWidth" ; vardef LeftMarginWidth = runscript mfid_LeftMarginWidth enddef ; -newinternal mfid_LeftMarginDistance ; mfid_LeftMarginDistance := scriptindex "LeftMarginDistance" ; vardef LeftMarginDistance = runscript mfid_LeftMarginDistance enddef ; -newinternal mfid_TextWidth ; mfid_TextWidth := scriptindex "TextWidth" ; vardef TextWidth = runscript mfid_TextWidth enddef ; -newinternal mfid_RightMarginDistance ; mfid_RightMarginDistance := scriptindex "RightMarginDistance" ; vardef RightMarginDistance = runscript mfid_RightMarginDistance enddef ; -newinternal mfid_RightMarginWidth ; mfid_RightMarginWidth := scriptindex "RightMarginWidth" ; vardef RightMarginWidth = runscript mfid_RightMarginWidth enddef ; -newinternal mfid_RightEdgeDistance ; mfid_RightEdgeDistance := scriptindex "RightEdgeDistance" ; vardef RightEdgeDistance = runscript mfid_RightEdgeDistance enddef ; -newinternal mfid_RightEdgeWidth ; mfid_RightEdgeWidth := scriptindex "RightEdgeWidth" ; vardef RightEdgeWidth = runscript mfid_RightEdgeWidth enddef ; -newinternal mfid_InnerMarginDistance ; mfid_InnerMarginDistance := scriptindex "InnerMarginDistance" ; vardef InnerMarginDistance = runscript mfid_InnerMarginDistance enddef ; -newinternal mfid_InnerMarginWidth ; mfid_InnerMarginWidth := scriptindex "InnerMarginWidth" ; vardef InnerMarginWidth = runscript mfid_InnerMarginWidth enddef ; -newinternal mfid_OuterMarginDistance ; mfid_OuterMarginDistance := scriptindex "OuterMarginDistance" ; vardef OuterMarginDistance = runscript mfid_OuterMarginDistance enddef ; -newinternal mfid_OuterMarginWidth ; mfid_OuterMarginWidth := scriptindex "OuterMarginWidth" ; vardef OuterMarginWidth = runscript mfid_OuterMarginWidth enddef ; -newinternal mfid_InnerEdgeDistance ; mfid_InnerEdgeDistance := scriptindex "InnerEdgeDistance" ; vardef InnerEdgeDistance = runscript mfid_InnerEdgeDistance enddef ; -newinternal mfid_InnerEdgeWidth ; mfid_InnerEdgeWidth := scriptindex "InnerEdgeWidth" ; vardef InnerEdgeWidth = runscript mfid_InnerEdgeWidth enddef ; -newinternal mfid_OuterEdgeDistance ; mfid_OuterEdgeDistance := scriptindex "OuterEdgeDistance" ; vardef OuterEdgeDistance = runscript mfid_OuterEdgeDistance enddef ; -newinternal mfid_OuterEdgeWidth ; mfid_OuterEdgeWidth := scriptindex "OuterEdgeWidth" ; vardef OuterEdgeWidth = runscript mfid_OuterEdgeWidth enddef ; -newinternal mfid_PageOffset ; mfid_PageOffset := scriptindex "PageOffset" ; vardef PageOffset = runscript mfid_PageOffset enddef ; -newinternal mfid_PageDepth ; mfid_PageDepth := scriptindex "PageDepth" ; vardef PageDepth = runscript mfid_PageDepth enddef ; -newinternal mfid_LayoutColumns ; mfid_LayoutColumns := scriptindex "LayoutColumns" ; vardef LayoutColumns = runscript mfid_LayoutColumns enddef ; -newinternal mfid_LayoutColumnDistance ; mfid_LayoutColumnDistance := scriptindex "LayoutColumnDistance" ; vardef LayoutColumnDistance = runscript mfid_LayoutColumnDistance enddef ; -newinternal mfid_LayoutColumnWidth ; mfid_LayoutColumnWidth := scriptindex "LayoutColumnWidth" ; vardef LayoutColumnWidth = runscript mfid_LayoutColumnWidth enddef ; - -newinternal mfid_OnRightPage ; mfid_OnRightPage := scriptindex "OnRightPage" ; vardef OnRightPage = runscript mfid_OnRightPage enddef ; -newinternal mfid_OnOddPage ; mfid_OnOddPage := scriptindex "OnOddPage" ; vardef OnOddPage = runscript mfid_OnOddPage enddef ; -newinternal mfid_InPageBody ; mfid_InPageBody := scriptindex "InPageBody" ; vardef InPageBody = runscript mfid_InPageBody enddef ; - -newinternal mfid_RealPageNumber ; mfid_RealPageNumber := scriptindex "RealPageNumber" ; vardef RealPageNumber = runscript mfid_RealPageNumber enddef ; -newinternal mfid_LastPageNumber ; mfid_LastPageNumber := scriptindex "LastPageNumber" ; vardef LastPageNumber = runscript mfid_LastPageNumber enddef ; - -newinternal mfid_PageNumber ; mfid_PageNumber := scriptindex "PageNumber" ; vardef PageNumber = runscript mfid_PageNumber enddef ; -newinternal mfid_NOfPages ; mfid_NOfPages := scriptindex "NOfPages" ; vardef NOfPages = runscript mfid_NOfPages enddef ; - -newinternal mfid_SubPageNumber ; mfid_SubPageNumber := scriptindex "SubPageNumber" ; vardef SubPageNumber = runscript mfid_SubPageNumber enddef ; -newinternal mfid_NOfSubPages ; mfid_NOfSubPages := scriptindex "NOfSubPages" ; vardef NOfSubPages = runscript mfid_NOfSubPages enddef ; - -newinternal mfid_CurrentColumn ; mfid_CurrentColumn := scriptindex "CurrentColumn" ; vardef CurrentColumn = runscript mfid_CurrentColumn enddef ; -newinternal mfid_NOfColumns ; mfid_NOfColumns := scriptindex "NOfColumns" ; vardef NOfColumns = runscript mfid_NOfColumns enddef ; - -newinternal mfid_BaseLineSkip ; mfid_BaseLineSkip := scriptindex "BaseLineSkip" ; vardef BaseLineSkip = runscript mfid_BaseLineSkip enddef ; -newinternal mfid_LineHeight ; mfid_LineHeight := scriptindex "LineHeight" ; vardef LineHeight = runscript mfid_LineHeight enddef ; -newinternal mfid_BodyFontSize ; mfid_BodyFontSize := scriptindex "BodyFontSize" ; vardef BodyFontSize = runscript mfid_BodyFontSize enddef ; - -newinternal mfid_TopSkip ; mfid_TopSkip := scriptindex "TopSkip" ; vardef TopSkip = runscript mfid_TopSkip enddef ; -newinternal mfid_StrutHeight ; mfid_StrutHeight := scriptindex "StrutHeight" ; vardef StrutHeight = runscript mfid_StrutHeight enddef ; -newinternal mfid_StrutDepth ; mfid_StrutDepth := scriptindex "StrutDepth" ; vardef StrutDepth = runscript mfid_StrutDepth enddef ; - -newinternal mfid_CurrentWidth ; mfid_CurrentWidth := scriptindex "CurrentWidth" ; vardef CurrentWidth = runscript mfid_CurrentWidth enddef ; -newinternal mfid_CurrentHeight ; mfid_CurrentHeight := scriptindex "CurrentHeight" ; vardef CurrentHeight = runscript mfid_CurrentHeight enddef ; - -newinternal mfid_HSize ; mfid_HSize := scriptindex "HSize" ; vardef HSize = runscript mfid_HSize enddef ; -newinternal mfid_VSize ; mfid_VSize := scriptindex "VSize" ; vardef VSize = runscript mfid_VSize enddef ; - -newinternal mfid_EmWidth ; mfid_EmWidth := scriptindex "EmWidth" ; vardef EmWidth = runscript mfid_EmWidth enddef ; -newinternal mfid_ExHeight ; mfid_ExHeight := scriptindex "ExHeight" ; vardef ExHeight = runscript mfid_ExHeight enddef ; - -newinternal mfid_PageFraction ; mfid_PageFraction := scriptindex "PageFraction" ; vardef PageFraction = runscript mfid_PageFraction enddef ; - -newinternal mfid_SpineWidth ; mfid_SpineWidth := scriptindex "SpineWidth" ; vardef SpineWidth = runscript mfid_SpineWidth enddef ; -newinternal mfid_PaperBleed ; mfid_PaperBleed := scriptindex "PaperBleed" ; vardef PaperBleed = runscript mfid_PaperBleed enddef ; - -% mfid_CurrentLayout ; mfid_CurrentLayout := scriptindex "CurrentLayout" ; vardef CurrentLayout = runscript mfid_CurrentLayout enddef ; -newinternal mfid_OverlayWidth ; mfid_OverlayWidth := scriptindex "OverlayWidth" ; vardef OverlayWidth = runscript mfid_OverlayWidth enddef ; -newinternal mfid_OverlayHeight ; mfid_OverlayHeight := scriptindex "OverlayHeight" ; vardef OverlayHeight = runscript mfid_OverlayHeight enddef ; -newinternal mfid_OverlayDepth ; mfid_OverlayDepth := scriptindex "OverlayDepth" ; vardef OverlayDepth = runscript mfid_OverlayDepth enddef ; -newinternal mfid_OverlayLineWidth ; mfid_OverlayLineWidth := scriptindex "OverlayLineWidth" ; vardef OverlayLineWidth = runscript mfid_OverlayLineWidth enddef ; -newinternal mfid_OverlayOffset ; mfid_OverlayOffset := scriptindex "OverlayOffset" ; vardef OverlayOffset = runscript mfid_OverlayOffset enddef ; -newinternal mfid_OverlayRegion ; mfid_OverlayRegion := scriptindex "OverlayRegion" ; vardef OverlayRegion = runscript mfid_OverlayRegion enddef ; -% mfid_OverlayLineColor ; mfid_OverlayLineColor := scriptindex "OverlayLineColor ; vardef OverlayLineColor = runscript mfid_OverlayLineColor enddef ; -% mfid_OverlayColor ; mfid_OverlayColor := scriptindex "OverlayColor ; vardef OverlayColor = runscript mfid_OverlayColor enddef ; - -newinternal mfid_defaultcolormodel ; mfid_defaultcolormodel := scriptindex "defaultcolormodel" ; vardef defaultcolormodel = runscript mfid_defaultcolormodel enddef ; - -vardef LeftMarginWidth = if mfun_swapped and not OnRightPage : runscript mfid_RightMarginWidth else : runscript mfid_LeftMarginWidth fi enddef ; -vardef RightMarginWidth = if mfun_swapped and not OnRightPage : runscript mfid_LeftMarginWidth else : runscript mfid_RightMarginWidth fi enddef ; -vardef LeftMarginDistance = if mfun_swapped and not OnRightPage : runscript mfid_RightMarginDistance else : runscript mfid_LeftMarginDistance fi enddef ; -vardef RightMarginDistance = if mfun_swapped and not OnRightPage : runscript mfid_LeftMarginDistance else : runscript mfid_RightMarginDistance fi enddef ; - -vardef LeftEdgeWidth = if mfun_swapped and not OnRightPage : runscript mfid_RightEdgeWidth else : runscript mfid_LeftEdgeWidth fi enddef ; -vardef RightEdgeWidth = if mfun_swapped and not OnRightPage : runscript mfid_LeftEdgeWidth else : runscript mfid_RightEdgeWidth fi enddef ; -vardef LeftEdgeDistance = if mfun_swapped and not OnRightPage : runscript mfid_RightEdgeDistance else : runscript mfid_LeftEdgeDistance fi enddef ; -vardef RightEdgeDistance = if mfun_swapped and not OnRightPage : runscript mfid_LeftEdgeDistance else : runscript mfid_RightEdgeDistance fi enddef ; - -vardef BackSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi runscript mfid_BackSpace enddef ; -vardef CutSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi runscript mfid_CutSpace enddef ; - -% better use: - -vardef OuterMarginWidth = if not OnRightPage : runscript mfid_LeftMarginWidth else : runscript mfid_RightMarginWidth fi enddef ; -vardef InnerMarginWidth = if not OnRightPage : runscript mfid_RightMarginWidth else : runscript mfid_LeftMarginWidth fi enddef ; -vardef OuterMarginDistance = if not OnRightPage : runscript mfid_LeftMarginDistance else : runscript mfid_RightMarginDistance fi enddef ; -vardef InnerMarginDistance = if not OnRightPage : runscript mfid_RightMarginDistance else : runscript mfid_LeftMarginDistance fi enddef ; - -vardef OuterEdgeWidth = if not OnRightPage : runscript mfid_LeftEdgeWidth else : runscript mfid_RightEdgeWidth fi enddef ; -vardef InnerEdgeWidth = if not OnRightPage : runscript mfid_RightEdgeWidth else : runscript mfid_LeftEdgeWidth fi enddef ; -vardef OuterEdgeDistance = if not OnRightPage : runscript mfid_LeftEdgeDistance else : runscript mfid_RightEdgeDistance fi enddef ; -vardef InnerEdgeDistance = if not OnRightPage : runscript mfid_RightEdgeDistance else : runscript mfid_LeftEdgeDistance fi enddef ; - -vardef OuterSpaceWidth = if not OnRightPage : runscript mfid_BackSpace else : runscript mfid_CutSpace fi enddef ; -vardef InnerSpaceWidth = if not OnRightPage : runscript mfid_CutSpace else : runscript mfid_BackSpace fi enddef ; - -% indices - -vardef OuterMargin = if not OnRightPage : LeftMargin else : RightMargin fi enddef ; -vardef InnerMargin = if not OnRightPage : RightMargin else : LeftMargin fi enddef ; - -vardef OuterEdge = if not OnRightPage : LeftEdge else : RightEdge fi enddef ; -vardef InnerEdge = if not OnRightPage : Rightedge else : LeftEdge fi enddef ; - - diff --git a/metapost/context/base/mpiv/mp-lmtx.mpxl b/metapost/context/base/mpiv/mp-lmtx.mpxl deleted file mode 100644 index 1f70d0ac1..000000000 --- a/metapost/context/base/mpiv/mp-lmtx.mpxl +++ /dev/null @@ -1,2281 +0,0 @@ -%D \module -%D [ file=mp-luas.lmtx, -%D version=2019.06.23, -%D title=\CONTEXT\ \METAPOST\ graphics, -%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. - -% This is an experimental module where I test some new interface methods; -% for real advanced graphics use the luapost module. - -if known context_lmtx : endinput ; fi ; - -boolean context_lmtx ; context_lmtx := true ; - -presetparameters "text" [ - offset = 0, - strut = "auto", - style = "", - color = "", - text = "", - anchor = "", - format = "", - position = origin, - trace = false, - - background = "", % "color", - backgroundcolor = "gray", -] ; - -def lmt_text = applyparameters "text" "lmt_do_text" enddef ; - -vardef lmt_do_text = - image ( - pushparameters "text" ; - save style, anchor, txt, fmt, strt ; - string style, anchor, txt, fmt, strt, bgr ; - interim textextoffset := getparameter "offset" ; - style := getparameter "style" ; - anchor := getparameter "anchor" ; - strt := getparameter "strut" ; - fmt := getparameter "format" ; - txt := getparameter "text" ; - bgr := getparameter "background" ; - if fmt <> "" : - txt := "\formatone{" & fmt & "}{" & txt & "}" - fi ; - if strt = "yes" : - txt := "\strut " & txt ; - elseif strt = "auto" : - txt := "\setstrut\strut " & txt ; - fi ; - if style <> "" : - txt := "\style[" & style & "]{" & txt & "}" ; - fi ; - if getparameter "trace" : - txt := "\ruledhbox{\showstruts" & txt & "}" ; - fi ; - draw - if anchor = "" : thetextext else : scantokens("thetextext." & anchor) fi ( - txt, - getparameter "position" - ) - withcolor getparameter "color" ; - if bgr = "color" : - addbackground withcolor getparameter "backgroundcolor" ; - fi ; - popparameters ; - ) -enddef ; - -presetparameters "grid" [ - nx = 1, dx = 1, - ny = 1, dy = 1, -] ; - -def lmt_grid = applyparameters "grid" "lmt_do_grid" enddef ; - -vardef lmt_do_grid = - image ( - save nx; nx := getparameter "grid" "nx" ; - save ny; ny := getparameter "grid" "ny" ; - save dx; dx := getparameter "grid" "dx" ; - save dy; dy := getparameter "grid" "dy" ; - for i = 0 step dx until nx : - draw ((0,0) -- (0,ny)) shifted (i,0) ; - endfor ; - for i = 0 step dy until ny : - draw ((0,0) -- (nx,0)) shifted (0,i) ; - endfor ; - ) -enddef ; - -def lmt_axis = applyparameters "axis" "lmt_do_axis" enddef ; - -presetparameters "axis" [ - nx = 1, dx = 1, tx = 0, sx = 1, startx = 0, - ny = 1, dy = 1, ty = 0, sy = 1, starty = 0, - - samples = { }, - list = { }, - connect = false, - list = [ close = false ], - samplecolors = { "" }, - axiscolor = "", - textcolor = "", -] ; - -vardef lmt_do_axis = - image ( - - pushparameters "axis" ; - save nx, ny, dx, dy, tx, ty ; - save c, startx, starty ; string c ; - nx := getparameter "nx" ; - ny := getparameter "ny" ; - dx := getparameter "dx" ; - dy := getparameter "dy" ; - tx := getparameter "tx" ; - ty := getparameter "ty" ; - c := getparameter "axiscolor" ; - startx := getparameter "startx" ; - starty := getparameter "starty" ; - draw (startx,starty) -- (startx,ny) withcolor c ; - draw (startx,starty) -- (nx,starty) withcolor c ; - for i = startx step dx until nx : - if (i > startx) or (startx = 0) : - draw ((0,0) -- (0,-2)) shifted (i,starty) withcolor c ; - fi ; - endfor ; - for i = starty step dy until ny : - if (i > starty) or (starty = 0) : - draw ((0,0) -- (-2,0)) shifted (startx,i) withcolor c ; - fi ; - endfor ; - if tx <> 0 : - c := getparameter "textcolor" ; - for i = startx step tx until nx : - if (i > startx) or (startx = 0) : - draw - textext("\strut " & decimal (i)) ysized 2 shifted (i,-4+starty) - withcolor c; - fi ; - endfor ; - fi ; - if ty <> 0 : - c := getparameter "textcolor" ; - for i = starty step ty until ny : - if (i > starty) or (starty = 0) : - draw - textext.lft("\strut " & decimal (i)) ysized 2 shifted (-3+startx,i) - withcolor c; - fi ; - endfor ; - fi ; - - if (getparametercount "samples") > 0 : - if getparameter "connect" : - for s = 1 upto getparametercount "samples" : - c := getparameter "samplecolors" s ; - draw for i = 1 upto getparametercount "samples" s : - if (i > 1) : -- fi (i, getparameter "samples" s i) - endfor - withcolor c ; - endfor ; - else : - for s = 1 upto getparametercount "samples" : - c := getparameter "samplecolors" s ; - for i = 1 upto getparametercount "samples" s : - draw (i, getparameter "samples" s i) - withcolor c ; - endfor ; - endfor ; - fi ; - fi ; - - if (getparametercount "list") > 0 : - - save p, ts, a, d ; path p ; numeric ts ; pair a, d ; - - ts := (getparameter "sy") / 20 ; - - pushparameters "list" ; - for s = 1 upto getparametercount : - pushparameters s ; - - c := getparameter "color" ; - - % p := for i = 1 upto getparametercount "points": - % if (i > 1) : -- fi (getparameter "points" i) - % endfor - % if (getparameterdefault "close" false) : -- cycle fi ; - - % this can become: - - % p := if (getparameterdefault "close" false) : - % % getparameterpath "points" "--" true ; - % getparameterpath "points" true ; - % else : - % % getparameterpath "points" "--" false ; - % getparameterpath "points" ; - % fi ; - - % p := getparameterpath "points" if (getparameterdefault "close" false) : true fi ; - - p := getparameterpath "points" (getparameterdefault "close" false) ; - % p := getparameterpath "points" getparameterdefault "close" false ; - - draw p withcolor c ; - - pushparameters "labels" ; - if (getparametercount) > 0 : - for i = 1 upto getparametercount: - n := i - 1 ; - a := point n of p ; - d := direction n of p ; - draw - textext(getparametertext i true) - ysized ts - shifted (a + .5 * unitvector(d) rotated 90) ; - endfor ; - fi ; - popparameters ; - - pushparameters "texts" ; - if (getparametercount) > 0 : - for i = 1 upto getparametercount : - n := i + 0.5 ; - a := point n of p ; - d := direction n of p ; - draw textext.d(getparametertext i true) - if d < left : rotated 180 shifted (0,-5) else : shifted (0,5) fi - ysized ts - shifted a - rotatedaround(a,angle(d)) ; - endfor ; - fi ; - popparameters ; - - popparameters ; - endfor ; - popparameters ; - fi ; - - popparameters ; - - ) - xyscaled(getparameter "axis" "sx",getparameter "axis" "sy") -enddef ; - -presetparameters "outline" [ - text = "", - kind = "draw", - fillcolor = "", - drawcolor = "", - rulethickness = 1/10, - align = "", - style = "", - width = 0, -] ; - -def lmt_outline = applyparameters "outline" "lmt_do_outline" enddef ; - -vardef lmt_do_outline = - image ( normaldraw image ( - save kind ; string kind ; kind := getparameter "outline" "kind" ; - save align ; string align ; align := getparameter "outline" "align" ; - save style ; string style ; style := getparameter "outline" "style" ; - save width ; numeric width ; width := getparameter "outline" "width" ; - if kind = "draw" : - kind := "d" ; - elseif kind = "fill" : - kind := "f" ; - elseif kind = "both" : - kind := "b" ; - elseif kind = "reverse" : - kind := "r" ; - elseif kind = "fillup" : - kind := "u" ; - fi ; - currentoutlinetext := currentoutlinetext + 1 ; - lua.mp.mf_outline_text( - currentoutlinetext, - if align = "" : - getparameter "outline" "text", - else : - "\framed[align={" & align & "}" - if width > 0 : - & ",width=" & decimal width & "bp" - fi - if style <> "" : - & ",foregroundstyle={" & style & "}" - fi - & ",offset=none,frame=off]{" - & (getparameter "outline" "text") - & "}", - fi, - kind - ) ; - save currentpen; pen currentpen ; - pickup pencircle scaled getparameter "outline" "rulethickness" ; - if kind = "f" : - mfun_do_outline_text_set_f ( - withcolor getparameter "outline" "fillcolor" - ); - elseif kind = "d" : - mfun_do_outline_text_set_d ( - withcolor getparameter "outline" "drawcolor" - ); - elseif kind = "b" : - mfun_do_outline_text_set_b ( - withcolor getparameter "outline" "fillcolor" - ) ( - withcolor getparameter "outline" "drawcolor" - ); - elseif kind = "u" : - mfun_do_outline_text_set_u ( - withcolor getparameter "outline" "fillcolor" - ); - elseif kind = "r" : - mfun_do_outline_text_set_r ( - withcolor getparameter "outline" "drawcolor" - ) ( - withcolor getparameter "outline" "fillcolor" - ) ; - elseif kind = "p" : - mfun_do_outline_text_set_p ; - else : - mfun_do_outline_text_set_n ( - % what to use here - ); - fi ; - lua.mp.mf_get_outline_text(currentoutlinetext) ; - ) ) -enddef ; - -presetparameters "followtext" [ - text = "", - spread = true, - trace = false, - reverse = false, - autoscaleup = "no", - autoscaledown = "no", - path = (fullcircle), -] ; - -def lmt_followtext = applyparameters "followtext" "lmt_do_followtext" enddef ; - -vardef lmt_do_followtext = - image ( - pushparameters "followtext" ; - save s_u ; string s_u ; s_u := getparameter "autoscaleup" ; - save s_d ; string s_d ; s_d := getparameter "autoscaledown" ; - save followtextalternative ; followtextalternative := if getparameter "spread" : 1 else : 0 fi ; - save tracingfollowtext ; tracingfollowtext := if getparameter "trace" : 1 else : 0 fi ; - save autoscaleupfollowtext ; autoscaleupfollowtext := if s_u = "yes" : 1 elseif s_u = "max" : 2 else : 0 fi ; - save autoscaledownfollowtext ; autoscaledownfollowtext := if s_d = "yes" : 1 elseif s_d = "max" : 2 else : 0 fi ; - draw followtext ( - if (getparameter "reverse") : reverse fi (getparameter "path"), - getparameter "text" - ) ; - popparameters ; - ) -enddef ; - -presetparameters "arrow" [ - path = origin, - % pen = ..., - kind = "fill", - dimple = 1/5, - scale = 3/4, - penscale = 3, - length = 4, - angle = 45, - location = "end", % middle both - alternative = "normal", % dimpled curved - percentage = 50, - headonly = false, -] ; - -def lmt_arrow = applyparameters "arrow" "lmt_do_arrow" enddef ; - -vardef lmt_do_arrow = - image ( - pushparameters "arrow" ; - save a ; string a ; a := getparameter "alternative" ; - save l ; string l ; l := getparameter "location" ; - save k ; string k ; k := getparameter "kind" ; - save p ; path p ; p := getparameter "path" ; - save ahvariant ; ahvariant := if a = "dimpled" : 1 elseif a = "curved" : 2 else : 0 fi ; - save ahdimple ; ahdimple := getparameter "dimple" ; - save ahscale ; ahscale := getparameter "scale" ; - save ahangle ; ahangle := getparameter "angle" ; - save ahlength ; ahlength := getparameter "length" ; - if not getparameter "headonly" : - draw p ; - fi ; - if hasparameter "pen" : - % a cheat: we should have a type check in lua - if hasoption "pen" "auto" : - ahlength := (getparameter "penscale") * boundingradius(currentpen) ; - else : - ahlength := (getparameter "penscale") * boundingradius(getparameterpen "pen") ; - fi ; - fi ; - if k = "draw" : draw elseif k = "both" : filldraw else : fill fi - if l = "middle" : - midarrowhead p ; - elseif l = "percentage" : - arrowheadonpath (p, (getparameter "percentage")/100) ; - elseif l = "both" : - arrowhead p ; - if k = "draw" : draw elseif k = "both" : filldraw else : fill fi - arrowhead reverse p ; - else : - arrowhead p ; - fi ; - popparameters ; - ) -enddef ; - -% from dum - -presetparameters "placeholder" [ - color = "red", - width = 1, - height = 1, - reduction = 0, - alternative = "circle", -] ; - -def lmt_placeholder = applyparameters "placeholder" "lmt_do_placeholder" enddef ; - -def lmt_do_placeholder = - begingroup ; - pushparameters "placeholder" ; - save w, h, d, r, p, c, b, s, q, a ; - numeric w, h, d, r ; path p ; string s, a ; - s := getparameter "color" ; - w := getparameter "width" ; - h := getparameter "height" ; - r := getparameter "reduction" ; - a := getparameter "alternative" ; - d := max(w,h) ; - if cmykcolor resolvedcolor(s) : - cmykcolor c, b ; b := (0,0,0,0) - else : - color c, b ; b := (1,1,1) - fi ; - c := resolvedcolor(s) ; - p := unitsquare xyscaled (w,h) ; - fill p withcolor r[.5c,b] ; - if a = "square" : - vardef q = fullsquare enddef ; - elseif a = "triangle" : - vardef q = fulltriangle rotated (90 * round(uniformdeviate(4))) enddef ; - else : - vardef q = fullcircle enddef ; - fi ; - for i := 1 upto 60 : - fill q - scaled (d/5 randomized (d/5)) - shifted (center p randomized (d)) - withcolor r[c randomized(.3,.9),b] ; - endfor ; - clip currentpicture to p ; - popparameters ; - endgroup ; -enddef ; - -% maybe: - -vardef lmt_connected(text t) = - save p ; path p ; - p := origin t ; - subpath (1,length(p)) of p -enddef ; - -def lmt_connection expr t = - -- t -enddef ; - -% also (todo) - -% % draw lmt_path [ -% % points = [ color = "darkred", size = 6 ], -% % controls = [ color = "darkgreen", size = 4 ], -% % lines = [ color = "darkgray", size = 1 ], -% % shape = [ color = "middlegray", size = 8 ], -% % labels = [ ], -% % path = ((1cm,1cm) -- (1.5cm,1.5cm) .. (2cm,0cm) .. cycle) -% % ] ; -% -% presetparameters "path" [ -% labels = [ -% color = "", -% size = 1 -% ], -% controls = [ -% color = "black", -% size = 2.5 -% ], -% lines = [ -% color = "middlegray", -% size = 1 -% ], -% points = [ -% color = "black", -% size = 4 -% ], -% path = [ -% color = "lightgray", -% size = 5, -% path = origin -% ] -% ] ; -% -% def lmt_path = applyparameters "path" "lmt_do_path" enddef ; -% -% vardef lmt_do_path = -% image ( -% % This one is not that efficient ... we can better inline the drawing routines here, but -% % it's just an interfacing test after all. -% if hasparameter "path" "path" : -% save p ; path p ; p := getparameter "path" "path" ; -% drawpath p -% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "shape" "size" "*") -% withcolor getparameterdefault "path" "shape" "color" "*" -% ; -% if hasparameter "path" "controls" : -% drawcontrollines p -% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "lines" "size" "*" ) -% withcolor getparameterdefault "path" "lines" "color" "*" -% ; -% drawcontrolpoints p -% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "controls" "size" "*") -% withcolor getparameterdefault "path" "controls" "color" "*" -% ; -% fi ; -% if hasparameter "path" "points" : -% drawpoints p -% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "points" "size" "*") -% withcolor getparameterdefault "path" "points" "color" "*" -% ; -% if hasparameter "path" "labels" : -% drawpointlabels p -% withcolor getparameterdefault "path" "labels" "color" "*" -% ; -% fi ; -% fi ; -% fi ; -% ) -% enddef ; - -% Here we use nodraw and dodraw to create efficient axis ticks. Yet another demo -% of coding. - -presetparameters "function" [ - sx = 1mm, - sy = 1mm, - offset = 0, - xmin = 1, - xmax = 1, - xstep = 1, - xsmall = 0, - xlarge = 0, - xlabels = "no", - xticks = "bottom", % top bottom middle - xcaption = "", - ymin = 1, - ymax = 1, - ystep = 1, - ysmall = 0, - ylarge = 0, - % xfirst = 0, - % xlast = 0, - % yfirst = 0, - % ylast = 0, - ylabels = "no", - yticks = "left", % left right middle - ycaption = "", - code = "", - close = false, - shape = "curve", - fillcolor = "", - drawsize = 1, - drawcolor = "", - frame = "", % yes ticks - linewidth = .05mm, - pointsymbol = "", - pointsize = 2, - pointcolor = "", - xarrow = "", - yarrow = "", - reverse = false, -] ; - -def lmt_function = applyparameters "function" "lmt_do_function" enddef ; - -vardef lmt_do_function_p(expr xmin, xmax, xstep, code, shape, close, fcolor, dsize, dcolor, psymbol, psize, pcolor) = - save p, q ; path p, q ; - p := lua.mp.lmt_function_x(xmin,xmax,xstep,code,shape) ; - if close : - q := (xmin,0) -- p -- (xmax,0) -- cycle ; - fill q withcolor fcolor ; - else : - draw p withpen currentpen scaled dsize withcolor dcolor - ; - fi ; - if psize > 0 : - if psymbol = "dot" : - draw image ( - for i = 0 upto length(p) : - draw point i of p ; - endfor ; - ) withpen currentpen scaled psize withcolor pcolor ; - fi ; - fi ; -enddef ; - -vardef lmt_do_function = - image ( - pushparameters "function" ; - save sx, sy, lw, tl, tr, ts, tt, currentpen ; transform tr, tt ; pen currentpen ; - sx := getparameter "sx" ; - sy := getparameter "sy" ; - lw := getparameter "linewidth" ; - tl := 1/20 ; % tick length - ts := 1/10 ; % text scale - tr := identity xyscaled(10/sx,10/sy) ; - tt := identity xyscaled(ts/sx,ts/sy) ; - pickup pencircle xyscaled(lw/sx,lw/sy) ; - draw image ( - save xmin, xmax, xstep, xsmall, xlarge, ymin, ymax, ystep, ysmall, ylarge, p ; - save code, option, txl, txs, tyl, tys, swap ; - string code, option ; - path txl, txs, tyl, tys ; boolean swap ; - picture p ; - - xmin := getparameter "xmin" ; - xmax := getparameter "xmax" ; - xstep := getparameter "xstep" ; - xsmall := getparameter "xsmall" ; - xlarge := getparameter "xlarge" ; - ymin := getparameter "ymin" ; - ymax := getparameter "ymax" ; - ystep := getparameter "ystep" ; - ysmall := getparameter "ysmall" ; - ylarge := getparameter "ylarge" ; - code := getparameter "code" ; - swap := getparameter "reverse" ; - - p := image ( - - if (getparametercount "functions") > 0 : - for s = 1 upto getparametercount "functions" : - pushparameters "functions" s ; - lmt_do_function_p ( - getparameterdefault "xmin", - getparameterdefault "xmax", - getparameterdefault "xstep", - getparameterdefault "code", - getparameterdefault "shape", - getparameterdefault "close", - getparameterdefault "fillcolor", - getparameterdefault "drawsize", - getparameterdefault "drawcolor", - getparameterdefault "pointsymbol", - getparameterdefault "pointsize", - getparameterdefault "pointcolor" - ) ; - popparameters ; - endfor ; - elseif code <> "" : - lmt_do_function_p ( - getparameter "xmin", - getparameter "xmax", - getparameter "xstep", - getparameter "code", - getparameter "shape", - getparameter "close", - getparameter "fillcolor", - getparameter "drawsize", - getparameter "drawcolor", - getparameter "pointsymbol", - getparameter "pointsize", - getparameter "pointcolor" - ) ; - fi ; - ) ; - - if not swap : draw p fi ; - - option := getparameter "xticks" ; - if option = "top" : - txs := (0,0) -- (0,tl) ; - elseif option = "bottom" : - txs := (0,-tl) -- (0,0) ; - else : - txs := (0,-tl) -- (0,tl) ; - fi ; - - option := getparameter "yticks" ; - if option = "left" : - tys := (-tl,0) -- (0,0) ; - elseif option = "right" : - tys := (0,0) -- (tl,0) ; - else : - tys := (-tl,0) -- (tl,0) ; - fi ; - - txs := txs transformed tr ; - tys := tys transformed tr ; - txl := txs scaled 2 ; - tyl := tys scaled 2 ; - - % this arrow head scaling is for Alan to sort out ... - - xmin := getparameterdefault "xfirst" xmin ; - xmax := getparameterdefault "xlast" xmax ; - ymin := getparameterdefault "yfirst" ymin ; - ymax := getparameterdefault "ylast" ymax ; - - if hasoption "frame" "ticks,sticks" : - if xsmall > 0 : - if hasoption "frame" "horizontal" : - for i = ymin step ((ymax-ymin)/ysmall) until ymax : - draw (xmin,i) -- (xmax,i) ; - endfor ; - dodraw (xmin,ymin) ; % flush snippets - fi ; - fi ; - if ysmall > 0 : - if hasoption "frame" "vertical" : - for i = xmin step ((xmax-xmin)/xsmall) until xmax : - draw (i,ymin) -- (i,ymax) ; - endfor ; - dodraw (xmin,ymin) ; % flush snippets - fi ; - fi ; - fi ; - - option := getparameter "xarrow" ; - if option = "yes" : - save ahlength ; ahlength := tl ; - % save ahangle ; ahangle := 100/sy ; - drawarrow (xmin,0) -- (xmax,0) ; - else : - draw (xmin,0) -- (xmax,0) ; - fi ; - - option := getparameter "yarrow" ; - if option = "yes" : - save ahlength ; ahlength := tl ; - % save ahangle ; ahangle := 100/sx ; - drawarrow (xmin,ymin) -- (xmin,ymax) ; - else : - draw (xmin,ymin) -- (xmin,ymax) ; - fi ; - - if hasoption "frame" "yes" : - draw (xmin,ymin) -- (xmax,ymin) -- (xmax,ymax) -- (xmin,ymax) -- cycle ; - fi ; - - if hasoption "frame" "ticks,sticks" : - if xsmall > 0 : - if hasoption "frame" "horizontal" : - for i = ymin step ((ymax-ymin)/ysmall) until ymax : - draw (xmin,i) -- (xmax,i) ; - endfor ; - fi ; - if hasoption "frame" "bottom" : - txs := ((0,0) -- (0,tl)) if hasoption "frame" "sticks" : rotated 180 fi ; - txs := txs transformed tr ; - for i = xmin step ((xmax-xmin)/xsmall) until xmax : - nodraw txs shifted (i,ymin) ; - endfor ; - fi ; - if hasoption "frame" "top" : - txs := (0,0) -- (0,-tl) if hasoption "frame" "sticks" : rotated 180 fi ; - txs := txs transformed tr ; - for i = xmin step ((xmax-xmin)/xsmall) until xmax : - nodraw txs shifted (i,ymax) ; - endfor ; - fi ; - dodraw (xmin,ymin) ; % flush snippets - fi ; - if ysmall > 0 : - if hasoption "frame" "vertical" : - for i = xmin step ((xmax-xmin)/xsmall) until xmax : - draw (i,ymin) -- (i,ymax) ; - endfor ; - fi ; - if hasoption "frame" "left" : - tys := (0,0) -- (tl,0) if hasoption "frame" "sticks" : rotated 180 fi ; - tys := tys transformed tr ; - for i = ymin step ((ymax-ymin)/ysmall) until ymax : - nodraw tys shifted (xmin,i) ; - endfor ; - fi ; - if hasoption "frame" "right" : - tys := (0,0) -- (-tl,0) if hasoption "frame" "sticks" : rotated 180 fi ; - tys := tys transformed tr ; - for i = ymin step ((ymax-ymin)/ysmall) until ymax : - nodraw tys shifted (xmax,i) ; - endfor ; - fi ; - dodraw (xmin,ymin) ; % flush snippets - fi ; - fi ; - - if xsmall > 0 : - for i = xmin step xsmall until xmax : - nodraw txs shifted (i,0) ; - endfor ; - fi ; - - if xlarge > 0 : - for i = xmin step xlarge until xmax : - nodraw txl shifted (i,0) ; - endfor ; - dodraw (xmin,0) ; % flush snippets - elseif xsmall > 0 : - dodraw (xmin,0) ; % flush snippets - fi ; - - if ysmall > 0 : - for i = ymin step ysmall until ymax : - nodraw tys shifted (xmin,i) ; - endfor ; - fi ; - - if ylarge > 0 : - for i = ymin step ylarge until ymax : - nodraw tyl shifted (xmin,i) ; - endfor ; - dodraw (xmin,ymin) ; % flush snippets - elseif ysmall > 0 : - dodraw (xmin,ymin) ; % flush snippets - fi ; - - if swap : draw p fi ; - - if xlarge > 0 : - option := getparameter "xlabels" ; - if option <> "no" : - for i = xmin step xlarge until xmax : - if ((i <> 0) and ((option <> "nolimits") or ((i > xmin) and (i < xmax)))) : - draw textext.bot(decimal i) transformed tt - shifted (i,1.25*(ypart point 0 of txl)) ; - fi ; - endfor ; - fi ; - fi ; - - if ylarge > 0 : - option := getparameter "ylabels" ; - if option <> "no" : - for i = ymin step ylarge until ymax : - if ((i <> 0) and ((option <> "nolimits") or ((i > ymin) and (i < ymax)))) : - draw textext.lft(decimal i) transformed tt - shifted (xmin+1.25*(xpart point 0 of tyl),i) ; - fi ; - endfor ; - fi ; - fi ; - - option := getparameter "xcaption" ; - if (option <> "") : - draw textext.bot(option) transformed tt - shifted (xmin,-tl) - shifted center bottomboundary currentpicture ; - fi ; - - option := getparameter "ycaption" ; - if (option <> "") : - draw textext.lft(option) transformed tt - shifted (xmin-tl,0) - shifted center leftboundary currentpicture ; - fi ; - ) - - xyscaled(sx,sy) ; - - setbounds currentpicture to - boundingbox currentpicture - enlarged (getparameter "offset") ; - - popparameters ; - ) -enddef ; - -% Don't use this one! - -presetparameters "mesh" [ - trace = false, - auto = false, - step = 0.05, - % box = ... - % paths = { ..., ..., ... } -] ; - -def lmt_mesh = applyparameters "mesh" "lmt_do_mesh" enddef ; - -vardef lmt_do_mesh = - image ( - save p, b ; path p, b ; - pushparameters "mesh" ; - if getparameter "auto" : - b := if hasparameter "box" : getparameter "box" else : OverlayBox fi ; - for i=1 upto getparametercount "paths" : - p := getparameter "paths" i ; - p := meshed(p if not cycle p : -- cycle fi,b,getparameter "step") ; - if getparameter "trace" : - draw p ; - fi ; - runscript("mp.lmt_mesh_update()") i p ; - endfor ; - elseif getparameter "trace" : - for i=1 upto getparametercount "paths" : - p := getparameter "paths" i ; - draw p if not cycle p : -- cycle fi ; - endfor ; - fi ; - popparameters ; - runscript("mp.lmt_mesh_set()") ; - ) -enddef ; - -vardef mfun_meshed_clipped(expr pat, box, pct) = - pp := point (arctime pct of pat) of pat ; - if (ypart pp <= lly) or (ypart pp >= ury) or (xpart pp <= llx) or (xpart pp >= urx) : - (cp -- pp) intersection_point bb - else : - pp - fi -enddef ; - -vardef mfun_meshed_clipped(expr pat, box, pct) = - pp := point (arctime pct of pat) of pat ; - if ypart pp <= lly : - if xpart pp <= llx : - (llx, lly) - elseif xpart pp >= urx : - (urx, lly) - else : - (xpart pp, lly) - fi - elseif ypart pp >= ury : - if xpart pp <= llx : - (llx, ury) - elseif xpart pp >= urx : - (urx, ury) - else : - (xpart pp, ury) - fi - elseif xpart pp <= llx : - (llx, ypart pp) - elseif xpart pp >= urx : - (urx, ypart pp) - else : - pp - fi -enddef ; - -vardef meshed(expr pth, box, stp) = - begingroup - save cb, cp, llx, lly, urx, ury, pp, lp, bb ; pair cb, cp, pp ; path bb ; - bb := box enlarged -1/10; - cb := center bb ; - cp := center pth ; - llx := xpart llcorner bb; - lly := ypart llcorner bb; - urx := xpart urcorner bb; - ury := ypart urcorner bb; - lp := arclength pth ; - for i=stp step stp until 1+stp/2 : - cp -- - mfun_meshed_clipped(pth,bb,lp*(i-stp)) -- - mfun_meshed_clipped(pth,bb,lp*(i )) -- - cp -- - endfor cycle - endgroup -enddef ; - -vardef OverlayMesh(expr p, s) = - lmt_mesh [ paths = { meshed(p,OverlayBox,s) } ] -enddef ; - -% charts - -presetparameters "chart" [ - originsize = 1mm, - trace = false, - showlabels = true, - center = false, - - samples = { }, - - cumulative = false, - percentage = false, - maximum = 0, - distance = 1mm, - - % labels = { }, - labelstyle = "", - labelformat = "", - % labelstrut = "auto", - % labelanchor = "", - % labeloffset = 0, - labelfraction = 0.8, - labelcolor = "", - - backgroundcolor = "", - drawcolor = "white", - fillcolors = { % use color palet - "darkred", "darkgreen", "darkblue", - "darkyellow", "darkmagenta", "darkcyan", - "darkgray" - }, - colormode = "global", - - linewidth = .25mm, - - legendcolor = "", - legendstyle = "", - legend = { }, -] ; - -presetparameters "chart:circle" "chart" [ - height = 5cm, - width = 5mm, - labelanchor = "", - labeloffset = 0, - labelstrut = "no", -] ; - -presetparameters "chart:histogram" "chart" [ - height = 5cm, - width = 5mm, - labelanchor = "bot", - labeloffset = 1mm, - labelstrut = "auto", -] ; - -presetparameters "chart:bar" "chart" [ - height = 5mm, - width = 5cm, - labelanchor = "lft", - labeloffset = 1mm, - labelstrut = "no", -] ; - -def lmt_chart_circle = applyparameters "chart:circle" "lmt_do_chart_circle" enddef ; -def lmt_chart_histogram = applyparameters "chart:histogram" "lmt_do_chart_histogram" enddef ; -def lmt_chart_bar = applyparameters "chart:bar" "lmt_do_chart_bar" enddef ; - -def lmt_do_chart_start (expr what) = - pushparameters what ; - save width, height, distance, linewidth, labelgap, labelfraction, value, nofsamples, nofsamplesets ; - save fillcolor, drawcolor, labelcolor, labelstyle, labelformat, labelstrut, labelanchor, colormode ; - string fillcolor, drawcolor, labelcolor, labelstyle, labelformat, labelstrut, labelanchor, colormode ; - height := getparameter "height" ; - width := getparameter "width" ; - distance := getparameter "distance" ; - linewidth := getparameter "linewidth" ; - drawcolor := getparameter "drawcolor" ; - colormode := getparameter "colormode" ; - labelcolor := getparameter "labelcolor" ; - labelgap := getparameter "labeloffset" ; - labelstyle := getparameter "labelstyle" ; - labelformat := getparameter "labelformat" ; - labelstrut := getparameter "labelstrut" ; - labelanchor := getparameter "labelanchor" ; - labelfraction := getparameter "labelfraction" ; - nofsamplesets := getparametercount "samples" ; - nofsamples := getmaxparametercount "samples" ; -enddef ; - -def lmt_do_chart_stop = - if getparameter "center" : - currentpicture := currentpicture shifted - center currentpicture ; - fi - if (getparameter "backgroundcolor") <> "" : - addbackground withcolor getparameter "backgroundcolor" ; - fi - if getparameter "trace" : - save b ; path b ; b := boundingbox currentpicture ; - draw image ( - draw fullcircle scaled 1mm ; - draw b - ) - dashed evenly scaled 1/4 - withpen pencircle scaled .125mm - withcolor "darkgray" ; - fi - popparameters ; -enddef ; - -vardef lmt_do_chart_text(expr s, i, value) = - lmt_text [ - style = labelstyle, - format = labelformat, - strut = labelstrut, - anchor = labelanchor, - offset = labelgap, - color = labelcolor, - text = (getparameterdefault "labels" s i (decimal value)) - background = "", - ] -enddef ; - -def lmt_do_chart_legend = - n := getparametercount "legend" ; - if n > 0 : - save dx, dy, p, l, w, o, d, ddy ; picture l ; - dx := xpart urcorner currentpicture + EmWidth ; - dy := ypart urcorner currentpicture ; - labelcolor := getparameter "legendcolor" ; - labelstyle := getparameter "legendstyle" ; - w := 2EmWidth ; - o := .25EmWidth ; - d := ExHeight ; - ddy := .8LineHeight ; - for i=1 upto n : - dy := dy - ddy ; - l := lmt_text [ - text = getparameter "legend" i, - anchor = "rt" - style = labelstyle, - color = labelcolor, - background = "", - ] ; - fill leftboundary l rightenlarged w - shifted (dx,dy+d) - withcolor getparameter "fillcolors" i ; - draw l - shifted (dx+w+o,dy+d) ; - endfor ; - fi ; -enddef ; - -vardef lmt_do_chart_circle = - image ( - lmt_do_chart_start("chart:circle") ; - if (nofsamplesets > 0) and (nofsamples > 0) : - nofsamplesets := 1 ; - save p, r, s, first, last, total, factor, n, percentage ; - path p, r, s[] ; boolean percentage ; - percentage := getparameter "percentage" ; - total := 0 ; - for i = 1 upto nofsamples : - total := total + getparameter "samples" (1) i ; % () is needed else 1i - endfor ; - factor := 100/total ; - first := 0 ; - p := fullcircle ysized (height) ; - r := origin -- (2*height,0) ; - for i = 1 upto nofsamples : - fillcolor := getparameter "fillcolors" i ; - value := (getparameter "samples" (1) i) * factor ; - last := first + (360 / 100) * value ; - s[i] := ((p cutbefore (r rotated first)) cutafter (r rotated last)) ; - fill origin -- s[i] -- cycle withcolor fillcolor ; - first := last ; - endfor ; - if linewidth > 0 : - if drawcolor = "" : - drawcolor := backgroundcolor ; - fi ; - for i = 1 upto nofsamples : - interim linecap := butt ; - draw origin -- (point 0 of s[i]) withpen pencircle scaled linewidth withcolor drawcolor ; - draw origin -- (point length(s[i]) of s[i]) withpen pencircle scaled linewidth withcolor drawcolor ; - endfor ; - fi ; - if getparameter "showlabels" : - first := 0 ; - for i = 1 upto nofsamples : - value := getparameter "samples" (1) i ; - last := first + (360/100) * value * factor ; - draw lmt_do_chart_text (s,i,value) - shifted ((labelfraction*(height/2),0) rotated ((first+last)/2)) ; - first := last ; - endfor ; - fi ; - lmt_do_chart_legend ; - n := getparameter "originsize" ; - if n > 0 : - fill fullcircle scaled n withcolor "white" ; - fi ; - fi ; - lmt_do_chart_stop ; - ) -enddef ; - -vardef lmt_do_chart_histogram = - image ( - lmt_do_chart_start("chart:histogram") ; - if (nofsamplesets > 0) and (nofsamples > 0) : - save value, maximum, cumulative, maxwidth ; boolean cumulative ; - maximum := getparameter "maximum" ; - cumulative := getparameter "cumulative" ; - if labelanchor = "center" : - labelanchor := "vcenter" ; - fi ; - if maximum = 0 : - for s = 1 upto nofsamplesets : - for i = 1 upto nofsamples : - value := getparameter "samples" s i ; - maximum := if cumulative : - maximum + value ; - else : - max(maximum,value) ; - fi ; - endfor ; - endfor ; - fi ; - if nofsamplesets = 1 : - distance := 0 ; - fi ; - maxwidth := nofsamplesets * nofsamples * width + (nofsamples - 1)* distance ; - value := 0 ; - for s = 1 upto nofsamplesets : - for i = 1 upto nofsamples : - value := if cumulative : value + fi (getparameter "samples" s i) * height / maximum ; - fill unitsquare xyscaled (width,value) - if linewidth > 0 : - if i > 1 : leftenlarged (-linewidth/2) fi - if i < nofsamples : rightenlarged (-linewidth/2) fi - fi - shifted (nofsamplesets*(i-1)*width+(s-1)*width+(i-1)*distance,0) - withcolor getparameter "fillcolors" if colormode = "local" : s else : i fi ; - endfor ; - endfor ; - setbounds currentpicture to unitsquare xyscaled (maxwidth,height) ; - for s = 1 upto nofsamplesets : - if getparameter "showlabels" : - for i = 1 upto nofsamples : - draw lmt_do_chart_text (s,i,getparameter "samples" s i) - shifted (nofsamplesets*((i-1)*width)+width/2+(s-1)*width+(i-1)*distance,0) ; - endfor ; - fi ; - endfor ; - lmt_do_chart_legend ; - fi ; - lmt_do_chart_stop ; - ) -enddef ; - -vardef lmt_do_chart_bar = - - image ( - lmt_do_chart_start("chart:bar") ; - if (nofsamplesets > 0) and (nofsamples > 0) : - save value, maximum, cumulative, maxheight ; boolean cumulative ; - maximum := getparameter "maximum" ; - cumulative := getparameter "cumulative" ; - if labelanchor = "center" : - labelanchor := "hcenter" ; - fi ; - if maximum = 0 : - for s = 1 upto nofsamplesets : - for i = 1 upto nofsamples : - value := getparameter "samples" s i ; - maximum := if cumulative : maximum + value else : max(maximum,value) fi ; - endfor ; - endfor ; - fi ; - if nofsamplesets = 1 : - distance := 0 ; - fi ; - maxheight := nofsamplesets * nofsamples * height + (nofsamples - 1)* distance ; - for s = 1 upto nofsamplesets : - value := 0 ; - for i = 1 upto nofsamples : - value := if cumulative : value + fi (getparameter "samples" s i) * width / maximum ; - fill unitsquare xyscaled (value,height) - if linewidth > 0 : - if i > 1 : topenlarged (-linewidth/2) fi - if i < nofsamples : bottomenlarged (-linewidth/2) fi - fi - shifted (0,maxheight-nofsamplesets*i*height+(s-1)*height-(i-1)*distance) - withcolor getparameter "fillcolors" if colormode = "local" : s else : i fi ; - endfor ; - endfor ; - setbounds currentpicture to unitsquare xyscaled (width,maxheight) ; - if getparameter "showlabels" : - for s = 1 upto nofsamplesets : - for i = 1 upto nofsamples : - draw lmt_do_chart_text (s,i,getparameter "samples" s i) - shifted (0,maxheight-nofsamplesets*(i*height)+height/2+(s-1)*height-(i-1)*distance) ; - endfor ; - endfor ; - fi ; - lmt_do_chart_legend ; - fi ; - lmt_do_chart_stop ; - ) -enddef ; - -%D This one is more complex than needed but I want to trace so I need all those -%D variables. - -presetparameters "shade" [ - alternative = "circular", - path = origin -- cycle, - trace = false - - % alternative = "circular" | "linear" - % domain = { a, b } - % radius = a | { a, b } - % factor = a - % origin = (a,b) | { (a,b), {c, d) } - % vector = { a, b } - % colors = { a, b } - % center = a | { a, b } - % direction = "up" | "down" | "left" | "right" | { a, b } - -] ; - -% TODO: pass colors as strings - -def lmt_shade = applyparameters "shade" "lmt_do_shade" enddef ; - -vardef lmt_do_shade = - image ( - pushparameters "shade" ; - - save domain_min, domain_max, radius_a, radius_b, factor ; - save color_a, color_b, center_a, center_b, alternative, s ; - string color_a, color_b, alternative, s ; pair center_a, center_b ; - - alternative := getparameter "alternative" ; - - mfun_with_shade_method_analyze(getparameter "path") ; - - domain_min := 0 ; - domain_max := 1 ; - - color_a := "white" ; - color_b := "black" ; - - if alternative = "circular" : - center_a := center mfun_shade_path ; - center_b := center_a ; - radius_a := 0 ; - radius_b := mfun_max_radius(mfun_shade_path) ; - factor := 1.2 ; - else : - center_a := llcorner mfun_shade_path ; - center_b := urcorner mfun_shade_path ; - radius_a := 0 ; - radius_b := 0 ; - factor := 0; - fi ; - - if hasparameter "domain" : - domain_min := getparameter "domain" 1 ; - domain_max := getparameter "domain" 2 ; - fi - if hasparameter "radius" : - if numeric getparameter "radius" : - radius_a := 0 ; - radius_b := getparameter "radius" ; - else : - radius_a := getparameter "radius" 1 ; - radius_b := getparameter "radius" 2 ; - fi ; - factor := 1 ; - fi - if hasparameter "factor" : - factor := getparameter "factor" ; - fi - if hasparameter "origin" : - if pair getparameter "origin" : - center_a := getparameter "origin" ; - center_b := center_b ; - else : - center_a := getparameter "origin" 1 ; - center_b := getparameter "origin" 2 ; - fi ; - fi - if hasparameter "colors" : - color_a := getparameter "colors" 1 ; - color_b := getparameter "colors" 2 ; - fi - if hasparameter "direction" : - save a, b, bb ; path bb ; - bb := boundingbox(mfun_shade_path) ; - a := b := -1 ; - if string getparameter "direction" : - s := getparameter "direction" ; - if s = "up" : - p_a := xpart shadedup ; - p_b := ypart shadedup ; - elseif s = "down" : - p_a := xpart shadeddown ; - p_b := ypart shadeddown ; - elseif s = "left" : - p_a := xpart shadedleft ; - p_b := ypart shadedleft ; - elseif s = "right" : - p_a := xpart shadedright ; - p_b := ypart shadedright ; - fi - else : - p_a := getparameter "direction" 1 ; - p_a := getparameter "direction" 2 ; - fi - if p_a >= 0 : - center_a := point p_a of bb ; - fi - if p_b >= 0 : - center_b := point p_b of bb ; - fi - fi ; - if hasparameter "center" : - save cx, cy ; - if numeric getparameter "center" : - cx := getparameter "center" ; - cx := cy ; - % elseif pair getparameter "center" : - % cx := xpart getparameter "center" ; - % cy := ypart getparameter "center" ; - else : - cx := getparameter "center" 1 ; - cy := getparameter "center" 2 ; - fi - center_a := center mfun_shade_path shifted ( - cx * bbwidth (mfun_shade_path)/2, - cy * bbheight(mfun_shade_path)/2 - ) ; - elseif hasparameter "vector" : - center_a := point (getparameter "vector" 1) of mfun_shade_path ; - center_b := point (getparameter "vector" 2) of mfun_shade_path ; - fi - fill mfun_shade_path - withprescript "sh_domain=" & decimal domain_min & " " & decimal domain_max - withprescript "sh_transform=yes" - withprescript "sh_color=into" - withprescript "sh_color_a=" & colordecimals color_a - withprescript "sh_color_b=" & colordecimals color_b - withprescript "sh_first=" & ddecimal point 0 of mfun_shade_path % used for support scaling - withprescript "sh_set_x=" & ddecimal (mfun_shade_nx,mfun_shade_lx) % - withprescript "sh_set_y=" & ddecimal (mfun_shade_ny,mfun_shade_ly) % - if alternative = "linear" : - withprescript "sh_type=linear" - % withprescript "sh_factor=1" - withprescript "sh_factor=" & decimal factor - withprescript "sh_center_a=" & ddecimal center_a - withprescript "sh_center_b=" & ddecimal center_b - else : - withprescript "sh_type=circular" - % withprescript "sh_factor=1.2" - withprescript "sh_factor=" & decimal factor - withprescript "sh_center_a=" & ddecimal center_a - withprescript "sh_center_b=" & ddecimal center_b - withprescript "sh_radius_a=" & decimal radius_a - withprescript "sh_radius_b=" & decimal radius_b - fi ; - if getparameter "trace" : - draw fullcircle scaled 1mm shifted center_a ; - draw fullsquare scaled 2mm shifted center_b ; - draw textext.top("\strut\ttx center a") ysized LineHeight shifted center_a shifted (0, 2mm) ; - draw textext.bot("\strut\ttx center b") ysized LineHeight shifted center_b shifted (0,-2mm) ; - if alternative = "circular" : -% draw fullcircle scaled ( radius_a * 2) shifted center_a dashed evenly ; -% draw fullcircle scaled (factor * radius_b * 2) shifted -center_b dashed evenly ; - draw fullcircle scaled ( radius_a) shifted center_a dashed evenly ; - draw fullcircle scaled (factor * radius_b) shifted -center_b dashed evenly ; - fi - fi - popparameters ; - ) -enddef ; - -% This is very experimental and will first be tested by a few users who -% are interested in this. - -presetparameters "contour" [ - xmin = 0, - xmax = 0, - ymin = 0, - ymax = 0, - xstep = 0, - ystep = 0, - levels = 10, - % colors = { }, % used when set - preamble = "", - function = "x + y", - color = "lin(l)", % l/n - background = "bitmap", % bitmap | shape | band - foreground = "auto", % cell| edge | shape | auto: bitmap/edge shape/shape - linewidth = .25, - backgroundcolor = "black", - linecolor = "gray", - xformat = "@0.2N", - yformat = "@0.2N", - zformat = "@0.2N", - xstyle = "", - ystyle = "", - zstyle = "", - - width = 0, % auto when 0 - height = 0, % auto when 0 - - trace = false, - checkresult = false, - defaultnan = 0, - defaultinf = 0, - - legend = "all", % x | y | z | function | range | all (but range) - legendheight = LineHeight, - legendwidth = LineHeight, - legendgap = 0, - legenddistance = EmWidth, - textdistance = 2EmWidth/3, - functiondistance = ExHeight, - functionstyle = "", - - level = 4096, % for selecting one (can't be too large for scaled) - - axisdistance = ExHeight, - axislinewidth = .25, - axisoffset = ExHeight/4, - axiscolor = "black", - ticklength = ExHeight, - - xtick = 5, - ytick = 5, - xlabel = 5, - ylabel = 5, - -] ; - -% we can as well push ... - -def lmt_contour = applyparameters "contour" "lmt_do_contour" enddef ; - -def mfun_only_draw = addto currentpicture doublepath enddef ; -def mfun_only_fill = addto currentpicture contour enddef ; -def mfun_only_fillup text t = addto currentpicture doublepath t withpostscript "both" enddef ; -def mfun_only_nodraw text t = addto currentpicture doublepath t withpostscript "collect" enddef ; -def mfun_only_nofill text t = addto currentpicture contour t withpostscript "evenodd" enddef ; -def mfun_only_eofill text t = addto currentpicture contour t withpostscript "collect" enddef ; - -def lmt_do_contour_shortcuts = - save D ; let D = mfun_only_draw ; - save E ; let E = mfun_only_eofill ; - save F ; let F = mfun_only_fill ; - save U ; let U = mfun_only_fillup ; - save d ; let d = mfun_only_nodraw ; - save e ; let f = mfun_only_eofill ; - save f ; let f = mfun_only_nofill ; - save C ; let C = cycle ; - save B ; let B = controls ; - save A ; let A = and ; -enddef ; - -def lmt_do_contour_band = - lua.mp.lmt_contours_edge_set_by_band() ; - for v=1 upto lua.mp.lmt_contours_nofvalues() : - draw image ( - lua.mp.lmt_contours_edge_get_band(v) ; - ) - withcolor lua.mp.lmt_contours_color(v) ; - endfor ; -enddef; - -def lmt_do_contour_cell(expr dx,dy) = - lua.mp.lmt_contours_edge_set_by_cell() ; - draw image ( - if level = 4096 : - for v=1+1 upto lua.mp.lmt_contours_nofvalues() : - lua.mp.lmt_contours_edge_get_cell(v) ; - endfor ; - else : - lua.mp.lmt_contours_edge_get_cell(level) ; - fi - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withcolor getparameter "linecolor" - withpen pencircle scaled getparameter "linewidth" ; -enddef ; - -def lmt_do_contour_edge(expr dx, dy) = - lua.mp.lmt_contours_edge_set() ; - draw image ( - if level = 4096 : - for v=1+1 upto lua.mp.lmt_contours_nofvalues() : - lua.mp.lmt_contours_edge_paths(v); - endfor ; - else : - lua.mp.lmt_contours_edge_paths(level); - fi - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withcolor getparameter "linecolor" - withpen pencircle scaled getparameter "linewidth" ; -enddef ; - -def lmt_do_contour_edges(expr dx, dy) = - lua.mp.lmt_contours_edge_set() ; - if level = 4096 : - for v=1+1 upto lua.mp.lmt_contours_nofvalues() : - draw image ( - lua.mp.lmt_contours_edge_paths(v); - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withpen pencircle scaled getparameter "linewidth" - withcolor lua.mp.lmt_contours_color(v) ; - endfor ; - else : - draw image ( - lua.mp.lmt_contours_edge_paths(level); - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withpen pencircle scaled getparameter "linewidth" - withcolor lua.mp.lmt_contours_color(level) ; - fi ; -enddef ; - -def lmt_do_contour_cells(expr dx, dy) = - lua.mp.lmt_contours_edge_set_by_cell() ; - if level = 4096 : - for v=1+1 upto lua.mp.lmt_contours_nofvalues() : - draw image ( - lua.mp.lmt_contours_edge_get_cell(v) ; - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withpen pencircle scaled getparameter "linewidth" - withcolor lua.mp.lmt_contours_color(v) ; - endfor ; - else : - draw image ( - lua.mp.lmt_contours_edge_get_cell(level) ; - ) - if offset : shifted (-1/2,-1/2) fi - withpen pencircle scaled getparameter "linewidth" - withcolor lua.mp.lmt_contours_color(v) ; - fi ; -enddef ; - -def lmt_do_contour_shape(expr dx, dy) = - draw image ( - if level = 4096 : - for v=1+1 upto lua.mp.lmt_contours_nofvalues() : - lua.mp.lmt_contours_shape_paths(v); - endfor ; - else : - lua.mp.lmt_contours_shape_paths(level); - lua.mp.lmt_contours_shape_paths(1); - fi - ) - if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi - withcolor getparameter "linecolor" - withpen pencircle scaled getparameter "linewidth" ; -enddef ; - -def lmt_do_contour_bitmap = - lua.mp.lmt_contours_bitmap_set() ; - lua.mp.lmt_contours_bitmap_get() ; -enddef ; - -def lmt_do_contour_shades(expr outlines) = - lua.mp.lmt_contours_shade_set(outlines) ; - if level = 4096 : - for v=1 upto lua.mp.lmt_contours_nofvalues() : % no + 1 here - draw image ( - lua.mp.lmt_contours_shade_paths(v) ; - ) - withpen pencircle scaled 0 - withcolor lua.mp.lmt_contours_color(v) ; - endfor ; - else : - draw image ( - lua.mp.lmt_contours_shade_paths(level); - ) - withpen pencircle scaled 0 - withcolor lua.mp.lmt_contours_color(level) ; - fi ; -enddef ; - -def lmt_load_mlib_cnt = - runscript("lua.registercode('mlib-cnt')"); - extra_beginfig := extra_beginfig & % todo: use different hook - "runscript(" & ditto & "mp.lmt_contours_cleanup()" & ditto & ")" ; - let lmt_load_mlib_cnt = relax ; -enddef ; - -vardef lmt_do_contour = - image ( - - lmt_load_mlib_cnt ; - - pushparameters "contour" ; - - lua.mp.lmt_contours_start() ; - - % graphic - - save bg, fg, nx, ny, trace, level, b, done ; string bg, fg ; boolean trace, done ; path b ; - - bg := getparameter "background" ; - fg := getparameter "foreground" ; - nx := lua.mp.lmt_contours_nx() ; - ny := lua.mp.lmt_contours_ny() ; - trace := getparameter "trace" ; - level := getparameter "level" ; - done := true ; - - begingroup ; - - lmt_do_contour_shortcuts ; - - if bg = "band" : - lmt_do_contour_band ; - b := boundingbox currentpicture ; - if (fg = "auto") or (fg = "cell") : - lmt_do_contour_cell(0,0) ; - elseif (fg = "edge") : - lmt_do_contour_edge(0,0) ; % true ? - fi ; - - elseif bg = "bitmap" : - - lmt_do_contour_bitmap ; - b := boundingbox currentpicture ; - if (fg = "auto") or (fg = "cell") : - lmt_do_contour_cell(-1/2,-1/2) ; - elseif (fg = "edge") : - lmt_do_contour_edge(-1/2,-1/2) ; - fi ; - - elseif bg = "shape" : - - lmt_do_contour_shades((fg = "auto") or (fg = "shape")) ; - b := boundingbox currentpicture ; - if (fg == "auto") or (fg = "shape") : - lmt_do_contour_shape(0,0) ; - elseif fg == "cell" : - lmt_do_contour_cell(-1,-1) ; - elseif fg == "edge" : - lmt_do_contour_edge(-1,-1) ; - fi ; - - % currentpicture := currentpicture reflectedabout ( (0, ny/2), (nx,ny/2) ) ; - - elseif fg = "cell" : - - lmt_do_contour_shortcuts ; - lmt_do_contour_cells(0,0) ; - b := boundingbox currentpicture ; - - elseif fg = "edge" : - - lmt_do_contour_shortcuts ; - lmt_do_contour_edges(0,0) ; - b := boundingbox currentpicture ; - - else : - - done := false ; - - fi ; - - endgroup ; - - if done : - - save w, h, cx, cy ; - - cx := - bbwidth (b)/(nx - 1) ; - cy := - bbheight(b)/(ny - 1) ; - clip currentpicture to b - leftenlarged cx rightenlarged cx - topenlarged cy bottomenlarged cy ; - currentpicture := currentpicture - shifted (cx,cy) ; - - w := getparameter "width" ; - h := getparameter "height" ; - - % axis - - save xtic, ytic, auto ; boolean auto ; - - xtic := getparameter "xtick" ; - ytic := getparameter "ytick" ; - auto := (w = 0) and (h = 0) ; - - % resize - - if w <> 0 : - if h <> 0 : - currentpicture := currentpicture xysized (w,h) ; - else : - currentpicture := currentpicture xsized w ; - fi ; - elseif h <> 0 : - currentpicture := currentpicture ysized h ; - fi ; - if w = 0 : - w := bbwidth(currentpicture) ; - fi ; - if h = 0 : - h := bbheight(currentpicture) ; - fi ; - - % legend - - if hasoption "legend" "all,x,y,z,range" : - - save u, s, sx, sy, ax, ay, ao, al, at, tl, ox, oy, lg, tx, ty, wx, hx, ry, fmt, pmin, pmax ; string fmt; picture pmin, pmax ; - - % move some in the ifs - - if hasoption "legend" "all,z" : - - % colorbar - - fmt := lua.mp.lmt_contours_format() ; - pmin := lmt_text [ format = fmt, text = decimal lua.mp.lmt_contours_minmean() ] ; - pmax := lmt_text [ format = fmt, text = decimal lua.mp.lmt_contours_maxmean() ] ; - wx := max(bbwidth(pmin),bbwidth(pmax)) ; - hx := bbheight(pmin) ; - - else : - - hx := 0; - - fi ; - - if auto : - % u := 1 ; - u := lua.mp.lmt_contours_ny() / 100 ; - ry := 4u ; - sy := 5u ; - sx := 5u ; - lg := 0 ; - ox := 5u ; - oy := - sy/2 + ry/2 ; - tx := 2u ; - ty := 1u ; - ax := 1u ; - ay := 1u ; - ao := u ; - al := u/8 ; - at := 3u/2 ; - al := u/4 ; - else : - ry := 0 ; - sy := getparameter "legendheight" ; - sx := getparameter "legendwidth" ; - lg := getparameter "legendgap" ; - ox := getparameter "legenddistance" ; - oy := - sy/2 + hx/2 ; - tx := getparameter "textdistance" ; - ty := getparameter "functiondistance" ; - ax := getparameter "axisdistance" ; - ay := ax ; - ao := getparameter "axisoffset" ; - at := getparameter "ticklength" ; - al := getparameter "axislinewidth" ; - fi ; - - if hasoption "legend" "all,z" : - - save dy ; dy := h ; - - for v=1 upto lua.mp.lmt_contours_nofvalues() : - dy := dy - sy ; - fill unitsquare xyscaled (sx,sy) - shifted (w+ox,dy) - withcolor lua.mp.lmt_contours_color(v) ; - draw - lmt_text [ - trace = trace, - anchor = "llft", - format = fmt, - text = decimal lua.mp.lmt_contours_value(v), - style = getparameter "zstyle", - position = (wx,0), - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (w+ox+tx+sx,dy+sy+oy) - ; - dy := dy - lg ; - endfor ; - - fi ; - - if hasoption "legend" "x,all" : - - save n, d, s, xmin, xmax, xlab ; - - xmin := getparameter "xmin" ; - xmax := getparameter "xmax" ; - xlab := getparameter "xlabel" ; - - draw image ( - interim linecap := butt ; - draw ((0,0) -- (w,0)) ; - n := al/2 ; s := (w - al) / xtic ; d := (xmax - xmin) / xtic ; - for i=xmin step d until xmax : - draw (n,0) -- (n,-at) ; - n := n + s ; - endfor ; - ) shifted (0,-ay) - withpen pencircle scaled al - withcolor getparameter "axiscolor" - ; - - if hasoption "legend" "label,all" : - - draw image ( - n := al/2 ; s := (w - al) / xlab ; d := (xmax - xmin) / xlab ; - for i=xmin step d until xmax : - draw lmt_text [ - trace = trace, - anchor = "bot", - format = getparameter "xformat", - style = getparameter "xstyle", - text = decimal i - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (n,-at-ao) - ; - n := n + s ; - endfor ; - ) shifted (0,-ay) ; - - fi ; - - fi ; - - if hasoption "legend" "y,all" : - - save n, d, s, ymin, ymax, ylab ; - - ymin := getparameter "ymin" ; - ymax := getparameter "ymax" ; - ylab := getparameter "ylabel" ; - - draw image ( - interim linecap := butt ; - draw ((0,0) -- (0,h)) ; - n := al/2 ; s := (h - al) / ytic ; d := (ymax - ymin) / ytic ; - for i=ymin step d until ymax : - draw (0,n) -- (-at,n) ; - n := n + s ; - endfor ; - ) shifted (-ax,0) - withpen pencircle scaled al - withcolor getparameter "axiscolor" ; - ; - - if hasoption "legend" "label,all" : - - draw image ( - n := al/2 ; s := (h - al) / ylab ; d := (ymax - ymin) / ylab ; - for i=ymin step d until ymax : - draw lmt_text [ - trace = trace, - anchor = "lft", - format = getparameter "yformat", - style = getparameter "ystyle", - text = decimal i - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (-at-ao,n) - ; - n := n + s ; - endfor ; - ) shifted (-ax,0) ; - - fi ; - - fi ; - - if hasoption "legend" "range,all" : - - % range - - save d ; d := ypart llcorner currentpicture ; - - draw - lmt_text [ - trace = trace, - anchor = "bot", - text = lua.mp.lmt_contours_range() - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (w/2,d-ty) - ; - - % minmax - - draw - lmt_text [ - trace = trace, - anchor = "lrt", - text = lua.mp.lmt_contours_xrange() - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (0,d-ty) - ; - - draw - lmt_text [ - trace = trace, - anchor = "llft", - text = lua.mp.lmt_contours_yrange() - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (w,d-ty) - ; - - fi ; - - if hasoption "legend" "function,all" : - - % formula - - draw - lmt_text [ - trace = trace, - anchor = "bot", - style = getparameter "functionstyle", - text = lua.mp.lmt_contours_function() - background = "", - ] - if ry <> 0 : ysized (ry) fi - shifted (w/2,ypart llcorner currentpicture - ty) - ; - - fi ; - - if trace : - draw boundingbox currentpicture - dashed evenly - withpen pencircle scaled al ; - fi ; - - fi ; - - fi ; - - lua.mp.lmt_contours_stop() ; - - popparameters ; - ) -enddef ; - -newinternal svgforcecmyk ; svgforcecmyk := 0 ; - -vardef svgcolor(expr r, g, b) = - if svgforcecmyk > 0 : - (1-r,1-g,1-b,0) % simple: no black component, kind of ok for emoji - else : - (r,g,b) - fi -enddef ; - -vardef svgcmyk(expr c, m, y, k) = - (c,m,y,k) -enddef ; - -vardef svggray(expr s) = - s -enddef ; - -presetparameters "svg" [ - filename = "", - fontname = "", - colormap = "", - % unicode = 0, - width = 0, - height = 0, - origin = false, - offset = 0, -] ; - -def lmt_svg = applyparameters "svg" "lmt_do_svg" enddef ; - -vardef lmt_do_svg = - save w, h, o; - image ( - pushparameters "svg" ; - w := getparameter "width" ; - h := getparameter "height" ; - o := getparameter "offset" ; - lua.mp.lmt_svg_include() ; - if getparameter "origin" : - currentpicture := currentpicture shifted -llcorner currentpicture ; - fi ; - popparameters ; - if o <> 0 : - setbounds currentpicture to boundingbox currentpicture enlarged o ; - fi ; - ) - if w > 0 : - if h > 0 : xysized(w,h) else : xsized(w) fi - else : - if h > 0 : ysized(h) fi - fi -enddef ; - -% Another experiment. Parameters might change pending a discussion between Alan -% and me. - -presetparameters "surface" [ - code = "x + y", - color = "f, 0, 0", - linecolor = 1, - xmin = -1, - xmax = 1, - ymin = -1, - ymax = 1, - xstep = .1, - ystep = .1, - snap = .01, - xvector = { -0.7, -0.7 }, - yvector = { 1, 0 }, - zvector = { 0, 1 }, - light = { 3, 3, 10 }, - bright = 100, - clip = false, - lines = true, - linecolor = 1, - % axis = { } - % clipaxis = false - axiscolor = "gray" - axislinewidth = 1/2, -] ; - -def lmt_surface = applyparameters "surface" "lmt_do_surface" enddef ; - -vardef lmt_do_surface = - image ( - - lmt_load_mlib_cnt ; - - pushparameters "surface" ; - - save currentpen; pen currentpen ; - currentpen := pencircle scaled .25 ; - - interim linejoin := butt ; - - lmt_do_contour_shortcuts ; - - lua.mp.lmt_surface_do() ; - - currentpicture := currentpicture ysized getparameter "height" ; - - if hasparameter "axis" : - - save p ; picture p ; p := image ( - if hasparameter "axis" 1 : - draw ((origin) -- unitvector(getparameter "xvector")) scaled (getparameter "axis" 1) ; - fi ; - if hasparameter "axis" 2 : - draw ((origin) -- unitvector(getparameter "yvector")) scaled (getparameter "axis" 2) ; - fi ; - if hasparameter "axis" 3 : - draw ((origin) -- unitvector(getparameter "zvector")) scaled (getparameter "axis" 3) ; - fi ; - ) ; - - if getparameterdefault "clipaxis" false : - clip p to boundingbox currentpicture ; - fi ; - - draw p - withpen pencircle scaled getparameter "axislinewidth" - withcolor getparameter "axiscolor" - ; - - fi ; - - popparameters ; - ) -enddef ; - -% I can make a variant that avoids the lmt_do ... and does an immediate function -% call instead. - -presetparameters "mpsglyphs" [ - name = "dummy", - units = 1000, -] ; - -presetparameters "mpsglyph" [ - category = "dummy", - unicode = 0, - % unichar = "" -] ; - -def lmt_registerglyphs = applyparameters "mpsglyphs" "lmt_do_registerglyphs" enddef ; -def lmt_registerglyph = applyparameters "mpsglyph" "lmt_do_registerglyph" enddef ; - -vardef lmt_do_registerglyphs = lua.mp.lmt_register_glyphs() ; enddef ; -vardef lmt_do_registerglyph = lua.mp.lmt_register_glyph () ; enddef ; - -% Again an experiment (todo: the faster method): - -def lmt_remaptext = runscript("mp.lmt_do_remaptext()") enddef ; - -triplet mfun_tt_s ; - -vardef rawmaptext(expr s) = - mfun_tt_n := mfun_tt_n + 1 ; - mfun_tt_c := nullpicture ; - mfun_tt_o := nullpicture ; - addto mfun_tt_o doublepath origin _op_ ; % save drawoptions - mfun_tt_r := lua.mp.mf_map_text(mfun_tt_n,s,catcoderegime) ; - mfun_tt_s := lua.mp.mf_map_move(mfun_tt_n) ; - addto mfun_tt_c doublepath unitsquare - xscaled wdpart mfun_tt_r - yscaled (htpart mfun_tt_r + dppart mfun_tt_r) - shifted (0,-dppart mfun_tt_r) - withprescript "mf_object=text" - withprescript "tx_index=" & decimal mfun_tt_n - withprescript "tx_color=" & colordecimals colorpart mfun_tt_o - ; - mfun_tt_c -enddef ; - -vardef svgtext(expr t) = - save p ; picture p ; - % mfun_tt_s := (0,0,0) ; - % mfun_tt_r := (0,0,0) ; - p := rawmaptext(t) ; - p - if (mfun_labtype.drt >= 10) : % drt etc - shifted (0,ypart center p) - fi - shifted ( - - mfun_labshift.drt(p) - - (redpart mfun_tt_s,0) - + (greenpart mfun_tt_s,bluepart mfun_tt_s) - ) -enddef ; - -vardef svg expr c = lmt_svg [ code = c ] enddef ; - -% Fun stuff: - -presetparameters "poisson" [ - width = 50, - height = 50, - initialx = 0, - initialy = 0, - distance = 1, - count = 20, - macro = "draw", - arguments = 2 -] ; - -def lmt_poisson = applyparameters "poisson" "lmt_do_poisson" enddef ; - -vardef lmt_do_poisson = - image ( - pushparameters "poisson" ; - lua.mp.lmt_poisson_generate(); - popparameters ; - ) -enddef ; diff --git a/metapost/context/base/mpiv/mp-luas.mpxl b/metapost/context/base/mpiv/mp-luas.mpxl deleted file mode 100644 index 421e82946..000000000 --- a/metapost/context/base/mpiv/mp-luas.mpxl +++ /dev/null @@ -1,250 +0,0 @@ -%D \module -%D [ file=mp-luas.mpiv, -%D version=2014.04.14, -%D title=\CONTEXT\ \METAPOST\ graphics, -%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. - -if known context_luas : endinput ; fi ; - -% When I prototyped the runscript primitive I was just thinking of a usage like -% the original \directlua primitive in luatex: genererate something and pipe -% that back to metapost, and have access to some internals. Instead of compiling -% the code a the metapost end here we delegate that to the lua end. Only strings -% get passed. Of course in the end the real usage got a bit beyong the intended -% usage. So, in addition to some definitions here there are and will be use in -% other metafun modules too. Of course in retrospect I should have done this five -% years earlier. - -boolean context_luas ; context_luas := true ; - -newinternal mfid_scriptindex ; -mfid_scriptindex := runscript("mp.mf_script_index('scriptindex')") ; - -def scriptindex = runscript mfid_scriptindex enddef ; - -string mfun_lua_bs ; mfun_lua_bs := "[===[" ; -string mfun_lua_es ; mfun_lua_es := "]===]" ; - -vardef mlib_luas_luacall(text t) = - runscript("" for s = t : - if string s : - & s - % & mfun_lua_bs & s & mfun_lua_es - elseif numeric s : - & decimal s - elseif boolean s : - & if s : "true" else : "false" fi - elseif pair s : - & mfun_pair_to_table(s) - elseif path s : - & mfun_path_to_table(s) - elseif rgbcolor s : - & mfun_rgb_to_table(s) - elseif cmykcolor s : - & mfun_cmyk_to_table(s) - else : - & ditto & tostring(s) & ditto - fi endfor - ) -enddef ; - -newinternal mfun_luas_b ; - -def mlib_luas_luadone = - exitif numeric begingroup mfun_luas_b := 1 ; endgroup ; -enddef ; - -vardef mlib_luas_lualist(expr c)(text t) = % we could use mlib_luas_s instead of c - interim mfun_luas_b := 0 ; - runscript(c & for s = t : - if mfun_luas_b = 0 : - "(" - % hide(mfun_luas_b := 1) - mlib_luas_luadone - else : - "," - fi - & - if string s : - mfun_lua_bs & s & mfun_lua_es - elseif numeric s : - decimal s - elseif boolean s : - if s : "true" else : "false" fi - elseif pair s : - mfun_pair_to_table(s) - elseif path s : - mfun_path_to_table(s) - elseif rgbcolor s : - mfun_rgb_to_table(s) - elseif cmykcolor s : - mfun_cmyk_to_table(s) - else : - ditto & tostring(s) & ditto - fi & endfor if mfun_luas_b = 0 : "()" else : ")" fi - ) -enddef ; - -def luacall = mlib_luas_luacall enddef ; % why no let - -vardef lualist@#(text t) = mlib_luas_lualist(str @#)(t) enddef ; - -string mlib_luas_s ; % saves save/restore - -vardef lua@#(text t) = - mlib_luas_s := str @# ; - if length(mlib_luas_s) > 0 : - mlib_luas_lualist(mlib_luas_s,t) - else : - mlib_luas_luacall(t) - fi -enddef ; - -vardef MP@#(text t) = - mlib_luas_lualist("MP." & str @#,t) -enddef ; - -def message expr t = - lua.mp.report(tostring(t)) ; -enddef ; - -% Color: - -% We do a low level runscript: -% -% lua.mp.namedcolor(s) % conflicts with macro namedcolor -% lua.mp.mf_named_color(s) % okay but, can also be -% lua.mp("mf_named_color",s) % which gives expansion mess - -newinternal mfid_resolvedcolor ; mfid_resolvedcolor := scriptindex "namedcolor" ; - -def resolvedcolor = runscript mfid_resolvedcolor enddef ; - -% Modes: - -vardef texmode (expr s) = lua.mp("mode", s) enddef ; -vardef systemmode(expr s) = lua.mp("systemmode",s) enddef ; - -% A few helpers - -vardef isarray suffix a = lua.mp.isarray (str a) enddef ; -vardef prefix suffix a = lua.mp.prefix (str a) enddef ; -vardef dimension suffix a = lua.mp.dimension(str a) enddef ; - -% More access - -vardef getmacro(expr k) = lua.mp._get_macro_(k) enddef ; -vardef getdimen(expr k) = lua.mp._get_dimen_(k) enddef ; -vardef getcount(expr k) = lua.mp._get_count_(k) enddef ; -vardef gettoks (expr k) = lua.mp._get_toks_ (k) enddef ; - -def setmacro(expr k,v) = lua.mp._set_macro_(k,v) enddef ; -def setdimen(expr k,v) = lua.mp._set_dimen_(k,v) enddef ; -def setcount(expr k,v) = lua.mp._set_count_(k,v) enddef ; -def settoks (expr k,v) = lua.mp._set_toks_ (k,v) enddef ; - -vardef positionpath (expr name) = lua.mp.positionpath (name) enddef ; -vardef positioncurve (expr name) = lua.mp.positioncurve (name) enddef ; -vardef positionxy (expr name) = lua.mp.positionxy (name) enddef ; -vardef positionpxy (expr name) = lua.mp.positionpxy (name) enddef ; -vardef positionwhd (expr name) = lua.mp.positionwhd (name) enddef ; -vardef positionpage (expr name) = lua.mp.positionpage (name) enddef ; -vardef positionregion(expr name) = lua.mp.positionregion(name) enddef ; -vardef positionbox (expr name) = lua.mp.positionbox (name) enddef ; -vardef positionanchor = lua.mp.positionanchor() enddef ; - -let wdpart = redpart ; -let htpart = greenpart ; -let dppart = bluepart ; - -vardef positioninregion = - currentpicture := currentpicture shifted - positionxy(positionanchor) ; -enddef ; - -vardef positionatanchor(expr name) = - currentpicture := currentpicture shifted - positionxy(name) ; -enddef ; - -vardef texvar(expr name) = lua.mp.texvar(name) enddef ; -vardef texstr(expr name) = lua.mp.texstr(name) enddef ; - -newinternal mfid_path_lengthof ; mfid_path_lengthof := scriptindex "pathlengthof" ; -newinternal mfid_path_pointof ; mfid_path_pointof := scriptindex "pathpointof" ; -newinternal mfid_path_leftof ; mfid_path_leftof := scriptindex "pathleftof" ; -newinternal mfid_path_rightof ; mfid_path_rightof := scriptindex "pathrightof" ; -newinternal mfid_path_reset ; mfid_path_reset := scriptindex "pathreset" ; - -% 25 pct gain - - def inpath = = 1 step 1 until runscript mfid_path_lengthof enddef ; -vardef pointof primary i = runscript mfid_path_pointof i enddef ; -vardef leftof primary i = runscript mfid_path_leftof i enddef ; -vardef rightof primary i = runscript mfid_path_rightof i enddef ; - -% another 10 pct gain - -% def inpath = = 1 step 1 until runscript mfid_path_lengthof enddef ; -% def pointof = runscript mfid_path_pointof enddef ; -% def leftof = runscript mfid_path_leftof enddef ; -% def rightof = runscript mfid_path_rightof enddef ; - -extra_endfig := extra_endfig & " runscript mfid_path_reset ; " ; - -vardef utflen(expr s) = lua.mp.utflen(s) enddef ; -vardef utfsub(expr s,f,t) = lua.mp.utfsub(s,f,t) enddef ; - -newinternal mfid_getparameters ; mfid_getparameters := scriptindex "getparameters" ; -newinternal mfid_presetparameters ; mfid_presetparameters := scriptindex "presetparameters" ; -newinternal mfid_hasparameter ; mfid_hasparameter := scriptindex "hasparameter" ; -newinternal mfid_hasoption ; mfid_hasoption := scriptindex "hasoption" ; -newinternal mfid_getparameter ; mfid_getparameter := scriptindex "getparameter" ; -newinternal mfid_getparameterdefault ; mfid_getparameterdefault := scriptindex "getparameterdefault" ; -newinternal mfid_getparametercount ; mfid_getparametercount := scriptindex "getparametercount" ; -newinternal mfid_getmaxparametercount ; mfid_getmaxparametercount := scriptindex "getmaxparametercount" ; -newinternal mfid_getparameterpath ; mfid_getparameterpath := scriptindex "getparameterpath" ; -newinternal mfid_getparameterpen ; mfid_getparameterpen := scriptindex "getparameterpen" ; -newinternal mfid_getparametertext ; mfid_getparametertext := scriptindex "getparametertext" ; -%%%%%%%%%%% mfid_getparameteroption ; mfid_getparameteroption := scriptindex "getparameteroption" ; -newinternal mfid_applyparameters ; mfid_applyparameters := scriptindex "applyparameters" ; -newinternal mfid_pushparameters ; mfid_pushparameters := scriptindex "pushparameters" ; -newinternal mfid_popparameters ; mfid_popparameters := scriptindex "popparameters" ; - -def getparameters = runscript mfid_getparameters enddef ; -def presetparameters = runscript mfid_presetparameters enddef ; -def hasparameter = runscript mfid_hasparameter enddef ; -def hasoption = runscript mfid_hasoption enddef ; -def getparameter = runscript mfid_getparameter enddef ; -def getparameterdefault = runscript mfid_getparameterdefault enddef ; -def getparametercount = runscript mfid_getparametercount enddef ; -def getmaxparametercount = runscript mfid_getmaxparametercount enddef ; -def getparameterpath = runscript mfid_getparameterpath enddef ; -def getparameterpen = runscript mfid_getparameterpen enddef ; -def getparametertext = runscript mfid_getparametertext enddef ; -%%% getparameteroption = runscript mfid_getparameteroption enddef ; -def applyparameters = runscript mfid_applyparameters enddef ; -def pushparameters = runscript mfid_pushparameters enddef ; -def popparameters = runscript mfid_popparameters enddef ; - -% This might also be done in stock mkiv: - -newinternal mfid_year ; mfid_year := scriptindex "year" ; vardef year = runscript mfid_year enddef ; -newinternal mfid_month ; mfid_month := scriptindex "month" ; vardef month = runscript mfid_month enddef ; -newinternal mfid_day ; mfid_day := scriptindex "day" ; vardef day = runscript mfid_day enddef ; -newinternal mfid_hour ; mfid_hour := scriptindex "hour" ; vardef hour = runscript mfid_hour enddef ; -newinternal mfid_minute ; mfid_minute := scriptindex "minute" ; vardef minute = runscript mfid_minute enddef ; -newinternal mfid_second ; mfid_second := scriptindex "second" ; vardef second = runscript mfid_second enddef ; - -% You cannot overload a local color bu using a prefix works ok: -% -% \definecolor [ name = "mp:myred", r = .9 ] ; - -newinternal mfid_definecolor ; mfid_definecolor := scriptindex "definecolor" ; - -def definecolor = runscript mfid_definecolor ; enddef ; % the semicolon prevents lookahead diff --git a/metapost/context/base/mpiv/mp-math.mpxl b/metapost/context/base/mpiv/mp-math.mpxl deleted file mode 100644 index ea8c1cd7c..000000000 --- a/metapost/context/base/mpiv/mp-math.mpxl +++ /dev/null @@ -1,161 +0,0 @@ -%D \module -%D [ file=mp-math.mpiv, -%D version=2019.07.26, % was mp-core: 1999.08.01, anchoring -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=extra math functions, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -if known context_math : endinput ; fi ; - -boolean context_math ; context_math := true ; - -% draw textext(decimal runscript("mp.numeric(xmath.gamma(.12))")) ; - -newinternal mfid_m_acos ; mfid_m_acos := scriptindex "m_acos" ; def m_acos = runscript mfid_m_acos enddef ; -newinternal mfid_m_acosh ; mfid_m_acosh := scriptindex "m_acosh" ; def m_acosh = runscript mfid_m_acosh enddef ; -newinternal mfid_m_asin ; mfid_m_asin := scriptindex "m_asin" ; def m_asin = runscript mfid_m_asin enddef ; -newinternal mfid_m_asinh ; mfid_m_asinh := scriptindex "m_asinh" ; def m_asinh = runscript mfid_m_asinh enddef ; -newinternal mfid_m_atan ; mfid_m_atan := scriptindex "m_atan" ; def m_atan = runscript mfid_m_atan enddef ; -newinternal mfid_m_atantwo ; mfid_m_atantwo := scriptindex "m_atan2" ; def m_atantwo = runscript mfid_m_atantwo enddef ; % atan2 -newinternal mfid_m_atanh ; mfid_m_atanh := scriptindex "m_atanh" ; def m_atanh = runscript mfid_m_atanh enddef ; -newinternal mfid_m_cbrt ; mfid_m_cbrt := scriptindex "m_cbrt" ; def m_cbrt = runscript mfid_m_cbrt enddef ; -newinternal mfid_m_ceil ; mfid_m_ceil := scriptindex "m_ceil" ; def m_ceil = runscript mfid_m_ceil enddef ; -newinternal mfid_m_copysign ; mfid_m_copysign := scriptindex "m_copysign" ; def m_copysign = runscript mfid_m_copysign enddef ; -newinternal mfid_m_cos ; mfid_m_cos := scriptindex "m_cos" ; def m_cos = runscript mfid_m_cos enddef ; -newinternal mfid_m_cosh ; mfid_m_cosh := scriptindex "m_cosh" ; def m_cosh = runscript mfid_m_cosh enddef ; -newinternal mfid_m_deg ; mfid_m_deg := scriptindex "m_deg" ; def m_deg = runscript mfid_m_deg enddef ; -newinternal mfid_m_erf ; mfid_m_erf := scriptindex "m_erf" ; def m_erf = runscript mfid_m_erf enddef ; -newinternal mfid_m_erfc ; mfid_m_erfc := scriptindex "m_erfc" ; def m_erfc = runscript mfid_m_erfc enddef ; -newinternal mfid_m_exp ; mfid_m_exp := scriptindex "m_exp" ; def m_exp = runscript mfid_m_exp enddef ; -newinternal mfid_m_exptwo ; mfid_m_exptwo := scriptindex "m_exp2" ; def m_exptwo = runscript mfid_m_exptwo enddef ; % exp2 -newinternal mfid_m_expm ; mfid_m_expm := scriptindex "m_expm1" ; def m_expm = runscript mfid_m_expm enddef ; % expm1 -newinternal mfid_m_fabs ; mfid_m_fabs := scriptindex "m_fabs" ; def m_fabs = runscript mfid_m_fabs enddef ; -newinternal mfid_m_fdim ; mfid_m_fdim := scriptindex "m_fdim" ; def m_fdim = runscript mfid_m_fdim enddef ; -newinternal mfid_m_floor ; mfid_m_floor := scriptindex "m_floor" ; def m_floor = runscript mfid_m_floor enddef ; -newinternal mfid_m_fma ; mfid_m_fma := scriptindex "m_fma" ; def m_fma = runscript mfid_m_fma enddef ; -newinternal mfid_m_fmax ; mfid_m_fmax := scriptindex "m_fmax" ; def m_fmax = runscript mfid_m_fmax enddef ; -newinternal mfid_m_fmin ; mfid_m_fmin := scriptindex "m_fmin" ; def m_fmin = runscript mfid_m_fmin enddef ; -newinternal mfid_m_fmod ; mfid_m_fmod := scriptindex "m_fmod" ; def m_fmod = runscript mfid_m_fmod enddef ; -newinternal mfid_m_frexp ; mfid_m_frexp := scriptindex "m_frexp" ; def m_frexp = runscript mfid_m_frexp enddef ; -newinternal mfid_m_gamma ; mfid_m_gamma := scriptindex "m_gamma" ; def m_gamma = runscript mfid_m_gamma enddef ; -newinternal mfid_m_hypot ; mfid_m_hypot := scriptindex "m_hypot" ; def m_hypot = runscript mfid_m_hypot enddef ; -newinternal mfid_m_isfinite ; mfid_m_isfinite := scriptindex "m_isfinite" ; def m_isfinite = runscript mfid_m_isfinite enddef ; -newinternal mfid_m_isinf ; mfid_m_isinf := scriptindex "m_isinf" ; def m_isinf = runscript mfid_m_isinf enddef ; -newinternal mfid_m_isnan ; mfid_m_isnan := scriptindex "m_isnan" ; def m_isnan = runscript mfid_m_isnan enddef ; -newinternal mfid_m_isnormal ; mfid_m_isnormal := scriptindex "m_isnormal" ; def m_isnormal = runscript mfid_m_isnormal enddef ; -newinternal mfid_m_jz ; mfid_m_jz := scriptindex "m_j0" ; def m_jz = runscript mfid_m_jz enddef ; % j0 -newinternal mfid_m_j ; mfid_m_j := scriptindex "m_j1" ; def m_j = runscript mfid_m_j enddef ; % j1 -newinternal mfid_m_jn ; mfid_m_jn := scriptindex "m_jn" ; def m_jn = runscript mfid_m_jn enddef ; -newinternal mfid_m_ldexp ; mfid_m_ldexp := scriptindex "m_ldexp" ; def m_ldexp = runscript mfid_m_ldexp enddef ; -newinternal mfid_m_lgamma ; mfid_m_lgamma := scriptindex "m_lgamma" ; def m_lgamma = runscript mfid_m_lgamma enddef ; -newinternal mfid_m_log ; mfid_m_log := scriptindex "m_log" ; def m_log = runscript mfid_m_log enddef ; -newinternal mfid_m_logten ; mfid_m_logte := scriptindex "m_log10" ; def m_logten = runscript mfid_m_logten enddef ; % log10 -newinternal mfid_m_logp ; mfid_m_logp := scriptindex "m_log1p" ; def m_logp = runscript mfid_m_logp enddef ; % log1p -newinternal mfid_m_logtwo ; mfid_m_logtwo := scriptindex "m_log2" ; def m_logtwo = runscript mfid_m_logtwo enddef ; % log2 -newinternal mfid_m_logb ; mfid_m_logb := scriptindex "m_logb" ; def m_logb = runscript mfid_m_logb enddef ; -newinternal mfid_m_modf ; mfid_m_modf := scriptindex "m_modf" ; def m_modf = runscript mfid_m_modf enddef ; -newinternal mfid_m_nearbyint ; mfid_m_nearbyint := scriptindex "m_nearbyint" ; def m_nearbyint = runscript mfid_m_nearbyint enddef ; -newinternal mfid_m_nextafter ; mfid_m_nextafter := scriptindex "m_nextafter" ; def m_nextafter = runscript mfid_m_nextafter enddef ; -newinternal mfid_m_pow ; mfid_m_pow := scriptindex "m_pow" ; def m_pow = runscript mfid_m_pow enddef ; -newinternal mfid_m_rad ; mfid_m_rad := scriptindex "m_rad" ; def m_rad = runscript mfid_m_rad enddef ; -newinternal mfid_m_remainder ; mfid_m_remainder := scriptindex "m_remainder" ; def m_remainder = runscript mfid_m_remainder enddef ; -newinternal mfid_m_remquo ; mfid_m_remquo := scriptindex "m_remquo" ; def m_remquo = runscript mfid_m_remquo enddef ; -newinternal mfid_m_round ; mfid_m_round := scriptindex "m_round" ; def m_round = runscript mfid_m_round enddef ; -newinternal mfid_m_scalbn ; mfid_m_scalbn := scriptindex "m_scalbn" ; def m_scalbn = runscript mfid_m_scalbn enddef ; -newinternal mfid_m_sin ; mfid_m_sin := scriptindex "m_sin" ; def m_sin = runscript mfid_m_sin enddef ; -newinternal mfid_m_sinh ; mfid_m_sinh := scriptindex "m_sinh" ; def m_sinh = runscript mfid_m_sinh enddef ; -newinternal mfid_m_sqrt ; mfid_m_sqrt := scriptindex "m_sqrt" ; def m_sqrt = runscript mfid_m_sqrt enddef ; -newinternal mfid_m_tan ; mfid_m_tan := scriptindex "m_tan" ; def m_tan = runscript mfid_m_tan enddef ; -newinternal mfid_m_tanh ; mfid_m_tanh := scriptindex "m_tanh" ; def m_tanh = runscript mfid_m_tanh enddef ; -newinternal mfid_m_tgamma ; mfid_m_tgamma := scriptindex "m_tgamma" ; def m_tgamma = runscript mfid_m_tgamma enddef ; -newinternal mfid_m_trunc ; mfid_m_trunc := scriptindex "m_trunc" ; def m_trunc = runscript mfid_m_trunc enddef ; -newinternal mfid_m_yz ; mfid_m_yz := scriptindex "m_y0" ; def m_yz = runscript mfid_m_yz enddef ; % y0 -newinternal mfid_m_y ; mfid_m_y := scriptindex "m_y1" ; def m_y = runscript mfid_m_y enddef ; % y1 -newinternal mfid_m_yn ; mfid_m_yn := scriptindex "m_yn" ; def m_yn = runscript mfid_m_yn enddef ; - -newinternal mfid_c_sin ; mfid_c_asin := scriptindex "c_sin" ; def c_sin = runscript mfid_c_sin enddef ; -newinternal mfid_c_cos ; mfid_c_acos := scriptindex "c_cos" ; def c_cos = runscript mfid_c_cos enddef ; -newinternal mfid_c_tan ; mfid_c_acos := scriptindex "c_tan" ; def c_tan = runscript mfid_c_tan enddef ; -newinternal mfid_c_sinh ; mfid_c_acos := scriptindex "c_sinh" ; def c_sinh = runscript mfid_c_sinh enddef ; -newinternal mfid_c_cosh ; mfid_c_acos := scriptindex "c_cosh" ; def c_cosh = runscript mfid_c_cosh enddef ; -newinternal mfid_c_tanh ; mfid_c_acos := scriptindex "c_tanh" ; def c_tanh = runscript mfid_c_tanh enddef ; - -newinternal mfid_c_asin ; mfid_c_acos := scriptindex "c_asin" ; def c_asin = runscript mfid_c_asin enddef ; -newinternal mfid_c_acos ; mfid_c_acos := scriptindex "c_acos" ; def c_acos = runscript mfid_c_acos enddef ; -newinternal mfid_c_atan ; mfid_c_acos := scriptindex "c_atan" ; def c_atan = runscript mfid_c_atan enddef ; -newinternal mfid_c_asinh ; mfid_c_acos := scriptindex "c_asinh" ; def c_asinh = runscript mfid_c_asinh enddef ; -newinternal mfid_c_acosh ; mfid_c_acos := scriptindex "c_acosh" ; def c_acosh = runscript mfid_c_acosh enddef ; -newinternal mfid_c_atanh ; mfid_c_acos := scriptindex "c_atanh" ; def c_atanh = runscript mfid_c_atanh enddef ; - -newinternal mfid_c_sqrt ; mfid_c_acos := scriptindex "c_sqrt" ; def c_sqrt = runscript mfid_c_sqrt enddef ; -newinternal mfid_c_abs ; mfid_c_acos := scriptindex "c_abs" ; def c_abs = runscript mfid_c_abs enddef ; -newinternal mfid_c_arg ; mfid_c_acos := scriptindex "c_arg" ; def c_arg = runscript mfid_c_arg enddef ; -newinternal mfid_c_conj ; mfid_c_acos := scriptindex "c_conj" ; def c_conj = runscript mfid_c_conj enddef ; -newinternal mfid_c_exp ; mfid_c_acos := scriptindex "c_exp" ; def c_exp = runscript mfid_c_exp enddef ; -newinternal mfid_c_log ; mfid_c_acos := scriptindex "c_log" ; def c_log = runscript mfid_c_log enddef ; -newinternal mfid_c_proj ; mfid_c_acos := scriptindex "c_proj" ; def c_proj = runscript mfid_c_proj enddef ; - -newinternal mfid_c_erf ; mfid_c_erf := scriptindex "c_erf" ; def c_erf = runscript mfid_c_erf enddef ; -newinternal mfid_c_erfc ; mfid_c_erfc := scriptindex "c_erfc" ; def c_erfc = runscript mfid_c_erfc enddef ; -newinternal mfid_c_erfcx ; mfid_c_erfcx := scriptindex "c_erfcx" ; def c_erfcx = runscript mfid_c_erfcx enddef ; -newinternal mfid_c_erfi ; mfid_c_erfi := scriptindex "c_erfi" ; def c_erfi = runscript mfid_c_erfi enddef ; - -% mfid_c_imag ; mfid_c_acos := scriptindex "c_imag" ; def c_imag = runscript mfid_c_imag enddef ; -% mfid_c_real ; mfid_c_acos := scriptindex "c_real" ; def c_real = runscript mfid_c_real enddef ; -% mfid_c_neg ; mfid_c_neg := scriptindex "c_neg" ; def c_neg = runscript mfid_c_neg enddef ; - -newinternal mfid_c_pow ; mfid_c_pow := scriptindex "c_pow" ; def c_pow (expr a,b) = runscript mfid_c_pow a b enddef ; -% mfid_c_add ; mfid_c_add := scriptindex "c_add" ; def c_add (expr a,b) = runscript mfid_c_add a b enddef ; -% mfid_c_sub ; mfid_c_sub := scriptindex "c_sub" ; def c_sub (expr a,b) = runscript mfid_c_sub a b enddef ; -newinternal mfid_c_mul ; mfid_c_mul := scriptindex "c_mul" ; def c_mul (expr a,b) = runscript mfid_c_mul a b enddef ; -newinternal mfid_c_div ; mfid_c_div := scriptindex "c_div" ; def c_div (expr a,b) = runscript mfid_c_div a b enddef ; - -newinternal mfid_c_voigt ; mfid_c_voigt := scriptindex "c_voigt" ; def c_voigt (expr a,b,c) = runscript mfid_c_voigt a b c enddef ; -newinternal mfid_c_voigt_hwhm ; mfid_c_voigt_hwhm := scriptindex "c_voigt_hwhm" ; def c_voigt_hwhm(expr a,b) = runscript mfid_c_voigt_hwhm a b enddef ; - -vardef c_add (expr a, b) = a + b enddef ; -vardef c_sub (expr a, b) = a + b enddef ; -vardef c_imag(expr a) = ypart a enddef ; -vardef c_real(expr a) = xpart a enddef ; -vardef c_neg (expr a) = -a enddef ; - -if (numbersystem == "scaled") or (numbersystem == "double") : - - % vardef sqrt primary x = m_sqrt x enddef ; - - % vardef sqr primary x = x*x enddef ; - % vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; - % vardef ln primary x = if x=0: 0 else: mlog(x)/256 fi enddef ; - % vardef exp primary x = (mexp 256)**x enddef ; - % vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; - - vardef sin primary x = m_sin x enddef ; vardef sinh primary x = m_sinh x enddef ; - vardef cos primary x = m_cos x enddef ; vardef cosh primary x = m_cosh x enddef ; - vardef tan primary x = m_tan x enddef ; vardef tanh primary x = m_tanh x enddef ; - vardef asin primary x = m_asin x enddef ; vardef asinh primary x = m_asinh x enddef ; - vardef acos primary x = m_acos x enddef ; vardef acosh primary x = m_acosh x enddef ; - vardef atan primary x = m_atan x enddef ; vardef atanh primary x = m_atanh x enddef ; - - vardef invsin primary x = (m_asin(x))/radian enddef ; - vardef invcos primary x = (m_acos(x))/radian enddef ; - vardef invtan primary x = (m_atan(x))/radian enddef ; - - - % vardef sind primary x = angle(m_sin x) enddef ; - % vardef cosd primary x = angle(m_cos x) enddef ; - % vardef tand primary x = angle(m_tan x) enddef ; - - vardef asind primary x = angle(m_asin x) enddef ; - vardef acosd primary x = angle(m_acos x) enddef ; - vardef atand primary x = angle(m_atan x) enddef ; - - % vardef tand primary x = sind(x)/cosd(x) enddef ; - % vardef cotd primary x = cosd(x)/sind(x) enddef ; - -fi ; diff --git a/metapost/context/base/mpiv/mp-page.mpxl b/metapost/context/base/mpiv/mp-page.mpxl deleted file mode 100644 index 8a4b735e0..000000000 --- a/metapost/context/base/mpiv/mp-page.mpxl +++ /dev/null @@ -1,243 +0,0 @@ -%D \module -%D [ file=mp-page.mpiv, -%D version=1999.03.10, -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=page enhancements, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This module is rather preliminary and subjected to changes.In the process of -%D moving to \METAFUN2\ this might change. - -if known context_page : endinput ; fi ; - -boolean context_page ; context_page := true ; - -def LoadPageState = enddef ; % just in case some old style uses it - -% Next we implement the the page area model. First some constants. - -LeftEdge := -4 ; Top := -40 ; -LeftEdgeSeparator := -3 ; TopSeparator := -30 ; -LeftMargin := -2 ; Header := -20 ; -LeftMarginSeparator := -1 ; HeaderSeparator := -10 ; -Text := 0 ; Text := 0 ; -RightMarginSeparator := +1 ; FooterSeparator := +10 ; -RightMargin := +2 ; Footer := +20 ; -RightEdgeSeparator := +3 ; BottomSeparator := +30 ; -RightEdge := +4 ; Bottom := +40 ; - -numeric HorPos ; HorPos := 0 ; -numeric VerPos ; VerPos := 0 ; - -% Because metapost > 1.50 has dynamic memory management and is less efficient than -% before we now delay calculations ... (on a document with 150 pages the time spent -% in mp was close to 5 seconds which was only due to initialising the page related -% areas, something that was hardly noticeable before. At least now we're back to -% half a second for such a case. - -def SetPageVsize = - numeric Vsize[] ; - Vsize[Top] = TopHeight ; - Vsize[TopSeparator] = TopDistance ; - Vsize[Header] = HeaderHeight ; - Vsize[HeaderSeparator] = HeaderDistance ; - Vsize[Text] = TextHeight ; - Vsize[FooterSeparator] = FooterDistance ; - Vsize[Footer] = FooterHeight ; - Vsize[BottomSeparator] = BottomDistance ; - Vsize[Bottom] = BottomHeight ; -enddef ; - -def SetPageHsize = - numeric Hsize[] ; - Hsize[LeftEdge] = LeftEdgeWidth ; - Hsize[LeftEdgeSeparator] = LeftEdgeDistance ; - Hsize[LeftMargin] = LeftMarginWidth ; - Hsize[LeftMarginSeparator] = LeftMarginDistance ; - Hsize[Text] = MakeupWidth ; - Hsize[RightMarginSeparator] = RightMarginDistance ; - Hsize[RightMargin] = RightMarginWidth ; - Hsize[RightEdgeSeparator] = RightEdgeDistance ; - Hsize[RightEdge] = RightEdgeWidth ; -enddef ; - -def SetPageVstep = - numeric Vstep[] ; - Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ; - Vstep[TopSeparator] = PaperHeight-TopSpace ; - Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ; - Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ; - Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ; - Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ; - Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ; - Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ; - Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ; -enddef ; - -def SetPageHstep = - numeric Hstep[] ; - Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ; - Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ; - Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ; - Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ; - Hstep[Text] = BackSpace ; - Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ; - Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ; - Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ; - Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ; -enddef ; - -def SetPageArea = - path Area[][] ; - for VerPos=Top step 10 until Bottom: - for HorPos=LeftEdge step 1 until RightEdge: - Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ; - Area[VerPos][HorPos] := Area[HorPos][VerPos] ; - endfor ; - endfor ; -enddef ; - -def SetPageLocation = - pair Location[][] ; - for VerPos=Top step 10 until Bottom: - for HorPos=LeftEdge step 1 until RightEdge: - Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ; - Location[VerPos][HorPos] := Location[HorPos][VerPos] ; - endfor ; - endfor ; -enddef ; - -def SetPageField = - path Field[][] ; - for VerPos=Top step 10 until Bottom: - for HorPos=LeftEdge step 1 until RightEdge: - Field[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] shifted (Hstep[HorPos],Vstep[VerPos]) ; - Field[VerPos][HorPos] := Field[HorPos][VerPos] ; - endfor ; - endfor ; -enddef ; - -def Area = hide(SetPageArea ;) Area enddef ; -def Location = hide(SetPageLocation ;) Location enddef ; -def Field = hide(SetPageField ;) Field enddef ; -def Vsize = hide(SetPageVsize ;) Vsize enddef ; -def Hsize = hide(SetPageHsize ;) Hsize enddef ; -def Vstep = hide(SetPageVstep ;) Vstep enddef ; -def Hstep = hide(SetPageHstep ;) Hstep enddef ; - -vardef FrontPageWidth = PaperWidth enddef ; -vardef BackPageWidth = PaperWidth enddef ; -vardef CoverWidth = 2 * PaperWidth + SpineWidth enddef ; -vardef CoverHeight = PaperHeight enddef ; - -vardef FrontPageHeight = PaperHeight enddef ; -vardef BackPageHeight = PaperHeight enddef ; -vardef SpineHeight = PaperHeight enddef ; - -def SetPagePage = path Page ; Page := unitsquare xscaled PaperWidth yscaled PaperHeight ; enddef ; -def SetPageCoverPage = path CoverPage ; CoverPage := unitsquare xscaled CoverWidth yscaled CoverHeight ; enddef ; -def SetPageSpine = path Spine ; Spine := unitsquare xscaled SpineWidth yscaled CoverHeight shifted (BackPageWidth,0) ; enddef ; -def SetPageBackPage = path BackPage ; BackPage := unitsquare xscaled BackPageWidth yscaled CoverHeight ; enddef ; -def SetPageFrontPage = path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth yscaled CoverHeight shifted (BackPageWidth+SpineWidth,0) ; enddef ; - -def Page = hide(SetPagePage ;) Page enddef ; -def CoverPage = hide(SetPageCoverPage;) CoverPage enddef ; -def Spine = hide(SetPageSpine ;) Spine enddef ; -def BackPage = hide(SetPageBackPage ;) BackPage enddef ; -def FrontPage = hide(SetPageFrontPage;) FrontPage enddef ; - -% pages - -def StartPage = - begingroup ; - setbounds currentpicture to Page ; -enddef ; - -def StopPage = - setbounds currentpicture to Page ; - endgroup ; -enddef ; - -% cover pages - -def StartCover = - begingroup ; - setbounds currentpicture to CoverPage enlarged PaperBleed ; -enddef ; - -def StopCover = - setbounds currentpicture to CoverPage enlarged PaperBleed ; - endgroup ; -enddef ; - -% overlays: - -def OverlayBox = - (unitsquare xyscaled (OverlayWidth,OverlayHeight)) -enddef ; - -% handy - -def innerenlarged = - if OnRightPage : leftenlarged else : rightenlarged fi -enddef ; - -def outerenlarged = - if OnRightPage : rightenlarged else : leftenlarged fi -enddef ; - -% obsolete - -% def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ; -% def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ; -% def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ; -% def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ; - -% def Enlarged (expr p, d) = -% ( -% llEnlarged (p,d) -- -% lrEnlarged (p,d) -- -% urEnlarged (p,d) -- -% ulEnlarged (p,d) -- -% cycle -% ) -% enddef ; - -% for the moment we put these here: - -string RuleDirection ; RuleDirection := "" ; -string RuleOption ; RuleOption := "" ; -numeric RuleWidth ; RuleWidth := 0 ; -numeric RuleHeight ; RuleHeight := 0 ; -numeric RuleDepth ; RuleDepth := 0 ; -numeric RuleH ; RuleH := 0 ; -numeric RuleV ; RuleV := 0 ; -numeric RuleThickness ; RuleThickness := 0 ; -numeric RuleFactor ; RuleFactor := 0 ; -numeric RuleOffset ; RuleOffset := 0 ; - def RuleColor = (.5white) enddef ; - -def FakeWord(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) = - fill unitsquare - xscaled RuleWidth - yscaled (RuleDepth-RuleThickness/2) - withcolor RuleColor ; - fill unitsquare - xscaled RuleWidth - yscaled (RuleHeight-RuleDepth-RuleThickness/2) - shifted (0,RuleDepth+RuleThickness) - withcolor RuleColor ; -enddef ; - -def FakeRule(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) = - fill unitsquare - xscaled RuleWidth - yscaled RuleHeight - withcolor RuleColor ; -enddef ; diff --git a/metapost/context/base/mpxl/metafun.mpxl b/metapost/context/base/mpxl/metafun.mpxl new file mode 100644 index 000000000..a6160ef3e --- /dev/null +++ b/metapost/context/base/mpxl/metafun.mpxl @@ -0,0 +1,46 @@ +%D \module +%D [ file=metafun.mp, +%D version=2000.07.15, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=format generation file, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D First we input John Hobby's metapost plain file. However, because we want to +%D prevent dependency problems and in the end even may use a patched version, +%D we prefer to use a copy. + +boolean contextlmtxmode ; contextlmtxmode := if known fontmaking : false else: true fi; + +input "mp-base.mpiv" ; +input "mp-tool.mpiv" ; +input "mp-mlib.mpiv" ; +input "mp-luas.mpxl" ; +input "mp-math.mpxl" ; +input "mp-cont.mpxl" ; +input "mp-page.mpxl" ; +input "mp-butt.mpiv" ; +input "mp-shap.mpiv" ; +input "mp-grph.mpiv" ; +input "mp-grid.mpiv" ; +input "mp-form.mpiv" ; +input "mp-figs.mpiv" ; +input "mp-func.mpiv" ; +input "mp-node.mpiv" ; +input "mp-apos.mpiv" ; +input "mp-abck.mpiv" ; +input "mp-blob.mpiv" ; + +input "mp-lmtx.mpxl" ; % playground, not official + +string metafunversion ; metafunversion = "metafun xl " & mfun_timestamp; + +let normalend = end ; + +def end = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; +def bye = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; diff --git a/metapost/context/base/mpxl/minifun.mpxl b/metapost/context/base/mpxl/minifun.mpxl new file mode 100644 index 000000000..6769d26e4 --- /dev/null +++ b/metapost/context/base/mpxl/minifun.mpxl @@ -0,0 +1,35 @@ +%D \module +%D [ file=minifun.mp, +%D version=2018.06.02, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=format generation file, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This is a minimal \METAFUN\ instance which can be handy for isolated +%D subruns. + +boolean contextlmtxmode ; contextlmtxmode := if known fontmaking : false else: true fi; + +prologues := 0 ; +mpprocset := 1 ; + +input "mp-base.mpiv" ; +input "mp-tool.mpiv" ; +input "mp-mlib.mpiv" ; +input "mp-luas.mpxl" ; +input "mp-math.mpxl" ; +input "mp-cont.mpxl" ; +input "mp-page.mpiv" ; + +string minifunversion ; minifunversion = "minifun xl " & mfun_timestamp; + +let normalend = end ; + +def end = ; message "" ; message minifunversion ; message "" ; endinput ; enddef ; +def bye = ; message "" ; message minifunversion ; message "" ; endinput ; enddef ; diff --git a/metapost/context/base/mpxl/mp-cont.mpxl b/metapost/context/base/mpxl/mp-cont.mpxl new file mode 100644 index 000000000..bc318d4b9 --- /dev/null +++ b/metapost/context/base/mpxl/mp-cont.mpxl @@ -0,0 +1,158 @@ +%D \module +%D [ file=mp-cont.mpiv, +%D version=1999.03.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=Interfaces, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is rather preliminary and subjected to changes. + +if known context_cont : endinput ; fi ; + +boolean context_cont ; context_cont := true ; + +string CurrentLayout ; CurrentLayout := "default" ; + +boolean mfun_swapped ; + +def SwapPageState = + mfun_swapped := true ; % eventually this will go ! +enddef ; + +extra_beginfig := extra_beginfig & "mfun_swapped := false ;" ; + +newinternal mfid_PaperHeight ; mfid_PaperHeight := scriptindex "PaperHeight" ; vardef PaperHeight = runscript mfid_PaperHeight enddef ; +newinternal mfid_PaperWidth ; mfid_PaperWidth := scriptindex "PaperWidth" ; vardef PaperWidth = runscript mfid_PaperWidth enddef ; +newinternal mfid_PrintPaperHeight ; mfid_PrintPaperHeight := scriptindex "PrintPaperHeight" ; vardef PrintPaperHeight = runscript mfid_PrintPaperHeight enddef ; +newinternal mfid_PrintPaperWidth ; mfid_PrintPaperWidth := scriptindex "PrintPaperWidth" ; vardef PrintPaperWidth = runscript mfid_PrintPaperWidth enddef ; +newinternal mfid_TopSpace ; mfid_TopSpace := scriptindex "TopSpace" ; vardef TopSpace = runscript mfid_TopSpace enddef ; +newinternal mfid_BottomSpace ; mfid_BottomSpace := scriptindex "BottomSpace" ; vardef BottomSpace = runscript mfid_BottomSpace enddef ; +newinternal mfid_BackSpace ; mfid_BackSpace := scriptindex "BackSpace" ; vardef BackSpace = runscript mfid_BackSpace enddef ; +newinternal mfid_CutSpace ; mfid_CutSpace := scriptindex "CutSpace" ; vardef CutSpace = runscript mfid_CutSpace enddef ; +newinternal mfid_MakeupHeight ; mfid_MakeupHeight := scriptindex "MakeupHeight" ; vardef MakeupHeight = runscript mfid_MakeupHeight enddef ; +newinternal mfid_MakeupWidth ; mfid_MakeupWidth := scriptindex "MakeupWidth" ; vardef MakeupWidth = runscript mfid_MakeupWidth enddef ; +newinternal mfid_TopHeight ; mfid_TopHeight := scriptindex "TopHeight" ; vardef TopHeight = runscript mfid_TopHeight enddef ; +newinternal mfid_TopDistance ; mfid_TopDistance := scriptindex "TopDistance" ; vardef TopDistance = runscript mfid_TopDistance enddef ; +newinternal mfid_HeaderHeight ; mfid_HeaderHeight := scriptindex "HeaderHeight" ; vardef HeaderHeight = runscript mfid_HeaderHeight enddef ; +newinternal mfid_HeaderDistance ; mfid_HeaderDistance := scriptindex "HeaderDistance" ; vardef HeaderDistance = runscript mfid_HeaderDistance enddef ; +newinternal mfid_TextHeight ; mfid_TextHeight := scriptindex "TextHeight" ; vardef TextHeight = runscript mfid_TextHeight enddef ; +newinternal mfid_FooterDistance ; mfid_FooterDistance := scriptindex "FooterDistance" ; vardef FooterDistance = runscript mfid_FooterDistance enddef ; +newinternal mfid_FooterHeight ; mfid_FooterHeight := scriptindex "FooterHeight" ; vardef FooterHeight = runscript mfid_FooterHeight enddef ; +newinternal mfid_BottomDistance ; mfid_BottomDistance := scriptindex "BottomDistance" ; vardef BottomDistance = runscript mfid_BottomDistance enddef ; +newinternal mfid_BottomHeight ; mfid_BottomHeight := scriptindex "BottomHeight" ; vardef BottomHeight = runscript mfid_BottomHeight enddef ; +newinternal mfid_LeftEdgeWidth ; mfid_LeftEdgeWidth := scriptindex "LeftEdgeWidth" ; vardef LeftEdgeWidth = runscript mfid_LeftEdgeWidth enddef ; +newinternal mfid_LeftEdgeDistance ; mfid_LeftEdgeDistance := scriptindex "LeftEdgeDistance" ; vardef LeftEdgeDistance = runscript mfid_LeftEdgeDistance enddef ; +newinternal mfid_LeftMarginWidth ; mfid_LeftMarginWidth := scriptindex "LeftMarginWidth" ; vardef LeftMarginWidth = runscript mfid_LeftMarginWidth enddef ; +newinternal mfid_LeftMarginDistance ; mfid_LeftMarginDistance := scriptindex "LeftMarginDistance" ; vardef LeftMarginDistance = runscript mfid_LeftMarginDistance enddef ; +newinternal mfid_TextWidth ; mfid_TextWidth := scriptindex "TextWidth" ; vardef TextWidth = runscript mfid_TextWidth enddef ; +newinternal mfid_RightMarginDistance ; mfid_RightMarginDistance := scriptindex "RightMarginDistance" ; vardef RightMarginDistance = runscript mfid_RightMarginDistance enddef ; +newinternal mfid_RightMarginWidth ; mfid_RightMarginWidth := scriptindex "RightMarginWidth" ; vardef RightMarginWidth = runscript mfid_RightMarginWidth enddef ; +newinternal mfid_RightEdgeDistance ; mfid_RightEdgeDistance := scriptindex "RightEdgeDistance" ; vardef RightEdgeDistance = runscript mfid_RightEdgeDistance enddef ; +newinternal mfid_RightEdgeWidth ; mfid_RightEdgeWidth := scriptindex "RightEdgeWidth" ; vardef RightEdgeWidth = runscript mfid_RightEdgeWidth enddef ; +newinternal mfid_InnerMarginDistance ; mfid_InnerMarginDistance := scriptindex "InnerMarginDistance" ; vardef InnerMarginDistance = runscript mfid_InnerMarginDistance enddef ; +newinternal mfid_InnerMarginWidth ; mfid_InnerMarginWidth := scriptindex "InnerMarginWidth" ; vardef InnerMarginWidth = runscript mfid_InnerMarginWidth enddef ; +newinternal mfid_OuterMarginDistance ; mfid_OuterMarginDistance := scriptindex "OuterMarginDistance" ; vardef OuterMarginDistance = runscript mfid_OuterMarginDistance enddef ; +newinternal mfid_OuterMarginWidth ; mfid_OuterMarginWidth := scriptindex "OuterMarginWidth" ; vardef OuterMarginWidth = runscript mfid_OuterMarginWidth enddef ; +newinternal mfid_InnerEdgeDistance ; mfid_InnerEdgeDistance := scriptindex "InnerEdgeDistance" ; vardef InnerEdgeDistance = runscript mfid_InnerEdgeDistance enddef ; +newinternal mfid_InnerEdgeWidth ; mfid_InnerEdgeWidth := scriptindex "InnerEdgeWidth" ; vardef InnerEdgeWidth = runscript mfid_InnerEdgeWidth enddef ; +newinternal mfid_OuterEdgeDistance ; mfid_OuterEdgeDistance := scriptindex "OuterEdgeDistance" ; vardef OuterEdgeDistance = runscript mfid_OuterEdgeDistance enddef ; +newinternal mfid_OuterEdgeWidth ; mfid_OuterEdgeWidth := scriptindex "OuterEdgeWidth" ; vardef OuterEdgeWidth = runscript mfid_OuterEdgeWidth enddef ; +newinternal mfid_PageOffset ; mfid_PageOffset := scriptindex "PageOffset" ; vardef PageOffset = runscript mfid_PageOffset enddef ; +newinternal mfid_PageDepth ; mfid_PageDepth := scriptindex "PageDepth" ; vardef PageDepth = runscript mfid_PageDepth enddef ; +newinternal mfid_LayoutColumns ; mfid_LayoutColumns := scriptindex "LayoutColumns" ; vardef LayoutColumns = runscript mfid_LayoutColumns enddef ; +newinternal mfid_LayoutColumnDistance ; mfid_LayoutColumnDistance := scriptindex "LayoutColumnDistance" ; vardef LayoutColumnDistance = runscript mfid_LayoutColumnDistance enddef ; +newinternal mfid_LayoutColumnWidth ; mfid_LayoutColumnWidth := scriptindex "LayoutColumnWidth" ; vardef LayoutColumnWidth = runscript mfid_LayoutColumnWidth enddef ; + +newinternal mfid_OnRightPage ; mfid_OnRightPage := scriptindex "OnRightPage" ; vardef OnRightPage = runscript mfid_OnRightPage enddef ; +newinternal mfid_OnOddPage ; mfid_OnOddPage := scriptindex "OnOddPage" ; vardef OnOddPage = runscript mfid_OnOddPage enddef ; +newinternal mfid_InPageBody ; mfid_InPageBody := scriptindex "InPageBody" ; vardef InPageBody = runscript mfid_InPageBody enddef ; + +newinternal mfid_RealPageNumber ; mfid_RealPageNumber := scriptindex "RealPageNumber" ; vardef RealPageNumber = runscript mfid_RealPageNumber enddef ; +newinternal mfid_LastPageNumber ; mfid_LastPageNumber := scriptindex "LastPageNumber" ; vardef LastPageNumber = runscript mfid_LastPageNumber enddef ; + +newinternal mfid_PageNumber ; mfid_PageNumber := scriptindex "PageNumber" ; vardef PageNumber = runscript mfid_PageNumber enddef ; +newinternal mfid_NOfPages ; mfid_NOfPages := scriptindex "NOfPages" ; vardef NOfPages = runscript mfid_NOfPages enddef ; + +newinternal mfid_SubPageNumber ; mfid_SubPageNumber := scriptindex "SubPageNumber" ; vardef SubPageNumber = runscript mfid_SubPageNumber enddef ; +newinternal mfid_NOfSubPages ; mfid_NOfSubPages := scriptindex "NOfSubPages" ; vardef NOfSubPages = runscript mfid_NOfSubPages enddef ; + +newinternal mfid_CurrentColumn ; mfid_CurrentColumn := scriptindex "CurrentColumn" ; vardef CurrentColumn = runscript mfid_CurrentColumn enddef ; +newinternal mfid_NOfColumns ; mfid_NOfColumns := scriptindex "NOfColumns" ; vardef NOfColumns = runscript mfid_NOfColumns enddef ; + +newinternal mfid_BaseLineSkip ; mfid_BaseLineSkip := scriptindex "BaseLineSkip" ; vardef BaseLineSkip = runscript mfid_BaseLineSkip enddef ; +newinternal mfid_LineHeight ; mfid_LineHeight := scriptindex "LineHeight" ; vardef LineHeight = runscript mfid_LineHeight enddef ; +newinternal mfid_BodyFontSize ; mfid_BodyFontSize := scriptindex "BodyFontSize" ; vardef BodyFontSize = runscript mfid_BodyFontSize enddef ; + +newinternal mfid_TopSkip ; mfid_TopSkip := scriptindex "TopSkip" ; vardef TopSkip = runscript mfid_TopSkip enddef ; +newinternal mfid_StrutHeight ; mfid_StrutHeight := scriptindex "StrutHeight" ; vardef StrutHeight = runscript mfid_StrutHeight enddef ; +newinternal mfid_StrutDepth ; mfid_StrutDepth := scriptindex "StrutDepth" ; vardef StrutDepth = runscript mfid_StrutDepth enddef ; + +newinternal mfid_CurrentWidth ; mfid_CurrentWidth := scriptindex "CurrentWidth" ; vardef CurrentWidth = runscript mfid_CurrentWidth enddef ; +newinternal mfid_CurrentHeight ; mfid_CurrentHeight := scriptindex "CurrentHeight" ; vardef CurrentHeight = runscript mfid_CurrentHeight enddef ; + +newinternal mfid_HSize ; mfid_HSize := scriptindex "HSize" ; vardef HSize = runscript mfid_HSize enddef ; +newinternal mfid_VSize ; mfid_VSize := scriptindex "VSize" ; vardef VSize = runscript mfid_VSize enddef ; + +newinternal mfid_EmWidth ; mfid_EmWidth := scriptindex "EmWidth" ; vardef EmWidth = runscript mfid_EmWidth enddef ; +newinternal mfid_ExHeight ; mfid_ExHeight := scriptindex "ExHeight" ; vardef ExHeight = runscript mfid_ExHeight enddef ; + +newinternal mfid_PageFraction ; mfid_PageFraction := scriptindex "PageFraction" ; vardef PageFraction = runscript mfid_PageFraction enddef ; + +newinternal mfid_SpineWidth ; mfid_SpineWidth := scriptindex "SpineWidth" ; vardef SpineWidth = runscript mfid_SpineWidth enddef ; +newinternal mfid_PaperBleed ; mfid_PaperBleed := scriptindex "PaperBleed" ; vardef PaperBleed = runscript mfid_PaperBleed enddef ; + +% mfid_CurrentLayout ; mfid_CurrentLayout := scriptindex "CurrentLayout" ; vardef CurrentLayout = runscript mfid_CurrentLayout enddef ; +newinternal mfid_OverlayWidth ; mfid_OverlayWidth := scriptindex "OverlayWidth" ; vardef OverlayWidth = runscript mfid_OverlayWidth enddef ; +newinternal mfid_OverlayHeight ; mfid_OverlayHeight := scriptindex "OverlayHeight" ; vardef OverlayHeight = runscript mfid_OverlayHeight enddef ; +newinternal mfid_OverlayDepth ; mfid_OverlayDepth := scriptindex "OverlayDepth" ; vardef OverlayDepth = runscript mfid_OverlayDepth enddef ; +newinternal mfid_OverlayLineWidth ; mfid_OverlayLineWidth := scriptindex "OverlayLineWidth" ; vardef OverlayLineWidth = runscript mfid_OverlayLineWidth enddef ; +newinternal mfid_OverlayOffset ; mfid_OverlayOffset := scriptindex "OverlayOffset" ; vardef OverlayOffset = runscript mfid_OverlayOffset enddef ; +newinternal mfid_OverlayRegion ; mfid_OverlayRegion := scriptindex "OverlayRegion" ; vardef OverlayRegion = runscript mfid_OverlayRegion enddef ; +% mfid_OverlayLineColor ; mfid_OverlayLineColor := scriptindex "OverlayLineColor ; vardef OverlayLineColor = runscript mfid_OverlayLineColor enddef ; +% mfid_OverlayColor ; mfid_OverlayColor := scriptindex "OverlayColor ; vardef OverlayColor = runscript mfid_OverlayColor enddef ; + +newinternal mfid_defaultcolormodel ; mfid_defaultcolormodel := scriptindex "defaultcolormodel" ; vardef defaultcolormodel = runscript mfid_defaultcolormodel enddef ; + +vardef LeftMarginWidth = if mfun_swapped and not OnRightPage : runscript mfid_RightMarginWidth else : runscript mfid_LeftMarginWidth fi enddef ; +vardef RightMarginWidth = if mfun_swapped and not OnRightPage : runscript mfid_LeftMarginWidth else : runscript mfid_RightMarginWidth fi enddef ; +vardef LeftMarginDistance = if mfun_swapped and not OnRightPage : runscript mfid_RightMarginDistance else : runscript mfid_LeftMarginDistance fi enddef ; +vardef RightMarginDistance = if mfun_swapped and not OnRightPage : runscript mfid_LeftMarginDistance else : runscript mfid_RightMarginDistance fi enddef ; + +vardef LeftEdgeWidth = if mfun_swapped and not OnRightPage : runscript mfid_RightEdgeWidth else : runscript mfid_LeftEdgeWidth fi enddef ; +vardef RightEdgeWidth = if mfun_swapped and not OnRightPage : runscript mfid_LeftEdgeWidth else : runscript mfid_RightEdgeWidth fi enddef ; +vardef LeftEdgeDistance = if mfun_swapped and not OnRightPage : runscript mfid_RightEdgeDistance else : runscript mfid_LeftEdgeDistance fi enddef ; +vardef RightEdgeDistance = if mfun_swapped and not OnRightPage : runscript mfid_LeftEdgeDistance else : runscript mfid_RightEdgeDistance fi enddef ; + +vardef BackSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi runscript mfid_BackSpace enddef ; +vardef CutSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi runscript mfid_CutSpace enddef ; + +% better use: + +vardef OuterMarginWidth = if not OnRightPage : runscript mfid_LeftMarginWidth else : runscript mfid_RightMarginWidth fi enddef ; +vardef InnerMarginWidth = if not OnRightPage : runscript mfid_RightMarginWidth else : runscript mfid_LeftMarginWidth fi enddef ; +vardef OuterMarginDistance = if not OnRightPage : runscript mfid_LeftMarginDistance else : runscript mfid_RightMarginDistance fi enddef ; +vardef InnerMarginDistance = if not OnRightPage : runscript mfid_RightMarginDistance else : runscript mfid_LeftMarginDistance fi enddef ; + +vardef OuterEdgeWidth = if not OnRightPage : runscript mfid_LeftEdgeWidth else : runscript mfid_RightEdgeWidth fi enddef ; +vardef InnerEdgeWidth = if not OnRightPage : runscript mfid_RightEdgeWidth else : runscript mfid_LeftEdgeWidth fi enddef ; +vardef OuterEdgeDistance = if not OnRightPage : runscript mfid_LeftEdgeDistance else : runscript mfid_RightEdgeDistance fi enddef ; +vardef InnerEdgeDistance = if not OnRightPage : runscript mfid_RightEdgeDistance else : runscript mfid_LeftEdgeDistance fi enddef ; + +vardef OuterSpaceWidth = if not OnRightPage : runscript mfid_BackSpace else : runscript mfid_CutSpace fi enddef ; +vardef InnerSpaceWidth = if not OnRightPage : runscript mfid_CutSpace else : runscript mfid_BackSpace fi enddef ; + +% indices + +vardef OuterMargin = if not OnRightPage : LeftMargin else : RightMargin fi enddef ; +vardef InnerMargin = if not OnRightPage : RightMargin else : LeftMargin fi enddef ; + +vardef OuterEdge = if not OnRightPage : LeftEdge else : RightEdge fi enddef ; +vardef InnerEdge = if not OnRightPage : Rightedge else : LeftEdge fi enddef ; + + diff --git a/metapost/context/base/mpxl/mp-lmtx.mpxl b/metapost/context/base/mpxl/mp-lmtx.mpxl new file mode 100644 index 000000000..1f70d0ac1 --- /dev/null +++ b/metapost/context/base/mpxl/mp-lmtx.mpxl @@ -0,0 +1,2281 @@ +%D \module +%D [ file=mp-luas.lmtx, +%D version=2019.06.23, +%D title=\CONTEXT\ \METAPOST\ graphics, +%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. + +% This is an experimental module where I test some new interface methods; +% for real advanced graphics use the luapost module. + +if known context_lmtx : endinput ; fi ; + +boolean context_lmtx ; context_lmtx := true ; + +presetparameters "text" [ + offset = 0, + strut = "auto", + style = "", + color = "", + text = "", + anchor = "", + format = "", + position = origin, + trace = false, + + background = "", % "color", + backgroundcolor = "gray", +] ; + +def lmt_text = applyparameters "text" "lmt_do_text" enddef ; + +vardef lmt_do_text = + image ( + pushparameters "text" ; + save style, anchor, txt, fmt, strt ; + string style, anchor, txt, fmt, strt, bgr ; + interim textextoffset := getparameter "offset" ; + style := getparameter "style" ; + anchor := getparameter "anchor" ; + strt := getparameter "strut" ; + fmt := getparameter "format" ; + txt := getparameter "text" ; + bgr := getparameter "background" ; + if fmt <> "" : + txt := "\formatone{" & fmt & "}{" & txt & "}" + fi ; + if strt = "yes" : + txt := "\strut " & txt ; + elseif strt = "auto" : + txt := "\setstrut\strut " & txt ; + fi ; + if style <> "" : + txt := "\style[" & style & "]{" & txt & "}" ; + fi ; + if getparameter "trace" : + txt := "\ruledhbox{\showstruts" & txt & "}" ; + fi ; + draw + if anchor = "" : thetextext else : scantokens("thetextext." & anchor) fi ( + txt, + getparameter "position" + ) + withcolor getparameter "color" ; + if bgr = "color" : + addbackground withcolor getparameter "backgroundcolor" ; + fi ; + popparameters ; + ) +enddef ; + +presetparameters "grid" [ + nx = 1, dx = 1, + ny = 1, dy = 1, +] ; + +def lmt_grid = applyparameters "grid" "lmt_do_grid" enddef ; + +vardef lmt_do_grid = + image ( + save nx; nx := getparameter "grid" "nx" ; + save ny; ny := getparameter "grid" "ny" ; + save dx; dx := getparameter "grid" "dx" ; + save dy; dy := getparameter "grid" "dy" ; + for i = 0 step dx until nx : + draw ((0,0) -- (0,ny)) shifted (i,0) ; + endfor ; + for i = 0 step dy until ny : + draw ((0,0) -- (nx,0)) shifted (0,i) ; + endfor ; + ) +enddef ; + +def lmt_axis = applyparameters "axis" "lmt_do_axis" enddef ; + +presetparameters "axis" [ + nx = 1, dx = 1, tx = 0, sx = 1, startx = 0, + ny = 1, dy = 1, ty = 0, sy = 1, starty = 0, + + samples = { }, + list = { }, + connect = false, + list = [ close = false ], + samplecolors = { "" }, + axiscolor = "", + textcolor = "", +] ; + +vardef lmt_do_axis = + image ( + + pushparameters "axis" ; + save nx, ny, dx, dy, tx, ty ; + save c, startx, starty ; string c ; + nx := getparameter "nx" ; + ny := getparameter "ny" ; + dx := getparameter "dx" ; + dy := getparameter "dy" ; + tx := getparameter "tx" ; + ty := getparameter "ty" ; + c := getparameter "axiscolor" ; + startx := getparameter "startx" ; + starty := getparameter "starty" ; + draw (startx,starty) -- (startx,ny) withcolor c ; + draw (startx,starty) -- (nx,starty) withcolor c ; + for i = startx step dx until nx : + if (i > startx) or (startx = 0) : + draw ((0,0) -- (0,-2)) shifted (i,starty) withcolor c ; + fi ; + endfor ; + for i = starty step dy until ny : + if (i > starty) or (starty = 0) : + draw ((0,0) -- (-2,0)) shifted (startx,i) withcolor c ; + fi ; + endfor ; + if tx <> 0 : + c := getparameter "textcolor" ; + for i = startx step tx until nx : + if (i > startx) or (startx = 0) : + draw + textext("\strut " & decimal (i)) ysized 2 shifted (i,-4+starty) + withcolor c; + fi ; + endfor ; + fi ; + if ty <> 0 : + c := getparameter "textcolor" ; + for i = starty step ty until ny : + if (i > starty) or (starty = 0) : + draw + textext.lft("\strut " & decimal (i)) ysized 2 shifted (-3+startx,i) + withcolor c; + fi ; + endfor ; + fi ; + + if (getparametercount "samples") > 0 : + if getparameter "connect" : + for s = 1 upto getparametercount "samples" : + c := getparameter "samplecolors" s ; + draw for i = 1 upto getparametercount "samples" s : + if (i > 1) : -- fi (i, getparameter "samples" s i) + endfor + withcolor c ; + endfor ; + else : + for s = 1 upto getparametercount "samples" : + c := getparameter "samplecolors" s ; + for i = 1 upto getparametercount "samples" s : + draw (i, getparameter "samples" s i) + withcolor c ; + endfor ; + endfor ; + fi ; + fi ; + + if (getparametercount "list") > 0 : + + save p, ts, a, d ; path p ; numeric ts ; pair a, d ; + + ts := (getparameter "sy") / 20 ; + + pushparameters "list" ; + for s = 1 upto getparametercount : + pushparameters s ; + + c := getparameter "color" ; + + % p := for i = 1 upto getparametercount "points": + % if (i > 1) : -- fi (getparameter "points" i) + % endfor + % if (getparameterdefault "close" false) : -- cycle fi ; + + % this can become: + + % p := if (getparameterdefault "close" false) : + % % getparameterpath "points" "--" true ; + % getparameterpath "points" true ; + % else : + % % getparameterpath "points" "--" false ; + % getparameterpath "points" ; + % fi ; + + % p := getparameterpath "points" if (getparameterdefault "close" false) : true fi ; + + p := getparameterpath "points" (getparameterdefault "close" false) ; + % p := getparameterpath "points" getparameterdefault "close" false ; + + draw p withcolor c ; + + pushparameters "labels" ; + if (getparametercount) > 0 : + for i = 1 upto getparametercount: + n := i - 1 ; + a := point n of p ; + d := direction n of p ; + draw + textext(getparametertext i true) + ysized ts + shifted (a + .5 * unitvector(d) rotated 90) ; + endfor ; + fi ; + popparameters ; + + pushparameters "texts" ; + if (getparametercount) > 0 : + for i = 1 upto getparametercount : + n := i + 0.5 ; + a := point n of p ; + d := direction n of p ; + draw textext.d(getparametertext i true) + if d < left : rotated 180 shifted (0,-5) else : shifted (0,5) fi + ysized ts + shifted a + rotatedaround(a,angle(d)) ; + endfor ; + fi ; + popparameters ; + + popparameters ; + endfor ; + popparameters ; + fi ; + + popparameters ; + + ) + xyscaled(getparameter "axis" "sx",getparameter "axis" "sy") +enddef ; + +presetparameters "outline" [ + text = "", + kind = "draw", + fillcolor = "", + drawcolor = "", + rulethickness = 1/10, + align = "", + style = "", + width = 0, +] ; + +def lmt_outline = applyparameters "outline" "lmt_do_outline" enddef ; + +vardef lmt_do_outline = + image ( normaldraw image ( + save kind ; string kind ; kind := getparameter "outline" "kind" ; + save align ; string align ; align := getparameter "outline" "align" ; + save style ; string style ; style := getparameter "outline" "style" ; + save width ; numeric width ; width := getparameter "outline" "width" ; + if kind = "draw" : + kind := "d" ; + elseif kind = "fill" : + kind := "f" ; + elseif kind = "both" : + kind := "b" ; + elseif kind = "reverse" : + kind := "r" ; + elseif kind = "fillup" : + kind := "u" ; + fi ; + currentoutlinetext := currentoutlinetext + 1 ; + lua.mp.mf_outline_text( + currentoutlinetext, + if align = "" : + getparameter "outline" "text", + else : + "\framed[align={" & align & "}" + if width > 0 : + & ",width=" & decimal width & "bp" + fi + if style <> "" : + & ",foregroundstyle={" & style & "}" + fi + & ",offset=none,frame=off]{" + & (getparameter "outline" "text") + & "}", + fi, + kind + ) ; + save currentpen; pen currentpen ; + pickup pencircle scaled getparameter "outline" "rulethickness" ; + if kind = "f" : + mfun_do_outline_text_set_f ( + withcolor getparameter "outline" "fillcolor" + ); + elseif kind = "d" : + mfun_do_outline_text_set_d ( + withcolor getparameter "outline" "drawcolor" + ); + elseif kind = "b" : + mfun_do_outline_text_set_b ( + withcolor getparameter "outline" "fillcolor" + ) ( + withcolor getparameter "outline" "drawcolor" + ); + elseif kind = "u" : + mfun_do_outline_text_set_u ( + withcolor getparameter "outline" "fillcolor" + ); + elseif kind = "r" : + mfun_do_outline_text_set_r ( + withcolor getparameter "outline" "drawcolor" + ) ( + withcolor getparameter "outline" "fillcolor" + ) ; + elseif kind = "p" : + mfun_do_outline_text_set_p ; + else : + mfun_do_outline_text_set_n ( + % what to use here + ); + fi ; + lua.mp.mf_get_outline_text(currentoutlinetext) ; + ) ) +enddef ; + +presetparameters "followtext" [ + text = "", + spread = true, + trace = false, + reverse = false, + autoscaleup = "no", + autoscaledown = "no", + path = (fullcircle), +] ; + +def lmt_followtext = applyparameters "followtext" "lmt_do_followtext" enddef ; + +vardef lmt_do_followtext = + image ( + pushparameters "followtext" ; + save s_u ; string s_u ; s_u := getparameter "autoscaleup" ; + save s_d ; string s_d ; s_d := getparameter "autoscaledown" ; + save followtextalternative ; followtextalternative := if getparameter "spread" : 1 else : 0 fi ; + save tracingfollowtext ; tracingfollowtext := if getparameter "trace" : 1 else : 0 fi ; + save autoscaleupfollowtext ; autoscaleupfollowtext := if s_u = "yes" : 1 elseif s_u = "max" : 2 else : 0 fi ; + save autoscaledownfollowtext ; autoscaledownfollowtext := if s_d = "yes" : 1 elseif s_d = "max" : 2 else : 0 fi ; + draw followtext ( + if (getparameter "reverse") : reverse fi (getparameter "path"), + getparameter "text" + ) ; + popparameters ; + ) +enddef ; + +presetparameters "arrow" [ + path = origin, + % pen = ..., + kind = "fill", + dimple = 1/5, + scale = 3/4, + penscale = 3, + length = 4, + angle = 45, + location = "end", % middle both + alternative = "normal", % dimpled curved + percentage = 50, + headonly = false, +] ; + +def lmt_arrow = applyparameters "arrow" "lmt_do_arrow" enddef ; + +vardef lmt_do_arrow = + image ( + pushparameters "arrow" ; + save a ; string a ; a := getparameter "alternative" ; + save l ; string l ; l := getparameter "location" ; + save k ; string k ; k := getparameter "kind" ; + save p ; path p ; p := getparameter "path" ; + save ahvariant ; ahvariant := if a = "dimpled" : 1 elseif a = "curved" : 2 else : 0 fi ; + save ahdimple ; ahdimple := getparameter "dimple" ; + save ahscale ; ahscale := getparameter "scale" ; + save ahangle ; ahangle := getparameter "angle" ; + save ahlength ; ahlength := getparameter "length" ; + if not getparameter "headonly" : + draw p ; + fi ; + if hasparameter "pen" : + % a cheat: we should have a type check in lua + if hasoption "pen" "auto" : + ahlength := (getparameter "penscale") * boundingradius(currentpen) ; + else : + ahlength := (getparameter "penscale") * boundingradius(getparameterpen "pen") ; + fi ; + fi ; + if k = "draw" : draw elseif k = "both" : filldraw else : fill fi + if l = "middle" : + midarrowhead p ; + elseif l = "percentage" : + arrowheadonpath (p, (getparameter "percentage")/100) ; + elseif l = "both" : + arrowhead p ; + if k = "draw" : draw elseif k = "both" : filldraw else : fill fi + arrowhead reverse p ; + else : + arrowhead p ; + fi ; + popparameters ; + ) +enddef ; + +% from dum + +presetparameters "placeholder" [ + color = "red", + width = 1, + height = 1, + reduction = 0, + alternative = "circle", +] ; + +def lmt_placeholder = applyparameters "placeholder" "lmt_do_placeholder" enddef ; + +def lmt_do_placeholder = + begingroup ; + pushparameters "placeholder" ; + save w, h, d, r, p, c, b, s, q, a ; + numeric w, h, d, r ; path p ; string s, a ; + s := getparameter "color" ; + w := getparameter "width" ; + h := getparameter "height" ; + r := getparameter "reduction" ; + a := getparameter "alternative" ; + d := max(w,h) ; + if cmykcolor resolvedcolor(s) : + cmykcolor c, b ; b := (0,0,0,0) + else : + color c, b ; b := (1,1,1) + fi ; + c := resolvedcolor(s) ; + p := unitsquare xyscaled (w,h) ; + fill p withcolor r[.5c,b] ; + if a = "square" : + vardef q = fullsquare enddef ; + elseif a = "triangle" : + vardef q = fulltriangle rotated (90 * round(uniformdeviate(4))) enddef ; + else : + vardef q = fullcircle enddef ; + fi ; + for i := 1 upto 60 : + fill q + scaled (d/5 randomized (d/5)) + shifted (center p randomized (d)) + withcolor r[c randomized(.3,.9),b] ; + endfor ; + clip currentpicture to p ; + popparameters ; + endgroup ; +enddef ; + +% maybe: + +vardef lmt_connected(text t) = + save p ; path p ; + p := origin t ; + subpath (1,length(p)) of p +enddef ; + +def lmt_connection expr t = + -- t +enddef ; + +% also (todo) + +% % draw lmt_path [ +% % points = [ color = "darkred", size = 6 ], +% % controls = [ color = "darkgreen", size = 4 ], +% % lines = [ color = "darkgray", size = 1 ], +% % shape = [ color = "middlegray", size = 8 ], +% % labels = [ ], +% % path = ((1cm,1cm) -- (1.5cm,1.5cm) .. (2cm,0cm) .. cycle) +% % ] ; +% +% presetparameters "path" [ +% labels = [ +% color = "", +% size = 1 +% ], +% controls = [ +% color = "black", +% size = 2.5 +% ], +% lines = [ +% color = "middlegray", +% size = 1 +% ], +% points = [ +% color = "black", +% size = 4 +% ], +% path = [ +% color = "lightgray", +% size = 5, +% path = origin +% ] +% ] ; +% +% def lmt_path = applyparameters "path" "lmt_do_path" enddef ; +% +% vardef lmt_do_path = +% image ( +% % This one is not that efficient ... we can better inline the drawing routines here, but +% % it's just an interfacing test after all. +% if hasparameter "path" "path" : +% save p ; path p ; p := getparameter "path" "path" ; +% drawpath p +% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "shape" "size" "*") +% withcolor getparameterdefault "path" "shape" "color" "*" +% ; +% if hasparameter "path" "controls" : +% drawcontrollines p +% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "lines" "size" "*" ) +% withcolor getparameterdefault "path" "lines" "color" "*" +% ; +% drawcontrolpoints p +% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "controls" "size" "*") +% withcolor getparameterdefault "path" "controls" "color" "*" +% ; +% fi ; +% if hasparameter "path" "points" : +% drawpoints p +% withpen pencircle scaled (drawoptionsfactor * getparameterdefault "path" "points" "size" "*") +% withcolor getparameterdefault "path" "points" "color" "*" +% ; +% if hasparameter "path" "labels" : +% drawpointlabels p +% withcolor getparameterdefault "path" "labels" "color" "*" +% ; +% fi ; +% fi ; +% fi ; +% ) +% enddef ; + +% Here we use nodraw and dodraw to create efficient axis ticks. Yet another demo +% of coding. + +presetparameters "function" [ + sx = 1mm, + sy = 1mm, + offset = 0, + xmin = 1, + xmax = 1, + xstep = 1, + xsmall = 0, + xlarge = 0, + xlabels = "no", + xticks = "bottom", % top bottom middle + xcaption = "", + ymin = 1, + ymax = 1, + ystep = 1, + ysmall = 0, + ylarge = 0, + % xfirst = 0, + % xlast = 0, + % yfirst = 0, + % ylast = 0, + ylabels = "no", + yticks = "left", % left right middle + ycaption = "", + code = "", + close = false, + shape = "curve", + fillcolor = "", + drawsize = 1, + drawcolor = "", + frame = "", % yes ticks + linewidth = .05mm, + pointsymbol = "", + pointsize = 2, + pointcolor = "", + xarrow = "", + yarrow = "", + reverse = false, +] ; + +def lmt_function = applyparameters "function" "lmt_do_function" enddef ; + +vardef lmt_do_function_p(expr xmin, xmax, xstep, code, shape, close, fcolor, dsize, dcolor, psymbol, psize, pcolor) = + save p, q ; path p, q ; + p := lua.mp.lmt_function_x(xmin,xmax,xstep,code,shape) ; + if close : + q := (xmin,0) -- p -- (xmax,0) -- cycle ; + fill q withcolor fcolor ; + else : + draw p withpen currentpen scaled dsize withcolor dcolor + ; + fi ; + if psize > 0 : + if psymbol = "dot" : + draw image ( + for i = 0 upto length(p) : + draw point i of p ; + endfor ; + ) withpen currentpen scaled psize withcolor pcolor ; + fi ; + fi ; +enddef ; + +vardef lmt_do_function = + image ( + pushparameters "function" ; + save sx, sy, lw, tl, tr, ts, tt, currentpen ; transform tr, tt ; pen currentpen ; + sx := getparameter "sx" ; + sy := getparameter "sy" ; + lw := getparameter "linewidth" ; + tl := 1/20 ; % tick length + ts := 1/10 ; % text scale + tr := identity xyscaled(10/sx,10/sy) ; + tt := identity xyscaled(ts/sx,ts/sy) ; + pickup pencircle xyscaled(lw/sx,lw/sy) ; + draw image ( + save xmin, xmax, xstep, xsmall, xlarge, ymin, ymax, ystep, ysmall, ylarge, p ; + save code, option, txl, txs, tyl, tys, swap ; + string code, option ; + path txl, txs, tyl, tys ; boolean swap ; + picture p ; + + xmin := getparameter "xmin" ; + xmax := getparameter "xmax" ; + xstep := getparameter "xstep" ; + xsmall := getparameter "xsmall" ; + xlarge := getparameter "xlarge" ; + ymin := getparameter "ymin" ; + ymax := getparameter "ymax" ; + ystep := getparameter "ystep" ; + ysmall := getparameter "ysmall" ; + ylarge := getparameter "ylarge" ; + code := getparameter "code" ; + swap := getparameter "reverse" ; + + p := image ( + + if (getparametercount "functions") > 0 : + for s = 1 upto getparametercount "functions" : + pushparameters "functions" s ; + lmt_do_function_p ( + getparameterdefault "xmin", + getparameterdefault "xmax", + getparameterdefault "xstep", + getparameterdefault "code", + getparameterdefault "shape", + getparameterdefault "close", + getparameterdefault "fillcolor", + getparameterdefault "drawsize", + getparameterdefault "drawcolor", + getparameterdefault "pointsymbol", + getparameterdefault "pointsize", + getparameterdefault "pointcolor" + ) ; + popparameters ; + endfor ; + elseif code <> "" : + lmt_do_function_p ( + getparameter "xmin", + getparameter "xmax", + getparameter "xstep", + getparameter "code", + getparameter "shape", + getparameter "close", + getparameter "fillcolor", + getparameter "drawsize", + getparameter "drawcolor", + getparameter "pointsymbol", + getparameter "pointsize", + getparameter "pointcolor" + ) ; + fi ; + ) ; + + if not swap : draw p fi ; + + option := getparameter "xticks" ; + if option = "top" : + txs := (0,0) -- (0,tl) ; + elseif option = "bottom" : + txs := (0,-tl) -- (0,0) ; + else : + txs := (0,-tl) -- (0,tl) ; + fi ; + + option := getparameter "yticks" ; + if option = "left" : + tys := (-tl,0) -- (0,0) ; + elseif option = "right" : + tys := (0,0) -- (tl,0) ; + else : + tys := (-tl,0) -- (tl,0) ; + fi ; + + txs := txs transformed tr ; + tys := tys transformed tr ; + txl := txs scaled 2 ; + tyl := tys scaled 2 ; + + % this arrow head scaling is for Alan to sort out ... + + xmin := getparameterdefault "xfirst" xmin ; + xmax := getparameterdefault "xlast" xmax ; + ymin := getparameterdefault "yfirst" ymin ; + ymax := getparameterdefault "ylast" ymax ; + + if hasoption "frame" "ticks,sticks" : + if xsmall > 0 : + if hasoption "frame" "horizontal" : + for i = ymin step ((ymax-ymin)/ysmall) until ymax : + draw (xmin,i) -- (xmax,i) ; + endfor ; + dodraw (xmin,ymin) ; % flush snippets + fi ; + fi ; + if ysmall > 0 : + if hasoption "frame" "vertical" : + for i = xmin step ((xmax-xmin)/xsmall) until xmax : + draw (i,ymin) -- (i,ymax) ; + endfor ; + dodraw (xmin,ymin) ; % flush snippets + fi ; + fi ; + fi ; + + option := getparameter "xarrow" ; + if option = "yes" : + save ahlength ; ahlength := tl ; + % save ahangle ; ahangle := 100/sy ; + drawarrow (xmin,0) -- (xmax,0) ; + else : + draw (xmin,0) -- (xmax,0) ; + fi ; + + option := getparameter "yarrow" ; + if option = "yes" : + save ahlength ; ahlength := tl ; + % save ahangle ; ahangle := 100/sx ; + drawarrow (xmin,ymin) -- (xmin,ymax) ; + else : + draw (xmin,ymin) -- (xmin,ymax) ; + fi ; + + if hasoption "frame" "yes" : + draw (xmin,ymin) -- (xmax,ymin) -- (xmax,ymax) -- (xmin,ymax) -- cycle ; + fi ; + + if hasoption "frame" "ticks,sticks" : + if xsmall > 0 : + if hasoption "frame" "horizontal" : + for i = ymin step ((ymax-ymin)/ysmall) until ymax : + draw (xmin,i) -- (xmax,i) ; + endfor ; + fi ; + if hasoption "frame" "bottom" : + txs := ((0,0) -- (0,tl)) if hasoption "frame" "sticks" : rotated 180 fi ; + txs := txs transformed tr ; + for i = xmin step ((xmax-xmin)/xsmall) until xmax : + nodraw txs shifted (i,ymin) ; + endfor ; + fi ; + if hasoption "frame" "top" : + txs := (0,0) -- (0,-tl) if hasoption "frame" "sticks" : rotated 180 fi ; + txs := txs transformed tr ; + for i = xmin step ((xmax-xmin)/xsmall) until xmax : + nodraw txs shifted (i,ymax) ; + endfor ; + fi ; + dodraw (xmin,ymin) ; % flush snippets + fi ; + if ysmall > 0 : + if hasoption "frame" "vertical" : + for i = xmin step ((xmax-xmin)/xsmall) until xmax : + draw (i,ymin) -- (i,ymax) ; + endfor ; + fi ; + if hasoption "frame" "left" : + tys := (0,0) -- (tl,0) if hasoption "frame" "sticks" : rotated 180 fi ; + tys := tys transformed tr ; + for i = ymin step ((ymax-ymin)/ysmall) until ymax : + nodraw tys shifted (xmin,i) ; + endfor ; + fi ; + if hasoption "frame" "right" : + tys := (0,0) -- (-tl,0) if hasoption "frame" "sticks" : rotated 180 fi ; + tys := tys transformed tr ; + for i = ymin step ((ymax-ymin)/ysmall) until ymax : + nodraw tys shifted (xmax,i) ; + endfor ; + fi ; + dodraw (xmin,ymin) ; % flush snippets + fi ; + fi ; + + if xsmall > 0 : + for i = xmin step xsmall until xmax : + nodraw txs shifted (i,0) ; + endfor ; + fi ; + + if xlarge > 0 : + for i = xmin step xlarge until xmax : + nodraw txl shifted (i,0) ; + endfor ; + dodraw (xmin,0) ; % flush snippets + elseif xsmall > 0 : + dodraw (xmin,0) ; % flush snippets + fi ; + + if ysmall > 0 : + for i = ymin step ysmall until ymax : + nodraw tys shifted (xmin,i) ; + endfor ; + fi ; + + if ylarge > 0 : + for i = ymin step ylarge until ymax : + nodraw tyl shifted (xmin,i) ; + endfor ; + dodraw (xmin,ymin) ; % flush snippets + elseif ysmall > 0 : + dodraw (xmin,ymin) ; % flush snippets + fi ; + + if swap : draw p fi ; + + if xlarge > 0 : + option := getparameter "xlabels" ; + if option <> "no" : + for i = xmin step xlarge until xmax : + if ((i <> 0) and ((option <> "nolimits") or ((i > xmin) and (i < xmax)))) : + draw textext.bot(decimal i) transformed tt + shifted (i,1.25*(ypart point 0 of txl)) ; + fi ; + endfor ; + fi ; + fi ; + + if ylarge > 0 : + option := getparameter "ylabels" ; + if option <> "no" : + for i = ymin step ylarge until ymax : + if ((i <> 0) and ((option <> "nolimits") or ((i > ymin) and (i < ymax)))) : + draw textext.lft(decimal i) transformed tt + shifted (xmin+1.25*(xpart point 0 of tyl),i) ; + fi ; + endfor ; + fi ; + fi ; + + option := getparameter "xcaption" ; + if (option <> "") : + draw textext.bot(option) transformed tt + shifted (xmin,-tl) + shifted center bottomboundary currentpicture ; + fi ; + + option := getparameter "ycaption" ; + if (option <> "") : + draw textext.lft(option) transformed tt + shifted (xmin-tl,0) + shifted center leftboundary currentpicture ; + fi ; + ) + + xyscaled(sx,sy) ; + + setbounds currentpicture to + boundingbox currentpicture + enlarged (getparameter "offset") ; + + popparameters ; + ) +enddef ; + +% Don't use this one! + +presetparameters "mesh" [ + trace = false, + auto = false, + step = 0.05, + % box = ... + % paths = { ..., ..., ... } +] ; + +def lmt_mesh = applyparameters "mesh" "lmt_do_mesh" enddef ; + +vardef lmt_do_mesh = + image ( + save p, b ; path p, b ; + pushparameters "mesh" ; + if getparameter "auto" : + b := if hasparameter "box" : getparameter "box" else : OverlayBox fi ; + for i=1 upto getparametercount "paths" : + p := getparameter "paths" i ; + p := meshed(p if not cycle p : -- cycle fi,b,getparameter "step") ; + if getparameter "trace" : + draw p ; + fi ; + runscript("mp.lmt_mesh_update()") i p ; + endfor ; + elseif getparameter "trace" : + for i=1 upto getparametercount "paths" : + p := getparameter "paths" i ; + draw p if not cycle p : -- cycle fi ; + endfor ; + fi ; + popparameters ; + runscript("mp.lmt_mesh_set()") ; + ) +enddef ; + +vardef mfun_meshed_clipped(expr pat, box, pct) = + pp := point (arctime pct of pat) of pat ; + if (ypart pp <= lly) or (ypart pp >= ury) or (xpart pp <= llx) or (xpart pp >= urx) : + (cp -- pp) intersection_point bb + else : + pp + fi +enddef ; + +vardef mfun_meshed_clipped(expr pat, box, pct) = + pp := point (arctime pct of pat) of pat ; + if ypart pp <= lly : + if xpart pp <= llx : + (llx, lly) + elseif xpart pp >= urx : + (urx, lly) + else : + (xpart pp, lly) + fi + elseif ypart pp >= ury : + if xpart pp <= llx : + (llx, ury) + elseif xpart pp >= urx : + (urx, ury) + else : + (xpart pp, ury) + fi + elseif xpart pp <= llx : + (llx, ypart pp) + elseif xpart pp >= urx : + (urx, ypart pp) + else : + pp + fi +enddef ; + +vardef meshed(expr pth, box, stp) = + begingroup + save cb, cp, llx, lly, urx, ury, pp, lp, bb ; pair cb, cp, pp ; path bb ; + bb := box enlarged -1/10; + cb := center bb ; + cp := center pth ; + llx := xpart llcorner bb; + lly := ypart llcorner bb; + urx := xpart urcorner bb; + ury := ypart urcorner bb; + lp := arclength pth ; + for i=stp step stp until 1+stp/2 : + cp -- + mfun_meshed_clipped(pth,bb,lp*(i-stp)) -- + mfun_meshed_clipped(pth,bb,lp*(i )) -- + cp -- + endfor cycle + endgroup +enddef ; + +vardef OverlayMesh(expr p, s) = + lmt_mesh [ paths = { meshed(p,OverlayBox,s) } ] +enddef ; + +% charts + +presetparameters "chart" [ + originsize = 1mm, + trace = false, + showlabels = true, + center = false, + + samples = { }, + + cumulative = false, + percentage = false, + maximum = 0, + distance = 1mm, + + % labels = { }, + labelstyle = "", + labelformat = "", + % labelstrut = "auto", + % labelanchor = "", + % labeloffset = 0, + labelfraction = 0.8, + labelcolor = "", + + backgroundcolor = "", + drawcolor = "white", + fillcolors = { % use color palet + "darkred", "darkgreen", "darkblue", + "darkyellow", "darkmagenta", "darkcyan", + "darkgray" + }, + colormode = "global", + + linewidth = .25mm, + + legendcolor = "", + legendstyle = "", + legend = { }, +] ; + +presetparameters "chart:circle" "chart" [ + height = 5cm, + width = 5mm, + labelanchor = "", + labeloffset = 0, + labelstrut = "no", +] ; + +presetparameters "chart:histogram" "chart" [ + height = 5cm, + width = 5mm, + labelanchor = "bot", + labeloffset = 1mm, + labelstrut = "auto", +] ; + +presetparameters "chart:bar" "chart" [ + height = 5mm, + width = 5cm, + labelanchor = "lft", + labeloffset = 1mm, + labelstrut = "no", +] ; + +def lmt_chart_circle = applyparameters "chart:circle" "lmt_do_chart_circle" enddef ; +def lmt_chart_histogram = applyparameters "chart:histogram" "lmt_do_chart_histogram" enddef ; +def lmt_chart_bar = applyparameters "chart:bar" "lmt_do_chart_bar" enddef ; + +def lmt_do_chart_start (expr what) = + pushparameters what ; + save width, height, distance, linewidth, labelgap, labelfraction, value, nofsamples, nofsamplesets ; + save fillcolor, drawcolor, labelcolor, labelstyle, labelformat, labelstrut, labelanchor, colormode ; + string fillcolor, drawcolor, labelcolor, labelstyle, labelformat, labelstrut, labelanchor, colormode ; + height := getparameter "height" ; + width := getparameter "width" ; + distance := getparameter "distance" ; + linewidth := getparameter "linewidth" ; + drawcolor := getparameter "drawcolor" ; + colormode := getparameter "colormode" ; + labelcolor := getparameter "labelcolor" ; + labelgap := getparameter "labeloffset" ; + labelstyle := getparameter "labelstyle" ; + labelformat := getparameter "labelformat" ; + labelstrut := getparameter "labelstrut" ; + labelanchor := getparameter "labelanchor" ; + labelfraction := getparameter "labelfraction" ; + nofsamplesets := getparametercount "samples" ; + nofsamples := getmaxparametercount "samples" ; +enddef ; + +def lmt_do_chart_stop = + if getparameter "center" : + currentpicture := currentpicture shifted - center currentpicture ; + fi + if (getparameter "backgroundcolor") <> "" : + addbackground withcolor getparameter "backgroundcolor" ; + fi + if getparameter "trace" : + save b ; path b ; b := boundingbox currentpicture ; + draw image ( + draw fullcircle scaled 1mm ; + draw b + ) + dashed evenly scaled 1/4 + withpen pencircle scaled .125mm + withcolor "darkgray" ; + fi + popparameters ; +enddef ; + +vardef lmt_do_chart_text(expr s, i, value) = + lmt_text [ + style = labelstyle, + format = labelformat, + strut = labelstrut, + anchor = labelanchor, + offset = labelgap, + color = labelcolor, + text = (getparameterdefault "labels" s i (decimal value)) + background = "", + ] +enddef ; + +def lmt_do_chart_legend = + n := getparametercount "legend" ; + if n > 0 : + save dx, dy, p, l, w, o, d, ddy ; picture l ; + dx := xpart urcorner currentpicture + EmWidth ; + dy := ypart urcorner currentpicture ; + labelcolor := getparameter "legendcolor" ; + labelstyle := getparameter "legendstyle" ; + w := 2EmWidth ; + o := .25EmWidth ; + d := ExHeight ; + ddy := .8LineHeight ; + for i=1 upto n : + dy := dy - ddy ; + l := lmt_text [ + text = getparameter "legend" i, + anchor = "rt" + style = labelstyle, + color = labelcolor, + background = "", + ] ; + fill leftboundary l rightenlarged w + shifted (dx,dy+d) + withcolor getparameter "fillcolors" i ; + draw l + shifted (dx+w+o,dy+d) ; + endfor ; + fi ; +enddef ; + +vardef lmt_do_chart_circle = + image ( + lmt_do_chart_start("chart:circle") ; + if (nofsamplesets > 0) and (nofsamples > 0) : + nofsamplesets := 1 ; + save p, r, s, first, last, total, factor, n, percentage ; + path p, r, s[] ; boolean percentage ; + percentage := getparameter "percentage" ; + total := 0 ; + for i = 1 upto nofsamples : + total := total + getparameter "samples" (1) i ; % () is needed else 1i + endfor ; + factor := 100/total ; + first := 0 ; + p := fullcircle ysized (height) ; + r := origin -- (2*height,0) ; + for i = 1 upto nofsamples : + fillcolor := getparameter "fillcolors" i ; + value := (getparameter "samples" (1) i) * factor ; + last := first + (360 / 100) * value ; + s[i] := ((p cutbefore (r rotated first)) cutafter (r rotated last)) ; + fill origin -- s[i] -- cycle withcolor fillcolor ; + first := last ; + endfor ; + if linewidth > 0 : + if drawcolor = "" : + drawcolor := backgroundcolor ; + fi ; + for i = 1 upto nofsamples : + interim linecap := butt ; + draw origin -- (point 0 of s[i]) withpen pencircle scaled linewidth withcolor drawcolor ; + draw origin -- (point length(s[i]) of s[i]) withpen pencircle scaled linewidth withcolor drawcolor ; + endfor ; + fi ; + if getparameter "showlabels" : + first := 0 ; + for i = 1 upto nofsamples : + value := getparameter "samples" (1) i ; + last := first + (360/100) * value * factor ; + draw lmt_do_chart_text (s,i,value) + shifted ((labelfraction*(height/2),0) rotated ((first+last)/2)) ; + first := last ; + endfor ; + fi ; + lmt_do_chart_legend ; + n := getparameter "originsize" ; + if n > 0 : + fill fullcircle scaled n withcolor "white" ; + fi ; + fi ; + lmt_do_chart_stop ; + ) +enddef ; + +vardef lmt_do_chart_histogram = + image ( + lmt_do_chart_start("chart:histogram") ; + if (nofsamplesets > 0) and (nofsamples > 0) : + save value, maximum, cumulative, maxwidth ; boolean cumulative ; + maximum := getparameter "maximum" ; + cumulative := getparameter "cumulative" ; + if labelanchor = "center" : + labelanchor := "vcenter" ; + fi ; + if maximum = 0 : + for s = 1 upto nofsamplesets : + for i = 1 upto nofsamples : + value := getparameter "samples" s i ; + maximum := if cumulative : + maximum + value ; + else : + max(maximum,value) ; + fi ; + endfor ; + endfor ; + fi ; + if nofsamplesets = 1 : + distance := 0 ; + fi ; + maxwidth := nofsamplesets * nofsamples * width + (nofsamples - 1)* distance ; + value := 0 ; + for s = 1 upto nofsamplesets : + for i = 1 upto nofsamples : + value := if cumulative : value + fi (getparameter "samples" s i) * height / maximum ; + fill unitsquare xyscaled (width,value) + if linewidth > 0 : + if i > 1 : leftenlarged (-linewidth/2) fi + if i < nofsamples : rightenlarged (-linewidth/2) fi + fi + shifted (nofsamplesets*(i-1)*width+(s-1)*width+(i-1)*distance,0) + withcolor getparameter "fillcolors" if colormode = "local" : s else : i fi ; + endfor ; + endfor ; + setbounds currentpicture to unitsquare xyscaled (maxwidth,height) ; + for s = 1 upto nofsamplesets : + if getparameter "showlabels" : + for i = 1 upto nofsamples : + draw lmt_do_chart_text (s,i,getparameter "samples" s i) + shifted (nofsamplesets*((i-1)*width)+width/2+(s-1)*width+(i-1)*distance,0) ; + endfor ; + fi ; + endfor ; + lmt_do_chart_legend ; + fi ; + lmt_do_chart_stop ; + ) +enddef ; + +vardef lmt_do_chart_bar = + + image ( + lmt_do_chart_start("chart:bar") ; + if (nofsamplesets > 0) and (nofsamples > 0) : + save value, maximum, cumulative, maxheight ; boolean cumulative ; + maximum := getparameter "maximum" ; + cumulative := getparameter "cumulative" ; + if labelanchor = "center" : + labelanchor := "hcenter" ; + fi ; + if maximum = 0 : + for s = 1 upto nofsamplesets : + for i = 1 upto nofsamples : + value := getparameter "samples" s i ; + maximum := if cumulative : maximum + value else : max(maximum,value) fi ; + endfor ; + endfor ; + fi ; + if nofsamplesets = 1 : + distance := 0 ; + fi ; + maxheight := nofsamplesets * nofsamples * height + (nofsamples - 1)* distance ; + for s = 1 upto nofsamplesets : + value := 0 ; + for i = 1 upto nofsamples : + value := if cumulative : value + fi (getparameter "samples" s i) * width / maximum ; + fill unitsquare xyscaled (value,height) + if linewidth > 0 : + if i > 1 : topenlarged (-linewidth/2) fi + if i < nofsamples : bottomenlarged (-linewidth/2) fi + fi + shifted (0,maxheight-nofsamplesets*i*height+(s-1)*height-(i-1)*distance) + withcolor getparameter "fillcolors" if colormode = "local" : s else : i fi ; + endfor ; + endfor ; + setbounds currentpicture to unitsquare xyscaled (width,maxheight) ; + if getparameter "showlabels" : + for s = 1 upto nofsamplesets : + for i = 1 upto nofsamples : + draw lmt_do_chart_text (s,i,getparameter "samples" s i) + shifted (0,maxheight-nofsamplesets*(i*height)+height/2+(s-1)*height-(i-1)*distance) ; + endfor ; + endfor ; + fi ; + lmt_do_chart_legend ; + fi ; + lmt_do_chart_stop ; + ) +enddef ; + +%D This one is more complex than needed but I want to trace so I need all those +%D variables. + +presetparameters "shade" [ + alternative = "circular", + path = origin -- cycle, + trace = false + + % alternative = "circular" | "linear" + % domain = { a, b } + % radius = a | { a, b } + % factor = a + % origin = (a,b) | { (a,b), {c, d) } + % vector = { a, b } + % colors = { a, b } + % center = a | { a, b } + % direction = "up" | "down" | "left" | "right" | { a, b } + +] ; + +% TODO: pass colors as strings + +def lmt_shade = applyparameters "shade" "lmt_do_shade" enddef ; + +vardef lmt_do_shade = + image ( + pushparameters "shade" ; + + save domain_min, domain_max, radius_a, radius_b, factor ; + save color_a, color_b, center_a, center_b, alternative, s ; + string color_a, color_b, alternative, s ; pair center_a, center_b ; + + alternative := getparameter "alternative" ; + + mfun_with_shade_method_analyze(getparameter "path") ; + + domain_min := 0 ; + domain_max := 1 ; + + color_a := "white" ; + color_b := "black" ; + + if alternative = "circular" : + center_a := center mfun_shade_path ; + center_b := center_a ; + radius_a := 0 ; + radius_b := mfun_max_radius(mfun_shade_path) ; + factor := 1.2 ; + else : + center_a := llcorner mfun_shade_path ; + center_b := urcorner mfun_shade_path ; + radius_a := 0 ; + radius_b := 0 ; + factor := 0; + fi ; + + if hasparameter "domain" : + domain_min := getparameter "domain" 1 ; + domain_max := getparameter "domain" 2 ; + fi + if hasparameter "radius" : + if numeric getparameter "radius" : + radius_a := 0 ; + radius_b := getparameter "radius" ; + else : + radius_a := getparameter "radius" 1 ; + radius_b := getparameter "radius" 2 ; + fi ; + factor := 1 ; + fi + if hasparameter "factor" : + factor := getparameter "factor" ; + fi + if hasparameter "origin" : + if pair getparameter "origin" : + center_a := getparameter "origin" ; + center_b := center_b ; + else : + center_a := getparameter "origin" 1 ; + center_b := getparameter "origin" 2 ; + fi ; + fi + if hasparameter "colors" : + color_a := getparameter "colors" 1 ; + color_b := getparameter "colors" 2 ; + fi + if hasparameter "direction" : + save a, b, bb ; path bb ; + bb := boundingbox(mfun_shade_path) ; + a := b := -1 ; + if string getparameter "direction" : + s := getparameter "direction" ; + if s = "up" : + p_a := xpart shadedup ; + p_b := ypart shadedup ; + elseif s = "down" : + p_a := xpart shadeddown ; + p_b := ypart shadeddown ; + elseif s = "left" : + p_a := xpart shadedleft ; + p_b := ypart shadedleft ; + elseif s = "right" : + p_a := xpart shadedright ; + p_b := ypart shadedright ; + fi + else : + p_a := getparameter "direction" 1 ; + p_a := getparameter "direction" 2 ; + fi + if p_a >= 0 : + center_a := point p_a of bb ; + fi + if p_b >= 0 : + center_b := point p_b of bb ; + fi + fi ; + if hasparameter "center" : + save cx, cy ; + if numeric getparameter "center" : + cx := getparameter "center" ; + cx := cy ; + % elseif pair getparameter "center" : + % cx := xpart getparameter "center" ; + % cy := ypart getparameter "center" ; + else : + cx := getparameter "center" 1 ; + cy := getparameter "center" 2 ; + fi + center_a := center mfun_shade_path shifted ( + cx * bbwidth (mfun_shade_path)/2, + cy * bbheight(mfun_shade_path)/2 + ) ; + elseif hasparameter "vector" : + center_a := point (getparameter "vector" 1) of mfun_shade_path ; + center_b := point (getparameter "vector" 2) of mfun_shade_path ; + fi + fill mfun_shade_path + withprescript "sh_domain=" & decimal domain_min & " " & decimal domain_max + withprescript "sh_transform=yes" + withprescript "sh_color=into" + withprescript "sh_color_a=" & colordecimals color_a + withprescript "sh_color_b=" & colordecimals color_b + withprescript "sh_first=" & ddecimal point 0 of mfun_shade_path % used for support scaling + withprescript "sh_set_x=" & ddecimal (mfun_shade_nx,mfun_shade_lx) % + withprescript "sh_set_y=" & ddecimal (mfun_shade_ny,mfun_shade_ly) % + if alternative = "linear" : + withprescript "sh_type=linear" + % withprescript "sh_factor=1" + withprescript "sh_factor=" & decimal factor + withprescript "sh_center_a=" & ddecimal center_a + withprescript "sh_center_b=" & ddecimal center_b + else : + withprescript "sh_type=circular" + % withprescript "sh_factor=1.2" + withprescript "sh_factor=" & decimal factor + withprescript "sh_center_a=" & ddecimal center_a + withprescript "sh_center_b=" & ddecimal center_b + withprescript "sh_radius_a=" & decimal radius_a + withprescript "sh_radius_b=" & decimal radius_b + fi ; + if getparameter "trace" : + draw fullcircle scaled 1mm shifted center_a ; + draw fullsquare scaled 2mm shifted center_b ; + draw textext.top("\strut\ttx center a") ysized LineHeight shifted center_a shifted (0, 2mm) ; + draw textext.bot("\strut\ttx center b") ysized LineHeight shifted center_b shifted (0,-2mm) ; + if alternative = "circular" : +% draw fullcircle scaled ( radius_a * 2) shifted center_a dashed evenly ; +% draw fullcircle scaled (factor * radius_b * 2) shifted -center_b dashed evenly ; + draw fullcircle scaled ( radius_a) shifted center_a dashed evenly ; + draw fullcircle scaled (factor * radius_b) shifted -center_b dashed evenly ; + fi + fi + popparameters ; + ) +enddef ; + +% This is very experimental and will first be tested by a few users who +% are interested in this. + +presetparameters "contour" [ + xmin = 0, + xmax = 0, + ymin = 0, + ymax = 0, + xstep = 0, + ystep = 0, + levels = 10, + % colors = { }, % used when set + preamble = "", + function = "x + y", + color = "lin(l)", % l/n + background = "bitmap", % bitmap | shape | band + foreground = "auto", % cell| edge | shape | auto: bitmap/edge shape/shape + linewidth = .25, + backgroundcolor = "black", + linecolor = "gray", + xformat = "@0.2N", + yformat = "@0.2N", + zformat = "@0.2N", + xstyle = "", + ystyle = "", + zstyle = "", + + width = 0, % auto when 0 + height = 0, % auto when 0 + + trace = false, + checkresult = false, + defaultnan = 0, + defaultinf = 0, + + legend = "all", % x | y | z | function | range | all (but range) + legendheight = LineHeight, + legendwidth = LineHeight, + legendgap = 0, + legenddistance = EmWidth, + textdistance = 2EmWidth/3, + functiondistance = ExHeight, + functionstyle = "", + + level = 4096, % for selecting one (can't be too large for scaled) + + axisdistance = ExHeight, + axislinewidth = .25, + axisoffset = ExHeight/4, + axiscolor = "black", + ticklength = ExHeight, + + xtick = 5, + ytick = 5, + xlabel = 5, + ylabel = 5, + +] ; + +% we can as well push ... + +def lmt_contour = applyparameters "contour" "lmt_do_contour" enddef ; + +def mfun_only_draw = addto currentpicture doublepath enddef ; +def mfun_only_fill = addto currentpicture contour enddef ; +def mfun_only_fillup text t = addto currentpicture doublepath t withpostscript "both" enddef ; +def mfun_only_nodraw text t = addto currentpicture doublepath t withpostscript "collect" enddef ; +def mfun_only_nofill text t = addto currentpicture contour t withpostscript "evenodd" enddef ; +def mfun_only_eofill text t = addto currentpicture contour t withpostscript "collect" enddef ; + +def lmt_do_contour_shortcuts = + save D ; let D = mfun_only_draw ; + save E ; let E = mfun_only_eofill ; + save F ; let F = mfun_only_fill ; + save U ; let U = mfun_only_fillup ; + save d ; let d = mfun_only_nodraw ; + save e ; let f = mfun_only_eofill ; + save f ; let f = mfun_only_nofill ; + save C ; let C = cycle ; + save B ; let B = controls ; + save A ; let A = and ; +enddef ; + +def lmt_do_contour_band = + lua.mp.lmt_contours_edge_set_by_band() ; + for v=1 upto lua.mp.lmt_contours_nofvalues() : + draw image ( + lua.mp.lmt_contours_edge_get_band(v) ; + ) + withcolor lua.mp.lmt_contours_color(v) ; + endfor ; +enddef; + +def lmt_do_contour_cell(expr dx,dy) = + lua.mp.lmt_contours_edge_set_by_cell() ; + draw image ( + if level = 4096 : + for v=1+1 upto lua.mp.lmt_contours_nofvalues() : + lua.mp.lmt_contours_edge_get_cell(v) ; + endfor ; + else : + lua.mp.lmt_contours_edge_get_cell(level) ; + fi + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withcolor getparameter "linecolor" + withpen pencircle scaled getparameter "linewidth" ; +enddef ; + +def lmt_do_contour_edge(expr dx, dy) = + lua.mp.lmt_contours_edge_set() ; + draw image ( + if level = 4096 : + for v=1+1 upto lua.mp.lmt_contours_nofvalues() : + lua.mp.lmt_contours_edge_paths(v); + endfor ; + else : + lua.mp.lmt_contours_edge_paths(level); + fi + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withcolor getparameter "linecolor" + withpen pencircle scaled getparameter "linewidth" ; +enddef ; + +def lmt_do_contour_edges(expr dx, dy) = + lua.mp.lmt_contours_edge_set() ; + if level = 4096 : + for v=1+1 upto lua.mp.lmt_contours_nofvalues() : + draw image ( + lua.mp.lmt_contours_edge_paths(v); + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withpen pencircle scaled getparameter "linewidth" + withcolor lua.mp.lmt_contours_color(v) ; + endfor ; + else : + draw image ( + lua.mp.lmt_contours_edge_paths(level); + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withpen pencircle scaled getparameter "linewidth" + withcolor lua.mp.lmt_contours_color(level) ; + fi ; +enddef ; + +def lmt_do_contour_cells(expr dx, dy) = + lua.mp.lmt_contours_edge_set_by_cell() ; + if level = 4096 : + for v=1+1 upto lua.mp.lmt_contours_nofvalues() : + draw image ( + lua.mp.lmt_contours_edge_get_cell(v) ; + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withpen pencircle scaled getparameter "linewidth" + withcolor lua.mp.lmt_contours_color(v) ; + endfor ; + else : + draw image ( + lua.mp.lmt_contours_edge_get_cell(level) ; + ) + if offset : shifted (-1/2,-1/2) fi + withpen pencircle scaled getparameter "linewidth" + withcolor lua.mp.lmt_contours_color(v) ; + fi ; +enddef ; + +def lmt_do_contour_shape(expr dx, dy) = + draw image ( + if level = 4096 : + for v=1+1 upto lua.mp.lmt_contours_nofvalues() : + lua.mp.lmt_contours_shape_paths(v); + endfor ; + else : + lua.mp.lmt_contours_shape_paths(level); + lua.mp.lmt_contours_shape_paths(1); + fi + ) + if (dx <>0) or (dy <> 0) : shifted (dx,dy) fi + withcolor getparameter "linecolor" + withpen pencircle scaled getparameter "linewidth" ; +enddef ; + +def lmt_do_contour_bitmap = + lua.mp.lmt_contours_bitmap_set() ; + lua.mp.lmt_contours_bitmap_get() ; +enddef ; + +def lmt_do_contour_shades(expr outlines) = + lua.mp.lmt_contours_shade_set(outlines) ; + if level = 4096 : + for v=1 upto lua.mp.lmt_contours_nofvalues() : % no + 1 here + draw image ( + lua.mp.lmt_contours_shade_paths(v) ; + ) + withpen pencircle scaled 0 + withcolor lua.mp.lmt_contours_color(v) ; + endfor ; + else : + draw image ( + lua.mp.lmt_contours_shade_paths(level); + ) + withpen pencircle scaled 0 + withcolor lua.mp.lmt_contours_color(level) ; + fi ; +enddef ; + +def lmt_load_mlib_cnt = + runscript("lua.registercode('mlib-cnt')"); + extra_beginfig := extra_beginfig & % todo: use different hook + "runscript(" & ditto & "mp.lmt_contours_cleanup()" & ditto & ")" ; + let lmt_load_mlib_cnt = relax ; +enddef ; + +vardef lmt_do_contour = + image ( + + lmt_load_mlib_cnt ; + + pushparameters "contour" ; + + lua.mp.lmt_contours_start() ; + + % graphic + + save bg, fg, nx, ny, trace, level, b, done ; string bg, fg ; boolean trace, done ; path b ; + + bg := getparameter "background" ; + fg := getparameter "foreground" ; + nx := lua.mp.lmt_contours_nx() ; + ny := lua.mp.lmt_contours_ny() ; + trace := getparameter "trace" ; + level := getparameter "level" ; + done := true ; + + begingroup ; + + lmt_do_contour_shortcuts ; + + if bg = "band" : + lmt_do_contour_band ; + b := boundingbox currentpicture ; + if (fg = "auto") or (fg = "cell") : + lmt_do_contour_cell(0,0) ; + elseif (fg = "edge") : + lmt_do_contour_edge(0,0) ; % true ? + fi ; + + elseif bg = "bitmap" : + + lmt_do_contour_bitmap ; + b := boundingbox currentpicture ; + if (fg = "auto") or (fg = "cell") : + lmt_do_contour_cell(-1/2,-1/2) ; + elseif (fg = "edge") : + lmt_do_contour_edge(-1/2,-1/2) ; + fi ; + + elseif bg = "shape" : + + lmt_do_contour_shades((fg = "auto") or (fg = "shape")) ; + b := boundingbox currentpicture ; + if (fg == "auto") or (fg = "shape") : + lmt_do_contour_shape(0,0) ; + elseif fg == "cell" : + lmt_do_contour_cell(-1,-1) ; + elseif fg == "edge" : + lmt_do_contour_edge(-1,-1) ; + fi ; + + % currentpicture := currentpicture reflectedabout ( (0, ny/2), (nx,ny/2) ) ; + + elseif fg = "cell" : + + lmt_do_contour_shortcuts ; + lmt_do_contour_cells(0,0) ; + b := boundingbox currentpicture ; + + elseif fg = "edge" : + + lmt_do_contour_shortcuts ; + lmt_do_contour_edges(0,0) ; + b := boundingbox currentpicture ; + + else : + + done := false ; + + fi ; + + endgroup ; + + if done : + + save w, h, cx, cy ; + + cx := - bbwidth (b)/(nx - 1) ; + cy := - bbheight(b)/(ny - 1) ; + clip currentpicture to b + leftenlarged cx rightenlarged cx + topenlarged cy bottomenlarged cy ; + currentpicture := currentpicture + shifted (cx,cy) ; + + w := getparameter "width" ; + h := getparameter "height" ; + + % axis + + save xtic, ytic, auto ; boolean auto ; + + xtic := getparameter "xtick" ; + ytic := getparameter "ytick" ; + auto := (w = 0) and (h = 0) ; + + % resize + + if w <> 0 : + if h <> 0 : + currentpicture := currentpicture xysized (w,h) ; + else : + currentpicture := currentpicture xsized w ; + fi ; + elseif h <> 0 : + currentpicture := currentpicture ysized h ; + fi ; + if w = 0 : + w := bbwidth(currentpicture) ; + fi ; + if h = 0 : + h := bbheight(currentpicture) ; + fi ; + + % legend + + if hasoption "legend" "all,x,y,z,range" : + + save u, s, sx, sy, ax, ay, ao, al, at, tl, ox, oy, lg, tx, ty, wx, hx, ry, fmt, pmin, pmax ; string fmt; picture pmin, pmax ; + + % move some in the ifs + + if hasoption "legend" "all,z" : + + % colorbar + + fmt := lua.mp.lmt_contours_format() ; + pmin := lmt_text [ format = fmt, text = decimal lua.mp.lmt_contours_minmean() ] ; + pmax := lmt_text [ format = fmt, text = decimal lua.mp.lmt_contours_maxmean() ] ; + wx := max(bbwidth(pmin),bbwidth(pmax)) ; + hx := bbheight(pmin) ; + + else : + + hx := 0; + + fi ; + + if auto : + % u := 1 ; + u := lua.mp.lmt_contours_ny() / 100 ; + ry := 4u ; + sy := 5u ; + sx := 5u ; + lg := 0 ; + ox := 5u ; + oy := - sy/2 + ry/2 ; + tx := 2u ; + ty := 1u ; + ax := 1u ; + ay := 1u ; + ao := u ; + al := u/8 ; + at := 3u/2 ; + al := u/4 ; + else : + ry := 0 ; + sy := getparameter "legendheight" ; + sx := getparameter "legendwidth" ; + lg := getparameter "legendgap" ; + ox := getparameter "legenddistance" ; + oy := - sy/2 + hx/2 ; + tx := getparameter "textdistance" ; + ty := getparameter "functiondistance" ; + ax := getparameter "axisdistance" ; + ay := ax ; + ao := getparameter "axisoffset" ; + at := getparameter "ticklength" ; + al := getparameter "axislinewidth" ; + fi ; + + if hasoption "legend" "all,z" : + + save dy ; dy := h ; + + for v=1 upto lua.mp.lmt_contours_nofvalues() : + dy := dy - sy ; + fill unitsquare xyscaled (sx,sy) + shifted (w+ox,dy) + withcolor lua.mp.lmt_contours_color(v) ; + draw + lmt_text [ + trace = trace, + anchor = "llft", + format = fmt, + text = decimal lua.mp.lmt_contours_value(v), + style = getparameter "zstyle", + position = (wx,0), + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (w+ox+tx+sx,dy+sy+oy) + ; + dy := dy - lg ; + endfor ; + + fi ; + + if hasoption "legend" "x,all" : + + save n, d, s, xmin, xmax, xlab ; + + xmin := getparameter "xmin" ; + xmax := getparameter "xmax" ; + xlab := getparameter "xlabel" ; + + draw image ( + interim linecap := butt ; + draw ((0,0) -- (w,0)) ; + n := al/2 ; s := (w - al) / xtic ; d := (xmax - xmin) / xtic ; + for i=xmin step d until xmax : + draw (n,0) -- (n,-at) ; + n := n + s ; + endfor ; + ) shifted (0,-ay) + withpen pencircle scaled al + withcolor getparameter "axiscolor" + ; + + if hasoption "legend" "label,all" : + + draw image ( + n := al/2 ; s := (w - al) / xlab ; d := (xmax - xmin) / xlab ; + for i=xmin step d until xmax : + draw lmt_text [ + trace = trace, + anchor = "bot", + format = getparameter "xformat", + style = getparameter "xstyle", + text = decimal i + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (n,-at-ao) + ; + n := n + s ; + endfor ; + ) shifted (0,-ay) ; + + fi ; + + fi ; + + if hasoption "legend" "y,all" : + + save n, d, s, ymin, ymax, ylab ; + + ymin := getparameter "ymin" ; + ymax := getparameter "ymax" ; + ylab := getparameter "ylabel" ; + + draw image ( + interim linecap := butt ; + draw ((0,0) -- (0,h)) ; + n := al/2 ; s := (h - al) / ytic ; d := (ymax - ymin) / ytic ; + for i=ymin step d until ymax : + draw (0,n) -- (-at,n) ; + n := n + s ; + endfor ; + ) shifted (-ax,0) + withpen pencircle scaled al + withcolor getparameter "axiscolor" ; + ; + + if hasoption "legend" "label,all" : + + draw image ( + n := al/2 ; s := (h - al) / ylab ; d := (ymax - ymin) / ylab ; + for i=ymin step d until ymax : + draw lmt_text [ + trace = trace, + anchor = "lft", + format = getparameter "yformat", + style = getparameter "ystyle", + text = decimal i + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (-at-ao,n) + ; + n := n + s ; + endfor ; + ) shifted (-ax,0) ; + + fi ; + + fi ; + + if hasoption "legend" "range,all" : + + % range + + save d ; d := ypart llcorner currentpicture ; + + draw + lmt_text [ + trace = trace, + anchor = "bot", + text = lua.mp.lmt_contours_range() + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (w/2,d-ty) + ; + + % minmax + + draw + lmt_text [ + trace = trace, + anchor = "lrt", + text = lua.mp.lmt_contours_xrange() + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (0,d-ty) + ; + + draw + lmt_text [ + trace = trace, + anchor = "llft", + text = lua.mp.lmt_contours_yrange() + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (w,d-ty) + ; + + fi ; + + if hasoption "legend" "function,all" : + + % formula + + draw + lmt_text [ + trace = trace, + anchor = "bot", + style = getparameter "functionstyle", + text = lua.mp.lmt_contours_function() + background = "", + ] + if ry <> 0 : ysized (ry) fi + shifted (w/2,ypart llcorner currentpicture - ty) + ; + + fi ; + + if trace : + draw boundingbox currentpicture + dashed evenly + withpen pencircle scaled al ; + fi ; + + fi ; + + fi ; + + lua.mp.lmt_contours_stop() ; + + popparameters ; + ) +enddef ; + +newinternal svgforcecmyk ; svgforcecmyk := 0 ; + +vardef svgcolor(expr r, g, b) = + if svgforcecmyk > 0 : + (1-r,1-g,1-b,0) % simple: no black component, kind of ok for emoji + else : + (r,g,b) + fi +enddef ; + +vardef svgcmyk(expr c, m, y, k) = + (c,m,y,k) +enddef ; + +vardef svggray(expr s) = + s +enddef ; + +presetparameters "svg" [ + filename = "", + fontname = "", + colormap = "", + % unicode = 0, + width = 0, + height = 0, + origin = false, + offset = 0, +] ; + +def lmt_svg = applyparameters "svg" "lmt_do_svg" enddef ; + +vardef lmt_do_svg = + save w, h, o; + image ( + pushparameters "svg" ; + w := getparameter "width" ; + h := getparameter "height" ; + o := getparameter "offset" ; + lua.mp.lmt_svg_include() ; + if getparameter "origin" : + currentpicture := currentpicture shifted -llcorner currentpicture ; + fi ; + popparameters ; + if o <> 0 : + setbounds currentpicture to boundingbox currentpicture enlarged o ; + fi ; + ) + if w > 0 : + if h > 0 : xysized(w,h) else : xsized(w) fi + else : + if h > 0 : ysized(h) fi + fi +enddef ; + +% Another experiment. Parameters might change pending a discussion between Alan +% and me. + +presetparameters "surface" [ + code = "x + y", + color = "f, 0, 0", + linecolor = 1, + xmin = -1, + xmax = 1, + ymin = -1, + ymax = 1, + xstep = .1, + ystep = .1, + snap = .01, + xvector = { -0.7, -0.7 }, + yvector = { 1, 0 }, + zvector = { 0, 1 }, + light = { 3, 3, 10 }, + bright = 100, + clip = false, + lines = true, + linecolor = 1, + % axis = { } + % clipaxis = false + axiscolor = "gray" + axislinewidth = 1/2, +] ; + +def lmt_surface = applyparameters "surface" "lmt_do_surface" enddef ; + +vardef lmt_do_surface = + image ( + + lmt_load_mlib_cnt ; + + pushparameters "surface" ; + + save currentpen; pen currentpen ; + currentpen := pencircle scaled .25 ; + + interim linejoin := butt ; + + lmt_do_contour_shortcuts ; + + lua.mp.lmt_surface_do() ; + + currentpicture := currentpicture ysized getparameter "height" ; + + if hasparameter "axis" : + + save p ; picture p ; p := image ( + if hasparameter "axis" 1 : + draw ((origin) -- unitvector(getparameter "xvector")) scaled (getparameter "axis" 1) ; + fi ; + if hasparameter "axis" 2 : + draw ((origin) -- unitvector(getparameter "yvector")) scaled (getparameter "axis" 2) ; + fi ; + if hasparameter "axis" 3 : + draw ((origin) -- unitvector(getparameter "zvector")) scaled (getparameter "axis" 3) ; + fi ; + ) ; + + if getparameterdefault "clipaxis" false : + clip p to boundingbox currentpicture ; + fi ; + + draw p + withpen pencircle scaled getparameter "axislinewidth" + withcolor getparameter "axiscolor" + ; + + fi ; + + popparameters ; + ) +enddef ; + +% I can make a variant that avoids the lmt_do ... and does an immediate function +% call instead. + +presetparameters "mpsglyphs" [ + name = "dummy", + units = 1000, +] ; + +presetparameters "mpsglyph" [ + category = "dummy", + unicode = 0, + % unichar = "" +] ; + +def lmt_registerglyphs = applyparameters "mpsglyphs" "lmt_do_registerglyphs" enddef ; +def lmt_registerglyph = applyparameters "mpsglyph" "lmt_do_registerglyph" enddef ; + +vardef lmt_do_registerglyphs = lua.mp.lmt_register_glyphs() ; enddef ; +vardef lmt_do_registerglyph = lua.mp.lmt_register_glyph () ; enddef ; + +% Again an experiment (todo: the faster method): + +def lmt_remaptext = runscript("mp.lmt_do_remaptext()") enddef ; + +triplet mfun_tt_s ; + +vardef rawmaptext(expr s) = + mfun_tt_n := mfun_tt_n + 1 ; + mfun_tt_c := nullpicture ; + mfun_tt_o := nullpicture ; + addto mfun_tt_o doublepath origin _op_ ; % save drawoptions + mfun_tt_r := lua.mp.mf_map_text(mfun_tt_n,s,catcoderegime) ; + mfun_tt_s := lua.mp.mf_map_move(mfun_tt_n) ; + addto mfun_tt_c doublepath unitsquare + xscaled wdpart mfun_tt_r + yscaled (htpart mfun_tt_r + dppart mfun_tt_r) + shifted (0,-dppart mfun_tt_r) + withprescript "mf_object=text" + withprescript "tx_index=" & decimal mfun_tt_n + withprescript "tx_color=" & colordecimals colorpart mfun_tt_o + ; + mfun_tt_c +enddef ; + +vardef svgtext(expr t) = + save p ; picture p ; + % mfun_tt_s := (0,0,0) ; + % mfun_tt_r := (0,0,0) ; + p := rawmaptext(t) ; + p + if (mfun_labtype.drt >= 10) : % drt etc + shifted (0,ypart center p) + fi + shifted ( + - mfun_labshift.drt(p) + - (redpart mfun_tt_s,0) + + (greenpart mfun_tt_s,bluepart mfun_tt_s) + ) +enddef ; + +vardef svg expr c = lmt_svg [ code = c ] enddef ; + +% Fun stuff: + +presetparameters "poisson" [ + width = 50, + height = 50, + initialx = 0, + initialy = 0, + distance = 1, + count = 20, + macro = "draw", + arguments = 2 +] ; + +def lmt_poisson = applyparameters "poisson" "lmt_do_poisson" enddef ; + +vardef lmt_do_poisson = + image ( + pushparameters "poisson" ; + lua.mp.lmt_poisson_generate(); + popparameters ; + ) +enddef ; diff --git a/metapost/context/base/mpxl/mp-luas.mpxl b/metapost/context/base/mpxl/mp-luas.mpxl new file mode 100644 index 000000000..421e82946 --- /dev/null +++ b/metapost/context/base/mpxl/mp-luas.mpxl @@ -0,0 +1,250 @@ +%D \module +%D [ file=mp-luas.mpiv, +%D version=2014.04.14, +%D title=\CONTEXT\ \METAPOST\ graphics, +%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. + +if known context_luas : endinput ; fi ; + +% When I prototyped the runscript primitive I was just thinking of a usage like +% the original \directlua primitive in luatex: genererate something and pipe +% that back to metapost, and have access to some internals. Instead of compiling +% the code a the metapost end here we delegate that to the lua end. Only strings +% get passed. Of course in the end the real usage got a bit beyong the intended +% usage. So, in addition to some definitions here there are and will be use in +% other metafun modules too. Of course in retrospect I should have done this five +% years earlier. + +boolean context_luas ; context_luas := true ; + +newinternal mfid_scriptindex ; +mfid_scriptindex := runscript("mp.mf_script_index('scriptindex')") ; + +def scriptindex = runscript mfid_scriptindex enddef ; + +string mfun_lua_bs ; mfun_lua_bs := "[===[" ; +string mfun_lua_es ; mfun_lua_es := "]===]" ; + +vardef mlib_luas_luacall(text t) = + runscript("" for s = t : + if string s : + & s + % & mfun_lua_bs & s & mfun_lua_es + elseif numeric s : + & decimal s + elseif boolean s : + & if s : "true" else : "false" fi + elseif pair s : + & mfun_pair_to_table(s) + elseif path s : + & mfun_path_to_table(s) + elseif rgbcolor s : + & mfun_rgb_to_table(s) + elseif cmykcolor s : + & mfun_cmyk_to_table(s) + else : + & ditto & tostring(s) & ditto + fi endfor + ) +enddef ; + +newinternal mfun_luas_b ; + +def mlib_luas_luadone = + exitif numeric begingroup mfun_luas_b := 1 ; endgroup ; +enddef ; + +vardef mlib_luas_lualist(expr c)(text t) = % we could use mlib_luas_s instead of c + interim mfun_luas_b := 0 ; + runscript(c & for s = t : + if mfun_luas_b = 0 : + "(" + % hide(mfun_luas_b := 1) + mlib_luas_luadone + else : + "," + fi + & + if string s : + mfun_lua_bs & s & mfun_lua_es + elseif numeric s : + decimal s + elseif boolean s : + if s : "true" else : "false" fi + elseif pair s : + mfun_pair_to_table(s) + elseif path s : + mfun_path_to_table(s) + elseif rgbcolor s : + mfun_rgb_to_table(s) + elseif cmykcolor s : + mfun_cmyk_to_table(s) + else : + ditto & tostring(s) & ditto + fi & endfor if mfun_luas_b = 0 : "()" else : ")" fi + ) +enddef ; + +def luacall = mlib_luas_luacall enddef ; % why no let + +vardef lualist@#(text t) = mlib_luas_lualist(str @#)(t) enddef ; + +string mlib_luas_s ; % saves save/restore + +vardef lua@#(text t) = + mlib_luas_s := str @# ; + if length(mlib_luas_s) > 0 : + mlib_luas_lualist(mlib_luas_s,t) + else : + mlib_luas_luacall(t) + fi +enddef ; + +vardef MP@#(text t) = + mlib_luas_lualist("MP." & str @#,t) +enddef ; + +def message expr t = + lua.mp.report(tostring(t)) ; +enddef ; + +% Color: + +% We do a low level runscript: +% +% lua.mp.namedcolor(s) % conflicts with macro namedcolor +% lua.mp.mf_named_color(s) % okay but, can also be +% lua.mp("mf_named_color",s) % which gives expansion mess + +newinternal mfid_resolvedcolor ; mfid_resolvedcolor := scriptindex "namedcolor" ; + +def resolvedcolor = runscript mfid_resolvedcolor enddef ; + +% Modes: + +vardef texmode (expr s) = lua.mp("mode", s) enddef ; +vardef systemmode(expr s) = lua.mp("systemmode",s) enddef ; + +% A few helpers + +vardef isarray suffix a = lua.mp.isarray (str a) enddef ; +vardef prefix suffix a = lua.mp.prefix (str a) enddef ; +vardef dimension suffix a = lua.mp.dimension(str a) enddef ; + +% More access + +vardef getmacro(expr k) = lua.mp._get_macro_(k) enddef ; +vardef getdimen(expr k) = lua.mp._get_dimen_(k) enddef ; +vardef getcount(expr k) = lua.mp._get_count_(k) enddef ; +vardef gettoks (expr k) = lua.mp._get_toks_ (k) enddef ; + +def setmacro(expr k,v) = lua.mp._set_macro_(k,v) enddef ; +def setdimen(expr k,v) = lua.mp._set_dimen_(k,v) enddef ; +def setcount(expr k,v) = lua.mp._set_count_(k,v) enddef ; +def settoks (expr k,v) = lua.mp._set_toks_ (k,v) enddef ; + +vardef positionpath (expr name) = lua.mp.positionpath (name) enddef ; +vardef positioncurve (expr name) = lua.mp.positioncurve (name) enddef ; +vardef positionxy (expr name) = lua.mp.positionxy (name) enddef ; +vardef positionpxy (expr name) = lua.mp.positionpxy (name) enddef ; +vardef positionwhd (expr name) = lua.mp.positionwhd (name) enddef ; +vardef positionpage (expr name) = lua.mp.positionpage (name) enddef ; +vardef positionregion(expr name) = lua.mp.positionregion(name) enddef ; +vardef positionbox (expr name) = lua.mp.positionbox (name) enddef ; +vardef positionanchor = lua.mp.positionanchor() enddef ; + +let wdpart = redpart ; +let htpart = greenpart ; +let dppart = bluepart ; + +vardef positioninregion = + currentpicture := currentpicture shifted - positionxy(positionanchor) ; +enddef ; + +vardef positionatanchor(expr name) = + currentpicture := currentpicture shifted - positionxy(name) ; +enddef ; + +vardef texvar(expr name) = lua.mp.texvar(name) enddef ; +vardef texstr(expr name) = lua.mp.texstr(name) enddef ; + +newinternal mfid_path_lengthof ; mfid_path_lengthof := scriptindex "pathlengthof" ; +newinternal mfid_path_pointof ; mfid_path_pointof := scriptindex "pathpointof" ; +newinternal mfid_path_leftof ; mfid_path_leftof := scriptindex "pathleftof" ; +newinternal mfid_path_rightof ; mfid_path_rightof := scriptindex "pathrightof" ; +newinternal mfid_path_reset ; mfid_path_reset := scriptindex "pathreset" ; + +% 25 pct gain + + def inpath = = 1 step 1 until runscript mfid_path_lengthof enddef ; +vardef pointof primary i = runscript mfid_path_pointof i enddef ; +vardef leftof primary i = runscript mfid_path_leftof i enddef ; +vardef rightof primary i = runscript mfid_path_rightof i enddef ; + +% another 10 pct gain + +% def inpath = = 1 step 1 until runscript mfid_path_lengthof enddef ; +% def pointof = runscript mfid_path_pointof enddef ; +% def leftof = runscript mfid_path_leftof enddef ; +% def rightof = runscript mfid_path_rightof enddef ; + +extra_endfig := extra_endfig & " runscript mfid_path_reset ; " ; + +vardef utflen(expr s) = lua.mp.utflen(s) enddef ; +vardef utfsub(expr s,f,t) = lua.mp.utfsub(s,f,t) enddef ; + +newinternal mfid_getparameters ; mfid_getparameters := scriptindex "getparameters" ; +newinternal mfid_presetparameters ; mfid_presetparameters := scriptindex "presetparameters" ; +newinternal mfid_hasparameter ; mfid_hasparameter := scriptindex "hasparameter" ; +newinternal mfid_hasoption ; mfid_hasoption := scriptindex "hasoption" ; +newinternal mfid_getparameter ; mfid_getparameter := scriptindex "getparameter" ; +newinternal mfid_getparameterdefault ; mfid_getparameterdefault := scriptindex "getparameterdefault" ; +newinternal mfid_getparametercount ; mfid_getparametercount := scriptindex "getparametercount" ; +newinternal mfid_getmaxparametercount ; mfid_getmaxparametercount := scriptindex "getmaxparametercount" ; +newinternal mfid_getparameterpath ; mfid_getparameterpath := scriptindex "getparameterpath" ; +newinternal mfid_getparameterpen ; mfid_getparameterpen := scriptindex "getparameterpen" ; +newinternal mfid_getparametertext ; mfid_getparametertext := scriptindex "getparametertext" ; +%%%%%%%%%%% mfid_getparameteroption ; mfid_getparameteroption := scriptindex "getparameteroption" ; +newinternal mfid_applyparameters ; mfid_applyparameters := scriptindex "applyparameters" ; +newinternal mfid_pushparameters ; mfid_pushparameters := scriptindex "pushparameters" ; +newinternal mfid_popparameters ; mfid_popparameters := scriptindex "popparameters" ; + +def getparameters = runscript mfid_getparameters enddef ; +def presetparameters = runscript mfid_presetparameters enddef ; +def hasparameter = runscript mfid_hasparameter enddef ; +def hasoption = runscript mfid_hasoption enddef ; +def getparameter = runscript mfid_getparameter enddef ; +def getparameterdefault = runscript mfid_getparameterdefault enddef ; +def getparametercount = runscript mfid_getparametercount enddef ; +def getmaxparametercount = runscript mfid_getmaxparametercount enddef ; +def getparameterpath = runscript mfid_getparameterpath enddef ; +def getparameterpen = runscript mfid_getparameterpen enddef ; +def getparametertext = runscript mfid_getparametertext enddef ; +%%% getparameteroption = runscript mfid_getparameteroption enddef ; +def applyparameters = runscript mfid_applyparameters enddef ; +def pushparameters = runscript mfid_pushparameters enddef ; +def popparameters = runscript mfid_popparameters enddef ; + +% This might also be done in stock mkiv: + +newinternal mfid_year ; mfid_year := scriptindex "year" ; vardef year = runscript mfid_year enddef ; +newinternal mfid_month ; mfid_month := scriptindex "month" ; vardef month = runscript mfid_month enddef ; +newinternal mfid_day ; mfid_day := scriptindex "day" ; vardef day = runscript mfid_day enddef ; +newinternal mfid_hour ; mfid_hour := scriptindex "hour" ; vardef hour = runscript mfid_hour enddef ; +newinternal mfid_minute ; mfid_minute := scriptindex "minute" ; vardef minute = runscript mfid_minute enddef ; +newinternal mfid_second ; mfid_second := scriptindex "second" ; vardef second = runscript mfid_second enddef ; + +% You cannot overload a local color bu using a prefix works ok: +% +% \definecolor [ name = "mp:myred", r = .9 ] ; + +newinternal mfid_definecolor ; mfid_definecolor := scriptindex "definecolor" ; + +def definecolor = runscript mfid_definecolor ; enddef ; % the semicolon prevents lookahead diff --git a/metapost/context/base/mpxl/mp-math.mpxl b/metapost/context/base/mpxl/mp-math.mpxl new file mode 100644 index 000000000..ea8c1cd7c --- /dev/null +++ b/metapost/context/base/mpxl/mp-math.mpxl @@ -0,0 +1,161 @@ +%D \module +%D [ file=mp-math.mpiv, +%D version=2019.07.26, % was mp-core: 1999.08.01, anchoring +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=extra math functions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +if known context_math : endinput ; fi ; + +boolean context_math ; context_math := true ; + +% draw textext(decimal runscript("mp.numeric(xmath.gamma(.12))")) ; + +newinternal mfid_m_acos ; mfid_m_acos := scriptindex "m_acos" ; def m_acos = runscript mfid_m_acos enddef ; +newinternal mfid_m_acosh ; mfid_m_acosh := scriptindex "m_acosh" ; def m_acosh = runscript mfid_m_acosh enddef ; +newinternal mfid_m_asin ; mfid_m_asin := scriptindex "m_asin" ; def m_asin = runscript mfid_m_asin enddef ; +newinternal mfid_m_asinh ; mfid_m_asinh := scriptindex "m_asinh" ; def m_asinh = runscript mfid_m_asinh enddef ; +newinternal mfid_m_atan ; mfid_m_atan := scriptindex "m_atan" ; def m_atan = runscript mfid_m_atan enddef ; +newinternal mfid_m_atantwo ; mfid_m_atantwo := scriptindex "m_atan2" ; def m_atantwo = runscript mfid_m_atantwo enddef ; % atan2 +newinternal mfid_m_atanh ; mfid_m_atanh := scriptindex "m_atanh" ; def m_atanh = runscript mfid_m_atanh enddef ; +newinternal mfid_m_cbrt ; mfid_m_cbrt := scriptindex "m_cbrt" ; def m_cbrt = runscript mfid_m_cbrt enddef ; +newinternal mfid_m_ceil ; mfid_m_ceil := scriptindex "m_ceil" ; def m_ceil = runscript mfid_m_ceil enddef ; +newinternal mfid_m_copysign ; mfid_m_copysign := scriptindex "m_copysign" ; def m_copysign = runscript mfid_m_copysign enddef ; +newinternal mfid_m_cos ; mfid_m_cos := scriptindex "m_cos" ; def m_cos = runscript mfid_m_cos enddef ; +newinternal mfid_m_cosh ; mfid_m_cosh := scriptindex "m_cosh" ; def m_cosh = runscript mfid_m_cosh enddef ; +newinternal mfid_m_deg ; mfid_m_deg := scriptindex "m_deg" ; def m_deg = runscript mfid_m_deg enddef ; +newinternal mfid_m_erf ; mfid_m_erf := scriptindex "m_erf" ; def m_erf = runscript mfid_m_erf enddef ; +newinternal mfid_m_erfc ; mfid_m_erfc := scriptindex "m_erfc" ; def m_erfc = runscript mfid_m_erfc enddef ; +newinternal mfid_m_exp ; mfid_m_exp := scriptindex "m_exp" ; def m_exp = runscript mfid_m_exp enddef ; +newinternal mfid_m_exptwo ; mfid_m_exptwo := scriptindex "m_exp2" ; def m_exptwo = runscript mfid_m_exptwo enddef ; % exp2 +newinternal mfid_m_expm ; mfid_m_expm := scriptindex "m_expm1" ; def m_expm = runscript mfid_m_expm enddef ; % expm1 +newinternal mfid_m_fabs ; mfid_m_fabs := scriptindex "m_fabs" ; def m_fabs = runscript mfid_m_fabs enddef ; +newinternal mfid_m_fdim ; mfid_m_fdim := scriptindex "m_fdim" ; def m_fdim = runscript mfid_m_fdim enddef ; +newinternal mfid_m_floor ; mfid_m_floor := scriptindex "m_floor" ; def m_floor = runscript mfid_m_floor enddef ; +newinternal mfid_m_fma ; mfid_m_fma := scriptindex "m_fma" ; def m_fma = runscript mfid_m_fma enddef ; +newinternal mfid_m_fmax ; mfid_m_fmax := scriptindex "m_fmax" ; def m_fmax = runscript mfid_m_fmax enddef ; +newinternal mfid_m_fmin ; mfid_m_fmin := scriptindex "m_fmin" ; def m_fmin = runscript mfid_m_fmin enddef ; +newinternal mfid_m_fmod ; mfid_m_fmod := scriptindex "m_fmod" ; def m_fmod = runscript mfid_m_fmod enddef ; +newinternal mfid_m_frexp ; mfid_m_frexp := scriptindex "m_frexp" ; def m_frexp = runscript mfid_m_frexp enddef ; +newinternal mfid_m_gamma ; mfid_m_gamma := scriptindex "m_gamma" ; def m_gamma = runscript mfid_m_gamma enddef ; +newinternal mfid_m_hypot ; mfid_m_hypot := scriptindex "m_hypot" ; def m_hypot = runscript mfid_m_hypot enddef ; +newinternal mfid_m_isfinite ; mfid_m_isfinite := scriptindex "m_isfinite" ; def m_isfinite = runscript mfid_m_isfinite enddef ; +newinternal mfid_m_isinf ; mfid_m_isinf := scriptindex "m_isinf" ; def m_isinf = runscript mfid_m_isinf enddef ; +newinternal mfid_m_isnan ; mfid_m_isnan := scriptindex "m_isnan" ; def m_isnan = runscript mfid_m_isnan enddef ; +newinternal mfid_m_isnormal ; mfid_m_isnormal := scriptindex "m_isnormal" ; def m_isnormal = runscript mfid_m_isnormal enddef ; +newinternal mfid_m_jz ; mfid_m_jz := scriptindex "m_j0" ; def m_jz = runscript mfid_m_jz enddef ; % j0 +newinternal mfid_m_j ; mfid_m_j := scriptindex "m_j1" ; def m_j = runscript mfid_m_j enddef ; % j1 +newinternal mfid_m_jn ; mfid_m_jn := scriptindex "m_jn" ; def m_jn = runscript mfid_m_jn enddef ; +newinternal mfid_m_ldexp ; mfid_m_ldexp := scriptindex "m_ldexp" ; def m_ldexp = runscript mfid_m_ldexp enddef ; +newinternal mfid_m_lgamma ; mfid_m_lgamma := scriptindex "m_lgamma" ; def m_lgamma = runscript mfid_m_lgamma enddef ; +newinternal mfid_m_log ; mfid_m_log := scriptindex "m_log" ; def m_log = runscript mfid_m_log enddef ; +newinternal mfid_m_logten ; mfid_m_logte := scriptindex "m_log10" ; def m_logten = runscript mfid_m_logten enddef ; % log10 +newinternal mfid_m_logp ; mfid_m_logp := scriptindex "m_log1p" ; def m_logp = runscript mfid_m_logp enddef ; % log1p +newinternal mfid_m_logtwo ; mfid_m_logtwo := scriptindex "m_log2" ; def m_logtwo = runscript mfid_m_logtwo enddef ; % log2 +newinternal mfid_m_logb ; mfid_m_logb := scriptindex "m_logb" ; def m_logb = runscript mfid_m_logb enddef ; +newinternal mfid_m_modf ; mfid_m_modf := scriptindex "m_modf" ; def m_modf = runscript mfid_m_modf enddef ; +newinternal mfid_m_nearbyint ; mfid_m_nearbyint := scriptindex "m_nearbyint" ; def m_nearbyint = runscript mfid_m_nearbyint enddef ; +newinternal mfid_m_nextafter ; mfid_m_nextafter := scriptindex "m_nextafter" ; def m_nextafter = runscript mfid_m_nextafter enddef ; +newinternal mfid_m_pow ; mfid_m_pow := scriptindex "m_pow" ; def m_pow = runscript mfid_m_pow enddef ; +newinternal mfid_m_rad ; mfid_m_rad := scriptindex "m_rad" ; def m_rad = runscript mfid_m_rad enddef ; +newinternal mfid_m_remainder ; mfid_m_remainder := scriptindex "m_remainder" ; def m_remainder = runscript mfid_m_remainder enddef ; +newinternal mfid_m_remquo ; mfid_m_remquo := scriptindex "m_remquo" ; def m_remquo = runscript mfid_m_remquo enddef ; +newinternal mfid_m_round ; mfid_m_round := scriptindex "m_round" ; def m_round = runscript mfid_m_round enddef ; +newinternal mfid_m_scalbn ; mfid_m_scalbn := scriptindex "m_scalbn" ; def m_scalbn = runscript mfid_m_scalbn enddef ; +newinternal mfid_m_sin ; mfid_m_sin := scriptindex "m_sin" ; def m_sin = runscript mfid_m_sin enddef ; +newinternal mfid_m_sinh ; mfid_m_sinh := scriptindex "m_sinh" ; def m_sinh = runscript mfid_m_sinh enddef ; +newinternal mfid_m_sqrt ; mfid_m_sqrt := scriptindex "m_sqrt" ; def m_sqrt = runscript mfid_m_sqrt enddef ; +newinternal mfid_m_tan ; mfid_m_tan := scriptindex "m_tan" ; def m_tan = runscript mfid_m_tan enddef ; +newinternal mfid_m_tanh ; mfid_m_tanh := scriptindex "m_tanh" ; def m_tanh = runscript mfid_m_tanh enddef ; +newinternal mfid_m_tgamma ; mfid_m_tgamma := scriptindex "m_tgamma" ; def m_tgamma = runscript mfid_m_tgamma enddef ; +newinternal mfid_m_trunc ; mfid_m_trunc := scriptindex "m_trunc" ; def m_trunc = runscript mfid_m_trunc enddef ; +newinternal mfid_m_yz ; mfid_m_yz := scriptindex "m_y0" ; def m_yz = runscript mfid_m_yz enddef ; % y0 +newinternal mfid_m_y ; mfid_m_y := scriptindex "m_y1" ; def m_y = runscript mfid_m_y enddef ; % y1 +newinternal mfid_m_yn ; mfid_m_yn := scriptindex "m_yn" ; def m_yn = runscript mfid_m_yn enddef ; + +newinternal mfid_c_sin ; mfid_c_asin := scriptindex "c_sin" ; def c_sin = runscript mfid_c_sin enddef ; +newinternal mfid_c_cos ; mfid_c_acos := scriptindex "c_cos" ; def c_cos = runscript mfid_c_cos enddef ; +newinternal mfid_c_tan ; mfid_c_acos := scriptindex "c_tan" ; def c_tan = runscript mfid_c_tan enddef ; +newinternal mfid_c_sinh ; mfid_c_acos := scriptindex "c_sinh" ; def c_sinh = runscript mfid_c_sinh enddef ; +newinternal mfid_c_cosh ; mfid_c_acos := scriptindex "c_cosh" ; def c_cosh = runscript mfid_c_cosh enddef ; +newinternal mfid_c_tanh ; mfid_c_acos := scriptindex "c_tanh" ; def c_tanh = runscript mfid_c_tanh enddef ; + +newinternal mfid_c_asin ; mfid_c_acos := scriptindex "c_asin" ; def c_asin = runscript mfid_c_asin enddef ; +newinternal mfid_c_acos ; mfid_c_acos := scriptindex "c_acos" ; def c_acos = runscript mfid_c_acos enddef ; +newinternal mfid_c_atan ; mfid_c_acos := scriptindex "c_atan" ; def c_atan = runscript mfid_c_atan enddef ; +newinternal mfid_c_asinh ; mfid_c_acos := scriptindex "c_asinh" ; def c_asinh = runscript mfid_c_asinh enddef ; +newinternal mfid_c_acosh ; mfid_c_acos := scriptindex "c_acosh" ; def c_acosh = runscript mfid_c_acosh enddef ; +newinternal mfid_c_atanh ; mfid_c_acos := scriptindex "c_atanh" ; def c_atanh = runscript mfid_c_atanh enddef ; + +newinternal mfid_c_sqrt ; mfid_c_acos := scriptindex "c_sqrt" ; def c_sqrt = runscript mfid_c_sqrt enddef ; +newinternal mfid_c_abs ; mfid_c_acos := scriptindex "c_abs" ; def c_abs = runscript mfid_c_abs enddef ; +newinternal mfid_c_arg ; mfid_c_acos := scriptindex "c_arg" ; def c_arg = runscript mfid_c_arg enddef ; +newinternal mfid_c_conj ; mfid_c_acos := scriptindex "c_conj" ; def c_conj = runscript mfid_c_conj enddef ; +newinternal mfid_c_exp ; mfid_c_acos := scriptindex "c_exp" ; def c_exp = runscript mfid_c_exp enddef ; +newinternal mfid_c_log ; mfid_c_acos := scriptindex "c_log" ; def c_log = runscript mfid_c_log enddef ; +newinternal mfid_c_proj ; mfid_c_acos := scriptindex "c_proj" ; def c_proj = runscript mfid_c_proj enddef ; + +newinternal mfid_c_erf ; mfid_c_erf := scriptindex "c_erf" ; def c_erf = runscript mfid_c_erf enddef ; +newinternal mfid_c_erfc ; mfid_c_erfc := scriptindex "c_erfc" ; def c_erfc = runscript mfid_c_erfc enddef ; +newinternal mfid_c_erfcx ; mfid_c_erfcx := scriptindex "c_erfcx" ; def c_erfcx = runscript mfid_c_erfcx enddef ; +newinternal mfid_c_erfi ; mfid_c_erfi := scriptindex "c_erfi" ; def c_erfi = runscript mfid_c_erfi enddef ; + +% mfid_c_imag ; mfid_c_acos := scriptindex "c_imag" ; def c_imag = runscript mfid_c_imag enddef ; +% mfid_c_real ; mfid_c_acos := scriptindex "c_real" ; def c_real = runscript mfid_c_real enddef ; +% mfid_c_neg ; mfid_c_neg := scriptindex "c_neg" ; def c_neg = runscript mfid_c_neg enddef ; + +newinternal mfid_c_pow ; mfid_c_pow := scriptindex "c_pow" ; def c_pow (expr a,b) = runscript mfid_c_pow a b enddef ; +% mfid_c_add ; mfid_c_add := scriptindex "c_add" ; def c_add (expr a,b) = runscript mfid_c_add a b enddef ; +% mfid_c_sub ; mfid_c_sub := scriptindex "c_sub" ; def c_sub (expr a,b) = runscript mfid_c_sub a b enddef ; +newinternal mfid_c_mul ; mfid_c_mul := scriptindex "c_mul" ; def c_mul (expr a,b) = runscript mfid_c_mul a b enddef ; +newinternal mfid_c_div ; mfid_c_div := scriptindex "c_div" ; def c_div (expr a,b) = runscript mfid_c_div a b enddef ; + +newinternal mfid_c_voigt ; mfid_c_voigt := scriptindex "c_voigt" ; def c_voigt (expr a,b,c) = runscript mfid_c_voigt a b c enddef ; +newinternal mfid_c_voigt_hwhm ; mfid_c_voigt_hwhm := scriptindex "c_voigt_hwhm" ; def c_voigt_hwhm(expr a,b) = runscript mfid_c_voigt_hwhm a b enddef ; + +vardef c_add (expr a, b) = a + b enddef ; +vardef c_sub (expr a, b) = a + b enddef ; +vardef c_imag(expr a) = ypart a enddef ; +vardef c_real(expr a) = xpart a enddef ; +vardef c_neg (expr a) = -a enddef ; + +if (numbersystem == "scaled") or (numbersystem == "double") : + + % vardef sqrt primary x = m_sqrt x enddef ; + + % vardef sqr primary x = x*x enddef ; + % vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; + % vardef ln primary x = if x=0: 0 else: mlog(x)/256 fi enddef ; + % vardef exp primary x = (mexp 256)**x enddef ; + % vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; + + vardef sin primary x = m_sin x enddef ; vardef sinh primary x = m_sinh x enddef ; + vardef cos primary x = m_cos x enddef ; vardef cosh primary x = m_cosh x enddef ; + vardef tan primary x = m_tan x enddef ; vardef tanh primary x = m_tanh x enddef ; + vardef asin primary x = m_asin x enddef ; vardef asinh primary x = m_asinh x enddef ; + vardef acos primary x = m_acos x enddef ; vardef acosh primary x = m_acosh x enddef ; + vardef atan primary x = m_atan x enddef ; vardef atanh primary x = m_atanh x enddef ; + + vardef invsin primary x = (m_asin(x))/radian enddef ; + vardef invcos primary x = (m_acos(x))/radian enddef ; + vardef invtan primary x = (m_atan(x))/radian enddef ; + + + % vardef sind primary x = angle(m_sin x) enddef ; + % vardef cosd primary x = angle(m_cos x) enddef ; + % vardef tand primary x = angle(m_tan x) enddef ; + + vardef asind primary x = angle(m_asin x) enddef ; + vardef acosd primary x = angle(m_acos x) enddef ; + vardef atand primary x = angle(m_atan x) enddef ; + + % vardef tand primary x = sind(x)/cosd(x) enddef ; + % vardef cotd primary x = cosd(x)/sind(x) enddef ; + +fi ; diff --git a/metapost/context/base/mpxl/mp-page.mpxl b/metapost/context/base/mpxl/mp-page.mpxl new file mode 100644 index 000000000..8a4b735e0 --- /dev/null +++ b/metapost/context/base/mpxl/mp-page.mpxl @@ -0,0 +1,243 @@ +%D \module +%D [ file=mp-page.mpiv, +%D version=1999.03.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=page enhancements, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is rather preliminary and subjected to changes.In the process of +%D moving to \METAFUN2\ this might change. + +if known context_page : endinput ; fi ; + +boolean context_page ; context_page := true ; + +def LoadPageState = enddef ; % just in case some old style uses it + +% Next we implement the the page area model. First some constants. + +LeftEdge := -4 ; Top := -40 ; +LeftEdgeSeparator := -3 ; TopSeparator := -30 ; +LeftMargin := -2 ; Header := -20 ; +LeftMarginSeparator := -1 ; HeaderSeparator := -10 ; +Text := 0 ; Text := 0 ; +RightMarginSeparator := +1 ; FooterSeparator := +10 ; +RightMargin := +2 ; Footer := +20 ; +RightEdgeSeparator := +3 ; BottomSeparator := +30 ; +RightEdge := +4 ; Bottom := +40 ; + +numeric HorPos ; HorPos := 0 ; +numeric VerPos ; VerPos := 0 ; + +% Because metapost > 1.50 has dynamic memory management and is less efficient than +% before we now delay calculations ... (on a document with 150 pages the time spent +% in mp was close to 5 seconds which was only due to initialising the page related +% areas, something that was hardly noticeable before. At least now we're back to +% half a second for such a case. + +def SetPageVsize = + numeric Vsize[] ; + Vsize[Top] = TopHeight ; + Vsize[TopSeparator] = TopDistance ; + Vsize[Header] = HeaderHeight ; + Vsize[HeaderSeparator] = HeaderDistance ; + Vsize[Text] = TextHeight ; + Vsize[FooterSeparator] = FooterDistance ; + Vsize[Footer] = FooterHeight ; + Vsize[BottomSeparator] = BottomDistance ; + Vsize[Bottom] = BottomHeight ; +enddef ; + +def SetPageHsize = + numeric Hsize[] ; + Hsize[LeftEdge] = LeftEdgeWidth ; + Hsize[LeftEdgeSeparator] = LeftEdgeDistance ; + Hsize[LeftMargin] = LeftMarginWidth ; + Hsize[LeftMarginSeparator] = LeftMarginDistance ; + Hsize[Text] = MakeupWidth ; + Hsize[RightMarginSeparator] = RightMarginDistance ; + Hsize[RightMargin] = RightMarginWidth ; + Hsize[RightEdgeSeparator] = RightEdgeDistance ; + Hsize[RightEdge] = RightEdgeWidth ; +enddef ; + +def SetPageVstep = + numeric Vstep[] ; + Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ; + Vstep[TopSeparator] = PaperHeight-TopSpace ; + Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ; + Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ; + Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ; + Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ; + Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ; + Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ; + Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ; +enddef ; + +def SetPageHstep = + numeric Hstep[] ; + Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ; + Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ; + Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ; + Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ; + Hstep[Text] = BackSpace ; + Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ; + Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ; + Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ; + Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ; +enddef ; + +def SetPageArea = + path Area[][] ; + for VerPos=Top step 10 until Bottom: + for HorPos=LeftEdge step 1 until RightEdge: + Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ; + Area[VerPos][HorPos] := Area[HorPos][VerPos] ; + endfor ; + endfor ; +enddef ; + +def SetPageLocation = + pair Location[][] ; + for VerPos=Top step 10 until Bottom: + for HorPos=LeftEdge step 1 until RightEdge: + Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ; + Location[VerPos][HorPos] := Location[HorPos][VerPos] ; + endfor ; + endfor ; +enddef ; + +def SetPageField = + path Field[][] ; + for VerPos=Top step 10 until Bottom: + for HorPos=LeftEdge step 1 until RightEdge: + Field[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] shifted (Hstep[HorPos],Vstep[VerPos]) ; + Field[VerPos][HorPos] := Field[HorPos][VerPos] ; + endfor ; + endfor ; +enddef ; + +def Area = hide(SetPageArea ;) Area enddef ; +def Location = hide(SetPageLocation ;) Location enddef ; +def Field = hide(SetPageField ;) Field enddef ; +def Vsize = hide(SetPageVsize ;) Vsize enddef ; +def Hsize = hide(SetPageHsize ;) Hsize enddef ; +def Vstep = hide(SetPageVstep ;) Vstep enddef ; +def Hstep = hide(SetPageHstep ;) Hstep enddef ; + +vardef FrontPageWidth = PaperWidth enddef ; +vardef BackPageWidth = PaperWidth enddef ; +vardef CoverWidth = 2 * PaperWidth + SpineWidth enddef ; +vardef CoverHeight = PaperHeight enddef ; + +vardef FrontPageHeight = PaperHeight enddef ; +vardef BackPageHeight = PaperHeight enddef ; +vardef SpineHeight = PaperHeight enddef ; + +def SetPagePage = path Page ; Page := unitsquare xscaled PaperWidth yscaled PaperHeight ; enddef ; +def SetPageCoverPage = path CoverPage ; CoverPage := unitsquare xscaled CoverWidth yscaled CoverHeight ; enddef ; +def SetPageSpine = path Spine ; Spine := unitsquare xscaled SpineWidth yscaled CoverHeight shifted (BackPageWidth,0) ; enddef ; +def SetPageBackPage = path BackPage ; BackPage := unitsquare xscaled BackPageWidth yscaled CoverHeight ; enddef ; +def SetPageFrontPage = path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth yscaled CoverHeight shifted (BackPageWidth+SpineWidth,0) ; enddef ; + +def Page = hide(SetPagePage ;) Page enddef ; +def CoverPage = hide(SetPageCoverPage;) CoverPage enddef ; +def Spine = hide(SetPageSpine ;) Spine enddef ; +def BackPage = hide(SetPageBackPage ;) BackPage enddef ; +def FrontPage = hide(SetPageFrontPage;) FrontPage enddef ; + +% pages + +def StartPage = + begingroup ; + setbounds currentpicture to Page ; +enddef ; + +def StopPage = + setbounds currentpicture to Page ; + endgroup ; +enddef ; + +% cover pages + +def StartCover = + begingroup ; + setbounds currentpicture to CoverPage enlarged PaperBleed ; +enddef ; + +def StopCover = + setbounds currentpicture to CoverPage enlarged PaperBleed ; + endgroup ; +enddef ; + +% overlays: + +def OverlayBox = + (unitsquare xyscaled (OverlayWidth,OverlayHeight)) +enddef ; + +% handy + +def innerenlarged = + if OnRightPage : leftenlarged else : rightenlarged fi +enddef ; + +def outerenlarged = + if OnRightPage : rightenlarged else : leftenlarged fi +enddef ; + +% obsolete + +% def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ; +% def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ; +% def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ; +% def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ; + +% def Enlarged (expr p, d) = +% ( +% llEnlarged (p,d) -- +% lrEnlarged (p,d) -- +% urEnlarged (p,d) -- +% ulEnlarged (p,d) -- +% cycle +% ) +% enddef ; + +% for the moment we put these here: + +string RuleDirection ; RuleDirection := "" ; +string RuleOption ; RuleOption := "" ; +numeric RuleWidth ; RuleWidth := 0 ; +numeric RuleHeight ; RuleHeight := 0 ; +numeric RuleDepth ; RuleDepth := 0 ; +numeric RuleH ; RuleH := 0 ; +numeric RuleV ; RuleV := 0 ; +numeric RuleThickness ; RuleThickness := 0 ; +numeric RuleFactor ; RuleFactor := 0 ; +numeric RuleOffset ; RuleOffset := 0 ; + def RuleColor = (.5white) enddef ; + +def FakeWord(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) = + fill unitsquare + xscaled RuleWidth + yscaled (RuleDepth-RuleThickness/2) + withcolor RuleColor ; + fill unitsquare + xscaled RuleWidth + yscaled (RuleHeight-RuleDepth-RuleThickness/2) + shifted (0,RuleDepth+RuleThickness) + withcolor RuleColor ; +enddef ; + +def FakeRule(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) = + fill unitsquare + xscaled RuleWidth + yscaled RuleHeight + withcolor RuleColor ; +enddef ; diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 2eba08573..2398481f6 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -854,6 +854,11 @@ function scripts.context.run(ctxdata,filename) -- -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns -- + local engine = analysis.engine or "luametatex" + if engine == "luametatex" and (mainfile == usedfiles.yes or mainfile == usedfiles.nop) then + mainfile = "" -- we don't need that + end + -- for currentrun=1,maxnofruns do -- c_flags.final = false @@ -865,6 +870,7 @@ function scripts.context.run(ctxdata,filename) c_flags.profile = a_profile and (tonumber(a_profile) or 0) or nil -- print("") -- cleaner, else continuation on same line + -- local returncode = environment.run_format( formatfile, scriptfile, diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index e9b6498ba..e264dc856 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2020.11.19 11:23} +\newcontextversion{2020.11.23 18:34} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 7b8c74210..a4eaeaf72 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2020.11.19 11:23} +\edef\contextversion{2020.11.23 18:34} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii index b9235f6b7..3e2caec87 100644 --- a/tex/context/base/mkii/mult-de.mkii +++ b/tex/context/base/mkii/mult-de.mkii @@ -774,6 +774,7 @@ \setinterfaceconstant{deepnumbercommand}{deepnumbercommand} \setinterfaceconstant{deeptextcommand}{deeptextcommand} \setinterfaceconstant{default}{default} +\setinterfaceconstant{define}{define} \setinterfaceconstant{delay}{wartezeit} \setinterfaceconstant{depth}{tiefe} \setinterfaceconstant{depthcorrection}{tiefekorrektur} @@ -2073,7 +2074,7 @@ \setinterfacecommand{startnarrower}{startenger} \setinterfacecommand{startopposite}{startgegenueber} \setinterfacecommand{startoverlay}{startoverlay} -\setinterfacecommand{startoverzicht}{startueberblick} +\setinterfacecommand{startoverview}{startueberblick} \setinterfacecommand{startpacked}{startkleinerdurchschuss} \setinterfacecommand{startpositioning}{startpositionieren} \setinterfacecommand{startproduct}{startprodukt} @@ -2116,7 +2117,7 @@ \setinterfacecommand{stopnarrower}{stopenger} \setinterfacecommand{stopopposite}{stopgegenueber} \setinterfacecommand{stopoverlay}{stopoverlay} -\setinterfacecommand{stopoverzicht}{stopueberblick} +\setinterfacecommand{stopoverview}{stopueberblick} \setinterfacecommand{stoppacked}{stopkleinerdurchschuss} \setinterfacecommand{stoppositioning}{stoppositionieren} \setinterfacecommand{stopproduct}{stopprodukt} diff --git a/tex/context/base/mkiv/anch-bar.mkxl b/tex/context/base/mkiv/anch-bar.mkxl deleted file mode 100644 index 3587eb8a0..000000000 --- a/tex/context/base/mkiv/anch-bar.mkxl +++ /dev/null @@ -1,220 +0,0 @@ -%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 This can be done better now ... - -%D We will implement a sidebar mechanism using the functionality from -%D \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] - -\aliased\let\setupsidebars\setupsidebar - -\permanent\tolerant\protected\def\startsidebar[#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 - \ifhastok={#1}% - \edef\currentsidebar{\the\c_anch_sidebars_level}% - \checksidebarparent - \setupcurrentsidebar[#1]% - \else - \def\currentsidebar{#1}% - \setupcurrentsidebar[#2]% - \fi - \scratchdistance\sidebarparameter\c!distance\relax - \scratchdimen\sidebarparameter\c!leftmargindistance\relax - \edef\m_level{\sidebarparameter\c!level}% - \ifempty\m_level - \ifnum\c_anch_sidebars_level=\plusone - \ifzeropt\scratchdimen - \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 - \ifzeropt\scratchdimen - \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} - -\permanent\protected\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}% - 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 - -\permanent\tolerant\protected\def\setupmarginrule[#1]#*[#2]% - {\ifarguments\or - \setupsidebar[\v!margin][#1]% - \or - \setupsidebar[\v!margin:#1][#2]% - \fi} - -\aliased\let\setupmarginrules\setupmarginrule - -\permanent\tolerant\protected\def\startmarginrule[#1]% pretty inefficient checking - {\edef\m_anch_marginrules_kind{#1}% - \ifempty\m_anch_marginrules_kind - \startsidebar[\v!margin][]% - \orelse\ifhastok={\m_anch_marginrules_kind}% - \startsidebar[\v!margin][#1]% - \else - \anch_marginrules_check{#1}% - \startsidebar[\v!margin:#1][\c!level=#1]% - \fi} - -\def\anch_marginrules_check#1% - {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}} - -\aliased\let\stopmarginrule\stopsidebar - -\protect \endinput diff --git a/tex/context/base/mkiv/anch-bck.mklx b/tex/context/base/mkiv/anch-bck.mklx deleted file mode 100644 index 91e523d8f..000000000 --- a/tex/context/base/mkiv/anch-bck.mklx +++ /dev/null @@ -1,747 +0,0 @@ -%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 that use -%D attributes although not too much is to be expected, apart from better anchoring. -%D In fact better anchoring can be 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 - -\protected\def\anch_backgrounds_text_initialize - {\doifelsepositionsused\enableparpositions\donothing - \glet\anch_backgrounds_text_initialize\relax} - -\appendtoks - \anch_backgrounds_text_initialize -\to \everystarttext - -%D Some MP - -\newcount\MPparcounter - -\permanent\def\MPself {\MPvar{self}} -\permanent\def\MPbself {b:\MPvar{self}} -\permanent\def\MPeself {e:\MPvar{self}} -\permanent\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 - \frozen\instance\setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}% - \frozen\instance\setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}% - \frozen\instance\setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}% -\to \everydefinetextbackground - -\newconstant \c_anch_backgrounds_pos_state -\newconditional\c_anch_backgrounds_pos_no_shape - -\def\anch_backgrounds_bpos - {\ifconditional\c_anch_backgrounds_pos_no_shape - \bposkind\v_anch_backgrounds_text_current\plusthree - \else - \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state - \fi} - -\def\anch_backgrounds_epos - {\ifconditional\c_anch_backgrounds_pos_no_shape - \eposkind\v_anch_backgrounds_text_current\plusthree - \else - \eposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state - \fi} - -% \permanent\tolerant\protected\def\starttextbackground[#tag]#spacer[#settings]% -% {\begingroup -% \advance\c_anch_backgrounds_text_level\plusone -% \def\currenttextbackground{#tag}% -% \anch_backgrounds_text_initialize_next -% \ifparameter#settings\or -% \setupcurrenttextbackground[#settings]% -% \fi -% \doifelse{\textbackgroundparameter\c!state}\v!start -% \anch_backgrounds_text_preset_yes -% \anch_backgrounds_text_preset_nop -% \anch_backgrounds_text_start_indeed} - -% ugly hack to register usage - -\newcount \c_anch_backgrounds_text_count -\newcount \c_anch_backgrounds_text_check -\newconstant\c_anch_backgrounds_text_state - -\permanent\tolerant\protected\def\starttextbackground[#tag]#spacer[#settings]% - {\begingroup - \global\advance\c_anch_backgrounds_text_count\plusone - \advance\c_anch_backgrounds_text_level\plusone - \def\currenttextbackground{#tag}% - \anch_backgrounds_text_initialize_next - \ifparameter#settings\or - \setupcurrenttextbackground[#settings]% - \fi - \doifelse{\textbackgroundparameter\c!state}\v!start - \anch_backgrounds_text_preset_yes - \anch_backgrounds_text_preset_nop - \anch_backgrounds_text_start_indeed} - -\def\anch_backgrounds_text_level_start - {\c_anch_backgrounds_text_check\c_anch_backgrounds_text_count} - -\def\anch_backgrounds_text_level_stop - {\c_anch_backgrounds_text_state - \ifnum\c_anch_backgrounds_text_count>\c_anch_backgrounds_text_check - \plusone - \else - \zerocount - \fi} - -% todo \backgroundvariable\c!variant - -% criterium determines when we fall back on text -% always is always forcing paragraphs - -\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>\textbackgroundparameter\c!criterium\relax - \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!always}% - {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par - \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par} - -\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}}} - -\permanent\protected\def\stoptextbackground - {\anch_backgrounds_text_stop_indeed - \carryoverpar\endgroup} % why doesn't this work ? - -\permanent\protected\def\starttextbackgroundmanual - {\begingroup - \c_anch_backgrounds_pos_state\plusone - \usetextbackgroundstyleandcolor\c!style\c!color - \anch_backgrounds_bpos} - -\permanent\protected\def\stoptextbackgroundmanual - {\anch_backgrounds_epos - \carryoverpar\endgroup} - -\def\anch_backgrounds_text_start_txt - {\ifvmode \dontleavehmode \fi - \begingroup - \c_anch_backgrounds_pos_state\plusone - \usetextbackgroundstyleandcolor\c!style\c!color - \anch_backgrounds_bpos} - -\def\anch_backgrounds_text_stop_txt - {\anch_backgrounds_epos - \carryoverpar\endgroup} - -\newskip\textbackgroundskip - -% maybe we should have a resetter for such compensation struts - -\def\anch_backgrounds_reset_attributes - {\scratchcounter\c_attr_snapmethod - \resetallattributes % \c_attr_linenumber\attributeunsetvalue - \c_attr_snapmethod\scratchcounter} - -\def\anch_backgrounds_text_start_par % beware .. background shapes - {\endgraf % new - \textbackgroundparameter\c!before - \begingroup - \c_anch_backgrounds_pos_state\plustwo - \begingroup - \anch_backgrounds_reset_attributes - \noindent - \ifgridsnapping - \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}% - \ifdim\textbackgroundskip>\zeropoint - \struttedbox % not always ok (e.g. setups) - {\hpack{\raise\textbackgroundskip\hpack{\anch_backgrounds_bpos}}}% - \else - \anch_backgrounds_bpos - \fi - \else - \anch_backgrounds_bpos - \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 - \anch_backgrounds_reset_attributes - \nobreak \noindent \strut \hfill \kern\zeropoint - % so far - \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}% - \ifgridsnapping % experimental, pascal (todo: topoffset in same way) - \ifdim\textbackgroundskip>\zeropoint - \struttedbox % not always ok (e.g. setups) - {\hpack{\lower\textbackgroundskip\hpack{\anch_backgrounds_epos}}}% - \else - \anch_backgrounds_epos - \fi - \else - \anch_backgrounds_epos - \fi - \endgraf - \carryoverpar\endgroup - \endgraf % new - \textbackgroundparameter\c!after} - -\permanent\protected\def\checkpositionoverlays % overloads \relax in anch-pgr - {\ifproductionrun - \enabletextarearegistration - \enablehiddenbackground - \enforced\glet\checkpositionoverlays\relax - \fi} - -% shape handling - -\definesystemattribute[textbackground][public] - -% \def\page_prepare_backgrounds#1% -% {\clf_collectbackgrounds\realpageno#1\relax} - -\def\anch_backgrounds_bpos - {\ifconditional\c_anch_backgrounds_pos_no_shape - \c_attr_textbackground\attributeunsetvalue - \bposkind\v_anch_backgrounds_text_current\plusthree - \orelse\ifnum\c_anch_backgrounds_pos_state=\plusone - \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state - \clf_registerbackground{\v_anch_backgrounds_text_current}% - \else - \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state - \c_attr_textbackground\attributeunsetvalue - \fi} - -% plugs into other code - -\def\strc_floats_wrap_free_region - {\global\setbox\floatbox\hpack % we always need to wrap - {\ifconditional\c_strc_floats_trace_free - \strc_floats_show_free_region - \fi - \box\floatbox}} - -\startuseMPgraphic{floatfree} - draw_free_region( - \the\wd\floatbox, - \the\ht\floatbox, - \the\dp\floatbox, - \the\d_free_offset_left, - \the\d_free_offset_right, - \the\d_free_offset_top, - \the\d_free_offset_bottom - ) ; -\stopuseMPgraphic - -\def\strc_floats_show_free_region - {\lower\dp\floatbox\hpack to \zeropoint {\useMPgraphic{floatfree}}} - -\newconditional\c_strc_floats_mark_as_free -\newconditional\c_strc_floats_trace_free -\newconstant \c_free_offset_kind -\newdimen \d_free_offset_left -\newdimen \d_free_offset_right -\newdimen \d_free_offset_top -\newdimen \d_free_offset_bottom - -\installtextracker{floats.freeregion} - {\settrue \c_strc_floats_trace_free} - {\setfalse\c_strc_floats_trace_free} - -\def\strc_floats_mark_as_free#1#2#3#4#5% - {\c_free_offset_kind #1% - \d_free_offset_left #2% - \d_free_offset_right #3% - \d_free_offset_top #4% - \d_free_offset_bottom#5% - \strc_floats_wrap_free_region - \anch_mark_tagged_box_free - \floatbox - \c_free_offset_kind - \d_free_offset_left - \d_free_offset_right - \d_free_offset_top - \d_free_offset_bottom} - -\ifx\strc_floats_mark_pag_as_free\relax \else - \writestatus{error}{wrong place for pag_as_free}\wait -\fi - -\ifx\strc_floats_mark_par_as_free\relax \else - \writestatus{error}{wrong place for par_as_free}\wait -\fi - -\def\strc_floats_mark_pag_as_free - {\ifpositioning - \ifconditional\c_strc_floats_mark_as_free - \strc_floats_mark_as_free - \plusone - \zeropoint - \zeropoint - \d_strc_floats_top - \d_strc_floats_bottom - \fi - \fi} - -\def\strc_floats_mark_par_as_free - {\ifpositioning - \ifconditional\c_strc_floats_mark_as_free - \ifcase\c_page_sides_float_type - \or % backspace - \strc_floats_mark_as_free - \plustwo - \zeropoint - \d_page_sides_rightoffset - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % leftedge - \strc_floats_mark_as_free - \plustwo - \zeropoint - \d_page_sides_rightoffset - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % leftmargin - \strc_floats_mark_as_free - \plustwo - \zeropoint - \d_page_sides_rightoffset - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % leftside - \strc_floats_mark_as_free - \plustwo - \d_page_sides_leftskip % maybe too - \d_page_sides_margin - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % rightside - \strc_floats_mark_as_free - \plusthree - \d_page_sides_margin - \d_page_sides_rightskip % maybe too - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % rightmargin - \strc_floats_mark_as_free - \plusthree - \d_page_sides_leftoffset - \zeropoint - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % rightedge - \strc_floats_mark_as_free - \plusthree - \d_page_sides_leftoffset - \zeropoint - \d_page_sides_topskip - \d_page_sides_bottomskip - \or % cutspace - \strc_floats_mark_as_free - \plusthree - \d_page_sides_leftoffset - \zeropoint - \d_page_sides_topskip - \d_page_sides_bottomskip - \fi - \fi - \fi} - -% so far - -\setuptextbackground - [\c!mp=mpos:region:draw, - \c!method=mpos:region, - \c!state=\v!start, - \c!location=\v!text, - \c!leftoffset=\!!zeropoint, % 1em, - \c!rightoffset=\textbackgroundparameter\c!leftoffset, - \c!topoffset=\!!zeropoint, % \v!medium, - \c!bottomoffset=\textbackgroundparameter\c!topoffset, - \c!criterium=\plusone, - \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} - 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 boxgridcolor = \MPvar{gridcolor} enddef ; - def boxlinecolor = \MPvar{linecolor} enddef ; - def boxfillcolor = \MPvar{fillcolor} enddef ; - % - def boxgridoptions = withcolor boxgridcolor enddef ; - def boxlineoptions = withcolor boxlinecolor enddef ; - def boxfilloptions = withcolor boxfillcolor enddef ; -\stopuseMPgraphic - -\startuseMPgraphic{mpos:region:extra} - % user stuff -\stopuseMPgraphic - -\startuseMPgraphic{mpos:region:anchor} - setbounds currentpicture to multibox ; -\stopuseMPgraphic - -\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 - -%D For old times sake: - -\startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth} - string tag; tag := "\MPvar{self}" ; - path box ; box := positionbox(tag) ; - - box := box enlarged \MPvar{filloffset} ; - fill box withcolor \MPvar{fillcolor} ; - draw box withcolor \MPvar{linecolor} withpen pencircle scaled \MPvar{linewidth} ; - - positioninregion; -\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 \overloaded\aliased\letcsname\v!grid\endcsname\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} - \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} - 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/tex/context/base/mkiv/anch-pgr.mkxl b/tex/context/base/mkiv/anch-pgr.mkxl deleted file mode 100644 index 3439fd5a2..000000000 --- a/tex/context/base/mkiv/anch-pgr.mkxl +++ /dev/null @@ -1,445 +0,0 @@ -%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 the reference point -%D on the page. The next macros do so and are hooked into the page building routine. - -\registerctxluafile{anch-pgr}{} - -\unprotect - -%D A few more low level macros take care of defining and recalling actions. Actions -%D are saved globally! The lists can become quite long because there can be lots of -%D parameters passed on so we clean up the list afterwards. - -\newtoks\everypositionaction -\newtoks\everyinsertpositionaction -\newtoks\everycleanpositionaction - -\installcorenamespace{positionaction} -\installcorenamespace{positioncleanup} - -\protected\def\anch_positions_set_action#1% - {\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces - -\permanent\protected\def\doifpositionaction#1% - {\ifcsname\??positionaction#1\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifelsepositionaction#1% - {\ifcsname\??positionaction#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifpositionactionelse\doifelsepositionaction - -\protected\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 % \hpack - {\anch_positions_trace_action_yes - \the\everyinsertpositionaction - \the\everypositionaction - \begincsname\??positionaction\currentpositionaction\endcsname - \anch_positions_cleanup_action}% - \smashedbox\scratchbox % smashing is really needed else we get problems with too big overlays - \endgroup} - -\protected\def\anch_positions_trace_action_nop_indeed - {\anch_positions_trace\clap\darkred{<\currentpositionaction>}} - -\protected\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 for later execution. This -%D collection is especially handy when we want to move actions to a specific layer. -%D Such series of actions are stored in a macro that is cleaned up after each -%D invocation. - -\def\anch_positions_cleanup_action % not in trialtypesetting - {\ifcsname\??positioncleanup\currentpositionaction\endcsname - \the\everycleanpositionaction - \setxvalue{\??positioncleanup\currentpositionaction}{\csname\??positioncleanup\currentpositionaction\endcsname}% - \fi} - -\permanent\protected\def\handlepositionaction#1\with#2\on#3% ugly, will change - {\begingroup - \edef\currentpositionanchor - {\ifempty\currentpositionoverlay#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 anchors. Currently we -%D stick to just one anchor and derive the head and tail anchors from this one. We -%D set these anchors before and after each page. - -\newdimen\c_anch_page_width -\newdimen\c_anch_page_height - -\protected\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\hpack{\box#1}\fi - \fi - \else - \c_anch_page_width \paperwidth - \c_anch_page_height\paperheight - \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi - \fi - \fi\fi} - -\protected\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 % redundant - \wd\scratchbox\makeupwidth - \anch_mark_text_box\scratchbox - \box\scratchbox - \endgroup} - -\def\anch_positions_place_anchors_nop - {\vkern\textheight} - -%D \macros -%D {positionoverlay,startpositionoverlay} -%D -%D As long as we're dealing with graphics it makes much sense to use the available -%D overlay mechanism. For this purpose, we 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 macros defined in an -%D auxiliary \METAPOST\ module that is preloaded. -%D -%D \typebuffer[graphic] - -\def\MPanchoridentifier{mpa} % {mp-anchor} - -%D The rest of the definitions concerning such overlays may look complicated, - -\let\currentpositionoverlay\empty - -%D Position actions are automatically executed when a position is set. - -\def\textbackgroundoverlay#1{\v!text#1} -\def\MPanchornumber {\the\realpageno} - -\permanent\protected\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 % \hpack - {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% - \ht\scratchbox\d_overlay_height - \dp\scratchbox\zeropoint - \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox - \box\scratchbox - \vfill}} - -\permanent\protected\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 % \hpack - {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% - \ht\scratchbox\d_overlay_height - \dp\scratchbox\zeropoint - \box\scratchbox - \vfill}} - -% \let\anch_positions_overlay_nop\gobbleoneargument - -\permanent\protected\def\startpositionoverlay - {\iftrialtypesetting - \expandafter\anch_positions_overlay_start_nop - \else - \expandafter\anch_positions_overlay_start_yes - \fi} - -\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}} - -\permanent\protected\def\stoppositionoverlay - {\let\currentpositionoverlay\empty} - -%D A position graphic is a normal (non||reused) \METAPOST\ graphic, used -%D immediately, with zero dimensions, so that a sequence of them does not harm. - -\installcorenamespace{positiongraphic} -\installcorenamespace{positionmethod} -%installcorenamespace{graphicvariable} - -\newbox\b_anch_positions_graphic - -\permanent\tolerant\protected\def\startMPpositiongraphic#=#*#=#:#3\stopMPpositiongraphic % tag list mpcode - {\setgvalue{\??positiongraphic#1}{\anch_positions_meta_graphic_use{#1}{#2}{#3}}} - -\aliased\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} - -\permanent\tolerant\protected\def\MPpositiongraphic#=#*#=% - {\ifcsname\??positionmethod#1\endcsname % method - \expandafter\anch_positions_meta_graphic_direct_method - \orelse\ifcsname\??positiongraphic#1\endcsname - \expandafter\anch_positions_meta_graphic_direct_normal - \else - \expandafter\gobbletwoarguments - \fi{#1}{#2}} - -\def\anch_positions_meta_graphic_direct_method{\anch_positions_meta_graphic_direct\??positionmethod } -\def\anch_positions_meta_graphic_direct_normal{\anch_positions_meta_graphic_direct\??positiongraphic} - -\def\anch_positions_meta_graphic_direct#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 - \enforced\def\MPpositiongraphic{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments - \setbox\b_anch_positions_graphic\hbox % \hpack - {\ignorespaces\begincsname#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 - \begincsname\??positiongraphic#2\endcsname - \endgroup}% - -\permanent\def\startMPpositionmethod#1#2\stopMPpositionmethod - {\setgvalue{\??positionmethod#1}{#2}} % todo: var list here - -\aliased\let\stopMPpositionmethod\relax - -%D Simple one position graphics. - -\permanent\tolerant\protected\def\setMPpositiongraphic#=#*#=#*#=% - {\ifempty\currentpositionoverlay - \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). - -\permanent\tolerant\protected\def\setMPpositiongraphicrange#=#*#=#*#=#*#=% - {\ifempty\currentpositionoverlay - \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: - -\permanent\def\MPgetposboxes #1#2{\clf_fetchposboxes{#1}{#2}\realpageno} -\permanent\def\MPgetmultipars#1#2{\clf_fetchmultipar{#1}{#2}\realpageno} - -\protect \endinput diff --git a/tex/context/base/mkiv/anch-pos.lmt b/tex/context/base/mkiv/anch-pos.lmt deleted file mode 100644 index e1d9bd752..000000000 --- a/tex/context/base/mkiv/anch-pos.lmt +++ /dev/null @@ -1,1633 +0,0 @@ -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-- -

We save positional information in the main utility table. Not only -can we store much more information in but it's also -more efficient.

---ldx]]-- - --- plus (extra) is obsolete but we will keep it for a while --- --- maybe replace texsp by our own converter (stay at the lua end) --- eventually mp will have large numbers so we can use sp there too --- --- this is one of the first modules using scanners and we need to replace it by --- implement and friends --- --- we could have namespaces, like p, page, region, columnarea, textarea but then --- we need virtual table accessors as well as have tag/id accessors ... we don't --- save much here (at least not now) --- --- This was the last module that got rid of directly setting scanners, with a little --- performance degradation but not that noticeable. - -local tostring, next, setmetatable, tonumber = tostring, next, setmetatable, tonumber -local sort = table.sort -local format, gmatch = string.format, string.gmatch -local lpegmatch = lpeg.match -local insert, remove = table.insert, table.remove -local allocate = utilities.storage.allocate - -local report = logs.reporter("positions") - -local scanners = tokens.scanners -local scanstring = scanners.string -local scaninteger = scanners.integer -local scandimen = scanners.dimen - -local implement = interfaces.implement - -local commands = commands -local context = context - -local ctx_latelua = context.latelua - -local tex = tex -local texgetcount = tex.getcount -local texgetinteger = tex.getintegervalue or tex.getcount -local texsetcount = tex.setcount -local texget = tex.get -local texsp = tex.sp ------ texsp = string.todimen -- because we cache this is much faster but no rounding - -local setmetatableindex = table.setmetatableindex -local setmetatablenewindex = table.setmetatablenewindex - -local nuts = nodes.nuts - -local setlink = nuts.setlink -local getlist = nuts.getlist -local setlist = nuts.setlist -local getbox = nuts.getbox -local getid = nuts.getid -local getwhd = nuts.getwhd - -local hlist_code = nodes.nodecodes.hlist - -local find_tail = nuts.tail ------ hpack = nuts.hpack - -local new_latelua = nuts.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 - -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 - dir = 0, - } -} - -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_region = formatters["region:%s"] - -local f_tag_three = formatters["%s:%s:%s"] -local f_tag_two = formatters["%s:%s"] - -local nofregular = 0 -local nofspecial = 0 -local splitter = lpeg.splitat(":",true) - -local pagedata = { } -local columndata = setmetatableindex("table") -- per page -local freedata = setmetatableindex("table") -- per page - -local function initializer() - tobesaved = jobpositions.tobesaved - collected = jobpositions.collected - for tag, data in next, collected do - local prefix, rest = lpegmatch(splitter,tag) - if prefix == "p" then - nofregular = nofregular + 1 - elseif prefix == "page" then - nofregular = nofregular + 1 - pagedata[tonumber(rest) or 0] = data - elseif prefix == "free" then - nofspecial = nofspecial + 1 - local t = freedata[data.p or 0] - t[#t+1] = data - elseif prefix == "columnarea" then - columndata[data.p or 0][data.c or 0] = data - end - setmetatable(data,default) - end - -- - local pages = structures.pages.collected - if pages then - local last = nil - for p=1,#pages do - local region = "page:" .. p - local data = pagedata[p] - local free = freedata[p] - if free then - sort(free,function(a,b) return b.y < a.y end) -- order matters ! - end - if data then - last = data - last.free = free - elseif last then - local t = setmetatableindex({ free = free, p = p },last) - if not collected[region] then - collected[region] = t - else - -- something is wrong - end - pagedata[p] = t - end - end - end - jobpositions.pagedata = pagedata -end - -function jobpositions.used() - return next(collected) -- we can safe it -end - -function jobpositions.getfree(page) - return freedata[page] -end - --- we can gain a little when we group positions but then we still have to --- deal with regions and cells so we either end up with lots of extra small --- tables pointing to them and/or assembling/disassembling so in the end --- it makes no sense to do it (now) and still have such a mix --- --- proof of concept code removed ... see archive - -local function finalizer() - -- We make the (possible extensive) shape lists sparse working - -- from the end. We could also drop entries here that have l and - -- r the same which saves testing later on. - for k, v in next, tobesaved do - local s = v.s - if s then - for p, data in next, s do - local n = #data - if n > 1 then - local ph = data[1][2] - local pd = data[1][3] - local xl = data[1][4] - local xr = data[1][5] - for i=2,n do - local di = data[i] - local h = di[2] - local d = di[3] - local l = di[4] - local r = di[5] - if r == xr then - di[5] = nil - if l == xl then - di[4] = nil - if d == pd then - di[3] = nil - if h == ph then - di[2] = nil - else - ph = h - end - else - pd, ph = d, h - end - else - ph, pd, xl = h, d, l - end - else - ph, pd, xl, xr = h, d, l, r - end - end - end - end - end - end -end - -job.register('job.positions.collected', tobesaved, initializer, finalizer) - -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, gethpos, getvpos - -function jobpositions.registerhandlers(t) - getpos = t and t.getpos or function() return 0, 0 end - getrpos = t and t.getrpos or function() return 0, 0, 0 end - gethpos = t and t.gethpos or function() return 0 end - getvpos = t and t.getvpos or function() return 0 end -end - -function jobpositions.getpos () return getpos () end -function jobpositions.getrpos() return getrpos() end -function jobpositions.gethpos() return gethpos() end -function jobpositions.getvpos() return getvpos() end - --------- jobpositions.getcolumn() return column end - -jobpositions.registerhandlers() - -local function setall(name,p,x,y,w,h,d,extra) - tobesaved[name] = { - p = p, - x = x ~= 0 and x or nil, - y = y ~= 0 and y or nil, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - e = extra ~= "" and extra or nil, - r = region, - c = column, - r2l = texgetinteger("inlinelefttoright") == 1 and true or nil, - } -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 - local x, y = getpos() - data.x = x ~= 0 and x or nil - data.y = y ~= 0 and y or nil - else - local x = gethpos() - data.x = x ~= 0 and x or nil - end - elseif data.y == true then - local y = getvpos() - data.y = y ~= 0 and y or nil - end - if data.p == true then - data.p = texgetcount("realpageno") -- we should use a variable set in otr - 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,value) -- ,key - -- officially there should have been a settobesaved - local data = enhance(value or {}) - if value then - container = tobesaved[name] - if not container then - tobesaved[name] = { - [index] = data - } - else - container[index] = data - end - else - tobesaved[name] = data - end -end - -local function setspec(specification) - local name = specification.name - local index = specification.index - local value = specification.value - local data = enhance(value or {}) - if value then - container = tobesaved[name] - if not container then - tobesaved[name] = { - [index] = data - } - else - container[index] = data - end - else - tobesaved[name] = data - end -end - -local function get(id,index) - if index then - local container = collected[id] - return container and container[index] - else - return collected[id] - end -end - -------------.setdim = setdim -jobpositions.setall = setall -jobpositions.set = set -jobpositions.setspec = setspec -jobpositions.get = get - -implement { - name = "dosaveposition", - public = true, - protected = true, - arguments = { "argument", "integerargument", "dimenargument", "dimenargument" }, - actions = setall, -- name p x y -} - -implement { - name = "dosavepositionwhd", - public = true, - protected = true, - arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument" }, - actions = setall, -- name p x y w h d -} - -implement { - name = "dosavepositionplus", - public = true, - protected = true, - arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "argument" }, - actions = setall, -- name p x y w h d extra -} - --- 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) - -local function b_column(specification) - local tag = specification.tag - local x = gethpos() - tobesaved[tag] = { - r = true, - x = x ~= 0 and x or nil, - -- w = 0, - } - insert(columns,tag) - column = tag -end - -local function e_column() - local t = tobesaved[column] - if not t then - -- something's wrong - else - local x = gethpos() - t.x - t.w = x ~= 0 and x or nil - t.r = region - end - remove(columns) - column = columns[#columns] -end - -jobpositions.b_column = b_column -jobpositions.e_column = e_column - -implement { - name = "bposcolumn", - arguments = "string", - actions = function(tag) - insert(columns,tag) - column = tag - end -} - -implement { - name = "bposcolumnregistered", - arguments = "string", - actions = function(tag) - insert(columns,tag) - column = tag - ctx_latelua { action = b_column, tag = tag } - end -} - -implement { - name = "eposcolumn", - actions = function() - remove(columns) - column = columns[#columns] - end -} - -implement { - name = "eposcolumnregistered", - actions = function() - ctx_latelua { action = e_column } - remove(columns) - column = columns[#columns] - end -} - --- regions - -local function b_region(specification) - local tag = specification.tag or specification - local last = tobesaved[tag] - local x, y = getpos() - last.x = x ~= 0 and x or nil - last.y = y ~= 0 and y or nil - last.p = texgetcount("realpageno") - insert(regions,tag) -- todo: fast stack - region = tag -end - -local function e_region(specification) - local last = tobesaved[region] - local y = getvpos() - local x, y = getpos() - if specification.correct then - local h = (last.y or 0) - y - last.h = h ~= 0 and h or nil - end - last.y = y ~= 0 and y or nil - remove(regions) -- todo: fast stack - region = regions[#regions] -end - -jobpositions.b_region = b_region -jobpositions.e_region = e_region - -local lastregion - -local function setregionbox(n,tag,k,lo,ro,to,bo,column) -- kind - if not tag or tag == "" then - nofregions = nofregions + 1 - tag = f_region(nofregions) - end - local box = getbox(n) - local w, h, d = getwhd(box) - tobesaved[tag] = { - -- p = texgetcount("realpageno"), -- we copy them - x = 0, - y = 0, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - k = k ~= 0 and k or nil, - lo = lo ~= 0 and lo or nil, - ro = ro ~= 0 and ro or nil, - to = to ~= 0 and to or nil, - bo = bo ~= 0 and bo or nil, - c = column or nil, - } - lastregion = tag - return tag, box -end - -local function markregionbox(n,tag,correct,...) -- correct needs checking - local tag, box = setregionbox(n,tag,...) - -- todo: check if tostring is needed with formatter - local push = new_latelua { action = b_region, tag = tag } - local pop = new_latelua { action = e_region, correct = correct } - -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end - local head = getlist(box) - -- no, this fails with \framed[region=...] .. needs thinking - -- if getid(box) ~= hlist_code then - -- -- report("mark region box assumes a hlist, fix this for %a",tag) - -- head = hpack(head) - -- end - 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 - -function jobpositions.gettobesaved(name,tag) - local t = tobesaved[name] - if t and tag then - return t[tag] - else - return t - end -end - -function jobpositions.settobesaved(name,tag,data) - local t = tobesaved[name] - if t and tag and data then - t[tag] = data - end -end - -local nofparagraphs = 0 - -implement { - name = "parpos", - actions = function() - nofparagraphs = nofparagraphs + 1 - texsetcount("global","c_anch_positions_paragraph",nofparagraphs) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local t = { - p = true, - c = true, - r = true, - x = true, - y = true, - h = h, - d = d, - hs = texget("hsize"), -- never 0 - } - local leftskip = texget("leftskip",false) - local rightskip = texget("rightskip",false) - 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 name = f_p_tag(nofparagraphs) - tobesaved[name] = t - ctx_latelua { action = enhance, specification = t } - end -} - -implement { - name = "dosetposition", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} - -implement { - name = "dosetpositionwhd", - arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, - public = true, - protected = true, - actions = function(name,w,h,d) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} - -implement { - name = "dosetpositionbox", - arguments = { "argument", "integerargument" }, - public = true, - protected = true, - actions = function(name,n) - local box = getbox(n) - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} - -implement { - name = "dosetpositionplus", - arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, - public = true, - protected = true, - actions = function(name,w,h,d) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - e = scanstring(), - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} - -implement { - name = "dosetpositionstrut", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} - -implement { - name = "dosetpositionstrutkind", - arguments = { "argument", "integerargument" }, - public = true, - protected = true, - actions = function(name,kind) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - k = kind, - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - 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 - -local function getpage(id) - local jpi = collected[id] - return jpi and jpi.p -end - -local function getcolumn(id) - local jpi = collected[id] - return jpi and jpi.c or false -end - -local function getparagraph(id) - local jpi = collected[id] - return jpi and jpi.n -end - -local function getregion(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 - -jobpositions.page = getpage -jobpositions.column = getcolumn -jobpositions.paragraph = getparagraph -jobpositions.region = getregion - -jobpositions.p = getpage -- not used, kind of obsolete -jobpositions.c = getcolumn -- idem -jobpositions.n = getparagraph -- idem -jobpositions.r = getregion -- idem - -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.whd(id) - local jpi = collected[id] - if jpi then - return jpi.h, jpi.h, jpi.d - end -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 - -local splitter = lpeg.splitat(",") - -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 - -local function columnofpos(realpage,xposition) - local p = columndata[realpage] - if p then - for i=1,#p do - local c = p[i] - local x = c.x or 0 - local w = c.w or 0 - if xposition >= x and xposition <= (x + w) then - return i - end - end - end - return 1 -end - -jobpositions.overlapping = overlapping -jobpositions.onsamepage = onsamepage -jobpositions.columnofpos = columnofpos - --- interface - -implement { - name = "replacepospxywhd", - arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument" }, - public = true, - protected = true, - actions = function(name,page,x,y,w,h,d) - collected[name] = { - p = page, - x = x, - y = y, - w = w, - h = h, - d = d, - } - end -} - -implement { - name = "copyposition", - arguments = "2 arguments", - public = true, - protected = true, - actions = function(target,source) - collected[target] = collected[source] - end -} - -implement { - name = "MPp", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local p = jpi.p - if p and p ~= true then - context(p) - return - end - end - context('0') - end -} - -implement { - name = "MPx", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 -} - -implement { - name = "MPy", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 -} - -implement { - name = "MPw", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local w = jpi.w - if w and w ~= 0 then - context("%.5Fpt",w*pt) - return - end - end - context('0pt') - end -} - -implement { - name = "MPh", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local h = jpi.h - if h and h ~= 0 then - context("%.5Fpt",h*pt) - return - end - end - context('0pt') - end -} - -implement { - name = "MPd", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local d = jpi.d - if d and d ~= 0 then - context("%.5Fpt",d*pt) - return - end - end - context('0pt') - end -} - -implement { - name = "MPxy", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - context('(%.5Fpt,%.5Fpt)', - jpi.x*pt, - jpi.y*pt - ) - else - context('(0,0)') - end - end -} - -implement { - name = "MPwhd", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local w = jpi.w or 0 - local h = jpi.h or 0 - local d = jpi.d or 0 - if w ~= 0 or h ~= 0 or d ~= 0 then - context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt) - return - end - end - context('0pt,0pt,0pt') - end -} - -implement { - name = "MPll", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - context('(%.5Fpt,%.5Fpt)', - jpi.x *pt, - (jpi.y-jpi.d)*pt - ) - else - context('(0,0)') -- for mp only - end - end -} - -implement { - name = "MPlr", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 -} - -implement { - name = "MPur", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 -} - -implement { - name = "MPul", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 - -implement { - name = "MPpos", - arguments = "argument", - public = true, - actions = MPpos -} - -implement { - name = "MPn", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local n = jpi.n - if n then - context(n) - return - end - end - context(0) - end -} - -implement { - name = "MPc", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local c = jpi.c - if c and c ~= true then - context(c) - return - end - end - context('0') -- okay ? - end -} - -implement { - name = "MPr", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - local r = jpi.r - if r and r ~= true then - context(r) - return - end - local p = jpi.p - if p and p ~= true then - context("page:" .. p) - end - end - end -} - -local function MPpardata(id) - local t = collected[id] - if not t then - local tag = f_p_tag(id) - 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 - -implement { - name = "MPpardata", - arguments = "argument", - public = true, - actions = MPpardata -} - -implement { - name = "MPposset", - arguments = "argument", - public = true, - actions = function(name) - local b = f_b_tag(name) - local e = f_e_tag(name) - local w = f_w_tag(name) - local p = f_p_tag(getparagraph(b)) - MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) - end -} - -implement { - name = "MPls", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - context("%.5Fpt",jpi.ls*pt) - else - context("0pt") - end - end -} - -implement { - name = "MPrs", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - if jpi then - context("%.5Fpt",jpi.rs*pt) - else - context("0pt") - end - end -} - -local splitter = lpeg.tsplitat(",") - -implement { - name = "MPplus", - arguments = { "argument", "integerargument", "argument" }, - public = true, - actions = function(name,n,default) - local jpi = collected[name] - 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 -} - -implement { - name = "MPrest", - arguments = { "argument", "argument" }, - public = true, - actions = function(name,default) - local jpi = collected[name] - context(jpi and jpi.e or default) - end -} - -implement { - name = "MPxywhd", - arguments = "argument", - public = true, - actions = function(name) - local jpi = collected[name] - 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 - -implement { - name = "doifelseposition", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - doifelse(collected[name]) - end -} - -implement { - name = "doifposition", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - doif(collected[name]) - end -} - -implement { - name = "doifelsepositiononpage", - arguments = { "string", "integerargument" }, - public = true, - protected = true, - actions = function(name,p) - local c = collected[name] - doifelse(c and c.p == p) - end -} - -implement { - name = "doifelseoverlapping", - arguments = { "argument", "argument" }, - public = true, - protected = true, - actions = function(one,two) - doifelse(overlapping(one,two)) - end -} - -implement { - name = "doifelsepositionsonsamepage", - arguments = "argument", -- string - public = true, - protected = true, - actions = function(list) - doifelse(onsamepage(list)) - end -} - -implement { - name = "doifelsepositionsonthispage", - arguments = "argument", -- string - public = true, - protected = true, - actions = function(list) - doifelse(onsamepage(list,tostring(texgetcount("realpageno")))) - end -} - -implement { - name = "doifelsepositionsused", - public = true, - protected = true, - actions = function() - doifelse(next(collected)) - end -} - -implement { - name = "markregionbox", - arguments = "integer", - actions = markregionbox -} - -implement { - name = "setregionbox", - arguments = "integer", - actions = setregionbox -} - -implement { - name = "markregionboxtagged", - arguments = { "integer", "string" }, - actions = markregionbox -} - -implement { - name = "markregionboxtaggedn", - arguments = { "integer", "string", "integer" }, - actions = function(box,tag,n) - markregionbox(box,tag,nil,nil,nil,nil,nil,nil,n) - end -} - -implement { - name = "setregionboxtagged", - arguments = { "integer", "string" }, - actions = setregionbox -} - -implement { - name = "markregionboxcorrected", - arguments = { "integer", "string", true }, - actions = markregionbox -} - -implement { - name = "markregionboxtaggedkind", - arguments = { "integer", "string", "integer", "dimen", "dimen", "dimen", "dimen" }, - actions = function(box,tag,n,d1,d2,d3,d4) - markregionbox(box,tag,nil,n,d1,d2,d3,d4) - end -} - -implement { - name = "reservedautoregiontag", - public = true, - actions = function() - nofregions = nofregions + 1 - context(f_region(nofregions)) - 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) - -statistics.register("positions", function() - local total = nofregular + nofspecial - if total > 0 then - return format("%s collected, %s regular, %s special",total,nofregular,nofspecial) - else - return nil - end -end) - --- We support the low level positional commands too: - -local newsavepos = nodes.pool.savepos - -implement { name = "savepos", actions = function() context(newsavepos()) end } -implement { name = "lastxpos", actions = function() context(gethpos()) end } -implement { name = "lastypos", actions = function() context(getvpos()) end } diff --git a/tex/context/base/mkiv/anch-pos.mkxl b/tex/context/base/mkiv/anch-pos.mkxl deleted file mode 100644 index e232d9cd3..000000000 --- a/tex/context/base/mkiv/anch-pos.mkxl +++ /dev/null @@ -1,504 +0,0 @@ -%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}{autosuffix} - -\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 - -% \dosaveposition #1#2#3#4 % defined at lua end -% \dosavepositionwhd #1#2#3#4#5#6#7 % defined at lua end -% \dosavepositionplus #1#2#3#4#5#6#7#8 % defined at lua end - -% \dosetposition #1 % defined at lua end -% \dosetpositionwhd #1#2#3#4 % defined at lua end -% \dosetpositionplus #1#2#3#4#5 % defined at lua end -% \dosetpositionbox #1#2 % defined at lua end -% \dosetpositionstrut #1 % defined at lua end -% \dosetpositionstrutkind #1#2 % defined at lua end - -\newbox\b_anch_position -\newif \ifpositioning % sort of public - -%D Sometimes we want to trick the position handler a bit: - -% \replacepospxywhd #1#2#3#4#5#6#7 % defined at lua end - -%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. - -% \MPp : defined at lua end -% \MPr : defined at lua end -% \MPc : defined at lua end -% \MPn : defined at lua end -% \MPx : defined at lua end -% \MPy : defined at lua end -% \MPw : defined at lua end -% \MPh : defined at lua end -% \MPd : defined at lua end -% \MPxy : defined at lua end -% \MPwhd : defined at lua end -% \MPll : defined at lua end -% \MPlr : defined at lua end -% \MPur : defined at lua end -% \MPul : defined at lua end -% \MPpos : defined at lua end -% \MPls : defined at lua end -% \MPrs : defined at lua end -% \MPpardata : defined at lua end -% \MPxywhd : defined at lua end -% \MPposset : defined at lua end - -\aliased\let\MPpage \MPp -\aliased\let\MPregion \MPr -\aliased\let\MPcolumn \MPc -\aliased\let\MPparagraph\MPn - - \let\MPanchor \MPpos % overloaded locally when needed (todo: LMTX) - -\aliased\let\MPleftskip \MPls % compatible feature -\aliased\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. - -% \MPplus #1#2#3 % defined at lua end -% \MPrest #1 % defined at lua end - -\aliased\let\MPv \MPplus -\aliased\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} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\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 % \hpack - {\edef\currentposition{#1}% - \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr - \anch_positions_trace_left - \dopositionaction\currentposition - \hss}} - -\permanent\protected\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 % \hpack - {\edef\currentposition{#1}% - \dosetpositionbox\currentposition\nextbox - \anch_positions_trace_left - \setbox\b_anch_position\box\nextbox - \dopositionaction\currentposition - \box\b_anch_position - \hss}} - -\permanent\protected\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 % \hpack - {\edef\currentposition{#1}% - \dosetpositionstrut\currentposition - \anch_positions_trace_left - \dopositionaction\currentposition - \strut - \hss}} - -\permanent\protected\def\setpositionstrutkind - {\iftrialtypesetting - \expandafter\anch_positions_set_strut_kind_nop - \else - \expandafter\anch_positions_set_strut_kind_yes - \fi} - -\def\anch_positions_set_strut_kind_yes#1#2% - {\anch_positions_initialize - \hbox to \zeropoint % \hpack - {\edef\currentposition{#1}% - \dosetpositionstrutkind\currentposition{#2}% - \anch_positions_trace_left - \dopositionaction\currentposition - \strut - \hss}} - -\def\anch_positions_set_strut_kind_nop#1#2% - {\strut} - -\permanent\protected\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 % \hpack - {\edef\currentposition{#1}% - \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr - \anch_positions_trace_right - \dopositionaction\currentposition - \hss}} - -\permanent\protected\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 % \hpack - {\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 { } - -\protected\def\anch_mark_column_box#1#2% box n - {\global\advance\c_anch_column\plusone - \clf_markregionboxtaggedn#1{columnarea:\the\c_anch_column}#2\relax} % extra height - -\protected\def\anch_mark_region_box - {\iftrialtypesetting - \expandafter\gobbleoneargument - \orelse\ifpositioning - \expandafter\anch_mark_region_box_indeed - \else - \expandafter\gobbleoneargument - \fi} - -\protected\def\anch_mark_region_box_indeed#1% - {\clf_markregionbox#1\relax} - -\protected\def\anch_mark_flow_box#1% will be extended / renamed - {\hpack\bgroup - \global\advance\c_anch_text\plusone - \clf_markregionboxtagged#1{textarea:\the\c_anch_text}% - \box#1% - \egroup} - -\protected\def\anch_mark_tagged_box#1#2% - {\clf_markregionboxtagged#1{#2}} - -\protected\def\anch_mark_flow_only#1% will be extended / renamed - {\global\advance\c_anch_text\plusone - \clf_markregionboxcorrected#1{textarea:\the\c_anch_text}} - -\protected\def\anch_make_page_box#1% maybe like text - {\clf_setregionboxtagged#1{page:\the\realpageno}} - -\protected\def\anch_mark_text_box#1% - {\clf_markregionboxtagged#1{text:\the\realpageno}} % needs an hbox - -\newcount\c_anch_free - -\protected\def\anch_mark_tagged_box_free#1#2#3#4#5#6% only needed when positions - {\ifpositioning - \global\advance\c_anch_free\plusone % could be done at the lua end - \clf_markregionboxtaggedkind - #1% - {free:\number\c_anch_free}% - #2\space % kind - #3\space % leftoffset - #4\space % rightoffset - #5\space % topoffset - #6\relax % bottomoffset - \fi} - -% \reservedautoregiontag % define at lua end - -%D We can copy a position with: -%D -%D \starttyping -%D \copyposition {to} {from} -%D \stoptyping -%D -%D Again, this is a global operation. - -% \copyposition #1#2 % defined at lua end - -%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 - -% \doifposition #1 % defined at lua end -% \doifelseposition #1#2 % defined at lua end -% \doifelsepositiononpage #1#2 % defined at lua end - -\aliased\let\doifpositionelse \doifelseposition -\aliased\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. - -\aliased\let\xypos\setpositiononly - -\permanent\protected\def\hpos #1{\dontleavehmode\setpositionbox{#1}\hbox} -\permanent\protected\def\vpos #1{\setpositionbox{#1}\vbox} -\permanent\protected\def\bpos #1{\dontleavehmode\setpositionstrut{b:#1}\ignorespaces} -\permanent\protected\def\epos #1{\removeunwantedspaces\setpositionstrut{e:#1}} -\permanent\protected\def\bposkind#1#2{\dontleavehmode\setpositionstrutkind{b:#1}{#2}\ignorespaces} % not public, used in backgrounds -\permanent\protected\def\eposkind#1#2{\removeunwantedspaces\setpositionstrutkind{e:#1}{#2}} % not public, used in backgrounds - -%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 - -\permanent\protected\def\tracepositions - {\the\t_anch_positions_tracers} - -\permanent\protected\def\enableparpositions % global - {\glet\registerparoptions\doregisterparoptions - \global\positioningtrue} - -\permanent\let\disableparpositions\relax - -\let\registerparoptions\relax - -\protected\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 - -\protected\def\anch_positions_trace#1#2#3% - {\smashedhbox - {#1{\infofont#2#3}% - \kern-\onepoint - \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}} - -\protected\def\anch_positions_trace_left_indeed - {\anch_positions_trace\llap\darkmagenta{\currentposition>}} - -\protected\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 boxes do -%D overlap: -%D -%D \starttyping -%D \doifoverlappingelse{point a}{point b} -%D {action when overlapping} -%D {action when not overlapping} -%D \stoptyping - -% \doifelseoverlapping #1#2#3#4 % defined at lua end - -\aliased\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 - -% \doifelsepositionsonsamepage #1 % defined at lua end -% \doifelsepositionsonthispage #1 % defined at lua end -% \doifelsepositionsused % defined at lua end - -\aliased\let\doifpositionsonsamepageelse\doifelsepositionsonsamepage -\aliased\let\doifpositionsonthispageelse\doifelsepositionsonthispage -\aliased\let\doifpositionsusedelse \doifelsepositionsused - -%D Moved here: - -\permanent\protected\def\savepos {\clf_savepos} -\permanent\protected\def\lastxpos{\numexpr\clf_lastxpos\relax} -\permanent\protected\def\lastypos{\numexpr\clf_lastypos\relax} - -\protect \endinput diff --git a/tex/context/base/mkiv/anch-snc.mkxl b/tex/context/base/mkiv/anch-snc.mkxl deleted file mode 100644 index 5f0246155..000000000 --- a/tex/context/base/mkiv/anch-snc.mkxl +++ /dev/null @@ -1,160 +0,0 @@ -%D \module -%D [ file=anch-snc, -%D version=2003.12.01, % actually 1999 so real old -%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. - -%D The original is in the mkii file. It does more at the \TEX\ end and -%D has some more magic. If we really need that I'll add it. After all, -%D in mkiv we can do things different. - -%D TODO: bleed : + left , minus right oro check if it touches page ... autobleed - -\writestatus{loading}{ConTeXt Anchoring Macros / Synchronization} - -\registerctxluafile{anch-snc}{} - -\unprotect - -\ifx\??syncposcounter\undefined \installcorenamespace{syncposcounter} \fi -\ifx\s!syncpos \undefined \def\s!syncpos {syncpos} \fi - -\let\c_sync_n\relax - -\unexpanded\def\definesyncpositions[#1]% - {\ifcsname\??syncposcounter:#1\endcsname \else - \expandafter\newcount\csname\??syncposcounter:#1\endcsname - \fi} - -\unexpanded\def\syncposition - {\dodoubleempty\anch_sync_position} - -\def\anch_sync_position[#1][#2]% we could actually use par positions - {\dontleavehmode - \ifcsname\??syncposcounter:#1\endcsname - \let\c_sync_n\lastnamedcs - \global\advance\c_sync_n\plusone - \enabletextarearegistration - \setpositionplus{\s!syncpos:#1:\the\c_sync_n}{#2}\hpack{\strut}% - \else - \strut - \fi - \ignorespaces} - -\protect - -\continueifinputfile{anch-snc.mkiv} - -\starttext - -% \setuppapersize[A4][A3] - -\setuplayout[location=middle] - -\setupbodyfont[dejavu] - -\definesyncpositions[1] -\definesyncpositions[2] - -% \enabletrackers[metapost.lua] - -\startMPdefinitions - input "mp-asnc.mpiv" ; - - SetSyncColor(1,0,"magenta") ; - SetSyncColor(1,1,"red") ; - SetSyncColor(1,2,"green") ; - SetSyncColor(1,3,"blue") ; - SetSyncColor(1,4,"yellow") ; - - SetSyncColor(2,0,"magenta") ; - SetSyncColor(2,1,"red") ; - SetSyncColor(2,2,"green") ; - SetSyncColor(2,3,"blue") ; - SetSyncColor(2,4,"yellow") ; -\stopMPdefinitions - -\startuseMPgraphic{sync1} - StartPage ; - StartSync(1) ; - SyncHOffset := 0 ; - SyncWidth := BackSpace - LeftMarginDistance; - CollectSyncDataPage ; - % ExtendSyncPaths ; % to top of text area - PruneSyncPaths ; % clip top / bottom - CollapseSyncPaths ; - MakeSyncPaths ; - % DrawSyncPaths ; - FillSyncPaths ; - StopSync ; - clip currentpicture to Page ; - setbounds currentpicture to Page ; - StopPage ; -\stopuseMPgraphic - -\startuseMPgraphic{sync2} - StartSync(2) ; - SyncHOffset := -1cm ; - SyncWidth := 1cm ; - CollectSyncDataRegion(OverlayRegion) ; - ExtendSyncPaths ; % to top of text area - MakeSyncPaths ; - FillSyncPaths ; - StopSync ; - clip currentpicture to OverlayBox leftenlarged 1cm; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic - -\defineoverlay[tempoverlay1][\useMPgraphic{sync1}] -\defineoverlay[tempoverlay2][\useMPgraphic{sync2}] - -\setupbackgrounds[page][background=tempoverlay1] - -\framed[region=yes,background=tempoverlay2,width=14cm,align=normal]{ - \syncposition[2][1]\samplefile{ward}\endgraf - \syncposition[2][2]\samplefile{ward}\endgraf - \syncposition[2][3]\samplefile{ward}\endgraf -} - - -\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=16cm,align=normal]{ - \syncposition[2][1]\samplefile{ward}\endgraf - \syncposition[2][2]\samplefile{ward}\endgraf - \syncposition[2][3]\samplefile{ward}\endgraf -} - -\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=10cm,align=normal]{ - \syncposition[2][1]\samplefile{ward}\endgraf - \syncposition[2][2]\samplefile{ward}\endgraf - \syncposition[2][3]\samplefile{ward}\endgraf -} - - -\dorecurse {100} { -% \dorecurse {1} { - \startchapter[title={Test #1}] - \syncposition[1][1,reset]\dorecurse{20}{\samplefile{ward}\endgraf} - \syncposition[1][2]\dorecurse {4}{\samplefile{ward}\endgraf} - \syncposition[1][3]\dorecurse {7}{\samplefile{ward}\endgraf} - \syncposition[1][4]\dorecurse {3}{\samplefile{ward}\endgraf} - \stopchapter -} - -\dorecurse {100} { -% \dorecurse {1} { - \startchapter[title={Test #1}] - \syncposition[1][1]\dorecurse{1}{\samplefile{ward}\endgraf} - \syncposition[1][2]\dorecurse{1}{\samplefile{ward}\endgraf} - \syncposition[1][3]\dorecurse{1}{\samplefile{ward}\endgraf} - \syncposition[1][4]\dorecurse{1}{\samplefile{ward}\endgraf} - \stopchapter -} - -\stoptext diff --git a/tex/context/base/mkiv/anch-tab.mkxl b/tex/context/base/mkiv/anch-tab.mkxl deleted file mode 100644 index 8f4bb0b5b..000000000 --- a/tex/context/base/mkiv/anch-tab.mkxl +++ /dev/null @@ -1,382 +0,0 @@ -%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 dissappear in -%D favour of better solutions. Anyway, it now has been aroudn too long to bother. - -\unprotect - -\newcount\c_anch_tabs - -\protected\def\tabl_tabulate_hook_b - {\iftrialtypesetting\else - \ifpositioning - \ifconditional\tablehaspositions - \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 - \fi} - -\protected\def\tabl_tabulate_hook_e - {\iftrialtypesetting\else - \ifpositioning - \ifconditional\tablehaspositions - \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 - \fi} - -\protected\def\tabl_tabulate_hook_b_first{\clf_bposcolumnregistered{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}} -\protected\def\tabl_tabulate_hook_b_next {\clf_bposcolumn{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}} -\protected\def\tabl_tabulate_hook_e_first{\clf_eposcolumnregistered} -\protected\def\tabl_tabulate_hook_e_next {\clf_eposcolumn} - -% \appendtoks \registerparoptions \to \everypar - -\appendtoks - \global\advance\c_anch_tabs\plusone -\to \everytabulate - -% for text backgrounds - -\appendtoks - \settrue\c_anch_backgrounds_pos_no_shape -\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 - -\protected\def\anch_tabulate_bpos{\bpos} -\protected\def\anch_tabulate_epos{\epos} - -\installcorenamespace{positiontables} - -\permanent\def\tbPOSprefix{\??positiontables\number\noftabpositions:} - -\protected\def\tablepos - {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}} - -\permanent\protected\def\tbXC {\anch_table_checked\anch_tables_indeed_XC } -\permanent\protected\def\tbGSC{\anch_table_checked\anch_tables_indeed_GSC} -\permanent\protected\def\tbGFC{\anch_table_checked\anch_tables_indeed_GFC} -\permanent\protected\def\tbGTC{\anch_table_checked\anch_tables_indeed_GTC} - -\tolerant\def\anch_table_checked#1[#2]% - {\iftrialtypesetting - \global\settrue\tablehaspositions - \expandafter\anch_tables_indeed_NC - \orelse\ifparameter#2\or - \expandafter#1% - \else - \expandafter\anch_tables_indeed_NC - \fi[#2]} - -\def\anch_tables_indeed_NC[#1]% - {\NC} - -\def\anch_tables_indeed_XC[#1]% - {{\enforced\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]\orelse - \if#1+\anch_tables_indeed_GFC[#2:#2]\orelse - \if#1<\anch_tables_indeed_GTC[#2:#2]\orelse - \if#1-\anch_tables_indeed_GTC[#2:#2]\orelse - \if#1=\anch_tables_indeed_GSC[#2:#2]\orelse - \anch_tables_indeed_GSC[#1#2:#1#2]\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} - {\gtoksapp\posXCtoks{\anch_tables_process_GSC[#1:#2]}\NC} - -\def\anch_tables_process_GSC[#1:#2]% - {\remappositionframed{#2}{\tbPOSprefix#1}% - \anch_tabulate_bpos{\tbPOSprefix#1}% - \doglobal\appendtoks\expandafter\anch_tabulate_epos\expandafter{\tbPOSprefix#1}\to\posXCtoks} -% \xtoksapp\posXCtoks{\anch_tabulate_epos{\tbPOSprefix#1}}} - -\def\anch_tables_indeed_GFC[#1]% - {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC} -% {\gtoksapp\posXCtoks{\anch_tables_delayed_GFC[#1]}\NC} - -\def\anch_tables_delayed_GFC[#1]% - {\processcommalist[#1]\anch_tables_step_GFC} - -\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} -% {\gtoksapp\posXCtoks{\anch_tables_delayed_GTC[#1]}\NC} - -\def\anch_tables_delayed_GTC[#1]% - {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks} -% {\gtoksapp\posXCtoks{\anch_tables_process_GTC[#1]}\NC} - -\def\anch_tables_process_GTC[#1]% - {\processcommalist[#1]\anch_tables_step_GTC} - -\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 minimalistic. - -\aliased\let\tabulatepos\tablepos - -\def\tabulatenormalpos - {\iftrialtypesetting - % nothing - \orelse\ifconditional\tablehaspositions - \hss\tabulatepos\hss - \else - % nothing - \fi} - -\def\tabulateequalpos - {\iftrialtypesetting - \tabulateEQ - \orelse\ifconditional\tablehaspositions - \tabulateEQpos - \else - \tabulateEQ - \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 - -\protected\def\anch_tabulate_bpos_indeed - {\bpos} - -\protected\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} - -\permanent\def\flushtabulatesplitbox - {\box\b_tabl_tabulate - \iftrialtypesetting\orelse\ifconditional\tablehaspositions\anch_tabulate_flush_epos\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 - \enforced\let\GSC\tbGSC - \enforced\let\GFC\tbGFC - \enforced\let\GTC\tbGTC - \enforced\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: - -\permanent\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&} % | -\permanent\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \| -\permanent\def\normalTABLEquote {\unskip\!ttRightGlue&\omit\tablepos&} % " - -\appendtoks - \global\advance\noftabpositions\plusone - \global\setfalse\tablehaspositions -\to \everytable - -%D Since we don't want nameclashes: - -\appendtoks - \enforced\let\GSC\tbGSC - \enforced\let\GFC\tbGFC - \enforced\let\GTC\tbGTC - \enforced\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] - -\permanent\protected\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}}} - -\permanent\tolerant\protected\def\definepositionframed[#1]#*[#2]% - {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}} - -\protected\def\anch_framed_handle - {\bgroup - \anch_framed_indeed} - -\permanent\tolerant\protected\def\positionframed[#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/tex/context/base/mkiv/attr-col.mkxl b/tex/context/base/mkiv/attr-col.mkxl deleted file mode 100644 index c75f448e9..000000000 --- a/tex/context/base/mkiv/attr-col.mkxl +++ /dev/null @@ -1,22 +0,0 @@ -%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}{} - -\unprotect - -% We implement this elsewhere but some code might end up here. - -\protect \endinput diff --git a/tex/context/base/mkiv/attr-eff.mkxl b/tex/context/base/mkiv/attr-eff.mkxl deleted file mode 100644 index 04a0c55ce..000000000 --- a/tex/context/base/mkiv/attr-eff.mkxl +++ /dev/null @@ -1,60 +0,0 @@ -%D \module -%D [ file=attr-eff, -%D version=2007.06.06, -%D title=\CONTEXT\ Attribute Macros, -%D subtitle=Effects, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Attribute Macros / Effects} - -\registerctxluafile{attr-eff}{} - -\unprotect - -\installcorenamespace{effect} - -\installcommandhandler \??effect {effect} \??effect - -\setupeffect - [\c!method=\v!none, - \c!stretch=\zerocount, - \c!rulethickness=\zeropoint, - \c!alternative=\v!normal] - -\appendtoks - \edef\p_method{\effectparameter\c!method}% - \ifx\p_method\v!command - \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}% - \setuxvalue{\e!stop \currenteffect}{\stopeffect}% - \fi -\to \everydefineeffect - -\permanent\protected\def\starteffect[#1]% - {\clf_seteffect - alternative {\namedeffectparameter{#1}\c!alternative} - stretch \numexpr\namedeffectparameter{#1}\c!stretch\relax - rulethickness \dimexpr\namedeffectparameter{#1}\c!rulethickness\relax - \relax} - -\permanent\protected\def\stopeffect % can be special - {\clf_reseteffect} % v!normal 0 0 - -\permanent\protected\def\effect[#1]% - {\groupedcommand{\starteffect[#1]}{\stopeffect}} - -% yes or no grouped - -\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt] -\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt] -\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt] -\defineeffect [\v!normal] [\c!alternative=\v!normal] -\defineeffect [\v!hidden] [\c!alternative=\v!hidden] -\defineeffect [\v!stretch] [\c!alternative=\v!stretch,\c!stretch=1] - -\protect \endinput diff --git a/tex/context/base/mkiv/attr-ini.mkxl b/tex/context/base/mkiv/attr-ini.mkxl deleted file mode 100644 index 47e680c25..000000000 --- a/tex/context/base/mkiv/attr-ini.mkxl +++ /dev/null @@ -1,143 +0,0 @@ -%D \module -%D [ file=attr-ini, -%D version=2007.06.06, -%D title=\CONTEXT\ Attribute Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Attribute Macros / Initialization} - -%D Although it's still somewhat experimental, here we introduce code -%D related to attributes. Housekeeping will move completely to \LUA\ -%D and \type {\newattribute} will go away. - -\unprotect - -\registerctxluafile{attr-ini}{} - -\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd) -\installcorenamespace{attributeid} % the internal number -\installcorenamespace{attributestack} % the attribute specific stack -\installcorenamespace{attributepickup} - -\permanent\protected\def\pushattribute#1% - {\global\advance\csname\??attributestack\string#1\endcsname\plusone - \global\defcsname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}} - -\permanent\protected\def\popattribute#1% - {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax - \global\advance\csname\??attributestack\string#1\endcsname\minusone} - -\permanent\protected\def\installattributestack#1% - {\ifcsname\??attributestack\string#1\endcsname \else - \expandafter\newcount\csname\??attributestack\string#1\endcsname - \fi} - -\newtoks \t_attr_list_global -\newtoks \t_attr_list_local -\newtoks \t_attr_list_pickup -\newtoks \t_attr_list_nomath - -\ifdefined \s!global \else \immutable\def\s!global {global} \fi % for metatex % or hard check later -\ifdefined \s!public \else \immutable\def\s!public {public} \fi % for metatex % or hard check later -\ifdefined \s!private \else \immutable\def\s!private {private} \fi % for metatex % or hard check later -\ifdefined \s!attribute \else \immutable\def\s!attribute{attribute} \fi % for metatex % or hard check later -\ifdefined \s!pickup \else \immutable\def\s!pickup {pickup} \fi % for metatex % or hard check later -\ifdefined \s!forget \else \immutable\def\s!forget {forget} \fi % for metatex % or hard check later - -\immutable\def\??attributeprefix{c_attr_} - -\permanent\protected\def\defineattribute {\attr_basics_define_indeed[\s!public ]} -\permanent\protected\def\definesystemattribute{\attr_basics_define_indeed[\s!private]} - -\tolerant\def\attr_basics_define_indeed[#1]#*[#2]#*[#3]% - {\ifcsname\??attributeprefix#2\endcsname\else - \scratchcounter\clf_defineattribute{#2}{#1}\relax - %\writestatus\m!system{defining #1 attribute #2 with number \number\scratchcounter}% - \global\permanent\expandafter\attributedef\csname\??attributeprefix#2\endcsname\scratchcounter % \foo = 123 - \global\permanent\expandafter\integerdef \csname\??attributeid #2\endcsname\scratchcounter % \attribute\foo = 123 - % some attributes are always global - \doifelseinset\s!global{#3}% - {\xtoksapp\t_attr_list_global{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% \c_attr_foo - {\xtoksapp\t_attr_list_local {\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% - \doifinset\s!nomath{#3}% - {\xtoksapp\t_attr_list_nomath{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% - \doifinset\s!public{#3}% - {\aliased\global\letcsname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}% \attribute\fooattribute - \doifinset\s!pickup{#3}% - {\global\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue - \xtoksapp\t_attr_list_pickup{\csname\??attributeprefix#2\endcsname\csname\??attributepickup#2\endcsname}% - \ifcsname#2\s!attribute\endcsname - \global\edefcsname\s!pickup#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\csname\??attributeprefix#2\endcsname}% - \global\edefcsname\s!forget#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue}% - \fi}% - \fi} - -\permanent\protected\def\pickupattributes - {\the\t_attr_list_pickup\relax} - -\permanent\protected\def\newattribute#1% - {\attr_basics_define_indeed\s!public[\csstring#1][]% - \expandafter\glet\expandafter#1\csname\??attributeid\csstring#1\endcsname} - -% expandable so we can \edef them for speed - -\permanent\def\dosetattribute#1#2{\csname\??attributeprefix#1\endcsname#2\relax} -\permanent\def\doresetattribute#1{\csname\??attributeprefix#1\endcsname\attributeunsetvalue} -\permanent\def\dogetattribute #1{\number\csname\??attributeprefix#1\endcsname} -\permanent\def\dogetattributeid#1{\number\csname\??attributeid #1\endcsname} - -\aliased\let\dompattribute\gobbletwoarguments - -\permanent\protected\def\resetglobalattributes{\the\t_attr_list_global\glyphdatafield\zerocount\glyphscriptfield\zerocount} -\permanent\protected\def\resetlocalattributes {\the\t_attr_list_local \glyphdatafield\zerocount\glyphscriptfield\zerocount} - -\aliased\let\resetallattributes\resetlocalattributes - -%D Rather special. - -\permanent\protected\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}} -\permanent\protected\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}} - -%D For the moment we put this here. The order of definition matters a bit because -%D performance is better when we put frequently accessed attributes at the front. -%D So, we might move more here. - -%definesystemattribute [state] % nomath -\definesystemattribute [color] [public] % global -\definesystemattribute [colormodel] [public,global] -%definesystemattribute [skip] -%definesystemattribute [penalty] -\definesystemattribute [transparency] [public] -\definesystemattribute [reference] [public] -\definesystemattribute [destination] [public] -\definesystemattribute [case] [public] -\definesystemattribute [visual] [public,global] -\definesystemattribute [viewerlayer] [public] -\definesystemattribute [background] [public] -\definesystemattribute [alignbackground] [public] -\definesystemattribute [colorintent] [public] -\definesystemattribute [negative] [public] -\definesystemattribute [effect] [public] -\definesystemattribute [layoutcomponent] [public] -\definesystemattribute [internal] [public] -\definesystemattribute [ruled] [public] -\definesystemattribute [shifted] [public] -\definesystemattribute [checkedbreak] [public] -\definesystemattribute [vboxtohboxseparator] [public] - -\permanent\protected\let\showattributes\clf_showattributes % maybe at lua end - -%D Todo: - -% \appendtoks -% \clf_cleanupattributes -% \to \everyafterpagebreak - -\protect \endinput diff --git a/tex/context/base/mkiv/attr-lay.lmt b/tex/context/base/mkiv/attr-lay.lmt deleted file mode 100644 index d0febb9ee..000000000 --- a/tex/context/base/mkiv/attr-lay.lmt +++ /dev/null @@ -1,311 +0,0 @@ -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 enableaction = nodes.tasks.enableaction -local disableaction = nodes.tasks.disableaction -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 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 - disableaction("shipouts","attributes.viewerlayers.handler") - end - enabled = false - else - if not enabled then - 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 - -- or macro - 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", - public = true, - protected = true, - actions = viewerlayers.start, - arguments = "optional", -} - -implement { - name = "stopviewerlayer", - public = true, - protected = true, - actions = viewerlayers.stop -} - -implement { - name = "registeredviewerlayer", - actions = { register, context }, - arguments = { "string", true } -- true forces a use -} diff --git a/tex/context/base/mkiv/attr-lay.mkxl b/tex/context/base/mkiv/attr-lay.mkxl deleted file mode 100644 index 4e8a56eba..000000000 --- a/tex/context/base/mkiv/attr-lay.mkxl +++ /dev/null @@ -1,105 +0,0 @@ -%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}{autosuffix} - -% 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 - {\frozen\instance\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}% - \frozen\instance\setuxvalue{\e!stop #1}{\stopviewerlayer}}% -\to \everydefineviewerlayer - -% \startviewerlayer[#1] % defined at lua end -% \stopviewerlayer % defined at lua end - -\permanent\protected\def\viewerlayer[#1]% - {\groupedcommand{\startviewerlayer[#1]}{\stopviewerlayer}} - -% 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} - -\permanent\def\attr_layoutcomponent_initialize#1% - {\edef\layoutcomponentboxattribute{\clf_definedlayoutcomponent{#1}}% - \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}% - \global\letcsname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute} - -\permanent\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} - -\permanent\def\attr_layoutcomponent_reset - {\let\layoutcomponentboxattribute\empty} - -\permanent\let\setlayoutcomponentattribute \gobbleoneargument -\permanent\let\resetlayoutcomponentattribute\relax - \let\layoutcomponentboxattribute \empty - -\protected\def\showlayoutcomponents - {\enforced\let\setlayoutcomponentattribute \attr_layoutcomponent_set - \enforced\let\resetlayoutcomponentattribute\attr_layoutcomponent_reset} - -\protected\def\attr_layoutcomponent_cleanup - {\clf_cleanuplayers} - -\appendtoks - \attr_layoutcomponent_cleanup -\to \everyshipout - -\protect \endinput diff --git a/tex/context/base/mkiv/attr-mkr.mkxl b/tex/context/base/mkiv/attr-mkr.mkxl deleted file mode 100644 index 2209af241..000000000 --- a/tex/context/base/mkiv/attr-mkr.mkxl +++ /dev/null @@ -1,25 +0,0 @@ -%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}{} - -\permanent \protected\def\definemarker [#1]{\defineattribute[\s!marker:#1]} -\permanent\tolerant\protected\def\setmarker [#1]#*[#2]{\dosetattribute{\s!marker:#1}{#2}} -\permanent \protected\def\resetmarker [#1]{\dogetattribute{\s!marker:#1}} -\permanent \def\boxmarker #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax} - -\protect \endinput diff --git a/tex/context/base/mkiv/attr-neg.mkxl b/tex/context/base/mkiv/attr-neg.mkxl deleted file mode 100644 index c849e6bf6..000000000 --- a/tex/context/base/mkiv/attr-neg.mkxl +++ /dev/null @@ -1,28 +0,0 @@ -%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}{} - -\unprotect - -% positive and negative are preregistered - -\permanent\protected\def\startnegative{\clf_setnegative{\v!negative}} -\permanent\protected\def\stopnegative {\clf_setnegative{\v!positive}} - -\permanent\protected\def\startpositive{\clf_setnegative{\v!positive}} -\permanent\protected\def\stoppositive {\clf_setnegative{\v!negative}} - -\protect \endinput diff --git a/tex/context/base/mkiv/back-exp.mkxl b/tex/context/base/mkiv/back-exp.mkxl deleted file mode 100644 index f248ca214..000000000 --- a/tex/context/base/mkiv/back-exp.mkxl +++ /dev/null @@ -1,356 +0,0 @@ -%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}{} - -%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 because otherwise rendering information would get lost. In -%D general we assume that when the \XML\ is converted to \HTML\ some stylesheet -%D is applied anyway. - -\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] - -\permanent\tolerant\protected\def\setelementexporttag[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \clf_settagproperty{#1}{export}{#2}% - \or - \clf_settagproperty{#1}{#2}{#3}% - \fi} - -% todo: no need for calls when trialtypesetting - -\permanent\def\taggedctxcommand - {\iftrialtypesetting - \expandafter\gobbleoneargument - \else - \expandafter\ctxcommand - \fi} - -\newcount\tagparcounter - -\aliased\let\dotagsetparcounter\relax -\aliased\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 - \enforced\permanent\protected\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) - \enforced\permanent\protected\def\dotagTABLEsignal - {\signalcharacter}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagtabulatecell - {\iftrialtypesetting\else - \clf_settagtabulatecell\c_tabl_tabulate_align\c_tabl_tabulate_kind - \fi}% - \enforced\permanent\protected\def\dotagtabulatesignal - {\dontleavehmode\signalcharacter\ignorespaces}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsynonym - {\iftrialtypesetting\else\clf_settagsynonym{\currentsynonymtag}\fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsorting - {\iftrialtypesetting\else\clf_settagsorting{\currentsortingtag}\fi}% -\to \everyenableelements - -\appendtoks % frozen and assumed global per highlight class - \enforced\permanent\protected\def\dotagconstruct - {\iftrialtypesetting\else - \clf_settagconstruct - {\currentstartstop}% - {\startstopparameter\c!style}% - \c_attr_color - \ifvmode\plusone\else\zerocount\fi - \relax - \fi}% -\to \everyenableelements - -\appendtoks % frozen and assumed global per highlight class - \enforced\permanent\protected\def\dotaghighlight - {\iftrialtypesetting\else - \clf_settaghighlight - {\currenthighlight}% - {\highlightparameter\c!style} - \c_attr_color - \ifvmode\plusone\else\zerocount\fi - \relax - \fi}% -\to \everyenableelements - -\appendtoks % we can have differently scaled images - \enforced\permanent\protected\def\dotagfigure - {\iftrialtypesetting\else - \clf_settagfigure - {\figurefileoriginal}% - {\figurefullname}% - {\figurefilepage}% - \dimexpr\figurewidth\relax - \dimexpr\figureheight\relax - {\figurelabel}% - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagcombination - {\iftrialtypesetting\else - \clf_settagcombination - \numexpr\combinationparameter\c!nx\relax - \numexpr\combinationparameter\c!ny\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetparcounter - {\global\advance\tagparcounter\plusone\c_attr_taggedpar\tagparcounter}% - \enforced\permanent\protected\def\doresetparcounter - {\c_attr_taggedpar\attributeunsetvalue}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetitemgroup - {\iftrialtypesetting\else - \clf_settagitemgroup - \ifconditional\c_strc_itemgroups_pack true\else false\fi\space - \numexpr\currentitemlevel\relax - {\currentitemgroupsymbol}% - \fi}% - \enforced\permanent\protected\def\dotagsetitem#1% - {\iftrialtypesetting\else - \clf_settagitem{#1}% - \fi}% -\to \everyenableelements - -% \appendtoks -% \enforced\permanent\protected\def\dotagsetdescription -% {\iftrialtypesetting\else -% \clf_settagdescription{\currentdescription}\currentdescriptionnumberentry\relax -% \fi}% -% \to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetnotation - {\iftrialtypesetting\else - \clf_settagnotation{\currentnote}\currentnotenumber\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetnotesymbol - {\iftrialtypesetting\else - \clf_settagnotationsymbol{\currentnote}\currentnotenumber\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagregisterlocation - {\iftrialtypesetting\else - \clf_settagregister{\currentregister}\currentregisternumber\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotaglistlocation - {\iftrialtypesetting\else - \clf_settaglist\currentlistindex\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetdelimitedsymbol#1% - {\iftrialtypesetting\else - \clf_settagdelimitedsymbol{#1}\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagsetsubsentencesymbol#1% - {\iftrialtypesetting\else - \clf_settagsubsentencesymbol{#1}\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagregisterfloat#1#2% - {\iftrialtypesetting\else - \clf_settagfloat{#1}{#2}\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\let\specialfixedspace \explicitfixedspace - \enforced\let\specialobeyedspace \explicitobeyedspace - \enforced\let\specialstretchedspace\explicitstretchedspace - \enforced\let\specialcontrolspace \explicitcontrolspace -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagregisterformula#1% - {\iftrialtypesetting\else - \clf_settagformulacontent#1\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagmarginanchor#1% - {\iftrialtypesetting\else\clf_settagmarginanchor#1\relax\fi}% - \enforced\permanent\protected\def\dotagmargintext#1% - {\iftrialtypesetting\else\clf_settagmargintext#1\relax\fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagpublication#1#2% - {\iftrialtypesetting\else - \clf_settagpublication{#1}{#2}\relax - \fi}% -\to \everyenableelements - -\appendtoks - \enforced\permanent\protected\def\dotagparagraph#1% - {\iftrialtypesetting\else - \clf_settagparagraph{#1}\relax - \fi}% -\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!properties=\v!no, % no: ignore, yes: as attribute, otherwise: use as prefix - \c!hyphen=\v!no, - \c!svgstyle=, - \c!cssfile=, - \c!file=] - -\resetsystemmode\v!export - -\permanent\protected\def\doinitializeexport - {\edef\p_export{\backendparameter\c!export}% - \ifx\p_export\empty \else - % yes | xml - \setuptagging[\c!state=\v!start]% - \clf_initializeexport - \setsystemmode\v!export - \exportingtrue - \writestatus\m!backend\empty % so messages will stand out a bit - \the\everyinitializeexport - \writestatus\m!backend\empty % so messages will stand out a bit - \enforced\glet\doinitializeexport\relax - \fi} - -\permanent\protected\def\dostartexport - {%\glet\dostartexport\relax - \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}% - file {\exportparameter\c!file}% - export {\backendparameter\c!export}% - \relax} - -\permanent\protected\def\dostopexport - {\enforced\glet\dostopexport\relax - \clf_finishexport} - -\appendtoks - \doinitializeexport -\to \everysetupbackend - -\appendtoks - \ifexporting - \dostartexport - \fi -\to \everystarttext - -% better (before pdf gets closed, so we can embed), but it needs testing: - -\appendtoks - \ifexporting - \dostopexport - \fi -\to \everystoptext - -\appendtoks - \ifexporting - \dostartexport % in case it is done inside \starttext - \fi -\to \everystartdocument - -\protect \endinput diff --git a/tex/context/base/mkiv/back-ini.mkxl b/tex/context/base/mkiv/back-ini.mkxl deleted file mode 100644 index 00bfeb188..000000000 --- a/tex/context/base/mkiv/back-ini.mkxl +++ /dev/null @@ -1,80 +0,0 @@ -%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. - -\writestatus{loading}{ConTeXt Backend Macros / Initialization} - -\registerctxluafile{back-ini}{} - -\unprotect - -%D Right from the start \CONTEXT\ had a backend system based on runtime pluggable -%D code. As most backend issues involved specials and since postprocessors had not -%D that much in common, we ended up with a system where we could switch backend as -%D well as output code for multiple backends at the same time. -%D -%D Because \LUATEX\ has the backend built in, and since some backend issues have -%D been moved to the frontend I decided to provide new backend code for \MKIV, -%D starting with what was actually used. -%D -%D At this moment \DVI\ is no longer used for advanced document output and we -%D therefore dropped support for this format. Future versions might support more -%D backends again, but this has a low priority. - -%D The exact page model depends on the backend so we just define some variables that -%D are used. A helper at the \LUA\ end will synchronize with the internal variables. -%D We store these in the format. - -\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi -\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi -\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi - -\installcorenamespace{backend} - -\installsetuponlycommandhandler \??backend {backend} - -%D \starttyping -%D \setupbackend[space=yes] -%D \stoptyping - -\appendtoks - \clf_setrealspaces{\backendparameter\c!space}% -\to \everysetupbackend - -\appendtoks - \ifdefined\clf_resetmapfile - \clf_resetmapfile - \fi -\to \everysetupbackend - -%D For the moment this is an experiment (defauls is pdf, but we also -%D have lua, json and mps). -%D -%D \starttyping -%D % \setupoutput[lua] -%D % \setupoutput[json] -%D % \setupoutput[mps] -%D % \setupoutput[none] % for testing only -%D % \setupoutput[empty] % for testing only -%D -%D \starttext -%D \dorecurse{1000}{ -%D {\tf \red \samplefile{tufte}} \par -%D {\bf \green \samplefile {ward}} \par -%D {\sl \blue \samplefile{davis}} \par -%D } -%D \stoptext -%D \stoptyping - -\permanent\protected\def\setupoutput[#1]{\clf_enabledriver{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/back-lua.lmt b/tex/context/base/mkiv/back-lua.lmt deleted file mode 100644 index dc836f12b..000000000 --- a/tex/context/base/mkiv/back-lua.lmt +++ /dev/null @@ -1,366 +0,0 @@ -if not modules then modules = { } end modules ['back-lua'] = { - version = 1.001, - optimize = true, - 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" -} - --- we can remap fonts - -local fontproperties = fonts.hashes.properties -local fontparameters = fonts.hashes.parameters -local fontshapes = fonts.hashes.shapes - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local bpfactor = number.dimenfactors.bp -local texgetbox = tex.getbox - -local rulecodes = nodes.rulecodes -local normalrule_code = rulecodes.normal ------ boxrule_code = rulecodes.box ------ imagerule_code = rulecodes.image ------ emptyrule_code = rulecodes.empty ------ userrule_code = rulecodes.user ------ overrule_code = rulecodes.over ------ underrule_code = rulecodes.under ------ fractionrule_code = rulecodes.fraction ------ radicalrule_code = rulecodes.radical -local outlinerule_code = rulecodes.outline - --- todo : per instance - -local pages = { } -local fonts = { } -local names = { } -local mapping = { } -local used = { } -local shapes = { } -local glyphs = { } -local buffer = { } -local b = 0 -local converter = nil - -local compact = false -- true -local shapestoo = true - -local x, y, d, f, c, w, h, t, r, o - -local function reset() - buffer = { } - b = 0 - t = nil - x = nil - y = nil - d = nil - f = nil - c = nil - w = nil - h = nil - r = nil - o = nil -end - -local function result() - -- todo: we're now still in the pdf backend but need different codeinjections - local codeinjections = backends.pdf.codeinjections - local getvariable = codeinjections.getidentityvariable or function() end - local jobname = environment.jobname or tex.jobname or "unknown" - return { - metadata = { - unit = "bp", - jobname = jobname, - title = getvariable("title") or jobname, - subject = getvariable("subject"), - author = getvariable("author"), - keywords = getvariable("keywords"), - time = os.date("%Y-%m-%d %H:%M"), - engine = environment.luatexengine .. " " .. environment.luatexversion, - context = environment.version, - }, - fonts = fonts, - pages = pages, - shapes = shapes, - } -end - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.lua" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - io.savedata(filename,table.serialize(data)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - -local function initialize(driver,details) - reset() -end - -local function finalize(driver,details) - local n = details.pagenumber - local b = details.boundingbox - pages[n] = { - number = n, - content = buffer, - boundingbox = { - b[1] * bpfactor, - b[2] * bpfactor, - b[3] * bpfactor, - b[4] * bpfactor, - }, - } -end - -local function wrapup(driver) -end - -local function cleanup(driver) - reset() -end - -local function convert(driver,boxnumber,pagenumber) - converter(driver,texgetbox(boxnumber),"page",pagenumber) -end - --- flushers - -local function updatefontstate(id) - if not mapping[id] then - local fn = #fonts + 1 - mapping[id] = fn - local properties = fontproperties[id] - local parameters = fontparameters[id] - local filename = file.basename(properties.filename) - local fontname = properties.fullname or properties.fontname - if shapestoo then - if not names[fontname] then - local sn = #shapes+1 - names[fontname] = sn - shapes[sn] = { } - glyphs[sn] = fontshapes[id].glyphs - end - end - fonts[fn] = { - filename = filename, - name = fontname, - size = parameters.size * bpfactor, - shapes = shapestoo and names[fontname] or nil, - } - end -end - -local function flushcharacter(current, pos_h, pos_v, pos_r, font, char) - local fnt = mapping[font] - b = b + 1 - buffer[b] = { - t = "glyph" ~= t and "glyph" or nil, - f = font ~= f and fnt or nil, - c = char ~= c and char or nil, - x = pos_h ~= x and (pos_h * bpfactor) or nil, - y = pos_v ~= y and (pos_v * bpfactor) or nil, - d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, - } - t = "glyph" - f = font - c = char - x = pos_h - y = pos_v - d = pos_r - if shapestoo then - -- can be sped up if needed - local sn = fonts[fnt].shapes - local shp = shapes[sn] - if not shp[char] then - shp[char] = glyphs[sn][char] - end - end -end - -local function rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) - b = b + 1 - buffer[b] = { - t = "rule" ~= t and "rule" or nil, - r = rule_s ~= r and rule_s or nil, - o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil, - w = size_h ~= w and (size_h * bpfactor) or nil, - h = size_v ~= h and (size_v * bpfactor) or nil, - x = pos_h ~= x and (pos_h * bpfactor) or nil, - y = pos_v ~= y and (pos_v * bpfactor) or nil, - d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, - } - t = "rule" - w = size_h - h = size_v - x = pos_h - y = pos_v - d = pos_r -end - -local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype) - local rule_s, rule_o - if subtype == normalrule_code then - rule_s = "normal" - elseif subtype == outlinerule_code then - rule_s = "outline" - rule_o = getdata(current) - else - return - end - return rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) -end - -local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v) - return rule(pos_h, pos_v, pos_r, size_h, size_v, "normal", nil) -end - -local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline) - -- no l support yet - return rule(pos_h, pos_v - d, pos_r, w, h + d, outline and "outline" or "normal") -end - --- file stuff too --- todo: default flushers --- also color (via hash) - --- installer - -drivers.install { - name = "lua", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - } -} - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.json" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - if not utilities.json then - require("util-jsn") - end - io.savedata(filename,utilities.json.tostring(data,not compact)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - --- installer - -drivers.install { - name = "json", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - } -} - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.js" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - if not utilities.json then - require("util-jsn") - end - io.savedata(filename, - "const JSON_CONTEXT = JSON.parse ( `" .. - utilities.json.tostring(data,not compact) .. - "` ) ;\n" - ) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - --- installer - -drivers.install { - name = "js", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - } -} diff --git a/tex/context/base/mkiv/back-lua.mkxl b/tex/context/base/mkiv/back-lua.mkxl deleted file mode 100644 index 0fb1bcc88..000000000 --- a/tex/context/base/mkiv/back-lua.mkxl +++ /dev/null @@ -1,16 +0,0 @@ -%D \module -%D [ file=back-lua, -%D version=2018.07.26, -%D title=\CONTEXT\ Backend 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{back-lua}{autosuffix,optimize} - -\endinput diff --git a/tex/context/base/mkiv/back-mps.lmt b/tex/context/base/mkiv/back-mps.lmt deleted file mode 100644 index 4a2a573c4..000000000 --- a/tex/context/base/mkiv/back-mps.lmt +++ /dev/null @@ -1,210 +0,0 @@ -if not modules then modules = { } end modules ['back-mps'] = { - version = 1.001, - optimize = true, - 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 fontproperties = fonts.hashes.properties -local fontparameters = fonts.hashes.parameters - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local bpfactor = number.dimenfactors.bp -local texgetbox = tex.getbox -local formatters = string.formatters - -local rulecodes = nodes.rulecodes -local normalrule_code = rulecodes.normal ------ boxrule_code = rulecodes.box ------ imagerule_code = rulecodes.image ------ emptyrule_code = rulecodes.empty ------ userrule_code = rulecodes.user ------ overrule_code = rulecodes.over ------ underrule_code = rulecodes.under ------ fractionrule_code = rulecodes.fraction ------ radicalrule_code = rulecodes.radical -local outlinerule_code = rulecodes.outline - -local fonts = { } -local pages = { } -local buffer = { } -local b = 0 -local converter = nil - -local function reset() - buffer = { } - b = 0 -end - -local f_font = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ] - -local f_glyph = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ] -local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] -local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.tex" -end - -local function save() -- might become a driver function that already is plugged into stopactions - starttiming(drivers) - if #pages > 0 then - local filename = outputfilename() - drivers.report("saving result in %a",filename) - reset() - b = b + 1 - buffer[b] = "\\starttext\n" - for k, v in table.sortedhash(fonts) do - b = b + 1 - buffer[b] = f_font(v.name,v.filename,v.size) - end - for i=1,#pages do - b = b + 1 - buffer[b] = pages[i] - end - b = b + 1 - buffer[b] = "\\stoptext\n" - io.savedata(filename,table.concat(buffer,"",1,b)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - -local function initialize(driver,details) - reset() - b = b + 1 - buffer[b] = "\n\\startMPpage" -end - -local function finalize(driver,details) - b = b + 1 - buffer[b] = "\\stopMPpage\n" - pages[details.pagenumber] = table.concat(buffer,"\n",1,b) -end - -local function wrapup(driver) -end - -local function cleanup(driver) - reset() -end - -local function convert(driver,boxnumber,pagenumber) - converter(driver,texgetbox(boxnumber),"page",pagenumber) -end - --- flushers - -local last - -local function updatefontstate(id) - if fonts[id] then - last = fonts[id].name - else - last = "MPSfont" .. converters.Characters(id) - fonts[id] = { - filename = file.basename(fontproperties[id].filename), - size = fontparameters[id].size * bpfactor, - name = last, - } - end -end - -local function flushcharacter(current, pos_h, pos_v, pod_r, font, char) - b = b + 1 - buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor) -end - -local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v, subtype) - if subtype == normalrule_code then - b = b + 1 - buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) - elseif subtype == outlinerule_code then - b = b + 1 - buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) - end -end - -local function flushsimplerule(pos_h, pos_v, pod_r, size_h, size_v) - flush_rule(false,pos_h,pos_v,pod_r,size_h,size_v,normalrule_code) -end - -local function flushspecialrule(pos_h, pos_v, pod_r, w, h, d, l, outline) - flush_rule(false,pos_h,pos_v-d,pod_r,w,h+d,outline and outlinerule_code or normalrule_code) -end - --- installer - -drivers.install { - name = "mps", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - } -} - --- extras - --- if not mp then --- return --- end --- --- local mpprint = mp.print --- local formatters = string.formatters --- --- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ] --- local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] --- --- local current = nil --- local size = 0 --- --- function mp.place_buffermake(box) --- drivers.convert("mps",box) --- current = drivers.action("mps","fetch") --- size = #current --- end --- --- function mp.place_buffersize() --- mpprint(size) --- end --- --- function mp.place_bufferslot(i) --- if i > 0 and i <= size then --- local b = buffer[i] --- local t = b[1] --- if t == "glyph" then --- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor)) --- elseif t == "rule" then --- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor)) --- end --- end --- end --- --- function mp.place_bufferwipe() --- current = nil --- size = 0 --- end diff --git a/tex/context/base/mkiv/back-mps.mkxl b/tex/context/base/mkiv/back-mps.mkxl deleted file mode 100644 index d4d428d42..000000000 --- a/tex/context/base/mkiv/back-mps.mkxl +++ /dev/null @@ -1,16 +0,0 @@ -%D \module -%D [ file=back-mps, -%D version=2018.07.26, -%D title=\CONTEXT\ Backend 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{back-mps}{autosuffix,optimize} - -\endinput diff --git a/tex/context/base/mkiv/back-out.lmt b/tex/context/base/mkiv/back-out.lmt deleted file mode 100644 index 1f33da557..000000000 --- a/tex/context/base/mkiv/back-out.lmt +++ /dev/null @@ -1,255 +0,0 @@ -if not modules then modules = { } end modules ['back-out'] = { - 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" -} - -local type = type -local loadstring = loadstring - -local context = context - --- tokens.scanners..... - -local get = token.get_index -local scanners = tokens.scanners -local scaninteger = scanners.integer -local scanstring = scanners.string -local scankeyword = scanners.keyword -local scantokenlist = scanners.tokenlist - -local serialize = token.serialize - -local logwriter = logs.writer -local openfile = io.open -local flushio = io.flush - -local nuts = nodes.nuts -local tonode = nuts.tonode -local copynode = nuts.copy -local nodepool = nuts.pool - -local getdata = nuts.getdata - -local whatsit_code = nodes.nodecodes.whatsit - -local whatsitcodes = nodes.whatsitcodes - -local literalvalues = nodes.literalvalues -local originliteral_code = literalvalues.origin -local pageliteral_code = literalvalues.page -local directliteral_code = literalvalues.direct -local rawliteral_code = literalvalues.raw - -local immediate_code = tex.flagcodes.immediate - -local nodeproperties = nodes.properties.data - -local channels = { } - -local register = nodepool.register -local newnut = nuts.new - -local opennode = register(newnut(whatsit_code,whatsitcodes.open)) -local writenode = register(newnut(whatsit_code,whatsitcodes.write)) -local closenode = register(newnut(whatsit_code,whatsitcodes.close)) -local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua)) -local literalnode = register(newnut(whatsit_code,whatsitcodes.literal)) -local savenode = register(newnut(whatsit_code,whatsitcodes.save)) -local restorenode = register(newnut(whatsit_code,whatsitcodes.restore)) -local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix)) - -local tomatrix = drivers.helpers.tomatrix - -local open_command, write_command, close_command - -backends = backends or { } - -local function immediately(prefix) - return prefix and (prefix & immediate_code) ~= 0 -end - -local function openout(prefix) - local channel = scaninteger() - scankeyword("=") -- hack - local filename = scanstring() - if not immediately(prefix) then - local n = copynode(opennode) - nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" - return context(tonode(n)) - elseif not channels[channel] then - local handle = openfile(filename,"wb") or false - if handle then - channels[channel] = handle - else - -- error - end - end -end - -function backends.openout(n) - local p = nodeproperties[n] - if p then - local handle = openfile(p.filename,"wb") or false - if handle then - channels[p.channel] = handle - else - -- error - end - end -end - -local function write(prefix) - local channel = scaninteger() - if not immediately(prefix) then - local t = scantokenlist() - local n = copynode(writenode) - nodeproperties[n] = { channel = channel, data = t } -- action = "write" - return context(tonode(n)) - else - local content = scanstring() - local handle = channels[channel] - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end -end - -function backends.writeout(n) - local p = nodeproperties[n] - if p then - local handle = channels[p.channel] - local content = serialize(p.data) - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end -end - -local function closeout(prefix) - local channel = scaninteger() - if not immediately(prefix) then - local n = copynode(closenode) - nodeproperties[n] = { channel = channel } -- action = "close" - return context(tonode(n)) - else - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end -end - -function backends.closeout(n) - local p = nodeproperties[n] - if p then - local channel = p.channel - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end -end - -local noflatelua = 0 - -local function latelua() - local node = copynode(lateluanode) - local name = "latelua" - if scankeyword("name") then - name = scanstring() - end - local data = scantokenlist() - nodeproperties[node] = { name = name, data = data } - return context(tonode(node)) -end - -function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) - local p = nodeproperties[current] - if p then - data = p.data - else - data = getdata(current) - end - noflatelua = noflatelua + 1 - local kind = type(data) - if kind == "table" then - data.action(data.specification or data) - elseif kind == "function" then - data() - else - if kind ~= "string" then - data = serialize(data) - end - if #data ~= "" then - local code = loadstring(data) - if code then - code() - end - end - end -end - -function backends.getcallbackstate() - return { count = noflatelua } -end - -function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end -function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end -function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end -function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end - -local pdfliterals = { - [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, - [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, - [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, - [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, -} - -function nodepool.literal(mode,str) - local t = copynode(literalnode) - if str then - nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } - else - nodeproperties[t] = { data = mode, mode = pageliteral_code } - end - return t -end - -function nodepool.save() - return copynode(savenode) -end - -function nodepool.restore() - return copynode(restorenode) -end - -function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) - local t = copynode(setmatrixnode) - nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) } - return t -end - -interfaces.implement { name = "openout", actions = openout, public = true, usage = "value" } -interfaces.implement { name = "write", actions = write, public = true, usage = "value" } -interfaces.implement { name = "closeout", actions = closeout, public = true, usage = "value" } -interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true } -interfaces.implement { name = "special", actions = scanstring, public = true, protected = true } - -open_command = get(token.create("openout")) -write_command = get(token.create("write")) -close_command = get(token.create("closeout")) diff --git a/tex/context/base/mkiv/back-out.mkxl b/tex/context/base/mkiv/back-out.mkxl deleted file mode 100644 index 5cf79b2ea..000000000 --- a/tex/context/base/mkiv/back-out.mkxl +++ /dev/null @@ -1,22 +0,0 @@ -%D \module -%D [ file=back-out, -%D version=2019.02.08, -%D title=\CONTEXT\ Backend Macros, -%D subtitle=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. - -\registerctxluafile{back-out}{autosuffix} - -% \let\normalopenout \openout -% \let\normalwrite \write -% \let\normalcloseout\closeout -% \let\normallatelua \latelua -% \let\normalspecial \special - -\endinput diff --git a/tex/context/base/mkiv/back-pdf.mkxl b/tex/context/base/mkiv/back-pdf.mkxl deleted file mode 100644 index c28352c92..000000000 --- a/tex/context/base/mkiv/back-pdf.mkxl +++ /dev/null @@ -1,157 +0,0 @@ -%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. - -%D The less there is here, the better. After a decade it is time to remove the \type -%D {\pdf*} ones completely. For the moment I keep them commented but even that will -%D go away. - -\writestatus{loading}{ConTeXt Backend Macros / PDF} - -\registerctxluafile{lpdf-ini}{optimize} -\registerctxluafile{lpdf-lmt}{autosuffix,optimize} -\registerctxluafile{lpdf-col}{} -\registerctxluafile{lpdf-vfc}{autosuffix} -\registerctxluafile{lpdf-xmp}{} -\registerctxluafile{lpdf-ano}{} -\registerctxluafile{lpdf-res}{} -\registerctxluafile{lpdf-mis}{} -\registerctxluafile{lpdf-ren}{} -\registerctxluafile{lpdf-grp}{} -\registerctxluafile{lpdf-wid}{} -\registerctxluafile{lpdf-fld}{} -\registerctxluafile{lpdf-mov}{} -\registerctxluafile{lpdf-u3d}{} % this will become a module -\registerctxluafile{lpdf-swf}{} % this will become a module -\registerctxluafile{lpdf-tag}{} -\registerctxluafile{lpdf-fmt}{} -\registerctxluafile{lpdf-pde}{} -\registerctxluafile{lpdf-img}{autosuffix,optimize} -\registerctxluafile{lpdf-epa}{} -\registerctxluafile{lpdf-emb}{autosuffix,optimize} -\registerctxluafile{lpdf-fnt}{} - -\registerctxluafile{back-pdp}{} -\registerctxluafile{back-pdf}{} % some code will move to lpdf-* - -\loadmarkfile{back-u3d} % this will become a module -\loadmarkfile{back-swf} % this will become a module - -\unprotect - -%D We will minimize the number of calls to \PDF\ specific primitives and delegate -%D all management and injection of code to the backend. -%D -%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. - -\permanent\protected\def\pdfextension{\clf_pdfextension} -\permanent \def\pdffeedback {\clf_pdffeedback} -\permanent \def\pdfvariable {\clf_pdfvariable} - -%D For the moment we keep this for tikz but hopefully it will at some point use -%D the proper ones. Consider them obsolete: - -\permanent\protected\def\pdfliteral {\clf_pdfliteral} -\permanent\protected\def\pdfobj {\clf_pdfobj}% -\permanent\protected\def\pdflastobj {\numexpr\clf_pdflastobj\relax} -\permanent\protected\def\pdfrefobj {\clf_pdfrefobj} - -\permanent\protected\def\pdfrestore {\pdfextension restore} -\permanent\protected\def\pdfsave {\pdfextension save} -\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix} - -\permanent\let\pdfxform \saveboxresource -\permanent\let\pdflastxform\lastsavedboxresourceindex -\permanent\let\pdfrefxform \useboxresource - -%D Here are quick and dirty compression flippers, mostly used when testing something -%D as one can best stick to the defaults that also adapt to specific standards. - -\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} -\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} -\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } -\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} - -%D PDF/X (maybe combine the two lua calls) - -\setupbackend - [xmpfile=] - -\appendtoks - \edef\p_file{\backendparameter{xmpfile}}% - \ifempty\p_file\else - \clf_setxmpfile{\p_file}% - \fi -\to \everysetupbackend - -%D This will change: - -\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 These are the only official methods to add stuff to the resources. If more is -%D needed for third party low level code, it can be added. - -\permanent\protected\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} -\permanent\protected\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} -\permanent\protected\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} - -\permanent\protected\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} -\permanent\protected\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} -\permanent\protected\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} - -\permanent\protected\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} -\permanent\protected\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} -\permanent\protected\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} -\permanent\protected\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} - -\permanent \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} -\permanent \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} - -%D This is a temporary hack mthat will be removed, improved or somehow can become -%D default. - -\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} - -%D Just in case one needs this \unknown: -%D -%D \starttyping -%D text \pdfbackendactualtext{Meier}{Müller} text -%D \stoptyping - -\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced - {\clf_startactualtext{#2}% - #1% - \clf_stopactualtext} - -\let\pdfactualtext\pdfbackendactualtext - -%D Bah, this is also needed for tikz: - -\ifdefined\pdfsavepos\else - \permanent\let\pdfsavepos \savepos - \permanent\let\pdflastxpos\lastxpos - \permanent\let\pdflastypos\lastypos -\fi - -\protect \endinput diff --git a/tex/context/base/mkiv/back-res.mkxl b/tex/context/base/mkiv/back-res.mkxl deleted file mode 100644 index 52317b946..000000000 --- a/tex/context/base/mkiv/back-res.mkxl +++ /dev/null @@ -1,34 +0,0 @@ -%D \module -%D [ file=back-res, -%D version=2019.05.23, % 2009.04.15, -%D title=\CONTEXT\ Backend Macros, -%D subtitle=Resources, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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 / Resources} - -\registerctxluafile{back-res}{} - -\unprotect - -%D We overload the primitives with our own but use a bit of indirection for the -%D purpose of tracing. Some of these are needed for packages like tikz. - -% todo: public implementors (we can update the lua code anyway) - -\permanent\protected\def\saveboxresource {\clf_saveboxresource} -\permanent\protected\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax} -\permanent\protected\def\useboxresource {\clf_useboxresource} - -\permanent\protected\def\saveimageresource {\clf_saveimageresource} -\permanent\protected\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax} -\permanent\protected\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax} -\permanent\protected\def\useimageresource {\clf_useimageresource} - -\protect \endinput diff --git a/tex/context/base/mkiv/back-trf.mkxl b/tex/context/base/mkiv/back-trf.mkxl deleted file mode 100644 index 2eedcdd1c..000000000 --- a/tex/context/base/mkiv/back-trf.mkxl +++ /dev/null @@ -1,79 +0,0 @@ -%D \module -%D [ file=back-trf, -%D version=2019.02.08, % 2009.04.15, -%D title=\CONTEXT\ Backend 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. - -\unprotect - -\registerctxluafile{back-trf}{} - -% rotation - -\permanent\protected\def\dostartrotation#1% - {\forcecolorhack - \clf_startrotation#1\relax} % todo: implement without Q q - -\permanent\protected\def\dostoprotation - {\clf_stoprotation - \forcecolorhack} - -% scaling - -\permanent\protected\def\dostartscaling#1#2% - {\forcecolorhack - \clf_startscaling rx #1 ry #2\relax} - -\permanent\protected\def\dostopscaling - {\clf_stopscaling - \forcecolorhack} - -% mirroring - -\permanent\protected\def\dostartmirroring - {\clf_startmirroring} - -\permanent\protected\def\dostopmirroring - {\clf_stopmirroring} - -% transform - -\permanent\protected\def\dotransformnextbox#1#2#3#4#5#6% - {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} - -\permanent\protected\def\dodotransformnextbox#1#2#3#4#5#6% - {\hpack - {\kern #5\onebasepoint - \raise#6\onebasepoint - \hpack - {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax - \box\nextbox - \clf_stopmatrix}}} - -%D \macros -%D {dostartclipping,dostopclipping} -%D -%D Clipping is implemented in such a way that an arbitrary code can be fed. -%D -%D \starttyping -%D \dostartclipping {pathname} {width} {height} -%D \dostopclipping -%D \stoptyping - -\permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here - {\forcecolorhack - \meta_grab_clip_path{#1}{#2}{#3}% - \clf_startclipping{\MPclippath}% - \glet\MPclippath\empty} - -\permanent\protected\def\dostopclipping - {\clf_stopclipping} - -\protect \endinput diff --git a/tex/context/base/mkiv/bibl-bib.mkxl b/tex/context/base/mkiv/bibl-bib.mkxl deleted file mode 100644 index f8a8a7cd9..000000000 --- a/tex/context/base/mkiv/bibl-bib.mkxl +++ /dev/null @@ -1,982 +0,0 @@ -%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. - -%D This is really obsolete in \LMTX. For now I keep it but it will either go -%D away. The code is not upgraded, we only deal with macro protection. - -\writestatus{loading}{ConTeXt Bibliography Support / Experimental BibTeX} - -\registerctxluafile{bibl-bib}{} - -\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 some -%D motivation to spend time on it, and an occasional question on the list can be a -%D reason. A few examples. As \BIBTEX\ databases can be poluted by local commands, -%D 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 strip -%D 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 familiar with -%D \XML\ processing in \MKIV. -%D -%D Here we regular setups. Three elements are mapped but only one is actually used -%D 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 element -%D 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 - -\protected\def\definebibtexsession {\dosingleargument\dodefinebibtexsession} - \def\preparebibtexsession{\dodoubleempty \dopreparebibtexsession} -\protected\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]{\xmlprocess{bibtex:#1}{#2}{#2}} - -\protected\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] - -% \protected\def\startpublication#1\stoppublication -% {\blank -% todo -% \blank} - -% \let\stoppublication\relax - -\protected\def\bibtexspace {\removeunwantedspaces\space} -\protected\def\bibtexperiod {\removeunwantedspaces.\space} -\protected\def\bibtexcomma {\removeunwantedspaces,\space} -\protected\def\bibtexlparent {\removeunwantedspaces\space(} -\protected\def\bibtexrparent {\removeunwantedspaces)\space} -\protected\def\bibtexlbracket{\removeunwantedspaces\space[} -\protected\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 - -\protected\def\setupbibtexpublications - {\let\currentpublicationclass\??pb - \let\everysetupbibtexwhatever\everysetupbibtexpublications - \dodoubleargument\dosetupbibtexwhatever} - -\protected\def\setupbibtexcitations - {\let\currentpublicationclass\??pv - \let\everysetupbibtexwhatever\everysetupbibtexcitations - \dodoubleargument\dosetupbibtexwhatever} - -\protected\def\setupbibtexpublicationvariants - {\let\currentpublicationclass\??pb - \let\everysetupbibtexwhatever\everysetupbibtexpublications - \dotripleargument\dosetupbibtexwhatevervariant} - -\protected\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} -\protected\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} - -\protected\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 - -\protected\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 - -\protected\def\doifelsebibtexinteraction - {\iflocation - \edef\temp{\bibtexcitationparameter\c!interaction}% - \ifx\temp\v!stop - \doubleexpandafter\secondoftwoarguments - \else - \doubleexpandafter\firstoftwoarguments - \fi - \else - \expandafter\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 - -\protected\def\bibtexdataref {\dodoubleargument\dobibtexdataref} -\protected\def\bibtextyperef {\dodoubleargument\dobibtextyperef} -\protected\def\bibtexkeyref {\dodoubleargument\dobibtexkeyref} -\protected\def\bibtexserialref {\dodoubleargument\dobibtexserialref} -\protected\def\bibtexurlref {\dodoubleargument\dobibtexurlref} -\protected\def\bibtexdoiref {\dodoubleargument\dobibtexdoiref} -\protected\def\bibtexpageref {\dodoubleargument\dobibtexpageref} -\protected\def\bibtexnoneref {\dodoubleargument\dobibtexnoneref} -\protected\def\bibtexshortref {\dodoubleargument\dobibtexshortref} -\protected\def\bibtexyearref {\dodoubleargument\dobibtexyearref} -\protected\def\bibtexauthorref {\dodoubleargument\dobibtexauthorref} -\protected\def\bibtexauthoryearref {\dodoubleargument\dobibtexauthoryearref} -\protected\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")}} - -\protected\def\bibtexsingularplural#1#2{\ctxlua{bibtex.singularorplural(\!!bs#1\!!es,\!!bs#2\!!es)}} - -\protect \endinput - diff --git a/tex/context/base/mkiv/bibl-tra.mkxl b/tex/context/base/mkiv/bibl-tra.mkxl deleted file mode 100644 index c85a664ba..000000000 --- a/tex/context/base/mkiv/bibl-tra.mkxl +++ /dev/null @@ -1,1509 +0,0 @@ -%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. - -%D This is really obsolete in \LMTX. For now I keep it but it will either go -%D away. The code is not upgraded, we only deal with macro protection. - -% % % % 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, he is -%D to blame. The changes concern references and lists but teh rendering itself is -%D unchanged. Future versions might provide variants as we have plans for an -%D upgrade. -%D -%D We use a still somewhat experimental extension to the list mechanism. Eventually -%D the bibtex module will use the bibl loader and access the data by means of lpath -%D expressions. In that case we don't need to process the bibliography but still -%D need to track usage as done here. -%D -%D A bit ongoing: make more local macros prefixed with bib, i.e. the bib namespace -%D is reserved. - -%D Todo: commandhandler - -\writestatus{loading}{ConTeXt Bibliography Support / BibTeX} - -\definefilesynonym[bib][obsolete] - -\registerctxluafile{bibl-tra}{} - -%D The original was developed independantly by Taco Hoekwater while still working -%D for Kluwer Academic publishers (it still used the dutch interface then). -%D Development continued after he left Kluwer, and in Januari 2005, the then already -%D internationalized file was merged with the core distribution by Hans Hagen. The -%D 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{}} (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{}} -%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. - -\protected\def\bibdoifelse#1% - {\expandafter\def\expandafter\!!stringa\expandafter{#1}% - \ifx\!!stringa\empty - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\protected\def\bibdoifnot#1% - {\expandafter\def\expandafter\!!stringa\expandafter{#1}% - \ifx\!!stringa\empty - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\protected\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 around. The names of -%D the commands it parses as well as the \type {.aux} extension to the file name are -%D both hardwired. -%D -%D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk! The good -%D news is that it can be rather short. We'll just ask \BIBTEX\ to output the entire -%D database(s) into the \type {bbl} file. -%D -%D The \type {\bibstyle} command controls how the \type {bbl} file will be sorted. -%D 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 - -\protected\def\setupbibtex - {\dosingleempty\dosetupbibtex} - -\protected\def\dosetupbibtex[#1]% - {\let\@@pbdatabase\empty - \getparameters[\??pb][#1]% - \the\everysetupbibtex} - -\protected\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 - -\protected\def\setuppublications - {\dosingleargument\dosetuppublications} - -\protected\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 lists each time -%D (\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 - -\protected\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 because -%D similar numbers can be confusing. So, for the moment this is not supported in -%D \MKIV. (So no: see reference [3-5,9] in "some other document") - -\protected\def\usepublications[#1]% - {\processcommalist[#1]\dousepublications} - -\protected\def\dousepublications#1% - {\doonlyonce{#1.\f!bibextension}{\dodousepublications{#1}}} - -\protected\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} files. \quote -%D {samplesize} is a sample value (in case of \BIBTEX|-|generated files, this will -%D be the longest \quote {short} key). Here \quote {totalnumber} is the total number -%D of entries that will follow in this file. -%D -%D Both values are only needed for the label calculation if \quote {autohang} is -%D \quote {true}, so by default the command is not even needed, and therefore I saw -%D no need to give it it's own system variable and it just re-uses \type {pb}. - -\def\publicationlistparameter#1{\csname\??pv:l:#1\endcsname} - -\protected\def\setuppublicationlist - {\dosingleempty\dosetuppublicationlist} - -\protected\def\dosetuppublicationlist[#1]% - {\getparameters[\??pv:l:][#1]% - \setuplist[pubs][\c!samplesize={AA99},\c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1,\c!command=]} - -\protected\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 key in the weird -%D \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 use one argument -%D that is stored in \type {@@pb@#1}. -%D -%D \type {\simplebibdef} also defines \type {bibinsert#1}, which can be used in the -%D argument of \type {\setuppublicationlayout} to fetch one of the \type {@@pb@} -%D data entries. \type {bibinsert#1} then has three arguments: \type {#1} are -%D commands to be executed before the data, \type {#2} are commands to be executed -%D after the data, and \type {#3} are commands to be executed if the data is not -%D found. -%D -%D \type {\bibcommandlist} is the list of commands that is affected by this -%D approach. Later on, it will be used to do a series of assignments from \type {#1} -%D to \type {bib@#1}: e.g \type {\title} becomes \type {\bib@title} when used within -%D a publication. - -\newtoks\initializebibdefinitions % we need to prevent clashes - -\protected\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\protected\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 - -\protected\def\bibinsertdoi#1#2#3% let's see how this fails - {\bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}} - -\protected\def\bibinsertbiburl#1#2#3% let's see how this fails - {\bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}} - -\protected\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 - -\protected\def\newbibfield[#1]% - {\simplebibdef{#1}% - \edef\bibcommandlist{\bibcommandlist,#1}} - -%D \macros{complexbibdef,specialbibinsert} -%D -%D The commands \type {\artauthor}, \type {\author} and \type {\editor} are more -%D complex than the other commands. 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 these -%D commands. This is why a special command is needed to insert them, as well as one -%D 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 look far -%D more complex than it really is. For example, the argument \type {author} defines -%D the macro \type {\bib@author} to do two things: increment the counter \type -%D {\author@num} (let's say to 2) and next store it's arguments in the macro \type -%D {\@@pb@author2}. And it defines \type {\bibinsertauthors} to expand into -%D -%D \starttyping -%D \specialbibinsert{author}{\author@num}{}{}{} -%D \stoptyping - -\protected\def\docomplexbibdef#1% - {\dodoubleempty\dodocomplexbibdef[#1]} - -\protected\def\dodocomplexbibdef[#1][#2]#3% - {\doquadrupleempty\dododocomplexbibdef[#1][#2][#3]} - -\protected\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} - -\protected\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 typesetting of all of these -%D arguments. - -\newcount\etallimitcounter -\newcount\etaldisplaycounter -\newcount\todocounter - -\protected\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 output, with -%D proper regard of all the inbetween strings that can arise depending on length of -%D the list of people. - -%D \#1 = type -%D \#2 = number of items to be typeset -%D \#3 = commacommand containing authors - -\protected\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} - -\protected\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 as well define -%D some of these commands yourself. -%D -%D The argument list has been reordered here, and the meanings 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 - -\protected\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}} - -\protected\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}} - -\protected\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}} - -\protected\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 initializations and -%D cleanups. - -\protected\def\clearbibitem#1{\setvalue{\??pb @#1}{}}% - -\protected\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} - -\protected\def\bibitemdefs#1% - {\expandafter\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname} - -\protected\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 do typesetting and -%D read the \type {bbl} file. -%D -%D Just a \type {\dosingleempty} is the most friendly of doing this: there need not -%D even be an argument to \type {\startpublication}. Of course, then there is no key -%D either, and it had better be an article (otherwise the layout will be all screwed -%D up). -%D -%D Only specifying the key in the argument is also legal. In storing this stuff into -%D macros, some trickery with token registers is needed to fix the expansion -%D problems. Even so, 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 the primitive \type -%D {\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 - -\pushoverloadmode - -\overloaded \protected\def\startpublication - {\dosingleempty\dostartpublication} - -\overloaded\let\stoppublication\relax - -\popoverloadmode - -%D This is rather memory hungry; some day i will rewrite this so that we use the -%D database instead. - -%D \macros{doifbibreferencefoundelse} -%D -%D Some macros to fetch the information provided by \type {\startpublication}. -%D -%D We can consider a faster variant in the bbl file; we can also consider storing -%D 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 ... - -\protected\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} - -\protected\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 } - -\protected\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 entry. Because of -%D this special situation, it has to be defined separately. Since this command will -%D not be seen until at \type {\placepublications}, it may force extra runs. The -%D same is true for \type {\cite} commands inside of publications. - -% used in bib self - -\protected\def\bib@crossref#1% called via \csname \endcsname - {\setvalue{\??pb @crossref}{#1}\ignorespaces} - -\protected\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 publist sometimes -%D needs to fetch something from the current item (like the 'short' key). For this, -%D the ID of the current item is passed in the implict parameter \type -%D {\currentpublicationkey}. - -\protected\def\doprocessbibtexentry#1{\typesetapublication{#1}} - -\protected\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 - -\protected\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} - -%D The full list of publications - -\protected\def\completepublications - {\dosingleempty\docompletepublications} - -\protected\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:} - -\protected\def\placepublications - {\dosingleempty\doplacepublications} - -\protected\def\doplacepublications[#1]% - {\begingroup - \setuplist[pubs][#1]% - \dodoplacepublications - \endgroup} - -\protected\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 text when you want -%D text only. - -\protected\def\typesetapublication#1% - {\doifsomething{#1} - {\doifelse{\namedlistparameter{pubs}\c!criterium}\v!all - {\doplacepublicationindeed{#1}}% - {\ctxlua{bibtex.hacks.doifalreadyplaced("#1")} - {} - {\doplacepublicationindeed{#1}}}% - }} - -%D For the moment we don't access the data directly but we will do that later when -%D we get away from storing the data and only deal with references. - -% we'll define proper handlers later - -\protected\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 - -\protected\def\bibtexpubtext - {\expanded{\reference[\bibrefprefix\currentpublicationkey]{\number\bibtexcounter}}% - \strut\dotypesetapublication\currentpublicationkey\strut} - -\protected\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. - -\protected\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}} - -\protected\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 \type {\cite} -%D commands with a braced argument (these might appear in included data from the -%D \type {.bib} file). - -\pushoverloadmode - -\protected\def\cite - {\strictdoifelsenextoptional\dodocite\dobibref} - -\popoverloadmode - -\protected\def\dobibref#1% - {\docite[#1][]} - -\protected\def\dodocite[#1]% - {\strictdoifelsenextoptional{\docite[#1]}{\docite[#1][]}} - -\protected\def\docite[#1][#2]% - {\begingroup - \doifelsenothing{#2}\secondargumentfalse\secondargumenttrue - \ifsecondargument - \dowhatevercite{#1}{#2}% - \else - \donumberedcite{#1}% - \fi - \endgroup} - -\protected\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]} - -\protected\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} - -\pushoverloadmode - -\protected\def\nocite[#1]% - {\processcommalist[#1]\docitation} - -\popoverloadmode - -%D \macros{setupcite} - -\protected\def\setupcite{\dodoubleempty\dosetupcite} - -\protected\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 - -\protected\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} - -\protected\def\dofetchapublication#1% - {\def\currentpublicationkey{#1}% - \presetbibvariables - \ignorespaces\bibgetvard{#1}} - -\protected\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, the macros that deal -%D with authors and years call this internal command to do the actual typesetting. -%D -%D Two entries with same author but with different years may be condensed into -%D ``Author (year1,year2)''. This is about the only optimization that makes sense -%D for the (author,year) style of citations (years within one author have to be -%D unique 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, the macro \type {\thebibauthors} holds the names of the -%D alternative author info fields for the current list. This is a commalist, and -%D \type {\thebibyears} holds the (collection of) year(s) that go with this author -%D (possibly as a nested commalist). -%D -%D There had better be an author for all cases, but there does not have to be year -%D info always. \type{\thebibyears} is pre|-|initialized because this makes the -%D 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 - -\protected\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 \type {\thebibauthors} and \type -%D {\thebibyears} are printed. - -\protected\def\dobibauthoryear - {\scratchcounter\zerocount - \getcommacommandsize[\thebibauthors]% - \edef\authorcount{\commalistsize}% - \expandafter\processcommalist\expandafter[\thebibauthors]\dodobibauthoryear} - -\protected\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} - -\protected\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 - -\protected\def\handlemultiplebibauthors#1#2% - {\citescratchcounter\zerocount - \let\currentbibauthor\empty - \protected\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. - -\protected\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}. - -\pushoverloadmode - - \protected\def\robustaddtocommalist#1#2% {item} \cs - {\robustdoifelseinset{#1}#2\resetglobal - {\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}} - -\popoverloadmode - -%D \macros{donormalbibauthoryear} -%D -%D Now we get to the macros that fill the two lists. The \quote {simple} one really -%D is quite simple. - -\protected\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 the reference is not -%D found or the reference does not contain author data. No questions marks o.s.s. -%D (to be fixed later). - -\protected\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 by \type -%D {\scratchcounter}. - -\newcount\bibitemcounter -\newcount\bibitemwanted - -%D The first portion is simple enough: if this is the very first author it is quite -%D straightforward to add it. \type {\bibitemcounter} and \type {\bibitemwanted} are -%D needed later to insert the year information in the correct item of \type -%D {\thebibyears}. - -\protected\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 a new author to \type -%D {\thebibauthors}. The messing about with the two counters is again to make sure -%D that \type {\thebibyears} will be updated correctly.If the author {\it was} -%D found, the counters will stay at their present values and everything will be -%D setup properly to insert the year info. - -\protected\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. - -\protected\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. - -\protected\def\gotobiblink#1[#2]{\doifelsereferencefound{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}} -\protected\def\atbiblink [#1]{\doifelsereferencefound{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}} -\protected\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. \type -%D {\ixbibauthoryearref} stores the data in the macros \type {\currentbibauthor} and -%D \type {\currentbibyear}. - -\protected\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 - -\protected\def\bibmaybeinteractive#1#2% - {\doifelsebibinteraction{\gotobiblink{#2}[#1]}{#2}} - -\protected\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}}} - -\protected\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} - -\protected\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} - -\protected\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 thing that needs -%D to be done is making sure that the separations are inserted correctly. And that -%D is what \type {\bibinsertrefsep} does. - -\newconditional\firstbibrefsep - -\protected\def\bibresetrefsep - {\settrue\firstbibrefsep} - -\protected\def\bibinsertrefsep - {\ifconditional\firstbibrefsep - \setfalse\firstbibrefsep - \else - \bibalternative\c!pubsep - \fi} - -\protected\def\bibshortref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibshortref - \bibalternative\v!right} - -\protected\def\dobibshortref#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\gotobiblink{\bibgetvars{#1}}[#1]} - {}} - -\protected\def\bibserialref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibserialref - \bibalternative\v!right} - -\protected\def\dobibserialref#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\gotobiblink{\bibgetvarn{#1}}[#1]} - {}} - -\protected\def\bibkeyref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibkeyref - \bibalternative\v!right} - -\protected\def\dobibkeyref#1% - {\bibinsertrefsep - \gotobiblink{#1}[#1]} - -\protected\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}}} - -\protected\def\bibdoiref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibdoiref - \bibalternative\v!right} - -\protected\def\dobibdoiref#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\expanded{\bibgotoDOI{#1}{\bibgetvaro{#1}}}} - {}} - -\protected\def\biburlref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobiburlref - \bibalternative\v!right} - -\protected\def\bibgotoURL#1#2% - {\doifelsebibinteraction - {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]} - {\hyphenatedurl{#2}}} - -\protected\def\dobiburlref#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\expanded{\bibgotoURL{#1}{\bibgetvaru{#1}}}} - {}} - -\protected\def\bibtyperef[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibtyperef - \bibalternative\v!right} - -\protected\def\dobibtyperef#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\gotobiblink{\bibgetvart{#1}}[#1]} - {}} - -\protected\def\bibpageref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibpageref - \bibalternative\v!right} - -\protected\def\dobibpageref#1% - {\bibinsertrefsep - \doifelsebibinteraction - {\atbiblink[#1]} - {{\referencingfalse\at[#1]}}} - -\protected\def\bibdataref[#1]% - {\bibalternative\v!left - \bibresetrefsep\processcommalist[#1]\dobibdata - \bibalternative\v!right} - -\protected\def\dobibdata#1% - {\bibinsertrefsep - \doifelsebibreferencefound{#1} - {\dotypesetapublication{#1}} - {}} - -\let\bibnoneref\nocite - -%D \macros{bibnumref} - -\protected\def\bibnumref[#1]% - {\begingroup - \bibalternative\v!left - \penalty\plustenthousand - \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}% - \bibalternative\v!right - \endgroup} - -\protected\def\dowithbibtexnumrefconnector#1#2% - {\ifnum#1>\plusone - \ifnum#2>\plusone - \ifnum#2=#1\relax - \bibalternative{lastpubsep}% - \else - \bibalternative{pubsep}% - \fi - \fi - \fi} - -\protected\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref - {\dowithbibtexnumrefconnector{#1}{#2}% - \def\bibrefprefix{#4:}% - \inbiblink[#5]} - -\protected\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 \type {\citeasnoun}. - -\protected\def\bibauthornumref[#1]% - {\getcommalistsize[#1]% - \global\bibitemcounter\commalistsize - \bibresetrefsep - \processcommalist[#1]\dobibauthornumref} - -\protected\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] - -\protected\def\preloadbiblist - {\glet\preloadbiblist\relax - \dousepublications\jobname} - -% \appendtoks \preloadbiblist \to \everysetuppublications -% \appendtoks \preloadbiblist \to \everystarttext - -\let\ifbibinteractionelse\doifbibinteractionelse - -\protect \endinput diff --git a/tex/context/base/mkiv/blob-ini.lmt b/tex/context/base/mkiv/blob-ini.lmt deleted file mode 100644 index 42a18fddd..000000000 --- a/tex/context/base/mkiv/blob-ini.lmt +++ /dev/null @@ -1,210 +0,0 @@ -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 ------ 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 - --- upgraded - -local dimension_code = tokens.values.dimension -local scan_hbox = tokens.scanners.hbox - -local function action(field,what) - local l = scan_hbox() - local d = l[field] - flush_node_list(l) - if what == "value" then - return dimension_code, d - else - context("%p",d) - end -end - -implement { name = "widthofstring", public = true, usage = "value", actions = function(w) return action("width", w) end } -implement { name = "heightofstring", public = true, usage = "value", actions = function(w) return action("height",w) end } -implement { name = "depthofstring", public = true, usage = "value", actions = function(w) return action("depth", w) end } -implement { name = "totalofstring", public = true, usage = "value", actions = function(w) return action("total", w) end } diff --git a/tex/context/base/mkiv/blob-ini.mkxl b/tex/context/base/mkiv/blob-ini.mkxl deleted file mode 100644 index 3443836b7..000000000 --- a/tex/context/base/mkiv/blob-ini.mkxl +++ /dev/null @@ -1,56 +0,0 @@ -%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}{} % experimental -\registerctxluafile{blob-ini}{autosuffix} - -\unprotect - -% \widthofstring % defined in lua -% \heightofstring % defined in lua -% \depthofstring % defined in lua -% \heightanddepthofstring % defined in lua - -\permanent\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen -\permanent\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen -\permanent\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen -\permanent\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen - -\aliased\let\heightanddepthofstring\totalofstring -\aliased\let\htdpofstring \hdofstring - -\let\hd\htdp % if yes then move this - -% This one takes anything that can be typeset - -\permanent\protected\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}} - -\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/tex/context/base/mkiv/buff-ver.mkxl b/tex/context/base/mkiv/buff-ver.mkxl deleted file mode 100644 index 6e3b0ffe3..000000000 --- a/tex/context/base/mkiv/buff-ver.mkxl +++ /dev/null @@ -1,998 +0,0 @@ -%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}{} - -\unprotect - -\startcontextdefinitioncode - -\definesystemattribute[verbatimline][public] - -\appendtoksonce - \c_attr_verbatimline\attributeunsetvalue -\to \everyforgetall - -%D Initializations. - -\installcorenamespace{typinglines} -\installcorenamespace{typingspace} -\installcorenamespace{typingblank} % needs checking ... used? - -\newtoks\everyinitializeverbatim - -\appendtoks - \the\everyresettypesetting - \resetfontfeature - \resetcharacterspacing - \resetbreakpoints -\to \everyinitializeverbatim - -\permanent\protected\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 }{\enforced\let\obeyedspace\specialcontrolspace} -\setvalue{\??typingspace\v!stretch }{\enforced\let\obeyedspace\specialstretchedspace} -\setvalue{\??typingspace\v!normal }{} -\setvalue{\??typingspace\v!fixed }{\enforced\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} - -\protected\def\buff_verbatim_obey_hyphens - {} - -\protected\def\buff_verbatim_obey_breakpoints - {\nohyphens - \veryraggedright} - -\protected\def\buff_verbatim_ignore_hyphens - {\nohyphens} - -\def\buff_verbatim_initialize_type_one - {\enforced\let\obeylines\ignorelines - \edef\p_buff_option{\typeparameter\c!option}% - \ifx\p_buff_option\v!none - \usetypestyleandcolor\c!style\c!color - \orelse\ifempty\p_buff_option - \usetypestyleandcolor\c!style\c!color - \else - \usetypestyleparameter\c!style % no color - \fi - \setcatcodetable\vrbcatcodes} - -\def\buff_verbatim_initialize_type_two - {\spaceskip.5\emwidth\relax - \enforced\let\obeyedspace\specialobeyedspace - \enforced\let\controlspace\specialcontrolspace - \edef\p_buff_lines{\typeparameter\c!lines}% - \begincsname\??typinglines\p_buff_lines\endcsname - \edef\p_buff_space{\typeparameter\c!space}% - \begincsname\??typingspace\p_buff_space\endcsname - \relax\the\everyinitializeverbatim\relax} - -\protected\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 - \orelse\ifempty\p_buff_option - \usetypingstyleandcolor\c!style\c!color - \else - \usetypingstyleparameter\c!style % no color ! - \fi - \usealignparameter\typingparameter} - -\def\buff_verbatim_initialize_typing_two - {\spaceskip.5\emwidth\relax - \enforced\let\obeyedspace\specialobeyedspace - \enforced\let\controlspace\specialcontrolspace - \edef\p_buff_lines{\typingparameter\c!lines}% - \begincsname\??typinglines\p_buff_lines\endcsname - \edef\p_buff_space{\typingparameter\c!space}% - \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 following command. - -\installcorenamespace{type} - -\installcommandhandler \??type {type} \??type - -\appendtoks - \frozen\instance\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 will suffice, but -%D for documentation purposes the next 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 - \frozen\instance\setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}% - \frozen\instance\setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}% - \ifempty\currenttypingparent - \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} - -\protected\def\doifelsevisualizer#1% - {\clf_doifelsevisualizer{#1}} - -\let\doifvisualizerelse\doifelsevisualizer - -%D Verbatim command are very sensitive to argument processing, which is a direct -%D result of the \CATCODES\ being fixed at reading time. -%D -%D Typesetting inline verbatim can be accomplished by \type {\type}, which in this -%D sentence was typeset by saying just \type {\type {\type}}, which in turn was -%D typeset by \unknown. Using the normal grouping characters \type {{}} is the most -%D natural way of using this command. -%D -%D A second, more or less redundant, alternative is delimiting the argument with an -%D own character. This method was implemented in the context of a publication in the -%D \MAPS, where this way of delimiting is recognized by \LATEX\ users. -%D -%D The third, more original alternative, is the one using \type {<<} and \type {>>} -%D as delimiters. This alternative can be used in situations where slanted -%D typeseting is needed. -%D -%D \macros -%D {type} -%D -%D We define \type {\type} as a protected command. This command has several -%D invocations: grouped, wirt boundary characters, and with font switches. -%D -%D \starttyping -%D normal: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par -%D normal: \par \type{xx<..xx.. >..>xx} \par \type{<....>} \par \type{<....>} -%D \setuptype[option=slanted] -%D slanted: \par \type{xx<<..sl..<> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<>..>> \par -%D slanted: \par \type{xx<<..sl.. xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<....>> \par -%D \setuptype[option=none] -%D none: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par -%D \stoptyping -%D -%D When writing the manual to \CONTEXT\ and documenting this source we needed to -%D typeset \type {<<} and \type {>>}. Because we wanted to do this in the natural -%D way, we've adapted the original definition a bit. This implementation went -%D through several live cycles. The final implementation looks a bit further and -%D treats the lone \type {<<} and \type {>>} a bit different. The \type {\null} -%D prevents ligatures, which unfortunately turn up in Lucida fonts. -%D -%D The following lines show what happens when we set \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} - -\permanent\protected\def\type{\buff_verbatim_type\empty} -\permanent\protected\def\typ {\buff_verbatim_typ \empty} - -\protected\def\buff_verbatim_type#1% - {\dontleavehmode - \bgroup - \edef\currenttype{#1}% - \buff_verbatim_type_indeed} - -\def\buff_verbatim_typ#1% - {\dontleavehmode - \bgroup - \edef\currenttype{#1}% - \lettypeparameter\c!lines\v!hyphenated - \enforced\let\specialobeyedspace\specialstretchedspace - \buff_verbatim_type_indeed} - -\tolerant\def\buff_verbatim_type_indeed[#1]% - {\ifarguments\or\setupcurrenttype[#1]\fi - \buff_verbatim_left_of_type - \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one} - -\def\buff_verbatim_type_one - {\catcode`<=\othercatcode % old precaution - \catcode`>=\othercatcode % old precaution - \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c} - -\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 trait of this macros, -%D which are build on top of the support module, is that they don't hyphenate. We -%D therefore offer the alternative \type{\typ}. The current implementation works all -%D right, but a decent hyphenation support of \type{\tt} text will be implemented -%D soon. - -\permanent\protected\def\specialfixedspace {\kern\interwordspace\relax} -\permanent\protected\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip -\permanent\protected\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero -\permanent\protected\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback - -\permanent\protected\def\explicitfixedspace {\asciispacechar} -\permanent\protected\def\explicitobeyedspace {\asciispacechar\allowbreak} -\permanent\protected\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}% -\permanent\protected\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace - -\appendtoks - \enforced\protected\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}% -\to \everyenableelements - -\permanent\protected\def\obeyhyphens - {\enforced\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace - \enforced\let\controlspace\specialcontrolspace - \spaceskip.25\emwidth\relax} % hm a bit of stretch ! - -\permanent\protected\def\obeybreakpoints - {\ignorehyphens - \veryraggedright} - -\permanent\protected\def\ignorehyphens - {\nohyphens - \enforced\let\obeyedspace \specialobeyedspace - \enforced\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 argument, the fixed -%D \CATCODES\ interfere with our wishes. An experimental implementation of character -%D by character processing of verbatim text did overcome this limitation, but we've -%D decided not to use that slow and sometimes troublesome solution. Instead we stick -%D to some 'old' \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} - -\protected\def\tex{\buff_verbatim_special_type\texescape \relax} -\protected\def\arg{\buff_verbatim_special_type\leftargument \rightargument} -\protected\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker} -\protected\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker} - -\let\normaltexttex\tex -\let\normaltextarg\arg -\let\normaltextmat\mat -\let\normaltextdis\dis - -\permanent\protected\def\astype - {\dontleavehmode - \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken} - -\permanent\protected\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 - -\protected\def\buff_verbatim_typing_start#1% tricky non standard lookahead - {\begingroup - \edef\currenttyping{#1}% - \obeylines - \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop} - -\def\buff_verbatim_typing_start_nop - {\typingparameter\c!before\relax - \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\relax - \startpacked[\v!blank]% - \ifcondition\validassignment{#1}% - \setupcurrenttyping[#1]% - \else - \doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}% - \fi - \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}}} - -% \startnamedtyping[#1] - -\protected\def\buff_verbatim_setup_keep_together - {\edef\p_keeptogether{\typingparameter\c!keeptogether}% - \ifx\p_keeptogether\v!yes - \settrue \c_buff_optimize_linebreaks - \else - \setfalse\c_buff_optimize_linebreaks - \fi} - -\protected\def\buff_verbatim_type_block#1#2% - {\edef\p_strip{\typingparameter\c!strip}% - \normalexpanded{\buff_pickup - {_typing_}% - {#1}% - {#2}% - {}% - {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}% - \ifx\p_strip\v!no\zerocount\else\plusone\fi}} - -\protected\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 - \begincsname#2\endcsname} - -\protected\def\buff_verbatim_typing_stop#1% hm, currenttyping - {\stoppacked - \typingparameter\c!after\relax - \useindentnextparameter\typingparameter - \endgroup - \dorechecknextindentation} - -%D Line numbering for files is combined with filtering, while display verbatim has -%D 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 colorization of \TEX\ -%D sources as valid option. The other setup values are inherited from display -%D verbatim. The implementation of \type {\typefile} is straightforward: - -% [category] [settings] {name} % for historic reasons, all filenames are {} - -\appendtoks - \frozen\instance\setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}% -\to \everydefinetyping - -\permanent\tolerant\protected\def\typefile[#1]#*[#2]#:#3% - {\begingroup - \ifparameter#2\or - \setuptyping[#1][#2]% - \buff_verbatim_type_file_checked{#1}{#3}% - \orelse\ifparameter#1\or - \ifhastok={#1}% - \setuptyping[\v!file][#1]% - \buff_verbatim_type_file_checked\v!file{#3}% - \else - \buff_verbatim_type_file_checked{#1}{#3}% - \fi - \else - \buff_verbatim_type_file_checked\v!file{#3}% - \fi - \useindentnextparameter\typingparameter % needs checking - \endgroup - \dorechecknextindentation} % needs checking - -\def\buff_verbatim_type_file_checked#1#2% - {\doifelsetypingfile{#2} - {\buff_verbatim_type_file_indeed{#1}\askedtypingfile} - {\showmessage\m!verbatims1{#2}}} - -\permanent\protected\def\doifelsetypingfile#1% - {\edef\askedtypingfile{\locfilename{#1}}% - \ifempty\askedtypingfile - \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible - \fi - \ifempty\askedtypingfile - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\aliased\let\doiftypingfileelse\doifelsetypingfile - -\def\buff_verbatim_type_file_indeed#1#2% category name - {\edef\currenttyping{#1}% - \typingparameter\c!before\relax - \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\relax} - -%D Line numbering: - -\newconditional\verbatimnumberinglines - -\permanent\protected\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]} - -\overloaded\protected\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 - \orelse\ifx\currenttypingnumbering\v!line - \settrue\verbatimnumberinglines - \else - \setfalse\verbatimnumberinglines - \fi - \ifconditional\verbatimnumberinglines - \enforced\let\beginofverbatimlines\beginofverbatimlinenumbering - \enforced\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. - -\permanent\protected\def\filename#1{{\tttf\hyphenatedfilename{#1}}} - -%D \macros -%D {verbatim} -%d -%D And a bonus macro, an unexpanded detokenize: - -\permanent\protected\def\verbatim#1{\detokenize{#1}} - -%D The setups for display verbatim and file verbatim are shared. One can adapt the -%D extra defined typing environments, but they also default to the values below. -%D Watch the 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] - -% the \zeropoint forces the number to the margin but also works ok in text - -\setuplinenumbering[\v!typing][\c!location=\v!left,\c!width=\zeropoint] - -\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] - -\permanent\protected\def\typebuffer - {\begingroup - \let\currenttyping\v!buffer - \buff_verbatim_type_buffer} - -\protected\def\typedefinedbuffer[#1]% - {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}% - -\appendtoks - \frozen\instance\setuevalue{\e!type\currentbuffer}{\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}% -\to \everydefinebuffer - -\appendtoks % \e!buffer - \frozen\instance\setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}% -\to \everydefinetyping - -\tolerant\protected\def\buff_verbatim_type_buffer[#1]#*[#2]% - {\ifarguments - \buff_verbatim_type_buffer_indeed\currenttyping\empty% [] - \or - \ifhastok={#1}% - \setupcurrenttyping[#1]% - \buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings] - \else - \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] - \fi - \or - \setupcurrenttyping[#2]% - \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings] - \fi - \useindentnextparameter\typingparameter - \endgroup - \dorechecknextindentation} - -\protected\def\buff_verbatim_type_buffer_class#1% - {\begingroup - \edef\currenttyping{#1}% - \buff_verbatim_type_buffer} - -\tolerant\protected\def\buff_verbatim_type_defined_buffer[#1]#*[#2]#*[#3]% category name settings - {\begingroup - \ifarguments\or\or\or - \setuptyping[#1][#3]% - \fi - \buff_verbatim_type_buffer_indeed{#1}{#2}% - \useindentnextparameter\typingparameter - \endgroup - \dorechecknextindentation} - -\protected\def\buff_verbatim_type_buffer_indeed#1#2% category name - {\edef\currenttyping{#1}% - \typingparameter\c!before\relax - \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\relax} - -\permanent\protected\def\typeinlinebuffer - {\dontleavehmode - \begingroup - \let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline - \let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code - \let\currenttype\empty - \buff_verbatim_type_buffer} - -\protected\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name - {\edef\currenttype{#1}% - \buff_verbatim_initialize_type_one - \dostarttaggedchained\t!verbatim\currenttype\??type - \clf_typebuffer - name {#2}% - strip {\v!yes}% - regime {\currentregime}% - method {\p_buff_option}% - nature {inline}% is default anyway - \relax - \dostoptagged} - -% 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 - -\permanent\tolerant\protected\def\processbuffer[#1]#*[#2]% - {\writestatus{nota bene}{\string\processbuffer\space is obsolete}% - \begingroup - \ifarguments - \buff_verbatim_process_indeed\v!buffer\empty% [] - \or - %\ifcondition\validassignment{#1}% - \ifhastok={#1}% - \setuptyping[\v!buffer][#1]% - \buff_verbatim_process_indeed\v!buffer\empty% [settings] - \else - \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] - \fi - \or - \setuptyping[\v!buffer][#2]% - \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings] - \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 - -\protected\def\buff_verbatim_begin_of_line - {\ifconditional\verbatimnumberinglines - \global\advance\nofverbatimlines\plusone - \c_attr_verbatimline\nofverbatimlines - \fi - \noindent - \buff_verbatim_set_line_margin - \the\everyline % maybe also after starttagged - \strut % after starttagged, else break ! - \dostarttagged\t!verbatimline\empty} - -\protected\def\buff_verbatim_end_of_line - {\dostoptagged - \obeyedline % still needed? - \par - \ifconditional\verbatimnumberinglines - \c_attr_verbatimline\attributeunsetvalue - \fi} - -\protected\def\buff_verbatim_empty_line - {\dostoptagged - \ifconditional\verbatimnumberinglines - \par\strut\par % this will be an option where we use a signal instead of a strut - \else - \blank[\typingparameter\c!blank]% - \fi - \dostarttagged\t!verbatimlines\empty} - -% hooks (todo: frozen): - -\newcount \c_buff_verbatim_noflines -\newcount \c_buff_verbatim_current -\newconditional\c_buff_optimize_linebreaks - - \def\doverbatimspace {\obeyedspace} - -\protected\def\doinlineverbatimstart {} -\protected\def\doinlineverbatimstop {} -\protected\def\doinlineverbatimbeginline {} -\protected\def\doinlineverbatimnewline {\obeyedspace} -\protected\def\doinlineverbatimemptyline {\obeyedspace} - -\protected\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone - \buff_verbatim_begin_of_line} -\protected\def\dodisplayverbatimstop {\buff_verbatim_end_of_line} -\protected\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone - \buff_verbatim_begin_of_line} -\protected\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line - \par - \ifconditional\c_buff_optimize_linebreaks - \buff_verbatim_inject_breaks - \fi} -\protected\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line} - -\protected\def\buff_verbatim_inject_breaks - {\ifnum\c_buff_verbatim_current=\plusone - \nobreak - \orelse\ifnum\c_buff_verbatim_noflines=\plusthree - \nobreak - \orelse\ifnum\c_buff_verbatim_current=\numexpr\c_buff_verbatim_noflines-\plusone\relax - \nobreak - \fi} - -\protected\def\dodisplayverbatiminitialize#1% - {\forgetparindent % maybe more - \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 -% \frozen\instance\setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}% -% \to \everydefinevisualizer -% -% \protected\def\buff_verbatim_visualize#1% -% {\bgroup -% \def\currentvisualizer{#1}% -% \usevisualizerstyleandcolor\c!style\c!color -% \let\next} - -\appendtoks - \enforced\def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize - \enforced\def\tex #1{\letterbackslash#1}% -\to \everysimplifycommands - -\stopcontextdefinitioncode - -%D This is \type {\asciimode} without the double comment hackery: - -\protected\def\literalmode{\setcatcodetable\txtcatcodes} - -\protect \endinput diff --git a/tex/context/base/mkiv/catc-act.mkxl b/tex/context/base/mkiv/catc-act.mkxl deleted file mode 100644 index 4ccf22a7f..000000000 --- a/tex/context/base/mkiv/catc-act.mkxl +++ /dev/null @@ -1,51 +0,0 @@ -%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. - -\unprotect - -%D \macros -%D {installactivecharacter, defineactivecharacter} -%D -%D This module deals with some active character handling and I still need to -%D update it to use \typ {\letcharcode = \something}. This module -%D will be simplified stepwise. Look into the \MKIV\ variant for originals. -%D -%D There was a time when we had active double quotes and such but we no longer -%D do that. In fact, only the tilde and bar can be active in \CONTEXT. -%D -%D For those who love the more obscure features of \TEX: whenever you see -%D uppercase magic with active characters, keep in mind that this is something -%D deep down in the engine: handling of that specific case. The code here is -%D not used and not really tested. - -\permanent\protected\def\installactivecharacter#1 % - {\ifchknum#1\or - \scratchcounter #1\edef\scratchmacro{\expandtoken\othercatcode\scratchcounter}% - \else - \scratchcounter`#1\let \scratchmacro #1% - \fi - \normalexpanded{\startextendcatcodetable\ctxcatcodes\catcode\the\scratchcounter\activecatcode\stopextendcatcodetable}% - \letcatcodecommand \ctxcatcodes \scratchcounter \scratchmacro - \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi} - -\permanent\protected\def\defineactivecharacter #1 #2% - {\ifchknum#1\or\letcharcode#1=#2\relax\else\letcharcode`#1=#2\relax\fi} - -\permanent\protected\def\makecharacteractive #1 % - {\catcode`#1\activecatcode} - -\permanent\protected\def\installanddefineactivecharacter #1 #2% - {\normalexpanded{\installactivecharacter \utfchar{#1} }% - \defineactivecharacter #1 #2} - -\protect \endinput diff --git a/tex/context/base/mkiv/catc-ctx.mkxl b/tex/context/base/mkiv/catc-ctx.mkxl deleted file mode 100644 index fcaec65d0..000000000 --- a/tex/context/base/mkiv/catc-ctx.mkxl +++ /dev/null @@ -1,162 +0,0 @@ -%D \module -%D [ file=catc-cys, -%D version=2006.09.18, -%D title=\CONTEXT\ Catcode Macros, -%D subtitle=Extra Tables, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D We prefer to define relevant catcode tables in this file instead -%D of everywhere around. - -\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi -\ifdefined \prtcatcodes \else \newcatcodetable \prtcatcodes \fi -\ifdefined \txtcatcodes \else \newcatcodetable \txtcatcodes \fi -%ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky -\ifdefined \tpacatcodes \else \newcatcodetable \tpacatcodes \fi % { } -\ifdefined \tpbcatcodes \else \newcatcodetable \tpbcatcodes \fi % < > - -\setnewconstant \doublecommentsignal "10FF25 %% < 110000 (last valid range) - -\startcatcodetable \ctxcatcodes - \catcode\tabasciicode \spacecatcode - \catcode\endoflineasciicode \endoflinecatcode - \catcode\formfeedasciicode \endoflinecatcode - \catcode\spaceasciicode \spacecatcode - \catcode\endoffileasciicode \ignorecatcode - % \catcode\circumflexasciicode\superscriptcatcode - % \catcode\underscoreasciicode\subscriptcatcode - % \catcode\ampersandasciicode \alignmentcatcode - \catcode\underscoreasciicode\othercatcode - \catcode\circumflexasciicode\othercatcode - \catcode\ampersandasciicode \othercatcode - \catcode\backslashasciicode \escapecatcode - \catcode\leftbraceasciicode \begingroupcatcode - \catcode\rightbraceasciicode\endgroupcatcode - \catcode\dollarasciicode \mathshiftcatcode - \catcode\hashasciicode \parametercatcode - \catcode\commentasciicode \commentcatcode - \catcode\tildeasciicode \activecatcode - \catcode\barasciicode \activecatcode -\stopcatcodetable - -\startcatcodetable \prtcatcodes - \catcode\tabasciicode \spacecatcode - \catcode\endoflineasciicode \endoflinecatcode - \catcode\formfeedasciicode \endoflinecatcode - \catcode\spaceasciicode \spacecatcode - \catcode\endoffileasciicode \ignorecatcode - \catcode\circumflexasciicode \superscriptcatcode % candidate - \catcode\underscoreasciicode \lettercatcode - \catcode\ampersandasciicode \alignmentcatcode - \catcode\backslashasciicode \escapecatcode - \catcode\leftbraceasciicode \begingroupcatcode - \catcode\rightbraceasciicode \endgroupcatcode - \catcode\dollarasciicode \mathshiftcatcode - \catcode\hashasciicode \parametercatcode - \catcode\commentasciicode \commentcatcode - \catcode\atsignasciicode \lettercatcode - \catcode\exclamationmarkasciicode\lettercatcode - \catcode\questionmarkasciicode \lettercatcode - \catcode\tildeasciicode \activecatcode - \catcode\barasciicode \activecatcode -\stopcatcodetable - -\startcatcodetable \tpacatcodes - \catcode\tabasciicode \othercatcode - \catcode\endoflineasciicode \othercatcode - \catcode\formfeedasciicode \othercatcode - \catcode\spaceasciicode \othercatcode - \catcode\endoffileasciicode \othercatcode - \catcode\leftbraceasciicode \begingroupcatcode - \catcode\rightbraceasciicode\endgroupcatcode -\stopcatcodetable - -\startcatcodetable \tpbcatcodes - \catcode\tabasciicode \othercatcode - \catcode\endoflineasciicode \othercatcode - \catcode\formfeedasciicode \othercatcode - \catcode\spaceasciicode \othercatcode - \catcode\endoffileasciicode \othercatcode - \catcode\lessthanasciicode \begingroupcatcode - \catcode\morethanasciicode \endgroupcatcode -\stopcatcodetable - -\startcatcodetable \txtcatcodes - \catcode\tabasciicode \spacecatcode - \catcode\endoflineasciicode \endoflinecatcode - \catcode\formfeedasciicode \endoflinecatcode - \catcode\spaceasciicode \spacecatcode - \catcode\endoffileasciicode \ignorecatcode - \catcode\backslashasciicode \escapecatcode - \catcode\leftbraceasciicode \begingroupcatcode - \catcode\rightbraceasciicode\endgroupcatcode - \catcode\doublecommentsignal\commentcatcode -\stopcatcodetable - -\letcatcodecommand \ctxcatcodes \barasciicode \relax -\letcatcodecommand \ctxcatcodes \tildeasciicode \relax - -\pushoverloadmode - - \catcodetable \ctxcatcodes -\let \defaultcatcodetable \ctxcatcodes - -\popoverloadmode - -% for the moment here: - -\permanent\protected\def\starttexcode - {\pushcatcodetable - \catcodetable\prtcatcodes} - -\permanent\protected\def\stoptexcode - {\popcatcodetable} - -\permanent\protected\def\startcontextcode - {\pushcatcodetable - \catcodetable\ctxcatcodes} - -\permanent\protected\def\stopcontextcode - {\popcatcodetable} - -% not visible, only for special cases - -\newcatcodetable \ctdcatcodes % context definitions - -\startcatcodetable \ctdcatcodes - \catcode\tabasciicode \ignorecatcode - \catcode\endoflineasciicode \ignorecatcode - \catcode\formfeedasciicode \ignorecatcode - \catcode\spaceasciicode \ignorecatcode - \catcode\endoffileasciicode \ignorecatcode - \catcode\circumflexasciicode \superscriptcatcode % candidate - \catcode\underscoreasciicode \lettercatcode - \catcode\ampersandasciicode \alignmentcatcode -% \catcode\colonasciicode \lettercatcode % candidate - \catcode\backslashasciicode \escapecatcode - \catcode\leftbraceasciicode \begingroupcatcode - \catcode\rightbraceasciicode \endgroupcatcode - \catcode\dollarasciicode \mathshiftcatcode - \catcode\hashasciicode \parametercatcode - \catcode\commentasciicode \commentcatcode - \catcode\atsignasciicode \lettercatcode - \catcode\exclamationmarkasciicode\lettercatcode - \catcode\questionmarkasciicode \lettercatcode - \catcode\tildeasciicode \activecatcode - \catcode\barasciicode \activecatcode -\stopcatcodetable - -\permanent\protected\def\startcontextdefinitioncode - {\pushcatcodetable - \catcodetable\ctdcatcodes} - -\permanent\protected\def\stopcontextdefinitioncode - {\popcatcodetable} - -\endinput diff --git a/tex/context/base/mkiv/catc-def.mkxl b/tex/context/base/mkiv/catc-def.mkxl deleted file mode 100644 index e93345e1c..000000000 --- a/tex/context/base/mkiv/catc-def.mkxl +++ /dev/null @@ -1,147 +0,0 @@ -%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 shortcuts to their -%D character representation. Some will be overloaded (which might change). - -\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. - -\permanent\protected\def\unprotect{\pushcatcodetable\setcatcodetable\prtcatcodes} -\permanent\protected\def\protect {\popcatcodetable} - -% \prependtoks \catcodetable\ctxcatcodes \to \everyjob - -\endinput diff --git a/tex/context/base/mkiv/catc-ini.mkxl b/tex/context/base/mkiv/catc-ini.mkxl deleted file mode 100644 index 1dcd2107f..000000000 --- a/tex/context/base/mkiv/catc-ini.mkxl +++ /dev/null @@ -1,329 +0,0 @@ -%D \module -%D [ file=catc-ini, -%D version=2006.09.18, -%D title=\CONTEXT\ System Macros, -%D subtitle=Catcode Handling, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D We've split the functionality of syst-cat.* over more files -%D now so that we can load more selectively. - -\registerctxluafile{catc-ini}{} - -\unprotect - -%D A long standing wish has been the availability of catcode arrays. Because -%D traditional \TEX\ does not provide this we implement a fake method in the -%D \MKII\ file. There is some overlap in code with \MKII\ but we take that -%D for granted. Also, in \MKIV\ less active characters are used. - -% \begingroup -% -% \catcode\tabasciicode \activecatcode -% \catcode\formfeedasciicode \activecatcode -% \catcode\endoflineasciicode\activecatcode -% -% \letcharcode\tabasciicode \relax -% \letcharcode\newlineasciicode \relax -% \letcharcode\formfeedasciicode \relax -% \letcharcode\endoflineasciicode\relax -% -% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I} -% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J} -% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L} -% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M} -% -% \endgroup - -\begingroup - \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode} -\endgroup - -% \endlinechar = \endoflineasciicode % appended to input lines -% \newlinechar = \newlineasciicode % can be used in write - -% rather special and used in writing to file: \let\par\outputnewlinechar - -% \protected\def\initializenewlinechar % operating system dependent -% {\begingroup -% \newlinechar\newlineasciicode -% \xdef\outputnewlinechar{^^J}% -% \endgroup} - -\permanent\protected\def\initializenewlinechar % operating system dependent - {\begingroup - \letcharcode\newlineasciicode\relax - \newlinechar\newlineasciicode - \xdef\outputnewlinechar{\Uchar\newlineasciicode}% - \endgroup} - -%D We predefine some prefixes ahead of syst-aux and mult-sys. - -% We reserve 8 slots for catcodes. -% -% \def\??catcodelet {1>>} % let : \let -% \def\??catcodedef {2>>} % def : \def -% \def\??catcodeued {3>>} % ued : \protected\def -% \def\??catcodeget {4>>} % \meaning -% -% \def\??catcodetablet{5>>} -% \def\??catcodetablen{6>>} - -\installsystemnamespace {catcodelet} % let : \let -\installsystemnamespace {catcodedef} % def : \def -\installsystemnamespace {catcodeued} % ued : \protected\def -\installsystemnamespace {catcodeget} % \meaning - -\installsystemnamespace {catcodetablet} -\installsystemnamespace {catcodetablen} - -\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate -\newcount\c_syst_catcodes_a -\newcount\c_syst_catcodes_b -\newcount\c_syst_catcodes_c - -\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua - {\global\advance\c_syst_catcodes_n\plusone - \global\defcsname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging - %\setnewconstant#1\c_syst_catcodes_n - \immutable\integerdef#1\c_syst_catcodes_n - \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}} - -\newtoks \everysetdefaultcatcodes - -\everysetdefaultcatcodes % this might get dropped - {\catcode\backslashasciicode\othercatcode - \catcode\endoflineasciicode\othercatcode - \catcode\spaceasciicode \othercatcode - \catcode\commentasciicode \othercatcode - \catcode\delasciicode \othercatcode} - -\permanent\protected\def\startcatcodetable#1#2\stopcatcodetable - {\begingroup - \catcodetable\inicatcodes - \the\everysetdefaultcatcodes - #2% - \savecatcodetable#1\relax - \endgroup} - -\permanent\let\stopcatcodetable\relax - -\permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable - {\begingroup - \catcodetable#1\relax - \globaldefs\plusone - #2% - \globaldefs\zerocount - \endgroup} - -\permanent\let\stopextendcatcodetable\relax - -\permanent\protected\def\permitcircumflexescape % to be used grouped - {\catcode\circumflexasciicode\superscriptcatcode} - -\aliased\let\permitcaretescape\permitcircumflexescape - -% == -% -% \protected\def\startextendcatcodetable#1#2\stopextendcatcodetable -% {\bgroup -% \scratchcounter\the\catcodetable -% \catcodetable #1 #2 -% \catcodetable\scratchcounter -% \egroup} - -%D The next command can be defined in a cleaner way in the MkIV way but we want -%D to have a fast one with a minimal chance for interference. Do we still need -%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use -%D active characters for very special cases. - -\setnewconstant\c_syst_catcodes_hack\tildeasciicode - -%D Once a catcode is assigned, the next assignments will happen faster. However, -%D redefinitions probably happen seldom so it's sort of overkill. - -\permanent\protected\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a} -\permanent\protected\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a} -\permanent\protected\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a} - -\def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b} -\def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b} -\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b} - -\def\syst_catcodes_let_b % each time - {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \expandafter\lastnamedcs - \else - \expandafter\syst_catcodes_let_c - \fi} - -\def\syst_catcodes_def_b % each time - {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \expandafter\lastnamedcs - \else - \expandafter\syst_catcodes_def_c - \fi} - -\def\syst_catcodes_ued_b % each time - {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \expandafter\lastnamedcs - \else - \expandafter\syst_catcodes_ued_c - \fi} - -\def\syst_catcodes_let_c % only first time - {\frozen\enforced\global\defcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter - {\enforced\letcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}% - \syst_catcodes_reinstate_unexpanded - \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} - -\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here) - {\frozen\enforced\global\defcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname - \expandafter##\expandafter1\expandafter - {\frozen\enforced\defcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% - \syst_catcodes_reinstate_normal - \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} - -\def\syst_catcodes_ued_c % only first time - {\frozen\enforced\global\defcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname - \expandafter##\expandafter1\expandafter - {\frozen\enforced\protected\defcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% - \syst_catcodes_reinstate_unexpanded - \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} - -\permanent\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b} - -% \def\syst_catcodes_reinstate_normal % can be used when a direct definition has been done -% {\begingroup % and the selector has been lost -% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b -% \catcode\uccode\c_syst_catcodes_hack\activecatcode -% \uppercase{\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% -% \endgroup} - -% \def\syst_catcodes_reinstate_unexpanded % can be used when a direct definition has been done -% {\begingroup % and the selector has been lost -% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b -% \catcode\uccode\c_syst_catcodes_hack\activecatcode -% \uppercase{\protected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% -% \endgroup} - -%D This can be used when a direct definition has been done and the selector has been -%D lost. - -% problem: \next needs to be unique (as it gets bound) - -\def\syst_catcodes_reinstate_normal - {\begingroup - \edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% - \global\letcharcode\c_syst_catcodes_b\c_syst_char_code - \endgroup} - -\def\syst_catcodes_reinstate_unexpanded - {\begingroup - \protected\edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% - \global\letcharcode\c_syst_catcodes_b\c_syst_char_code - \endgroup} - -\newconstant\defaultcatcodetable - -\permanent\def\catcodecommand#1% - {\csname\??catcodeget\number - \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname - \currentcatcodetable \else \defaultcatcodetable - \fi - :\number#1\endcsname} - -%D \macros -%D {restorecatcodes,pushcatcodetable,popcatcodetable} -%D -%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary -%D file, which deals with tables of contents, registers, two pass tracking, references -%D etc. This file, as well as files concerning graphics, is processed when needed, -%D which can be in the mid of typesetting verbatim. However, when reading in data in -%D verbatim mode, we should temporary restore the normal \CATCODES, and that's exactly -%D what the next macros do. Saving the catcodes can be disabled by saying \type -%D {\localcatcodestrue}. In \MKIV\ instead we can push and pop catcode tables and as -%D we keep track of used tables users seldom need to deal with this themselves. - -\newcount\c_syst_catcodes_level - -\permanent\protected\def\pushcatcodetable - {\advance\c_syst_catcodes_level\plusone - \syst_catcodes_trace_push - \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable} - -\permanent\protected\def\popcatcodetable - {\ifcase\c_syst_catcodes_level - \syst_catcodes_trace_nesting_error - \else - \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname - \syst_catcodes_trace_pop - \advance\c_syst_catcodes_level\minusone - \fi} - -\protected\def\syst_catcodes_trace_nesting_error - {\immediate\write\statuswrite{}% - \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end - \immediate\write\statuswrite{}} - -\permanent\protected\def\restorecatcodes % takes previous level - {\ifnum\c_syst_catcodes_level>\plusone - \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname - \fi} - -% \newtoks\everycatcodetable - -\permanent\protected\def\setcatcodetable#1% - {\catcodetable#1% -% \the\everycatcodetable - \syst_catcodes_trace_set} - -%D Handy for debugging: -%D -%D \starttyping -%D \tracecatcodetables -%D \stoptyping - -\permanent\protected\def\tracecatcodetables - {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \number\c_syst_catcodes_level}}% - \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}% - \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}} - -\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}} - -\def\syst_catcodes_prev - {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount - \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname - \else - -% - \fi} - -\def\catcodetablename - {\ifnum\currentcatcodetable>\zerocount - \csname\??catcodetablen\number\currentcatcodetable\endcsname - \else - -% - \fi} - -\let\syst_catcodes_trace_set \empty -\let\syst_catcodes_trace_push\empty -\let\syst_catcodes_trace_pop \empty - -% \tracecatcodetables - -\protect - -%D We still have to define these so let's do that now: - -\newcatcodetable \inicatcodes -\initcatcodetable\inicatcodes - -\let\currentcatcodetable\catcodetable - -\endinput diff --git a/tex/context/base/mkiv/catc-sym.mkxl b/tex/context/base/mkiv/catc-sym.mkxl deleted file mode 100644 index 5334d7723..000000000 --- a/tex/context/base/mkiv/catc-sym.mkxl +++ /dev/null @@ -1,95 +0,0 @@ -%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 The following definitions can be used for mapping special characters onto -%D letters, although we cheat a bit: they actually are of category other but -%D for users that distinction doesn't matter here. The definitions in \MKII\ -%D and \MKIV\ look more impressive but here we use a \LUAMETATEX\ feature -%D that permits a more direct definition (that also looks nice with the -%D \CONTEXT\ syntax highlighting): - -\immutable\edef\letterleftbrace {\expandtoken \othercatcode \leftbraceasciicode} -\immutable\edef\letterrightbrace {\expandtoken \othercatcode \rightbraceasciicode} -\immutable\edef\letterampersand {\expandtoken \othercatcode \ampersandasciicode} -\immutable\edef\letterless {\expandtoken \othercatcode \lessthanasciicode} -\immutable\edef\lettermore {\expandtoken \othercatcode \morethanasciicode} -\immutable\edef\letterhash {\expandtoken \othercatcode \hashasciicode} -\immutable\edef\letterdoublequote {\expandtoken \othercatcode \doublequoteasciicode} -\immutable\edef\lettersinglequote {\expandtoken \othercatcode \singlequoteasciicode} -\immutable\edef\letterdollar {\expandtoken \othercatcode \dollarasciicode} -\immutable\edef\letterpercent {\expandtoken \othercatcode \percentasciicode} -\immutable\edef\letterhat {\expandtoken \othercatcode \circumflexasciicode} -\immutable\edef\letterunderscore {\expandtoken \othercatcode \underscoreasciicode} -\immutable\edef\letterbar {\expandtoken \othercatcode \barasciicode} -\immutable\edef\lettertilde {\expandtoken \othercatcode \tildeasciicode} -\immutable\edef\letterbackslash {\expandtoken \othercatcode \backslashasciicode} -\immutable\edef\letterslash {\expandtoken \othercatcode \forwardslashasciicode} -\immutable\edef\letterquestionmark {\expandtoken \othercatcode \questionmarkasciicode} -\immutable\edef\letterexclamationmark {\expandtoken \othercatcode \exclamationmarkasciicode} -\immutable\edef\letterat {\expandtoken \othercatcode \atsignasciicode} -\immutable\edef\lettercolon {\expandtoken \othercatcode \colonasciicode} - -\immutable\edef\letterleftparenthesis {\expandtoken \othercatcode \leftparentasciicode} -\immutable\edef\letterrightparenthesis {\expandtoken \othercatcode \rightparentasciicode} -\immutable\edef\letterleftbracket {\expandtoken \othercatcode \leftbracketasciicode} -\immutable\edef\letterrightbracket {\expandtoken \othercatcode \rightbracketasciicode} - -\aliased\let\letterescape \letterbackslash -\aliased\let\letterbgroup \letterleftbrace -\aliased\let\letteregroup \letterrightbrace -\aliased\let\letteropenbrace \letterleftbrace -\aliased\let\letterclosebrace\letterrightbrace - -\unprotect - -%immutable\edef\_n_u_l_{\expandtoken \othercatcode \zerocount} % nul(l) -%immutable\edef\_s_o_h_{\expandtoken \othercatcode \plusone } % start of header ^^^^0001 -\immutable\edef\_s_t_x_{\expandtoken \othercatcode \plustwo } % start of text ^^^^0002 -\immutable\edef\_e_t_x_{\expandtoken \othercatcode \plusthree} % end of text ^^^^0003 -\immutable\edef\_e_o_t_{\expandtoken \othercatcode \plusfour } % end of transmission ^^^^0004 -%immutable\edef\_e_n_q_{\expandtoken \othercatcode \plusfive } % enquiry -%immutable\edef\_a_c_k_{\expandtoken \othercatcode \plussix } % aknowledgement - -\protect - -%D \macros -%D {uncatcodespecials,setnaturalcatcodes,setnormalcatcodes, -%D uncatcodecharacters,uncatcodeallcharacters, -%D uncatcodespacetokens} -%D -%D The following macros are more or less replaced by switching to a catcode table -%D (which we simulate in \MKII) but we keep them for convenience and compatibility. -%D Some old engine code has been removed. A few ar still used a few times so I need -%D to clean that up. - -%permanent\protected\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens} -%permanent\protected\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes} -\permanent\protected\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes -%permanent\protected\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now -%permanent\protected\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore - -\permanent\protected\def\uncatcodespacetokens - {\catcode\spaceasciicode \spacecatcode - \catcode\tabasciicode \spacecatcode - \catcode\formfeedasciicode \endoflinecatcode - \catcode\endoflineasciicode\endoflinecatcode - \catcode\delasciicode \ignorecatcode} - -%D These two are probably no longer needed, but we keep them for a while. Some more -%D explanation can be foun din the mkiv variant of this module, where we also -%D discuss side effects. It's time to move on, so these might go away some day. - -\aliased \let\rescan \scantextokens -\permanent\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup} - -\endinput diff --git a/tex/context/base/mkiv/char-act.mkxl b/tex/context/base/mkiv/char-act.mkxl deleted file mode 100644 index 3fb4d2da6..000000000 --- a/tex/context/base/mkiv/char-act.mkxl +++ /dev/null @@ -1,99 +0,0 @@ -%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, \NEWLINE\ and \NEWPAGE\ -%D active and assigning them \type {\obeysomething}, but first we set some default -%D values. -%D -%D These are expandable: - -\permanent\def\obeyedspace{\space} -\permanent\def\obeyedtab {\obeyedspace} -\permanent\def\obeyedline {\par} -\permanent\def\obeyedpage {\page_otr_fill_and_eject_page} - -%D \macros -%D {controlspace,setcontrolspaces} -%D -%D First we define \type {\obeyspaces}. When we want visible spaces (control spaces) -%D we only have to adapt the definition of \type {\obeyedspace} to: - -\immutable\chardef\asciispacechar\spaceasciicode % a real space character - -\permanent\protected\def\naturalspace{\asciispacechar} -\permanent\protected\def\controlspace{\hbox{\asciispacechar}} % rather tex, we need the unicode value -\permanent\protected\def\normalspaces{\catcode\spaceasciicode\spacecatcode} - -% \bgroup -% \catcode\spaceasciicode\activecatcode -% \protected\gdef\obeyspaces {\catcode\spaceasciicode\activecatcode\def {\obeyedspace }} -% \protected\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}} -% \egroup - -%permanent\protected\def\obeyspaces {\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\obeyedspace } -%permanent\protected\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\controlspace} - -%D \macros -%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages} -%D -%D Next we take care of \NEWLINE\ and \NEWPAGE\ and because we want to be able to -%D typeset listings that contain \TAB, we have to handle those too. Because we have -%D to redefine the \NEWPAGE\ character locally, we redefine the meaning of this -%D (often already) active character. - -% \expandafter\def\activeformfeedtoken{\par} - -\letcharcode\formfeedasciicode\par - -%D The following indirect definitions enable us to implement all kind of \type -%D {\obeyed} handlers. - -% \protected\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }} -% \protected\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}} -% \protected\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}} - -% \protected\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}} -% \protected\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}} -% \protected\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} -% \protected\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} - -% but ... as we don't want to freeze to \obeyedspace etc which can be set after -% \obeyspaces, we use an idirectness - -\def\syst_obeyed_space{\obeyedspace} -\def\syst_obeyed_tab {\obeyedtab} -\def\syst_obeyed_line {\obeyedline} -\def\syst_obeyed_page {\obeyedpage} - -\permanent\protected\def\obeyspaces {\catcode\spaceasciicode \activecatcode\enforced\letcharcode\spaceasciicode \syst_obeyed_space} -\permanent\protected\def\obeytabs {\catcode\tabasciicode \activecatcode\enforced\letcharcode\tabasciicode \syst_obeyed_tab } -\permanent\protected\def\obeylines {\catcode\endoflineasciicode\activecatcode\enforced\letcharcode\endoflineasciicode\syst_obeyed_line } -\permanent\protected\def\obeypages {\catcode\formfeedasciicode \activecatcode\enforced\letcharcode\formfeedasciicode \syst_obeyed_page } - -\permanent\protected\def\ignoretabs {\catcode\tabasciicode \activecatcode\enforced\letcharcode\tabasciicode \syst_obeyed_space} -\permanent\protected\def\ignorelines{\catcode\endoflineasciicode\activecatcode\enforced\letcharcode\endoflineasciicode\syst_obeyed_space} -\permanent\protected\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} -\permanent\protected\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} - -\permanent\protected\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\enforced\letcharcode\spaceasciicode\controlspace} - -\endinput \protect diff --git a/tex/context/base/mkiv/char-def.lua b/tex/context/base/mkiv/char-def.lua index 70e564399..79a210338 100644 --- a/tex/context/base/mkiv/char-def.lua +++ b/tex/context/base/mkiv/char-def.lua @@ -71060,6 +71060,7 @@ characters.data={ [0x2423]={ adobename="blank", category="so", + contextname="textcontrolspace", description="OPEN BOX", direction="on", linebreak="al", diff --git a/tex/context/base/mkiv/char-enc.mkxl b/tex/context/base/mkiv/char-enc.mkxl deleted file mode 100644 index d0dd3d20a..000000000 --- a/tex/context/base/mkiv/char-enc.mkxl +++ /dev/null @@ -1,18 +0,0 @@ -%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}{} - -\endinput diff --git a/tex/context/base/mkiv/char-ini.mkxl b/tex/context/base/mkiv/char-ini.mkxl deleted file mode 100644 index 1df5d4b01..000000000 --- a/tex/context/base/mkiv/char-ini.mkxl +++ /dev/null @@ -1,130 +0,0 @@ -%D \module -%D [ file=char-ini, -%D version=2006.08.20, -%D title=\CONTEXT\ Character Support, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Character Support / Initialization} - -\registerctxluafile{char-fio}{} -\registerctxluafile{char-map}{} % maybe we will load this someplace else -\registerctxluafile{char-tex}{} -\registerctxluafile{char-ent}{} - -\unprotect - -% ¨äëïöüÿ -% ´áćéíĺńóŕśúýź -% ˙ċėġiż -% ¯āēīōū -% ˝őű -% ˆâĉêĝĥîĵôŝûŵŷ -% `àèìòùỳ -% ¸çķļņŗşţ -% ˛ąęįų -% ˚åů -% ˘ăĕğĭŏŭ -% ˇčďěľňřšťž -% ˜ãĩñõũ - -% \def\checkedchar#1% #2% -% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} -% -% impossible in math mode so there always fallback (till we have gyre): -% -% use \normalUchar when possible .. the next one is nice for documents and it also accepts -% 0x prefixed numbers - -\permanent\def\utfchar #1{\clf_utfchar {#1}} % todo: define public at lua end -\permanent\def\safechar#1{\clf_safechar{#1}} % todo: define public at lua end - -\permanent\protected\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) -\permanent \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) - -\permanent\def\expandUx{\enforced\let\Ux\eUx} - -\permanent \def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2 -\permanent \def\checkedmathchar#1#2{#2} -%permanent \def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} -\permanent\protected\def\checkedtextchar #1{\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2} - -\newconditional\prefermathovertextchar - -\permanent\protected\def\textormathchar#1% - {\begingroup - \scratchcounter#1\relax - \ifmmode - \char\scratchcounter - \else - \ifconditional\prefermathovertextchar - % dirty trick .. maybe let this adapt to bf too ? - \setfontid\fontid\textfont\c_font_fam_mr - \fi - \iffontchar\font\scratchcounter - \char\scratchcounter - \else - \normalstartimath\char\scratchcounter\normalstopimath - \fi - \fi - \endgroup} - -\permanent\protected\def\textormathchars#1% - {{\font_text_or_mathchars#1\relax}} - -\protected\def\font_text_or_mathchars#1#2\relax - {\relax\ifmmode - #1#2% - \orelse\iffontchar\font`#1\relax - #1#2\relax - \else - \normalstartimath#1#2\normalstopimath - \fi} - -%D The codes are stored in the format, so we don't need to reinitialize -%D them (unless of course we have adapted the table). It is on the agenda -%D to do this with \type {tex.lccode} cum suis once they're available. - -% \def\setcclcuc#1#2#3{\global\catcode#1=\lettercatcode\global\lccode#1=#2\global\uccode#1=#3\relax} -% \def\setcclcucself#1{\global\catcode#1=\lettercatcode\global\lccode#1=#1\global\uccode#1=#1\relax } - -% Is setting up vrb tpa and tpb needed? - -% move to lua side - -%clf_setcharactercodes - -\clf_setlettercatcodes\texcatcodes -\clf_setlettercatcodes\ctxcatcodes -\clf_setlettercatcodes\notcatcodes -%clf_setlettercatcodes\mthcatcodes -\clf_setlettercatcodes\vrbcatcodes -\clf_setlettercatcodes\prtcatcodes -\clf_setlettercatcodes\tpacatcodes -\clf_setlettercatcodes\tpbcatcodes -\clf_setlettercatcodes\txtcatcodes - -\clf_setactivecatcodes\ctxcatcodes -\clf_setactivecatcodes\notcatcodes -\clf_setactivecatcodes\prtcatcodes - -\clf_setcharacternames\ctxcatcodes - -\permanent\def\chardescription#1{\clf_chardescription#1\relax} - -% experiment (watch out: this is global and very font dependent when used with -% casing mechanisms) -% -% \overloaduppercase{0xDF}{0x1E9E}} -% \overloaduppercase{0xDF}{0x53,0x53} - -\permanent\protected\def\overloaduppercase{\clf_overloaduppercase} % todo: define public at lua end -\permanent\protected\def\overloadlowercase{\clf_overloadlowercase} % todo: define public at lua end - -\protect \endinput diff --git a/tex/context/base/mkiv/char-tex.lua b/tex/context/base/mkiv/char-tex.lua index 1e86ca171..4580ae40a 100644 --- a/tex/context/base/mkiv/char-tex.lua +++ b/tex/context/base/mkiv/char-tex.lua @@ -679,15 +679,15 @@ if not csletters then if is_character[category] then if chr.unicodeslot < 128 then if isletter then - texsetmacro(contextname,utfchar(u),"permanent") + texsetmacro(contextname,utfchar(u),"immutable") else texsetchar(contextname,u) end else - texsetmacro(contextname,utfchar(u),"permanent") + texsetmacro(contextname,utfchar(u),"immutable") end elseif is_command[category] and not forbidden[u] then - texsetmacro(contextname,utfchar(u),"permanent") + texsetmacro(contextname,utfchar(u),"immutable") end end end diff --git a/tex/context/base/mkiv/char-utf.mkxl b/tex/context/base/mkiv/char-utf.mkxl deleted file mode 100644 index a7cbab345..000000000 --- a/tex/context/base/mkiv/char-utf.mkxl +++ /dev/null @@ -1,44 +0,0 @@ -%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\ 8, 16 and 32 -%D were supported as well as collapsing (combining sequences). Writing the code was -%D a relaxed experience, not in the last place because it was accompanied by -%D listening to those nice Vienna Teng cd's (who decided that making music was more -%D fun than programming, but then, she may not know \TEX\ and \LUA). - -\unprotect - -\registerctxluafile{char-def}{} -\registerctxluafile{char-ini}{} -\registerctxluafile{char-utf}{} -\registerctxluafile{char-cjk}{} - -%D We enable collapsing (combining characters) by default, but since the source -%D files are rather simple, we postpone the 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 - -\permanent\protected\def\definecomposedutf#1 #2 #3 {\clf_addgrapheme{#1}{#2}{#3}} - -\protect diff --git a/tex/context/base/mkiv/chem-ini.mkxl b/tex/context/base/mkiv/chem-ini.mkxl deleted file mode 100644 index 55bbbd874..000000000 --- a/tex/context/base/mkiv/chem-ini.mkxl +++ /dev/null @@ -1,53 +0,0 @@ -%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}{} - -\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 - -\permanent\protected\def\molecule#1% todo: can become a public implementor - {\clf_molecule{#1}} - -%D For old times sake: - -\permanent\protected\def\chem#1#2#3% - {\dontleavehmode\begingroup#1\lohi{#2}{#3}\endgroup} - -\protect \endinput - - diff --git a/tex/context/base/mkiv/chem-str.mkxl b/tex/context/base/mkiv/chem-str.mkxl deleted file mode 100644 index 5274de949..000000000 --- a/tex/context/base/mkiv/chem-str.mkxl +++ /dev/null @@ -1,749 +0,0 @@ -%D \module -%D [ file=chem-ini, -%D version=2009.05.13, -%D subtitle=Chemistry, -%D author=Hans Hagen \& Alan Braslau, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made -%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between -%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible -%D but better implementation, later versions might provide more, - -%D NOT YET LMTX'd - -\writestatus{loading}{ConTeXt Chemistry Macros / Structure} - -\registerctxluafile{chem-str}{} - -% We have a slightly different interface. This is unchanged: -% -% \startchemical[axis=on] -% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1] -% \stopchemical -% -% Here we use chemicalformula instead, so no longer a mix: -% -% \startchemicalformula -% \chemical{2H_2}{top}{bottom} -% \chemical{PLUS}{top}{bottom} -% \chemical{O_2}{top}{bottom} -% \chemical{GIVES}{top}{bottom} -% \chemical{2H_2O}{top}{bottom} -% \stopchemicalformula -% -% \startchemicalformula -% \chemical{2H_2} -% \chemical{PLUS} -% \chemical{O_2} -% \chemical{GIVES} -% \chemical{2H_2O} -% \stopchemicalformula -% -% The inline variant has only one argument: -% -% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O} - -\unprotect - -\installcorenamespace{chemical} -\installcorenamespace{chemicalsymbol} -\installcorenamespace{chemicalframed} -\installcorenamespace{chemicalsize} - -% \installsimplecommandhandler \??chemical {chemical} \??chemical % no \define... -\installcommandhandler \??chemical {chemical} \??chemical % no \define... - -\aliased\let\setupchemicals \setupchemical -\aliased\let\definechemicals\definechemical - -%D We use a dedicated framed macro instead of inheriting one. This is both -%D a historical and practical reason (like shared keys with different meaning -%D that could clash, e.g.\ align). - -\defineMPinstance % not really needed as we set in lua - [chemistry] - [\s!format=metafun, - %\s!extensions=\v!yes, % Should we add extensions and initializations? - %\s!initializations=\v!yes, % Would this give EmWidth, etc.? - \c!method=\s!double] - -\startMPdefinitions{chemistry} - loadmodule "chem" ; -\stopMPdefinitions - -\defineframed - [\??chemicalframed] - [\c!align=\v!normal, - \c!strut=\v!no] - -\permanent\protected\def\setupchemicalframed - {\setupframed[\??chemicalframed]} - -\permanent\protected\overloaded\def\definechemical % is global (so we don't use the commandhandler) - {\dosingleargument\chem_define} - -\def\chem_define[#1]#2% - {\startnointerference - \edef\currentdefinedchemical{#1}% - \enforced\let\chemical\chem_chemical_nested - \clf_undefinechemical{#1}% - #2% flush - \stopnointerference} - -\permanent\tolerant\protected\def\chem_chemical_nested[#1]#*[#2]% - {\clf_definechemical{\currentdefinedchemical}{#1}{\detokenize{#2}}} - -% chemical symbols - -\permanent\tolerant\protected\def\definechemicalsymbol[#1]#*[#2]% - {\ifarguments\else\setvalue{\??chemicalsymbol#1}{#2}\fi} - -\permanent\protected\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} - -\permanent\protected\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 - -\permanent\tolerant\protected\def\startchemical[#1]#*[#2]% - {\ifmmode\vcenter\else\vbox\fi % vpack ? - \bgroup - \synchronizestrut{\chemicalparameter\c!strut}% - \dontcomplain - %\settrue\indisplaychemical - \forgetall - \ifparameter#2\or - \ifhastok={#1}% - \setupcurrentchemical[#1]% same as \currentchemical - \else - \edef\currentchemical{#1}% - \setupcurrentchemical[#2]% - \fi - \orelse\ifparameter#1\or - \ifhastok={#1}% - \setupcurrentchemical[#1]% same as \currentchemical - \else - \edef\currentchemical{#1}% - \fi - \fi - \the\everystructurechemical - \setbox\b_chem_result\hpack\bgroup - \clf_startchemical - width {\chemicalparameter\c!width}% - height {\chemicalparameter\c!height}% - left {\chemicalparameter\c!left}% - right {\chemicalparameter\c!right}% - top {\chemicalparameter\c!top}% - bottom {\chemicalparameter\c!bottom}% - scale {\chemicalparameter\c!scale}% - rotation {\chemicalparameter\c!rotation}% - symalign {\chemicalparameter\c!symalign}% - axis {\chemicalparameter\c!axis}% was \MPcolor{...} - framecolor {\chemicalparameter\c!framecolor}% - rulethickness {\number\dimexpr\chemicalparameter\c!rulethickness}% - offset {\number\dimexpr\chemicalparameter\c!offset}% - unit {\number\dimexpr\chemicalparameter\c!unit}% - factor {\number\chemicalparameter\c!factor}% - \relax - \startnointerference} - -\permanent\protected\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} - -\protected\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 - -\protected\def\chem_framed_nop - {\directlocalframed - [\??chemicalframed]% - {\vpack{\box\b_chem_result\vss}}} % remove depth - -\aliased\let\startstructurechemical\startchemical -\aliased\let\stopstructurechemical \stopchemical - -\appendtoks - \enforced\let\chemical\structurechemical -\to\everystructurechemical - -\protected\def\structurechemical - {\dotripleempty\strc_chem_indeed} - -\def\strc_chem_indeed - {\ifthirdargument - \expandafter\strc_chem_indeed_three - \else - \expandafter\strc_chem_indeed_two - \fi} - -\def\strc_chem_indeed_three[#1][#2][#3]% - {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored - \clf_chemicalcomponent - {#2}% - {\detokenize{#3}}% - {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points - {\chemicalparameter\c!rulecolor}% - \relax - \ignorespaces} - -\def\strc_chem_indeed_two[#1][#2]% why no [#3] here - {\clf_chemicalcomponent - {#1}% - {\detokenize{#2}}% - {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points - {\chemicalparameter\c!rulecolor}% - \relax - \ignorespaces} - -\appendtoks - \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}% - \d_chem_width \wd\b_chem_result - \d_chem_height\ht\b_chem_result - \d_chem_depth \dp\b_chem_result -\to \t_chem_every_box - -% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize) - -\appendtoks - \edef\m_bodyfont{\chemicalparameter\c!bodyfont}% - \ifempty\m_bodyfont - \switchtobodyfont[\m_bodyfont]% - \fi - \getvalue{\??chemicalsize\chemicalparameter\c!size}% -% \to \everystructurechemical -\to \everychemical - -\permanent\protected\def\chemicaltoptext#1{\global\settrue\c_chem_some_text\gdef\m_chem_top_text{#1}\ignorespaces} -\permanent\protected\def\chemicalbottext#1{\global\settrue\c_chem_some_text\gdef\m_chem_bot_text{#1}\ignorespaces} -\permanent\protected\def\chemicalmidtext#1{\global\settrue\c_chem_some_text\gdef\m_chem_mid_text{#1}\ignorespaces} - -\appendtoks - \enforced\let\toptext\chemicaltoptext \glet\m_chem_top_text\empty - \enforced\let\bottext\chemicalbottext \glet\m_chem_bot_text\empty - \enforced\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} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\chemicaltop {\chem_top_construct \hss \hss } -\permanent\protected\def\chemicallefttop {\chem_top_construct \relax\hss } -\permanent\protected\def\chemicalrighttop {\chem_top_construct \hss \relax} -\permanent\protected\def\chemicalbottom {\chem_bottom_construct\hss \hss } -\permanent\protected\def\chemicalleftbottom {\chem_bottom_construct\relax\hss } -\permanent\protected\def\chemicalrightbottom{\chem_bottom_construct\hss \relax} - -\permanent\protected\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}} -\permanent\protected\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}} -\permanent\protected\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}} -\permanent\protected\def\chemicalbottomright#1{\chemicalright{\chemicalleftbottom {#1}{}}} - -% \protected\def\chemicalcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1\hss}} -% \protected\def\chemicalleftcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut #1\hss}} -% \protected\def\chemicalrightcentered#1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1}} - -% \let\chemicalsmashedmiddle\chemicalcentered -% \let\chemicalsmashedleft \chemicalleftcentered -% \let\chemicalsmashedright \chemicalrightcentered - -\permanent\protected\def\chemicalalignedtext - {\ifmmode - \expandafter\chem_aligned_text_math - \else - \expandafter\chem_aligned_text_text - \fi} - -\aliased\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} - -\permanent\protected\def\chemicalcentered {\chemicalalignedtext\hss \hss } -\permanent\protected\def\chemicalleftcentered {\chemicalalignedtext\relax\hss } -\permanent\protected\def\chemicalrightcentered{\chemicalalignedtext\hss \relax} - -\aliased\let\chemicalsmashedmiddle\chemicalcentered -\aliased\let\chemicalsmashedleft \chemicalleftcentered -\aliased\let\chemicalsmashedright \chemicalrightcentered - -\permanent\protected\def\chemicaloxidation#1#2#3% - {\chemicaltop{\txx\ifcase#2\relax0\else#1\convertnumber{I}{#2}\fi}{#3}} - -\permanent\protected\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed! -\permanent\protected\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed! -\permanent\protected\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed! -\permanent\protected\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed! -\permanent\protected\def\chemicaloxidationone {\chemicaloxidation\relax1} -\permanent\protected\def\chemicaloxidationtwo {\chemicaloxidation\relax2} -\permanent\protected\def\chemicaloxidationthree{\chemicaloxidation\relax3} -\permanent\protected\def\chemicaloxidationfour {\chemicaloxidation\relax4} -\permanent\protected\def\chemicaloxidationfive {\chemicaloxidation\relax5} -\permanent\protected\def\chemicaloxidationsix {\chemicaloxidation\relax6} -\permanent\protected\def\chemicaloxidationseven{\chemicaloxidation\relax7} - -\permanent\protected\def\chemicalbar - {\hpack \s!spread .5\emwidth \bgroup - \hss - \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight - \hss - \egroup} - -\appendtoks - \enforced\let |\chemicalbar % \SR{N|NH} - \enforced\let \+\chemicaloxidationplus - \enforced\let \-\chemicaloxidationminus - \enforced\let \[\chemicalforeveropen - \enforced\let \]\chemicalforeverclose - \enforced\let \1\chemicaloxidationone - \enforced\let \2\chemicaloxidationtwo - \enforced\let \3\chemicaloxidationthree - \enforced\let \4\chemicaloxidationfour - \enforced\let \5\chemicaloxidationfive - \enforced\let \6\chemicaloxidationsix - \enforced\let \7\chemicaloxidationseven - \enforced\let \X\chemicaltighttext - \enforced\let \T\chemicaltop - \enforced\let \B\chemicalbottom - \enforced\let \L\chemicalleft - \enforced\let\LC\chemicalleftcentered - \enforced\let \R\chemicalright - \enforced\let\RC\chemicalrightcentered - \enforced\let\TL\chemicaltopleft - \enforced\let\BL\chemicalbottomleft - \enforced\let\TR\chemicaltopright - \enforced\let\BR\chemicalbottomright - \enforced\let\LT\chemicallefttop - \enforced\let\LB\chemicalleftbottom - \enforced\let\RT\chemicalrighttop - \enforced\let\RB\chemicalrightbottom - \enforced\let\SL\chemicalsmashedleft - \enforced\let\SM\chemicalsmashedmiddle - \enforced\let\SR\chemicalsmashedright -\to \everychemical - -% Should these also be defined in lower case, so as to be case independent? - -\appendtoks - \the\everychemical -\to \everystructurechemical - -% inline - -\permanent\protected\def\chemical - {\ifinformula - \expandafter\indisplaychemical - \else - \expandafter\inlinechemical - \fi} - -\permanent\protected\def\indisplaychemical - {\mathstylecommand\displaychemical\inlinechemical\inlinechemical} - -% \permanent\protected\def\inlinechemical#1% -% {\dontleavehmode -% \begingroup -% \scratchcounter\normalmathstyle -% \usechemicalstyleandcolor\c!style\c!color -% \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\clf_inlinechemical{#1}}}% -% \endgroup} - -\permanent\protected\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} - -\permanent\protected\def\inlinechemical#1% - {\dontleavehmode - \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}} - -\permanent\protected\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}] - -\permanent\protected\def\chemicalsinglebond {\chemicalsymbol[i:single]} -\permanent\protected\def\chemicaldoublebond {\chemicalsymbol[i:double]} -\permanent\protected\def\chemicaltriplebond {\chemicalsymbol[i:triple]} -\permanent\protected\def\chemicalgives {\chemicalsymbol[i:gives]} -\permanent\protected\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]} -\permanent\protected\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]} -\permanent\protected\def\chemicalplus {\chemicalsymbol[i:plus]} -\permanent\protected\def\chemicalminus {\chemicalsymbol[i:minus]} -\permanent\protected\def\chemicalequals {\chemicalsymbol[i:equals]} -\permanent\protected\def\chemicalspace {\chemicalsymbol[i:space]} -\permanent\protected\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 - -\permanent\protected\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 - \enforced\let\chemical\formulachemical - \setfalse\c_chem_has_top - \setfalse\c_chem_has_bot} - -\permanent\protected\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]}] - -\permanent\protected\def\formulachemical - {\relax\dotriplegroupempty\chem_formula} - -\def\chem_formula#1#2#3% we could do hboxes and measure - {\ifthirdargument - \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}% - \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}% - \else\ifsecondargument - \chem_formula_top_nop - \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}% - \else - \chem_formula_top_nop - \chem_formula_bot_nop - \fi\fi - \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname - \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}% - \else - \toksapp\t_chem_mid{\molecule{#1}\aligntab}% - \fi} - -\def\chem_formula_mid#1% - {\csname\??chemicalsymbol\detokenize{#1}\endcsname} - -\def\chem_formula_top_nop {\toksapp\t_chem_top{\aligntab}} -\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}} -\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} -\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot} - -\def\chem_formula_top_indeed#1{\strut#1} -\def\chem_formula_bot_indeed#1{\strut#1} - -% Experimental: defaults might change. - -\definefloat - [\v!chemical] - [\v!chemicals] - -\setuplabeltext - [\v!chemical=] - -\setupfloat - [\v!chemical] - [\c!location=\v!here, - \c!inner=\hsize.8\textwidth\dontleavehmode, % brr - \c!align={\v!flushleft,\v!lohi}] - -\setupcaption - [\v!chemical] - [\c!location=\v!right, - \c!distance=\zeropoint, - \c!width=.2\textwidth, - \c!align=\v!flushright] - -% Can be used as for displayed math: \startplaceformula... to display a chemical formula -% or a chemical structure: -% -% \startplacechemical -% \startchemicalformula -% \chemical{2H_2} -% \chemical{PLUS} -% \chemical{O_2} -% \chemical{GIVES} -% \chemical{2H_2O} -% \stopchemicalformula -% \stopplacechemical - -% gone: state option resolution offset (now frame offset) alternative - -\setupchemicalframed - [\c!align=\v!normal, - \c!strut=\v!no, - \c!offset=\v!overlay, - \c!frame=\v!off] - -\definecolor % private color - [chemicalframecolor] - [r=.75,g=.85,b=.95] - -\setupchemical - [\c!frame=, - \c!width=\v!fit, % or unitless number, multiplies scale*unit - \c!height=\v!fit, % or unitless number, multiplies scale*unit - \c!left=\v!fit, % or unitless number, multiplies scale*unit - \c!right=\v!fit, % or unitless number, multiplies scale*unit - \c!top=\v!fit, % or unitless number, multiplies scale*unit - \c!bottom=\v!fit, % or unitless number, multiplies scale*unit - \c!bodyfont=, - \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies unit) - \c!size=\v!medium, - \c!textsize=\v!big, % how is textsize used?? - \c!axis=\v!off, - \c!style=\rm, - \c!rotation=0, % unitless number (interpreted as degrees) - \c!symalign=\v!auto, - \c!location=, % not yet used (was interaction related in mkii) - \c!offset=.25\emwidth, - \c!unit=\emwidth, - \c!factor=3, - \c!color=, - \c!strut=\v!yes, - \c!framecolor=chemicalframecolor, - \c!rulethickness=0.6pt, %1.5\linewidth, - \c!rulecolor=] - -%D Compatibility: - -\definechemical[+R] {\chemical[RR]} -\definechemical[-R] {\chemical[LR]} - -\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]} -\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]} -\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]} -\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]} - -\definechemical[NEWMAN] {\chemical[]} -\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]} -\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]} -\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]} -\definechemical[SIX:FRONT] {\chemical[SIXFRONT]} -\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]} - -\protect \endinput diff --git a/tex/context/base/mkiv/cldf-bas.mkxl b/tex/context/base/mkiv/cldf-bas.mkxl deleted file mode 100644 index 962db5209..000000000 --- a/tex/context/base/mkiv/cldf-bas.mkxl +++ /dev/null @@ -1,19 +0,0 @@ -%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}{} -\registerctxluafile{cldf-prs}{} - -\endinput diff --git a/tex/context/base/mkiv/cldf-com.mkxl b/tex/context/base/mkiv/cldf-com.mkxl deleted file mode 100644 index 7a8f7bf5c..000000000 --- a/tex/context/base/mkiv/cldf-com.mkxl +++ /dev/null @@ -1,19 +0,0 @@ -%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}{} -%registerctxluafile{cldf-ver}{} - -\endinput diff --git a/tex/context/base/mkiv/cldf-ini.mkxl b/tex/context/base/mkiv/cldf-ini.mkxl deleted file mode 100644 index b393eb9b5..000000000 --- a/tex/context/base/mkiv/cldf-ini.mkxl +++ /dev/null @@ -1,45 +0,0 @@ -%D \module -%D [ file=cldf-int, -%D version=2019.01.01, -%D title=\CONTEXT\ Data Macros, -%D subtitle=Integer, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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} - -\newcount\trialtypesettingstate % gets aliased at the Lua end - -\registerctxluafile{cldf-ini}{autosuffix} - -%D With each new update of \MKIV\ we can join Within Temptation in 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: - -% \catcode`=\activecatcode \let\luafunction % saves 10% on the call - -% todo: these can become implementers - -\permanent\protected\def\cldprocessfile#1{\directlua{context.runfile("#1")}} -\permanent \def\cldloadfile #1{\directlua{context.loadfile("#1")}} -\permanent \def\cldloadviafile#1{\directlua{context.loadviafile("#1")}} -\permanent \def\cldcontext #1{\directlua{context(#1)}} -\permanent \def\cldcommand #1{\directlua{context.#1}} - -\endinput diff --git a/tex/context/base/mkiv/cldf-int.lmt b/tex/context/base/mkiv/cldf-int.lmt deleted file mode 100644 index 4f486221b..000000000 --- a/tex/context/base/mkiv/cldf-int.lmt +++ /dev/null @@ -1,252 +0,0 @@ -if not modules then modules = { } end modules ['cldf-int'] = { - version = 1.001, - comment = "companion to cldf-int.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 byte = string.byte -local insert, remove, concat = table.insert, table.remove, table.concat -local unpack, type = unpack or table.unpack, type - -local ctxcatcodes = catcodes.numbers.ctxcatcodes -local context = context -local contextsprint = context.sprint - -local trace_define = false trackers.register("context.define", function(v) trace_define = v end) - -interfaces = interfaces or { } -local implement = interfaces.implement -local estart = interfaces.elements.start -local estop = interfaces.elements.stop - -local scanners = tokens.scanners -local shortcuts = tokens.shortcuts - -local peekchar = scanners.peekchar -local scankey = scanners.key -local scanvalue = scanners.value -local scanskip = scanners.skip - -local open = byte('[') -local close = byte(']') -local equal = byte('=') -local comma = byte(',') - -function scanhash(scanners) - if peekchar() == open then - local data = { } - scanskip() - while true do - local c = peekchar() - if c == comma then - scanskip() - elseif c == close then - scanskip() - break - else - local key = scankey(equal) - if key then - if peekchar() == equal then - scanskip() - if scanners then - local scanner = scanners[key] - if scanner then - data[key] = scanner() - else - data[key] = scanvalue(comma,close) or "" - end - else - data[key] = scanvalue(comma,close) or "" - end - else - break - end - else - break - end - end - end - return data - end -end - -function scanarray() - if peekchar() == open then - local data = { } - local d = 0 - scanskip() - while true do - local c = peekchar() - if c == comma then - scanskip() - elseif c == close then - scanskip() - break - else - local v = scanvalue(comma,close) or "" - d = d + 1 - data[d] = v - end - end - return data - end -end - -shortcuts.scanhash = scanhash -shortcuts.scanarray = scanarray - -scanners.hash = scanhash -scanners.array = scanarray - -local function remap(arguments) - -- backward compatibility - if type(arguments) == "table" then - for i=1,#arguments do - local a = arguments[i] - if type(a) == "table" then - local t = a[2] - arguments[i] = t == "list" and "array" or t - end - end - return arguments - end -end - -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 environment = specification.environment - local arguments = remap(specification.arguments) - if environment then - local starter = specification.starter - local stopper = specification.stopper - if starter and stopper then - implement { - name = estart .. name, - arguments = arguments, - public = true, - protected = true, - actions = starter, - } - implement { - name = estop .. name, - public = true, - protected = true, - actions = stopper, - } - else - -- message - end - end - if not environment or environment == "both" then - local macro = specification.macro - if macro then - implement { - name = name, - arguments = arguments, - public = true, - protected = true, - actions = macro, - } - else - -- message - end - end - else - -- message - end -end - -function interfaces.tolist(t) - if t then - 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,", ") - else - return "" - end -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() --- context.stopnarrower() --- context("stop more") --- 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 --- --- More modern (no need for option or content): --- --- \startluacode --- interfaces.definecommand { --- name = "test", --- arguments = { --- "array", -- or list --- "hash", --- "string", --- "number", --- }, --- macro = test, --- } --- \stopluacode --- diff --git a/tex/context/base/mkiv/cldf-int.mkxl b/tex/context/base/mkiv/cldf-int.mkxl deleted file mode 100644 index a564afc80..000000000 --- a/tex/context/base/mkiv/cldf-int.mkxl +++ /dev/null @@ -1,34 +0,0 @@ -%D \module -%D [ file=cldf-int, -%D version=2019.01.01, -%D title=\CONTEXT\ Data Macros, -%D subtitle=Integer, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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}{autosuffix} - -%D These are user commands so we don't add any protection against overloading -%D here. - -\unprotect - -\permanent\protected\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}} -\permanent\protected\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}} - -\installcorenamespace{datavalue} - -\permanent\protected\def\setdatavalue#1#2% #2 is a number (expression) - {\expandafter\integerdef\csname\??datavalue#1\endcsname\numexpr#2\relax} - -\permanent\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname} -\permanent\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname} - -\protect \endinput diff --git a/tex/context/base/mkiv/cldf-lmt.lmt b/tex/context/base/mkiv/cldf-lmt.lmt deleted file mode 100644 index f3121eadc..000000000 --- a/tex/context/base/mkiv/cldf-lmt.lmt +++ /dev/null @@ -1,949 +0,0 @@ -if not modules then modules = { } end modules ['cldf-lmt'] = { - version = 1.001, - comment = "companion to toks-scn.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local next, load = next, load -local gmatch, gsub, byte = string.gmatch, string.gsub, string.byte - -local setmetatableindex = table.setmetatableindex -local setmetatablenewindex = table.setmetatablenewindex -local serialize = table.serialize -local concat = table.concat - -local random = math.random -local randomseed = math.randomseed -local round = math.round -local abs = math.abs - -local implement = interfaces.implement - -local scanners = tokens.scanners -local scanword = scanners.word -local scanstring = scanners.string -local scanboolean = scanners.boolean -local scandimen = scanners.dimen -local scanfloat = scanners.float -local scaninteger = scanners.integer -local scancardinal = scanners.cardinal -local scannumber = scanners.luanumber -local scanluainteger = scanners.luainteger -local scanluacardinal = scanners.luacardinal -local scanluanumber = scanners.luanumber -local scanargument = scanners.argument -local scantoken = scanners.token -local scancsname = scanners.csname -local scankeyword = scanners.keyword - -local peekchar = scanners.peekchar -local skipnext = scanners.skip - -local getindex = token.get_index - -local texsetdimen = tex.setdimen -local texsetcount = tex.setcount -local texgetcount = tex.getcount -local texget = tex.get - -local values = tokens.values -local none_code = values.none -local integer_code = values.integer -local cardinal_code = values.cardinal -local dimension_code = values.dimension -local skip_code = values.skip -local boolean_code = values.boolean -local float_code = values.float - -local global_code = tex.flagcodes.global - -local context = context - --- variables -- - -local floats = { } -local integers = { } -local cardinals = { } -local numbers = { } - -implement { - name = "luafloat", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - context("%.99g",floats[n] or 0) - else - floats[n] = scanluanumber(true) - -- floats[n] = scanfloat(true) - end - end, -} - -implement { - name = "luainteger", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - context("%i",integers[n] or 0) - else - integers[n] = scanluainteger(true) - end - end, -} - -implement { - name = "luacount", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - return integer_code, integers[n] or 0 - else - integers[n] = scaninteger(true) - end - end, -} - -implement { - name = "luadimen", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - return dimension_code, integers[n] or 0 - else - integers[n] = scandimen(false,false,true) - end - end, -} - -implement { - name = "luacardinal", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - context("%1.0f",cardinals[n] or 0) - else - cardinals[n] = scanluacardinal(true) - end - end, -} - -implement { - name = "luanumber", - public = true, - usage = "value", - actions = function(b) - local n = scanword() - if b == "value" then - context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N - else - -- floats[n] = scanfloat(true) - floats[n] = scanluanumber(true) - end - end, -} - -implement { - name = "luarandom", - public = true, - usage = "value", - actions = function(b) - if b == "value" then - return integer_code, random(scanluainteger(),scanluainteger()) - else - randomseed(scanluainteger(true)) - end - end, -} - -interfaces.floats = floats -interfaces.integers = integers -interfaces.cardinals = cardinals - -interfaces.numbers = table.setmetatableindex(function(t,k) - return floats[k] or integers[k] or cardinals[k] -end) - --- arrays -- - -local arrays = { } - -interfaces.arrays = arrays - -local newindex = lua.newindex - -implement { - name = "newarray", - public = true, - protected = true, - arguments = { { - { "name", "string" }, - { "nx", "integer" }, - { "ny", "integer" }, - { "type", "string" }, - } }, - actions = function(t) - local name = t.name - if t.name then - local nx = t.nx - local ny = t.ny - local ty = t.type or "integer" - local df = nil - if ty == "integer" or ty == "float" or ty == "dimension" then - df = 0 - elseif ty == "boolean" then - df = false - else - ty = nil - end - if nx and ty ~= nil then - local data - if ny then - data = newindex(t.ny) - for i=1,ny do - data[i] = newindex(nx,df) - end - else - data = newindex(nx,df) - end - arrays[name] = data - data.nx = nx - data.ny = ny - data.type = ty - if ty == "integer" then - data.scanner = scaninteger - elseif ty == "boolean" then - data.scanner = scanboolean - elseif ty == "dimension" then - data.scanner = scandimen - elseif ty == "float" then - data.scanner = scanfloat - end - if ty == "integer" then - data.code = integer_code - elseif ty == "boolean" then - data.code = boolean_code - elseif ty == "dimension" then - data.code = dimension_code - elseif ty == "float" then - data.code = float_code - end - end - end - end, -} - -implement { - name = "arrayvalue", - public = true, - usage = "value", - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - local code = a.code - if code == float_code then - context("%.99g",d[x]) - else - return code, d[x] - end - else - d[x] = a.scanner() - end - end - end - end, -} - -implement { - name = "arrayequals", - public = true, - usage = "value", - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - return boolean_code, a.scanner() == d[x] - end - end - end - end, -} - -implement { - name = "arraycompare", - public = true, - usage = "value", - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - local v = a.scanner() - local d = d[x] - if d < v then - return integer_code, 0 - elseif d == v then - return integer_code, 1 - else - return integer_code, 2 - end - end - end - end - end, -} - -implement { - name = "showarray", - public = true, - protected = true, - actions = function() - local name = scanstring() - if name then - inspect(arrays[name]) - end - end, -} - --- expressions -- - -local cache = table.setmetatableindex(function(t,k) - local code = "return function() local n = interfaces.numbers local a = interfaces.arrays return " .. k .. " end" - code = loadstring(code) - if code then - code = code() - end - t[k] = code or false - return code -end) - -table.makeweak(cache) - -implement { - name = "luaexpression", - public = true, - actions = function() - local how = scanword() - local code = cache[scanargument()] - if code then - local result = code() - if result then - if not how then - context(tostring(code())) - elseif how == "float" then - context("%.99g",result) - elseif how == "integer" then - context("%i",round(result)) - elseif how == "cardinal" then - context("%d",abs(round(result))) - elseif how == "dimen" then - context("%p",result) - elseif how == "boolean" then - context("%d",result and 1 or 0) - elseif how == "lua" then - context("%q",result) - else - context(tostring(code())) - end - end - end - end -} - -local dimenfactors = number.dimenfactors - -implement { - name = "nodimen", - public = true, - usage = "value", - actions = function(b) - if b == "value" then - local how = scanword() - local what = scandimen() - if how then - local factor = dimenfactors[how] - if factor then - context("%.6N%s",factor*what,how) - else - return dimension_code, what - end - else - return dimension_code, what - end - else - local t = scantoken() - if t then - local i = getindex(t) - if i then - local d = scandimen(false,false,true) - texsetdimen(i,d) - end - end - end - end, -} - --- experimental: - -local grouped = { } -local slots = { } -local nofslots = 0 -local nofgrouped = 0 - -local getinteger = tokens.getinteger -local setinteger = tokens.setinteger - -local report = logs.reporter("lua table") - -local ctxsprint = context.sprint - --- we could have an extra one that collects all end of grouped actions --- so that we dispose more in one go but it doesn's pay off - -local function newluatable(name,mt,dispose) - local g = { } - local t = slots[nofslots] - slots[nofslots] = false - nofslots = nofslots - 1 - if not t then - nofgrouped = nofgrouped + 1 - t = nofgrouped - end - if mt then - mt = getinteger(name) - if mt then - mt = grouped[mt] - if mt then - setmetatableindex(g,mt) - end - end - end - grouped[t] = g - setinteger(name,t) - -- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll - -- think of something that we can set it at the Lua end. - if dispose then - ctxsprint("\\atendofgrouped{\\disposeluatable\\" .. name .. "}") - end -end - -local function disposeluatable(name) - local t = getinteger(name) - local g = grouped[t] - if g then - grouped[t] = false - nofslots = nofslots + 1 - slots[nofslots] = t - end -end - -local function setluatable(name,kv) - local t = getinteger(name) - local g = grouped[t] - if g and kv then - for k, v in next, kv do - g[k] = v - end - end -end - -local function getfromluatable(name,k) - local t = getinteger(name) - local g = grouped[t] - if g then - local v = g[k] - if v then - context(v) - else - local n = tonumber(k) - if n then - local v = g[n] - if v then - context(v) - end - end - end - end -end - -local function idxfromluatable(name,k) - local t = getinteger(name) - local g = grouped[t] - if g then - local v = g[k] - if v then - context(v) - end - end -end - -local function getluatable(name,k) - local t = getinteger(name) - local g = grouped[t] - if g then - return g - end -end - -local function inspectluatable(name) - local t = getinteger(name) - local g = grouped[t] - if g then - report("%s", serialize(g,'[grouped slot ' .. t .. ']')) - end -end - -local function showluatables() - report("nofgrouped %i, nofslots %i",nofgrouped,nofslots) - for t=1,nofgrouped do - local g = grouped[t] - if g then - report("%s", serialize(g,'[grouped slot ' .. t .. ']')) - end - end -end - -implement { - name = "newluatable", - protected = true, - arguments = "csname", - actions = newluatable, -} - -implement { - name = "useluatable", - protected = true, - arguments = { "csname", true }, - actions = newluatable, -} - -implement { - name = "disposeluatable", - protected = true, - public = true, - arguments = "csname", - actions = disposeluatable, -} - -implement { - name = "inspectluatable", - protected = true, - public = true, - arguments = "csname", - actions = inspectluatable, -} - -implement { - name = "showluatables", - protected = true, - public = true, - actions = showluatables, -} - -implement { - name = "setluatable", - protected = true, - public = true, - arguments = { "csname", "argument" }, - actions = function(name,data) - data = load("return {" .. data .. "}") - if data then - data = data() - if data then - setluatable(name,data) - end - end - end -} - -implement { - name = "getfromluatable", - protected = false, - public = true, - arguments = { "csname", "argument" }, - actions = getfromluatable, -} - -implement { - name = "idxfromluatable", - protected = false, - public = true, - arguments = { "csname", "integer" }, - actions = idxfromluatable, -} - -context.luatables = { - new = function(name) newluatable(name,false,true) end, - use = function(name) useluatable(name,true, true) end, - dispose = disposeluatable, - set = setluatable, - get = getluatable, - getfrom = getfromluatable, - idxfrom = idxfromluatable, - inspect = inspectluatable, - show = showluatables, -} - --- Here's another mechanism ... - -local tables = { } -local stack = setmetatableindex("table") - -interfaces.implement { - name = "droptablegroup", - public = true, - actions = function() - local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() - local s = stack[g] - if s then - for t, data in next, s do - for k, v in next, data do - t[k] = v - end - end - stack[g] = { } - end - end, -} - -local ctx_atendofgroup = context.core.cs.atendofgroup -local ctx_droptablegroup = context.core.cs.droptablegroup - -local function handletable(t,b,array) - if b == "value" then - local k = array and scaninteger() or scanargument() - local v = t[k] - if v then - context(v) - end - else - local data = scanargument() - data = load("return {" .. data .. "}") - if data then - data = data() - if data then - local l = t.level - local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() - local s = stack[g] - local d = s[t] - if not d then - d = { } - s[t] = d - ctx_atendofgroup() - ctx_droptablegroup() - end - for k, v in next, data do - if not d[k] then - d[k] = t[k] - end - t[k] = v - end - -- if b == "global" then - if b and (b & 0x04) ~= 0 then -- or just band(b,0x04) - for k, v in next, stack do - local t = s[t] - if t then - for k, v in next, data do - if t[k] then - t[k] = nil - end - end - end - end - end - end - end - end -end - -local function newtable(array) - local name = scancsname(true) - if not tables[name] then - local t = { } - tables[name] = t - interfaces.implement { - name = name, - public = true, - usage = "value", - actions = function(b) - handletable(t,b,array) - end, - } - else - -- already defined - end -end - -implement { - name = "newhashedtable", - protected = true, - public = true, - actions = newtable, -} - -implement { - name = "newindexedtable", - protected = true, - public = true, - actions = function() newtable(true) end, -} - -context.hashedtables = setmetatableindex(function(t,k) return tables[k] end) -context.indexedtables = context.hashedtables - --- I played with adding bitwise operator to the expr scanners but in the end didn't --- keep the code ... the problem is in what symbols ... so for now a more verbose --- and/or/xor is okay. Extending the expression scanner would add a little overhead --- to all expressions while an logical operator would gain less that 50% so for now --- we don't bother. Providing \ifbitwiseand makes sense for performance reasons as --- if a bit beter than testing the bitwise and with an \ifcase. - -local reporterror = logs.texerrormessage - -local function youcant(cmd) - reporterror("you can't use \\%s this way, it's an integer value", cmd) -end - -implement { - name = "bitwiseset", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - if what == "value" then - return cardinal_code, a - else - youcant("bitwiseset") - end - end -} - -implement { - name = "bitwiseand", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - scankeyword("with") - local b = scancardinal() - if what == "value" then - return cardinal_code, a & b - else - youcant("bitwiseand") - end - end -} - -implement { - name = "bitwiseor", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - scankeyword("with") - local b = scancardinal() - if what == "value" then - return cardinal_code, a | b - else - youcant("bitwiseor") - end - end -} - -implement { - name = "bitwisexor", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - scankeyword("with") - local b = scancardinal() - if what == "value" then - return cardinal_code, a ~ b - else - youcant("bitwisexor") - end - end -} - -implement { - name = "bitwisenot", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - if what == "value" then - return cardinal_code, ~a & 0xFFFFFFFF - else - youcant("bitwisenot") - end - end -} - -implement { - name = "bitwisenil", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - scankeyword("with") - local b = scancardinal() - if what == "value" then - return cardinal_code, a & (~b & 0xFFFFFFFF) - else - youcant("bitwisenil") - end - end -} - -implement { - name = "bitwiseshift", - public = true, - usage = "value", - actions = function(what) - local a = scancardinal() - scankeyword("by") - local b = scaninteger() - if what == "value" then - return cardinal_code, (b < 0) and (a << -b) or (a >> b) - else - youcant("bitwiseshift") - end - end -} - -implement { - name = "bitwiseflip", - public = true, - usage = "value", - actions = function(what) - local t = scancsname() - local b = scaninteger() - local c = texgetcount(t) - if c then - if b > 0 then - c = c | b - elseif b < 0 then - c = c & (~(-b) & 0xFFFFFFFF) - end - if what == "value" then - return cardinal_code, c - elseif what and (what & global_code) ~= 0 then - texsetcount("global",t,c) - else - texsetcount(t,c) - end - end - end -} - -implement { - name = "ifbitwiseand", - public = true, - usage = "condition", - actions = function(what) - local a = scancardinal() - local b = scancardinal() - return boolean_code, (a & b) ~= 0 - end -} - -interfaces.implement { - name = "bitwise", - public = true, - usage = "value", - actions = function(what) - if what == "value" then - local b = 0 - while true do - local c = peekchar() - if c == 48 or c == 49 then - skipnext() - b = (b << 1) + (c - 48) - if b == 0xFFFFFFFF then - break - end - else - break - end - end - return 1, b - else - local b = scancardinal() - local t = nil - local n = 0 - for i=1,32 do - if (b & (0x100000000 >> i)) == 0 then - if n > 0 then - n = n + 1 - t[n] = "0" - end - elseif t then - n = n + 1 - t[n] = "1" - else - n = 1 - t = { "1" } - end - end - context(n > 0 and table.concat(t) or "0") - end - end, -} - --- something to play with, this might move to syst-aux.lmt when we have that - -local escape = function(s) return "\\" .. byte(s) end - -interfaces.implement { - name = "ctxluamatch", - public = true, - usage = "value", - actions = function() - local command = context[scancsname()] - local pattern = gsub(scanstring(),"\\.",escape) - local input = gsub(scanstring(),"\\.",escape) - for a, b, c, d, e, f, g, h, i in gmatch(input,pattern) do - command(a, b or "", c or "", d or "", e or "", f or "", g or "", h or "", i or "") - end - return none_code - end, -} diff --git a/tex/context/base/mkiv/cldf-ver.mkxl b/tex/context/base/mkiv/cldf-ver.mkxl deleted file mode 100644 index 0ff63810e..000000000 --- a/tex/context/base/mkiv/cldf-ver.mkxl +++ /dev/null @@ -1,18 +0,0 @@ -%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}{} - -\endinput diff --git a/tex/context/base/mkiv/colo-ext.mkxl b/tex/context/base/mkiv/colo-ext.mkxl deleted file mode 100644 index df2d9d768..000000000 --- a/tex/context/base/mkiv/colo-ext.mkxl +++ /dev/null @@ -1,99 +0,0 @@ -%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 devices, we want to reverse -%D the color scheme. Instead of recalculating all those colors, we use a quick and -%D dirty approach: -%D -%D \starttyping -%D \negativecolorbox0 -%D \stoptyping -%D -%D will negate the colors in box zero. - -\permanent\protected\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 or -%D independent. For the moment we only support independent overprint handling. Here -%D we deal with a per-document setting. - -%D We can move the stack and attribute setting to the \LUA\ end. - -\installcorenamespace{colorintent} - -\permanent\protected\def\registercolorintent#1#2% \relax is needed ! - {\setevalue{\??colorintent#1}{\c_attr_colorintent\clf_registercolorintent{#2}\relax}} - -\protected\def\colo_intents_set - {\clf_enablecolorintents - \protected\gdef\colo_intents_set##1{\csname\??colorintent##1\endcsname}% - \colo_intents_set} - -\registercolorintent{knockout} {knockout} -\registercolorintent{overprint}{overprint} - -\installattributestack\colorintentattribute - -\setevalue{\??colorintent\v!none}{\c_attr_colorintent\attributeunsetvalue} % or reset? used at all? - -\permanent\protected\def\startcolorintent[#1]% - {\pushattribute\colorintentattribute - \colo_intents_set{#1}} - -\permanent\protected\def\stopcolorintent - {\popattribute\colorintentattribute} - -\permanent\protected\def\startoverprint{\startcolorintent[\v!overprint]} -\permanent\protected\def\startknockout {\startcolorintent[\v!knockout ]} - -\aliased\let\stopoverprint\stopcolorintent -\aliased\let\stopknockout \stopcolorintent - -\aliased\let\starttextcolorintent\relax -\aliased\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 - \enforced\protected\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/tex/context/base/mkiv/colo-grp.mkxl b/tex/context/base/mkiv/colo-grp.mkxl deleted file mode 100644 index 82dd67959..000000000 --- a/tex/context/base/mkiv/colo-grp.mkxl +++ /dev/null @@ -1,163 +0,0 @@ -%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 which is why we -%D 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 ordening, which in turn is -%D 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 defining each color -%D separate, it also loads faster and takes less bytes. - -\installcorenamespace{colorgroup} -\installcorenamespace{colorgroupsetter} - -\newcount\c_colo_groups_n % scratch counter - -\permanent\tolerant\protected\def\definecolorgroup[#1]#*[#2]#*[#3]% % sort of obsolete, just use palets directly - {\ifarguments\or\or - \ifhastok:{#2}% - \colo_groups_define_normal[#1][\v!rgb][#2] - \else - \colo_groups_define_checked[#1][#2][]% - \fi - \else - \colo_groups_define_normal[#1][#2][#3]% - \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]% - {\doloop % inherited - {\ifcsname#2:##1\endcsname - \definecolor[#1:##1][#2:##1]% - \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!colo_run - -%D There are ten predefined color groups, like \color [green] {\em groen}, \color -%D [red] {\em rood}, \color [blue] {\em blauw}, \color [cyan] {\em cyaan}, \color -%D [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 zeta}. As long as we -%D don't use colors from the same row, we get ourselves distinctive palets. By -%D activating such a palet one gains access to its members {\em top} to {\em charm} -%D (of 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 components are shown too. -%D When printed in color, these 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!colo_run - -\protect \endinput diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl deleted file mode 100644 index 21d5d5aba..000000000 --- a/tex/context/base/mkiv/colo-ini.mkxl +++ /dev/null @@ -1,1370 +0,0 @@ -%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. - -\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. - -\installcorenamespace{color} -\installcorenamespace{colorattribute} -\installcorenamespace{transparencyattribute} -\installcorenamespace{colorsetter} -\installcorenamespace{transparencysetter} -\installcorenamespace{colorpaletspecification} -\installcorenamespace{colorpalet} -\installcorenamespace{colorstack} -\installcorenamespace{colorconversions} -\installcorenamespace{colornumber} - -\registerctxluafile{colo-ini}{} -\registerctxluafile{colo-icc}{} - -\unprotect - -%D In \MKIV\ we have independent color, colorspace and transparency but I'm still -%D not sure if I keep it that way as it's probably more efficient to combine them -%D (less attributes and finalizing). If it becomes a bottleneck we can set up a more -%D complex system with one shared attribute for colorspace, color and transparency. -%D -%D When typesetting for paper, we prefer using the \CMYK\ color space, but for -%D on||screen viewing we prefer \RGB\ (the previous implementation supported only -%D this scheme). Independant of such specifications, we support some automatic -%D 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_convert_gray \settrue\c_colo_convert_gray -\newconditional\c_colo_enabled -\newconditional\c_colo_expanded - -\let\m_colo_weight_gray\v!yes - -\let\currentcolormodel \empty -\let\currentcolorname \empty -\let\currentcolorpalet \empty -\let\currentcolorprefix\empty % \currentcolorpalet: - -%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 - -\permanent\protected\def\loadfoundcolorsetfile#1#2% name foundname / not a user command - {\startreadingfile - \startcolorset[#1]% - \input{#2}% - \stopcolorset - \showmessage\m!colors4{#1}% - \stopreadingfile} - -%D \macros -%D {startcolor,stopcolor,color,graycolor} -%D -%D The local and global commands are here just for compatibility 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 - -\protected\def\switchtocolor[#1]{\begincsname#1\endcsname} - -% transparency - -\permanent\protected\def\transparent[#1]% - {\bgroup - \edef\currenttransparencyname{#1}% - % the \relax catches a non existent csname - \ifx\currenttransparencyname\v!reset - \c_attr_transparency\attributeunsetvalue - \else - \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax - \fi - \let\nexttoken} - -\permanent\protected\def\starttransparent[#1]%$ - {\begingroup - \edef\currenttransparencyname{#1}% - \ifx\currenttransparencyname\v!reset - \c_attr_transparency\attributeunsetvalue - \else - \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax - \fi} - -\permanent\protected\def\stoptransparent - {\endgroup} - -% color - -\permanent\protected\def\coloronly[#1]% - {\bgroup - \edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop_only - \else - \colo_helpers_activate_yes_only - \fi - \let\nexttoken} - -\permanent\protected\def\startcoloronly[#1]%$ - {\begingroup - \edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop_only - \else - \colo_helpers_activate_yes_only - \fi} - -\permanent\protected\def\stopcoloronly - {\endgroup} - -% color + transparency - -\permanent\protected\def\color[#1]% - {\bgroup - \edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop - \else - \colo_helpers_activate_yes - \fi - \let\nexttoken} - -\permanent\protected\def\graycolor[#1]% - {\bgroup - \colo_helpers_set_model\s!gray\colo_helpers_activate{#1}% - \let\nexttoken} - -\permanent\protected\def\startcolor[#1]%$ - {\begingroup - \edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop - \else - \colo_helpers_activate_yes - \fi} - -\permanent\protected\def\stopcolor - {\endgroup} - -\permanent\protected\def\colored[#1]% - {\bgroup - \colo_basics_defined_and_activated{#1}% - \let\nexttoken} - -\permanent\protected\def\fastcolored[#1]#2% - {\begingroup % is this command still needed? - \colo_basics_defined_and_activated{#1}% - #2% - \endgroup} - -\permanent\protected\def\directcolored[#1]% - {\colo_basics_defined_and_activated{#1}} - -\permanent\protected\def\fastcolor[#1]#2% - {\begingroup % is this command still needed? - \edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop - \else - \colo_helpers_activate_yes - \fi - #2% - \endgroup} - -\permanent\protected\def\directcolor[#1]% - {\edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - \colo_helpers_activate_nop - \else - \colo_helpers_activate_yes - \fi} - -%D The following command is obsolete: - -\permanent\protected\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} -\permanent\protected\def\stopcolorpage {\stopcolor} - -\permanent\protected\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ... - {\begingroup - \colo_helpers_activate{#1}% - \normalexpanded{\endgroup\edef\noexpand#2{\ifnum\c_attr_color=\attributeunsetvalue\else\number\c_attr_color\fi}}} - -\let\grey\graycolor % these macros are only used in tracing - -%D \macros -%D {startcurrentcolor,stopcurrentcolor} - -\permanent\protected\def\startcurrentcolor{\startcolor[\outercolorname]} -\permanent\protected\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}, which is loaded into -%D the format by default. -%D -%D Some demo palets and groups are defined in \type {colo-imp-dem} which can be -%D loaded with: -%D -%D \starttyping -%D \usecolors[dem] -%D \stoptyping - -\permanent\protected\def\startcolorset[#1]{\clf_startcolorset{#1}} -\permanent\protected\def\stopcolorset {\clf_stopcolorset} -\permanent\protected\def\usecolors [#1]{\clf_usecolors{#1}} - -\aliased\let\setupcolor\usecolors - -\installsetuponlycommandhandler \??color {colors} - -\let\colo_helpers_show_message\gobblethreearguments - -% \newtoks\everysetupcolors - -\let\v_colo_freeze_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!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 - % - \edef\m_colo_weight_gray{\directcolorsparameter\c!factor}% - % - \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 - -\permanent\protected\def\pushcolor[#1]% - {\global\advance\c_colo_nesting\plusone - \edefcsname\??colorstack\number\c_colo_nesting\endcsname - {\c_attr_colormodel \the\c_attr_colormodel - \c_attr_color \the\c_attr_color - \c_attr_transparency\the\c_attr_transparency - \relax}% stack - \colo_helpers_activate{#1}} - -\permanent\protected\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 - -\permanent\protected\def\savecolor - {\c_colo_saved_attribute_color \c_attr_color - \c_colo_saved_attribute_transparency\c_attr_transparency} - -\permanent\protected\def\restorecolor - {\c_attr_color \c_colo_saved_attribute_color - \c_attr_transparency\c_colo_saved_attribute_transparency} - -%D In this documentation we will not go into too much details on palets. Curious -%D users can find more information on this topic in \from[use of color]. -%D -%D At the moment we implemented color in \CONTEXT\ color printing was not yet on the -%D desktop. In spite of this lack our graphics designer made colorfull -%D illustrations. When printed on a black and white printer, distinctive colors can -%D come out equally gray. We therefore decided to use only colors that were -%D distinctive in colors as well as in black and white print. -%D -%D Although none of the graphic packages we used supported logical colors and global -%D color redefition, we build this support into \CONTEXT. This enabled us to -%D experiment and also prepared us for the future. - -%D \macros -%D {definepalet} -%D -%D Colors are grouped in palets. The colors in such a palet can have colorful names, -%D but best is to use names that specify their use, like {\em important} or {\em -%D danger}. As a sort of example \CONTEXT\ has some palets predefined, -%D like:\footnote{At the time I wrote the palet support, I was reading 'A hort -%D history of time' of S.~Hawkins, so that's 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 palet components (not -%D 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 deal with pretty -%D verbatim typesetting. - -\installcorenamespace{paletlist} -\installcorenamespace{paletsize} - -\let\m_colo_palet\relax -\let\c_colo_palet\relax - -\def\colo_palet_allocate#1% - {\letcsname\??paletlist#1\endcsname\empty - \ifcsname\??paletsize#1\endcsname\else - \expandafter\newcount\csname\??paletsize#1\endcsname - \fi} - -\def\colo_palet_prepare#1% - {\edef\colo_palet_name{#1}% - \ifcsname\??paletlist\colo_palet_name\endcsname - \csname\??paletsize\colo_palet_name\endcsname\zerocount - \else - \colo_palet_allocate\colo_palet_name - \fi - \enforced\expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname - \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}} - -\def\colo_palet_extend#1% - {\addtocommalist{#1}\m_colo_palet - \letcsname\??paletlist\colo_palet_name\endcsname\m_colo_palet - %\advance\csname\??paletsize\colo_palet_name\endcsname\plusone - \advance\c_colo_palet\plusone} - -\permanent\protected\def\doifelsecolorpalet#1% - {\ifcsname\??paletlist#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\let\paletlist\empty -\let\paletsize\!!zerocount - -\permanent\protected\def\getpaletlist[#1]% - {\edef\paletlist{\begincsname\??paletlist#1\endcsname}} - -\permanent\protected\def\getpaletsize[#1]% - {\ifcsname\??paletsize#1\endcsname - \edef\paletsize{\the\lastnamedcs}% - \else - \let\paletsize\!!zerocount - \fi} - -\permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% - {\ifarguments - \expandafter\gobblethreearguments - \or - \expandafter\gobblethreearguments - \or - \expandafter\colo_palets_define_a - \or - \expandafter\colo_palets_define_b - \fi{#1}{#2}{#3}} - -\protected\def\colo_palets_define_a#1#2#3% - {\colo_palet_prepare{#1}% - \ifcondition\validassignment{#2}% - \setevalue{\??colorpaletspecification#1}{#2}% - \processcommalist[#2]{\colo_palets_define_one{#1}}% - \orelse\ifcsname\??colorpaletspecification#2\endcsname - \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}\empty}% - \fi} - -\protected\def\colo_palets_define_b#1#2#3% - {\colo_palet_prepare{#1}% - \setevalue{\??colorpaletspecification#1}{#2}% - \colo_palet_extend{#2}% - \colo_palets_define_assign{#1}{#2}{#3}} - -% % or, it being not that critital, just this -% -% \permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% -% {\ifarguments -% \or -% \or -% \colo_palet_prepare{#1}% -% \ifcondition\validassignment{#2}% -% \setevalue{\??colorpaletspecification#1}{#2}% -% \processcommalist[#2]{\colo_palets_define_one{#1}}% -% \orelse\ifcsname\??colorpaletspecification#2\endcsname -% \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}{}}% -% \fi -% \or -% \colo_palet_prepare{#1}% -% \setevalue{\??colorpaletspecification#1}{#2}% -% \colo_palet_extend{#2}% -% \colo_palets_define_assign{#1}{#2}{#3}% -% \fi} - -\def\colo_palets_define_one#1#2% get rid of { } - {\ifcondition\validassignment{#2}% catch empty entries - \colo_palets_define_two{#1}[#2]% - \else - \colo_palets_define_three{#1}{#2}% - \fi} - -\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 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. Setting the current palet is -%D done by: -%D -%D \showsetup{setuppalet} - -\newtoks\everysetuppalet - -% \newtoks\t_colo_prefix % used in mp interface - -\permanent\tolerant\protected\def\setuppalet[#1]% - {\edef\currentcolorpalet{#1}% - \ifempty\currentcolorpalet - % seems to be a reset - \let\currentcolorprefix\empty - %\t_colo_prefix\emptytoks - \orelse\ifcsname\??paletlist\currentcolorpalet\endcsname - \edef\currentcolorprefix{#1:}% - %\t_colo_prefix\expandafter{\currentcolorprefix}% - \else - \colo_helpers_show_message\m!colors7\currentcolorpalet - \let\currentcolorpalet\empty - \let\currentcolorprefix\empty - %\t_colo_prefix\emptytoks - \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!colo_run - -%D \macros -%D {showcolorcomponents} -%D -%D \starttyping -%D \showcolorcomponents[color-1,color-2] -%D \stoptyping - -\fetchruntimecommand \showcolorcomponents \f!colo_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!colo_run - -%D \macros -%D {showcolor} -%D -%D But let's not forget that we also have the more traditional non||related colors. -%D 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!colo_run - -%D It would make sense to put the following code in \type {colo-mps}, but it it -%D rather low level. - -%D \macros -%D {negatecolorcomponent,negatedcolorcomponent} -%D -%D These speak for themselves. See \type {colo-ext} for usage. - -\permanent\protected\def\negatecolorcomponent#1% #1 = \macro - {\edef#1{\clf_negatecolorcomponent{#1}}} - -\permanent\def\negatedcolorcomponent#1% - {\clf_negatecolorcomponent{#1}} - -%D \macros -%D {MPcolor} -%D -%D A very special macro is \type{\MPcolor}. This one can be used to pass a \CONTEXT\ -%D 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 switch, i.e.\ expanded -%D colors. However, predefined colors and palets are no longer expanded (which is -%D what I wanted in the first place). -%D -%D In \MKIV\ we don't support color separation as we might now assume that printing -%D houses have the right programs to do it themselves. If it's ever needed in \MKIV\ -%D It is relatively 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 - -\permanent\protected\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is - {\colo_helpers_set_model{#1}} % only for local usage - -\def\colo_helpers_set_model#1% direct - {\edef\currentcolormodel{#1}% - \clf_setcolormodel{\currentcolormodel}{\m_colo_weight_gray}} % 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 - \orelse\ifconditional\c_colo_cmyk_supported - \colo_helpers_set_model\s!cmyk - \orelse\ifconditional\c_colo_convert_gray - \colo_helpers_set_model\s!gray - \else - \colo_helpers_set_model\s!none - \fi - \orelse\ifconditional\c_colo_convert_gray - \colo_helpers_set_model\s!gray - \else - \colo_helpers_set_model\s!none - \fi} - -%D Currently in mkiv transparency is implemented independent of color. This costs a -%D bit more processing time but gives the possibility to apply transparency -%D independently in the future. Is this useful? If not we may as well combine them -%D again in the future. By coupling we are downward compatible. When we decouple we -%D need to do more tricky housekeeping (e.g. persist color independent -%D 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{c_o_l_o_r} - -\letvalue{\??colorattribute \v_colo_dummy_name}\empty -\letvalue{\??transparencyattribute\v_colo_dummy_name}\empty -\letvalue{\??colorsetter \v_colo_dummy_name}\empty -\letvalue{\??transparencysetter \v_colo_dummy_name}\empty - -\letvalue{\??colorsetter -}\empty % used? -\letvalue{\??transparencysetter-}\empty % used? - -% new: expandable (see tbl) - -\def\colo_helpers_fast_activate - {\ifempty\currentcolorprefix - \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 - \begincsname\??transparencysetter\currentcolorprefix#1\endcsname - \orelse\ifcsname\??colorsetter#1\endcsname - \lastnamedcs - \begincsname\??transparencysetter#1\endcsname - \fi} - -\def\colo_helpers_fast_activate_nop#1% - {\ifcsname\??colorsetter#1\endcsname - \lastnamedcs - \begincsname\??transparencysetter#1\endcsname - \fi} - -\def\colo_helpers_activate_dummy - {\begincsname\??colorsetter \v_colo_dummy_name\endcsname - \begincsname\??transparencysetter\v_colo_dummy_name\endcsname} - -\let\dofastcoloractivation\colo_helpers_fast_activate - -% so far - -\def\colo_helpers_activate#1% two-step is not that much faster but less tracing - {\edef\currentcolorname{#1}% - \ifempty\currentcolorprefix - %\expandafter - \colo_helpers_activate_nop - \else - %\expandafter - \colo_helpers_activate_yes - \fi} - -\def\colo_helpers_activate_yes - {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname - \lastnamedcs - \begincsname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname - \orelse\ifcsname\??colorsetter\currentcolorname\endcsname - \lastnamedcs - \begincsname\??transparencysetter\currentcolorname\endcsname - \fi} - -\def\colo_helpers_activate_nop - {\ifcsname\??colorsetter\currentcolorname\endcsname - \lastnamedcs - \begincsname\??transparencysetter\currentcolorname\endcsname - \fi} - -\def\colo_helpers_activate_yes_only - {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname - \lastnamedcs - \orelse\ifcsname\??colorsetter\currentcolorname\endcsname - \lastnamedcs - \fi} - -\def\colo_helpers_activate_nop_only - {\ifcsname\??colorsetter\currentcolorname\endcsname - \lastnamedcs - \fi} - -\let\dousecolorparameter\colo_helpers_activate - -\permanent\protected\def\dousecolorhashparameter#1#2% - {\ifcsname#1#2\endcsname - \expandafter\dousecolorparameter\csname#1#2\endcsname - \fi} - -\permanent\protected\def\dousecurrentcolorparameter - {\let\currentcolorname\currentcolorparameter % maybe only when success - \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname - \lastnamedcs - \begincsname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname - \orelse\ifcsname\??colorsetter\currentcolorparameter\endcsname - \lastnamedcs - \begincsname\??transparencysetter\currentcolorparameter\endcsname - \fi} - -\let\dosetcolorattribute\dousecolorhashparameter % for a while - -\permanent\protected\def\deactivatecolor % sort of public but a bad name - {\let\currentcolorname\s!black - \c_attr_color \attributeunsetvalue - \c_attr_transparency\attributeunsetvalue} - -% todo: check if color is overloading a non-color command - -% \let\colo_basics_synchronize\gobbleoneargument % used in mp interface -% \let\colo_basics_inherit \gobbletwoarguments % used in mp interface - -\def\colo_basics_allocate#1% - {\expandafter\newcount\csname\??colornumber#1\endcsname - \clf_synccolorcount{#1}\c_syst_last_allocated_count} - -\def\colo_basics_synchronize#1% - {\ifcsname\??colornumber#1\endcsname\else - \colo_basics_allocate{#1}% - \fi - \clf_synccolor{#1}% - %\csname\??colornumber#1\endcsname\csname\??colorattribute#1\endcsname - \lastnamedcs\csname\??colorattribute#1\endcsname} - -\let\colo_basics_inherit\clf_synccolorclone - -\newcount\c_colo_protection - -\permanent\protected\def\startprotectedcolors{\advance\c_colo_protection\plusone } -\permanent\protected\def\stopprotectedcolors {\advance\c_colo_protection\minusone} - -\permanent\tolerant\protected\def\definecolor[#1]#*[#2]% - {\iftok{#1}{#2}% - % maybe a warning - \else - \clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \protected\instance\setvalue{#1}{\colo_helpers_activate{#1}}% - \fi - \fi} - -\permanent\tolerant\protected\def\defineglobalcolor[#1]#*[#2]% - {\iftok{#1}{#2}% - % maybe a warning - \else - \clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% - \fi - \fi} - -\let\definenamedcolor\definecolor - -\def\colo_basics_defined_and_activated#1% - {\clf_defineprocesscolordummy{#1}% we could pass dummy here too - \colo_basics_synchronize{\v_colo_dummy_name}% - \colo_helpers_activate_dummy} - -\permanent\tolerant\protected\def\defineprocesscolor[#1]#*[#2]#*[#3]% - {\ifarguments\or - \colo_basics_define_process_wrapup{#1}\empty - \or - \colo_basics_define_process_wrapup{#1}{#2}% - \or % we could just pass #3 to clf_... also when it's empty ... todo after split - \colo_basics_define_process_wrapup{#1}{\processcolorcomponents{#2},#3}% - \fi} - -\def\colo_basics_define_process_wrapup#1#2% - {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \protected\instance\setvalue{#1}{\colo_helpers_activate{#1}}% - \fi} - -%D Spotcolors used setxvalue but that messes up currentcolor and probably no global -%D is needed either but they are global at the lua end (true argument) so we keep -%D that if only because spot colors often are a document wide property - -\permanent\tolerant\protected\def\definespotcolor[#1]#*[#2]#*[#3]% - {\clf_definespotcolorglobal{#1}{#2}{#3}% - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% - \fi} - -\permanent\tolerant\protected\def\definemultitonecolor[#1]#*[#2]#*[#3]#*[#4]% - {\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}% - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% - \fi} - -%D Transparencies (only): - -\permanent\tolerant\protected\def\definetransparency[#1]#*[#2]% - {\clf_definetransparency{#1}{#2}} - -\permanent\tolerant\protected\def\defineglobaltransparency[#1]#*[#2]% - {\clf_definetransparencyglobal{#1}{#2}} - -% 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. - -\permanent\tolerant\protected\def\defineintermediatecolor[#1]#*[#2]#*[#3] - {\colo_basics_define_intermediate_indeed[#1][#2][#3]} - -\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]% - {\clf_defineintermediatecolor % not global - {#1}% - {#2}% - \rawcolorattribute{#3} % - \rawcolorattribute{#4} % - \rawtransparencyattribute{#3} % - \rawtransparencyattribute{#4} % - {#5}% - \v_colo_freeze_state - \relax - \colo_basics_synchronize{#1}% - \protected\instance\setvalue{#1}{\colo_helpers_activate{#1}}} - -%D Here is a more efficient helper for pgf: -%D -%D \starttyping -%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 command. Later on we will -%D explain the use of palets. We define ourselves a color conditional first. - -\permanent\def\doifelsecolor#1% - {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname - \expandafter\firstoftwoarguments - \orelse\ifcsname\??colorattribute#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\let\doifcolorelse\doifelsecolor - -\permanent\def\doifcolor#1% - {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname - \expandafter\firstofoneargument - \orelse\ifcsname\??colorattribute#1\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -%D \macros -%D {startregistercolor,stopregistercolor,permitcolormode} -%D -%D If you only want to register a color, the switch \type {\ifpermitcolormode} can -%D be used. That way the nested colors know where to go back to. -%D -%D We use these macros for implementing text colors (actually, the first application -%D was in foreground 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} - -\permanent\protected\def\inheritmaintextcolor - {\ifempty\maintextcolor\else\colo_helpers_activate\maintextcolor\fi} - -\permanent\protected\def\onlyinheritmaintextcolor - {\ifempty\maintextcolor - \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} - -\permanent\protected\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}% - \ifempty\p_colo_textcolor - \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{\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} - -\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% - {\ifcondition\validassignment{#3}% \definepalet[test][xx={y=.4}] - \expandafter\colo_palets_define_assign - \orelse\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_basics_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\c_attr_color} % for mpcolor -\setvalue{\??transparencyattribute currentcolor}{\the\c_attr_transparency} % for mpcolor - -\def\colo_helpers_inherited_current_ca#1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi} -\def\colo_helpers_inherited_current_cs#1{\ifcsname\??colorsetter \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorsetter #1\endcsname\lastnamedcs\fi} -\def\colo_helpers_inherited_current_ta#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi} -\def\colo_helpers_inherited_current_ts#1{\ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi} - -%D Low level defs: - -\permanent\protected\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\c_attr_color #2 }} -\permanent\protected\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\c_attr_color #2 }} % was not g -\permanent\protected\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\c_attr_transparency#2 }} -\permanent\protected\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\c_attr_transparency#2 }} - -\permanent\protected\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} -\permanent\protected\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} -\permanent\protected\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} -\permanent\protected\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} - -\permanent\protected\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}} -\permanent\protected\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}} -\permanent\protected\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}} -\permanent\protected\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}} - -%D \macros -%D {colorvalue, grayvalue} -%D -%D We can typeset the color components using \type {\colorvalue} and \type -%D {\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 - -\permanent\def\MPcolor#1% - {\clf_mpcolor - \c_attr_colormodel - \colo_helpers_inherited_current_ca{#1} % - \colo_helpers_inherited_current_ta{#1} } - -\permanent\def\MPcoloronly#1% - {\clf_mpcolor - \c_attr_colormodel - \colo_helpers_inherited_current_ca{#1} % - \zerocount} - -\permanent\def\MPtransparency#1% - {\clf_mpcolor - \zerocount - \zerocount - \colo_helpers_inherited_current_ta{#1} } - -\permanent\def\MPoptions#1% - {\clf_mpoptions - \c_attr_colormodel - \colo_helpers_inherited_current_ca{#1} % - \colo_helpers_inherited_current_ta{#1} } - -\permanent\def\thecolormodelattribute {\the\c_attr_colormodel} - -\permanent\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} -\permanent\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} - -\permanent\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} -\permanent\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} - -\permanent\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}} -\permanent\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}} -\permanent\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}} - -\permanent\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}} -\permanent\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}} -\permanent\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}} - -\permanent\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}} -\permanent\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}} - -\permanent\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}} -\permanent\def\doifelsedrawingblack {\clf_doifelsedrawingblack} - -\aliased\let\doifblackelse \doifelseblack -\aliased\let\doifdrawingblackelse \doifelsedrawingblack - -%D \macros -%D {forcecolorhack} -%D -%D We can out this in front of (for instance) a special and so force color to be -%D 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) - -% \protected\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed ! -% -% I really need to sort this out! - -\permanent\protected\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! - -%D We default to the colors defined in \type {colo-imp-rgb} and support both \RGB\ -%D and \CMYK\ output. Transparencies are defined 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] - -%D Some common ones: - -\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[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:c][g=.75,b=.75,t=.5,a=1] -\definecolor[trace:m][r=.75,b=.75,t=.5,a=1] -\definecolor[trace:y][r=.75,g=.75,t=.5,a=1] -\definecolor[trace:s][s=.75,t=.5,a=1] -\definecolor[trace:d][s=.25,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:dc][g=.75,b=.75,t=.75,a=1] -\definecolor[trace:dm][r=.75,b=.75,t=.75,a=1] -\definecolor[trace:dy][r=.75,g=.75,t=.75,a=1] -\definecolor[trace:ds][s=.75,t=.75,a=1] -\definecolor[trace:dd][s=.25,t=.75,a=1] -\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1] - -\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/tex/context/base/mkiv/cont-cs.mkxl b/tex/context/base/mkiv/cont-cs.mkxl deleted file mode 100644 index 8e5ae567c..000000000 --- a/tex/context/base/mkiv/cont-cs.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-de.mkxl b/tex/context/base/mkiv/cont-de.mkxl deleted file mode 100644 index 579cc88c3..000000000 --- a/tex/context/base/mkiv/cont-de.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-en.mkxl b/tex/context/base/mkiv/cont-en.mkxl deleted file mode 100644 index bfb17ffb3..000000000 --- a/tex/context/base/mkiv/cont-en.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-fil.mkiv b/tex/context/base/mkiv/cont-fil.mkiv index aa7d9ddb3..edef8dbc8 100644 --- a/tex/context/base/mkiv/cont-fil.mkiv +++ b/tex/context/base/mkiv/cont-fil.mkiv @@ -149,9 +149,4 @@ %definefilesynonym [set-13] [setups-proofing] %definefilesynonym [set-15] [setups-generate] -\ifcase\contextlmtxmode \else - \definefilesynonym [ecmascript] [libs-imp-mujs] - \definefilesynonym [zint] [libs-imp-zint] -\fi - \endinput diff --git a/tex/context/base/mkiv/cont-fr.mkxl b/tex/context/base/mkiv/cont-fr.mkxl deleted file mode 100644 index bedae536b..000000000 --- a/tex/context/base/mkiv/cont-fr.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-gb.mkxl b/tex/context/base/mkiv/cont-gb.mkxl deleted file mode 100644 index 464b237da..000000000 --- a/tex/context/base/mkiv/cont-gb.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-it.mkxl b/tex/context/base/mkiv/cont-it.mkxl deleted file mode 100644 index 1702a872f..000000000 --- a/tex/context/base/mkiv/cont-it.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 53f8ab353..6ff794299 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.11.19 11:23} +\newcontextversion{2020.11.23 18:34} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc @@ -35,16 +35,10 @@ \ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi \appendtoks - \enforced\overloaded\let\t\mathtext - \enforced\overloaded\let\w\mathword + \let\t\mathtext + \let\w\mathword \to \everymathematics -\pushoverloadmode - % charts needs these - \overloaded\unletfrozen\name % for now - \overloaded\frozen\let\type\type -\popoverloadmode - %D We're done. \protect \endinput diff --git a/tex/context/base/mkiv/cont-nl.mkxl b/tex/context/base/mkiv/cont-nl.mkxl deleted file mode 100644 index 1f00e7e89..000000000 --- a/tex/context/base/mkiv/cont-nl.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-pe.mkxl b/tex/context/base/mkiv/cont-pe.mkxl deleted file mode 100644 index 82bf73721..000000000 --- a/tex/context/base/mkiv/cont-pe.mkxl +++ /dev/null @@ -1,22 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-ro.mkxl b/tex/context/base/mkiv/cont-ro.mkxl deleted file mode 100644 index 6d636c7dc..000000000 --- a/tex/context/base/mkiv/cont-ro.mkxl +++ /dev/null @@ -1,21 +0,0 @@ -%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.mkxl - -\endinput diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv index fba9cfaa9..12c12e0d9 100644 --- a/tex/context/base/mkiv/cont-run.mkiv +++ b/tex/context/base/mkiv/cont-run.mkiv @@ -53,16 +53,12 @@ \unexpanded\def\blocksynctexfile[#1]% {\processcommacommand{#1}\synctexblockfilename} -\ifcase\contextlmtxmode - \def\continuewhenlmtxmode - {\starttext - \startTEXpage[\c!offset=2ex,\c!foregroundstyle=\tttf]% - This file needs \LuaMetaTeX\ and \ConTeXt\ \LMTX.% - \stopTEXpage - \stoptext - \endinput} -\else - \let\continuewhenlmtxmode\relax -\fi +\def\continuewhenlmtxmode + {\starttext + \startTEXpage[\c!offset=2ex,\c!foregroundstyle=\tttf]% + This file needs \LuaMetaTeX\ and \ConTeXt\ \LMTX.% + \stopTEXpage + \stoptext + \endinput} \protect \endinput diff --git a/tex/context/base/mkiv/cont-yes.mkiv b/tex/context/base/mkiv/cont-yes.mkiv index f9af8fcee..d17c4878c 100644 --- a/tex/context/base/mkiv/cont-yes.mkiv +++ b/tex/context/base/mkiv/cont-yes.mkiv @@ -11,89 +11,6 @@ %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! - -\processjob % from cont-run.lua +\processjob \endinput diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 2331cd2e2..0e8437dc0 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.11.19 11:23} +\edef\contextversion{2020.11.23 18:34} %D Kind of special: @@ -462,8 +462,6 @@ \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} diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl deleted file mode 100644 index e28f32f07..000000000 --- a/tex/context/base/mkiv/context.mkxl +++ /dev/null @@ -1,618 +0,0 @@ -%D \module -%D [ file=context, -%D version=2019.07.24, % 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. - -% http://build.contextgarden.net/waterfall?tag=c/lua(meta)tex - -%D 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 distribution) -%D later on we will calculate a number that can be used by use modules to identify -%D the feature level. Starting with version 2004.8.30 the low level interface is -%D english. Watch out and adapt 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 up and the -%D dependencies are more consistent. Beware, the version number has to match \type -%D {YYYY.MM.DD HH:MM} format. - -\edef\contextformat {\jobname} -\edef\contextversion{2020.11.19 11:23} - -%overloadmode 1 % check frozen / warning -%overloadmode 2 % check frozen / error -%overloadmode 3 % check frozen, primitive, permanent / warning -\overloadmode 4 % check frozen, primitive, permanent / error - -%D Kind of special: - -\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax - -%D For those who want to use this: - -\let\fmtname \contextformat -\let\fmtversion\contextversion - -%D Loading: - -\edef\mksuffix {mkiv} -\edef\contextmark{LMTX} - -\ifx\normalinput\undefined \let\normalinput\input \fi - -\def\loadmarkfile#1{\normalinput{#1.\mksuffix}} -\def\loadmkivfile#1{\normalinput{#1.mkiv}} -\def\loadmkvifile#1{\normalinput{#1.mkvi}} -\def\loadmkxlfile#1{\normalinput{#1.mkxl}} -\def\loadmklxfile#1{\normalinput{#1.mklx}} - -%D First we load the system modules. These implement a lot of manipulation macros. -%D We start with setting up some basic \TEX\ machinery. - -\loadmkxlfile{syst-ini} - -%D We just quit if new functionality is expected. - -\ifnum\luatexversion<200 % also change message - \writestatus{!!!!}{Your luametatex binary is too old, you need at least version 2.00!} - \expandafter\end -\fi - -%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 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} - -% \normaleverypar{\wait} % uncomment for test of funny injections - -%D Now the more fundamental code gets defined. - -\loadmkxlfile{norm-ctx} -\loadmarkfile{syst-pln} -\loadmarkfile{syst-mes} - -\loadmkxlfile{luat-cod} -\loadmarkfile{luat-bas} -\loadmarkfile{luat-lib} -\loadmarkfile{luat-soc} - -\loadmkxlfile{catc-ini} -\loadmkxlfile{catc-act} -\loadmkxlfile{catc-def} -\loadmkxlfile{catc-ctx} -\loadmkxlfile{catc-sym} - -\loadmkxlfile{toks-ini} -\loadmkxlfile{cldf-ini} - -% \tracecatcodetables - -%D From here on we have \unexpanded being \normalprotected, as we already had -%D \type {\unexpanded} long before etex came around. - -\loadmarkfile{luat-ini} -\loadmkxlfile{toks-scn} - -\loadmkxlfile{syst-aux} -\loadmkxlfile{syst-lua} -\loadmkxlfile{syst-con} - -\loadmkxlfile{syst-fnt} -\loadmarkfile{syst-rtp} - -\loadmarkfile{luat-usr} - -\loadmklxfile{file-ini} -\loadmklxfile{file-res} -\loadmkxlfile{file-lib} - -\loadmkxlfile{core-lmt} - -%D This needs more checking for clashes: -%D -%D \starttyping -%D \doifelsefileexists{l-macro-imp-codes-luametatex.lua}{\registerctxluafile{l-macro-imp-codes-luametatex}{}}{} -%D \stoptyping - -\loadmkxlfile{supp-dir} - -\loadmkxlfile{char-utf} -\loadmkxlfile{char-ini} -\loadmkxlfile{char-act} - -\loadmkxlfile{mult-ini} -\loadmkxlfile{mult-sys} -\loadmkxlfile{mult-aux} -\loadmkxlfile{mult-def} -%loadmarkfile{mult-chk} -\loadmklxfile{mult-dim} - -\loadmkxlfile{cldf-int} % interface - -\loadmkxlfile{trac-ctx} % maybe move up - -\loadmarkfile{toks-aux} - -\loadmkxlfile{attr-ini} - -\loadmkxlfile{core-ini} -\loadmkxlfile{core-env} - -\loadmkxlfile{layo-ini} - -\loadmkxlfile{node-ini} - -\loadmkxlfile{cldf-bas} % basics / depends on nodes - -\loadmkxlfile{node-fin} -\loadmkxlfile{node-mig} -%loadmkxlfile{node-pag} - -\loadmkxlfile{driv-ini} - -\loadmkxlfile{back-ini} -\loadmkxlfile{back-res} -\loadmkxlfile{back-trf} -\loadmkxlfile{back-out} - -\loadmkxlfile{attr-col} -\loadmkxlfile{attr-lay} -\loadmkxlfile{attr-neg} -\loadmkxlfile{attr-eff} -\loadmkxlfile{attr-mkr} - -\loadmkxlfile{trac-tex} -\loadmkxlfile{trac-deb} % will move up - -\loadmkxlfile{supp-box} - -\loadmarkfile{supp-ran} -\loadmkxlfile{supp-mat} - -\loadmkxlfile{core-uti} -\loadmklxfile{file-job} - -\loadmkxlfile{anch-pos} - -\loadmkxlfile{typo-ini} -\loadmkxlfile{typo-lin} -\loadmarkfile{typo-bld} % par builders - -\loadmkxlfile{typo-inj} - -\loadmklxfile{file-syn} -\loadmklxfile{file-mod} - -\loadmkxlfile{core-sys} -\loadmkxlfile{core-con} - -\loadmarkfile{cont-fil} - -\loadmkxlfile{regi-ini} -\loadmkxlfile{enco-ini} -\loadmkxlfile{hand-ini} - -\loadmkxlfile{lang-ini} -\loadmarkfile{lang-hyp} % also loads dis -\loadmkxlfile{lang-lab} - -\loadmkxlfile{unic-ini} - -\loadmkxlfile{core-two} -\loadmkxlfile{core-dat} - -\loadmkxlfile{colo-ini} -\loadmkxlfile{colo-grp} % optional -\loadmkxlfile{colo-ext} - -\loadmkxlfile{node-bck} % overloads anch-pgr (experimental and undocumented) - -\loadmarkfile{pack-cut} - -\loadmkxlfile{lang-mis} -\loadmkxlfile{lang-url} -\loadmarkfile{lang-def} - -% \loadmkvifile{file-job} % why so late? - -\loadmkxlfile{symb-ini} % brrr depends on fonts - -\loadmarkfile{sort-ini} - -\loadmkvifile{pack-mis} -\loadmkxlfile{pack-ori} -\loadmkxlfile{pack-rul} -\loadmkxlfile{pack-mrl} -\loadmklxfile{pack-bck} -\loadmarkfile{pack-fen} - -\loadmkxlfile{lxml-ini} -\loadmkxlfile{lxml-sor} - -\loadmkvifile{typo-prc} -\loadmkivfile{typo-plc} - -\loadmklxfile{strc-ini} -\loadmkxlfile{strc-tag} -\loadmkxlfile{strc-doc} -\loadmkxlfile{strc-num} -\loadmkxlfile{strc-mar} -\loadmkxlfile{strc-sbe} -\loadmklxfile{strc-lst} -\loadmkxlfile{strc-sec} -\loadmkxlfile{strc-pag} % hm, depends on core-num -\loadmkxlfile{strc-ren} -%loadmarkfile{strc-xml} -\loadmarkfile{strc-def} % might happen later -\loadmklxfile{strc-ref} -%loadmarkfile{strc-reg} -\loadmklxfile{strc-lev} % experiment - -\loadmkxlfile{spac-hor} -\loadmkxlfile{spac-ali} -\loadmarkfile{spac-flr} -\loadmkxlfile{spac-ver} % beware, hooks into strc-sec -\loadmarkfile{spac-lin} -\loadmarkfile{spac-pag} -\loadmkxlfile{spac-par} -\loadmarkfile{spac-def} -\loadmkvifile{spac-prf} -\loadmkxlfile{spac-grd} - -\loadmklxfile{scrn-ini} -\loadmkvifile{scrn-ref} - -\loadmarkfile{pack-obj} - -\loadmklxfile{strc-itm} - -\loadmklxfile{strc-con} -\loadmklxfile{strc-des} -\loadmklxfile{strc-enu} - -\loadmkxlfile{strc-ind} -\loadmkxlfile{strc-lab} -\loadmkxlfile{strc-syn} - -% \loadmarkfile{core-sys} - -\loadmarkfile{page-var} -\loadmklxfile{page-otr} -\loadmkxlfile{page-ini} -\loadmarkfile{page-ins} -\loadmarkfile{page-fac} -\loadmarkfile{page-brk} -\loadmarkfile{page-col} -\loadmarkfile{page-inf} -\loadmarkfile{page-flt} -\loadmkxlfile{page-bck} -\loadmkxlfile{page-not} -\loadmkxlfile{page-one} -\loadmkxlfile{page-lay} -\loadmkvifile{page-box} -\loadmklxfile{page-txt} -\loadmarkfile{page-sid} % when - -\loadmklxfile{strc-flt} - -\loadmarkfile{page-pst} -\loadmkvifile{page-mbk} -%loadmarkfile{page-mul} % \usecolumns[old-multicolumns] -\loadmarkfile{page-mix} -\loadmarkfile{page-smp} -%loadmarkfile{page-set} % \usecolumns[old-columnsets] -\loadmarkfile{page-cst} -\loadmarkfile{page-pcl} % new -\loadmkxlfile{pack-lyr} -\loadmarkfile{pack-pos} -\loadmkvifile{page-mak} -\loadmkxlfile{page-mcl} - -\loadmkxlfile{strc-reg} % uses mixed columns - -\loadmkvifile{page-lin} -\loadmarkfile{page-par} -\loadmarkfile{typo-pag} -\loadmkxlfile{typo-mar} -\loadmarkfile{typo-itm} - -\loadmarkfile{buff-ini} -\loadmkxlfile{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 - -\loadmkxlfile{strc-blk} - -\loadmarkfile{page-imp} -\loadmkvifile{page-sel} % optional -\loadmkvifile{page-inj} % optional - -\loadmklxfile{scrn-pag} -\loadmkvifile{scrn-wid} -\loadmkvifile{scrn-but} -\loadmkvifile{scrn-bar} - -\loadmarkfile{page-com} % optional (after scrn-pag) - -\loadmkxlfile{strc-bkm} % bookmarks - -\loadmkxlfile{java-ini} - -\loadmkvifile{scrn-fld} -\loadmkvifile{scrn-hlp} - -\loadmkxlfile{char-enc} - -\loadmkvifile{font-lib} % way too late but after language -\loadmklxfile{font-fil} -\loadmkvifile{font-var} -\loadmklxfile{font-fea} -\loadmklxfile{font-mat} -\loadmklxfile{font-ini} -\loadmklxfile{font-sym} -\loadmklxfile{font-sty} -\loadmkvifile{font-set} -\loadmklxfile{font-emp} -\loadmkxlfile{font-pre} -\loadmarkfile{font-unk} -\loadmkxlfile{font-tra} -\loadmkxlfile{font-chk} -\loadmarkfile{font-uni} -\loadmklxfile{font-col} -\loadmkvifile{font-gds} -\loadmklxfile{font-aux} -\loadmkvifile{font-sel} - -\loadmarkfile{typo-tal} -\loadmarkfile{typo-par} % par builders (uses fonts) - -\loadmkxlfile{tabl-com} -%loadmarkfile{tabl-pln} - -\loadmkxlfile{tabl-tab} % thrd-tab stripped and merged - -\loadmkxlfile{tabl-tbl} -\loadmkxlfile{tabl-ntb} -\loadmkxlfile{tabl-nte} -\loadmkxlfile{tabl-ltb} -\loadmkxlfile{tabl-frm} -\loadmkxlfile{tabl-tsp} -\loadmklxfile{tabl-xtb} -\loadmkxlfile{tabl-mis} - -\loadmkxlfile{typo-lan} - -\loadmkxlfile{lxml-css} - -\loadmkxlfile{spac-chr} % depends on fonts - -\loadmkxlfile{blob-ini} - -\loadmkxlfile{trac-vis} -\loadmkxlfile{trac-jus} - -\loadmkxlfile{typo-cln} -\loadmarkfile{typo-wrp} -\loadmarkfile{typo-spa} -\loadmkxlfile{typo-krn} -\loadmklxfile{typo-itc} -\loadmkxlfile{typo-dir} -\loadmkxlfile{typo-brk} -\loadmkxlfile{typo-cap} -\loadmarkfile{typo-dig} -\loadmarkfile{typo-rep} -\loadmkvifile{typo-txt} -\loadmarkfile{typo-drp} -\loadmarkfile{typo-fln} -\loadmarkfile{typo-sus} -\loadmkxlfile{typo-lig} -\loadmarkfile{typo-chr} -\loadmarkfile{typo-rub} -\loadmkivfile{typo-fkr} -\loadmkxlfile{typo-pnc} - -\loadmklxfile{type-ini} -\loadmarkfile{type-set} - -\loadmarkfile{scrp-ini} - -\loadmkxlfile{symb-emj} - -\loadmarkfile{lang-tra} % can be optional (discussion with mm sideeffect) -\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 - -\loadmkxlfile{mlib-ctx} % messy order - -\loadmkxlfile{meta-ini} -\loadmarkfile{meta-tex} -\loadmarkfile{meta-fun} -\loadmkxlfile{meta-pag} -\loadmarkfile{meta-grd} -\loadmarkfile{meta-fnt} -\loadmarkfile{meta-nod} -\loadmarkfile{meta-lua} -\loadmkxlfile{meta-mac} - -\loadmarkfile{page-mrk} % depends on mp - -\loadmarkfile{page-flw} -\loadmkxlfile{page-spr} -\loadmarkfile{page-plg} -\loadmarkfile{page-str} - -\loadmkxlfile{anch-pgr} % can be moved up (nicer for dependencies) -\loadmklxfile{anch-bck} -\loadmkxlfile{anch-tab} % overloads tabl-tbl -\loadmkxlfile{anch-bar} -%loadmkxlfile{anch-snc} % when needed this one will be redone - -\loadmkxlfile{math-ini} % way after font-pre ! -\loadmkxlfile{math-pln} -\loadmarkfile{math-for} -\loadmarkfile{math-def} % also saves some meanings -\loadmkxlfile{math-ali} -\loadmklxfile{math-stc} -\loadmkxlfile{math-frc} -\loadmarkfile{math-mis} -\loadmarkfile{math-scr} -\loadmarkfile{math-int} -\loadmarkfile{math-del} -\loadmkxlfile{math-fen} -\loadmkvifile{math-acc} -\loadmkvifile{math-rad} -\loadmarkfile{math-inl} -\loadmarkfile{math-dis} -%loadmarkfile{math-lan} -\loadmkxlfile{math-toy} - -\loadmkxlfile{strc-mat} - -\loadmkxlfile{chem-ini} -\loadmkxlfile{chem-str} - -\loadmkxlfile{typo-scr} -\loadmkxlfile{phys-dim} - -\loadmkxlfile{node-rul} % beware, defined \underbar so after math -\loadmklxfile{font-sol} % font solutions - -\loadmklxfile{strc-not} -\loadmklxfile{strc-lnt} -\loadmkxlfile{strc-tnt} -\loadmkxlfile{strc-usr} - -\loadmkxlfile{pack-com} -\loadmkxlfile{typo-del} - -\loadmkxlfile{grph-trf} -\loadmkxlfile{grph-inc} -\loadmkxlfile{grph-fig} -\loadmkxlfile{grph-raw} -\loadmkxlfile{grph-rul} -\loadmkxlfile{grph-pat} - -\loadmkxlfile{pack-box} -\loadmkxlfile{pack-bar} -\loadmarkfile{page-app} -\loadmarkfile{meta-fig} - -\loadmarkfile{page-ffl} - -\loadmarkfile{lang-spa} % will become obsolete - -\loadmarkfile{typo-ovl} % fuzzy project (tracing) code - -% old bibtex support: (will be m-oldbibtex.mkiv) - -% \loadmarkfile{bibl-bib} -% \loadmarkfile{bibl-tra} - -% new bibtex support: - -\loadmkxlfile{publ-ini} -\loadmkxlfile{publ-tra} -\loadmkxlfile{publ-xml} -\loadmarkfile{publ-old} - -%loadmarkfile{x-xtag} % no longer preloaded - -\loadmarkfile{meta-xml} - -\loadmarkfile{cont-log} - -\loadmkxlfile{cldf-ver} % verbatim, this can come late -\loadmkxlfile{cldf-com} % commands, this can come late - -\loadmkxlfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace - -\loadmkxlfile{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) - -\loadmkxlfile{driv-shp} - -\loadmkxlfile{back-exp} -\loadmkxlfile{back-pdf} -\loadmkxlfile{back-mps} -\loadmkxlfile{back-lua} - -\loadmkxlfile{mlib-pdf} -\loadmkxlfile{mlib-pps} -\loadmarkfile{meta-pdf} -\loadmarkfile{meta-blb} -\loadmkxlfile{grph-epd} - -\loadmarkfile{math-inc} % an experiment -\loadmkxlfile{publ-inc} % an experiment - -\loadmkxlfile{task-ini} - -\loadmarkfile{syst-cmp} % compatibility stuff moved here - -\loadmkxlfile{libs-ini} - -\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{job.prepare()}% -% \to \everyjob - -% \appendtoks -% \enabletrackers[*]% -% \to \everyjob - -\appendtoks - \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkxl","\contextbanner")}% can become automatic -\to \everydump - -% some day: -% -% \prependtoks -% \overloadmode 255 -% \to \everyjob - -\overloadmode 0 % for now - -\errorstopmode \dump \endinput diff --git a/tex/context/base/mkiv/core-con.mkxl b/tex/context/base/mkiv/core-con.mkxl deleted file mode 100644 index 088a118f2..000000000 --- a/tex/context/base/mkiv/core-con.mkxl +++ /dev/null @@ -1,1013 +0,0 @@ -%D \module -%D [ file=core-con, -%D version=1997.26.08, -%D title=\CONTEXT\ Core Macros, -%D subtitle=Conversion, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Core Macros / Conversion} - -\registerctxluafile{core-con}{} - -% todo: iso date ranges (from/to) - -\unprotect - -\ifdefined\currentlanguage \else \let\currentlanguage\empty \fi -\ifdefined\labeltext \else \let\labeltext \firstofoneargument \fi - -%D This module deals with all kind of conversions from numbers and dates. I -%D considered splitting this module in a support one and a core one, but to keep -%D things simple as well as preserve the overview, I decided against splitting. - -\let\spr\firstofoneargument % separator -\let\stp\firstofoneargument % stopper - -% needed for arab: - -\permanent\protected\def\isolateseparators % even works with list separator overloading - {\def\spr##1{{##1}}% % we can probably best mess around with zwj - \def\stp##1{{##1}}} % and friends - -%D \macros -%D {numbers} -%D -%D First we deal with the dummy conversion of numbers using the \TEX\ primitive -%D \type{\number}. The uppercase alternative is only there for compatibility with -%D the other conversion macros. We could do without \type{#1} but this way we get -%D rid of unwanted braces. For the savety we also define a non||sence uppercase -%D alternative. -%D -%D \showsetup{numbers} -%D -%D \starttyping -%D \def\numbers#1{\number#1} -%D \def\Numbers#1{\number#1} -%D \stoptyping -%D -%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear, -%D unless we use: - -\permanent\def\numbers#1{\purenumber{#1}} -\permanent\def\Numbers#1{\purenumber{#1}} - -%D \macros -%D {romannumerals,Romannumerals} -%D -%D \TEX\ the program uses a rather tricky conversion from numbers to their roman -%D counterparts. This conversion could of course be programmed in \TEX\ itself, but -%D I guess Knuth found the programming trick worth presenting. -%D -%D \showsetup{romannumerals} -%D \showsetup{Romannumerals} - -\permanent\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax} -\permanent\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax} - -%D Arabic etc: - -\permanent\def\abjadnumerals #1{\clf_abjadnumerals \numexpr#1\relax} -\permanent\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax} -\permanent\def\abjadnaivenumerals#1{\clf_alphabetic \numexpr#1\relax{arabic}} % okay? - -\permanent\def\hebrewnumerals #1{\clf_hebrewnumerals\numexpr#1\relax} -\aliased \let\yiddishnumerals \hebrewnumerals - -\permanent\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new -\permanent\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new - -\permanent\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}} -\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}} - -\permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}} -\permanent\def\devanagarinumerals#1{\clf_alphabetic\numexpr#1\relax{devanagari}} -\permanent\def\gurmurkhinumerals #1{\clf_alphabetic\numexpr#1\relax{gurmurkhi}} -\permanent\def\gujaratinumerals #1{\clf_alphabetic\numexpr#1\relax{gujarati}} -\permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}} -\permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}} -\permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}} -\permanent\def\arabicnumerals #1{\clf_alphabetic\numexpr#1\relax{arabic}} -\permanent\def\persiannumerals #1{\clf_alphabetic\numexpr#1\relax{persian}} -\permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}} -\permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}} - -\aliased \let\arabicexnumerals \persiannumerals - -\permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}} -\permanent\def\koreannumeralsp #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}} -\permanent\def\koreannumeralsc #1{\clf_alphabetic\numexpr#1\relax{korean-circle}} - -\aliased \let\koreanparentnumerals \koreannumeralsp -\aliased \let\koreanparenthesisnumerals\koreannumeralsp -\aliased \let\koreancirclenumerals \koreannumeralsc - -\permanent\def\chinesenumerals #1{\clf_chinesenumerals\numexpr#1\relax{normal}} -\permanent\def\chinesecapnumerals#1{\clf_chinesenumerals\numexpr#1\relax{cap}} -\permanent\def\chineseallnumerals#1{\clf_chinesenumerals\numexpr#1\relax{all}} - -%D \macros -%D {character,Character} -%D -%D Converting a number into a character can of course only be done with numbers -%D less or equal to~26. At the cost of much more macros a faster conversion is -%D possible, using: -%D -%D \starttyping -%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}} -%D \stoptyping -%D -%D But we prefer a simpel \type{\case}. -%D -%D \showsetup{character} -%D \showsetup{Character} - -\def\unknowncharacter{-} % else in lists \relax - -\permanent\def\character#1{\clf_character\numexpr#1\relax} -\permanent\def\Character#1{\clf_Character\numexpr#1\relax} - -%D \macros -%D {characters,Characters} -%D -%D Converting large numbers is supported by the next two macros. This time we -%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$. -%D -%D \showsetup{characters} -%D \showsetup{Characters} - -\permanent\def\characters#1{\clf_characters\numexpr#1\relax} -\permanent\def\Characters#1{\clf_Characters\numexpr#1\relax} - -%D \macros -%D {greeknumerals,Greeknumerals} -%D -%D Why should we only honour the romans, and not the greek? - -% \let\greeknumerals\gobbleoneargument -% \let\Greeknumerals\gobbleoneargument - -%D \macros -%D {oldstylenumerals,oldstyleromannumerals} -%D -%D These conversions are dedicated to Frans Goddijn. - -\permanent\protected\def\oldstylenumerals#1% - {\begingroup - \os\number#1% - \endgroup} - -\permanent\protected\def\oldstyleromannumerals#1% will become obsolete - {\dontleavehmode - \hbox\bgroup - \ss\txx - \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}% - \scratchwidth \wd\scratchbox - \scratchheight\ht\scratchbox - \scratchdimen .1\exheight - \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax - \hskip-\scratchwidth - \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen - \hskip-\scratchwidth - \box\scratchbox - \egroup} - -%D \macros -%D {protectconversion} -%D -%D The previous two commands are not robust enough to be passed to \type -%D {\write} en \type{\message}. That's why we introduce: - -\permanent\protected\def\protectconversion - {\let\doconvertcharacters\firstofoneargument} - -%D \macros -%D {normaltime,normalyear,normalmonth,normalday} -%D -%D The last part of this module is dedicated to converting dates. Because we want to -%D use as meaningful commands as possible, and because \TEX\ already uses up some of -%D those, we save the original meanings. - -% \savenormalmeaning\time -% \savenormalmeaning\year -% \savenormalmeaning\month -% \savenormalmeaning\day - -%D \macros -%D {month,MONTH} -%D -%D Converting the month number into a month name is done using a case statement, -%D abstact values and the label mechanism. This way users can easily redefine a -%D label from for instance german into austrian. -%D -%D \starttyping -%D \setuplabeltext [de] [january=J\"anner] -%D \stoptyping -%D -%D Anyhow, the conversion looks like: - -\permanent\protected\def\monthlong #1{\clf_monthname\numexpr#1\relax} -\permanent\protected\def\monthshort#1{\clf_monthmnem\numexpr#1\relax} -\permanent\protected\def\daylong #1{\clf_dayname\numexpr#1\relax} -\permanent\protected\def\dayshort #1{\clf_daymnem\numexpr#1\relax} -\aliased \let\convertmonth\monthlong % for old times sake - -%D We redefine the \TEX\ primitive \type{\month} as: -%D -%D \showsetup{month} -%D \showsetup{MONTH} - -\pushoverloadmode - -\aliased\let\month\monthlong - -\popoverloadmode - -\permanent\protected\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}} -\permanent\protected\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}} -\permanent\protected\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}} - -%D We never explicitly needed this, but Tobias Burnus pointed out that it would be -%D handy to convert to the day of the week. In doing so, we have to calculate the -%D total number of days, taking leapyears into account. For those who are curious: -%D -%D \startitemize[packed] -%D \item years that can be divided by 4 are leapyears -%D \item exept years that can be divided by 100 -%D \item unless years can be divided by 400 -%D \stopitemize - -%D \macros -%D {weekday,WEEKDAY} -%D -%D The first one is sort of redundant. It takes the day number argument. -%D -%D \showsetup{weekday} -%D \showsetup{WEEKDAY} - -\permanent\protected\def\weekday #1{\clf_dayname\numexpr#1\relax} -\permanent\protected\def\WEEKDAY #1{\WORD{\clf_dayname\numexpr#1\relax}} -\permanent\protected\def\DAYLONG #1{\WORD{\clf_dayname\numexpr#1\relax}} -\permanent\protected\def\DAYSHORT#1{\WORD{\clf_daymnem\numexpr#1\relax}} - -%D \macros -%D {getdayoftheweek, dayoftheweek} - -\newcount\normalweekday - -\permanent \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax} % name -\permanent\protected\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number - -%D Using this macro in -%D -%D \startbuffer -%D monday: \dayoftheweek {4} {5} {1992} -%D friday: \dayoftheweek {16} {6} {1995} -%D monday: \dayoftheweek {25} {8} {1997} -%D saturday: \dayoftheweek {30} {8} {1997} -%D tuesday: \dayoftheweek {2} {1} {1996} -%D tuesday: \dayoftheweek {7} {1} {1997} -%D tuesday: \dayoftheweek {13} {1} {1998} -%D friday: \dayoftheweek {1} {1} {2000} -%D \stopbuffer -%D -%D \typebuffer -%D -%D gives -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D The macro \type {\getdayoftheweek} can be used to calculate the number \type -%D {\normalweekday}. - -%D \macros -%D {doifleapyearelse, -%D getdayspermonth} -%D -%D Sometimes we need to know if we're dealing with a leapyear, so here is a -%D testmacro: -%D -%D \starttyping -%D \doifleapyearelse{year}{yes}{no} -%D \stoptyping -%D -%D An example of its use can be seen in the macro -%D -%D \starttyping -%D \getdayspermonth{year}{month} -%D \stoptyping -%D -%D The number of days is available in the macro \type {\numberofdays}. - -\permanent\def\doifelseleapyear#1% expandable check - {\clf_doifelseleapyear\numexpr#1\relax} - -\aliased\let\doifleapyearelse\doifelseleapyear - -\permanent\protected\def\getdayspermonth#1#2% - {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}} - -\permanent\def\dayspermonth#1#2% - {\clf_nofdays\numexpr#1\relax\numexpr#2\relax} - -% \dayoftheweek{2006}{9}{15} -% \doifleapyearelse{2000}{OK}{NOT OK} -% \doifleapyearelse{2100}{NOT OK}{OK} -% \doifleapyearelse{2004}{OK}{NOT OK} -% \doifleapyearelse{2003}{NOT OK}{OK} -% \dayspermonth{2000}{2} -% [\the\normaltime=\the\time] - -%D \macros -%D {currentdate, rawdate, date} -%D -%D We use these conversion macros in the date formatting macro: -%D -%D \showsetup{currentdate} -%D -%D This macro takes care of proper spacing and delivers for instance: -%D -%D \startbuffer -%D \currentdate[weekday,day,month,year] -%D \currentdate[WEEKDAY,day,MONTH,year] -%D \stopbuffer -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D depending of course on the keywords. Here we gave: -%D -%D \typebuffer -%D -%D If needed one can also add non||keywords, like in -%D -%D \startbuffer -%D \currentdate[dd,--,mm,--,yy] -%D \stopbuffer -%D -%D \typebuffer -%D -%D or typeset: \getbuffer. -%D -%D When no argument is passed, the current date is given as specified per -%D language (using \type{\installlanguage}). -%D -%D \showsetup{currentdate} -%D -%D \startbuffer -%D \date -%D \date[d=12,m=12,y=1998][weekday] -%D \date[d=12,m=12,y=1998] -%D \stopbuffer -%D -%D We can also typeset arbitrary dates, using the previous -%D command. -%D -%D \typebuffer -%D -%D The date is specified by one character keys. When no date is given, we get the -%D current date. -%D -%D \startlines -%D \getbuffer -%D \stoplines - -%D \starttabulate[|l|l|] -%D \HL -%D \NC year \NC (\currentdate[year]) \NC\NR -%D \NC yy \NC (\currentdate[yy]) \NC\NR -%D \NC y \NC (\currentdate[y]) \NC\NR -%D \NC Y \NC (\currentdate[Y]) \NC\NR -%D \HL -%D \NC month \NC (\currentdate[month]) \NC\NR -%D \NC mm \NC (\currentdate[mm]) \NC\NR -%D \NC m \NC (\currentdate[m]) \NC\NR -%D \NC M \NC (\currentdate[M]) \NC\NR -%D \HL -%D \NC day \NC (\currentdate[day]) \NC\NR -%D \NC dd \NC (\currentdate[dd]) \NC\NR -%D \NC d \NC (\currentdate[d]) \NC\NR -%D \NC D \NC (\currentdate[D]) \NC\NR -%D \HL -%D \NC weekday \NC (\currentdate[weekday]) \NC\NR -%D \NC w \NC (\currentdate[w]) \NC\NR -%D \NC W \NC (\currentdate[W]) \NC\NR -%D \HL -%D \NC referral \NC (\currentdate[referral]) \NC\NR -%D \HL -%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR -%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR -%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR -%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR -%D \HL -%D \stoptabulate -%D -%D \startbuffer -%D (\currentdate[D,.,M,.,Y]) -%D (\currentdate[day,month,year]) -%D (\currentdate[day,+,month,+,year]) -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D Some indirectness and abstraction: -%D -%D \starttyping -%D \definedate[crap][year] -%D \currentdate[crap] -%D \stoptyping - -\installcorenamespace{date} - -\permanent\tolerant\protected\def\definedate[#1]#*[#2]% - {\ifarguments\else\setvalue{\??date#1}{#2}\fi} - -\def\syst_converters_check_date_specification#1% - {\ifcsname\??date#1\endcsname - \edef#1{\lastnamedcs}% - \fi} - -\newtoks\everycurrentdate - -\permanent\tolerant\protected\def\currentdate[#1]% - {\dontleavehmode - \begingroup - \the\everycurrentdate - \edef\forceddatespecification{#1}% - \syst_converters_check_date_specification\forceddatespecification - \syst_converters_check_date_specification\currentdatespecification - \clf_currentdate - {\forceddatespecification}{\currentdatespecification}{\labellanguage}% - \normalyear\normalmonth\normalday - \endgroup} - -\permanent\tolerant\protected\def\date[#1]#*[#2]% sets the date ! - {\dontleavehmode - \ifparameter#1\or - \begingroup - \letdummyparameter\c!d\normalday - \letdummyparameter\c!m\normalmonth - \letdummyparameter\c!y\normalyear - \getdummyparameters[#1]% - \normalexpanded - {\endgroup - \normalday \number\directdummyparameter\c!d\relax - \normalmonth\number\directdummyparameter\c!m\relax - \normalyear \number\directdummyparameter\c!y\relax}% - \fi - \begingroup - \the\everycurrentdate - \edef\forceddatespecification{#2}% - \syst_converters_check_date_specification\forceddatespecification - \syst_converters_check_date_specification\currentdatespecification - \clf_currentdate - {\forceddatespecification}{\currentdatespecification}{\labellanguage}% - \normalyear\normalmonth\normalday - \endgroup} - -\permanent\def\rawdate[#1]% expandable and no labels - {\clf_currentdate - {#1}{\currentdatespecification}{}% - \normalyear\normalmonth\normalday} - -%D \macros -%D {currenttime} -%D -%D The currenttime is actually the jobtime. You can specify a pattern similar -%D to the previous date macro using the keys \type {h}, \type {m} and a separator. - -\permanent\protected\def\calculatecurrenttime - {\edef\currenthour {\clf_hour }% - \edef\currentminute{\clf_minute}% - \edef\currentsecond{\clf_second}} - -\let\currenthour \!!plusone -\let\currentminute\!!plusone -\let\currentsecond\!!plusone - -% \def\currenttimespecification{h,:,m} - -\permanent\protected\def\currenttime - {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop} - -\protected\def\syst_converters_current_time_yes[#1]% - {\calculatecurrenttime - \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} - -\protected\def\syst_converters_current_time_nop - {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}} - -%D Because we're dealing with dates, we also introduce a few day loops: -%D -%D \starttyping -%D \processmonth{year}{month}{command} -%D \processyear{year}{command}{before}{after} -%D \stoptyping -%D -%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday} -%D can be used for for date manipulations. - -\permanent\protected\def\processmonth#1#2#3% year month command - {\begingroup - \getdayspermonth{#1}{#2}% - \dostepwiserecurse\plusone\numberofdays\plusone - {\normalyear #1\relax - \normalmonth#2\relax - \normalday \recurselevel\relax - #3}% - \endgroup} - -\def\lastmonth{12} % can be set to e.g. 1 when testing - -\permanent\protected\def\processyear#1#2#3#4% year command before after - {\begingroup - \dorecurse\lastmonth - {\normalyear #1\relax - \normalmonth\recurselevel\relax - #3\processmonth\normalyear\normalmonth{#2}#4}% - \endgroup} - -%D \macros -%D {defineconversion, convertnumber} -%D -%D Conversion involves the macros that we implemented earlier in this module. -%D -%D \showsetup{defineconversion} -%D \showsetup{convertnumber} -%D -%D We can feed this command with conversion macros as well as a set of conversion -%D symbols. Both need a bit different treatment. -%D -%D \starttyping -%D \defineconversion [roman] [\romannumerals] -%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$] -%D \stoptyping -%D -%D You can define a language dependent conversion with: -%D -%D \starttyping -%D \defineconversion [en] [whatever] [\something] -%D \stoptyping - -\installcorenamespace {conversion} -\installcorenamespace {conversionarguments} -\installcorenamespace {conversionwords} - -%D It might be better to move more to \LUA\ as we also need conversion there and -%D doublicating logic doesn't make things cleaner. It means that all conversions -%D will get a language argument too. However, we permit definitions at the \TEX\ end -%D so we have to provide some hybrid method. - -% checkedconversion(method,n,language) - -\protected\def\defineconversion - {\dotripleempty\syst_converters_define_conversion} - -\def\syst_converters_define_conversion[#1][#2][#3]% from now on global (maybe local again some day) - {\ifthirdargument - \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}% - \else - \syst_converters_define_conversion_indeed{#1}{#1}{#2}% - \fi} - -\def\syst_converters_define_conversion_indeed#1#2#3% - {\doifelseinstring{,}{\detokenize{#3}} - {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols - \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}} - {\setgvalue{\??conversion#1}{#3}}} - -\def\syst_converters_checked_conversion#1#2% - {\clf_checkedconversion{#1}\numexpr#2\relax} - -%D If a conversion is just a font switch then we need to make sure that the number -%D is indeed ends up as number in the input, so we need to handle the second -%D argument. - -\permanent\def\convertnumber#1#2% expandable - {\csname\??conversionarguments - \ifcsname\??conversion\currentlanguage#1\endcsname1\else - \ifcsname\??conversion #1\endcsname2\else - 3\fi\fi - \endcsname{#1}{\number#2}} - -\protected\def\uconvertnumber % unexpandable - {\convertnumber} - -\setvalue{\??conversionarguments1}#1{\csname\??conversion\currentlanguage#1\endcsname} -\setvalue{\??conversionarguments2}#1{\csname\??conversion #1\endcsname} -\letvalue{\??conversionarguments3}\syst_converters_checked_conversion - -% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check -% if we have definitions that are not matched at the lua end .. eventually we might do -% that when more shows up - -\permanent\def\doifelseconversiondefined#1% expandable - {\ifcsname\??conversion\currentlanguage#1\endcsname - \expandafter\firstoftwoarguments - \orelse\ifcsname\??conversion#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\def\doifelseconversionnumber#1#2% expandable - {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\aliased\let\doifconversiondefinedelse\doifelseconversiondefined -\aliased\let\doifconversionnumberelse \doifelseconversionnumber - -%D Handy. - -\setvalue{\??conversionwords\v!one }{1} -\setvalue{\??conversionwords\v!two }{2} -\setvalue{\??conversionwords\v!three}{3} -\setvalue{\??conversionwords\v!four }{4} -\setvalue{\??conversionwords\v!five }{5} - -%permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi} -\permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi} - -% \defineconversion[ctx][c,o,n,t,e,x,t] -% -% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}} - -%D \macros -%D {ordinalnumber, highordinalstr, ordinalstr} -%D -%D Efficient general ordinal number converters are sometimes difficult to -%D implement. Fortunately dates never exceed the number~31. - -\permanent\def\highordinalstr#1{\high{\notsmallcapped{#1}}} -\permanent\def\ordinalstr #1{\notsmallcapped{#1}} -\permanent\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}} -\permanent\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}} - -\permanent\def\verbosenumber#1{\clf_verbose\numexpr#1\relax{\currentlanguage}} -\permanent\def\VerboseNumber#1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}}} - -%D As longs as symbols are linked to levels or numbers, we can also use the -%D conversion mechanism, but in for instance the itemization macros, we prefer -%D symbols because they can more easier be (partially) redefined. Symbols are -%D implemented in another module. - -\permanent\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}} -\permanent\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}} - -\defineconversion [] [\numbers] % the default conversion -\defineconversion [\v!empty] [\gobbleoneargument] -\defineconversion [\v!none] [\numbers] -\defineconversion [\s!default] [\numbers] - -\defineconversion [month] [\monthlong] -\defineconversion [month:mnem] [\monthshort] - -\defineconversion [\v!character] [\character] -\defineconversion [\v!Character] [\Character] - -\defineconversion [\v!characters] [\characters] -\defineconversion [\v!Characters] [\Characters] - -\defineconversion [a] [\alphabeticnumerals] -\defineconversion [A] [\Alphabeticnumerals] -\defineconversion [AK] [\smallcappedcharacters] -\defineconversion [KA] [\smallcappedcharacters] - -\defineconversion [\v!alphabetic] [\alphabeticnumerals] -\defineconversion [\v!Alphabetic] [\Alphabeticnumerals] - -\defineconversion [\v!number] [\numbers] -\defineconversion [\v!numbers] [\numbers] -\defineconversion [\v!Numbers] [\Numbers] -\defineconversion [\v!mediaeval] [\mediaeval] - -\defineconversion [\v!word] [\verbosenumber] -\defineconversion [\v!words] [\verbosenumber] - -\defineconversion [\v!Word] [\VerboseNumber] -\defineconversion [\v!Words] [\VerboseNumber] - -\defineconversion[\v!ordinal] [\ordinalnumber] -\defineconversion[\v!Ordinal] [\Ordinalnumber] - -\defineconversion [n] [\numbers] -\defineconversion [N] [\Numbers] -\defineconversion [m] [\mediaeval] -\defineconversion [o] [\oldstylenumerals] -\defineconversion [O] [\oldstylenumerals] -\defineconversion [or] [\oldstyleromannumerals] - -\defineconversion [\v!romannumerals] [\romannumerals] -\defineconversion [\v!Romannumerals] [\Romannumerals] - -\defineconversion [i] [\romannumerals] -\defineconversion [I] [\Romannumerals] -\defineconversion [r] [\romannumerals] -\defineconversion [R] [\Romannumerals] - -\defineconversion [KR] [\smallcappedromannumerals] -\defineconversion [RK] [\smallcappedromannumerals] - -\defineconversion [\v!greek] [\greeknumerals] -\defineconversion [\v!Greek] [\Greeknumerals] - -\defineconversion [g] [\greeknumerals] -\defineconversion [G] [\Greeknumerals] - -%defineconversion [ñ] [\spanishnumerals] -%defineconversion [Ñ] [\Spanishnumerals] - -\defineconversion [abjadnumerals] [\abjadnumerals] -\defineconversion [abjadnodotnumerals] [\abjadnodotnumerals] -\defineconversion [abjadnaivenumerals] [\abjadnaivenumerals] - -\defineconversion [hebrewnumerals] [\hebrewnumerals] -\defineconversion [yiddishnumerals] [\yiddishnumerals] - -% users can do: \defineconversion [he] [\hebrewnumerals] -% users can do: \defineconversion [yi] [\hebrewnumerals] - -\defineconversion [thainumerals] [\thainumerals] -\defineconversion [devanagarinumerals] [\devanagarinumerals] -\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals] -\defineconversion [gujaratinumerals] [\gujaratinumerals] -\defineconversion [tibetannumerals] [\tibetannumerals] -\defineconversion [greeknumerals] [\greeknumerals] -\defineconversion [Greeknumerals] [\Greeknumerals] -\defineconversion [arabicnumerals] [\arabicnumerals] -\defineconversion [persiannumerals] [\persiannumerals] -\defineconversion [arabicexnumerals] [\arabicexnumerals] -\defineconversion [arabicdecimals] [\arabicdecimals] -\defineconversion [persiandecimals] [\persiandecimals] - -\defineconversion [koreannumerals] [\koreannumerals] -\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while) -\defineconversion [koreanparenthesisnumerals] - [\koreanparenthesisnumerals] -\defineconversion [koreancirclenumerals] [\koreancirclenumerals] - -\defineconversion [kr] [\koreannumerals] -\defineconversion [kr-p] [\koreanparentnumerals] -\defineconversion [kr-c] [\koreancirclenumerals] - -\defineconversion [chinesenumerals] [\chinesenumerals] -\defineconversion [chinesecapnumerals] [\chinesecapnumerals] -\defineconversion [chineseallnumerals] [\chineseallnumerals] - -\defineconversion [cn] [\chinesenumerals] -\defineconversion [cn-c] [\chinesecapnumerals] -\defineconversion [cn-a] [\chineseallnumerals] - -%D Moved from lang-def.mkiv: -%D -%D Define these as the general character enumeration when language is Slovenian. If -%D you feel uncomfortable with this, mail Mojca, since she promised to to take the -%D heat. Pablo was next to request this. We changed characters to numerals for this -%D feature. We do need these definitions for mechanisms like itemize that check -%D for converters. - -\permanent\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}} -\permanent\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}} - -\permanent\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}} -\permanent\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}} - -\permanent\def\russiannumerals #1{\clf_alphabetic\numexpr#1\relax{ru}} -\permanent\def\russianNumerals #1{\clf_Alphabetic\numexpr#1\relax{ru}} - -%defineconversion [\s!sl] [character] [\sloveniannumerals] -%defineconversion [\s!sl] [Character] [\slovenianNumerals] -%defineconversion [\s!sl] [characters] [\sloveniannumerals] -%defineconversion [\s!sl] [Characters] [\slovenianNumerals] - -\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals] -\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals] - -\defineconversion [\s!sl] [a] [\sloveniannumerals] -\defineconversion [\s!sl] [A] [\slovenianNumerals] -\defineconversion [\s!sl] [AK] [\smallcapped\sloveniannumerals] -\defineconversion [\s!sl] [KA] [\smallcapped\sloveniannumerals] - -%defineconversion [\s!es] [character] [\spanishnumerals] -%defineconversion [\s!es] [Character] [\spanishNumerals] -%defineconversion [\s!es] [characters] [\spanishnumerals] -%defineconversion [\s!es] [Characters] [\spanishNumerals] - -\defineconversion [\s!es] [alphabetic] [\spanishnumerals] -\defineconversion [\s!es] [Alphabetic] [\spanishNumerals] - -\defineconversion [\s!es] [a] [\spanishnumerals] -\defineconversion [\s!es] [A] [\spanishNumerals] -\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals] -\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals] - -%defineconversion [\s!ru] [character] [\russiannumerals] -%defineconversion [\s!ru] [Character] [\russianNumerals] -%defineconversion [\s!ru] [characters] [\russiannumerals] -%defineconversion [\s!ru] [Characters] [\russianNumerals] - -\defineconversion [\s!ru] [alphabetic] [\russiannumerals] -\defineconversion [\s!ru] [Alphabetic] [\russianNumerals] - -\defineconversion [\s!ru] [a] [\russiannumerals] -\defineconversion [\s!ru] [A] [\russianNumerals] -\defineconversion [\s!ru] [AK] [\smallcapped\russiannumerals] -\defineconversion [\s!ru] [KA] [\smallcapped\russiannumerals] - -\defineconversion [sloveniannumerals] [\sloveniannumerals] -\defineconversion [slovenianNumerals] [\slovenianNumerals] - -\defineconversion [spanishnumerals] [\spanishnumerals] -\defineconversion [spanishNumerals] [\spanishNumerals] - -\defineconversion [russiannumerals] [\russiannumerals] -\defineconversion [russianNumerals] [\russianNumerals] - -%D In case a font has no greek (WS): - -\defineconversion [mathgreek] - [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ}, - \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ}, - \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ}, - \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}] - -%D Handy too (expanded!): - -\permanent\def\unihex#1{\clf_unihex\numexpr#1\relax} - -%D Symbol sets: - -\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo - -% \defineconversion -% [set 0] -% [{\symbol[bullet]}, -% {\symbol[dash]}, -% {\symbol[star]}, -% {\symbol[triangle]}, -% {\symbol[circle]}, -% {\symbol[medcircle]}, -% {\symbol[bigcircle]}, -% {\symbol[square]}, -% {\symbol[checkmark]}] - -% \defineconversion -% [set 1] -% [\mathematics{\star}, -% \mathematics{\star\star}, -% \mathematics{\star\star\star}, -% \mathematics{\ddagger}, -% \mathematics{\ddagger\ddagger}, -% \mathematics{\ddagger\ddagger\ddagger}, -% \mathematics{\ast}, -% \mathematics{\ast\ast}, -% \mathematics{\ast\ast\ast}] -% -% \defineconversion -% [set 2] -% [\mathematics{\ast}, -% \mathematics{\dag}, -% \mathematics{\ddag}, -% \mathematics{\ast\ast}, -% \mathematics{\dag\dag}, -% \mathematics{\ddag\ddag}, -% \mathematics{\ast\ast\ast}, -% \mathematics{\dag\dag\dag}, -% \mathematics{\ddag\ddag\ddag}, -% \mathematics{\ast\ast\ast\ast}, -% \mathematics{\dag\dag\dag\dag}, -% \mathematics{\ddag\ddag\ddag\ddag}] -% -% \defineconversion -% [set 3] -% [\mathematics{\star}, -% \mathematics{\star\star}, -% \mathematics{\star\star\star}, -% \mathematics{\ddagger}, -% \mathematics{\ddagger\ddagger}, -% \mathematics{\ddagger\ddagger\ddagger}, -% \mathematics{\P}, -% \mathematics{\P\P}, -% \mathematics{\P\P\P}, -% \mathematics{\S}, -% \mathematics{\S\S}, -% \mathematics{\S\S\S}, -% \mathematics{\ast}, -% \mathematics{\ast\ast}, -% \mathematics{\ast\ast\ast}] - -\defineconversion - [set 0] - [\symbol{bullet}, - \symbol{dash}, - \symbol{star}, - \symbol{triangle}, - \symbol{circle}, - \symbol{medcircle}, - \symbol{bigcircle}, - \symbol{square}, - \symbol{checkmark}] - -\defineconversion - [set 1] - [\textormathchars{⋆}, - \textormathchars{⋆⋆}, - \textormathchars{⋆⋆⋆}, - \textormathchars{‡}, - \textormathchars{‡‡}, - \textormathchars{‡‡‡}, - \textormathchars{∗}, - \textormathchars{∗∗}, - \textormathchars{∗∗∗}] - -\defineconversion - [set 2] - [\textormathchars{∗}, - \textormathchars{†}, - \textormathchars{‡}, - \textormathchars{∗∗}, - \textormathchars{††}, - \textormathchars{‡‡}, - \textormathchars{∗∗∗}, - \textormathchars{†††}, - \textormathchars{‡‡‡}, - \textormathchars{∗∗∗∗}, - \textormathchars{††††}, - \textormathchars{‡‡‡‡}] - -\defineconversion - [set 3] - [\textormathchars{⋆}, - \textormathchars{⋆⋆}, - \textormathchars{⋆⋆⋆}, - \textormathchars{‡}, - \textormathchars{‡‡}, - \textormathchars{‡‡‡}, - \textormathchars{¶}, - \textormathchars{¶¶}, - \textormathchars{¶¶¶}, - \textormathchars{§}, - \textormathchars{§§}, - \textormathchars{§§§}, - \textormathchars{∗}, - \textormathchars{∗∗}, - \textormathchars{∗∗∗}] - -%D Iteration of suggestion by WS on mailinglist 2010.12.22: -%D -%D \starttyping -%D \setupfloatsplitting[conversion=continued] -%D \stoptyping - -\permanent\protected\def\continuednumber#1% - {\labeltext{\ifcase#1\or\else\v!continued\fi}} - -\defineconversion - [\v!continued] - [\continuednumber] - -%D Taken from x-asciimath (see digits-001.tex for an example): - -\let\spaceddigitsmethod \empty % alternative methods : 1 default, 2 and 3 only when > 4 -\let\spaceddigitssymbol \empty % extra splitter symbol : {,} -\let\spaceddigitsseparator\empty % separator symbol : {\Uchar{"2008}} - -\permanent\protected\def\spaceddigits#1% - {\clf_spaceddigits - method {\spaceddigitsmethod}% - symbol {\spaceddigitssymbol}% - separator {\spaceddigitsseparator}% - data {#1}% - \relax} - -%D For those who sart counting at zero: -%D -%D \starttyping -%D \defineconversionset [zero] [n,zero] [n] -%D -%D \setuphead [sectionconversionset=zero] -%D -%D \starttext -%D \startchapter [title=Introduction] -%D \startsection [title=First topic] \stopsection -%D \startsection [title=Second topic] \stopsection -%D \stopchapter -%D \stoptext -%D \stoptyping - -\permanent\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax} - -\defineconversion [zero] [\zeronumberconversion] - -\protect \endinput diff --git a/tex/context/base/mkiv/core-ctx.mkxl b/tex/context/base/mkiv/core-ctx.mkxl deleted file mode 100644 index 77fb0f139..000000000 --- a/tex/context/base/mkiv/core-ctx.mkxl +++ /dev/null @@ -1,29 +0,0 @@ -%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}{} - -\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/tex/context/base/mkiv/core-dat.mkxl b/tex/context/base/mkiv/core-dat.mkxl deleted file mode 100644 index 7360a4e46..000000000 --- a/tex/context/base/mkiv/core-dat.mkxl +++ /dev/null @@ -1,110 +0,0 @@ -%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}{} - -\installcorenamespace{dataset} - -\installcommandhandler \??dataset {dataset} \??dataset - -\permanent\tolerant\protected\def\setdataset[#1]#*[#2]#*[#3]% - {\begingroup - \edef\currentdataset{#1}% - \ifparameters\or\or - \clf_setdataset - name {\currentdataset}% - delay {\datasetparameter\c!delay}% - data {#2}% - \relax - \or - \edef\currentdataset{#1}% - \clf_setdataset - name {\currentdataset}% - tag {#2}% - delay {\datasetparameter\c!delay}% - data {#3}% - \relax - \fi - \endgroup} - -\permanent\def\datasetvariable#1#2#3% - {\clf_datasetvariable{#1}{#2}{#3}} - -\installcorenamespace{pagestate} -\installcorenamespace{pagestatecounter} - -\installcommandhandler \??pagestate {pagestate} \??pagestate - -\def\syst_pagestates_allocate - {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname} - -\appendtoks - \syst_pagestates_allocate -\to \everydefinepagestate - -\setuppagestate - [\c!delay=\v!yes] - -\permanent\tolerant\protected\def\setpagestate[#1]#*[#2]% - {\begingroup - \edef\currentpagestate{#1}% - \ifcsname\??pagestatecounter\currentpagestate\endcsname - \scratchcounter\lastnamedcs - \advance\scratchcounter\plusone - \else - \scratchcounter\plusone - \syst_pagestates_allocate - \fi - \global\csname\??pagestatecounter\currentpagestate\endcsname\scratchcounter - \clf_setpagestate - name {\currentpagestate}% - tag {\ifparameter#2\or#2\else\number\scratchcounter\fi}% - delay {\pagestateparameter\c!delay}% - \relax - \endgroup} - -\permanent\protected\def\autosetpagestate#1% - {\syst_pagestates_set[#1]\relax} - -\permanent\def\autopagestatenumber#1{\begincsname\??pagestatecounter#1\endcsname} - -\permanent\def\pagestaterealpage #1#2{\clf_pagestaterealpage {#1}{#2}} -\permanent\def\setpagestaterealpageno#1#2{\clf_setpagestaterealpageno{#1}{#2}} -\permanent\def\pagestaterealpageorder#1#2{\clf_pagestaterealpageorder{#1}#2\relax} - -\permanent\def\autopagestaterealpage #1{\clf_pagestaterealpage {#1}{\number\autopagestatenumber{#1}}} -\permanent\def\setautopagestaterealpageno#1{\clf_setpagestaterealpageno{#1}{\number\autopagestatenumber{#1}}} -\permanent\def\autopagestaterealpageorder#1{\clf_pagestaterealpageorder{#1}\numexpr\autopagestatenumber{#1}\relax} - -\protect diff --git a/tex/context/base/mkiv/core-def.mkxl b/tex/context/base/mkiv/core-def.mkxl deleted file mode 100644 index a413b8738..000000000 --- a/tex/context/base/mkiv/core-def.mkxl +++ /dev/null @@ -1,182 +0,0 @@ -%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 - % - \spac_paragraph_wrap - \spac_paragraph_freeze -\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 - % for the moment here (before doc env) - \setupoutput[pdf]% - % - \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: - -\pushoverloadmode - \frozen\unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg} -\popoverloadmode - -% 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] - -%D Till we fixed all styles: - -\enforced\let\\\crlf % frozen or permanent? - -\protect \endinput diff --git a/tex/context/base/mkiv/core-env.lmt b/tex/context/base/mkiv/core-env.lmt deleted file mode 100644 index 388e96787..000000000 --- a/tex/context/base/mkiv/core-env.lmt +++ /dev/null @@ -1,213 +0,0 @@ -if not modules then modules = { } end modules ['core-env'] = { - version = 1.001, - comment = "companion to core-env.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- maybe this will move to the context name space although the --- plurals are unlikely to clash with future tex primitives --- --- if tex.modes['xxxx'] then .... else .... end - -local rawset = rawset - -local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns - -local context = context -local ctxcore = context.core - -local texgetcount = tex.getcount -local texgetintegervalue = token.get_integer -- todo: in tex namespace - -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex -local setmetatablenewindex = table.setmetatablenewindex -local setmetatablecall = table.setmetatablecall - -local createtoken = token.create -local isdefined = tokens.isdefined - -texmodes = allocate { } tex.modes = texmodes -texsystemmodes = allocate { } tex.systemmodes = texsystemmodes -texconstants = allocate { } tex.constants = texconstants -texconditionals = allocate { } tex.conditionals = texconditionals -texifs = allocate { } tex.ifs = texifs -texisdefined = allocate { } tex.isdefined = texisdefined - -local modes = { } -local systemmodes = { } - --- we could use the built-in tex.is[count|dimen|skip|toks] here but caching --- at the lua end is not that bad (and we need more anyway) - -local cache = tokens.cache - --- we can have a modes cache too - -local commandcodes = tokens.commands -local iftrue = cache["iftrue"].index - --- local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen --- local countcode = cache["scratchcounter"].command -- tokens.commands.register_int --- local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks --- local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue --- local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue --- local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test - --- local types = { --- [dimencode] = "dimen", --- [countcode] = "count", --- [tokencode] = "token", --- [skipcode] = "skip", --- [muskipcode] = "muskip", --- -- [attributecode] = "attribute", --- [conditioncode] = "condition" --- } - -local dimencode = commandcodes.register_dimen -- cache["scratchdimen"] .command -- tokens.commands.register_dimen -local countcode = commandcodes.register_int -- cache["scratchcounter"].command -- tokens.commands.register_int -local tokencode = commandcodes.register_toks -- ["scratchtoks"] .command -- tokens.commands.register_toks -local skipcode = commandcodes.register_glue -- cache["scratchskip"] .command -- tokens.commands.register_glue -local muskipcode = commandcodes.register_mu_glue -- cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue -local conditioncode = commandcodes.if_test -- cache["iftrue"] .command -- tokens.commands.if_test -local integercode = commandcodes.integer - -local types = { - [dimencode] = "dimen", - [countcode] = "count", - [tokencode] = "token", - [skipcode] = "skip", - [muskipcode] = "muskip", - -- [attributecode] = "attribute", - [conditioncode] = "condition", - [integercode] = "integer", -} - -setmetatableindex(texmodes, function(t,k) - local m = systemmodes[k] - if not m then - local n = "mode>" .. k - m = function() return texgetintegervalue(n) == 1 end - rawset(modes,k,m) - end - return m() -end) - -setmetatableindex(texsystemmodes, function(t,k) - local m = systemmodes[k] - if not m then - local n = "mode>*" .. k - m = function() return texgetintegervalue(n) == 1 end - rawset(modes,k,m) - end - return m() -end) - --- also a call method - -context.settrialtypesettingmethod(function() return texsystemmodes.trialtypesetting end) - -setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end) -setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end) -setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end) -setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end) -setmetatablenewindex(texifs, function(t,k) end) - --- if we really need performance we can have a dedicated cache for each --- kind of variable ... maybe we no longer have to cache anyway (in lmtx) - -setmetatableindex(texconstants, function(t,k) - -- return cache[k].command == countcode and texgetcount(k) or 0 - return cache[k].command == integercode and texgetintegervalue(k) or 0 -end) - -setmetatableindex(texconditionals, function(t,k) -- 0 == true - -- return cache[k].command == countcode and texgetcount(k) == 0 - return cache[k].command == integercode and texgetintegervalue(k) == 0 -end) - -setmetatableindex(texifs, function(t,k) - local c = cache[k] - return c.command == conditioncode and c.index == iftrue -end) - -tex.isdefined = isdefined - -function tex.isdimen(name) - local hit = cache[name] - return hit.command == dimencode and hit.index or true -end - -function tex.iscount(name) - local hit = cache[name] - return hit.command == countcode and hit.index or true -end - -function tex.istoken(name) - local hit = cache[name] - return hit.command == tokencode and hit.index or true -end - -function tex.isskip(name) - local hit = cache[name] - return hit.command == skipcode and hit.index or true -end - -function tex.ismuskip(name) - local hit = cache[name] - return hit.command == muskipcode and hit.index or true -end - -function tex.type(name) - return types[cache[name].command] or "macro" -end - -function context.setconditional(name,value) - if value then - ctxcore.settruevalue(name) - else - ctxcore.setfalsevalue(name) - end -end - -function context.setmode(name,value) - if value then - ctxcore.setmode(name) - else - ctxcore.resetmode(name) - end -end - -function context.setsystemmode(name,value) - if value then - ctxcore.setsystemmode(name) - else - ctxcore.resetsystemmode(name) - end -end - -context.modes = texmodes -context.systemmodes = texsystemmodes -context.conditionals = texconditionals --------.constants = texconstants --------.ifs = texifs - -local sep = S("), ") -local str = C((1-sep)^1) -local tag = P("(") * C((1-S(")" ))^1) * P(")") -local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")") - -local pattern = ( - P("lua") * tag / ctxcore.luasetup - + P("xml") * arg / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments - + (P("tex") * tag + str) / ctxcore.texsetup - + sep^1 -)^1 - -interfaces.implement { - name = "autosetups", - actions = function(str) lpegmatch(pattern,str) end, - arguments = "string" -} diff --git a/tex/context/base/mkiv/core-env.mkxl b/tex/context/base/mkiv/core-env.mkxl deleted file mode 100644 index e1a96b35f..000000000 --- a/tex/context/base/mkiv/core-env.mkxl +++ /dev/null @@ -1,770 +0,0 @@ -%D \module -%D [ file=core-env, % was core-new -%D version=1995.01.01, % wrong -%D title=\CONTEXT\ Core Macros, -%D subtitle=New ones, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Core Macros / Environments} - -\registerctxluafile{core-env}{autosuffix} - -\unprotect - -%D Modes: -%D -%D \starttyping -%D \enablemode[screen,paper,bound] -%D -%D \doifmodeelse {paper} {this} {that} -%D \doifmode {paper,screen} {this} -%D \doifnotmode {paper,bound} {that} -%D -%D \startmode [list] -%D \stopmode -%D -%D \startnotmode [list] -%D \stopnotmode -%D \stoptyping -%D -%D system modes have a * as prefix -%D -%D Sometimes, we want to prevent a mode for being set. Think of situations where a -%D style enables a mode, but an outer level style does not want that. Preventing can -%D be considered a permanent disabling on forehand. - -\aliased\let\systemmodeprefix\wildcardsymbol - -% we will have \installcorenamespace{mode} but need some hackery at the lua end then - -% TODO: make them mutable, also at the lua end - -\installcorenamespace{modestack} - -\immutable\def\??mode{mode>} % special namespace, also used at lua end - -\permanent\protected\def\newmode #1{\ifcsname \??mode#1\endcsname\else\resetmode{#1}\fi} -\permanent\protected\def\setmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\plusone} -\permanent\protected\def\resetmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\zerocount} -\permanent\protected\def\globalsetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\plusone} -\permanent\protected\def\globalresetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\zerocount} - -\permanent\protected\def\newsystemmode #1{\ifcsname \??mode\systemmodeprefix#1\endcsname\else\resetsystemmode{#1}\fi} -\permanent\protected\def\setsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} -\permanent\protected\def\resetsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} -\permanent\protected\def\globalsetsystemmode #1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} -\permanent\protected\def\globalresetsystemmode#1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} - -\expandafter \appendtoks - \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\plusone - \luacopyinputnodes\plusone -\to \everysettrialtypesetting - -\expandafter \appendtoks - \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\zerocount - \luacopyinputnodes\zerocount -\to \everyresettrialtypesetting - -\pushoverloadmode \newsystemmode{trialtypesetting} \popoverloadmode - -\the\everyresettrialtypesetting - -% user ones - -\mutable\let\syst_mode_prefix\relax - -\protected\def\preventmode{\unprotect\syst_modes_prevent} -\protected\def\enablemode {\unprotect\syst_modes_enable } -\protected\def\disablemode{\unprotect\syst_modes_disable} - -\protected\def\globalpreventmode{\let\syst_mode_prefix\global\unprotect\syst_modes_prevent} -\protected\def\globalenablemode {\let\syst_mode_prefix\global\unprotect\syst_modes_enable } -\protected\def\globaldisablemode{\let\syst_mode_prefix\global\unprotect\syst_modes_disable} - -\def\syst_modes_prevent[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_prevent_indeed\let\syst_mode_prefix\relax} -\def\syst_modes_enable [#1]{\protect\fastprocesscommacommand[#1]\syst_modes_enable_indeed \let\syst_mode_prefix\relax} -\def\syst_modes_disable[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_disable_indeed\let\syst_mode_prefix\relax} - -\def\syst_modes_prevent_indeed#1% - {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi - \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plustwo} - -\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside - {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi - \ifnum\lastnamedcs=\plustwo\else - \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plusone - \fi} - -\def\syst_modes_disable_indeed#1% - {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi - \ifnum\lastnamedcs=\plustwo\else - \syst_mode_prefix\expandafter\integerdef\lastnamedcs\zerocount - \fi} - -%D If you do a lot of mode testing, it makes sense to define modes (or disable them -%D explicitly if unset. This makes testing twice as fast. Often one enables modes -%D beforehand, in which case \type {\definemode} would reset the mode. The optional -%D second argument \type {keep} will prevent changing the already set mode but defines -%D it when undefined. - -\permanent\protected\def\definemode - {\unprotect - \syst_modes_define} - -\tolerant\def\syst_modes_define[#1]#*[#2]% - {\protect - \edef\m_modes_asked{#2}% - \fastprocesscommacommand[#1]\syst_modes_define_indeed} - -\def\syst_modes_define_indeed#1% - {\ifcsname\??mode#1\endcsname - % already set - \else - \newmode{#1}% - \fi - \ifx\m_modes_asked\v!keep - % not changes, disabled when undefined - \orelse\ifx\m_modes_asked\v!yes - \setmode{#1}% - \else - \resetmode{#1}% - \fi} - -% handy for mp - -\def\booleanmodevalue#1% - {\ifcsname\??mode#1\endcsname - \ifcase\lastnamedcs - \s!false - \or - \s!true - \else - \s!false - \fi - \else - \s!false - \fi} - -% check macros - -\newconditional\c_checked_mode - -% one - -\def\syst_modes_check_indeed#1% - {\ifcsname\??mode#1\endcsname - \ifcase\lastnamedcs\else - \let\syst_modes_check_step\gobbleoneargument - \fi - \fi} - -\def\syst_modes_check_nop#1#2#3% - {\let\syst_modes_check_step\syst_modes_check_indeed - \fastprocesscommacommand[#3]\syst_modes_check_step - \ifx\syst_modes_check_step\gobbleoneargument - \expandafter#1% - \else - \expandafter#2% - \fi} - -\def\syst_modes_check_yes#1#2#3% - {\ifcase\lastnamedcs - \expandafter#2% - \or - \expandafter#1% - \else - \expandafter#2% - \fi} - -\def\syst_modes_check_lr#1#2#3% - {\ifcsname\??mode#3\endcsname - \expandafter\syst_modes_check_yes - \else - \expandafter\syst_modes_check_nop - \fi#1#2{#3}} - -\def\syst_modes_check_ss#1#2[#3]% - {\ifcsname\??mode#3\endcsname - \expandafter\syst_modes_check_yes - \else - \expandafter\syst_modes_check_nop - \fi#1#2{#3}} - -% all - -\def\syst_modes_check_all_indeed#1% - {\ifcsname\??mode#1\endcsname - \ifcase\lastnamedcs - \let\syst_modes_check_all_step\gobbleoneargument - \or - % enabled - \else - \let\syst_modes_check_all_step\gobbleoneargument - \fi - \else - \let\syst_modes_check_all_step\gobbleoneargument - \fi} - -\def\syst_modes_check_all_lr#1#2#3% - {\let\syst_modes_check_all_step\syst_modes_check_all_indeed - \fastprocesscommacommand[#3]\syst_modes_check_all_step - \ifx\syst_modes_check_all_step\gobbleoneargument - \expandafter#2% - \else - \expandafter#1% - \fi} - -\def\syst_modes_check_all_ss#1#2[#3]% - {\let\syst_modes_check_all_step\syst_modes_check_all_indeed - \fastprocesscommacommand[#3]\syst_modes_check_all_step - \ifx\syst_modes_check_all_step\gobbleoneargument - \expandafter#2% - \else - \expandafter#1% - \fi} - -\permanent\protected\def\doifelsemode {\syst_modes_check_lr \firstoftwoarguments \secondoftwoarguments} -\permanent\protected\def\doifmode {\syst_modes_check_lr \firstofoneargument \gobbleoneargument} -\permanent\protected\def\doifnotmode {\syst_modes_check_lr \gobbleoneargument \firstofoneargument} -\permanent\protected\def\startmode {\syst_modes_check_ss \donothing \syst_modes_stop_yes} -\permanent\protected\def\startnotmode {\syst_modes_check_ss \syst_modes_stop_nop \donothing} -\permanent\protected\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments \secondoftwoarguments} -\permanent\protected\def\doifallmodes {\syst_modes_check_all_lr\firstofoneargument \gobbleoneargument} -\permanent\protected\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument \firstofoneargument} -\permanent\protected\def\startallmodes {\syst_modes_check_all_ss\donothing \syst_modes_stop_all_yes} -\permanent\protected\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing} - -\aliased\let\doifmodeelse \doifelsemode -\aliased\let\doifallmodeselse\doifelseallmodes - -\permanent\protected\def\stopmode {} % no relax -\permanent\protected\def\stopnotmode {} % no relax -\permanent\protected\def\stopallmodes {} % no relax -\permanent\protected\def\stopnotallmodes{} % no relax - -\def\syst_modes_stop_yes #1\stopmode {} -\def\syst_modes_stop_nop #1\stopnotmode {} -\def\syst_modes_stop_all_yes#1\stopallmodes {} -\def\syst_modes_stop_all_nop#1\stopnotallmodes{} - -%D Pushing/popping: - -\permanent\protected\def\pushmode[#1]{\expandafter\pushmacro\csname\??mode#1\endcsname} -\permanent\protected\def\popmode [#1]{\expandafter\popmacro \csname\??mode#1\endcsname} - -\permanent\protected\def\pushsystemmode#1{\expandafter\pushmacro\csname\??mode\systemmodeprefix#1\endcsname} -\permanent\protected\def\popsystemmode #1{\expandafter\popmacro \csname\??mode\systemmodeprefix#1\endcsname} - -%D Here is a relatively new variant of mode checking: -%D -%D \starttyping -%D \enablemode[two] -%D -%D \startmodeset -%D [one] {1} -%D [two] {2} -%D [two] {2} -%D [three] {3} -%D [default] {?} -%D \stopmodeset -%D -%D \startmodeset -%D [one] {1} -%D [three] {3} -%D [default] {?} -%D \stopmodeset -%D -%D \startmodeset -%D [one] { -%D \input tufte -%D } -%D [two] { -%D \startmodeset -%D [one] {1} -%D [two] {2} -%D [two] {2} -%D [three] {3} -%D [default] {?} -%D \stopmodeset -%D } -%D [three] { -%D \input zapf -%D } -%D [default] { -%D \input ward -%D } -%D \stopmodeset -%D \stoptyping - -\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped - -\installmacrostack\c_syst_modes_set_done - -\permanent\protected\def\startmodeset - {\push_macro_c_syst_modes_set_done - \setfalse\c_syst_modes_set_done - \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} - -\aliased\let\stopmodeset\relax - -\def\syst_modes_set_start[#1]% - {\edef\m_mode_case{#1}% - \unless\ifx\m_mode_case\s!default - \expandafter\syst_modes_set_check - \orelse\ifconditional\c_syst_modes_set_done - \expandafter\syst_modes_set_quit - \else - \expandafter\syst_modes_set_yes - \fi} - -\def\syst_modes_set_check - {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case} - -\def\syst_modes_set_yes#1% - {\settrue\c_syst_modes_set_done - #1% - \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} - -\def\syst_modes_set_nop#1% - {\doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} - -\def\syst_modes_set_quit#-\stopmodeset - {\pop_macro_c_syst_modes_set_done} - -%D Lets now set a mode: - -\enablemode[mkiv] \newsystemmode{mkiv} \setsystemmode{mkiv} - -%D Setups: - -\installcorenamespace{setup} % we can probably get rid of some :'s later on - -% \protected\def\startsetups{} % to please dep checker -% \protected\def\stopsetups {} % to please dep checker -% -% \protected\def\setups{\doifelsenextbgroup\syst_setups_a\syst_setups_b} % {..} or [..] -% \protected\def\setup {\doifelsenextbgroup\syst_setups \syst_setups_c} % {..} or [..] -% -% \def\syst_setups_a #1{\processcommacommand[#1]\syst_setups} % {..} -% \def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..] -% \def\syst_setups_c[#1]{\syst_setups{#1}} % [..] - -\permanent\protected\tolerant\def\setups[#1]#;#2{\processcommacommand[#1#2]\syst_setups} % {..} or [..] -\permanent\protected\tolerant\def\setup [#1]#;#2{\syst_setups{#1#2}} % {..} or [..] - -\letvalue{\??setup:\??empty}\gobbleoneargument - -\permanent\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: - -\permanent\def\fastsetup #1{\csname\??setup:#1\endcsname\empty} -\permanent\def\fastsetupwithargument #1{\csname\??setup:#1\endcsname} % swapped per 2015-08-30 -\permanent\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 - -\permanent\protected\def\doprocesslocalsetups#1% sort of public, fast local variant - {\edef\m_syst_setups_asked{#1}% - \ifempty\m_syst_setups_asked\else - \expandafter\syst_setups_process_local - \fi} - -\permanent\protected\def\usesetupsparameter#1% - {\edef\m_syst_setups_asked{#1\c!setups}% - \ifempty\m_syst_setups_asked\else - \expandafter\syst_setups_process_local - \fi} - -% setups=S1 -% setups=lua(S2) -% setups=S3 -% setups={S1,lua(S2),xml(test{123}),S3} - -\def\syst_setups_process_local - {\clf_autosetups{\m_syst_setups_asked}% - \relax} % let's prevent lookahead - -\permanent\def\autosetups#1{\clf_autosetups{#1}} % todo: public implementor - -\permanent\edef\setupwithargument#1% saves a few expansions - {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname} - -\permanent\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}} - -\aliased\let\directsetup\syst_setups -\aliased\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup - -\permanent\protected\def\doifelsesetups#1% to be done: grid - {\ifcsname\??setup:#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifsetupselse\doifelsesetups - -\permanent\protected\def\doifsetups#1% to be done: grid - {\ifcsname\??setup:#1\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotsetups#1% to be done: grid - {\ifcsname\??setup:#1\endcsname - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -% maybe some day: -% -% \protected\def\fastsetupfallback#1#2% -% {\ifcsname\??setup:#1\endcsname -% \expandafter\lastnamedcs -% \else -% \csname\??setup:#2\expandafter\endcsname -% \fi} -% -% or -% -% \protected\def\fastsetupfallback#1#2#3% prefix preferred fallback -% {\ifcsname\??setup:#1#2\endcsname -% \expandafter\lastnamedcs -% \else -% \csname\??setup:#1#3\expandafter\endcsname -% \fi} - -% \startluasetups oeps -% context("DONE") -% a = 1 -% b = 1 -% \stopluasetups -% -% \luasetup{oeps} -% -% \startsetups xxx -% ziezo -% \stopsetups -% -% \directsetup{xxx} -% -% \startxmlsetups zzz -% [[#1]] -% \stopxmlsetups -% -% \xmlsetup{123}{zzz} -% -% \startbuffer[what] -% context("DONE") -% \stopbuffer -% -% \startbuffer -% context("MORE") -% \stopbuffer -% -% \ctxluabuffer[what] -% -% \ctxluabuffer - -\newtoks\t_syst_setups_tex \appendtoks - \catcode\endoflineasciicode \ignorecatcode -\to \t_syst_setups_tex - -\newtoks\t_syst_setups_loc \appendtoks - \catcode\endoflineasciicode \ignorecatcode -\to \t_syst_setups_loc - -\newtoks\t_syst_setups_raw \appendtoks - % nothing -\to \t_syst_setups_raw - -\newtoks\t_syst_setups_xml \appendtoks - \catcode\endoflineasciicode\ignorecatcode - \catcode\barasciicode \othercatcode -\to \t_syst_setups_xml - -\newtoks\t_syst_setups_lua \appendtoks - \obeylualines - \obeyluatokens -\to \t_syst_setups_lua - -% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete. - -\permanent\protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_yes\syst_setups_start_lua_nop} \aliased\let\stopluasetups \relax -\permanent\protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_yes\syst_setups_start_xml_nop} \aliased\let\stopxmlsetups \relax -\permanent\protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_yes\syst_setups_start_raw_nop} \aliased\let\stoprawsetups \relax -\permanent\protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_yes\syst_setups_start_loc_nop} \aliased\let\stoplocalsetups\relax -\permanent\protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_yes\syst_setups_start_tex_nop} \aliased\let\stopsetups \relax - -\def\syst_setups_start_lua_two#1#2#+\stopluasetups {\endgroup\dodoglobal\defcsname\??setup#1:#2\endcsname##1{#3}} -\def\syst_setups_start_xml_two#1#2#+\stopxmlsetups {\endgroup\dodoglobal\defcsname\??setup#1:#2\endcsname##1{#3}} -\def\syst_setups_start_raw_two#1#2#+\stoprawsetups {\endgroup\dodoglobal\defcsname\??setup#1:#2\endcsname##1{#3}} -\def\syst_setups_start_loc_two#1#2#+\stoplocalsetups{\endgroup\dodoglobal\defcsname\??setup#1:#2\endcsname##1{#3}} -\def\syst_setups_start_tex_two#1#2#+\stopsetups {\endgroup\dodoglobal\defcsname\??setup#1:#2\endcsname##1{#3}} - -\tolerant\def\syst_setups_start_lua_yes[#1]#*[#2]% - {\the\t_syst_setups_lua - \ifarguments\expandafter\syst_setups_start_lua_one - \or \expandafter\syst_setups_start_lua_one - \else \expandafter\syst_setups_start_lua_two - \fi{#1}{#2}} - -\tolerant\def\syst_setups_start_xml_yes[#1]#*[#2]% - {\the\t_syst_setups_xml - \ifarguments\expandafter\syst_setups_start_xml_one - \or \expandafter\syst_setups_start_xml_one - \else \expandafter\syst_setups_start_xml_two - \fi{#1}{#2}} - -\tolerant\def\syst_setups_start_raw_yes[#1]#*[#2]% - {\the\t_syst_setups_raw - \ifarguments\expandafter\syst_setups_start_raw_one - \or \expandafter\syst_setups_start_raw_one - \else \expandafter\syst_setups_start_raw_two - \fi{#1}{#2}} - -\tolerant\def\syst_setups_start_loc_yes[#1]#*[#2]% - {\the\t_syst_setups_loc - \ifarguments\expandafter\syst_setups_start_loc_one - \or \expandafter\syst_setups_start_loc_one - \else \expandafter\syst_setups_start_loc_two - \fi{#1}{#2}} - -\tolerant\def\syst_setups_start_tex_yes[#1]#*[#2]% - {\the\t_syst_setups_tex - \ifarguments\expandafter\syst_setups_start_tex_one - \or \expandafter\syst_setups_start_tex_one - \else \expandafter\syst_setups_start_tex_two - \fi{#1}{#2}} - -\def\syst_setups_start_lua_nop#1 {\the\t_syst_setups_lua\syst_setups_start_lua_two{}{#1}} % space delimited -\def\syst_setups_start_xml_nop#1 {\the\t_syst_setups_xml\syst_setups_start_xml_two{}{#1}} % space delimited -\def\syst_setups_start_raw_nop#1 {\the\t_syst_setups_raw\syst_setups_start_raw_two{}{#1}} % space delimited -\def\syst_setups_start_loc_nop#1 {\the\t_syst_setups_loc\syst_setups_start_loc_two{}{#1}} % space delimited -\def\syst_setups_start_tex_nop#1 {\the\t_syst_setups_tex\syst_setups_start_tex_two{}{#1}} % space delimited - -\def\syst_setups_start_lua_one#1#2{\syst_setups_start_lua_two{}{#1}} % [..] -\def\syst_setups_start_xml_one#1#2{\syst_setups_start_xml_two{}{#1}} % [..] -\def\syst_setups_start_raw_one#1#2{\syst_setups_start_raw_two{}{#1}} % [..] -\def\syst_setups_start_loc_one#1#2{\syst_setups_start_loc_two{}{#1}} % [..] -\def\syst_setups_start_tex_one#1#2{\syst_setups_start_tex_two{}{#1}} % [..] - -\def\luasetup#1{\ctxlua{\syst_setups{#1}}} - -%D System setups: - -\aliased\let\systemsetupsprefix\wildcardsymbol - -\permanent\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}} - -\permanent\protected\def\resetsetups[#1]% see x-fo for usage - {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname - \dodoglobal\undefinevalue{\??setup\ifgridsnapping\v!grid\fi:#1}% - \else - \dodoglobal\undefinevalue{\??setup:#1}% - \fi} - -\permanent\tolerant\protected\def\copysetups[#1]#*[#2]% - {\ifcsname\??setup:#2\endcsname - \letcsname\??setup:#1\expandafter\endcsname\lastnamedcs - \fi} - -\permanent\protected\def\showsetupsdefinition[#1]% - {\showvalue{\??setup:#1}} % temp hack for debugging - -%D \macros -%D {setvariables,getvariable,getvariabledefault} -%D -%D \starttyping -%D \setvariables[xx][title=] -%D \setvariables[xx][title=test test] -%D \setvariables[xx][title=test $x=1$ test] % fatal error reported -%D \setvariables[xx][title=test {$x=1$} test] -%D \setvariables[xx][title] % fatal error reported -%D \setvariables[xx][titletitel=e] -%D \stoptyping - -\installcorenamespace{variables} - -\permanent\protected\def\setvariables {\syst_variables_set[\getrawparameters ]} -\permanent\protected\def\setevariables{\syst_variables_set[\getraweparameters]} -\permanent\protected\def\setgvariables{\syst_variables_set[\getrawgparameters]} -\permanent\protected\def\setxvariables{\syst_variables_set[\getrawxparameters]} - -\tolerant\def\syst_variables_set[#1]#*[#2]#*[#3]% tricky, test on s-pre-60 - {\doifelse{#2}\currentvariableclass - {#1[\??variables#2:][#3]}% - {\pushmacro\currentvariableclass - \def\currentvariableclass{#2}% - \getvariable{#2}\s!reset - #1[\??variables#2:][#3]% - \getvariable{#2}\s!set - \popmacro\currentvariableclass}} - -\permanent\protected\def\setvariable #1#2#3{\defcsname \??variables#1:#2\endcsname{#3}} -\permanent\protected\def\setevariable#1#2#3{\edefcsname \??variables#1:#2\endcsname{#3}} -\permanent\protected\def\setgvariable#1#2#3{\global\defcsname \??variables#1:#2\endcsname{#3}} -\permanent\protected\def\setxvariable#1#2#3{\global\edefcsname\??variables#1:#2\endcsname{#3}} - -\permanent \def\getvariable #1#2{\begincsname\??variables#1:#2\endcsname} -\permanent\protected\def\showvariable#1#2{\showvalue{\begincsname\??variables#1:#2\endcsname}} - -\let\currentvariableclass\empty - -%D \macros -%D {checkvariables} -%D -%D I'll probably forget that this on exists. - -\let\m_syst_variables_temp\empty - -\permanent\tolerant\def\checkvariables[#1]#*[#2]% - {\dogetparameters\syst_variables_check_value[#1][#2]} - -\def\syst_variables_check_value#1#2#3% - {\ifcsname\??variables#1:#2\endcsname - \edef\m_syst_variables_temp{\lastnamedcs}% - \ifempty\m_syst_variables_temp - \defcsname\??variables#1:#2\endcsname{#3}% - \fi - \else - \defcsname\??variables#1:#2\endcsname{#3}% - \fi} - -%D \macros -%D {doifelsevariable,doifvariable,doifnotvariable} -%D -%D A few trivial macros: - -\permanent\protected\def\doifelsevariable#1#2% - {\ifcsname\??variables#1:#2\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifvariableelse\doifelsevariable - -\permanent\protected\def\doifvariable#1#2% - {\ifcsname\??variables#1:#2\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotvariable#1#2% - {\ifcsname\??variables#1:#2\endcsname - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -%D A few more (we could use a public test variable so that we only need to expand -%D once, assuming expandable variables): - -\letvalue{\??variables:}\empty - -\permanent\protected\def\doifelseemptyvariable#1#2% - {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% - \ifempty\m_syst_string_one - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifemptyvariableelse\doifelseemptyvariable - -\permanent\protected\def\doifemptyvariable#1#2% - {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% - \ifempty\m_syst_string_one - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotemptyvariable#1#2% - {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% - \ifempty\m_syst_string_one - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\def\getvariabledefault#1#2% #3% can be command - {\ifcsname\??variables#1:#2\endcsname - \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\tolerant\protected\def\setupenv[#1]% - {\syst_variables_set[\getrawparameters][\s!environment][#1]} - -\permanent\protected\def\doifelseenv{\doifelsevariable \s!environment} -\permanent\protected\def\doifenv {\doifvariable \s!environment} -\permanent\protected\def\doifnotenv {\doifnotvariable \s!environment} -\permanent \def\env {\getvariable \s!environment} -\permanent \def\envvar {\getvariabledefault\s!environment} - -\aliased\let\doifenvelse\doifelseenv - -%D \macros -%D {defineselector,setupselector,select,directselect} -%D -%D \starttyping -%D \defineselector[caption][max=2,n=2] -%D -%D \start -%D \setupselector[caption][n=1] -%D \placelist[figure][criterium=all] -%D \stop -%D -%D \starttext -%D \placefigure -%D {\select{caption}{zapf}{\input zapf \relax}} -%D {} -%D \stoptext -%D \stoptyping - -\installcorenamespace{selector} - -\permanent\tolerant\protected\def\defineselector[#1]#*[#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]} -\permanent\tolerant\protected\def\setupselector [#1]#*[#2]{\getparameters[\??selector#1][#2]} - -\permanent\protected\let\select\directselect % we promote to protected - -% \def\directselect#1% expandable -% {\filterfromnext % maybe add an \expanded -% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}% -% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}} -% -% this is more efficient when the arguments are used a few times (or passed along): - -\permanent\def\directselect#1% expandable - {\expandafter\filterfromnext - \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname - \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname} - -\letvalue{\??selector\c!max}\plusone % \aliased ? -\letvalue{\??selector\c!n }\plusone % \aliased ? - -\protect \endinput diff --git a/tex/context/base/mkiv/core-ini.mkxl b/tex/context/base/mkiv/core-ini.mkxl deleted file mode 100644 index 2e32e9bdd..000000000 --- a/tex/context/base/mkiv/core-ini.mkxl +++ /dev/null @@ -1,224 +0,0 @@ -%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 \everyendoftextbody - -\newtoks \everystarttext -\newtoks \everystoptext - -\newtoks \everystartdocument -\newtoks \everystopdocument - -%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 - -\permanent\protected\def\forgetall {\the\everyforgetall} -\permanent\protected\def\cleanupfeatures {\the\everycleanupfeatures} -\permanent\protected\def\simplifycommands{\the\everysimplifycommands} - -\appendtoks - \settrue\simplifyingcommands -\to \everysimplifycommands - -\appendtoks - \everypar\emptytoks % pretty important -\to \everyforgetall - -%D Page building: - -\newtoks \everybeforepagebody -\newtoks \everyafterpagebody - -\aliased\let\everypagebody\everybeforepagebody % backward compatible, will become obsolete - -%D Floats: - -\newtoks \everyinsidefloat - -%D Exporting: - -\newtoks \everyinitializeexport - -%D Sectioning: - -%newtoks \everyheadstart - -%D Par building (experimental, used in xml

..

) - -\newtoks \everybeginofpar -\newtoks \everyendofpar -%newtoks \everyparflush - -\protected\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar -\protected\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 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 \ifinsidemulticolumns % simple mixed-in-text columns -\newif \ifdoublesided \doublesidedfalse -\newif \ifsinglesided \singlesidedtrue -\newif \ifinsidefloat -\newif \ifdoingblocks -\newif \ifgridsnapping -\newif \ifexporting - -\newconstant\pageduplexmode % 0 single 1 double 2 mix -\newconstant\pagebodymode % 0 not 1 normal pagebody 2 spread - -\newcount\nofcolumns \nofcolumns \plusone -\newcount\nofmulticolumns \nofmulticolumns\plusone - -%D \macros -%D {ifproductionrun} -%D -%D This boolean can be used to bypass certain initializations. - -% \newif\ifproductionrun % already defined - -\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/tex/context/base/mkiv/core-lmt.lmt b/tex/context/base/mkiv/core-lmt.lmt deleted file mode 100644 index ccbdcc0df..000000000 --- a/tex/context/base/mkiv/core-lmt.lmt +++ /dev/null @@ -1,95 +0,0 @@ -if not modules then modules = { } end modules ['core-lmt'] = { - version = 1.001, - comment = "companion to core-lmt.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Kind of obsolete ... old school directions. - -local implement = interfaces.implement -local scankeyword = tokens.scanners.keyword -local scaninteger = tokens.scanners.integer - -local settextdir = tex.settextdir -local setlinedir = tex.setlinedir -local setpardir = tex.setpardir -local setboxdir = tex.setboxdir - -local gettextdir = tex.gettextdir -local getlinedir = tex.getlinedir -local getpardir = tex.getpardir -local getboxdir = tex.getboxdir - -local none_code = tokens.values.none - -local context = context - -local function scandir() - if scankeyword("tlt") then - return 0 - elseif scankeyword("trt") then - return 1 - else - return 0 - end -end - -local function showdir(d) - context(d == 1 and "TRT" or "LTL") - return none_code -end - -implement { - name = "textdir", - public = true, - usage = "value", - actions = function(what) - if what == "value" then - showdir(gettextdir()) - else - settextdir(scandir()) - end - end -} - -implement { - name = "linedir", - public = true, - usage = "value", - actions = function(what) - if what == "value" then - return showdir(getlinedir()) - else - setlinedir(scandir()) - end - end -} - -implement { - name = "pardir", - public = true, - usage = "value", - actions = function(what) - if what == "value" then - return showdir(getpardir()) - else - setpardir(scandir()) - end - end -} - -implement { - name = "boxdir", - public = true, - usage = "value", - actions = function(what) - local n = scaninteger() - if what == "value" then - return showdir(getboxdir(n)) - else - setboxdir(n,scandir()) - end - end -} diff --git a/tex/context/base/mkiv/core-lmt.mkxl b/tex/context/base/mkiv/core-lmt.mkxl deleted file mode 100644 index 77ef17966..000000000 --- a/tex/context/base/mkiv/core-lmt.mkxl +++ /dev/null @@ -1,28 +0,0 @@ -%D \module -%D [ file=core-lmt, -%D version=2018.08.2, -%D title=\CONTEXT\ System Macros, -%D subtitle=Primitives, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt System Macros / Primitives} - -\registerctxluafile{core-lmt}{autosuffix} - -\unprotect - -% nothing here - -\protect \endinput - -% \starttext -% abc{\textdir TRTdef}ghi -% abc{\textdir trtdef}ghi -% \boxdirection0=1 -% \stoptext diff --git a/tex/context/base/mkiv/core-sys.lmt b/tex/context/base/mkiv/core-sys.lmt deleted file mode 100644 index 12f001e37..000000000 --- a/tex/context/base/mkiv/core-sys.lmt +++ /dev/null @@ -1,91 +0,0 @@ -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.jobfilefullname = fulljobname - 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 - - -- if tex then - -- tex.jobname = jobfilename - -- end - - 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", public = true, actions = function() context(os.platform) end } -implement { name = "jobfilefullname", public = true, actions = function() context(environment.jobfilefullname) end } -implement { name = "jobfilename", public = true, actions = function() context(environment.jobfilename) end } -implement { name = "jobfilesuffix", public = true, actions = function() context(environment.jobfilesuffix) end } -implement { name = "inputfilebarename", public = true, actions = function() context(environment.inputfilebarename) end } -implement { name = "inputfilerealsuffix", public = true, actions = function() context(environment.inputfilerealsuffix) end } -implement { name = "inputfilesuffix", public = true, actions = function() context(environment.inputfilesuffix) end } -implement { name = "inputfilename", public = true, actions = function() context(environment.inputfilename) end } -implement { name = "outputfilename", public = true, 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 "" - return lpdf and format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf", - lpdf.getcompression() - ) or "error" -end) - -implement { - name = "systemlog", - arguments = "3 strings", - actions = function(whereto,category,text) - logs.system(whereto,"context",tex.jobname,category,text) - end, -} diff --git a/tex/context/base/mkiv/core-sys.mkxl b/tex/context/base/mkiv/core-sys.mkxl deleted file mode 100644 index c0280033f..000000000 --- a/tex/context/base/mkiv/core-sys.mkxl +++ /dev/null @@ -1,446 +0,0 @@ -%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}{autosuffix} - -\unprotect - -%D Version checking: - -\permanent\protected\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. - - -% \operatingsystem % defined at lua end - -%D The jobname is what gets loaded by the cont-yes stub file. This name also -%D determines the name of tuc etc files. - -% \jobfilefullname % defined at lua end -% \jobfilename % defined at lua end -% \jobfilesuffix % defined at lua end - -%D However, that one can itself load another file. - -% \inputfilebarename % defined at lua end -% \inputfilerealsuffix % defined at lua end -% \inputfilesuffix % defined at lua end -% \inputfilename % defined at lua end - -%D The output name is only used for some checking. - -% \outputfilename % defined at lua end - -\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 - -\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. - -\permanent\def\jobfullname{\jobfilename.\jobfilesuffix} - -\permanent\protected\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 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 - -\permanent\protected\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 is more -%D picky, so we default to the \type {cr}. I never understood why \type {crlf} was -%D not used in all systems, since it makes most sense. But anyway, in \MKIV\ we -%D avoid most of the complications anyway as we deal with much at the \LUA\ end. - -\permanent\tolerant\protected\def\start[#1]% - {\bgroup - \ifparameters - \expandafter\syst_start_nop - \else - \edef\m_syst_start_stop{#1}% - \expandafter\syst_start_yes - \fi} - -\def\syst_start_yes - {\ifempty\m_syst_start_stop - \let\syst_stop_indeed\donothing - \orelse\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} - -\def\syst_start_nop - {\let\syst_stop_indeed\donothing} - -\permanent\protected\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 - \frozen\setuevalue{\e!start\currentstartstop}{\syst_startstop_start {\currentstartstop}}% - \frozen\setuevalue{\e!stop \currentstartstop}{\syst_startstop_stop {\currentstartstop}}% - \frozen\setuevalue {\currentstartstop}{\syst_startstop_indeed{\currentstartstop}}% -\to \everydefinestartstop - -\ifdefined\dotagconstruct \else \let\dotagconstruct\relax \fi - -\protected\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 - \dotagconstruct} - -\protected\def\syst_startstop_stop#1% - {\dostoptagged - \egroup - \namedstartstopparameter{#1}\c!after\relax} - -\protected\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, not really needed - \startstopparameter\c!right\relax - \dostoptagged - \startstopparameter\c!inbetween\relax}} - -% \definestartstop[tracing][\c!style=\tt] - -% \protected\def\ignorestartstop[#1]% -% {\protected\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 - \frozen\setuevalue\currenthighlight{\typo_highlights_indeed{\currenthighlight}}% - \fi -\to \everydefinehighlight - -\ifdefined\dotaghighlight \else \let\dotaghighlight\relax \fi - -\permanent\protected\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}} - -\permanent\protected\def\highlight[#1]% - {\typo_highlights_indeed{#1}} - -\permanent\protected\def\starthighlight[#1]% - {\begingroup - \def\currenthighlight{#1}% - \dostarttagged\t!highlight\currenthighlight - \usehighlightstyleandcolor\c!style\c!color - \dotaghighlight} - -\permanent\protected\def\stophighlight - {\dostoptagged - \endgroup} - -\aliased\let\directhighlight\typo_highlights_indeed - -\permanent\protected\def\defineexpandable - {\doifelsenextoptional - {\syst_basics_define_yes\def}% - {\syst_basics_define_nop\def}} - -\permanent\protected\def\define - {\doifelsenextoptional - {\syst_basics_define_yes{\protected\def}}% - {\syst_basics_define_nop{\protected\def}}} - -\protected\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} - -\protected\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} - -\permanent\protected\def\unique#1#2% - {\ifdefined#2% - \showmessage\m!system4{\string#2}% - \expandafter#1\expandafter\gobbleddefinition - \else - \expandafter#1% - \fi#2} - -\permanent\protected\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["\\protected\\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 -% -% \protected\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}. - -\permanent\protected\def\macroname#1% brrr - {\begincsname#1\endcsname} - -% %D A weird one that I probably needed once, so it might as well become -% %D obsolete. -% -% \protected\def\usecommands#1% -% {\begingroup -% \def\docommand##1{\setbox\scratchbox\hbox{\csname\string##1\endcsname##1}}% -% \processcommalist[#1]\docommand -% \endgroup} - -\permanent\protected\def\syst_log_indeed#1#2#3% - {\ctxcommand{systemlog("#1","#2",\!!bs#3\!!es)}} - -\aliased\let\systemlog\syst_log_indeed - -\permanent\protected\def\systemlogfirst - {\ifcase\directsystemparameter\c!n\relax - \expandafter\syst_log_indeed - \or - \expandafter\syst_log_indeed - \else - \expandafter\gobblethreearguments - \fi} - -\permanent\protected\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/tex/context/base/mkiv/core-two.mkxl b/tex/context/base/mkiv/core-two.mkxl deleted file mode 100644 index 0299e76f5..000000000 --- a/tex/context/base/mkiv/core-two.mkxl +++ /dev/null @@ -1,109 +0,0 @@ -%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 time, apart from -%D adding a few more selectors. This code used to be part of \type {core-uti}. The -%D following examples demonstrate 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}{} - -\permanent\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\clf_savetwopassdata{#1}{#3}}} -\permanent\def \lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata("#1","#3")}}} -\permanent\let \savetwopassdata \lazysavetwopassdata -\permanent\def \savetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}} -\permanent\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 - -\def\syst_twopass_check % can be delegated to lua once obsolete is gone - {\ifx\twopassdata\empty - \setfalse\twopassdatafound - \else - \settrue\twopassdatafound - \fi} - -\permanent\protected\def\definetwopasslist #1{\clf_definetwopasslist{#1}} -\permanent\protected\def\gettwopassdata #1{\edef\twopassdata {\clf_gettwopassdata {#1}}\syst_twopass_check} -\permanent\protected\def\checktwopassdata #1{\edef\twopassdata {\clf_checktwopassdata {#1}}\syst_twopass_check} -\permanent\protected\def\findtwopassdata #1#2{\edef\twopassdata {\clf_findtwopassdata {#1}{#2}}\syst_twopass_check} -\permanent\protected\def\getfirsttwopassdata #1{\edef\twopassdata {\clf_getfirsttwopassdata {#1}}\syst_twopass_check} -\permanent\protected\def\getlasttwopassdata #1{\edef\twopassdata {\clf_getlasttwopassdata {#1}}% - \edef\noftwopassitems{\clf_counttwopassdata {#1}}\syst_twopass_check} -\permanent\protected\def\getnamedtwopassdatalist#1#2{\edef #1{\clf_gettwopassdatalist {#2}}} -\permanent\protected\def\gettwopassdatalist #1{\edef\twopassdatalist{\clf_gettwopassdatalist {#1}}} - -\permanent\protected\def\doifelseintwopassdata #1#2{\clf_doifelseintwopassdata{#1}{#2}} - -\aliased\let\doifintwopassdataelse\doifelseintwopassdata -\aliased\let\getfromtwopassdata \findtwopassdata - -\protect \endinput diff --git a/tex/context/base/mkiv/core-uti.mkxl b/tex/context/base/mkiv/core-uti.mkxl deleted file mode 100644 index b8d3bf7eb..000000000 --- a/tex/context/base/mkiv/core-uti.mkxl +++ /dev/null @@ -1,35 +0,0 @@ -%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}{} - -% savecurrentvalue#1#2% immediate, expanded, defined at lua end - -\appendtoks - \clf_setjobcomment - file {\jobname}% - format {\contextformat}% - stamp {\contextversion}% - escape {\!!bs\space...\space\!!es}% - \relax -\to \everystarttext - -\appendtoks - \clf_initializejob -\to \everyjob - -\protect \endinput diff --git a/tex/context/base/mkiv/driv-ini.mkxl b/tex/context/base/mkiv/driv-ini.mkxl deleted file mode 100644 index 9f489a2a1..000000000 --- a/tex/context/base/mkiv/driv-ini.mkxl +++ /dev/null @@ -1,20 +0,0 @@ -%D \module -%D [ file=driv-ini, -%D version=2018.07.26, -%D title=\CONTEXT\ Driver Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Driver Macros / Initialization} - -\registerctxluafile{driv-ini}{} - -\unprotect - -\protect \endinput diff --git a/tex/context/base/mkiv/driv-shp.lmt b/tex/context/base/mkiv/driv-shp.lmt deleted file mode 100644 index 8e3a936bb..000000000 --- a/tex/context/base/mkiv/driv-shp.lmt +++ /dev/null @@ -1,1360 +0,0 @@ -if not modules then modules = { } end modules ['driv-shp'] = { - version = 1.001, - optimize = true, - comment = "companion to driv-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, next = type, next -local round = math.round - -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local concat = table.concat -local keys = table.keys -local sortedhash = table.sortedhash -local splitstring = string.split -local idiv = number.idiv -local extract = bit32.extract -local nuts = nodes.nuts - -local tonut = nodes.tonut -local tonode = nodes.tonode - -local getdirection = nuts.getdirection -local getlist = nuts.getlist -local getoffsets = nuts.getoffsets -local getorientation = nuts.getorientation -local getfield = nuts.getfield -local getwhd = nuts.getwhd -local getkern = nuts.getkern -local getheight = nuts.getheight -local getdepth = nuts.getdepth ------ getwidth = nuts.getwidth -local getnext = nuts.getnext -local getsubtype = nuts.getsubtype -local getid = nuts.getid -local getleader = nuts.getleader ------ getglue = nuts.getglue -local getshift = nuts.getshift -local getdata = nuts.getdata ------ getexpansion = nuts.getexpansion -local getreplace = nuts.getreplace -local setreplace = nuts.setreplace -local getfont = nuts.getfont -local getkerndimension = nuts.getkerndimension - -local setdirection = nuts.setdirection -local setfield = nuts.setfield -local setlink = nuts.setlink - -local isglyph = nuts.isglyph -local findtail = nuts.tail -local nextdir = nuts.traversers.dir -local nextnode = nuts.traversers.node - -local rangedimensions = node.direct.rangedimensions -- nuts ? -local effectiveglue = nuts.effective_glue -local start_of_par = nuts.start_of_par -local dirdimensions = nuts.dirdimensions - -local texget = tex.get - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local characters = fonthashes.characters -local parameters = fonthashes.parameters - -local nodecodes = nodes.nodecodes -local whatsitcodes = nodes.whatsitcodes -local gluecodes = nodes.gluecodes -local dircodes = nodes.dircodes -local dirvalues = nodes.dirvalues -local subtypes = nodes.subtypes - -local normaldir_code = dircodes.normal - -local lefttoright_code = dirvalues.lefttoright -local righttoleft_code = dirvalues.righttoleft - -local glyph_code = nodecodes.glyph -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 disc_code = nodecodes.disc -local math_code = nodecodes.math -local rule_code = nodecodes.rule -local whatsit_code = nodecodes.whatsit ------ penalty_code = nodecodes.penalty ------ boundary_code = nodecodes.boundary - -local leaders_code = gluecodes.leaders -local cleaders_code = gluecodes.cleaders -local xleaders_code = gluecodes.xleaders -local gleaders_code = gluecodes.gleaders - -local spaceskip_code = gluecodes.spaceskip - -local saveposwhatsit_code = whatsitcodes.savepos -local userdefinedwhatsit_code = whatsitcodes.userdefined -local openwhatsit_code = whatsitcodes.open -local writewhatsit_code = whatsitcodes.write -local closewhatsit_code = whatsitcodes.close -local lateluawhatsit_code = whatsitcodes.latelua -local literalwhatsit_code = whatsitcodes.literal -local setmatrixwhatsit_code = whatsitcodes.setmatrix -local savewhatsit_code = whatsitcodes.save -local restorewhatsit_code = whatsitcodes.restore - -local getpagedimensions getpagedimensions = function() - getpagedimensions = backends.codeinjections.getpagedimensions - return getpagedimensions() -end - -local drivers = drivers -local instances = drivers.instances - -local report = logs.reporter("drivers") - ---------------------------------------------------------------------------------------- - -local lastfont = nil -local fontcharacters = nil - -local magicconstants = tex.magicconstants -local trueinch = magicconstants.trueinch -local maxdimen = magicconstants.maxdimen -local running = magicconstants.running - -local pos_h = 0 -local pos_v = 0 -local pos_r = lefttoright_code -local shippingmode = "none" - -local abs_max_v = 0 -local abs_max_h = 0 - -local shipbox_h = 0 -local shipbox_v = 0 -local page_size_h = 0 -local page_size_v = 0 ------ page_h_origin = 0 -- trueinch ------ page_v_origin = 0 -- trueinch - -local initialize -local finalize -local updatefontstate -local pushorientation -local poporientation -local flushcharacter -local flushfontchar -local flushrule -local flushliteral -local flushsetmatrix -local flushsave -local flushrestore -local flushspecial ------ flushimage - --- make local - -function drivers.getpos () return round(pos_h), round(pos_v) end -function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end -function drivers.gethpos() return round(pos_h) end -function drivers.getvpos() return round(pos_v) end - --- characters - -local flush_character - -local stack = setmetatableindex("table") -local level = 0 -local nesting = 0 -local main = 0 - --- experiment (smaller page stream but might be fragile) - -local tospace = false directives.register("backends.spaces", function(v) tospace = v end) - --- todo: cache streams - -local default = 16384 * number.dimenfactors.bp -- 65536 // 4 - -local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) - - if nesting > 100 then - return - elseif nesting == 0 then - main = font - end - - nesting = nesting + 1 - - local saved_h = pos_h - local saved_v = pos_v - local saved_r = pos_r - pos_r = lefttoright_code - - local data = fontdata[font] - local fnt = font - local fonts = data.fonts - local siz = (data.parameters.factor or 1)/65536 - - local function flushchar(font,char,fnt,chr,f,e) - if fnt then - local nest = char ~= chr or font ~= fnt - if fnt == 0 then - fnt = main - end - return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) - else - return 0 - end - end - - -- we assume resolved fonts: id mandate but maybe also size - - for i=1,#vfcommands do - local packet = vfcommands[i] - local command = packet[1] - if command == "char" then - local chr = packet[2] - local f = packet[3] - local e = packet[4] - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - elseif command == "slot" then - local index = packet[2] - local chr = packet[3] - local f = packet[4] - local e = packet[5] - if index == 0 then - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - else - local okay = fonts and fonts[index] - if okay then - local fnt = okay.id - if fnt then - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - end - else - -- safeguard, we assume the font itself (often index 1) - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - end - end - elseif command == "use" then - local index = packet[2] - if index then - local fnt - if index == 0 then - fnt = font - else - local okay = fonts and fonts[index] - if okay then - fnt = okay.id - end - end - if fnt then - -- not efficient but ok for now as experiment - local d = characters[fnt] - if d then - for i=3,#packet do - local chr = packet[i] - local dat = d[chr] - if dat then - flushfontchar(fnt,chr,dat) - end - end - end - end - end - elseif command == "right" then - local h = packet[2] -- already scaled - if factor ~= 0 and h ~= 0 then - h = h + h * factor / 1000 -- expansion - end - pos_h = pos_h + h - elseif command == "down" then - local v = packet[2] -- already scaled - pos_v = pos_v - v - elseif command == "push" then - level = level + 1 - local s = stack[level] - s[1] = pos_h - s[2] = pos_v - elseif command == "pop" then - if level > 0 then - local s = stack[level] - pos_h = s[1] - pos_v = s[2] - level = level - 1 - end - elseif command == "pdf" then - flushliteral(false,pos_h,pos_v,packet[2],packet[3]) - elseif command == "rule" then - local size_v = packet[2] - local size_h = packet[3] - if size_h > 0 and size_v > 0 then - if factor ~= 0 then - size_h = size_h + size_h * factor / 1000 - end - if size_h > 0 then - flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) - pos_h = pos_h + size_h - end - end - elseif command == "frame" then - local width = packet[2] - if width > 0 then - local height = packet[3] or 0 - local depth = packet[4] or 0 - local total = height + depth - if total > 0 then - if factor ~= 0 then - width = width + width * factor / 1000 - end - if width > 0 then - local line = packet[5] or default - local outline = not packet[6] - local advance = not packet[7] - flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline) - if advance then - pos_h = pos_h + width - end - end - end - end - elseif command == "font" then - local index = packet[2] - local okay = fonts and fonts[index] - if okay then - fnt = okay.id or fnt -- or maybe just return - end - elseif command == "lua" then - local code = packet[2] - if type(code) ~= "function" then - code = loadstring(code) - end - if type(code) == "function" then - code(font,char,pos_h,pos_v) - end - elseif command == "node" then - local h = packet[2] - hlist_out(h,getlist(h)) - elseif command == "image" then - -- doesn't work because intercepted by engine so we use a different - -- mechanism (for now) - local image = packet[2] - -- to do - elseif command == "pdfmode" then - -- doesn't happen - -- elseif command == "special" then - -- -- not supported - -- elseif command == "nop" then - -- -- nothing to do| - -- elseif command == "scale" then - -- -- not supported - end - end - - pos_h = saved_h - pos_v = saved_v - pos_r = saved_r - - nesting = nesting - 1 -end - -local onetimemessage -- could be defined later (todo: make plug for this) - -flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) - - if font ~= lastfont then - lastfont = font - fontcharacters = characters[font] - updatefontstate(font) - end - - local data = fontcharacters[char] - if not data then - if char > 0 then - if not onetimemessage then - onetimemessage = fonts.loggers.onetimemessage - end - onetimemessage(font,char,"missing") - end - return 0, 0, 0 - end - if vfcommands then - vfcommands = data.commands - end - local width, height, depth, naturalwidth - if current then - naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width - if factor == 0 then - width = naturalwidth - else - -- width = (1.0 + factor/1000000.0) * naturalwidth - width = naturalwidth + naturalwidth * factor/1000000.0 - -- width = naturalwidth + naturalwidth * 0.000001 * factor - end - else - width = data.width or 0 - height = data.height or 0 - depth = data.depth or 0 - naturalwidth = width - if not factor then - factor = 0 - end - end - if pos_r == righttoleft_code then - pos_h = pos_h - width -- here ? - end - if vfcommands then - flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? - else - -- kind of messy that we do orientation here and offsets elsewhere - local orientation = data.orientation - if orientation and (orientation == 1 or orientation == 3) then - local x = data.xoffset - local y = data.yoffset - if x then - pos_h = pos_h + x - end - if y then - pos_v = pos_v + y - end - pushorientation(orientation,pos_h,pos_v) - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - poporientation(orientation,pos_h,pos_v) - else - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - end - end - return width, height, depth -end - --- end of characters - -local function reset_state() - pos_h = 0 - pos_v = 0 - pos_r = lefttoright_code - shipbox_h = 0 - shipbox_v = 0 - shippingmode = "none" - page_size_h = 0 - page_size_v = 0 - -- page_h_origin = 0 -- trueinch - -- page_v_origin = 0 -- trueinch -end - --- local function dirstackentry(t,k) --- local v = { --- cur_h = 0, --- cur_v = 0, --- ref_h = 0, --- ref_v = 0, --- } --- t[k] = v --- return v --- end --- --- local dirstack = setmetatableindex(dirstackentry) --- --- local function reset_dir_stack() --- dirstack = setmetatableindex(dirstackentry) --- end - -local dirstack = { } - -local function reset_dir_stack() - dirstack = { } -end - -local leaderlevel = 0 - -local function flushlatelua(current,h,v) - -- Here we assume maganement by the lua function so currently we don't - -- check for leaderlevel. - return backends.latelua(current,h,v) -end - -local function flushwriteout(current) - if leaderlevel == 0 then - backends.writeout(current) - end -end - -local function flushopenout(current) - if leaderlevel == 0 then - backends.openout(current) - end -end - -local function flushcloseout(current) - if leaderlevel == 0 then - backends.closeout(current) - end -end - -local hlist_out, vlist_out do - - local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - local ot = extract(orientation, 0,4) - local ay = extract(orientation, 4,4) - local ax = extract(orientation, 8,4) - local of = extract(orientation,12,4) - if ot == 4 then - ot, ay = 0, 1 - elseif ot == 5 then - ot, ay = 0, 2 - end - if ot == 0 or ot == 2 then - if ax == 1 then x = x - width - elseif ax == 2 then x = x + width - elseif ax == 3 then x = x - width/2 - elseif ax == 4 then x = x + width/2 - end - if ot == 2 then - doffset, hoffset = hoffset, doffset - end - if ay == 1 then y = y - doffset - elseif ay == 2 then y = y + hoffset - elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset - end - elseif ot == 1 or ot == 3 then - if ay == 1 then y = y - height - elseif ay == 2 then y = y + height - elseif ay == 3 then y = y - height/2 - end - if ot == 1 then - doffset, hoffset = hoffset, doffset - end - if ax == 1 then x = x - width - elseif ax == 2 then x = x + width - elseif ax == 3 then x = x - width/2 - elseif ax == 4 then x = x + width/2 - elseif ax == 5 then x = x - hoffset - elseif ax == 6 then x = x + doffset - end - end - return ot, x + xoffset, y - yoffset - end - - -- to be checked: begin- or enddir kan nil zijn, weird - - -- local function calculate_width_to_enddir(this_box,begindir) -- can be a helper - -- local dir_nest = 1 - -- local enddir = begindir - -- for current, subtype in nextdir, getnext(begindir) do - -- if subtype == normaldir_code then -- todo - -- dir_nest = dir_nest + 1 - -- else - -- dir_nest = dir_nest - 1 - -- end - -- if dir_nest == 0 then -- does the type matter - -- enddir = current - -- local width = rangedimensions(this_box,begindir,enddir) - -- return enddir, width - -- end - -- end - -- if enddir == begindir then - -- local width = rangedimensions(this_box,begindir) -- ,enddir) - -- return enddir, width - -- end - -- return enddir, 0 - -- end - - -- check frequencies of nodes - - hlist_out = function(this_box,current) - local ref_h = pos_h - local ref_v = pos_v - local ref_r = pos_r - pos_r = getdirection(this_box) - local boxwidth, - boxheight, - boxdepth = getwhd(this_box) - - local cur_h = 0 - local cur_v = 0 - - -- if not current then - -- current = getlist(this_box) - -- end - - -- we can encounter par, boundary and penalty nodes but a special - -- iterator over content nodes won't save much - for current, id, subtype in nextnode, current do - if id == glyph_code then - local char, font = isglyph(current) - local x_offset, y_offset = getoffsets(current) - if x_offset ~= 0 or y_offset ~= 0 then - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + x_offset) - else - pos_h = ref_h + (cur_h + x_offset) - end - pos_v = ref_v - (cur_v - y_offset) - -- synced - end - local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) - cur_h = cur_h + wd - elseif id == glue_code then - local gluewidth = effectiveglue(current,this_box) - if gluewidth ~= 0 then - if subtype >= leaders_code then - local leader = getleader(current) - if leader then - local width, height, depth = getwhd(leader) - if getid(leader) == rule_code then - if gluewidth > 0 then - if height == running then - height = boxheight - end - if depth == running then - depth = boxdepth - end - local total = height + depth - if total > 0 then - if pos_r == righttoleft_code then - pos_h = pos_h - gluewidth - end - pos_v = pos_v - depth - flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader)) - end - cur_h = cur_h + gluewidth - end - elseif width > 0 and gluewidth > 0 then - local boxdir = getdirection(leader) or lefttoright_code - gluewidth = gluewidth + 10 - local edge = cur_h + gluewidth - local lx = 0 - if subtype == gleaders_code then - local save_h = cur_h - if pos_r == righttoleft_code then - cur_h = ref_h - shipbox_h - cur_h - cur_h = width * (cur_h / width) - cur_h = ref_h - shipbox_h - cur_h - else - cur_h = cur_h + ref_h - shipbox_h - cur_h = width * (cur_h / width) - cur_h = cur_h - ref_h - shipbox_h - end - if cur_h < save_h then - cur_h = cur_h + width - end - elseif subtype == leaders_code then - local save_h = cur_h - cur_h = width * (cur_h / width) - if cur_h < save_h then - cur_h = cur_h + width - end - else - lq = gluewidth / width - lr = gluewidth % width - if subtype == cleaders_code then - cur_h = cur_h + lr / 2 - else - lx = lr / (lq + 1) - cur_h = cur_h + (lr - (lq - 1) * lx) / 2 - end - end - local shift = getshift(leader) - leaderlevel = leaderlevel + 1 - while cur_h + width <= edge do - local basepoint_h = 0 - -- local basepoint_v = shift - if boxdir ~= pos_r then - basepoint_h = boxwidth - end - -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift) - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - shift - -- synced - if getid(leader) == vlist_code then - vlist_out(leader,getlist(leader)) - else - hlist_out(leader,getlist(leader)) - end - cur_h = cur_h + width + lx - end - leaderlevel = leaderlevel - 1 - cur_h = edge - 10 - else - cur_h = cur_h + gluewidth - end - else - cur_h = cur_h + gluewidth - end - else - if tospace and subtype == spaceskip_code then - -- todo: flush_space - flush_character(false,getfont(current),32,false,true,pos_h,pos_v,pos_r) - end - cur_h = cur_h + gluewidth - end - end - elseif id == hlist_code or id == vlist_code then - local width, height, depth = getwhd(current) - local list = getlist(current) - if list then - local boxdir = getdirection(current) or lefttoright_code - local shift, orientation = getshift(current) - if not orientation then - local basepoint_h = boxdir ~= pos_r and width or 0 - -- local basepoint_v = shift - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - shift - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - elseif orientation == 0x1000 then - local orientation, xoffset, yoffset = getorientation(current) - local basepoint_h = boxdir ~= pos_r and width or 0 - -- local basepoint_v = shift - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h + xoffset) - else - pos_h = ref_h + (cur_h + basepoint_h + xoffset) - end - pos_v = ref_v - (shift - yoffset) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - else - local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) - local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - if orientation == 1 then - basepoint_h = basepoint_h + doffset - if boxdir == pos_r then - basepoint_v = basepoint_v - height - end - elseif orientation == 2 then - if boxdir == pos_r then - basepoint_h = basepoint_h + width - end - elseif orientation == 3 then - basepoint_h = basepoint_h + hoffset - if boxdir ~= pos_r then - basepoint_v = basepoint_v - height - end - end - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - (cur_v + basepoint_v) - -- synced - pushorientation(orientation,pos_h,pos_v,pos_r) - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - poporientation(orientation,pos_h,pos_v,pos_r) - end - end - cur_h = cur_h + width - elseif id == kern_code then - -- we can use getkerndimension(current) but then we get rounded values so for - -- now we calculate ourselves - local kern, factor = getkern(current,true) - if kern ~= 0 then - if factor ~= 0 then - cur_h = cur_h + (1.0 + factor/1000000.0) * kern - else - cur_h = cur_h + kern - end - end - elseif id == rule_code then - local width, height, depth = getwhd(current) - if width > 0 then - if height == running then - height = boxheight - end - if depth == running then - depth = boxdepth - end - local total = height + depth - if total > 0 then - local xoffset, yoffset, left, right = getoffsets(current) -- top bottom - if left ~= 0 then - pos_v = pos_v + left - total = total - left - end - if right ~= 0 then - depth = depth - right - total = total - right - end - if pos_r == righttoleft_code then - pos_h = pos_h - width - xoffset = - xoffset - end - pos_v = pos_v - depth - flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype) - end - end - cur_h = cur_h + width - elseif id == math_code then - -- local kern = getkern(current) - -- if kern ~= 0 then - -- cur_h = cur_h + kern - -- else - cur_h = cur_h + effectiveglue(current,this_box) - -- end - elseif id == dir_code then - -- We normally have proper begin-end pairs. A begin without end is (silently) handled - -- and an end without a begin will be (silently) skipped we only need to move forward - -- so we then have a faster calculation. - local dir, cancel = getdirection(current) - if cancel then - local ds = dirstack[current] - if ds then - ref_h = ds.ref_h - ref_v = ds.ref_v - cur_h = ds.cur_h - cur_v = ds.cur_v - else - -- pardir - end - pos_r = dir - else - local width, enddir = dirdimensions(this_box,current) - local new_h = cur_h + width - if dir ~= pos_r then - cur_h = new_h - end - if enddir ~= current then - dirstack[enddir] = { - cur_h = new_h, - cur_v = cur_v, - ref_h = ref_h, - ref_v = ref_v, - } - setdirection(enddir,pos_r) - end - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - -- synced - ref_h = pos_h - ref_v = pos_v - cur_h = 0 - cur_v = 0 - pos_r = dir - goto synced - end - elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end - elseif id == disc_code then - local replace, tail = getreplace(current) - if replace and subtype ~= select_disc then - -- we could flatten .. no gain - setlink(tail,getnext(current)) - setlink(current,replace) - setreplace(current) - end - -- elseif id == par_code and start_of_par(current) then - -- local pardir = getdirection(current) or lefttoright_code - -- if pardir == righttoleft_code then - -- end - -- end - else - -- penalty, boundary ... no dimensions - goto synced - end - -- There is no gain in skipping over this when we have zero progression - -- and such. - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - ::synced:: - end - pos_h = ref_h - pos_v = ref_v - pos_r = ref_r - end - - vlist_out = function(this_box,current) - local ref_h = pos_h - local ref_v = pos_v - local ref_r = pos_r - pos_r = getdirection(this_box) - - local boxwidth, - boxheight, - boxdepth = getwhd(this_box) - - local cur_h = 0 - local cur_v = - boxheight - local top_edge = cur_v - - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - -- synced - - -- if not current then - -- current = getlist(this_box) - -- end - - -- while current do - -- local id = getid(current) - for current, id, subtype in nextnode, current do - if id == glue_code then - local glueheight = effectiveglue(current,this_box) - if glueheight ~= 0 then - if subtype >= leaders_code then - local leader = getleader(current) - if leader then - local width, height, depth = getwhd(leader) - local total = height + depth - if getid(leader) == rule_code then - depth = 0 -- hm --- forgotten ... needs testing -total = glueheight - if total > 0 then - if width == running then - width = boxwidth - end - if width > 0 then - if pos_r == righttoleft_code then - cur_h = cur_h - width - end - flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader)) - end - cur_v = cur_v + total - end - elseif total > 0 and glueheight > 0 then - glueheight = glueheight + 10 - local edge = cur_v + glueheight - local ly = 0 - if subtype == gleaders_code then - save_v = cur_v - cur_v = ref_v - shipbox_v - cur_v - cur_v = total * (cur_v / total) - cur_v = ref_v - shipbox_v - cur_v - if cur_v < save_v then - cur_v = cur_v + total - end - elseif subtype == leaders_code then -- aleader - save_v = cur_v - cur_v = top_edge + total * ((cur_v - top_edge) / total) - if cur_v < save_v then - cur_v = cur_v + total - end - else - lq = glueheight / total - lr = glueheight % total - if subtype == cleaders_code then - cur_v = cur_v + lr / 2 - else - ly = lr / (lq + 1) - cur_v = cur_v + (lr - (lq - 1) * ly) / 2 - end - end - local shift = getshift(leader) - leaderlevel = leaderlevel + 1 - while cur_v + total <= edge do -- todo: <= edge - total - -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height) - if pos_r == righttoleft_code then - pos_h = ref_h - shift - else - pos_h = ref_h + shift - end - pos_v = ref_v - (cur_v + height) - -- synced - if getid(leader) == vlist_code then - vlist_out(leader,getlist(leader)) - else - hlist_out(leader,getlist(leader)) - end - cur_v = cur_v + total + ly - end - leaderlevel = leaderlevel - 1 - cur_v = edge - 10 - else - cur_v = cur_v + glueheight - end - end - else - cur_v = cur_v + glueheight - end - end - elseif id == hlist_code or id == vlist_code then - local width, height, depth = getwhd(current) - local list = getlist(current) - if list then - local boxdir = getdirection(current) or lefttoright_code - local shift, orientation = getshift(current) - if not orientation then - -- local basepoint_h = shift - -- local basepoint_v = height - if boxdir ~= pos_r then - shift = shift + width - end - if pos_r == righttoleft_code then - pos_h = ref_h - shift - else - pos_h = ref_h + shift - end - pos_v = ref_v - (cur_v + height) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - elseif orientation == 0x1000 then - local orientation, xoffset, yoffset = getorientation(current) - -- local basepoint_h = shift - -- local basepoint_v = height - if boxdir ~= pos_r then - shift = shift + width - end - if pos_r == righttoleft_code then - pos_h = ref_h - (shift + xoffset) - else - pos_h = ref_h + (shift + xoffset) - end - pos_v = ref_v - (cur_v + height - yoffset) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - else - local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) - local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - if orientation == 1 then - basepoint_h = basepoint_h + width - height - basepoint_v = basepoint_v - height - elseif orientation == 2 then - basepoint_h = basepoint_h + width - basepoint_v = basepoint_v + depth - height - elseif orientation == 3 then -- weird - basepoint_h = basepoint_h + height - end - if pos_r == righttoleft_code then - pos_h = ref_h - basepoint_h - else - pos_h = ref_h + basepoint_h - end - pos_v = ref_v - (cur_v + basepoint_v) - -- synced - pushorientation(orientation,pos_h,pos_v,pos_r) - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - poporientation(orientation,pos_h,pos_v,pos_r) - end - end - cur_v = cur_v + height + depth - elseif id == kern_code then - cur_v = cur_v + getkern(current) - elseif id == rule_code then - local width, height, depth = getwhd(current) - local total = height + depth - if total > 0 then - if width == running then - width = boxwidth - end - if width > 0 then - local xoffset, yoffset, left, right = getoffsets(current) - if left ~= 0 then - width = width - left - xoffset = left - end - if right ~= 0 then - width = width - right - end - if pos_r == righttoleft_code then - xoffset = - xoffset - width - end - flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype) - end - end - cur_v = cur_v + total - elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end - else - -- penalty - goto synced - end - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - ::synced:: - end - pos_h = ref_h - pos_v = ref_v - pos_r = ref_r - end - -end - -function drivers.converters.lmtx(driver,box,smode,objnum,specification) - - if not driver then - report("error in converter, no driver") - return - end - - if box then - box = tonut(box) - else - report("error in converter, no box") - return - end - - local actions = driver.actions - local flushers = driver.flushers - - initialize = actions.initialize - finalize = actions.finalize - - updatefontstate = flushers.updatefontstate - - pushorientation = flushers.pushorientation - poporientation = flushers.poporientation - - flushcharacter = flushers.character - flushfontchar = flushers.fontchar - flushrule = flushers.rule - flushsimplerule = flushers.simplerule - flushspecialrule = flushers.specialrule - flushspecial = flushers.special - flushliteral = flushers.literal - flushsetmatrix = flushers.setmatrix - flushsave = flushers.save - flushrestore = flushers.restore - -- flushimage = flushers.image - - reset_dir_stack() - reset_state() - - shippingmode = smode - - local details = nil -- must be outside labels - - local width, height, depth = getwhd(box) - - local total = height + depth - - ----- v_offset_par = 0 - ----- h_offset_par = 0 - - local max_v = total -- + v_offset_par - local max_h = width -- + h_offset_par - - if height > maxdimen or depth > maxdimen or width > maxdimen then - goto DONE - end - - if max_v > maxdimen then - goto DONE - elseif max_v > abs_max_v then - abs_max_v = max_v - end - - if max_h > maxdimen then - goto DONE - elseif max_h > abs_max_h then - abs_max_h = max_h - end - - if shippingmode == "page" then - - -- We have zero offsets in ConTeXt. - - local pagewidth, pageheight = getpagedimensions() - - -- local h_offset_par = texget("hoffset") - -- local v_offset_par = texget("voffset") - - -- page_h_origin = trueinch - -- page_v_origin = trueinch - - pos_r = lefttoright_code - - if pagewidth > 0 then - page_size_h = pagewidth - else - page_size_h = width - end - - if page_size_h == 0 then - page_size_h = width - end - - if pageheight > 0 then - page_size_v = pageheight - else - page_size_v = total - end - - if page_size_v == 0 then - page_size_v = total - end - - local refpoint_h = 0 -- + page_h_origin + h_offset_par - local refpoint_v = page_size_v -- - page_v_origin - v_offset_par - - pos_h = refpoint_h - pos_v = refpoint_v - height - -- synced - - else - - -- page_h_origin = 0 - -- page_v_origin = 0 - page_size_h = width - page_size_v = total - pos_r = getdirection(box) - pos_v = depth - pos_h = pos_r == righttoleft_code and width or 0 - - end - - shipbox_ref_h = pos_h - shipbox_ref_v = pos_v - - details = { - shippingmode = smode, -- target - boundingbox = { 0, 0, page_size_h, page_size_v }, - objectnumber = smode ~= "page" and objnum or nil, - pagenumber = smode == "page" and objnum or nil, - specification = specification, - } - - initialize(driver,details) - - lastfont = nil -- this forces a sync each page / object - - if getid(box) == vlist_code then - vlist_out(box,getlist(box)) - else - hlist_out(box,getlist(box)) - end - - ::DONE:: - - finalize(driver,details) - - shippingmode = "none" -end - --- This will move to back-out.lua eventually. - -do - - ----- sortedhash = table.sortedhash - - ----- tonut = nodes.tonut - local properties = nodes.properties.data - local flush = texio.write_nl - - local periods = utilities.strings.newrepeater(".") - - local function showdetails(n,l) - local p = properties[tonut(n)] - if p then - local done = false - for k, v in sortedhash(p) do - if done then - flush("\n") - else - done = true - end - flush(periods[l+1] .. " " .. k .. " = " .. tostring(v)) - end - end - end - - local whatsittracers = { - latelua = showdetails, - literal = showdetails, - } - - callback.register("show_whatsit",function(n,l) - local s = nodes.whatsitcodes[n.subtype] - texio.write(" [" .. s .. "]") - local w = whatsittracers[s] - if w then - w(n,l) - end - end) - -end diff --git a/tex/context/base/mkiv/driv-shp.mkxl b/tex/context/base/mkiv/driv-shp.mkxl deleted file mode 100644 index 199215a59..000000000 --- a/tex/context/base/mkiv/driv-shp.mkxl +++ /dev/null @@ -1,18 +0,0 @@ -%D \module -%D [ file=driv-shp, -%D version=2018.07.26, -%D title=\CONTEXT\ Driver Macros, -%D subtitle=Shipout, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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{driv-shp}{autosuffix,optimize} - -\unprotect - -\protect \endinput diff --git a/tex/context/base/mkiv/enco-ini.mkxl b/tex/context/base/mkiv/enco-ini.mkxl deleted file mode 100644 index 104b2f890..000000000 --- a/tex/context/base/mkiv/enco-ini.mkxl +++ /dev/null @@ -1,570 +0,0 @@ -%D \module -%D [ file=enco-ini, -%D version=2007.02.19, % 2000.12.27, % 1998.12.03, -%D title=\CONTEXT\ Encoding Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This is stripped down version of th eoriginal enco-ini.tex file. For more details -%D you might want to study the \MKII\ file but since \LUATEX\ is unicode inside we -%D need less code. - -%D Much in here will disappear in \LMTX\ because we assume proper \UNICODE\ usage. - -% When dealing with characters we have four cases to take into account when moving -% from mkii to mkiv: - -% 1. => ref to slot 200 in current font -% 2. \char 200 => ref to slot 200 in current font -% 3. => can (e.g.) map to another slot in current font -% 4. \namedglyph => can map to some slot in some font - -% Using case 2 for special characters is doomed to fail because we are not going -% to intercept these on the fly as happens automatically with traditional font -% encoding handling. We could do that in a node pass but it's not worth the effort -% because we seldom use this case in a document source. - -% We can consider using utf as internal format for mkii. The main reason for not -% doing this before was that it was slow. On the other hand, it would make dealing -% with utility files easier. However, we've now kind of frozen mkii. - -\writestatus{loading}{ConTeXt Encoding Macros / Initialization} - -\unprotect - -%D Obsolete (but sometimes used in styles) - -\let\defaultencoding\s!default - -%D \macros -%D {defineaccent, definecharacter, definecommand} -%D -%D Some of these are used at the \LUA\ end! - -\installcorenamespace{accents} - -\permanent\protected\def\defineaccent#1 #2 #3 % - {\dodefineaccentcommand{#1}% - \dodefineaccent{#1}{#2}{#3}} - -\permanent\protected\def\dodefineaccentcommand#1% - {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}} - -\permanent\protected\def\dodefineaccent#1#2#3% no spaces, used low level - {\setvalue{\??accents\string#1\string#2\empty}{#3}} - -% the following dirty trick is needed to catch \asciimath{\^{1/5}log}: - -\permanent\protected\def\dohandleaccent#1#2% expandable because we want them in the tuc file - {\csname\??accents - \ifcsname\??accents\string#1#2\empty\endcsname - \string#1#2\empty - \orelse\ifcsname\??accents\string#1\string#2\empty\endcsname - \string#1\string#2\empty - \else - \endcsname#2\csname\??accents % very dirty trick: ignore accent but keep char - \fi - \endcsname} - -\immutable\letvalue{\??accents}\empty - -\permanent\protected\def\dodefinecommand#1#2% - {\frozen\setuvalue{\string#1}{#2}} % not permanent as these are kind of obsolete - -\permanent\protected\def\definecharacter#1 #2 % - {\doifelsenumber{\string#2} - {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax} - {\setuvalue{\string#1}{#2}}} - -\permanent\protected\def\definecommand#1 #2 % - {\setuvalue{\string#1}{#2}} - -%D \macros -%D {everyuppercase, everylowercase, everysanitize} - -\newtoks \everyuppercase -\newtoks \everylowercase -\newtoks \everysanitize - -%D Accent handling (try to avoid this): - -% \buildtextaccent\greekdasia\greekalphamacron -% \buildtextaccent\textacute q - -%D We can use offsets in \LMTX\ but even that makes n o sense because we have -%D a virtual feature already in \MKIV. - -%D We define them frozen so that we can overload them. - -\newbox\b_enco_accent - -\permanent\protected\def\buildmathaccent#1% - {\mathaccent#1 } - -\permanent\protected\def\buildtextaccent#1#2% we could do all at the lua end - {\dontleavehmode\begingroup % but that's no fun (yet) - \setbox\scratchboxone\hbox{#1}% accent - \setbox\scratchboxtwo\hbox{#2}% character - \scratchheight\dimexpr\ht\scratchboxtwo-\ht\scratchboxone\relax - \scratchdepth \dimexpr\dp\scratchboxtwo-\dp\scratchboxone\relax - \scratchwidth \wd\scratchboxtwo - \hbox to \wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi\bgroup - \hss\box\scratchboxtwo\hss - \hskip-\scratchwidth - \hss - \ifdim\ht\scratchboxone>\exheight - % top accent - \raise\dimexpr\scratchheight+\exheight/3\relax - \else - \lower-\dimexpr\scratchdepth+\exheight/3\relax - \fi - \box\scratchboxone - \hss - \egroup - \endgroup} - -\permanent\protected\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char - {\dontleavehmode % why this align mess - \vtop - {\forgetall - \baselineskip\zeropoint - \lineskip#1% - \everycr\emptytoks - \tabskip\zeropoint - \lineskiplimit\zeropoint - \setbox0\hbox{#4}% - \halign - {##\crcr\hbox{#5}\crcr - \hidewidth - \hskip#2\wd0 - \hskip-#3\slantperpoint % in plain 1ex * dimenless value - \vpack to .2\exheight{\box0\vss}\hidewidth - \crcr}}} - -\permanent\protected\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}} -\permanent\protected\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}} -\permanent\protected\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}} -\permanent\protected\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}} -\permanent\protected\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}} - -\aliased\let\d\buildtextbottomdot - -\permanent\protected\def\topaccent#1#2#3#4#5% down right slantcorrection accent char - {\dontleavehmode - \bgroup - \setbox0\hbox{#4}% - \setbox2\hbox{#5}% - \hbox to \wd2 \bgroup - \hss\copy2\hss - \hskip-\wd2 - \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss - \egroup - \egroup} - -\permanent\protected\def\buildtextgrave - {\topaccent{0pt}{0}{15}{\textgrave}} % e.g. - -\permanent\protected\def\definemathaccent#1 #2% - {\setvalue{#1}{\mathaccent#2 }} - -%D Math (will move): - -\definemathaccent acute \mathacute -\definemathaccent grave \mathgrave -\definemathaccent ddot \mathddot -\definemathaccent tilde \mathtilde -\definemathaccent bar \mathbar -\definemathaccent breve \mathbreve -\definemathaccent check \mathcheck -\definemathaccent hat \mathhat -\definemathaccent vec \mathvec -\definemathaccent dot \mathdot -%definemathaccent widetilde \mathwidetilde -%definemathaccent widehat \mathwidehat - -% from enco-def: - -% \aliased\let\i\dotlessi -% \aliased\let\j\dotlessj - -% \aliased\let\P\paragraphmark \aliased\let\textP\paragraphmark % obsolete (surfaced in bibliographic files) -% \aliased\let\S\sectionmark \aliased\let\textS\sectionmark % obsolete (surfaced in bibliographic files) - -\permanent\def\eszett {ß} \permanent\def\Eszett {SS} \permanent\def\Ssharp{SS} -\permanent\def\lslash {ł} \permanent\def\Lslash {Ł} -\permanent\def\dslash {đ} \permanent\def\Dslash {Đ} -%permanent\def\oslash {ø} %permanent\def\Oslash {Ø} % clashes with math: use \Ostroke -\permanent\def\dcroat {đ} \permanent\def\Dcroat {Đ} -\permanent\def\kcedilla{ķ} \permanent\def\Kcedilla{Ķ} -\permanent\def\lcedilla{ļ} \permanent\def\Lcedilla{Ļ} -\permanent\def\ncedilla{ņ} \permanent\def\Ncedilla{Ņ} -\permanent\def\rcedilla{ŗ} \permanent\def\Rcedilla{Ŗ} -\permanent\def\aumlaut {ä} \permanent\def\Aumlaut {Ä} -\permanent\def\eumlaut {ë} \permanent\def\Eumlaut {Ë} -\permanent\def\iumlaut {ï} \permanent\def\Iumlaut {Ï} -\permanent\def\oumlaut {ö} \permanent\def\Oumlaut {Ö} -\permanent\def\uumlaut {ü} \permanent\def\Uumlaut {Ü} - -% from enco-com: - -% \aliased\let\AE\AEligature \aliased\let\ae\aeligature -% \aliased\let\OE\OEligature \aliased\let\oe\oeligature -% \aliased\let\IJ\IJligature \aliased\let\ij\ijligature -% \aliased\let\AA\textAngstrom \aliased\let\aa\aring -% \aliased\let\CC\Ccedilla \aliased\let\cc\ccedilla -% \aliased\let\L \Lslash \aliased\let\l \lslash -% \aliased\let\O \Oslash \aliased\let\o \oslash -% \aliased\let\SZ\Eszett \aliased\let\sz\eszett % \aliased\let\SS\Ssharp - -% for old times sake (obsolete) - -\def\textflorin{ƒ} \def\florin {ƒ} -\def\pound {£} \def\sterling{£} -\def\promille {‰} \def\permille{‰} - -% tex specific - -\pushoverloadmode - -%D Was missing: - -\permanent\protected\def\ampersand{\mathortext\mathampersand\textampersand} - - -\ifdefined\textpercent - \permanent\let\percent \textpercent - \permanent\let\procent \textpercent - %\permanent\let\ampersand \textampersand - \permanent\let\dollar \textdollar - \permanent\let\hash \texthash -\else - \permanent\def\percent {\textpercent} - \permanent\def\procent {\textpercent} - %\permanent\def\ampersand {\textampersand} - \permanent\def\dollar {\textdollar} - \permanent\def\hash {\texthash} -\fi - -\popoverloadmode - -% from enco-mis: - -\permanent\protected\def\fakepercent - {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}} - -\permanent\protected\def\fakeperthousand - {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}} - -\permanent\protected\def\fakepermine - {\dontleavehmode - \bgroup - \setbox\scratchbox\hbox - {\mathematics{+}}% - \hbox to \wd\scratchbox - {\hss - \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}% - \hss}% - \egroup} - -\def\permine{\fakepermine} - -% some more: what with freezing here? - -\ifdefined\softhyphen \else - \aliased\let\softhyphen\explicitdiscretionary -\fi - -\def\hyphen {\softhyphen} -\def\compoundwordmark {\hyphen} -\def\cwm {\hyphen} -\def\nonbreakinghyphen{\hyphen} -\def\breakinghyphen {\hyphen\prewordbreak} - -% quotes - -\def\lowerleftsingleninequote {\quotesinglebase} -\def\lowerleftdoubleninequote {\quotedblbase} -\def\lowerrightsingleninequote {\quotesinglebase} -\def\lowerrightdoubleninequote {\quotedblbase} - -\def\upperleftsingleninequote {\quoteright} -\def\upperleftdoubleninequote {\quotedblright} -\def\upperrightsingleninequote {\quoteright} -\def\upperrightdoubleninequote {\quotedblright} - -\def\upperleftsinglesixquote {\quoteleft} -\def\upperleftdoublesixquote {\quotedblleft} -\def\upperrightsinglesixquote {\quoteleft} -\def\upperrightdoublesixquote {\quotedblleft} - -\def\leftsubguillemot {\guilsingleleft} -\def\rightsubguillemot {\guilsingleright} - -% left-overs (some day in private unicode space, so that we can roundtrip) - -\permanent\protected\def\textblacksquare{\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}} -%permanent\protected\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}} -\permanent\protected\def\schwagrave {\buildtextgrave\schwa} - -\chardef\textcontrolspace"2423 - -\installcorenamespace{controlspace} - -% \protected\def\fallbackcontrolspace % beware: non-matching widths -% {\hbox to \interwordspace{\hss\getglyph{LMTypewriter-Regular}\textcontrolspace\hss}% - -\permanent\protected\def\fallbackcontrolspace % beware, current font, we also need to honor color - {\hbox to \interwordspace \bgroup - \hss - \ifcsname\??controlspace\number\interwordspace\endcsname - \csname\??controlspace\number\interwordspace\endcsname - \else - \enco_fast_control_space_define % only regular - \fi - \textcontrolspace - \hss - \egroup} - -\protected\def\enco_fast_control_space_define - {\scratchdimen\interwordspace - \definedfont[LMTypewriter-Regular at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody]% see font-sym.mkiv - \global\letcsname\??controlspace\number\scratchdimen\endcsname\lastrawfontcall} - -\permanent\protected\def\normalcontrolspace - {\iffontchar\font\textcontrolspace - \textcontrolspace - \else - \fallbackcontrolspace - \fi} - -\let\textvisiblespace\normalcontrolspace - -\permanent\protected\def\optionalcontrolspace - {\iffontchar\font\textcontrolspace - \textcontrolspace - \else - \asciispacechar % used for export ! - \fi} - -% \protected\def\fastcontrolspace % no glyph resolving after first (use grouped) -% {\enco_fast_control_space} -% -% \def\enco_fast_control_space -% {\iffontchar\font\textcontrolspace -% \enco_fast_control_space_nop -% \else -% \enco_fast_control_space_yes -% \fi -% \enco_fast_control_space} -% -% \newbox\b_enco_control_space -% -% \def\enco_fast_control_space_nop -% {\let\enco_fast_control_space\textcontrolspace} -% -% \def\enco_fast_control_space_yes -% {\setbox\b_enco_control_space\fallbackcontrolspace -% \let\enco_fast_control_space\flushcontrolspacebox} -% -% \def\flushcontrolspacebox -% {\copy\b_enco_control_space} - -% a few defaults (\{}), we really need the verbose \empty as it will be -% stringified .. anyhow, we define this at the lua end now but keep it here as a -% reference -% -% \defineaccent ^ {\empty} {\textcircumflex} -% \defineaccent ` {\empty} {\textgrave} -% \defineaccent ~ {\empty} {\texttilde} -% \defineaccent " {\empty} {\textdiaeresis} -% \defineaccent ' {\empty} {\textacute} -% \defineaccent . {\empty} {\textdotaccent} -% \defineaccent = {\empty} {\textmacron} -% \defineaccent c {\empty} {\textcedilla} -% \defineaccent H {\empty} {\texthungarumlaut} -% \defineaccent k {\empty} {\textogonek} -% \defineaccent r {\empty} {\textring} -% \defineaccent u {\empty} {\textbreve} -% \defineaccent v {\empty} {\textcaron} - -\clf_defineaccents % one time - -%D A smaller and bolder variant, more like the math and monospaced ones. - -\permanent\protected\def\fakeunderscore - {\relax\ifmmode - \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax - \else - \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}% - \fi} - -\permanent\protected\def\fakeunderscores{\let\_\fakeunderscore} -\permanent\protected\def\textunderscores{\let\_\textunderscore} - -\textunderscores - -\ifdefined\mathunderscore \else \aliased\let\mathunderscore\fakeunderscore \fi -\ifdefined\textunderscore \else \aliased\let\textunderscore\fakeunderscore \fi - -\permanent\protected\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi} - -\let\_\normalunderscore - -%D To be sorted out: - -\pushoverloadmode - -\permanent\protected\def\textminus - {\char - \iffontchar\font"2012 "2012 \orelse % figuredash - \iffontchar\font"2013 "2013 \orelse % endash - \iffontchar\font"2212 "2212 \else % math minus - "002D \fi} % hyphen - -\permanent\protected\def\textplus - {\char"002B } % plus - -\popoverloadmode - -%D Moved from core-mis: - -\permanent\protected\def\celsius #1{#1\mathematics{^\circ}C} -\permanent\protected\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax} -\permanent\protected\def\fraction#1#2{\mathematics{#1\over#2}} - -% \def\periodswidth {.5em} -% \def\periodsdefault{3} % was 5, but now it's like \unknown -% -% \protected\def\periods -% {\dosingleempty\enco_periods} -% -% \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2 -% {\dontleavehmode -% \begingroup -% \scratchdimen\periodswidth -% \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen -% {\leaders\hbox to \scratchdimen{\hss\periodsymbol\hss}\hss}% -% \endgroup} -% -% better for export: -% -% \protected\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2 -% {\dontleavehmode -% \hbox\bgroup -% \setbox\scratchbox\hbox to \periodswidth{\hss\periodsymbol\hss}% -% \dorecurse{\iffirstargument#1\else\periodsdefault\fi}{\copy\scratchbox}% -% \egroup} -% -% \protected\def\unknown -% {\periods\relax} % relax prevents lookahead for [] -% -% per request: - -%D \startbuffer -%D \startlines -%D x\periods x -%D x\periods[10]x -%D x\periods[n=10,symbol={,}]x -%D x\periods[n=4,symbol={!!},width=1em]x -%D x\periods[n=4,symbol={!!},width=fit]x -%D x\periods[n=4,symbol={!!},width=fit,distance=1em]x -%D x\unknown x -%D \stoplines -%D \stopbuffer -%D -%D \typbuffer \getbuffer - -\def\periodswidth {.5\emwidth} % downward compatible -\def\periodsdefault{3} % downward compatible - -\installcorenamespace {periods} - -\installsetuponlycommandhandler \??periods {periods} - -\setupperiods - [\c!n=\periodsdefault, - \c!width=\periodswidth, % can also be \v!fit - \c!distance=.25\emwidth, - \c!symbol=.] - -\permanent\protected\def\periods - {\dontleavehmode - \hbox\bgroup - \doifelsenextoptional\enco_periods_yes\enco_periods_nop} - -\protected\def\enco_periods_yes[#1]% - {\doifelseassignment{#1} - {\setupcurrentperiods[#1]% - \scratchcounter\periodsparameter\c!n} - {\doifelsenothing{#1} - {\scratchcounter\periodsparameter\c!n}% - {\scratchcounter#1}}% - \enco_periods_finish} - -\protected\def\enco_periods_nop - {\scratchcounter\periodsparameter\c!n - \enco_periods_finish} - -\protected\def\enco_periods_finish - {\edef\p_width{\periodsparameter\c!width}% - \ifx\p_width\v!fit - \enco_periods_finish_fit - \else - \enco_periods_finish_width - \fi - \egroup} - -\protected\def\enco_periods_finish_width - {\setbox\scratchbox\hbox to \p_width - {\hss\periodsparameter\c!symbol\hss}% - \dorecurse\scratchcounter{\copy\scratchbox}} - -\protected\def\enco_periods_finish_fit - {\edef\p_symbol{\periodsparameter\c!symbol}% - \scratchdistance\periodsparameter\c!distance - \hskip\scratchdistance - \dorecurse\scratchcounter{\p_symbol\hskip\scratchdistance}} - -\permanent\protected\def\unknown - {\dontleavehmode - \hbox\bgroup - \enco_periods_nop} - -%D Left-overs: - -\appendtoks - \enforced\let\buildtextaccent\secondoftwoarguments -\to \everysimplifycommands - -%D A plain one: - -% \protected\def\t#1{% -% \dontleavehmode -% \begingroup -% \setbox\scratchboxone\hpack{#1}% -% \setbox\scratchboxtwo\hpack\bgroup -% \iffontchar\font"0361\relax -% \char"0361\relax -% \else -% \iffontchar\font"2040\relax\else -% \the\textfont0 -% \fi -% \char"2040 -% \fi -% \egroup -% \scratchdimenone\wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi -% \scratchdimentwo\dimexpr-\ht\scratchboxtwo+\ht\scratchboxone+.45\exheight\relax -% \hpack to \scratchdimenone\bgroup -% \hpack to \scratchdimenone{\hss\box\scratchboxone\hss}% -% \hskip -\scratchdimenone -% \hpack to \scratchdimenone{\hss\raise\scratchdimentwo\box\scratchboxtwo\hss}% -% \egroup -% \endgroup} - -\protect \endinput diff --git a/tex/context/base/mkiv/file-ini.mklx b/tex/context/base/mkiv/file-ini.mklx deleted file mode 100644 index a410854a8..000000000 --- a/tex/context/base/mkiv/file-ini.mklx +++ /dev/null @@ -1,231 +0,0 @@ -%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 is a separate module -%D for file commands. In \CONTEXT\ files 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 the \type {\input} -%D primitive or load them on a line||by||line basis, using \type {\read}. Writing is -%D always done line by line, using \type {\write}. - -\writestatus{loading}{ConTeXt File Macros / Helpers} - -\registerctxluafile{file-ini}{} - -\unprotect - -%D \macros -%D {scratchread, scratchwrite} -%D -%D We define a scratch file for reading. Keep in mind that the number of files is -%D limited to~16, so use this one when possible. We also define a scratch output -%D file. In \MKIV\ and \LMTX\ we never use these file handles. - -\ifdefined\scratchread \else \newread \scratchread \fi -\ifdefined\scratchwrite \else \newwrite\scratchwrite \fi - -%D Seldom needed: - -\permanent\def\openinputfile #handle#name{\immediate\openin #handle={#name}\relax} -\permanent\def\openoutputfile #handle#name{\immediate\openout#handle={#name}\relax} - -\permanent\def\closeinputfile #handle{\immediate\closein #handle\relax} -\permanent\def\closeoutputfile#handle{\immediate\closeout#handle\relax} - -%D \macros -%D {writeln} -%D -%D This saves a few tokens: - -\permanent\def\writeln#handle{\write#handle{}} - -%D \macros -%D {pushendofline,popendofline} -%D -%D When we are loading files in the middle of the typesetting process, for instance -%D when we load references, we have to be sure that the reading process does not -%D generate so called 'spurious spaces'. This can be prevented by assigning the line -%D ending character the \CATCODE\ comment. This is accomplished by -%D -%D \starttyping -%D \pushendofline -%D ... reading ... -%D \popendofline -%D \stoptyping - -\installsystemnamespace{eolstack} - -\newcount\c_system_files_eol_level - -\permanent\protected\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} - -\permanent\protected\def\popendofline - {\catcode\endoflineasciicode\csname\??eolstack\number\c_system_files_eol_level\endcsname - \advance\c_system_files_eol_level\minusone} - -\permanent\protected\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 - -\protected\def\startreadingfile% beter een every en \setnormalcatcodes - {\global\advance\readingfilelevel\plusone - \the\everystartreadingfile - \pushcatcodetable % saveguard - \setcatcodetable\ctxcatcodes - \clf_pushregime}% temporarily this way - -\protected\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 expanded, e.g. in -%D a \type {\write} (which happens in the metafun manual when we permit long MP -%D lines). So, instead of fixing that, we go for a redefinition of \type {\input}. -%D Of course it's better to use \type {\readfile} or \type {\processfile}. - -\permanent\def\inputgivenfile#name{\normalinput{#name}} % expands - -%D \macros -%D {doifelsefile} -%D -%D The next alternative only looks if a file is present. No loading is done. This -%D one obeys the standard \TEX\ lookup. -%D -%D \starttyping -%D \doiffileelse {filename} {found} {not found} -%D \stoptyping - -\permanent\protected\def\doifelsefile {\clf_doifelsefileexist} -\permanent\protected\def\doifelsepath {\clf_doifelsepathexist} -\permanent\protected\def\doiffile #name{\clf_doifelsefileexist{#name}\firstofoneargument\gobbleoneargument} -\permanent\protected\def\doifnotfile #name{\clf_doifelsefileexist{#name}\gobbleoneargument\firstofoneargument} - -\aliased\let\doiffileelse\doifelsefile -\aliased\let\doifpathelse\doifelsepath - -\aliased\let\doifelsefileexists\doifelsefile -\aliased\let\doifelsepathexists\doifelsepath - -\aliased\let\doiffileexistselse\doifelsefileexists -\aliased\let\doifpathexistselse\doifelsepathexists - -%D \macros -%D {doifparentfileelse} -%D -%D \starttyping -%D \doifparentfileelse{filename}{yes}{no} -%D \stoptyping - -\ifdefined\outputfilename \else \def\outputfilename{\jobname} \fi - -\permanent\protected\def\doifelseparentfile{\clf_doifelseparentfile} - -\aliased\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 - -\permanent\protected\def\splitfilename{\clf_splitfilename} - -%D \macros -%D {doonlyonce, doinputonce, doendinputonce} -%D -%D Especially macropackages need only be loaded once. Repetitive loading not only -%D costs time, relocating registers often leads to abortion of the processing -%D because \TEX's 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 move this -%D function to the \LUA\ end. - -\installsystemnamespace {fileonce} - -\permanent\protected\def\doonlyonce#whatever% - {\ifcsname\??fileonce#whatever\endcsname - \expandafter\gobbleoneargument - \else - \letgvalue{\??fileonce#whatever}\relax - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\doinputonce#name% - {\doonlyonce{#name}{\doifelsefile{#name}{\inputgivenfile{#name}}\donothing}} - -\permanent\protected\def\doendinputonce#name% - {\ifcsname\??fileonce#name\endcsname - \expandafter\endinput - \fi} - -\permanent\protected\def\forgetdoingonce#whatever% - {\global\undefinevalue{\??fileonce#whatever}} - -\protect \endinput diff --git a/tex/context/base/mkiv/file-job.lmt b/tex/context/base/mkiv/file-job.lmt deleted file mode 100644 index 95ad48e82..000000000 --- a/tex/context/base/mkiv/file-job.lmt +++ /dev/null @@ -1,1283 +0,0 @@ -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 next, rawget, tostring, tonumber = next, rawget, tostring, tonumber -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 setmetatableindex, setmetatablenewindex = table.setmetatableindex, table.setmetatablenewindex - -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 = logs.reporter("system") -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 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 is_qualified_path = file.is_qualified_path - -local cleanpath = resolvers.cleanpath -local toppath = resolvers.toppath -local resolveprefix = resolvers.resolve - -local hasscheme = url.hasscheme - -local jobresolvers = resolvers.jobs - -local registerextrapath = resolvers.registerextrapath -local resetextrapaths = resolvers.resetextrapaths -local getextrapaths = resolvers.getextrapath -local pushextrapath = resolvers.pushextrapath -local popextrapath = resolvers.popextrapath - ------ 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", - public = true, - protected = true, - actions = function(name) - name = findctxfile(name) - if name ~= "" then - context.input(name) - end - end -} - -implement { - name = "doifelseinputfile", - arguments = "string", - public = true, - protected = true, - 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 = "optional", - public = true, - protected = true, - actions = function(paths) - report_jobfiles("using path: %s",paths) - registerextrapath(paths) - end -} - -implement { - name = "pushpath", - arguments = "optional", - public = true, - protected = true, - actions = function(paths) - report_jobfiles("pushing path: %s",paths) - pushextrapath(paths) - end -} - -implement { - name = "poppath", - public = true, - protected = true, - actions = function(paths) - popextrapath() - report_jobfiles("popping path") - end -} - -implement { - name = "usesubpath", - arguments = "optional", - public = true, - protected = true, - actions = function(subpaths) - report_jobfiles("using subpath: %s",subpaths) - registerextrapath(nil,subpaths) - end -} - -implement { - name = "resetpath", - public = true, - protected = true, - actions = function() - report_jobfiles("resetting path") - resetextrapaths() - end -} - -implement { - name = "allinputpaths", - public = true, - actions = function() - context(concat(getextrapaths(),",")) - end -} - -implement { - name = "usezipfile", - public = true, - protected = true, - arguments = { "optional", "optional" }, - 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 -} - --- moved from tex to lua: - -local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.mklx", "%s.mkxl", "%s.tex" } -local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua", "%s.lmt" } -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", - public = true, - protected = true, - arguments = "string", - actions = function(name) - insert(processstack,name) - processedfile = name - insert(processedfiles,name) - end -} - -implement { - name = "dostoptextfile", - public = true, - protected = true, - actions = function() - processedfile = remove(processstack) or "" - end -} - -local function startprocessing(name,notext) - if not notext then - -- report("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("end file %a at line %a",name,status.linenumber or 0) - end -end - --- - -local typestack = { } -local currenttype = v_text -local nofmissing = 0 -local missing = { - tex = setmetatableindex("number"), - lua = setmetatableindex("number"), - cld = setmetatableindex("number"), - xml = setmetatableindex("number"), -} - -local function reportfailure(kind,name) - nofmissing = nofmissing + 1 - missing[kind][name] = true - report_jobfiles("unknown %s file %a",kind,name) -end - --- - -local function action(name,foundname) - input(foundname) -end -local function failure(name,foundname) - reportfailure("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 function action(name,foundname) - dofile(foundname) -end -local function failure(name,foundname) - reportfailure("lua",name) -end -local function useluafile(name,onlyonce,notext) - uselibrary { - name = name, - patterns = luapatterns, - action = action, - failure = failure, - onlyonce = onlyonce, - } -end - -local function action(name,foundname) - dofile(foundname) -end -local function failure(name,foundname) - reportfailure("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 function action(name,foundname) - context.xmlprocess(foundname,"main","") -end -local function failure(name,foundname) - reportfailure("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, - mklx = usetexfile, - mkxl = 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 = "loadtexfile", public = true, protected = true, actions = usetexfile, arguments = "optional" } -implement { name = "loadluafile", public = true, protected = true, actions = useluafile, arguments = "optional" } -implement { name = "loadcldfile", public = true, protected = true, actions = usecldfile, arguments = "optional" } -implement { name = "loadxmlfile", public = true, protected = true, actions = usexmlfile, arguments = "optional" } - -implement { name = "loadtexfileonce", public = true, protected = true, actions = usetexfile, arguments = { "optional", true } } -implement { name = "loadluafileonce", public = true, protected = true, actions = useluafile, arguments = { "optional", true } } -implement { name = "loadcldfileonce", public = true, protected = true, actions = usecldfile, arguments = { "optional", true } } -implement { name = "loadxmlfileonce", public = true, protected = true, actions = usexmlfile, arguments = { "optional", 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("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 - 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() - stopped = true - end - end -end - -implement { - name = "starttext", - public = true, - protected = true, - actions = starttext -} - -implement { - name = "stoptext", - public = true, - protected = true, - actions = stoptext -} - -implement { - name = "forcequitjob", - arguments = "string", - public = true, - protected = true, - actions = function(reason) - if reason then - report("forcing quit: %s",reason) - else - report("forcing quit") - end - context.batchmode() - while textlevel >= 0 do - context.stoptext() - end - end -} - -implement { - name = "forceendjob", - public = true, - protected = true, - actions = function() - report([[don't use \end to finish a document]]) - context.stoptext() - end -} - -implement { - name = "autostarttext", - public = true, - protected = true, - actions = function() - if textlevel == 0 then - report([[auto \starttext ... \stoptext]]) - end - context.starttext() - end -} - -implement { - name = "autostoptext", - public = true, - protected = true, - actions = stoptext -} - --- project structure - -implement { - name = "processfilemany", - public = true, - protected = true, - arguments = { "string", false }, - actions = useanyfile -} - -implement { - name = "processfileonce", - public = true, - protected = true, - arguments = { "string", true }, - actions = useanyfile -} - -implement { - name = "processfilenone", - arguments = "string", - public = true, - protected = true, - 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 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 - -do - - local function log_tree(report,top,depth) - report("%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(report,branches[i],depth) - end - end - end - - logs.registerfinalactions(function() - root.name = environment.jobname - -- - logs.startfilelogging(report,"used files") - log_tree(report,root,"") - logs.stopfilelogging() - -- - if nofmissing > 0 and logs.loggingerrors() then - logs.starterrorlogging(report,"missing files") - for kind, list in sortedhash(missing) do - for name in sortedhash(list) do - report("%w%s %s",6,kind,name) - end - end - logs.stoperrorlogging() - end - end) - -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 ctx_processfilemany = context.processfilemany -local ctx_processfileonce = context.processfileonce -local ctx_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,ctx_processfilemany) end -local function processfileonce(name) processfilecommon(name,ctx_processfileonce) end -local function processfilenone(name) processfilecommon(name,ctx_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 - -local scan_delimited = tokens.scanners.delimited - -local function getname() - return scan_delimited(91,93) or scan_delimited(0,32) -- [name] or name -end - -implement { name = "project", public = true, protected = true, actions = function() process(v_project, getname()) end } -implement { name = "environment", public = true, protected = true, actions = function() process(v_environment,getname()) end } -implement { name = "product", public = true, protected = true, actions = function() process(v_product, getname()) end } -- will be overloaded -implement { name = "component", public = true, protected = true, actions = function() process(v_component, getname()) end } - -implement { name = "useproject", public = true, protected = true, actions = function(name) process(v_project, name) end, arguments = "optional" } -implement { name = "useenvironment", public = true, protected = true, actions = function(name) process(v_environment,name) end, arguments = "optional" } -implement { name = "useproduct", public = true, protected = true, actions = function(name) process(v_product, name) end, arguments = "optional" } -- will be overloaded -implement { name = "usecomponent", public = true, protected = true, actions = function(name) process(v_component, name) end, arguments = "optional" } - --- 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() - local name = scan_delimited(91,93) or scan_delimited(0,32) -- [name] or name - if name == "*" then - name = nameonly(toppath() or name) - end - return name -end - -implement { name = "startproject", public = true, protected = true, actions = function() gotonextlevel(v_project, autoname()) end } -implement { name = "startproduct", public = true, protected = true, actions = function() gotonextlevel(v_product, autoname()) end } -implement { name = "startcomponent", public = true, protected = true, actions = function() gotonextlevel(v_component, autoname()) end } -implement { name = "startenvironment", public = true, protected = true, actions = function() gotonextlevel(v_environment,autoname()) end } - -implement { name = "stopproject", public = true, protected = true, actions = function() gotopreviouslevel(v_project ) end } -implement { name = "stopproduct", public = true, protected = true, actions = function() gotopreviouslevel(v_product ) end } -implement { name = "stopcomponent", public = true, protected = true, actions = function() gotopreviouslevel(v_component ) end } -implement { name = "stopenvironment", public = true, protected = true, actions = function() gotopreviouslevel(v_environment) end } - -implement { name = "currentproject", public = true, actions = function() context(topofstack(v_project )) end } -implement { name = "currentproduct", public = true, actions = function() context(topofstack(v_product )) end } -implement { name = "currentcomponent", public = true, actions = function() context(topofstack(v_component )) end } -implement { name = "currentenvironment", public = true, actions = function() context(topofstack(v_environment)) end } - --- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- --- --- --- nee --- standaard --- --- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -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, - public = true, - protected = true, - arguments = "optional" -} - --- 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 = "2 strings" -} - -implement { - name = "setdocumentdefaultargument", - actions = document.setdefaultargument, - arguments = "2 strings" -} - -implement { - name = "setdocumentfilename", - actions = document.setfilename, - arguments = { "integer", "string" } -} - -implement { - name = "getdocumentargument", - actions = { document.getargument, context }, - arguments = "2 strings" -} - -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.usage then - trackers.enable("system.usage") - 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 } - -do - - logs.registerfinalactions(function() - local foundintrees = resolvers.foundintrees() - if #foundintrees > 0 then - logs.startfilelogging(report,"used files") - for i=1,#foundintrees do - report("%4i: % T",i,foundintrees[i]) - end - logs.stopfilelogging() - end - end) - - logs.registerfinalactions(function() - local files = document.files -- or environment.files - local arguments = document.arguments -- or environment.arguments - -- - logs.startfilelogging(report,"commandline options") - if arguments and next(arguments) then - for argument, value in sortedhash(arguments) do - report("%s=%A",argument,value) - end - else - report("no arguments") - end - logs.stopfilelogging() - -- - logs.startfilelogging(report,"commandline files") - if files and #files > 0 then - for i=1,#files do - report("% 4i: %s",i,files[i]) - end - else - report("no files") - end - logs.stopfilelogging() - end) - -end - -if environment.initex then - - logs.registerfinalactions(function() - local startfilelogging = logs.startfilelogging - local stopfilelogging = logs.stopfilelogging - startfilelogging(report,"stored tables") - for k,v in sortedhash(storage.data) do - report("%03i %s",k,v[1]) - end - stopfilelogging() - startfilelogging(report,"stored modules") - for k,v in sortedhash(lua.bytedata) do - report("%03i %s %s",k,v.name) - end - stopfilelogging() - startfilelogging(report,"stored attributes") - for k,v in sortedhash(attributes.names) do - report("%03i %s",k,v) - end - stopfilelogging() - startfilelogging(report,"stored catcodetables") - for k,v in sortedhash(catcodes.names) do - report("%03i % t",k,v) - end - stopfilelogging() - startfilelogging(report,"stored corenamespaces") - for k,v in sortedhash(interfaces.corenamespaces) do - report("%03i %s",k,v) - end - stopfilelogging() - end) - -end - -implement { - name = "continueifinputfile", - public = true, - protected = true, - 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("continuing input file %a",inpname) - else - context.endinput() - end --- ctx_doifelse(continue) - end -} diff --git a/tex/context/base/mkiv/file-job.mklx b/tex/context/base/mkiv/file-job.mklx deleted file mode 100644 index 6e8f8e83f..000000000 --- a/tex/context/base/mkiv/file-job.mklx +++ /dev/null @@ -1,348 +0,0 @@ -%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. - -\writestatus{loading}{ConTeXt File Macros / Job Handling} - -\unprotect - -%D This module delegates most of the work to \LUA\ and therefore also let it -%D define the commands, which is more efficient. - -\registerctxluafile{file-job}{autosuffix} - -%D Here are some helpers for processing and path control. In the following example -%D the lookup order is \type {.}, {/foo}, \type {foo/bar} as one can always -%D explicitly prefix a wanted file. -%D -%D \starttyping -%D \pushpath[foo] -%D \pushpath[foo/bar] -%D \input test -%D \poppath -%D \poppath -%D \stoptyping - -% \usepath [#path] % defined at lua end -% \usesubpath [#path] % defined at lua end -% \pushpath [#path] % defined at lua end -% \poppath % defined at lua end -% \resetpath % defined at lua end (not the pushed paths) -% \allinputpaths % defined at lua end -% \doifelseinputfile #name % defined at lua end -% \processfile #name % defined at lua end - -\aliased\let\doifinputfileelse\doifelseinputfile - -% helper (not really needed nowadays) - -\mutable\let\locatedfilepath\empty - -\protected\def\locatefilepath#name{\edef\locatedfilepath{\clf_locatefilepath{#name}}} % todo: set at the lua end, catcodes and such - -% % 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 -% exa stuff might become obsolete: - -% \usezipfile [#zipname]#spacer[#subtree] % defined at lua end -% \loadexamodes [#name] % defined at lua end - -\protected\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 - -\protected\def\dostarttext - {\enforced\glet\dostarttext\relax - \the\everystarttext - \global\everystarttext\emptytoks} - -\protected\def\dostoptext - {\enforced\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 - % tex's \end: - \normalend} - -% \starttext % defined at lua end -% \stoptext % defined at lua end -% \forcequitjob % defined at lua end -% \autostarttext % defined at lua end -% \autostoptext % defined at lua end - -\pushoverloadmode - \aliased\let\end\forceendjob -\popoverloadmode - -\aliased\let\finishjob\stoptext % nicer in luatex call commandline - -\newtoks\everystartnotext -\newtoks\everystopnotext - -\protected\def\startnotext{\the\everystartnotext} -\protected\def\stopnotext {\the\everystopnotext\normalend} - -% protect structure - -% \processfilemany {#name} % defined at lua end -% \processfileonce {#name} % defined at lua end -% \processfilenone {#name} % defined at lua end - -% \useproject [#name] % defined at lua end -% \useproduct [#name] % defined at lua end -% \usecomponent [#name] % defined at lua end -% \useenvironment [#name] % defined at lua end - -% \project [#name] or #name % defined at lua end -% \product [#name] or #name % defined at lua end -% \component [#name] or #name % defined at lua end -% \environment [#name] or #name % defined at lua end - -% \startproject [#name] or #name % defined at lua end -% \startproduct [#name] or #name % defined at lua end -% \startcomponent [#name] or #name % defined at lua end -% \startenvironment [#name] or #name % defined at lua end - -\newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua - -% \protected\def\signalendofinput#1% argument just for tracing -% {\global\settrue\endofinput} -% -% \protected\def\honorendofinput -% {\ifconditional\endofinput -% \global\setfalse\endofinput -% \endinput -% \fi} - -% \protected\def\stopproject {\clf_stopproject \honorendofinput} % todo -% \protected\def\stopproduct {\clf_stopproduct \honorendofinput} % todo -% \protected\def\stopcomponent {\clf_stopcomponent \honorendofinput} % todo -% \protected\def\stopenvironment {\clf_stopenvironment\honorendofinput} % todo - -% \currentproject % defined at lua end -% \currentproduct % defined at lua end -% \currentcomponent % defined at lua end -% \currentenvironment % defined at lua end -% \processedfile % defined at lua end -% \processedfiles % defined at lua end -% -% \dostarttextfile #name % defined at lua end -% \dostoptextfile % defined at lua end -% -% \loadtexfile [#name] % defined at lua end -% \loadluafile [#name] % defined at lua end -% \loadcldfile [#name] % defined at lua end -% \loadanyfile [#name] % defined at lua end -% -% \loadtexfileonce [#name] % defined at lua end -% \loadluafileonce [#name] % defined at lua end -% \loadcldfileonce [#name] % defined at lua end -% \loadanyfileonce [#name] % defined at lua end - -%D Handy for modules that have a test/demo appended (true added). - -% \permanent\protected\def\continueifinputfile#name{\clf_doifelsecontinuewithfile{#name}\relax\endinput} % we cannot do \endinput via lua - -% \continueifinputfile #name % defined at lua end - -% \startproject test -% 1: \startmode[*project] project \stopmode \endgraf -% 2: \startmode[*product] product \stopmode \endgraf -% \stopproject - -% A bit 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 - -\permanent\protected\def\startprojectindeed - {%starttext - \pushsystemmode\v!project - \setsystemmode\v!project} - -\permanent\protected\def\stopprojectindeed - {\popsystemmode\v!project - %stoptext - }%\signalendofinput\v!project} - -\permanent\protected\def\startproductindeed - {\starttext - \pushsystemmode\v!product - \setsystemmode\v!product} - -\permanent\protected\def\stopproductindeed - {\popsystemmode\v!product - \stoptext - }%\signalendofinput\v!product} - -\permanent\protected\def\startcomponentindeed - {\starttext - \pushreferenceprefix\currentcomponent - \pushsystemmode\v!component - \setsystemmode\v!component} - -\permanent\protected\def\stopcomponentindeed - {\popsystemmode\v!component - \popreferenceprefix - \stoptext - }%\signalendofinput\v!component} - -\permanent\protected\def\startenvironmentindeed - {\pushsystemmode\v!environment - \setsystemmode\v!environment} - -\permanent\protected\def\stopenvironmentindeed - {\popsystemmode\v!environment - }%\signalendofinput\v!environment} - -%D Upgraded after the ctx 2020 meeting: -%D -%D \starttyping -%D \definedocument[thesis] -%D -%D \setupdocument[a=b,e=f] -%D \setupdocument[thesis][a=x,c=d] -%D -%D % \startsetups[thesis:start] -%D \startsetups[document:start] -%D START -%D \stopsetups -%D -%D \startsetups[thesis:stop] -%D % \startsetups[document:stop] -%D STOP -%D \stopsetups -%D -%D % \startdocument[thesis] -%D \startthesis -%D (\currentdocument/a): \documentvariable{a}\par -%D (\currentdocument/c): \documentvariable{c}\par -%D (\currentdocument/e): \documentvariable{e}\par -%D \stopthesis -%D % \stopdocument -%D \stoptyping - -\installcorenamespace {document} - -\installcommandhandler \??document \s!document \??document - -\setupdocument - [\c!before=\directsetup{\s!document:\v!start}, - \c!after =\directsetup{\s!document:\v!stop}] - -\def\syst_document_setup#1% - {\directsetup{\doifelsesetups{\currentdocument:\v!start}\currentdocument\s!document:\v!start}} - -\appendtoks - \normalexpanded {% - \startsetups[\currentdocument:\v!start]\noexpand\directsetup{\ifx\empty\currentdocumentparent\s!document\else\currentdocumentparent\fi:\v!start}\stopsetups - \startsetups[\currentdocument:\v!stop ]\noexpand\directsetup{\ifx\empty\currentdocumentparent\s!document\else\currentdocumentparent\fi:\v!stop }\stopsetups - \permanent\setvalue{\e!start\currentdocument}{\startdocument[\currentdocument]}% - \permanent\setvalue{\e!stop \currentdocument}{\stopdocument} - }% -\to \everydefinedocument - -% todo: dostarttagged\t!document - -\permanent\tolerant\protected\def\startdocument[#namespace]#spacer[#settings]% - {\pushmacro\currentdocument - \ifparameters - \or - \ifhastok={#namespace}% - \let\currentdocument\empty - \setupcurrentdocument[#namespace]% - \else - \edef\currentdocument{#namespace}% - \fi - \or - \edef\currentdocument{#namespace}% - \setupcurrentdocument[#settings]% - \fi - \ifempty\currentdocument\else\setmode\currentdocument\fi - \starttext - \the\everystartdocument - \documentvariable\c!before} - -\permanent\protected\def\stopdocument % todo: dostoptagged\t!document - {\documentvariable\c!after - \the\everystopdocument - \stoptext - \ifx\empty\currentdocument\else\resetmode\currentdocument\fi - \popmacro\currentdocument} - -\aliased \let\documentvariable \documentparameter -\aliased\protected\def\unexpandeddocumentvariable{\documentparameter} - -\permanent\protected\def\doifelsedocumentvariable#name{\doifelsesomething{\documentvariable{#name}}} -\permanent\protected\def\doifdocumentvariable #name{\doifsomething {\documentvariable{#name}}} -\permanent\protected\def\doifnotdocumentvariable #name{\doifnot {\documentvariable{#name}}} - -\aliased\let\doifdocumentvariableelse\doifelsedocumentvariable - -\permanent\tolerant\protected\def\presetdocument[#namespace]#spacer[#settings]% - {\pushmacro\currentdocument - \ifparameters - \or - \ifhastok={#namespace}% - \let\currentdocument\empty - \setupcurrentdocument[#namespace]% - \fi - \or - \edef\currentdocument{#namespace}% - \setupcurrentdocument[#settings]% - \fi - \popmacro\currentdocument} - -% Bonus: - -% \installcorenamespace{samplefile} -% -% \protected\def\samplefile#1% -% {\ifcsname\??samplefile#1\endcsname \else -% \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% -% \fi -% \lastnamedcs} - -\permanent\protected\def\samplefile#1{\clf_samplefile{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/file-lib.mkxl b/tex/context/base/mkiv/file-lib.mkxl deleted file mode 100644 index c2ec555cf..000000000 --- a/tex/context/base/mkiv/file-lib.mkxl +++ /dev/null @@ -1,20 +0,0 @@ -%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}{} - -\protect \endinput diff --git a/tex/context/base/mkiv/file-mod.mklx b/tex/context/base/mkiv/file-mod.mklx deleted file mode 100644 index bf9b948bf..000000000 --- a/tex/context/base/mkiv/file-mod.mklx +++ /dev/null @@ -1,289 +0,0 @@ -%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}{} - -%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. - -\installcorenamespace{module} - -\let\currentmodule \s!unknown -\let\currentmodulecategory \empty -\let\currentmoduleparameters\empty - -\installmacrostack\currentmodule -\installmacrostack\currentmodulecategory -\installmacrostack\currentmoduleparameters - -\permanent\tolerant\protected\def\usemodules[#category]#spacer[#name]#spacer[#parameters]% category=t|m|x|p|... - {\push_macro_currentmodule - \push_macro_currentmodulecategory - \push_macro_currentmoduleparameters - \ifparameters - \let\currentmodule\empty - \or - \let \currentmodulecategory \empty - \edef\currentmodule {#category}% - \let \currentmoduleparameters\empty - \or - \ifhastok={#name}% - \let\currentmodulecategory \empty - \edef\currentmodule {#category}% - \edef\currentmoduleparameters{#name}% - \else - \edef\currentmodulecategory {#category}% - \edef\currentmodule {#name}% - \let \currentmoduleparameters\empty - \fi - \or - \edef\currentmodulecategory {#category}% - \edef\currentmodule {#name}% - \def \currentmoduleparameters{#parameters}% - \fi - \processcommacommand[\currentmodule]{\strc_modules_use\currentmodulecategory}% - \pop_macro_currentmoduleparameters - \pop_macro_currentmodulecategory - \pop_macro_currentmodule} - -\def\strc_modules_use#category#name% - {\ifempty\currentmoduleparameters\else - \scratchtoks\expandafter{\currentmoduleparameters}% - \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% - \fi - \clf_usemodules{#category}{#name}} - -\aliased\let\usemodule \usemodules -\aliased\let\usetexmodule\usemodules - -\newcount\c_syst_modules_nesting -\newtoks \everysetupmodule - -\permanent\tolerant\protected\def\startmodule[#1]#;#2 % - {\global\advance\c_syst_modules_nesting\plusone - \push_macro_currentmodule - \push_macro_currentmoduleparameters - \def\currentmodule{#1#2}} - -\permanent\protected\def\stopmodule - {\ifcase\c_syst_modules_nesting - \writestatus\m!system{module wrapping error in '\currentmodule'}% - \else - \pop_macro_currentmoduleparameters - \pop_macro_currentmodule - \global\advance\c_syst_modules_nesting\minusone - \fi} - -\permanent\protected\def\setupmodule % to be lmtx'd - {\ifempty\currentmoduleparameters - \expandafter\syst_modules_setup_nop - \else - \expandafter\syst_modules_setup_yes - \fi} - -\tolerant\def\syst_modules_setup_nop[#name]#spacer[#parameters]% - {\ifarguments - % nothing - \or - \doifassignmentelse{#name}{\getparameters[\??module\currentmodule:][#name]}\donothing - \or - \getparameters[\??module#name:][#parameters]% internal (defaults) - \fi - \the\everysetupmodule} - -\tolerant\def\syst_modules_setup_yes[#name]#spacer[#parameters]% - {\scratchtoks\expandafter{\currentmoduleparameters}% - \ifparameters - \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% - \or - \ifhastok={#name}% - \getparameters[\??module\currentmodule:][#name]% internal (defaults) - \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% loadtime (user) - \else - \normalexpanded{\getparameters[\??module#1:][\the\scratchtoks]}% loadtime (user) - \fi - \or - \getparameters[\??module#name:][#parameters]% internal (defaults) - \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% loadtime (user) - \fi - \let\currentmoduleparameters\empty - \the\everysetupmodule} - -\permanent\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 - -\permanent\def\currentmoduleparameter{\moduleparameter\currentmodule} % no need for inlining - -%permanent\protected\def\useluamodule[#name]{\clf_loadluamodule{#1}} % why not use useluamodule - -\permanent\protected\def\useluamodule [#name]{\clf_useluamodule{#1}} -\permanent\protected\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: - -\permanent\protected\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}} - -\aliased\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!file_run % last is a file name -%D \stoptyping - -\installcorenamespace{runtimeloaded} - -\permanent\protected\def\fetchruntimecommand#1#2% - {\protected\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 - \glet#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}% - \protected\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). - -\permanent\protected\def\doifelseolderversion#parent#child{\clf_doifelseolderversion{#parent}{#child}} -\permanent\protected\def\doifelseoldercontext #child{\clf_doifelseolderversion{#child}{}} - -\aliased\let\doifolderversionelse\doifelseolderversion -\aliased\let\doifoldercontextelse\doifelseoldercontext - -%D Relatively new (no need for a speedup here). Can't this now be done nicer? - -\permanent\protected\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}} - -\permanent\protected\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} - -\permanent\protected\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}} - -\permanent\protected\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} - -\permanent\protected\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}} - -\permanent\protected\def\installmodulecommandlua #1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_direct_lua{\csstring#1}{#2}}}} -\permanent\protected\def\installmodulecommandluasingle#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_single_lua{\csstring#1}{#2}}}} -\permanent\protected\def\installmodulecommandluadouble#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_double_lua{\csstring#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}} - -\permanent\protected\def\installmodulecommandluaone#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_one_lua{\csstring#1}{#2}}}} -\permanent\protected\def\installmodulecommandluatwo#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_two_lua{\csstring#1}{#2}}}} - -% obsolete -% -% \def\documentresources{\@@erurl} -% -% \unexpanded\def\setupexternalresources -% {\dodoubleargument\getparameters[\??er]} -% -% \setupexternalresources -% [url=] - -% new: - -\protect \endinput diff --git a/tex/context/base/mkiv/file-res.mklx b/tex/context/base/mkiv/file-res.mklx deleted file mode 100644 index a523302d1..000000000 --- a/tex/context/base/mkiv/file-res.mklx +++ /dev/null @@ -1,145 +0,0 @@ -%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. - -%D We could move some more to the lua end (implementors). - -\writestatus{loading}{ConTeXt File Macros / Resolvers} - -\unprotect - -\registerctxluafile{file-res}{} - -%D \macros -%D {readfile,ReadFile} -%D -%D One cannot be sure if a file exists. When no file can be found, the \type -%D {\input} primitive gives an error message and switches to interactive mode. The -%D macro \type {\readfile} takes care of non||existing files. This macro has two -%D 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 locating files. This -%D can lead to unexpected results, especially when one loads files that are not -%D found in the current directory. Let's give an example of this. In \CONTEXT\ -%D illustrations can be defined in an external file. The resizing macro first looks -%D if an illustration is defined in the local definitions file. When no such file is -%D found, it searches for a global file and when this file is not found either, the -%D illustration itself is scanned for dimensions. One can imagine what happens if an -%D adapted, localy stored illustration, is scaled according to dimensions stored -%D somewhere else. -%D -%D When some \TEX\ implementation starts looking for a file, it normally first looks -%D in the current directory. When no file is found, \TEX\ starts searching on the -%D path where format and|/|or style files are stored. Depending on the -%D implementation this can considerably slow down processing speed. -%D -%D In \CONTEXT, we support a project||wise ordening of files. In such an approach it -%D seems feasible to store common files in a lower directory. When for instance -%D searching for a general layout file, we therefore have to backtrack. -%D -%D These three considerations have lead to a more advanced approach for loading -%D files. -%D -%D We first present an earlier implementation of \type {\readfile}. This command -%D backtracks parent 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} because we want to be able -%D to redefine the original \type {\input} when needed, for instance when loading -%D third party libraries. - -\let\readfilename\empty - -\def\syst_files_read_file#protocol#path#name% #true #false - {\edef\readfilename{\clf_getreadfilename{#protocol}{#path}{#name}}% - \ifempty\readfilename - \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 still can get unwanted -%D files loaded and/or can get involved in extensive searching. -%D -%D Due to different needs, we decided to offer four alternative loading commands. -%D With \type {\readjobfile} we load a local file and do no backtracking, while -%D \type {\readlocfile} backtracks~\number \maxreadlevel\ directories, including the -%D current one. -%D -%D System files can be anywhere and therefore \type {\readsysfile} is not bound to -%D the current directory and obeys the \TEX\ implementation. -%D -%D Of the last two, \type {\readfixfile} searches on the directory specified and -%D backtracks too, while \type {\readsetfile} does only search on the specified -%D path. -%D -%D The most liberal is \type {\readfile}. - -\permanent\protected\def\readjobfile #name{\syst_files_read_file{job} {.}{#name}} % current path, no backtracking -\permanent\protected\def\readlocfile #name{\syst_files_read_file{loc} {.}{#name}} % current path, backtracking -\permanent\protected\def\readsysfile #name{\syst_files_read_file{sys} {.}{#name}} % current path, obeys tex search -\permanent\protected\def\readfixfile#path#name{\syst_files_read_file{fix}{#path}{#name}} % specified path, backtracking -\permanent\protected\def\readsetfile#path#name{\syst_files_read_file{set}{#path}{#name}} % specified path, no backtracking -\permanent\protected\def\readfile #name{\syst_files_read_file{any} {.}{#name}} -\permanent\protected\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 - -\permanent\protected\def\readtexfile#name#true#false% - {\pushcatcodetable - \catcodetable\ctxcatcodes - \readfile{#name}{#true}{#false}% - \popcatcodetable} - -\permanent\protected\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 - -\permanent\protected\def\doifelselocfile#name{\clf_doifelselocfile{#name}} -\permanent \def\locfilename #name{\clf_locfilename {#name}} - -\aliased\let\doiflocfileelse\doifelselocfile - -\protect \endinput diff --git a/tex/context/base/mkiv/file-syn.mklx b/tex/context/base/mkiv/file-syn.mklx deleted file mode 100644 index 25f36f742..000000000 --- a/tex/context/base/mkiv/file-syn.mklx +++ /dev/null @@ -1,61 +0,0 @@ -%D \module -%D [ file=file-syn, % was core-fil, -%D version=20110701, % 1997.11.15, -%D title=\CONTEXT\ File Macros, -%D subtitle=Module Support, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt File Macros / Synonyms} - -\unprotect - -\registerctxluafile{file-syn}{} - -%D \macros -%D {definefilesynonym,definefilefallback} -%D -%D One of the problems with loading files is that their names can depend on the -%D interface language. We therefore need a method to define filesynonyms. The actual -%D synonyms are defined elsewhere, but look like: -%D -%D \starttyping -%D \definefilesynonym [chemic] [chemie] -%D \definefilesynonym [einheit] [unit] -%D \definefilesynonym [unit] [unit] -%D \stoptyping -%D -%D So we can say in english: -%D -%D \starttyping -%D \usemodules[pictex,chemic,unit] -%D \stoptyping -%D -%D and in dutch: -%D -%D \starttyping -%D \usemodules[pictex,chemie,unit] -%D \stoptyping - -\permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}} -\permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}} - -%D \macros -%D {truefilename} -%D -%D At the system level such a filename can be called upon by saying: -%D -%D \starttyping -%D \truefilename{filename/filesynonym} -%D \stoptyping -%D -%D The implementation shows that nesting is supported. - -\permanent\def\truefilename#1{\clf_truefilename{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/font-aux.mklx b/tex/context/base/mkiv/font-aux.mklx deleted file mode 100644 index caf32510e..000000000 --- a/tex/context/base/mkiv/font-aux.mklx +++ /dev/null @@ -1,26 +0,0 @@ -%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: - -\permanent\protected\def\xbox {\bgroup\aftergroup\egroup\hbox\bgroup\tx \let\next=} -\permanent\protected\def\xxbox{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=} - -\protect \endinput diff --git a/tex/context/base/mkiv/font-chk.mkxl b/tex/context/base/mkiv/font-chk.mkxl deleted file mode 100644 index b84056e4e..000000000 --- a/tex/context/base/mkiv/font-chk.mkxl +++ /dev/null @@ -1,29 +0,0 @@ -%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}{} - -\tracinglostchars\zerocount - -% Use this instead: -% -% \definefontfeature[default][default][missing=yes] -% \enabletrackers[fonts.missing=replace] - -\permanent\protected\def\checkcharactersinfont {\enabletrackers[fonts.missing]} -\permanent\protected\def\removemissingcharacters {\enabletrackers[fonts.missing=remove]} -\permanent\protected\def\replacemissingcharacters{\enabletrackers[fonts.missing=replace]} - -\endinput diff --git a/tex/context/base/mkiv/font-col.mklx b/tex/context/base/mkiv/font-col.mklx deleted file mode 100644 index 1dd5b25c6..000000000 --- a/tex/context/base/mkiv/font-col.mklx +++ /dev/null @@ -1,148 +0,0 @@ -%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. - -% 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] -% -% \definefontfeature [emboldened] [effect={width=0.1,delta=0.4,factor=0.3}] -% \definefontsynonym [SansEmboldened] [Sans] [features=emboldened] -% \definefontfallback[FakeSansCaps] [SansEmboldened] [0x0000-0xFFFF] [rscale=.8,method=uppercase] -% \definefontsynonym [SansCaps] [file:MyriadPro-Regular.otf] [fallbacks=FakeSansCaps] - -\writestatus{loading}{ConTeXt Font Macros / Collections} - -\registerctxluafile{font-col}{} - -\unprotect - -\permanent\tolerant\protected\def\definefontfallback[#name]#spacer[#font]#spacer[#ranges]#spacer[#settings]% - {\let\mathsizesuffix\relax - \clf_fontcollectiondefine{#name}{#font}{#ranges}{#settings}% - \let\mathsizesuffix\empty} - -\permanent\tolerant\protected\def\resetfontfallback[#name]#spacer[#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 - \ifempty\m_font_fallbacks - \ifempty\m_font_class_fallbacks\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}} - -% math (experiment, todo clf_) - -\def\font_fallbacks_register_math#1#2#3#4% - {\doifelsenothing{#3}% - {\definedfont[#2 at #4sp]}% - {\definedfont[#2*#3\space at #4\scaledpoint]}% - \clf_registerfontfallbackid#1\space\fontid\font\space{#2}} - -% \def\font_fallbacks_finish_math -% {\ctxlua{mathematics.finishfallbacks()}} - -% 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/tex/context/base/mkiv/font-emp.mklx b/tex/context/base/mkiv/font-emp.mklx deleted file mode 100644 index da993a82c..000000000 --- a/tex/context/base/mkiv/font-emp.mklx +++ /dev/null @@ -1,256 +0,0 @@ -%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 \type {\em} (\TUGNEWS\ -%D Vol.~3, no.~1, 1994). His implementation was a bit more sophisticated version of -%D the standard \LATEX\ one. We further enhanced the macro, so now it also adapts -%D itself to boldface mode. Because we favor {\sl slanted} type over {\it italic}, -%D we made the emphasis 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 \protected\def\emphasistypeface{\sl} -%D \protected\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% - \orelse\ifx\m_font_emphasized_typeface\v!italic - #italic% - \orelse\ifempty\m_font_emphasized_typeface - #slanted% - \else - \csname\m_font_emphasized_typeface\endcsname - \fi} - -\permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it} -\permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi} - -\permanent\protected\def\normalboldface % public - {\relax - \ifx\fontalternative\s!it\bi\orelse - \ifx\fontalternative\s!sl\bs\else - \bf\fi} - -\permanent\protected\def\normalitalicface % public - {\relax - \ifx\fontalternative\s!tf\it\orelse - \ifx\fontalternative\s!bf\bi\else - \tf\fi} - -\permanent\protected\def\normalslantedface % public - {\relax \ifx\fontalternative\s!tf\sl - \orelse\ifx\fontalternative\s!bf\bs - \else \tf\fi} - -\permanent\protected\def\normaltypeface % public - {\relax - \ifx\fontalternative\s!bi \it \orelse - \ifx\fontalternative\s!bs \sl \else - \tf \fi} - -\permanent\protected\def\swaptypeface % public - {\relax - \ifx\fontalternative\s!it \tf \orelse - \ifx\fontalternative\s!sl \tf \orelse - \ifx\fontalternative\s!bf \emphasisboldface \orelse - \ifx\fontalternative\s!bs \bf \orelse - \ifx\fontalternative\s!bi \bf \else - \emphasistypeface \fi} - -\let\typeface \normaltypeface % public -\let\boldface \normalboldface % public -\let\slantedface\normalslantedface % public -\let\italicface \normalitalicface % public -\let\swapface \swaptypeface % public - -%D To be set with the default body font environment: \type {em} being \type -%D {slanted} or \type {italic}. - -% maybe a \csname...\fontalternative\endcsname - -\newconditional\c_font_emphasis_needed - -\permanent\protected\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 - \enforced\permanent\protected\def\emphasistypeface{\it}\tf - \orelse\ifx\fontalternative\s!sl - \enforced\permanent\protected\def\emphasistypeface{\sl}\tf - \orelse\ifx\fontalternative\s!bf - \emphasisboldface - \orelse\ifx\fontalternative\s!bs - \enforced\permanent\protected\def\emphasisboldface{\bs}\bf - \orelse\ifx\fontalternative\s!bi - \enforced\permanent\protected\def\emphasisboldface{\bi}\bf - \else - \emphasistypeface - \fi - \ifconditional\c_font_emphasis_needed\else - \expandafter\aftergroup - \fi - \emphasiscorrection} - -%D The next feature was not present in previous versions. It takes care of \type -%D {\em \bf ...} situations. - -\let\font_emphasis_saved_emphasis_boldface\relax - -\def\font_emphasis_set_emphasis_boldface - {\let\font_emphasis_saved_emphasis_boldface\bf - \let\font_emphasis_set_emphasis_boldface\relax - \enforced\let\bf\font_emphasis_bold_bold} - -\protected\def\font_emphasis_bold_bold - {%\relax - \enforced\let\bf\relax % new - \ifx\fontalternative\s!it - \bi - \orelse\ifx\fontalternative\s!sl - \bs - \else - \font_emphasis_saved_emphasis_boldface - \fi - \enforced\let\bf\font_emphasis_saved_emphasis_boldface} - -%D Donald's (adapted) macros take the next character into account when placing -%D italic correction. As a bonus we also look for something that looks like a dash, -%D in which case we don't correct. - -\let\italiccorrection=\/ % tex primitive - -\permanent\protected\def\emphasiscorrection % public, not in raw alignment groups, else omit problem - {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else - \expandafter\expandafter\expandafter\font_emphasis_look - \fi\fi} - -\def\font_emphasis_look - {\begingroup - \futurelet\nexttoken\font_emphasis_test} - -\def\font_emphasis_test - {\ifcat\noexpand\nexttoken,% we can do better in luatex ... some day ... - \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 - \ifzeropt\ht\scratchbox % probably a space - \expandafter\font_emphasis_b - \orelse\ifdim\ht\scratchbox<.3\exheight - \expandafter\expandafter\expandafter\endgroup - \else - \expandafter\expandafter\expandafter\font_emphasis_b - \fi} - -\def\font_emphasis_b - {\scratchskip\lastskip - \ifzeropt\scratchskip - \italiccorrection\relax - \else - \unskip\italiccorrection\hskip\scratchskip - \fi - \endgroup} - -%D We end with some examples which show the behavior when some punctuation is met. -%D We also show how the mechanism 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 their style as good as -%D possible. These macros are obsolete in \MKIV. - -% \protected\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} -% \protected\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} -% \protected\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} -% \protected\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} -% \protected\def\emph {\groupedcommand{\em}{}} - -\protected\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}} -\protected\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}} -\protected\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}} -\protected\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}} - -\permanent\protected\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf} -\permanent\protected\def\emphit{\triggergroupedcommandcs\font_emphasis_it} -\permanent\protected\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl} -\permanent\protected\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf} -\permanent\protected\def\emph {\triggergroupedcommandcs\em} - -\permanent\protected\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/tex/context/base/mkiv/font-fea.mklx b/tex/context/base/mkiv/font-fea.mklx deleted file mode 100644 index 5f83c87d3..000000000 --- a/tex/context/base/mkiv/font-fea.mklx +++ /dev/null @@ -1,382 +0,0 @@ -%D \module -%D [ file=font-sty, -%D version=2011.01.13, % (copied fron font-ini) -%D title=\CONTEXT\ Font Macros, -%D subtitle=features, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Font Macros / Features} - -\unprotect - -%D Feature management. -%D -%D \starttyping -%D \definefontfeature[smallcaps][smcp=yes,script=latn] -%D \definefontfeature[smallcaps][SmallCapitals=yes,script=latn] -%D \definefontfeature[smallcaps][Small Capitals=yes,script=latn] -%D \definefontfeature[smallcaps][small capitals=yes,script=latn] -%D \definefontfeature[smallcaps][smallcapitals=yes,script=latn] -%D -%D \definedfont[cambria*smallcaps] test -%D -%D \starttext -%D \definefontfeature[basekerned][default][mode=base] -%D \definefontfeature[nodekerned][default][mode=node] -%D \definefontfeature[nonekerned][default][mode=base,kern=no] -%D \setupcolors[state=start] -%D \startoverlay -%D {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }} -%D {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }} -%D {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }} -%D \stopoverlay -%D \stoptext -%D -%D \enabletrackers[otf.kerns] -%D -%D \definefontfeature[withkern][default][mode=node] -%D \definefontfeature[nokern] [default][mode=node,kern=no] -%D \definefontfeature[single] [default][mode=node,cpsp=yes] -%D \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no] -%D -%D {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} -%D {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} -%D {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} -%D {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} -%D \stoptyping - -% \definefontfeature[slanted] [default][slant=.25] -% \definefontfeature[stretched][default][stretch=2] -% -% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop -% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop -% -% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes] -% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn] -% -% \starttypescript [serif] [palatino-nova-regular] [name] -% \definefontsynonym[Serif] [palatinonova-regular][features=default] -% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif -% \stoptypescript -% -% \starttypescript [serif] [palatino-nova-regular] [name] -% \definefontsynonym[Serif] [palatinonova-regular*default] -% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps] -% \stoptypescript -% -% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface] -% -% \starttext -% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl -% \stoptext -% -% \definefontfeature -% [default-base] -% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes] -% \definefontfeature -% [default-node] -% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node] -% \definefontfeature -% [default-none] -% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes] -% -% \startoverlay -% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}} -% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}} -% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}} -% \stopoverlay -% -% \blank -% -% \startoverlay -% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}} -% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}} -% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}} -% \stopoverlay -% -% \blank -% -% \startoverlay -% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}} -% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}} -% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}} -% \stopoverlay -% -% \startoverlay -% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}} -% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}} -% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}} -% \stopoverlay -% -% \definefontfeature[superdefault][default][compose=yes] -% -% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683} -% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683} - -\permanent\tolerant\protected\def\definefontfeature[#featureset]#spacer[#parent]#spacer[#settings]% - {\clf_definefontfeature{#featureset}{#parent}{#settings}} - -\permanent\tolerant\protected\def\adaptfontfeature[#pattern]#spacer[#settings]% - {\clf_adaptfontfeature{#pattern}{#settings}} - -\permanent\protected\def\fontfeatureslist[#name]#spacer[#separator]% todo: arg voor type - {\clf_featurelist{#name}{\detokenize{#separator}}} - -\attribute\zerocount\attributeunsetvalue - -\glyphdatafield\zerocount - -\let\font_dynamic_value\glyphdatafield - -% beware: these are global features on top of existing font features - -\let\currentfeature \s!current -\let\m_font_feature_list \s!current -\let\m_font_feature_asked\empty - -\newconstant\c_font_feature_state - -% hashing at this end is slower - -\permanent\tolerant\protected\def\addfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_add} -\permanent\tolerant\protected\def\subtractfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_subtract} -\permanent\tolerant\protected\def\replacefeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_replace} -\permanent\tolerant\protected\def\resetandaddfeature[#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_reset_add} -\permanent\tolerant\protected\def\feature [#1]#;#2{\begincsname\??featureshortcut#1#2\endcsname} - -% for old times sake - -\permanent\protected\def\doaddfeature #1{\edef\m_font_feature_asked{#1}\font_feature_add} -\permanent\protected\def\dosubtractfeature #1{\edef\m_font_feature_asked{#1}\font_feature_subtract} -\permanent\protected\def\doreplacefeature #1{\edef\m_font_feature_asked{#1}\font_feature_replace} -\permanent\protected\def\doresetandaddfeature#1{\edef\m_font_feature_asked{#1}\font_feature_reset_add} - -\protected\def\font_feature_add - {\ifnum\c_font_feature_state=\plusone - \ifx\m_font_feature_asked\currentfeature\else - \font_feature_add_indeed - \fi - \else - \font_feature_add_indeed - \fi} - -\protected\def\font_feature_add_indeed - {\clf_addfeature{\m_font_feature_list}{\m_font_feature_asked}% - \edef\m_font_feature_list{\m_font_feature_list+\m_font_feature_asked}% also + at the lua end - \c_font_feature_state\plusone - \let\currentfeature\m_font_feature_asked} - -\protected\def\font_feature_subtract - {\ifnum\c_font_feature_state=\minusone - \ifx\m_font_feature_asked\currentfeature\else - \font_feature_subtract_indeed - \fi - \else - \font_feature_subtract_indeed - \fi} - -\protected\def\font_feature_subtract_indeed - {\clf_subtractfeature{\m_font_feature_list}{\m_font_feature_asked}% - \edef\m_font_feature_list{\m_font_feature_list-\m_font_feature_asked}% also - at the lua end - \c_font_feature_state\minusone - \let\currentfeature\m_font_feature_asked} - -\protected\def\font_feature_replace - {\ifnum\c_font_feature_state=\zerocount - \ifx\m_font_feature_asked\currentfeature\else - \font_feature_replace_indeed - \fi - \else - \font_feature_replace_indeed - \fi} - -\protected\def\font_feature_replace_indeed - {\clf_replacefeature{\m_font_feature_list}{\m_font_feature_asked}% - \edef\m_font_feature_list{\m_font_feature_list=\m_font_feature_asked}% also = at the lua end - \c_font_feature_state\zerocount - \let\currentfeature\m_font_feature_asked} - -\permanent\protected\def\resetfeature - {\ifx\currentfeature\s!current \else - \font_feature_reset_indeed - \fi} - -\protected\def\font_feature_reset_indeed - {\let\m_font_feature_asked\empty - \let\currentfeature \s!current - \let\m_font_feature_list \s!current - \clf_resetfeature} - -\permanent\protected\def\revivefeature - {\ifx\currentfeature\s!current \else - \font_feature_revive_indeed - \fi} - -\protected\def\font_feature_revive_indeed - {\clf_revivefeature{\m_font_feature_list}} - -\protected\def\font_feature_reset_add - {\ifnum\c_font_feature_state=\plusone - \ifx\m_font_feature_asked\currentfeature\else - \font_feature_reset_add_indeed - \fi - \else - \font_feature_reset_add_indeed - \fi} - -\protected\def\font_feature_reset_add_indeed - {\clf_addfeature{\s!current}{\m_font_feature_asked}% - \edef\m_font_feature_list{\s!current+\m_font_feature_asked}% also + at the lua end - \c_font_feature_state\plusone - \let\currentfeature\m_font_feature_asked} - -\installcorenamespace{featureshortcut} - -\letvalue{\??featureshortcut +}\addfeature -\letvalue{\??featureshortcut -}\subtractfeature -\letvalue{\??featureshortcut =}\replacefeature -\letvalue{\??featureshortcut !}\resetandaddfeature -\letvalue{\??featureshortcut >}\revivefeature -\letvalue{\??featureshortcut <}\resetfeature - -\letvalue{\??featureshortcut\v!more }\addfeature % add set to previous set and combine with font set -\letvalue{\??featureshortcut\v!less }\subtractfeature % subtract set from previous set and combine with font set -\letvalue{\??featureshortcut\v!new }\replacefeature % replace font set -\letvalue{\??featureshortcut\v!reset }\resetfeature % forget sets and revert to font set -\letvalue{\??featureshortcut\v!default}\revivefeature % make sure the current set is used on top of the font set -\letvalue{\??featureshortcut\v!old }\revivefeature -\letvalue{\??featureshortcut\v!local }\resetandaddfeature -\letvalue{\??featureshortcut\s!unknown}\empty - -% experimental bonus: - -% \protected\def\addfflanguage -% {\ifnum\c_font_feature_state=\plusone -% \ifx\currentlanguage\currentfeature\else -% \font_feature_add_language_indeed -% \fi -% \else -% \font_feature_add_language_indeed -% \fi} -% -% \protected\def\font_feature_add_language_indeed -% {\clf_addfeature{\m_font_feature_list}{\currentlanguage}% -% \edef\m_font_feature_list{\m_font_feature_list+\currentlanguage}% also + at the lua end -% \c_font_feature_state\plusone -% \let\currentfeature\currentlanguage} -% -% some 3% slower: - -% \protected\def\addfflanguage -% {\let\m_font_feature_asked\currentlanguage -% \font_feature_add} - -\let\m_font_feature_language\currentlanguage - -\permanent\protected\def\addfflanguage - {\ifx\currentlanguage\m_font_feature_language\else - \let\m_font_feature_language\currentlanguage - \let\m_font_feature_asked \currentlanguage - \font_feature_add - \fi} - -% just for old times sake: - -\permanent\protected\def\featureattribute#feature% - {\clf_featureattribute{#feature}} - -\permanent\protected\def\setfontfeature#feature% - {\edef\currentfeature{#feature}% - \let\m_font_feature_list\currentfeature - \clf_setfontfeature{\currentfeature}} - -% these are obsolete (don't use them any longer) - -\aliased\let\resetfontfeature\resetfeature % obsolete - -% these are obsolete (don't use them any longer) - -% \let\addfontfeaturetoset \font_feature_add_nop % obsolete -% \let\subtractfontfeaturefromset \font_feature_subtract_nop % obsolete -% \let\addfontfeaturetofont \font_feature_add_nop % obsolete -% \let\subtractfontfeaturefromfont\font_feature_subtract_nop % obsolete - -% these are obsolete (don't use them any longer) - -\aliased\let\setff\setfontfeature % obsolete -\aliased\let\addfs\doaddfeature % obsolete -\aliased\let\subfs\dosubtractfeature % obsolete -\aliased\let\addff\doaddfeature % obsolete -\aliased\let\subff\dosubtractfeature % obsolete - -%D \macros -%D {os} -%D -%D In good old \TEX, the old style numerals were often taken from the math fonts. No -%D longer. - -\definefontfeature - [just-os] - [mode=node,onum=yes] - -%frozen\protected\def\sc{\setfontfeature{smallcaps}} -\permanent\protected\def\os{\setfontfeature{just-os}} - -% \doifelsecurrentfonthasfeature{smcp}{YES}{NO} -% \doifelsecurrentfonthasfeature{crap}{YES}{NO} -% \doifelsecurrentfonthasfeature{kern}{YES}{NO} - -\permanent\def\doifelsecurrentfonthasfeature#feature{\clf_doifelsecurrentfonthasfeature{#feature}} % expandable -\permanent\def\doifelsefontfeature #feature{\clf_doifelsefontfeature {#feature}} % expandable -\permanent\def\doifunknownfontfeature #feature{\clf_doifunknownfontfeature {#feature}} % expandable - -\aliased\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature -\aliased\let\doiffontfeatureelse \doifelsefontfeature - -% new: - -\clf_registerlanguagefeatures - -% also new - -\permanent\protected\def\useaddfontfeatureparameter#namespace% faster local variant - {\edef\m_font_feature_asked{#namespace\c!features}% - \ifempty\m_font_feature_asked\else - \font_feature_add - \fi} - -% let's put this here: - -\permanent\protected\def\slashedzero - {\dontleavehmode - \begingroup - %\addff{zero} - \doaddfeature{zero}% - 0% - \endgroup} - -% not nice but maybe handy - -% \starttyping -% \blockligatures[fi,ff] \blockligatures[fl] -% -% \definefontfeature[default:b][default][blockligatures=yes] -% -% \setupbodyfont[pagella] \showfontkerns -% -% \definedfont[Serif*default:b] -% -% \startTEXpage[offset=1em] -% fi ff fl -% \stopTEXpage -% \stoptyping - -\permanent\protected\def\blockligatures[#1]{\clf_blockligatures{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/font-fil.mklx b/tex/context/base/mkiv/font-fil.mklx deleted file mode 100644 index 7f618179c..000000000 --- a/tex/context/base/mkiv/font-fil.mklx +++ /dev/null @@ -1,385 +0,0 @@ -%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 complicated by the way -%D fonts are handled. Apart from the many encodings, we also deal with different -%D naming schemes. Confronted with this problem, I decided to change the definitions -%D 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] - -\permanent\protected\tolerant\protected\def\startfontclass[#class]% - {\push_macro_fontclass - \doifelse{#class}\v!each - {\let\fontclass\empty} - {\doifsomething{#class}{\def\fontclass{#class}}}} - -\permanent\protected\def\stopfontclass - {\pop_macro_fontclass} - -\permanent\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt] - -%D \macros -%D {definefontsynonym, doifelsefontsynonym, -%D expandfontsynonym, truefontname, truefontdata} -%D -%D While looking for fonts, fontsynonyms are used for accessing 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} - -\permanent\protected\def\definefontsynonym[#name]#spacer[#file]% - {\edef\m_font_name{#name}% - \edef\m_font_file{#file}% - \ifempty\fontclass - \expandafter\font_basics_define_font_synonym_nop - \else - \expandafter\font_basics_define_font_synonym_yes - \fi} - -\protected\def\font_basics_define_font_synonym_nop - {\letcsname\??fontfile\m_font_name\endcsname\m_font_file - \doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil} - -\protected\def\font_basics_define_font_synonym_yes - {\letcsname\??fontfile\fontclass\m_font_name\endcsname\m_font_file - \doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil} - -\protected\def\edefinefontsynonym[#name]#spacer[#file]% - {\edef\m_font_name{#name}% - \edef\m_font_file{#file}% - \ifempty\fontclass - \expandafter\font_basics_define_font_synonym_nop_expanded - \else - \expandafter\font_basics_define_font_synonym_yes_expanded - \fi} - -\protected\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]% - {\letcsname\??fontfile\m_font_name\endcsname\m_font_file - \normalexpanded{\font_basics_define_font_synonym_nop_opt[#spec]}} - -\protected\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]% - {\letcsname\??fontfile\fontclass\m_font_name\endcsname\m_font_file - \normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}} - -\protected\def\font_basics_define_font_synonym_nop_opt[#specification]% - {\let\p_features \undefined - \let\p_fallbacks \undefined - \let\p_goodies \undefined - \let\p_designsize\undefined - \expandafter\font_basics_get_font_parameter_nop#specification,\ignorearguments} - -\protected\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,\ignorearguments} - -% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that -% can be default then: \let\mathsizesuffix\relax .. i need to play with it first - -\def\font_basics_get_font_parameter_nop#key=#value,% - {\ifarguments - \font_basics_get_font_parameter_nop_finish - \else - \defcsname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix - \expandafter\font_basics_get_font_parameter_nop - \fi} - -\def\font_basics_get_font_parameter_yes#key=#value,% - {\ifarguments - \font_basics_get_font_parameter_yes_finish - \else - \defcsname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix - \expandafter\font_basics_get_font_parameter_yes - \fi} - -% helpers, some day these will be toks and counts - -% \def\fntsetdefname {\glet\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 - {\letcsname\??fontfile\m_font_name\s!features \endcsname\undefined - \letcsname\??fontfile\m_font_name\s!fallbacks \endcsname\undefined - \letcsname\??fontfile\m_font_name\s!goodies \endcsname\undefined - \letcsname\??fontfile\m_font_name\s!designsize\endcsname\undefined} - -\def\font_basics_define_font_synonym_yes_nil - {\global\letcsname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined - \global\letcsname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined - \global\letcsname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined - \global\letcsname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined} - -\def\font_basics_get_font_parameter_nop_finish - {\letcsname\??fontfile\m_font_name\s!features \endcsname\p_features - \letcsname\??fontfile\m_font_name\s!fallbacks \endcsname\p_fallbacks - \letcsname\??fontfile\m_font_name\s!goodies \endcsname\p_goodies - \letcsname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize} - -\def\font_basics_get_font_parameter_yes_finish - {\global\letcsname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features - \global\letcsname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks - \global\letcsname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies - \global\letcsname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize} - -%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}] -%\defineclassfontsynonym [KopFont] [officina] [SerifBold] -%\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]} - -\permanent\tolerant\protected\def\defineclassfontsynonym[#tag]#spacer[#class]#spacer[#fileortag]% needs testing - {\defcsname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}% - \font_basics_define_font_synonym_yes_nil} - -\aliased\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater - -\permanent\tolerant\protected\def\setupfontsynonym[#name]#spacer[#settings]% not yet supported, will do when needed - {} - -% todo: replace * by ... less messy with features - -% no \ifempty here as #1 can be empty - -\permanent\def\truefontname#name% - {\expandafter\font_helpers_true_fontname#name*\empty*\relax} - -\def\font_helpers_true_fontname#name*#first#rest*#ignore\relax - {\ifcsname\??fontfile\fontclass#name\endcsname - \ifx#first\empty - \expandafter\truefontname\lastnamedcs - \else - \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% - \fi - \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname - \ifx#first\empty - \expandafter\truefontname\lastnamedcs - \else - \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% - \fi - \orelse\ifcsname\??fontfile#name\endcsname - \ifx#first\empty - \expandafter\truefontname\lastnamedcs - \else - \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% - \fi - \else - #name\ifx#first\empty\else*#first#rest\fi - \fi} - -\def\font_helpers_true_fontname_check#name% - {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax} - -\def\font_helpers_true_fontname_check_indeed#name*#ignore\relax - {\ifcsname\??fontfile\fontclass#name\endcsname - \expandafter\font_helpers_true_fontname_check\lastnamedcs - \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname - \expandafter\font_helpers_true_fontname_check\lastnamedcs - \orelse\ifcsname\??fontfile#name\endcsname - \expandafter\font_helpers_true_fontname_check\lastnamedcs - \else - #name% - \fi} - -% ok when the last lookup is not stripped .. we need to be able to define synonyms for symbols - -\permanent\def\expandfontsynonym#command#name% one level expansion - {\ifcsname\??fontfile\fontclass#name\endcsname - \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% - \orelse\ifcsname\??fontfile\defaultfontclass#2\endcsname - \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% - \fi} - -\permanent\def\doifelsefontsynonym#name% - {\ifcsname\??fontfile\fontclass#name\endcsname - \expandafter\firstoftwoarguments - \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiffontsynonymelse\doifelsefontsynonym - -%D \macros -%D {tracedfontname} -%D -%D A goody: - -\permanent\def\tracedfontname#name% - {#name\ifcsname\??fontfile\fontclass#name\endcsname - %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname - \expandafter\tracedfontname\lastnamedcs - \orelse\ifcsname\??fontfile#name\endcsname - %\expandafter\tracedfontname\csname\??fontfile#name\endcsname - \expandafter\tracedfontname\lastnamedcs - \fi} - -%D \macros -%D {fontclass, defaultfontclass} -%D -%D The fontclass model was introduced a while after we implement the basic font -%D model and at that time we still defaulted to no model at all. Nowadays we default -%D to the \type {modern} fontclass. - -\let\fontclass \empty -\let\defaultfontclass\empty - -\permanent\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting - {\ifcsname\??fontfile#class#name\endcsname - \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}% - \orelse\ifcsname\??fontfile#name\endcsname - \fontclassname{#class}{\csname\??fontfile#name\endcsname}% - \else - #2% - \fi} - -\installmacrostack\fontclass - -%D Files or names can have properties and these need to be consulted at some point. -%D They can inherit them. - -% Why these expanded and rscale not ... maybe not worth the trouble (delayed -% expansion actually would be better i.e. macros in feature specs). Test without -% pre-expansion. - -\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{\lastnamedcs}\orelse % class + symbolic_name - \ifcsname\??fontfile #name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse % symbolic_name - \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \orelse % class + parent_name - \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % parent_name - \let\m_font_features\empty\fi} - -\def\font_helpers_set_fallbacks_yes#name% - {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse - \ifcsname\??fontfile #name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse - \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \orelse - \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else - \let\m_font_fallbacks\empty\fi} - -\def\font_helpers_set_goodies_yes#name% - {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse - \ifcsname\??fontfile #name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse - \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \orelse - \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else - \let\m_font_goodies\empty\fi} - -\def\font_helpers_set_designsize_yes#name% - {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse - \ifcsname\??fontfile #name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse - \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \orelse - \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else - \let\m_font_designsize\empty\fi} - -\def\font_helpers_set_features_nop#name% - {\ifcsname\??fontfile#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse - \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_features_nop\lastnamedcs \else - \let\m_font_features\empty\fi} - -\def\font_helpers_set_fallbacks_nop#name% - {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse - \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_fallbacks_nop\lastnamedcs \else - \let\m_font_fallbacks\empty\fi} - -\def\font_helpers_set_goodies_nop#name% - {\ifcsname\??fontfile#name\s!goodies\endcsname \edef\m_font_goodies{\lastnamedcs}\orelse - \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_goodies_nop\lastnamedcs \else - \let\m_font_goodies\empty\fi} - -\def\font_helpers_set_designsize_nop#name% - {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse - \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_designsize_nop\lastnamedcs \else - \let\m_font_designsize\empty\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 - {\ifempty\fontclass\font_helpers_update_font_parameters_nop\else\font_helpers_update_font_parameters_yes\fi} - -\installcorenamespace{fontclass} - -% we can pack them (don't use \setxvalue!) - -\permanent\protected\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction% - {\global\letcsname\??fontclass\fontclass#style\s!rscale \endcsname#rscale% - \global\letcsname\??fontclass\fontclass#style\s!features \endcsname#features% - \global\letcsname\??fontclass\fontclass#style\s!fallbacks \endcsname#fallbacks% - \global\letcsname\??fontclass\fontclass#style\s!goodies \endcsname#goodies% - \global\letcsname\??fontclass\fontclass#style\s!designsize\endcsname#designsize% - \global\letcsname\??fontclass\fontclass#style\s!direction \endcsname#direction}% math - -% bonus - -\let\currentfontinstancespec\clf_currentfontinstancespec % expandable - -\protect \endinput diff --git a/tex/context/base/mkiv/font-ini.mklx b/tex/context/base/mkiv/font-ini.mklx deleted file mode 100644 index 7bb7f832a..000000000 --- a/tex/context/base/mkiv/font-ini.mklx +++ /dev/null @@ -1,2512 +0,0 @@ -%D \module -%D [ file=font-ini, -%D version=1998.09.11, % (second) -%D version=2001.02.20, % (third) -%D title=\CONTEXT\ Font Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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: frozen tolerant iftok etc - -% 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 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 pure \TEX\ ones, the -%D 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 at}. This means as -%D much as: scale the bodyfontsize with this factor. The scaled option is not that -%D useful as one needs to know the design size. -%D -%D Because \type {sa} (scaled at) and \type {mo} (mapped on) are not low level \TEX\ -%D supported alternatives, we have to test for it ourselves. In doing so, we need an -%D auxiliary \DIMENSION. We cannot use \type{\scratchdimen} because font loading can -%D happen at any moment due to postponed loading. We could instead have used dirty -%D grouping tricks, but this 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, we distinguish -%D between several styles. In most cases we will 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 using Lucida Bright we -%D 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}) we can define a number -%D 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}. Users are not confronted -%D with sizes, but use the style or style+alternative to activate them. -%D -%D During the definition of a bodyfont one can also declare the available larger -%D 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 larger alternatives on the -%D other hand have no limitations. -%D -%D These larger alternatives are mostly used in chapter and section titles or on -%D title pages. When one switches to a larger alternative, the bold an other ones -%D automatically 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 before, we tried to make -%D 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 normally sized -%D typeface. This commands results in roman, sans serif, teletype or whatever style -%D is in charge. Such rather massive switches of style sometimes take more -%D processing time than comfortable. Of course there is a workaround for this: we -%D can call fonts directly by means of commands like: -%D -%D \starttyping -%D \rmtf \sssl \tttf \rmbsa -%D \stoptyping -%D -%D One should realize that this fast calls have limitations, they lack for instance -%D automatic super- and subscript support. -%D -%D This leaves us two more commands: \type {\tx} and \type {\txx}. These activate a -%D smaller and even more smaller font than the current one and adapt themselves to -%D the current alternative, so when \type {\bf} is active, \type {\tx} gives a -%D smaller boldface, which in turn can be called directly by \type {\bfx}. -%D -%D These two smaller alternatives are specified by the bodyfont environment and -%D therefore not necessarily have similar sizes as \type {\scriptsize} and \type -%D {\scriptscriptsize}. The main reason for this incompatibility (which can easily -%D be undone) lays in the fact that we often want a bit bigger characters than in -%D math mode. In \CONTEXT\ for instance the \type {\tx} and \type {\txx} commands -%D are used for surrogate \cap {smallcaps} which support both nesting and -%D alternatives, 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 \cap {THIS}: -%D \ruledhbox {$\rm \scriptstyle scriptstyle: THIS$} or \ruledhbox {\cap {x style: -%D THIS}} makes a big difference. -%D -%D The \type {x..d} sizes should be used grouped. If you don't group them, i.e. call -%D them in a row, \CONTEXT\ will not be able to sort out your intention (\type {x} -%D inside \type {d} inside \type {x}. etc.). The following table 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 - -\appendtoks - \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 -\to \everyjob - -%D Tracing - -\newtoks\t_font_tracers_definitions - -\permanent\protected\def\tracefontdefinitions - {\the\t_font_tracers_definitions} - -%D Some housekeeping macros: - -\permanent\protected\def\setfontparameters - {\setfalse\c_font_synchronize - \the\everybodyfont - \settrue\c_font_synchronize} - -\let\savedfont\empty - -\installmacrostack\savedfont - -% \fontname\font : string -% \fontid \font : integer -% \the \font : token (reference to font) -% \fontspecifiedname : string -% \the \fontspecifiedsize : dimension - -\permanent\protected\def\savefont - {\edef\savedfont{\the\font}% - \push_macro_savedfont} - -\permanent\protected\def\restorefont - {\pop_macro_savedfont - \savedfont} - -\permanent\protected\def\pushcurrentfont - {\enforced\permanent\protected\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} - -\mutable\let\thedefinedfont\relax % not to be confused with \everydefinefont - -\permanent\tolerant\protected\def\definedfont[#specification]% - {\ifarguments - \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly - \or - \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly - \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% - \fi - \thedefinedfont - \the\everydefinedfont} - -%D \macros{startfont} - -\permanent\protected\def\startfont{\begingroup\definedfont} -\permanent\protected\def\stopfont {\endgroup} - -%D \macros -%D {everybodyfont,everyglobalbodyfont} -%D -%D Every change in bodyfont size has conseqences for the baseline distance and skips -%D between paragraphs. These are initialized in other modules. Here we only provide -%D the hooks that 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 -%D Here we have to distinguish between the global (overal) bodyfont size and the -%D local (sometimes in the textflow) size. We store these dimensions in two -%D \DIMENSION\ registers. These registers are 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 {\the}'d -%D value comes out as 12.0pt, which is often not the way users specify the bodyfont -%D size. Therefore we use normalized values. They are cached to save overhead in -%D \LUA\ calls. - -\installcorenamespace{fontnormalizedbody} - -\protected\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\letcsname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro} - -\permanent\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 slightly different sizes -%D than the ones given. This happens for instance with the Math Times fonts. Mapped -%D font sizes can be specified by using the \type {mo} key instead of \type {sa} in -%D 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} - -\permanent\tolerant\protected\def\mapfontsize[#from]#spacer[#to]% - {\ifarguments\or\or\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}\fi} - -\def\font_basics_set_mapped_fontsize#from% - {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname - \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 - \orelse\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr - \lastnamedcs - \else - \v_font_rscale_default - \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% - {\letcsname\??fontbodyknown#body\endcsname\empty} - -%D \macros -%D {definefontstyle,definefontsize,definefontalternative} -%D -%D When setting of switching the overall style we can use the short identifier like -%D rm and ss, but when defined we can also use more verbose names like roman or -%D sansserif. Such 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{\letcsname\??fontstyleknown #style\endcsname\empty} -\def\font_helpers_register_size #size{\letcsname\??fontsizeknown #size\endcsname\empty} -\def\font_helpers_register_alternative#alternative{\letcsname\??fontalternativeknown#alternative\endcsname\empty} - -\permanent\protected\def\definefontstyle[#commands]#spacer[#style]% style: rm ss tt ... - {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw) - \font_helpers_register_style{#style}% - \toksapp\t_font_style_commands{\m_font_style_command{#style}}% - \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}} - -\permanent\protected\def\definefontsize[#size]% - {\ifcsname\??fontsizeknown#size\endcsname \else - \font_helpers_register_size{#size}% - \toksapp\t_font_size_commands{\m_font_size_command{#size}}% - \fi - \font_helpers_check_fontname_combinations} - -\permanent\protected\def\definefontalternative[#alternative]% - {\ifcsname\??fontalternativeknown#alternative\endcsname \else - \font_helpers_register_alternative{#alternative}% - \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}% - \fi - \font_helpers_check_fontname_combinations} - -\protected\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb) - {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s} - -\def\font_helpers_check_fontname_combinations_s#style% - {\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 of -%D the formal font interface once defined. The size can be empty (so checking is -%D needed as \type {\bf} is already defined). -%D -%D The \type {\normal..} variants are available as extras for cases where the \type -%D {..} 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% - {} - -\def\font_basics_check_text_bodyfont_step#whatever#body% size can be empty (checking needed as \bf is already defined) - {\ifcsname#whatever\endcsname\else - \permanent\setugvalue{#whatever}{#body}% - \fi} - -\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined) - {\font_basics_check_text_bodyfont_step{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma - \font_basics_check_text_bodyfont_step{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla - \font_basics_check_text_bodyfont_step{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla - \font_basics_check_text_bodyfont_step{#style}{\font_helpers_set_current_font_style{#style}}% \rm - \font_basics_check_text_bodyfont_step{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl - \font_basics_check_text_bodyfont_step{#style\s!x }{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx - \font_basics_check_text_bodyfont_step{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx - \font_basics_check_text_bodyfont_step{#alternative\s!x }{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx - \font_basics_check_text_bodyfont_step{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx - \font_basics_check_text_bodyfont_step{#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) demands: -%D -%D \startitemize -%D \item We support wildcards like \type {sa *} which will adapt to the current -%D size. This is also the default specification. -%D \item We support named scales like \type {sa d}; beware: \type {x} and \type {xx} -%D are valid scales but they are not alway the same as the ones used in for -%D instance \type {\bfx} because there the sized come from the bodyfont -%D environment. In the future there maybe a switch that also honors the -%D environment in named scales. -%D \stopitemize -%D -%D Keep in mind that the smaller sizes are just for text super and subscripts while -%D larger sizes can be used in titles where for 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 - -\permanent\def\safontscale{\number\dimexpr\v_font_size_absolute\relax} -\permanent\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax} - -\mutable\let\somefontname\s!unknown -\mutable\let\somefontspec\s!unknown -\mutable\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 - -\protected\def\font_helpers_low_level_define#specification#csname% - {% we can now set more at the lua end - \glet\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 - \ifempty\fontclass\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 - \letcsname#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 - \expandafter\let\expandafter\f_font_body_scale\lastnamedcs - \setfalse\c_font_body_scale % ! - \orelse\ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname - \expandafter\let\expandafter\f_font_body_scale\lastnamedcs - \settrue\c_font_body_scale - \orelse\ifcsname\??fontenvironments\fontbody#fontsize\endcsname - \expandafter\let\expandafter\f_font_body_scale\lastnamedcs - \setfalse\c_font_body_scale % ! - \orelse\ifcsname\??fontenvironments\s!default#fontsize\endcsname - \expandafter\let\expandafter\f_font_body_scale\lastnamedcs - \settrue\c_font_body_scale - \orelse\ifcsname\??fontenvironments\fontclass\s!default\s!text\endcsname - \expandafter\let\expandafter\f_font_body_scale\lastnamedcs - \settrue\c_font_body_scale - \orelse\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} - -\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue - -\tracingfonts\plussix % - -%D When fontclasses are used, we define the font global, since namespaces are -%D used. Otherwise we parse the specs each time. - -\mutable\let\fontfile\s!unknown - -%D Relatively new: - -\installcorenamespace{fonts} -\installcorenamespace{fontslanguage} - -\installsetuponlycommandhandler \??fonts {fonts} - -\newconstant\c_fonts_auto_language - -\letvalue{\??fontslanguage\v!auto}\plusone % experimental -%letvalue{\??fontslanguage\v!yes }\plustwo % less efficient, for experiments - -\appendtoks - \c_fonts_auto_language - \ifcsname\??fontslanguage\fontsparameter\c!language\endcsname - \lastnamedcs - \else - \zerocount - \fi -\to \everysetupfonts - -\appendtoks - \ifcase\c_fonts_auto_language - % nothing - \or - \addfflanguage - % \or - % font - \fi -\to \everylanguage - -% \setupfonts -% [\c!language=\v!auto] - -%D \macros -%D {everyfont,everyfontswitch} - -\ifdefined\everyfont \else \newtoks\everyfont \fi -\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi - -\permanent\def\setfontcharacteristics{\the\everyfont} - -% \appendtoks -% \ifcase\c_fonts_auto_language -% % nothing -% \or -% % auto -% \or -% \addfflanguage -% \fi -% \to \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 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: - -\permanent\tolerant\protected\def\definefont[#1]#*[#2]#*[#3]% [name][spec][1.6 | line=10pt | setup_id] - {\ifparameter#3\or - \expandafter\font_basics_define_font_a - \else - \expandafter\font_basics_define_font_b - \fi[#1][#2][#3]} - -\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. - -\permanent\tolerant\protected\def\definefrozenfont[#name]#spacer[#specification]#spacer[#settings]% - {\ifparameter#name\or - \begingroup - \definefont[#name][#specification][#settings]% - \csname#name\endcsname - \glet\lastglobalrawfontcall\lastrawfontcall - \endgroup - \letcsname#name\endcsname\lastglobalrawfontcall - \fi} - -%D The instance namespace protection makes the switch local so that we can redefine a -%D logical name and/or change the size in between. - -% 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 - -\mutable\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} - -\protected\def\font_helpers_trigger#identifier% make a traced variant - {\edef\lastfontidentifier{#identifier}% - \ifcsname\v_font_identifier_class\endcsname - % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}% - \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 including the \type {a}||\type -%D {d} sizes. The next macro returns the current scaling factor. Take a look at -%D \type {cont-log.tex} for an example of its use. - -\installcorenamespace{fontenvironments} - -\permanent\def\currentfontbodysize % gets number (the normal sa 1 etc) - {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname - \lastnamedcs - \orelse\ifcsname\??fontenvironments\s!default\somefontsize\endcsname - \lastnamedcs - \else - \somefontsize - \fi} - -\permanent\def\currentfontbodyscale % gets character (x xx a etc) - {\csname\??fontenvironments - \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\orelse - \ifcsname\??fontenvironments \s!default\fontsize\endcsname \s!default\fontsize\orelse - \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse - \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else - \s!default \fi - \endcsname} - -\def\font_currentfontbodyscale % gets character (x xx a etc) - {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments \s!default\fontsize\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else - \csname\??fontenvironments \s!default \endcsname \fi} - -\permanent\def\currentfontscale % used in default definition - {\csname\??fontenvironments - \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\orelse - \ifcsname\??fontenvironments \s!default\xfontsize\endcsname \s!default\fontsize\orelse - \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse - \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else - \s!default \fi - \endcsname} - -\def\font_currentfontscale % used in default definition - {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments \s!default\xfontsize\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else - \csname\??fontenvironments \s!default \endcsname \fi} - -\setvalue{\??fontenvironments\s!default}{1} - -%D In the following macros we use \type {\currentxfontsize} to hold the current -%D x||size of the font. This enables us to support for instance \type {\sl} inside a -%D \type {\tx} switch. - -\newconstant\currentxfontsize - -\permanent\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi} - -%D Now we enter the area of font switching. The switching mechanism has to take care -%D of several situations, like: -%D -%D \startitemize[packed] -%D \item changing the overal document fonts (including margins, headers and footers) -%D \item changing local fonts (only the running text) -%D \item smaller and even more smaller alternatives (super- and subscripts) -%D \stopitemize -%D -%D \TEX\ offers a powerfull family mechanism for super- and subscripts in math mode. -%D In text mode however, we don't use families for the smaller alternatives, and -%D therefore have to take care of it otherwise. -%D -%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 the moment we stick -%D 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 settings apply. All -%D second parameters are specified in dimensions and tell us more about related -%D 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 get -%D 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 environment checks -%D local. This means that multiple local checks resulting in definitions are not -%D that efficient. 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 - -\permanent\def\bodyfontvariable#parameter% - {\csname\??fontenvironments - \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\orelse - \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse - \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \normalizedbodyfontsize#parameter\orelse - \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi - \endcsname} - -\def\font_bodyfontvariable#parameter% - {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi} - -\permanent\def\bodyfontsizevariable#size#parameter% - {\csname\??fontenvironments - \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\orelse - \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse - \ifcsname\??fontenvironments #size#parameter\endcsname #size#parameter\orelse - \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi - \endcsname} - -\def\font_bodyfontsizevariable#size#parameter% - {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments #size#parameter\endcsname\lastnamedcs\orelse - \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi} - -\permanent\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere - -\permanent\def\bodyfontdimension#class#size#parameter#body% - {\the\dimexpr - \ifcsname\??fontenvironments #class#size#parameter\endcsname \lastnamedcs \orelse - \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\orelse % factor - \ifcsname\??fontenvironments #size#parameter\endcsname \lastnamedcs \else - \lastnamedcs\dimexpr#body\relax\fi % factor - \relax} - -\installcorenamespace{fontenvironmentknown} - -\def\font_helpers_register_environment#class#body% - {\letcsname\??fontenvironmentknown#class#body\endcsname\empty} - -\newmacro\m_font_body -\newmacro\m_font_body_normalized - -\permanent\tolerant\protected\def\definebodyfontenvironment[#1]#*[#2]#*[#3]% todo - {\ifarguments - \expandafter\font_basics_define_body_font_environment_unset - \or - \expandafter\font_basics_define_body_font_environment_unset - \or - \expandafter\font_basics_define_body_font_environment_empty - \or - \expandafter\font_basics_define_body_font_environment_class - \fi[#1][#2][#3]} - -\aliased\let\setupbodyfontenvironment\definebodyfontenvironment - -%D First we handle the class specific case. Beware: you can change values before -%D a bodyfont is loaded but changing them afterwards can be sort of tricky as -%D values are not consulted afterwards. - -\permanent\def\processbodyfontenvironmentlist#1% no \protected as then we cannot use it in alignments (still?) - {\clf_processbodyfontsizes{\strippedcsname#1}} - -\permanent\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 settings -%D (just to be sure, as it's not really needed). - -\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]% - {\push_macro_fontclass - \let\fontclass\empty - \font_basics_define_body_font_environment_class[][#body][#settings]% - \pop_macro_fontclass} - -\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]% - {\push_macro_fontclass - \let\fontclass\empty - \font_basics_define_body_font_environment_class[][#body][]% - \pop_macro_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 - \orelse\ifproductionrun - \push_macro_fontclass - \edef\fontclass{#class}% - \font_helpers_register_environment{#class}{#normalizedbody}% - \settrue\c_font_defining_environment_state - \font_helpers_define_unknown_font{#normalizedbody}% current class - \setfalse\c_font_defining_environment_state - \pop_macro_fontclass - \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 setup is valid -%D too: -%D -%D \starttyping -%D \definebodyfontenvironment[24pt] -%D \stoptyping -%D -%D All parameters can be redefined when needed, so one doesnot have to stick to the -%D default ones. - -%D \macros -%D {definebodyfont} -%D -%D The next step in defining a bodyfont involves the actual font files, which can be -%D recognized by their extension \type {tfm}. Installing those file is often beyond -%D the 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 size(s), the style -%D group to which the definitions belong, and an alternative, as specified by the -%D \TEX\ (math) families, extended with~a, b~\unknown. -%D -%D We show two examples, that show all the alternative scaling options. The \type -%D {\tfa} alternatives can be extended with \type {\bfa}, \type {\slb}, etc. or even -%D \type {e} and higher alternatives. The magic scaled values are derived from plain -%D \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 once. The main -%D difference between these examples is that the Computer Modern Roman come in many -%D design sizes. This means that there we cannot define them in bulk using \type -%D {sa}. Instead of \type {rm} (roman) one can define \type {ss} (sans serif), \type -%D {tt} (teletype), \type {hw} (hand written), \type {cg} (calygraphic) and whatever -%D styles. -%D -%D The first argument may be a comma separated list. This, combined with -%D specifications using \type{sa} can save a lot of typing. Although all arguments -%D should be specified, we treat the second argument as optional. -%D -%D Defining a bodyfont involves two actions: defining the specific style related -%D alternatives, like \type {\rma}, \type {\bfa} and \type {\rmsla}, and storing the -%D definitions of their bodyfont size related fonts. The first step is bodyfont -%D independant but executed every time. This permits user definitions like \type -%D {\tfw} or \type {\bfq} for real large alternatives. -%D -%D If we move design size info to the lfg file (after all only lm has design sizes) -%D 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] - -\permanent\tolerant\protected\def\definebodyfont[#1]#*[#2]#*[#3]#*[#4]% - {\ifarguments - \or - \font_basics_define_body_font[#1][\s!rm][]% - \or - \font_basics_define_body_font[#1][\s!rm][#2]% - \or - \font_basics_define_body_font[#1][#2][#3]% - \or - \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}% - \fi} - -\protected\def\font_basics_define_body_font[#whatever]% - {\doifelsenumber{#whatever}\font_basics_define_body_font_body\font_basics_define_body_font_name[#whatever]} - -\protected\def\font_basics_define_body_font_class_given[#1][#2][#3]#4% - {\push_macro_fontclass - \doifelse{#4}\s!default - {\let\fontclass\empty} - {\def\fontclass{#4}}% - \definebodyfont[#1][#2][#3]% - \pop_macro_fontclass} - -\protected\def\font_basics_define_body_font_body[#body][#style][#specification]% - {\ifcondition\validassignment{#specification}% - \expandafter\font_basics_define_body_font_body_assignment - \else - \expandafter\font_basics_define_body_font_body_identifier - \fi - [#body][#style][#specification]}% - -\protected\def\font_basics_define_body_font_name[#name][#style][#specification]% - {\ifcondition\validassignment{#specification}% - \expandafter\font_basics_define_body_font_name_assignment - \else - \expandafter\font_basics_define_body_font_name_identifier - \fi - [#name][#style][#specification]}% - -\protected\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]% - {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}} - -\protected\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body% - {\normalizebodyfontsize\m_font_asked_body{#body}% - % normally we define quite a lot in advance, i.e global defs - \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! - \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}} - -\protected\def\font_basics_define_body_font_body_assignment_b#assignments#style% - {\edef\m_font_asked_style{#style}% - \processcommalist[#assignments]\font_basics_define_body_font_defs} - -\protected\def\font_basics_define_body_font_defs - {\ifempty\fontclass - \expandafter\font_basics_define_body_font_defs_nop - \else - \expandafter\font_basics_define_body_font_defs_yes - \fi} - -\protected\def\font_basics_define_body_font_defs_yes_normal#assignment% - {\ifx\m_font_asked_style\s!mm - \expandafter\font_basics_define_body_font_yes_mm - \else - \expandafter\font_basics_define_body_font_yes_xx - \fi[#assignment]} - -\protected\def\font_basics_define_body_font_defs_nop_normal#assignment% - {\ifx\m_font_asked_style\s!mm - \expandafter\font_basics_define_body_font_nop_mm - \else - \expandafter\font_basics_define_body_font_nop_xx - \fi[#assignment]} - -\protected\def\font_basics_define_body_font_defs_yes_traced#assignment% - {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% - \ifx\m_font_asked_style\s!mm - \expandafter\font_basics_define_body_font_yes_mm - \else - \expandafter\font_basics_define_body_font_yes_xx - \fi[#assignment]} - -\protected\def\font_basics_define_body_font_defs_nop_traced#assignment% - {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% - \ifx\m_font_asked_style\s!mm - \expandafter\font_basics_define_body_font_nop_mm - \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 - -%D We split into two characters (first part of spec) and the rest: the first two are -%D the style and the rest is a size, although in practice one will seldom define the -%D size directly. We might even drop that as it gives faster code. - -\protected\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local - {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi - \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined - \protected\edefcsname\??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}}}% - \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined - \protected\edefcsname\??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}}}% - \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined - \protected\edefcsname\??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}}}% - } - -\protected\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global - {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi - \global\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined - \global\protected\edefcsname\??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\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined - \global\protected\edefcsname\??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\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined - \global\protected\edefcsname\??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. - -\protected\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local - {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi - \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined - % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined - % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined - \global\protected\edefcsname\??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}% - -\protected\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global - {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi - \global\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined - % \global\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined - % \global\letcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined - \global\protected\edefcsname\??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}% - -\protected\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]% - {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}} - -\protected\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body% - {\normalizebodyfontsize\m_font_asked_body{#body}% - \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! - \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}} - -\protected\def\font_basics_define_body_font_body_identifier_b#name#style% - {\edef\m_font_asked_style{#style}% - %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}% - \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking - -\protected\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]% - {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}} - -\protected\def\font_basics_define_body_font_name_assignment_a#name#assignments#style% - {%\writestatus\m!fonts{[#name:#style] => [#assignments]}% - \edefcsname\??fontdefinitions#name:#style\endcsname{\font_basics_define_body_font_default{#assignments}}} - -\protected\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]% - {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}} - -\protected\def\font_basics_define_body_font_name_identifier_a#name#identifier#style% - {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}% - \ifcsname\??fontdefinitions#name:#style\endcsname - \letcsname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname - \else - \defcsname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}% - \fi} - -%D The unknown: - -\newconditional\c_font_defining_unknown -\newconditional\c_font_defining_state - -\protected\def\font_helpers_define_unknown_font#body% one level only - {\font_helpers_register_fontbody{#body}% prevents loop, can go - \setfalse\c_font_defining_state - \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}% - \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 - \clf_registerunknownbodysize{#body}% - \fi - \setfalse\c_font_defining_state - \font_helpers_register_fontbody{#body}% - % needed ? - \ifconditional\c_font_defining_unknown - \else - \settrue\c_font_defining_unknown - \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}% - \setfalse\c_font_defining_unknown - \fi - \fi - \fi} - -\def\font_helpers_define_unknown_check_sizes#body#relativesize% - {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ? - \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}% - \settrue\c_font_defining_state - \fi} - -\def\font_helpers_define_unknown_check_definitions#body#style% - {\ifcsname\??fontdefinitions\s!default:#style\endcsname - \edef\m_font_asked_body{#body}% - \edef\m_font_asked_style{#style}% - \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 - \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname - \settrue\c_font_defining_state - \fi} - -\protected\def\font_basics_define_body_font_default#assignments% - {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here? - \ifcsname\m_font_asked_style\endcsname\else - \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}% - \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. - -\protected\def\font_basics_switch_points#body% - {\ifcsname\??fontbodyknown#body\endcsname \else - % we need to check the relative sizes for this body - \font_helpers_define_unknown_font{#body}% - \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} - -\protected\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 handle changes in size as -%D well as returning to the global 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}% - \ifempty\m_font_specification \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 - \ifempty\defaultfontclass - \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 - -\protected\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message% - {\edef\m_font_keyword{#keyword}% - \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname - \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}% - \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}% - \orelse\ifx\m_font_keyword\v!reset - \let\fontstyle\empty % new 31/7/2006 - \let\fontsize \empty - \orelse\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} - -\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later - {\let\fontstyle\s!rm} - -\protected\def\font_helpers_set_font_set_font_option_body#method#body#message% - {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls - \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else - \font_helpers_define_unknown_font\normalizedsetfont - \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 - -\permanent\def\registerfontclass#class% - {\letgvalue{\??fontclassyes#class}\v!yes} % global ? - -\permanent\def\setcurrentfontclass#class% - {\ifcsname\??fontclassyes#class\endcsname - \edef\fontclass{#class}% - \orelse\ifcsname\??fontclassnop#class\endcsname - % already tried - \else % too messy: \ifcase\currentgrouplevel % (unpredictable) - \trycurrentfontclass{#class}% - \fi} - -\ifdefined\trycurrentfontclass \else - - \protected\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.) - -\permanent\protected\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} - -\permanent\protected\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 - -\protected\def\font_helpers_set_current_font_style#style% - {\edef\fontstyle{#style}% - \font_typescripts_inherit_check\fontstyle - \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_xsize_alternative#xsize#alternative% - {\edef\fontface{#xsize}% - \edef\fontalternative{#alternative}% - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_alternative#alternative% - {\edef\fontalternative{#alternative}% - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_size#size% - {\edef\fontsize{#size}% - \font_helpers_check_big_math_synchronization % double? better in everymath? - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl - {\edef\fontstyle {#style}% - \edef\fontalternative{#alternative}% - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_style_size#style#size% \rma - {\edef\fontstyle{#style}% - \edef\fontsize {#size}% - \font_helpers_check_big_math_synchronization % double? better in everymath? - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla - {\edef\fontalternative{#alternative}% - \edef\fontsize {#size}% - \font_helpers_check_big_math_synchronization % double? better in everymath? - \font_helpers_synchronize_font} - -\protected\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla - {\edef\fontstyle {#style}% - \edef\fontalternative{#alternative}% - \edef\fontsize {#size}% - \font_helpers_check_big_math_synchronization % double? better in everymath? - \font_helpers_synchronize_font} - -\protected\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy - {\ifempty\fontclass - \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 -%D that often 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} - -\permanent\let\applyfontstrategies \font_helpers_check_strategy_a -\permanent\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 sizes is accomplished by -%D the next set of macros. When in math mode, the commands \type {\tx} and \type -%D {\txx} are just a switch to the script and double script styles, but in text mode -%D the values defined by the bodyfontenvironment are used. Here we also set \type -%D {\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_reset_x_fontsize - {\ifcase\currentxfontsize\else - \currentxfontsize\zerocount - % also \sx and \sxx ? - \enforced\let\tx \normaltx - \enforced\let\txx\normaltxx - \fi} - -\let\font_helpers_check_nested_x_fontsize\relax - -\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 - \enforced\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 - \enforced\let\tx\empty - \enforced\let\txx\empty} - -%D This alterative is not really needed, but for old time's sake we keep it there. -%D 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}, this macro is -%D redefined to be \type {\txx}. Therefore calls 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 takes a bit more -%D time. Keep in mind that the fontsize is represented by a character or empty. - -\installcorenamespace{fontscalex} -\installcorenamespace{fontscalexx} - -\newconditional\c_font_inherit_scale - -\def\font_scale_inherit#1% - {\begingroup - \scratchcounterone\fontid\font\relax - \currentxfontsize\plusone - \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}% - \scratchcountertwo\fontid\font\relax - \currentxfontsize\plustwo - \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}% - \scratchcounterthree\fontid\font\relax - % parent -> x -> xx - % parent -> xx - \global\expandafter\chardef\csname\??fontscalex \number\scratchcounterone\endcsname\scratchcountertwo - \global\expandafter\chardef\csname\??fontscalexx\number\scratchcounterone\endcsname\scratchcounterthree - \global\expandafter\chardef\csname\??fontscalex \number\scratchcountertwo\endcsname\scratchcounterthree - \global\expandafter\chardef\csname\??fontscalexx\number\scratchcountertwo\endcsname\scratchcounterthree - \endgroup - \setfontid\csname#1\number\fontid\font\endcsname} - -\def\font_scale_inherit_x - {\ifcsname\??fontscalex\number\fontid\font\endcsname - \setfontid\lastnamedcs - \else - \font_scale_inherit\??fontscalex - \fi - \ifskipfontcharacteristics - \setfontcharacteristics - \the\everyfontswitch - \fi} - -\def\font_scale_inherit_xx - {\ifcsname\??fontscalexx\number\fontid\font\endcsname - \setfontid\lastnamedcs - \else - \font_scale_inherit\??fontscalexx - \fi - \ifskipfontcharacteristics - \setfontcharacteristics - \the\everyfontswitch - \fi} - -\def\font_scale_defined_x - {\let\fontface\!!plusfour - \let\fontalternative\fontalternative - \font_helpers_synchronize_font} - -\def\font_scale_defined_xx - {\let\fontface\!!plusfive - \let\fontalternative\fontalternative - \font_helpers_synchronize_font} - -% to freeze or not ... - -\permanent\protected\def\tx - {\currentxfontsize\plusone - \ifmmode - \scriptstyle - \orelse\ifconditional\c_font_inherit_scale - \font_scale_inherit_x - \else - \font_scale_defined_x - \fi - \enforced\let\tx\txx} - -\permanent\protected\def\txx - {\currentxfontsize\plustwo - \ifmmode - \scriptscriptstyle - \orelse\ifconditional\c_font_inherit_scale - \font_scale_inherit_xx - \else - \font_scale_defined_xx - \fi - \enforced\let\tx \empty - \enforced\let\txx\empty} - -\permanent\protected\def\sx - {\currentxfontsize\plusone - \ifmmode - \scriptstyle - \else - \font_scale_inherit_x - \fi - \enforced\let\tx\txx - \enforced\let\sx\sxx} - -\permanent\protected\def\sxx - {\currentxfontsize\plustwo - \ifmmode - \scriptscriptstyle - \else - \font_scale_inherit_xx - \fi - \enforced\let\tx \empty - \enforced\let\txx\empty - \enforced\let\sx \empty - \enforced\let\sxx\empty} - -\permanent\protected\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me -\permanent\protected\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me - -\aliased\let\normaltx \tx -\aliased\let\normaltxx\txx - -\aliased\let\normalsx \sx -\aliased\let\normalsxx\sxx - -%D When asking for a complete font switch, for instance from 10 to 12~points, the -%D next macro does the job. First we normalize the size, next we define the current -%D range of text, script and scriptscript sizes, then we set the text fonts and the -%D math families and finally we activate the default typeface and also set the font -%D specific parameters assigned to \type {\everybodyfont}. - -\permanent\def\textface {\currentbodyfontdimension\s!text } -\permanent\def\scriptface {\currentbodyfontdimension\s!script } -\permanent\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript} -\permanent\def\xtextface {\currentbodyfontdimension\s!x } -\permanent\def\xxtextface {\currentbodyfontdimension\s!xx } - -\installcorenamespace{fontbodyfaces} - -\protected\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 - \enforced\noexpand\edef\noexpand\textface {\currentbodyfontdimension\s!text }% - \enforced\noexpand\edef\noexpand\scriptface {\currentbodyfontdimension\s!script }% - \enforced\noexpand\edef\noexpand\scriptscriptface{\currentbodyfontdimension\s!scriptscript}% - \enforced\noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }% - \enforced\noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }% - }% - \global\letcsname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces} - -\permanent\def\currentbodyfontdimension#parameter% there can be factors here - {\the\dimexpr - \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname - \lastnamedcs - \orelse\ifcsname\??fontenvironments\fontclass\s!default#parameter\endcsname - \lastnamedcs - \dimexpr\normalizedbodyfontsize\relax - \orelse\ifcsname\??fontenvironments\normalizedbodyfontsize#parameter\endcsname - \lastnamedcs - \else - \csname\??fontenvironments\s!default#parameter\endcsname - \dimexpr\normalizedbodyfontsize\relax - \fi - \relax} - -%D \macros -%D {setupbodyfont,switchtobodyfont} -%D -%D The next two macros are user ones. With \type {\setupbodyfont} one can set the -%D document bodyfont size, font family, style and/or options defined in files, for -%D example: -%D -%D \starttyping -%D \setupbodyfont[modern,12pt,roman] -%D \stoptyping -%D -%D This command affects the document as a whole: text, headers and footers. The -%D 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 all kind of keywords into -%D account. - -\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi -\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi - -% \newtoks \everysetupbodyfont -% \newtoks \everyswitchtobodyfont - -\permanent\protected\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}} - -\protected\def\font_basics_switchtobodyfont#specification% - {\edef\m_font_step{\font_bodyfontvariable{#specification}}% - \ifempty\m_font_step - \font_helpers_set_font\zerocount{#specification}% - \else - \font_helpers_switch_bodyfont_step % so we have a fast [small] switch - \fi - \the\everybodyfont - \the\everyswitchtobodyfont} - -\permanent\protected\def\switchtobodyfont[#specification]% could become an ifx - {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}} - -\permanent\protected\def\usebodyfontparameter#1% - {\edef\m_font_bodyfont_asked{#1\c!bodyfont}% - \ifempty\m_font_bodyfont_asked\else - \font_basics_switchtobodyfont\m_font_bodyfont_asked - \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 switching and will be -%D optimized. - -\permanent\protected\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 - -\permanent\protected\def\usebodyfont[#1]% - {\ifempty\fontclass - \setupbodyfont[#1]% - \else - \switchtobodyfont[#1]% - \fullrestoreglobalbodyfont - \fi} - -\permanent\protected\def\showbodyfontstate - {\dontleavehmode - \start - \infofont - [fontclass: \fontclass,\space - fontbody: \fontbody ,\space - fontface: \fontface ,\space - fontsize: \fontsize ]% - \stop} - -%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 \NC u \NC unicode descriptions \NC u:dog \NC \NR -%D \NC a \NC all (also descriptions) \NC a:rewind \NC \NR -%D \stoptabulate -%D -%D This is an expandable command! - -\permanent\protected\def\fontchar #character{\clf_fontchar{#character}} -\permanent\protected\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax} -\permanent \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef) - -%D The next auxilliary macro is an alternative to \type {\fontname}. - -\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 - -\permanent\protected\def\switchstyleonly - {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg} - -\def\font_basics_switch_style_only_arg#name% stupid version - {\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} to switch to a specific -%D bodyfontsize. Just for the sake of 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. - -\permanent\tolerant\protected\def\definebodyfontswitch[#command]#spacer[#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 the \type {small} as -%D well as the \type {big} alternative, related to this main size, using \type -%D {\switchtobodyfont[small]}. The three alternatives can be activated by the next -%D three 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} - -\permanent\protected\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont} -\permanent\protected\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont} - -\permanent\protected\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. Pagenumbers, -%D footers, headers etc. however must be typeset in the main bodyfont and style of -%D the document. Returning to the global state can be done with the next macro: -%D -%D This macro has to be called when entering the pagebody handling routine as well -%D as the footnote insert routine. Users can access this feature |<|for instance -%D when one wants to typeset tables and alike in the main bodyfont and style while -%D the running text is temporary set to a smaller one|>| by saying \type -%D {\switchtobodyfont [global]}. - -\let\globalfontstyle\s!rm - -\permanent\protected\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} - -\permanent\protected\def\partialrestoreglobalbodyfont - {\let\fontsize\defaultfontsize - \let\fontbody\defaultfontbody - \let\fontface\defaultfontface - \currentxfontsize\zerocount - \redoconvertfont - \tf - \the\everybodyfont % indeed needed - \the\everyglobalbodyfont % indeed needed - \saveinterlinespace} - -\permanent\protected\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 system is -%D 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} - -\permanent\protected\def\predefinefont[#1]#*[#2]% global ! - {\setugvalue{#1}{\font_basics_predefine{#1}{#2}}} - -\permanent\protected\def\predefinedfont[#1]% global ! - {\ifcsname\??predefinedfont#1\endcsname - \lastnamedcs - \else - \font_basics_predefined{#1}% - \fi} - -\protected\def\font_basics_predefine#1#2% - {\font_basics_defined_font_yes[#2]% - \global\letcsname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname} - -\protected\def\font_basics_predefined#1% - {\font_basics_predefine{\??predefinedfont#1}{#1}} - -%D Handy helper: - -\permanent\protected\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} - -%D Ugly helper: - -\permanent\protected\def\saverunningstyleandcolor - {\enforced\permanent\protected\edef\restorerunningstyleandcolor - {\setfontid \number\fontid\font - \c_attr_colormodel \the\c_attr_colormodel - \c_attr_color \the\c_attr_color - \c_attr_transparency\the\c_attr_transparency - \relax}} - -\let\restorerunningstyleandcolor\relax - -%D Handy for defining additional glyphs: - -% todo: public implementors - -\let\getprivateglyphslot\clf_getprivateglyphslot % kind of private macro - -\let\getprivatechar \clf_getprivatechar % gives back a utf ! -\let\getprivatemathchar \clf_getprivatemathchar % gives back a utf ! -\let\getprivateslot \clf_getprivateslot % companion to fonts.helpers.addprivate - -% \protected\def\getprivatemathchar#1% -% {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup} - -\permanent\protected\def\privatechar % the text variant gets expanded to utf - {\ifmmode - \expandafter\getprivatemathchar - \else - \expandafter\getprivatechar - \fi} - -%D Some fonts can have color specifiers: -%D -%D \starttyping -%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes] -%D \definefontsynonym[emoji][seguiemj*seguiemj-cl] -%D -%D \definecolor[emoji-red] [r=.4] -%D \definecolor[emoji-gray][s=1,t=.5,a=1] -%D -%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad -%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] % okay -%D -%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r] -%D -%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt] -%D -%D \startTEXpage[offset=10pt] -%D \MyEmojiR\resolvedemoji{triangular ruler} -%D \stopTEXpage -%D \stoptyping - -\permanent\tolerant\protected\def\definefontcolorpalette[#1]#*[#2]% - {\clf_definefontcolorpalette{#1}{#2}} - -%D \macros -%D {addfontpath} -%D -%D A way to add a path at runtime (no need to generate database): - -\permanent\protected\def\usefontpath[#1]% - {\clf_addfontpath{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi index f4a20c8df..db9df49cd 100644 --- a/tex/context/base/mkiv/font-lib.mkvi +++ b/tex/context/base/mkiv/font-lib.mkvi @@ -49,17 +49,13 @@ \registerctxluafile{font-osd}{} %registerctxluafile{font-osm}{} -\ifcase\contextlmtxmode - \ifcase\directlua{tex.print(callback.list()["provide_charproc_data"] == false and 1 or 0)}\relax - % this is the generic variant that will become luatex-fonts-ocl once we have - % more recent versions of luatex 1.13/1.14 on the garden - \registerctxluafile{font-ocl}{} - \else - \registerctxluafile{font-ocm}{} - \fi -\else - \registerctxluafile{font-ogr}{autosuffix} % lmtx -\fi +% \ifcase\directlua{tex.print(callback.list()["provide_charproc_data"] == false and 1 or 0)}\relax +% % this is the generic variant that will become luatex-fonts-ocl once we have +% % more recent versions of luatex 1.13/1.14 on the garden + \registerctxluafile{font-ocl}{} +% \else +% \registerctxluafile{font-ocm}{} +% \fi % we use otf code for type one diff --git a/tex/context/base/mkiv/font-mat.mklx b/tex/context/base/mkiv/font-mat.mklx deleted file mode 100644 index 8ee5f4043..000000000 --- a/tex/context/base/mkiv/font-mat.mklx +++ /dev/null @@ -1,490 +0,0 @@ -%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 The order 3 2 1 of siuze matters: needed for math-fbk relative size storage! - -%D \macros -%D {textonly} -%D -%D Traditionally math has a big impact on font definitions, mainly because we need -%D to define alphabet variants using families and fonts. This means that one can -%D easily get 10 fonts loaded per math size. In \MKIV\ we use a different approach: -%D one family which has either a virtual font made of traditional fonts, or an -%D \OPENTYPE\ font that has it all. -%D -%D We currently use only one math family but in the future we might consider using a -%D second one for bold math. For the moment we keep the \MKII\ method of using a -%D token register for definitions but we already dropped the text and symbols ones -%D 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 - -\protected\def\font_helpers_synchronize_math % math stuff in mmode - {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi} - -\permanent\protected\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this - -%D The main math font definer. We have removed some optimized code simply because we -%D now always have a fontclass. We could check for fontclass being default or empty -%D and save a few tests but it does not help us when no math is defined. -%D -%D Because we want to keep mr=.. and mb=... settings (read: not break downward -%D compatibility by enforcing mrlr etc) we need a 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 - -% \frozen ... - -\def\mathtextsuffix {-text} -\def\mathscriptsuffix {-script} -\def\mathscriptscriptsuffix{-scriptscript} - -\def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi} - -%D Beware: truefontname also does a fallback on defaultfontclass so there -%D can be some interference here, which is why we use a different method -%D for bold. - -\def\font_helpers_set_math_family_a - {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size - \lastnamedcs \orelse - \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size - \lastnamedcs \else - \font_helpers_set_math_family_b - \fi} - -\def\font_helpers_set_math_family_b - {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size - \lastnamedcs \orelse - \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size - \lastnamedcs \else - \font_helpers_set_math_family_c - \fi} - -\def\font_helpers_set_math_family_c - {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size - \lastnamedcs \orelse - \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size - \lastnamedcs \else - \settrue \c_font_auto_size - \fi} - -\let\mathsizesuffix\empty - -\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 - % enabling is needed when we have fallbacks which spoils the families - \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree - \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % defines - \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % enables - \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo - \font_helpers_set_math_family_a\scriptfont #mrtag\font % defines - \font_helpers_set_math_family_a\scriptfont #mrtag\font % enables - \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone - \font_helpers_set_math_family_a\textfont #mrtag\font % defines - \font_helpers_set_math_family_a\textfont #mrtag\font % enables - \let\mathsizesuffix\empty \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 - \lastnamedcs #font#mbfam\font \orelse - \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size - \lastnamedcs #font#mbfam\font \else - #font#mbfam#font#mrfam% - \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\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree - \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% defines - \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% enables - \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo - \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% defines - \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% enables - \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone - \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines - \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables - \let\mathsizesuffix\empty \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 we have a problem -%D with setting the global bodyfont size in the 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 -%D little in restoring global states and, what's more important, we get rid of large -%D math parameter 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 - \orelse\ifnum\fontid\textfont#fam=\fontid\v_font_math_one\else - \font_helpers_preset_math_family_indeed_changed#fam#familytag% - \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 - -%D It would be nice if characters could be defined in a neutral way (say fam 255) -%D and be mapped to a real family during noad list construction. However, this -%D changes tex in critical places so for the moment we simulate this using -%D manipulation. -%D -%D For tracing purposes we use three families but in l2r mode 1 and 2 are copies of -%D 0 while in rl mode 0 is a copy of 1. There is no real overhead involved in this. -%D 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_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 - \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr - \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr - \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr} - -\appendtoks - \ifconditional\c_font_bidirectional_mathstrategy - \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_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 - \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl - \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl - \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl} - -\def\font_helpers_apply_complete_bold_mathstrategy - {\ifconditional\c_font_complete_bold_mathstrategy - \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 - -\protected\def\font_helpers_synchronize_math_family_mr - {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy - \ifconditional\c_math_right_to_left - \plustwo - \else - \plusone - \fi - \else - \zerocount - \fi} - -\protected\def\font_helpers_synchronize_math_family_mb - {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy - \ifconditional\c_math_right_to_left - \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi - \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} - -\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 - -%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 - -%D Bold is somewhat special as we might want both full-bold-math mixed regular-math, -%D as well as automatic adaption to outer bold (in titles and inline text bold) so -%D we will need explicit switches as well as an automatic one. (We will use lucida -%D as an example.) - -\ifdefined\mathdefault \else \let\mathdefault\relax \fi - -\newconditional\c_math_bold - -\protected\def\mr % math regular - {\ifmmode - \font_helpers_synchronize_math_family_mr - \else - \font_helpers_set_current_font_alternative\s!mr - \fi - \mathdefault - \setfalse\c_math_bold} - -\protected\def\mb % math bold - {\ifmmode - \font_helpers_synchronize_math_family_mb - \else - \font_helpers_set_current_font_alternative\s!mb - \fi - \mathdefault - \settrue\c_math_bold} - -\appendtoks - \font_helpers_synchronize_math_family % auto bold -\to \everymathematics - -\appendtoks - \ifconditional\c_math_bold\mb\fi -\to \everymathematics - -%D \macros -%D {bigmath,nobigmath} -%D -%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 - -\protected\def\nobigmath {\synchronizebigmathflag\zerocount} -\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} -\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} - -\let\bigmathfontsize\empty - -\protected\def\synchronizebigmath - {\ifx\bigmathfontsize\fontsize - % already in sync - \else - \let\bigmathfontsize\fontsize - \font_helpers_synchronize_math - \fi} - -\protected\def\font_helpers_check_big_math_synchronization - {\ifcase\synchronizebigmathflag - % never - \or - \ifmmode \synchronizebigmath \fi - \or - \synchronizebigmath - \fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/font-ogr.lmt b/tex/context/base/mkiv/font-ogr.lmt deleted file mode 100644 index e57e88ed6..000000000 --- a/tex/context/base/mkiv/font-ogr.lmt +++ /dev/null @@ -1,673 +0,0 @@ -if not modules then modules = { } end modules ['font-ogr'] = { - 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" -} - --- Here we deal with graphic variants and for now also color support ends up here --- but that might change. It's lmtx only code. - -if not context then - return -elseif CONTEXTLMTXMODE == 0 then - return -end - -local tostring, tonumber, next, type = tostring, tonumber, next, type -local round, max, mod, div = math.round, math.max, math.mod, math.div -local find = string.find -local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash -local utfbyte = utf.byte -local formatters = string.formatters -local settings_to_hash_strict, settings_to_array = utilities.parsers.settings_to_hash_strict, utilities.parsers.settings_to_array - -local otf = fonts.handlers.otf -local otfregister = otf.features.register -otf.svgenabled = true -otf.pngenabled = true - --- Just to remind me ... rewritten around the time this was posted on YT which --- was also around the 2019 ctx meeting: --- --- Gavin Harrison - "Threatening War" by The Pineapple Thief --- https://www.youtube.com/watch?v=ENF9wth4kwM - --- todo: svg color plugin --- todo: get rid of double cm in svg (tricky as also elsewhere) --- todo: png offsets (depth) --- todo: maybe collapse indices so that we have less files (harder to debug) --- todo: manage (read: assign) font id's in lua so we know in advance - --- what here and what in backend ... - -do - - -- This is a prelude to something better but I'm still experimenting. - - local dropins = { } - fonts.dropins = dropins - local droppedin = 0 - local identifiers = fonts.hashes.identifiers - - function dropins.nextid() - droppedin = droppedin - 1 - return droppedin - end - - -- todo: pass specification table instead - - function dropins.provide(method,t_tfmdata,indexdata,...) - local droppedin = dropins.nextid() - local t_characters = t_tfmdata.characters - local t_descriptions = t_tfmdata.descriptions - local t_properties = t_tfmdata.properties - local d_tfmdata = setmetatableindex({ },t_tfmdata) - local d_properties = setmetatableindex({ },t_properties) - d_tfmdata.properties = d_properties - local d_characters = { } -- setmetatableindex({ },t_characters) -- hm, index vs unicode - local d_descriptions = { } -- setmetatableindex({ },t_descriptions) -- hm, index vs unicode - d_tfmdata.characters = d_characters - d_tfmdata.descriptions = d_descriptions - d_tfmdata.parentdata = t_tfmdata -- so we can access it if needed - d_properties.instance = - droppedin -- will become an extra element in the hash - t_properties.virtualized = true - identifiers[droppedin] = d_tfmdata - local fonts = t_tfmdata.fonts or { } - t_tfmdata.fonts = fonts - d_properties.format = "type3" - d_properties.method = method - d_properties.indexdata = { indexdata, ... } -- can take quite some memory - local slot = #fonts + 1 - fonts[slot] = { id = droppedin } - return slot, droppedin, d_tfmdata, d_properties - end - - -- todo: delay this, in which case we can be leaner and meaner - - function dropins.clone(method,tfmdata,shapes,...) -- by index - if method and shapes then - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local droppedin, tfmdrop, dropchars, dropdescs, colrshapes - local idx = 255 - local slot = 0 - for k, v in next, characters do - local index = v.index - if index then - local description = descriptions[k] - if description then - local shape = shapes[index] - if shape then - if idx >= 255 then - idx = 1 - colrshapes = setmetatableindex({ },shapes) - slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) - dropchars = tfmdrop.characters - dropdescs = tfmdrop.descriptions - else - idx = idx + 1 - end - colrshapes[idx] = shape -- so not: description - -- todo: prepend - v.commands = { { "slot", slot, idx } } - -- hack to prevent that type 3 also gets 'use' flags .. todo - local c = { commands = false, index = idx, dropin = tfmdrop } - local d = { } -- { index = idx, dropin = tfmdrop } - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - end - else - -- error - end - end - - function dropins.swap(method,tfmdata,shapes,...) -- by unicode - if method and shapes then - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local droppedin, tfmdrop, dropchars, dropdescs, colrshapes - local idx = 255 - local slot = 0 - -- we can have a variant where shaped are by unicode and not by index - for k, v in next, characters do - local description = descriptions[k] - if description then - local shape = shapes[k] - if shape then - if idx >= 255 then - idx = 1 - colrshapes = setmetatableindex({ },shapes) - slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) - dropchars = tfmdrop.characters - dropdescs = tfmdrop.descriptions - else - idx = idx + 1 - end - colrshapes[idx] = shape -- so not: description - -- todo: prepend - v.commands = { { "slot", slot, idx } } - -- hack to prevent that type 3 also gets 'use' flags .. todo - local c = { commands = false, index = idx, dropin = tfmdrop } - local d = { } -- index = idx, dropin = tfmdrop } - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - else - -- error - end - end - -end - -do -- this will move to its own module - - local dropins = fonts.dropins - - local shapes = setmetatableindex(function(t,k) - local v = { - glyphs = { }, - parameters = { - units = 1000 - }, - } - t[k] = v - return v - end) - - function dropins.registerglyphs(parameters) - local category = parameters.name - local target = shapes[category].parameters - for k, v in next, parameters do - if k ~= "glyphs" then - target[k] = v - end - end - end - - function dropins.registerglyph(parameters) - local category = parameters.category - local unicode = parameters.unicode - local private = parameters.private - local unichar = parameters.unichar - if private then - unicode = fonts.helpers.newprivateslot(private) - elseif type(unichar) == "string" then - unicode = utfbyte(unichar) - else - local unitype = type(unicode) - if unitype == "string" then - local uninumber = tonumber(unicode) - if uninumber then - unicode = round(uninumber) - else - unicode = utfbyte(unicode) - end - elseif unitype == "number" then - unicode = round(unicode) - end - end - if unicode then - parameters.unicode = unicode - -- print(category,unicode) - shapes[category].glyphs[unicode] = parameters - else - -- error - end - end - - -- local function hascolorspec(t) - -- if (t.color or "") ~= "" then - -- return true - -- elseif (t.fillcolor or "") ~= "" then - -- return true - -- elseif (t.drawcolor or "") ~= "" then - -- return true - -- elseif (t.linecolor or "") ~= "" then - -- return true - -- else - -- return false - -- end - -- end - - local function hascolorspec(t) - for k, v in next, t do - if find(k,"color") then - return true - end - end - return false - end - - local function initializemps(tfmdata,kind,value) - if value then - local specification = settings_to_hash_strict(value) - if not specification or not next(specification) then - specification = { category = value } - end - -- todo: multiple categories but then maybe also different - -- clones because of the units .. for now we assume the same - -- units - local category = specification.category - if category and category ~= "" then - local categories = settings_to_array(category) - local usedshapes = nil - local index = 0 - local spread = tonumber(specification.spread or 0) - local hascolor = hascolorspec(specification) - specification.spread = spread -- now a number - for i=1,#categories do - local category = categories[i] - local mpsshapes = shapes[category] - if mpsshapes then - local properties = tfmdata.properties - local parameters = tfmdata.parameters - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local mpsparameters = mpsshapes.parameters - local units = mpsparameters.units or 1000 - local defaultwidth = mpsparameters.width or 0 - local defaultheight = mpsparameters.height or 0 - local defaultdepth = mpsparameters.depth or 0 - local usecolor = mpsparameters.usecolor - local spread = spread * units - local defaultcode = mpsparameters.code or "" - local scale = parameters.size / units - if hascolor then - -- the graphic has color - usecolor = false - else - -- do whatever is specified - end - usedshapes = usedshapes or { - instance = "simplefun", - units = units, - usecolor = usecolor, - specification = specification, - shapes = mpsshapes, - } - -- todo: deal with extensibles and more properties - for unicode, shape in sortedhash(mpsshapes.glyphs) do - -- local oldc = characters[unicode] - -- if oldc then - index = index + 1 -- todo: somehow we end up with 2 as first entry after 0 - local wd = shape.width or defaultwidth - local ht = shape.height or defaultheight - local dp = shape.depth or defaultdepth - local newc = { - index = index, -- into usedshapes - width = scale * (wd + spread), - height = scale * ht, - depth = scale * dp, - unicode = unicode, - } - -- - characters [unicode] = newc - descriptions[unicode] = newc - -- - usedshapes[unicode] = shape.code or defaultcode - -- end - end - end - end - if usedshapes then - -- todo: different font when units and usecolor changes, maybe move into loop - -- above - dropins.swap("mps",tfmdata,usedshapes) - end - end - end - end - - -- This kicks in quite late, after features have been checked. So if needed - -- substitutions need to be defined with force. - - otfregister { - name = "metapost", - description = "metapost glyphs", - manipulators = { - base = initializemps, - node = initializemps, - } - } - -end - --- This sits here for historcal reasons so for now we keep it here. - -local startactualtext = nil -local stopactualtext = nil - -function otf.getactualtext(s) - if not startactualtext then - startactualtext = backends.codeinjections.startunicodetoactualtextdirect - stopactualtext = backends.codeinjections.stopunicodetoactualtextdirect - end - return startactualtext(s), stopactualtext() -end - --- This is also somewhat specific. - -local sharedpalettes do - - sharedpalettes = { } - - local colors = attributes.list[attributes.private('color')] or { } - local transparencies = attributes.list[attributes.private('transparency')] or { } - - function otf.registerpalette(name,values) - sharedpalettes[name] = values - local color = lpdf.color - local transparency = lpdf.transparency - local register = colors.register - for i=1,#values do - local v = values[i] - if v == "textcolor" then - values[i] = false - else - local c = nil - local t = nil - if type(v) == "table" then - c = register(name,"rgb", - max(round((v.r or 0)*255),255)/255, - max(round((v.g or 0)*255),255)/255, - max(round((v.b or 0)*255),255)/255 - ) - else - c = colors[v] - t = transparencies[v] - end - if c and t then - values[i] = color(1,c) .. " " .. transparency(t) - elseif c then - values[i] = color(1,c) - elseif t then - values[i] = color(1,t) - end - end - end - end - -end - -local initializeoverlay do - - -- we should use the proper interface instead but for now: - - local colors = attributes.colors - local rgbtocmyk = colors.rgbtocmyk - - local f_cmyk = formatters["%.3N %.3f %.3N %.3N k"] - local f_rgb = formatters["%.3N %.3f %.3N rg"] - local f_gray = formatters["%.3N g"] - - local function convert(t,k) - local v = { } - local m = colors.model - for i=1,#k do - local p = k[i] - local r, g, b = p[1]/255, p[2]/255, p[3]/255 - if r == g and g == b then - p = f_gray(r) - elseif m == "cmyk" then - p = f_cmyk(rgbtocmyk(r,g,b)) - else - p = f_rgb(r,g,b) - end - v[i] = p - end - t[k] = v - return v - end - - initializeoverlay = function(tfmdata,kind,value) -- we really need the id ... todo - if value then - local resources = tfmdata.resources - local palettes = resources.colorpalettes - if palettes then - -- - local converted = resources.converted - if not converted then - converted = setmetatableindex(convert) - resources.converted = converted - end - local colorvalues = sharedpalettes[value] - local default = false -- so the text color (bad for icon overloads) - if colorvalues then - default = colorvalues[#colorvalues] - else - colorvalues = converted[palettes[tonumber(value) or 1] or palettes[1]] or { } - end - local classes = #colorvalues - if classes == 0 then - return - end - -- - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local droppedin, tfmdrop, dropchars, dropdescs, colrshapes - local idx = 255 - local slot = 0 - -- - -- maybe delay in which case we have less fonts as we can be sparse - -- - for k, v in next, characters do - local index = v.index - if index then - local description = descriptions[k] - if description then - local colorlist = description.colors - if colorlist then - if idx >= 255 then - idx = 1 - colrshapes = { } - slot, droppedin, tfmdrop = fonts.dropins.provide("color",tfmdata,colrshapes,colorvalues) - dropchars = tfmdrop.characters - dropdescs = tfmdrop.descriptions - else - idx = idx + 1 - end - -- - colrshapes[idx] = description - -- todo: use extender - local u = { "use", 0 } - for i=1,#colorlist do - u[i+2] = colorlist[i].slot - end - v.commands = { u, { "slot", slot, idx } } - -- hack to prevent that type 3 also gets 'use' flags .. todo - local c = { commands = false, index = idx, dropin = tfmdata } - local d = { } -- index = idx, dropin = tfmdrop - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - end - return true - end - end - end - - fonts.handlers.otf.features.register { - name = "colr", - description = "color glyphs", - manipulators = { - base = initializeoverlay, - node = initializeoverlay, - } - } - -end - -local initializesvg do - - local report_svg = logs.reporter("fonts","svg") - - local cached = true -- maybe always false (after i've optimized the lot) - - directives.register("fonts.svg.cached", function(v) cached = v end) - - initializesvg = function(tfmdata,kind,value) -- hm, always value - if value then - local properties = tfmdata.properties - local svg = properties.svg - local hash = svg and svg.hash - local timestamp = svg and svg.timestamp - if not hash then - return - end - local shapes = nil - local method = nil - local enforce = attributes.colors.model == "cmyk" - if cached and not enforce then - -- we need a different hash than for mkiv, so we append: - local pdfhash = hash .. "-svg" - local pdffile = containers.read(otf.pdfcache,pdfhash) - local pdfshapes = pdffile and pdffile.pdfshapes - local pdftarget = file.join(otf.pdfcache.writable,file.addsuffix(pdfhash,"pdf")) - if not pdfshapes or pdffile.timestamp ~= timestamp or not next(pdfshapes) or not lfs.isfile(pdftarget) then - local svgfile = containers.read(otf.svgcache,hash) - local svgshapes = svgfile and svgfile.svgshapes - pdfshapes = svgshapes and metapost.svgshapestopdf(svgshapes,pdftarget,report_svg,tfmdata.parameters.units) or { } - -- look at ocl: we should store scale and x and y - containers.write(otf.pdfcache, pdfhash, { - pdfshapes = pdfshapes, - timestamp = timestamp, - }) - end - shapes = pdfshapes - method = "pdf" - else - local mpsfile = containers.read(otf.mpscache,hash) - local mpsshapes = mpsfile and mpsfile.mpsshapes - if not mpsshapes or mpsfile.timestamp ~= timestamp or not next(mpsshapes) then - local svgfile = containers.read(otf.svgcache,hash) - local svgshapes = svgfile and svgfile.svgshapes - -- still suboptimal - mpsshapes = svgshapes and metapost.svgshapestomp(svgshapes,report_svg,tfmdata.parameters.units) or { } - if enforce then - -- cheap conversion, no black component generation - mpsshapes.preamble = "interim svgforcecmyk := 1;" - end - containers.write(otf.mpscache, hash, { - mpsshapes = mpsshapes, - timestamp = timestamp, - }) - end - shapes = mpsshapes - method = "mps" - end - if shapes then - shapes.fixdepth = value == "fixdepth" - fonts.dropins.clone(method,tfmdata,shapes) - end - return true - end - end - - otfregister { - name = "svg", - description = "svg glyphs", - manipulators = { - base = initializesvg, - node = initializesvg, - } - } - -end - -local initializepng do - - -- If this is really critical we can also use a pdf file as cache but I don't expect - -- png fonts to remain used. - - local colors = attributes.colors - - local report_png = logs.reporter("fonts","png conversion") - - initializepng = function(tfmdata,kind,value) -- hm, always value - if value then - local properties = tfmdata.properties - local png = properties.png - local hash = png and png.hash - local timestamp = png and png.timestamp - if not hash then - return - end - local pngfile = containers.read(otf.pngcache,hash) - local pngshapes = pngfile and pngfile.pngshapes - if pngshapes then - if colors.model == "cmyk" then - pngshapes.enforcecmyk = true - end - fonts.dropins.clone("png",tfmdata,pngshapes) - end - return true - end - end - - otfregister { - name = "sbix", - description = "sbix glyphs", - manipulators = { - base = initializepng, - node = initializepng, - } - } - - otfregister { - name = "cblc", - description = "cblc glyphs", - manipulators = { - base = initializepng, - node = initializepng, - } - } - -end - -do - - -- I need to check jpeg and such but will do that when I run into - -- it. - - local function initializecolor(tfmdata,kind,value) - if value == "auto" then - return - initializeoverlay(tfmdata,kind,value) or - initializesvg(tfmdata,kind,value) or - initializepng(tfmdata,kind,value) - elseif value == "overlay" then - return initializeoverlay(tfmdata,kind,value) - elseif value == "svg" then - return initializesvg(tfmdata,kind,value) - elseif value == "png" or value == "bitmap" then - return initializepng(tfmdata,kind,value) - else - -- forget about it - end - end - - otfregister { - name = "color", - description = "color glyphs", - manipulators = { - base = initializecolor, - node = initializecolor, - } - } - -end diff --git a/tex/context/base/mkiv/font-pre.mkxl b/tex/context/base/mkiv/font-pre.mkxl deleted file mode 100644 index 8468fbbd7..000000000 --- a/tex/context/base/mkiv/font-pre.mkxl +++ /dev/null @@ -1,999 +0,0 @@ -%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 - -% frac : with numr dnom -% -% vkrn valt vert vrt2 vpal : when vertical -% -% rtlm rtla : in r2l runs -% ltrm ltra : in l2r runs -% -% rvrn : variable fonts -% -% rtbd lfbd : opbd -% -% rkrf rphf vatu vjmo tjmo rclt psts pstf ljmo haln -% pres pref nukt -% abvs abvm blwm blws cjct blwf akhn (indic) -% half -% abvf cfar (khmer) -% -% ccmp locl calt clig liga rlig -% -% mkmk mark kern (palt pwid) curs (by choice but some fonts need it) -% -% init medi isol fina (unicode) -% fin3 fin2 med2 : syriac -% -% cpsp : percentage spacing (todo) -% -% dtls flac :math - -\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, -% ccmp=yes, % maybe too -% locl=yes, % maybe too -% calt=yes, % maybe too -% clig=yes, % maybe too -% rlig=yes, % maybe too - tlig=yes, - trep=yes] % texligatures=yes,texquotes=yes - -\definefontfeature - [original] % a clone of default so we can revert - [default] - -\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, -% ccmp=yes, -% locl=yes, -% calt=yes, -% clig=yes, -% rlig=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, - % fin2=yes,fin3=yes,med2=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, - % fin2=yes,fin3=yes,med2=yes, - mark=yes,mkmk=yes,kern=yes,curs=yes, - rlig=yes,calt=yes] - -\definefontfeature - [arabic] - [semitic-complete] - [script=arab] - -\definefontfeature - [syriac] - [arabic] - [fin2=yes,fin3=yes,med2=yes] - -\definefontfeature - [reordercombining] - [reordercombining=yes] - -\definefontfeature - [hebrew] - [semitic-complete] - [script=hebr, - reordercombining=yes] % seems to work best with reasonable fonts - -\definefontfeature - [simplearabic] - [semitic-simple] - [script=arab] - -\definefontfeature - [simplehebrew] - [semitic-simple] - [script=hebr] - -% indic - -\definefontfeature - [indic-common] - [mode=node, - language=dflt, - % localized - locl=yes, - % positioning - kern=yes, - dist=yes, - % above/below base marks - abvm=yes, - blwm=yes, - % basic shaping - nukt=yes, - akhn=yes, - rphf=yes, - % presentation - pres=yes, - abvs=yes, - blws=yes, - psts=yes, - haln=yes, - calt=yes] - -\definefontfeature - [devanagari-one] - [indic-common] - [script=deva, - % basic shaping - rkrf=yes, - blwf=yes, - half=yes, - vatu=yes, - cjct=yes] - -\definefontfeature - [bengali-one] - [indic-common] - [script=beng, - % basic shaping - blwf=yes, - half=yes, - pstf=yes, - vatu=yes, - cjct=yes, - % presentation - init=yes] - -\definefontfeature - [gujarati-one] - [indic-common] - [script=gujr, - % basic shaping - rkrf=yes, - blwf=yes, - half=yes, - vatu=yes, - cjct=yes] - -\definefontfeature - [gurmukhi-one] - [indic-common] - [script=guru, - % basic shaping - blwf=yes, - half=yes, - pstf=yes, - vatu=yes, - cjct=yes] - -\definefontfeature - [kannada-one] - [indic-common] - [script=knda, - % basic shaping - pref=yes, - blwf=yes, - half=yes, - pstf=yes, - cjct=yes] - -\definefontfeature - [malayalam-one] - [indic-common] - [script=mlym, - % basic shaping - pref=yes, - blwf=yes, - half=yes, - pstf=yes, - cjct=yes] - -\definefontfeature - [oriya-one] - [indic-common] - [script=orya, - % basic shaping - blwf=yes, - pstf=yes, - cjct=yes] - -\definefontfeature - [tamil-one] - [indic-common] - [script=taml, - % basic shaping - pref=yes, - half=yes] - -\definefontfeature - [telugu-one] - [indic-common] - [script=telu, - % basic shaping - pref=yes, - blwf=yes, - half=yes, - pstf=yes, - cjct=yes] - -\definefontfeature [devanagari-two] [devanagari-one] [script=dev2] -\definefontfeature [bengali-two] [bengali-one] [script=bng2] -\definefontfeature [gujarati-two] [gujarati-one] [script=gjr2] -\definefontfeature [gurmukhi-two] [gurmukhi-one] [script=gur2] -\definefontfeature [kannada-two] [kannada-one] [script=knd2] -\definefontfeature [malayalam-two] [malayalam-one] [script=mlm2] -\definefontfeature [oriya-two] [oriya-one] [script=ory2] -\definefontfeature [tamil-two] [tamil-one] [script=tml2] -\definefontfeature [telugu-two] [telugu-one] [script=tel2] - -% mongolian - -\definefontfeature - [mongolian] - [default] - [script=mong, - init=yes,medi=yes,fina=yes,isol=yes, - rlig=yes,rclt=yes,calt=yes, - %dlig=yes,cswh=yes, % optional - mset] - -% tibetan - -\definefontfeature - [tibetan] - [always] - [script=tibt, - language=dflt, - locl=yes, - ccmp=yes, - abvs=yes, - blws=yes, - calt=yes, - liga=yes, - abvm=yes, - blwm=yes] - -% cjk - -\definefontfeature - [jamoforms] - [ljmo=yes, - tjmo=yes, - vjmo=yes] - -% \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, - kern=yes, - % liga=yes, % makes no sense - % tlig=yes, % makes no sense - % trep=yes, % makes no sense - mathnolimitsmode={0,800}, % this looks okay on the average font - mathalternates=yes, - mathitalics=yes, % we pass them - mathdimensions=all, - % mathgaps=yes, - language=dflt, - script=math] - -\ifdefined\mathnolimitsmode - \mathnolimitsmode\plusone % font driven (only opentype) -\fi - -\ifdefined\mathitalicsmode - \mathitalicsmode\plusone % simple noads become zero - % \mathitalicsmode\plustwo % idem but inner is kept (for testing) -\fi - -% \adaptfontfeature[*math*][mathnolimitsmode=1000] % only subscript - -\definefontfeature - [mathematics-l2r] - [mathematics] - [] - -% \definefontfeature -% [mathematics-r2l] -% [mathematics] -% [language=ara, -% rtlm=yes, -% locl=yes] - -\definefontfeature - [mathematics-r2l] - [mathematics] - [rtlm=yes, - locl=yes] - -\definefontfeature[virtualmath] [mathematics] % downward compatibility -\definefontfeature[virtualmath-l2r] [mathematics-l2r] % downward compatibility -\definefontfeature[virtualmath-r2l] [mathematics-r2l] % downward compatibility - -\definefontfeature[math-text] [mathematics] [ssty=no] -\definefontfeature[math-script] [mathematics] [ssty=1,mathsize=yes] -\definefontfeature[math-scriptscript] [mathematics] [ssty=2,mathsize=yes] - -\definefontfeature[math-text-l2r] [mathematics-l2r] [ssty=no] -\definefontfeature[math-script-l2r] [mathematics-l2r] [ssty=1,mathsize=yes] -\definefontfeature[math-scriptscript-l2r] [mathematics-l2r] [ssty=2,mathsize=yes] - -\definefontfeature[math-text-r2l] [mathematics-r2l] [ssty=no] -\definefontfeature[math-script-r2l] [mathematics-r2l] [ssty=1,mathsize=yes] -\definefontfeature[math-scriptscript-r2l] [mathematics-r2l] [ssty=2,mathsize=yes] - -\definefontfeature[math-nostack-text] [math-text] [nostackmath=yes] -\definefontfeature[math-nostack-script] [math-script] [nostackmath=yes] -\definefontfeature[math-nostack-scriptscript][math-scriptscript][nostackmath=yes] - -% \definefontfeature[mathtext] [math-text] -% \definefontfeature[mathscript] [math-script] -% \definefontfeature[mathscriptscript] [math-scriptscript] - -\definefontfeature - [missing] - [missing=yes] - -%D Nice to have too: - -\definefontfeature - [quality] - [expansion=quality, - protrusion=quality] - -\definefontfeature - [fullprotrusion] - [protrusion=pure] - -\definefontfeature - [slanted] - [slant=.2] - -% \definefontfeature -% [boldened] -% [extend=1.2] - -%D Neat: - -% By eye: -% -% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.125,extend=1.025,squeeze=0.99250}] -% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.250,extend=1.050,squeeze=0.98750}] -% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.375,extend=1.075,squeeze=0.98125}] -% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.500,extend=1.100,squeeze=0.97500}] -% -% By calculation: -% -% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.02500,ddelta=0.02500,vshift=0.02500,extend=1.050,squeeze=0.99500}] -% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.05625,ddelta=0.05625,vshift=0.05625,extend=1.075,squeeze=0.99250}] -% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.10000,ddelta=0.10000,vshift=0.10000,extend=1.100,squeeze=0.99000}] -% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.22500,ddelta=0.22500,vshift=0.22500,extend=1.150,squeeze=0.98500}] -% -% So we can do this: - -\definefontfeature[boldened-10][effect={width=0.10,auto=yes}] -\definefontfeature[boldened-15][effect={width=0.15,auto=yes}] -\definefontfeature[boldened-20][effect={width=0.20,auto=yes}] -\definefontfeature[boldened-25][effect={width=0.25,auto=yes}] -\definefontfeature[boldened-30][effect={width=0.30,auto=yes}] - -\definefontfeature - [boldened] - [boldened-30] - -%D Emoji etc: - -\definefontfeature[bandw:overlay][ccmp=yes,dist=yes] -\definefontfeature[color:overlay][ccmp=yes,dist=yes,colr=yes] -%definefontfeature[bandw:svg] [ccmp=yes,dist=yes] -\definefontfeature[color:svg] [ccmp=yes,dist=yes,svg=yes] -%definefontfeature[bandw:bitmap] [ccmp=yes,dist=yes,sbix=yes] -\definefontfeature[color:bitmap] [ccmp=yes,dist=yes,sbix=yes] % also cblc - -% Plus an automatic one: - -\definefontfeature[color] [ccmp=yes,dist=yes,color=auto] - -%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[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[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] [] - -\definealternativestyle [typeface] [\typeface] [] % no translation here (quite basic) -\definealternativestyle [boldface] [\boldface] [] -\definealternativestyle [slantedface] [\slantedface] [] -\definealternativestyle [italicface] [\italicface] [] -\definealternativestyle [swapface] [\swapface] [] - -\definealternativestyle [emphasize] [\em] [\em] % new - -% 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 different. We also provide -%D 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] -\definefontfeature[f:inferiors][subs=yes] -\definefontfeature[f:fractions][frac=yes] -\definefontfeature[f:kern] [kern=yes] -\definefontfeature[f:kerns] [kern=yes] - -\definealternativestyle [\v!smallcaps] [\setsmallcaps] [\setsmallcaps] -\definealternativestyle [\v!oldstyle] [\setoldstyle ] [\setoldstyle ] -\definealternativestyle [\v!fractions] [\setfractions\resetbreakpoints] [\setfractions\resetbreakpoints] - -\permanent\protected\def\setsmallcaps{\doaddfeature{f:smallcaps}} -\permanent\protected\def\setoldstyle {\doaddfeature{f:oldstyle}} -\permanent\protected\def\settabular {\doaddfeature{f:tabular}} -\permanent\protected\def\setsuperiors{\doaddfeature{f:superiors}} -\permanent\protected\def\setfractions{\doaddfeature{f:fractions}} - -% \permanent\protected\def\frc#1#2% -% {\dontleavehmode -% \begingroup -% \addff{frac}% -% \resetbreakpoints -% #1/#2% -% \endgroup} - -%D \macros -%D {uppercasing, lowercasing} - -\definefontfeature[lowercasing][lowercasing=yes] -\definefontfeature[uppercasing][uppercasing=yes] - -\permanent\protected\def\uppercasing{\addff{uppercasing}} -\permanent\protected\def\lowercasing{\addff{lowercasing}} - -%D \macros -%D {tinyfont} -%D -%D By default we load the Computer Modern Roman fonts (but not yet at this moment) -%D and activate the 12pt roman bodyfont. Sans serif and teletype are also available -%D and can be called for by \type {\ss} and \type {\tt}. Loading takes place -%D elsewhere. For tracing purposes we define: - -\definefont[tinyfont][file:dejavusansmono at 1ex] - -%D \macros -%D {infofont} -%D -%D The second situation occurs when we enable the info mode, and put all kind of -%D status information in the margin. We don't want huge switches to the main -%D bodyfont and style, so here too we use a direct method. - -\pushoverloadmode - -\let\infofont \relax -\let\infofontbold \relax -\let\smallinfofont \relax -\let\smallinfofontbold\relax - -\definefont[infofont] [file:dejavusansmono*none at 6pt] -\definefont[infofontbold] [file:dejavusansmono-bold*none at 6pt] -\definefont[smallinfofont] [file:dejavusansmono*none at 3pt] -\definefont[smallinfofontbold][file:dejavusansmono-bold*none at 3pt] - -%D Optimization (later we overload in math). Also needed in order to get \type {\ss} -%D properly defined. - -\permanent\protected\def\normaltf{\let\fontalternative\s!tf\font_helpers_synchronize_font} -\permanent\protected\def\normalbf{\let\fontalternative\s!bf\font_helpers_synchronize_font} -\permanent\protected\def\normalit{\let\fontalternative\s!it\font_helpers_synchronize_font} -\permanent\protected\def\normalsl{\let\fontalternative\s!sl\font_helpers_synchronize_font} -\permanent\protected\def\normalbi{\let\fontalternative\s!bi\font_helpers_synchronize_font} -\permanent\protected\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 - -\permanent\protected\def\normalrm{\font_helpers_set_current_font_style{\s!rm}} -\permanent\protected\def\normalss{\font_helpers_set_current_font_style{\s!ss}} -\permanent\protected\def\normaltt{\font_helpers_set_current_font_style{\s!tt}} - -\let\rm\normalrm -\let\ss\normalss -\let\tt\normaltt - -\popoverloadmode - -\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/tex/context/base/mkiv/font-sol.mklx b/tex/context/base/mkiv/font-sol.mklx deleted file mode 100644 index 8f3d3d712..000000000 --- a/tex/context/base/mkiv/font-sol.mklx +++ /dev/null @@ -1,131 +0,0 @@ -%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}{} - -\unprotect - -\definesystemattribute[splitter][public] - -\installcorenamespace{fontsolution} - -\installcommandhandler \??fontsolution {fontsolution} \??fontsolution - -\aliased\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 - -\permanent\protected\def\setfontsolution[#solution]% just one - {\edef\currentfontsolution{#solution}% - \clf_setfontsolution - {\currentfontsolution}% - {% - method {\fontsolutionparameter\c!method}% - criterium {\fontsolutionparameter\c!criterium}% - % randomseed {\fontsolutionparameter\c!random}% - }% - \relax} - -\let\currentfontsolution\empty - -\permanent\protected\def\resetfontsolution % resets all - {\clf_resetfontsolution - \let\currentfontsolution\empty} - -\permanent\protected\def\startfontsolution % [#1] - {\pushmacro\currentfontsolution - \setfontsolution} - -\permanent\protected\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/tex/context/base/mkiv/font-sty.mklx b/tex/context/base/mkiv/font-sty.mklx deleted file mode 100644 index 0cb76eee9..000000000 --- a/tex/context/base/mkiv/font-sty.mklx +++ /dev/null @@ -1,441 +0,0 @@ -%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 parameterized commands and -%D one of these parameters will concern the font to use. To suit consistent use of -%D fonts we here implement a mechanism for defining the keywords that present a -%D 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 second command takes -%D care of headings and alike. Consider 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 \type {\tfd} does not look -%D that well, so therefore we leave the second argument of \type -%D {\definealternativestyle} empty. When we capatalize characters using the pseudo -%D small cap command \type {\cap}, we want this to take effect in both text and -%D headings, which is accomplished by assigning both arguments. - -\installcorenamespace{alternativestyles} % settings -\installcorenamespace{alternativestyle} % instances - -\installsetuponlycommandhandler \??alternativestyles {alternativestyles} - -\setnewconstant \c_font_current_alternative_style_index \plusone - -\permanent\tolerant\protected\def\definealternativestyle[#commands]#spacer[#variantone]#spacer[#varianttwo]% - {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}} - -% \let\definestyle\definealternativestyle % later redefined - -\newconstant\c_fonts_basics_alternative_style_method - -% maybe permanent - -\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command% - {\setuvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}% - \ifcsname#command\endcsname - % no redefinition - \orelse\ifnum\c_fonts_basics_alternative_style_method=\plusone - \ifthirdargument - \permanent\setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}% - \else - \permanent\setuvalue{#command}{\triggergroupedcommand{#variantone}}% - \fi - \else - \permanent\setuvalue{#command}{\triggergroupedcommand{#variantone}}% - \fi} - -\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} - -\permanent\def\applyalternativestyle#name% public .. expandable? frozen? - {\begincsname\??alternativestyle#name\endcsname} - -\appendtoks - \doifelse{\alternativestylesparameter\c!method}\v!auto - {\c_fonts_basics_alternative_style_method\plusone}% - {\c_fonts_basics_alternative_style_method\zerocount}% -\to \everysetupalternativestyles - -%D Maybe too generic, but probably ok is the following. (Maybe one day we will use a -%D dedicated grouped command for styles.) - -% \appendtoks -% \let\groupedcommand\thirdofthreearguments -% \to \everysimplifycommands - -%D This command also defines the keyword as command. This means that the example -%D definition of \type {bold} we gave before, results in a command \type {\bold} -%D 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} because this would -%D result in an endless recursive call. Therefore we check on the existance of both -%D the command and the substitution. The latter is needed because for instance \type -%D {\type} is an entirely diferent command. That command handles verbatim, while the -%D style command would just switch to teletype font. This is just an example of a -%D tricky naming coincidence. -%D -%D \macros -%D {doconvertfont,noconvertfont, -%D dontconvertfont,redoconvertfont} -%D -%D After having defined such keywords, we can call for them by using -%D -%D \starttyping -%D \doconvertfont{keyword}{text} -%D \stoptyping -%D -%D We deliberately pass an argument. This enables us to assign converters that -%D handle one argument, like \type {\cap}. -%D -%D By default the first specification is used to set the style, exept when we say -%D \type {\dontconvertfont}, after which the second specification is used. We can -%D also directly call for \type {\noconvertfont}. In nested calls, we can restore -%D the conversion by saying \type {\redoconvertfont}. -%D -%D These commands are not grouped! Grouping is most probably done by the calling -%D macro's and would lead to unnecessary overhead. - -\let\m_current_convert_font \empty -\let\m_current_convert_font_dt\empty - -\permanent\protected\def\doconvertfont#specification% takes second argument / this command is obsolete - {\edef\m_current_convert_font{#specification}% - \ifempty\m_current_convert_font - %\expandafter\firstofoneargument - \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\??alternativestyle\m_current_convert_font_dt\endcsname - \expandafter\lastnamedcs - \orelse\ifcsname\m_current_convert_font_dt\endcsname - \expandafter\lastnamedcs - \else - \expandafter\m_current_convert_font - \fi} - -%D Low level switches (downward compatible, but we keep them as one can use them in -%D 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 - -\permanent\protected\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage -\permanent\protected\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage - -%D The new one: - -\setfalse\fontattributeisset - -\let\currentstyleparameter \empty % these might become private (possible conflict with defines) -\let\currentdetokenizedstyleparameter\empty % these might become private (possible conflict with defines) - -\permanent\protected\def\dousestyleparameter#value% - {\edef\currentstyleparameter{#value}% - \ifempty\currentstyleparameter\else - \expandafter\dousecurrentstyleparameter - \fi} - -\permanent\protected\def\dousestylehashparameter#hash#parameter% - {\ifcsname#hash#parameter\endcsname - \expandafter\dousestyleparameter\lastnamedcs - \fi} - -\permanent\protected\def\dousecurrentstyleparameter % empty check outside here - {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% - \settrue\fontattributeisset % reset is done elsewhere - \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname - \lastnamedcs - \orelse\ifcsname\currentdetokenizedstyleparameter\endcsname - \lastnamedcs - \else - \currentstyleparameter - \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} -\installcorenamespace{stylehack} - -\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 - \frozen\instance\setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}% - \frozen\instance\setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}% - \frozen\instance\setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here - \fi -\to \everydefinestyle - -\protected\def\font_styles_apply_start#name% - {\begingroup - \font_styles_use_defined{#name}} - -\protected\def\font_styles_apply_stop - {\endgroup} - -\protected\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup - {\bgroup - \def\g_style{\font_styles_use_defined{#name}}% - \afterassignment\g_style - \let\nexttoken} - -\protected\def\font_styles_use_defined#name% - {\edef\currentstyle{#name}% - \usestylestyleandcolor\c!style\c!color} - -\protected\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} - -\protected\def\style[#name]% as this is can be a switch we use groupedcommand % frozen? - {\csname\??styleargument - \ifcsname\??stylecheck#name\endcsname - 2% defined as style - \orelse\ifcsname\??stylehack#name\endcsname - 4% defined as command - \orelse\ifcsname#name\endcsname - 1% defined as command - \else - 3% specification - \fi - \endcsname{#name}} - -\setvalue{\??styleargument1}#name% - {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname} - -\setvalue{\??styleargument2}#name% - {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}} - -\setvalue{\??styleargument3}#specification% - {\doifelseassignment{#specification}\font_styles_assignment\font_styles_direct{#specification}} - -\setvalue{\??styleargument4}#name% - {\expandafter\triggergroupedcommandcs\begincsname\??stylehack#name\endcsname} - -\setvalue{\??stylehack\s!math}% dirty trick - {\groupedcommand\normalstartimath\normalstopimath} - -% \def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}} -% \def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}} - -\def\font_styles_assignment#specification{\triggergroupedcommand{\font_styles_use_generic{#specification}}} -\def\font_styles_direct #specification{\triggergroupedcommand{\definedfont[#specification]}} - -% environments - -\installcorenamespace{styleenvironment} - -\protected\def\startstyle[#name]% - {\begingroup - \csname\??styleenvironment - \ifcsname\??stylecheck#name\endcsname - 2% defined as style - \orelse\ifcsname#name\endcsname - 1% defined as command - \else - 3% specification - \fi - \endcsname{#name}} - -\protected\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} - -\permanent\tolerant\protected\def\definestylecollection[#name]% - {\ifarguments\or - \setuvalue{#name}{\styleinstance[#name]}% - \def\font_styles_define_style_collection_a#style% - {\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}% - \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 - -\permanent\tolerant\protected\def\definestyleinstance[#instance]#*[#2]#*[#3]#*[#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever] - {\ifparameter#instance\or - \ifarguments\or\or - \letvalueempty{\??stylecollection#instance::#2}% - \or - \setvalue{\??stylecollection#instance::#2}{#3}% - \or - \setvalue{\??stylecollection#instance:#2:#3}{#4}% - \fi - \ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi - \fi} - -\permanent\protected\def\styleinstance[#instance]% maybe \lastnamedcs here too - {\csname\??stylecollection#instance:% - \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname - \fontstyle:\fontalternative - \orelse\ifcsname\??stylecollection#instance:\fontstyle:\s!default\endcsname - \fontstyle:\s!default - \orelse\ifcsname\??stylecollection#instance::\fontalternative\endcsname - :\fontalternative - \else - :\s!default - \fi - \endcsname} - -%D Variant selectors -%D -%D \starttyping -%D \mathematics {\vsone{\utfchar{0x2229}}} -%D \mathematics {\utfchar{0x2229}\vsone{}} -%D \stoptyping - -\permanent\protected\edef\vsone#character{#character\normalUchar"FE00 } % used -\permanent\protected\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing - -%D For historic reasons we keep the following around but they are no longer that -%D relevant for \MKIV. But \unknown\ they will be dropped in \LMTX ! - -\permanent\protected\def\doattributes#1#2#3#4% - {\begingroup % geen \bgroup, anders in mathmode lege \hbox - \dousestylehashparameter{#1}{#2}% - \dousecolorhashparameter{#1}{#3}% - #4% - \endgroup} - -\permanent\protected\def\dostartattributes#1#2#3% - {\begingroup % geen \bgroup, anders in mathmode lege \hbox - \dousestylehashparameter{#1}{#2}% - \dousecolorhashparameter{#1}{#3}} - -\let\dostopattributes\endgroup - -%D New but it needs to be supported explicitly (as in natural tables). - -\newconditional\c_font_styles_math - -\protected\def\font_styles_math_reset - {\setfalse\c_font_styles_math} - -\protected\def\font_styles_math_start - {\ifconditional\c_font_styles_math - \startimath - \fi - \relax} - -\protected\def\font_styles_math_stop - {\relax - \ifconditional\c_font_styles_math - \stopimath - \fi} - -\definealternativestyle[\v!math][\settrue\c_font_styles_math] - -\protect \endinput diff --git a/tex/context/base/mkiv/font-sym.mklx b/tex/context/base/mkiv/font-sym.mklx deleted file mode 100644 index d95314099..000000000 --- a/tex/context/base/mkiv/font-sym.mklx +++ /dev/null @@ -1,246 +0,0 @@ -%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 as one can see, it does -%D obey the small and even smaller sizes. The \type {\symbolicfont} macro can be -%D used to switch to a font named \type {fontname} (see \type {cont-log} and \type -%D {symb-eur} for examples of symbolic definitions. - -\def\v_font_string_a - {\ifx\fontstyle\s!rm \s!Serif \orelse - \ifx\fontstyle\s!ss \s!Sans \orelse - \ifx\fontstyle\s!tt \s!Mono \else - \s!Serif \fi} - -\def\v_font_string_b - {\ifx\fontstyle\s!rm \s!Regular \orelse - \ifx\fontstyle\s!ss \s!Support \orelse - \ifx\fontstyle\s!tt \s!Type \else - \s!Serif \fi} - -\def\v_font_string_c - {\ifx\fontalternative\s!bf \s!Bold \orelse - \ifx\fontalternative\s!sl \s!Slanted \orelse - \ifx\fontalternative\s!it \s!Italic \orelse - \ifx\fontalternative\s!bs \s!BoldSlanted \orelse - \ifx\fontalternative\s!bi \s!BoldItalic \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. - -% \frozen ... - -\permanent\def\fontstylesuffix% why the \s!Regular ? see \getglyph - {\ifx\fontalternative\s!tf \s!Regular \orelse - \ifx\fontalternative\s!bf \s!Bold \orelse - \ifx\fontalternative\s!sl \s!Slanted \orelse - \ifx\fontalternative\s!it \s!Italic \orelse - \ifx\fontalternative\s!bs \s!BoldSlanted \orelse - \ifx\fontalternative\s!bi \s!BoldItalic \orelse - \ifx\fontalternative\s!sc \s!Caps \else - \s!Regular \fi} - -\permanent\def\glyphfontfile#base% appends - {#base% - \ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname - \v_font_string_a\v_font_string_c - \orelse\ifcsname\??fontfile#base\v_font_string_b\v_font_string_c\endcsname - \v_font_string_b\v_font_string_c - \orelse\ifcsname\??fontfile#base\v_font_string_a\endcsname - \v_font_string_a - \orelse\ifcsname\??fontfile#base\v_font_string_b\endcsname - \v_font_string_b - \orelse\ifcsname\??fontfile#base\v_font_string_c\endcsname - \v_font_string_c - \fi} - -%D The next macro can be used to make decisions based on the shape: - -\permanent\def\doifelseitalic#yes#nop% - {\ifx\fontalternative\s!sl#yes\orelse - \ifx\fontalternative\s!it#yes\orelse - \ifx\fontalternative\s!bs#yes\orelse - \ifx\fontalternative\s!bi#yes\else#nop\fi} - -\let\doifitalicelse\doifelseitalic - -%D For an example of usage of the following command, 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 implement a much faster -%D alternative: - -\installcorenamespace{symbolfont} - -\let\thedefinedfont\relax - -\permanent\protected\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile - {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% - \ifcsname\??symbolfont\askedsymbolfont\endcsname - \lastnamedcs - \else - \font_basics_define_symbolic_font - \fi} - -\permanent\protected\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile - {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% - \ifcsname\??symbolfont\askedsymbolfont\endcsname - \lastnamedcs - \else - \font_basics_define_symbolic_font - \fi} - -\permanent\protected\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile - {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}% - \ifcsname\??symbolfont\askedsymbolfont\endcsname - \lastnamedcs - \else - \font_basics_define_symbolic_font - \fi} - -\permanent\protected\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\letcsname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall} - -\permanent\protected\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}} -\permanent\protected\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}} -\permanent\protected\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} -\permanent\protected\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} -\permanent\protected\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}} -\permanent\protected\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}} - -% this one is wrong: - -\permanent\protected\def\getscaledglyph#scale#name#content% - {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}} - -\aliased\let\getglyph \getglyphstyled % old, soon obsolete -\aliased\let\getrawglyph \getglyphdirect % old, soon obsolete -\aliased\let\symbolicsizedfont\setscaledstyledsymbolicfont % old, soon obsolete -\aliased\let\symbolicfont \setstyledsymbolicfont % old, soon obsolete - -\permanent\protected\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody} - -%D The last implementation of \type {\getglyph} permits 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 environment. - -%D \macros -%D {setfont} -%D -%D Every now and then we want to define a font directly, for instance when we -%D typeset title pages. The next macro saves some typing: - -\permanent\protected\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 struts are set. - -%D \macros{doiffontcharelse} - -\permanent\protected\def\doifelsefontchar#specification#unicode% this could be a direct lua call - {\begingroup - \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% - \iffontchar\font#unicode\relax - \endgroup\expandafter\firstoftwoarguments - \else - \endgroup\expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiffontcharelse\doifelsefontchar - -\protect \endinput diff --git a/tex/context/base/mkiv/font-tra.mkxl b/tex/context/base/mkiv/font-tra.mkxl deleted file mode 100644 index 72addc5e9..000000000 --- a/tex/context/base/mkiv/font-tra.mkxl +++ /dev/null @@ -1,343 +0,0 @@ -%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 relations between -%D 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 \type {\halign}. - -\fetchruntimecommand \showbodyfont \f!font_run - -%D \macros -%D {showfontstrip, testminimalbaseline, showminimalbaseline} -%D -%D The next command can come in handy when combining different fonts into a -%D collection (typeface) and determining optimal baseline distances. -%D -%D \showfontstrip \blank \showminimalbaseline - -\fetchruntimecommand \showfontstrip \f!font_run -\fetchruntimecommand \testminimalbaseline \f!font_run -\fetchruntimecommand \showminimalbaseline \f!font_run - -%D \macros -%D {showkerning} -%D -%D A goody is: -%D -%D \showkerning{Can you guess what kerning is?} - -\fetchruntimecommand \showkerning \f!font_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!font_run - -%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!font_run -\fetchruntimecommand \showfontstyle \f!font_run -\fetchruntimecommand \showligature \f!font_run -\fetchruntimecommand \showligatures \f!font_run -\fetchruntimecommand \showcharratio \f!font_run -\fetchruntimecommand \showfontparameters \f!font_run - -\permanent\protected\def\showchardata#1{\ctxcommand{showchardata("#1")}} % todo: direct implementor -\permanent\protected\def\showfontdata {\ctxcommand{showfontparameters()}} % todo: direct implementor - -%D \macros -%D {doiffontpresentelse} -%D -%D \starttyping -%D \doiffontpresentelse{texnansi-lmr10}{YES}{NO} -%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO} -%D \stoptyping - -\permanent\protected\def\doifelsefontpresent#1{\clf_doifelsefontpresent{#1}} - -\aliased\let\doiffontpresentelse\doifelsefontpresent - -% experimental, maybe this becomes a module - -\newbox\otfcollector - -\permanent\protected\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}} -\permanent\protected\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}} -\permanent\protected\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}} - -% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page -% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page - -\permanent\protected\def\showotfstepglyphs#1% - {\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}% - \unhbox\otfcollector} - -\permanent\protected\def\otfstepspace - {\removeunwantedspaces - \hskip.5\emwidth \s!plus .125\emwidth \s!minus .125\emwidth\relax} - -\permanent\protected\def\otfstepcharcommand#1#2#3% font char class - {\otfstepspace - \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:% - \setbox\scratchbox\hbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}% - \ifzeropt\wd\scratchbox - \scratchwidth.125\onepoint - \scratchdistance\dimexpr(\emwidth/2-\scratchwidth)\relax - \kern\scratchdistance - \ruledhbox to \scratchwidth{\hss\box\scratchbox\hss}% - \kern-\scratchwidth - \hskip\scratchdistance - \else - \ruledhbox{\box\scratchbox}% - \fi - \otfstepspace} - -\permanent\protected\def\otfstepfontcommand#1#2#3% id font size - {\begingroup - \tttf #1: #2 @ \the\dimexpr#3\scaledpoint\relax - \endgroup} - -\permanent\protected\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} - -\permanent\protected\def\showotfstepfont - {\ctxlua{nodes.tracers.steppers.font("otfstepfontcommand")}} - -\permanent\protected\def\showotfstepchars#1% - {\ctxlua{nodes.tracers.steppers.codes(#1,"otfstepcharcommand","otfstepspace")}} - -\permanent\protected\def\showotfstepmessages#1% - {\ctxlua{nodes.tracers.steppers.messages(#1,"otfstepmessagecommand",true)}} - -\permanent\protected\def\showotfstepfeatures - {\ctxlua{nodes.tracers.steppers.features()}} - -\permanent\protected\def\otfnoffeaturesteps - {\ctxlua{nodes.tracers.steppers.nofsteps()}} - -\newconstant\showotfstepsmode \showotfstepsmode\plusfour - -\protected\def\showotfsteps_n - {\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 - \lefttoright - \dontleavehmode - \ifnum\recurselevel=\scratchcounter - \ruledhbox{\box\otfcompositionbox}% - \else - \ruledhbox{\showotfstepglyphs\recurselevel}% - \fi - \quad - \showotfstepchars\recurselevel - \hfill - \par - \egroup - \egroup - \blank} - -\permanent\protected\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 - {\ifcase\showotfstepsmode - \or % 1 = only first - \ifnum\recurselevel=\plusone - \showotfsteps_n - \fi - \or % 2 = only last - \ifnum\recurselevel=\scratchcounter - \showotfsteps_n - \fi - \or % 3 = first and last - \ifnum\recurselevel=\plusone - \showotfsteps_n - \orelse\ifnum\recurselevel=\scratchcounter - \showotfsteps_n - \fi - \else % everything - \showotfsteps_n - \fi}% - \endgroup} - -\permanent\protected\def\startotfsample - {\enabletrackers[otf.sample.silent]% beware, kind of global - \startotfcollecting - \begingroup - \veryraggedright - \forgetparindent - \forgeteverypar} - -\permanent\protected\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 - -\permanent\protected\def\setotfcompositiondirection#1% - {\begincsname\??otfcompositiondir#1\endcsname} - -\permanent\protected\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\setotfcompositiondirection{#2}\relax#3}% - \stopotfsample - \endgroup} - -%D \startbuffer -%D \startotfcompositionlist{Serif*default @ 11pt}{l2r}% -%D \showotfcompositionsample{effe} -%D \stopotfcompositionlist -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\permanent\protected\def\showotfcompositionlist#1#2#3% - {\begingroup - \definedfont[#1]% - \setbox\scratchbox\hbox\bgroup - \setotfcompositiondirection{#2}% - #3% - \egroup - \strut - \def|##1|{\kern\onepoint\string|\kern\onepoint##1\kern\onepoint\string|\kern\onepoint}% - \cldcontext{nodes.listtoutf(tex.box[\number\scratchbox].list,"{\\kern\\onepoint}",true)}% - \endgroup} - -\aliased\let\showotfcompositionsample\gobbleoneargument - -\permanent\protected\def\startotfcompositionlist#1#2#3\stopotfcompositionlist - {\begingroup - \enforced\protected\def\showotfcompositionsample##1% - {\NC\type{##1}% - \NC\showotfcompositionlist{Mono}{#2}{##1}% - \NC\showotfcompositionlist{#1}{#2}{##1}% - \NC\definedfont[#1]##1% - \NC\NR}% - \starttabulate[|||||]% - #3% - \stoptabulate - \endgroup} - -\aliased\let\stopotfcompositionlist\relax - -% new - -\permanent\protected\def\savefontdata[#1]% not yet in i-*.xml - {\begingroup - \getdummyparameters[#1]% - \clf_savefont { - filename {\dummyparameter\c!file} - fontname {\dummyparameter\c!name} - method {\dummyparameter\c!method} - }% - \endgroup} - -\protect \endinput diff --git a/tex/context/base/mkiv/grph-epd.mkxl b/tex/context/base/mkiv/grph-epd.mkxl deleted file mode 100644 index a0fcc51da..000000000 --- a/tex/context/base/mkiv/grph-epd.mkxl +++ /dev/null @@ -1,91 +0,0 @@ -%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}{} - -\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}] - -\protected\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 - -\defineframed - [epdfstampsymbol] - [\c!foregroundstyle=\v!mono, - \c!background=\c!color, - \c!rulethickness=.125\exheight, - \c!offset=.250\exheight, - \c!backgroundcolor=lightgray, % can be adapted before first usage - \c!framecolor=darkgray, % can be adapted before first usage - \c!corner=\v!round] - -\definesymbol[Stamped] [\epdfstampsymbol{Stamped}] - -\definesymbol[Approved] [\epdfstampsymbol{Approved}] -\definesymbol[Experimental] [\epdfstampsymbol{Experimental}] -\definesymbol[NotApproved] [\epdfstampsymbol{NotApproved}] -\definesymbol[AsIs] [\epdfstampsymbol{AsIs}] -\definesymbol[Expired] [\epdfstampsymbol{Expired}] -\definesymbol[NotForPublicRelease] [\epdfstampsymbol{NotForPublicRelease}] -\definesymbol[Confidential] [\epdfstampsymbol{Confidential}] -\definesymbol[Final] [\epdfstampsymbol{Final}] -\definesymbol[Sold] [\epdfstampsymbol{Sold}] -\definesymbol[Departmental] [\epdfstampsymbol{Departmental}] -\definesymbol[ForComment] [\epdfstampsymbol{ForComment}] -\definesymbol[TopSecret] [\epdfstampsymbol{TopSecret}] -\definesymbol[Draft] [\epdfstampsymbol{Draft}] -\definesymbol[ForPublicRelease] [\epdfstampsymbol{ForPublicRelease}] - -\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/tex/context/base/mkiv/grph-fig.mkxl b/tex/context/base/mkiv/grph-fig.mkxl deleted file mode 100644 index d28427d40..000000000 --- a/tex/context/base/mkiv/grph-fig.mkxl +++ /dev/null @@ -1,357 +0,0 @@ -%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. - -% This is (yet) untested in LMTX! - -\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 - -\permanent\protected\def\typesetbuffer {\bgroup\setconstant\c_grph_buffers_mode\plusone \grph_buffers_typeset} -\permanent\protected\def\typesetbufferonly{\bgroup\setconstant\c_grph_buffers_mode\zerocount\grph_buffers_typeset} - -\tolerant\permanent\protected\def\grph_buffers_typeset[#1]#*[#2]% - {\ifparameters - \grph_buffers_typeset_indeed\jobname\empty - \or - \ifhastok={#1}% - \grph_buffers_typeset_indeed\jobname{#1}% - \else - \grph_buffers_typeset_indeed{#1}\empty - \fi - \or - \grph_buffers_typeset_indeed{#1}{#2}% - \fi} - -\def\grph_buffers_typeset_indeed#1#2% we could use the via files - {\doifnot{#1}{*}{\xdef\lasttypesetbuffer{\clf_typesetbuffer{#1}}}% - \ifcase\c_grph_buffers_mode - % typesetonly - \or - \externalfigure[\lasttypesetbuffer][#2]% - \fi - \egroup} - -\tolerant\permanent\protected\def\runbuffer[#1]#*[#2]% - {\xdef\lasttypesetbuffer{\clf_runbuffer{#1}{#2}}} - -% 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} - -\tolerant\permanent\protected\def\definetypesetting[#1]#*[#2]#*[#3]% options settings-a - {\ifparameter#1\or\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}\fi} - -\tolerant\permanent\protected\def\typesetfile[#1]#*[#2]#*[#3]% filename settings-b | filename options settings - {\ifcsname\??typesettingfile#1\endcsname - \lastnamedcs{#2}{#3}% - \orelse\ifparameter#3\or - \grph_typesetting_process_indeed{#2}{#3}{#1}{}% - \orelse\ifparameter#2\or % filename settings - \grph_typesetting_process_indeed{}{#2}{#1}{}% - \fi} - -\defineexternalfigure[typesetting] % so one can set a frame and such - -\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 - \normalexpanded{\externalfigure[\m_typesetting_name][typesetting]}[#2,#4]% - \fi - \endgroup} - -%D Whatever ... hardly used ... but historic ... needs checking ... will probably -%D become m-fig-nn.mkiv .. or I will extend it cq. clean it up when I needed it. -%D 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 - -\tolerant\protected\def\grph_steps_place_figure#1#2#3#4[#5]% - {\hpack - {\setbox\scratchbox\hpack - {\useexternalfigure[\s!dummy][#2][#3,#5]% - \externalfigure[\s!dummy]}% - \grph_steps_calculate - \startpositioning - \enforced\let\referring\grph_steps_one_referring - \enforced\let\marking \grph_steps_one_marking - \enforced\let\remark \grph_steps_one_remark - \enforced\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% - \enforced\let\referring\grph_steps_two_referring - \enforced\let\marking \grph_steps_two_marking - \enforced\let\remark \grph_steps_two_remark - \enforced\let\colorbar \grph_steps_two_colorbar - \ignorespaces#4\removeunwantedspaces % or just grab #4 unspaced - \stoppositioning - \ifvoid\b_grph_steps_colorbar\else\box\b_grph_steps_colorbar\fi}} % not really needed - -\protected\def\grph_steps_one_referring(#1,#2)#*(#3,#4)#*[#5]% - {\position(#1,#2){\grph_steps_goto(#3,#4){\externalfigureparameter\c!frames}[#5]}} - -\protected\def\grph_steps_one_marking(#1,#2)#*(#3,#4)#*[#5]% - {\position(#1,#2){\grph_steps_this_is(#3,#4){\externalfigureparameter\c!frames}[#5]}} - -\protected\def\grph_steps_one_remark (#-,#-)#*(#-,#-)#*[#-]#*#:#-{}% (x,y)(h,b)[...]{tekst} -\protected\def\grph_steps_one_colorbar #-[#-]{} -\protected\def\grph_steps_two_referring(#-,#-)#*(#-,#-)#*[#-]{} - -\let\grph_steps_two_marking\grph_steps_two_referring - -\protected\def\grph_steps_two_remark - {\grph_steps_comment\v!no} - -\protected\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} - -\protected\def\grph_colorbar_make_step#1% - {\blackrule[\c!color=#1,\c!width=2\emwidth,\c!height=\exheight,\c!depth=\zeropoint]% - \endgraf} - -\permanent\protected\def\startfigure[#1]#*[#2]#*[#3]#:#4\stopfigure - {\doifelse{\externalfigureparameter\c!option}\v!test - {\grph_steps_test_figure{#1}{#2}{#3}{#4}% - \letexternalfigureparameter\c!frames\v!on}% - {\letexternalfigureparameter\c!frames\v!off}% - \setvalue{\??externalfigureinstance#1}% - {\grph_steps_place_figure{#1}{#2}{#3}{#4}}} - -\aliased\let\stopfigure\relax - -\protected\def\grph_steps_test_figure#1#2#3#4% - {\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 - \setbox\scratchboxone\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\removeunwantedspaces % or just grab #4 unspaced - \stoppositioning - \vfill}% - \c_grph_steps_reference\zerocount - \enforced\let\referring\grph_steps_four_referring - \enforced\let\marking \grph_steps_four_marking - \enforced\let\remark \grph_steps_four_remark - \enforced\let\colorbar \grph_steps_four_colorbar - \setbox\scratchboxtwo\vbox % \vpack ? - {\forgetall - \begingroup - \tfa\doifelsenothing{#1}{#2}{#1}% - \endgroup - \blank - \tfxx#4% - \vfilll}% - \ifdim\ht\scratchboxone>\ht\scratchboxtwo - \ht\scratchboxtwo\ht\scratchboxone - \else - \ht\scratchboxone\ht\scratchboxtwo - \fi - \hpack - {\hskip3\emwidth - \tpack{\vskip12\points\box\scratchboxone\vskip6\points}% - \tpack{\vskip12\points\box\scratchboxtwo\vskip6\points}}% - \endgroup} - -\definesystemconstant{vwa} -\definesystemconstant{vwb} - -\tolerant\protected\def\grph_steps_three_referring(#1,#2)#*(#3,#4)#*[#5]% - {\advance\c_grph_steps_reference\plusone - \position(#1,#2) - {\hbox{\the\c_grph_steps_reference}}% - \position(#1,#2) - {\gotosomeinternal\s!vwb{#5}\realfolio - {\grph_steps_marker(#3,#4)\v!on{\thisissomeinternal\s!vwa{#5}}}}} - -\protected\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 - -\protected\def\grph_steps_four_referring{\grph_steps_text{\normalstartimath\rightarrow\normalstopimath}} -\protected\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} - -\tolerant\def\grph_steps_comment#1(#2,#3)#*(#4,#5)#*[#6]#*#:#7% {kader}(x,y)(h,b)[...]{tekst} - {\position(#2,#3)% - {\setnostrut - \framed[\c!width=#4\d_grph_steps_x,\c!height=#5\d_grph_steps_y,\c!offset=\v!none,\c!frame=#1,#6]{#7}}} - -% \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]} - -\tolerant\def\grph_steps_text#1(#2,#3)#*(#4,#5)#*[#6]% - {\advance\c_grph_steps_reference\plusone - \hbox % \hpack ? - {\quad - \thisissomeinternal\s!vwb{#6}% - \gotosomeinternal\s!vwa{#6}\realfolio{\hbox to 1.5\emwidth{\the\c_grph_steps_reference\presetgoto\hfill}}% - \quad#1 (#2,#3) (#4,#5) [#6]\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/tex/context/base/mkiv/grph-inc.mkxl b/tex/context/base/mkiv/grph-inc.mkxl deleted file mode 100644 index 1e6d614a6..000000000 --- a/tex/context/base/mkiv/grph-inc.mkxl +++ /dev/null @@ -1,1076 +0,0 @@ -%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-img}{} -\registerctxluafile{grph-inc}{} -\registerctxluafile{grph-bmp}{} -\registerctxluafile{grph-chk}{} -\registerctxluafile{grph-con}{} -\registerctxluafile{grph-fil}{} -\registerctxluafile{grph-mem}{} -\registerctxluafile{grph-u3d}{} % this will become a module -\registerctxluafile{grph-swf}{} % this will become a module - -\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 not so much less code as in \MKII\ but it's -%D more powerful, flexible, pluggable and some of the extended functionality has been -%D moved from modules to the core. The overall functionality is rather stable and has -%D not changed much over the years. - -\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi - -\installcorenamespace{externalfigure} -\installcorenamespace{externalfigureinstance} -\installcorenamespace{externalfigurecollection} - -\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure - -\aliased\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!file =, - \c!display =, - \c!mask =, - \c!preset =\v!yes, - \c!split =, - \c!color =, - \c!arguments =, - \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. - \c!crossreference =\v!no, - \c!transform =\v!auto, - \c!userpassword =, - \c!ownerpassword =, - \c!compact =, - \c!cmyk =, - ] - -%D Defining figures. - -\newcount\c_grph_include_nesting - -\newtoks \everyexternalfigureresets % for the moment still public -\newtoks \everyexternalfigurechecks % for the moment still public - -% \useexternalfigure[alpha][cow] -% \useexternalfigure[beta] [cow] [width=1cm] -% \useexternalfigure[gamma][cow][alpha] -% \useexternalfigure[delta][cow][alpha][width=2cm] -% -% full width : \externalfigure[cow] \par -% 3cm width : \externalfigure[cow] [width=3cm] \par -% full width : \externalfigure[alpha] \par -% 1cm width : \externalfigure[beta] \par -% full width : \externalfigure[gamma] \par -% 2cm width : \externalfigure[delta] \par -% 4cm width : \externalfigure[beta] [width=4cm] \par -% 5cm width : \externalfigure[gamma][width=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, the already set -%D parameters need to be set again or otherwise the old values will be used. -%D -%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 the web -%D tools need a suffix (like gif) which we don't want as we want a high quality -%D format. - -\newconditional\c_grph_include_trace_inheritance - -\installtextracker - {graphics.inheritance} - {\settrue \c_grph_include_trace_inheritance} - {\setfalse\c_grph_include_trace_inheritance} - -\installcorenamespace{externalfiguredefinition} - -% \protected\def\defineexternalfigure -% {\dodoubleargument\grph_include_define} -% -% \def\grph_include_define[#1][#2]% -% {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}} - -\aliased\let\defineexternalfigures\defineexternalfigure - -% label file parent settings -% label file settings -% label file parent - -\permanent\tolerant\protected\def\useexternalfigure[#1]#*[#2]#*[#3]#*[#4]% - {\iftok{#1}\emptytoks - \iftok{#2}\emptytoks\else - \ifhastok={#3}% - \grph_include_use_indeed{#2}{#2}{#3}{#4}% - \else - \grph_include_use_indeed{#2}{#2}\empty{#4}% - \fi - \fi - \orelse\iftok{#2}\emptytoks - \ifhastok={#3}% - \grph_include_use_indeed{#1}{#1}\empty{#3}% - \else - \grph_include_use_indeed{#1}{#1}{#3}{#4}% - \fi - \else - \ifhastok={#3}% - \grph_include_use_indeed{#1}{#2}\empty{#3} - \else - \grph_include_use_indeed{#1}{#2}{#3}{#4}% - \fi - \fi} - -\def\grph_include_use_indeed#1#2#3#4% - {\dodoglobal\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}% - \grph_include_analyze_collection[#2][#4]} - -% inclusion - -\permanent\tolerant\protected\def\externalfigure[#1]#*[#2]#*[#3]% - {\ifhastok={#2}% - \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}% - \ifempty\m_grph_include_name \else - \let\p_grph_include_name\m_grph_include_name - \fi - \ifempty\m_grph_include_parent \else - \grph_include_inherit_from_parent\m_grph_include_parent - \fi - \setupcurrentexternalfigure[#3]} - -\def\grph_include_inherit_from_parent#1% - {\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 - \ifempty\p_grph_include_parent - % nothing to be done - \orelse\ifx\p_grph_include_parent\p_grph_include_label - % redundant - \else - \grph_include_inherit_from_parent\p_grph_include_parent - \fi - \ifempty\p_grph_include_label - % 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 - \ifhastok={#2}% - % [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}% - \ifempty\p_grph_include_parent - \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}% - \edef\p_reference{\externalfigureparameter\c!reference}% - % - \dostarttagged\t!image\empty - \clf_figure_push { - name {\p_grph_include_name}% - label {\ifempty\p_label\p_grph_include_label\else\p_label\fi}% - page {\externalfigureparameter\c!page}% - file {\externalfigureparameter\c!file}% - size {\externalfigureparameter\c!size}% - object {\externalfigureparameter\c!object}% - prefix {\externalfigureparameter\c!prefix}% - cache {\externalfigureparameter\c!cache}% - format {\externalfigureparameter\c!method}% - preset {\externalfigureparameter\c!prefix}% - controls {\externalfigureparameter\c!controls}% - resources {\externalfigureparameter\c!resources}% - preview {\externalfigureparameter\c!preview}% - display {\externalfigureparameter\c!display}% - mask {\externalfigureparameter\c!mask}% - conversion {\externalfigureparameter\c!conversion}% - resolution {\externalfigureparameter\c!resolution}% - color {\externalfigureparameter\c!color}% unprocessed raw key - cmyk {\externalfigureparameter\c!cmyk}% kind of special - arguments {\externalfigureparameter\c!arguments}% used for converters - repeat {\externalfigureparameter\c!repeat}% - transform {\externalfigureparameter\c!transform}% - compact {\externalfigureparameter\c!compact}% experiment, share fonts - userpassword {\externalfigureparameter\c!userpassword}% - ownerpassword{\externalfigureparameter\c!ownerpassword}% - \ifempty\p_width \else - width \dimexpr\p_width\relax - \fi - \ifempty\p_height \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 - % - \scratchcounter\zerocount - \edef\p_crossreference{\externalfigureparameter\c!crossreference}% - \iflocation\iftrialtypesetting\else - \ifempty\p_crossreference - % nothing - \orelse\ifx\p_crossreference\v!no - % nothing - \orelse\ifx\p_crossreference\v!yes - \ifhastok={#2}% - \scratchcounter\clf_figure_register_page{#1}{}{#2}\relax - \else - \scratchcounter\clf_figure_register_page{#1}{#2}{#3}\relax - \fi - \else - \scratchcounter-\p_crossreference % passed by repeater - \fi - \fi\fi - \naturalvpack - attr \imageattribute \plustwo - \ifnum\scratchcounter>\zerocount - {\strc_references_cross_forward {ex:\number \scratchcounter}{\box\foundexternalfigure}}% - \orelse\ifnum\scratchcounter<\zerocount - {\strc_references_cross_backward{ex:\number-\scratchcounter}{\box\foundexternalfigure}}% - \else - {\box\foundexternalfigure}% - \fi - % - % \naturalvpack attr \imageattribute \plustwo \bgroup - % \ifcmpnum\scratchcounter\zerocount - % \strc_references_cross_backward{ex:\number-\scratchcounter}{\box\foundexternalfigure}% - % \or % equal - % \box\foundexternalfigure% - % \or % more - % \strc_references_cross_forward {ex:\number \scratchcounter}{\box\foundexternalfigure}% - % \fi - % \egroup - % - \dostoptagged - \egroup} - -%D Next we provide a cross referenced scale-up mechanism: - -\def\strc_references_cross_forward#1#2% - {\begingroup - \strc_references_set_simple_internal_reference{cross:b:#1}% - \naturalhpack - attr \destinationattribute\number\lastdestinationattribute - {\naturalhpack{\strc_references_flush_destination_nodes\directgotodumbbox{#2}[cross:f:#1]}}% - \endgroup} - -\def\strc_references_cross_backward#1#2% - {\begingroup - \strc_references_set_simple_internal_reference{cross:f:#1}% - \naturalhpack - attr \destinationattribute\number\lastdestinationattribute - {\naturalhpack{\strc_references_flush_destination_nodes\directgotodumbbox{#2}[cross:b:#1]}}% - \endgroup} - -\let\doexternalfigurerepeat\gobblefourarguments % called from lua end - -\permanent\tolerant\protected\def\placeregisteredexternalfigures[#1]% - {\page - \begingroup - \protected\def\doexternalfigurerepeat{\grph_include_place_registered_indeed{#1}}% - \dorecurse\clf_figure_nof_registered_pages - {\page - \clf_figure_flush_registered_pages\recurselevel - \page}% - \endgroup - \page} - -\protected\def\grph_include_place_registered_indeed#1#2#3#4#5% called from lua end - {\grph_include_place[#2][#3][#4,% - \c!hfactor=,\c!wfactor=,\c!factor=,% - \c!maxwidth=,\c!maxheight=,% - \c!xscale=,\c!yscale=,\c!scale=,% - \c!sx=,\c!sy=,\c!s=,% - \c!width=,\c!height=,% - \c!crossreference=#5,% - #1]} - -%D Scaling: - -\let\dowithfigure\relax % name might change (into a proper hook) - -\permanent\protected\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] - -%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 - -\permanent\tolerant\protected\def\definegraphictypesynonym[#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. - -\permanent\protected\def\setfigurepathlist - {\clf_setfigurepaths{\externalfigureparameter\c!location}{\externalfigureparameter\c!directory}} - -%D Variables: - -\newbox \foundexternalfigure -\newtoks\externalfigurepostprocessors - -\def\defaultfigurewidth {8\lineheight} % permanent ? frozen ? -\def\defaultfigureheight {6\lineheight} % permanent ? frozen ? - -\permanent\def\figurestatus {\numexpr\clf_figurestatus{status}{0}\relax} % number: 0 = not found -\permanent\def\figurewidth {\clf_figurestatus{width}{0}sp} -\permanent\def\figureheight {\clf_figurestatus{height}{0}sp} -\permanent\def\figurexscale {\clf_figurestatus{xscale}{1}} -\permanent\def\figureyscale {\clf_figurestatus{yscale}{1}} - -\permanent\def\figuresize {\clf_figurerequest{size}{}} -\permanent\def\figurelabel {\clf_figurerequest{label}{}} -\permanent\def\figurefileoriginal {\clf_figurerequest{name}{}} -\permanent\def\figurefilepage {\clf_figurerequest{page}{1}} -\permanent\def\figurefileoptions {\clf_figurerequest{options}{}} -\permanent\def\figurefileconversion{\clf_figurerequest{conversion}{}} -\permanent\def\figurefileresolution{\clf_figurerequest{resolution}{}} -\permanent\def\figurefilecolor {\clf_figurerequest{color}{}} -\permanent\def\figurefilearguments {\clf_figurerequest{arguments}{}} -\permanent\def\figurefilecache {\clf_figurerequest{cache}{}} -\permanent\def\figurefileprefix {\clf_figurerequest{prefix}{}} - -\permanent\def\figurenaturalwidth {\clf_figureused{width}{\number\dimexpr\defaultfigurewidth\relax}sp} -\permanent\def\figurenaturalheight {\clf_figureused{height}{\number\dimexpr\defaultfigureheight\relax}sp} -\permanent\def\figurexresolution {\clf_figureused{xresolution}{0}} -\permanent\def\figureyresolution {\clf_figureused{yresolution}{0}} -\permanent\def\figureorientation {\clf_figureused{orientation}{1}} -\permanent\def\figurerotation {\clf_figureused{rotation}{0}} -\permanent\def\figurexsize {\clf_figureused{xsize}{0}} -\permanent\def\figureysize {\clf_figureused{ysize}{0}} -\permanent\def\figurecolordepth {\clf_figureused{colordepth}{0}} -\permanent\def\figuredepth {\clf_figureused{depth}{0}} - -\permanent\def\figurefullname {\clf_figureused{fullname}{}} -\permanent\def\noffigurepages {\clf_figureused{pages}{0}} - -% \permanent\def\figurefilepath {\clf_figurefilepath} % public in lua -% \permanent\def\figurefilename {\clf_figurefilename} % public in lua -% \permanent\def\figurefiletype {\clf_figurefiletype} % public in lua - -\permanent\let\naturalfigurewidth \figurenaturalwidth -\permanent\let\naturalfigureheight \figurenaturalheight - -\aliased\let\figurescalewidth \figurewidth -\aliased\let\figurescaleheight \figureheight -\aliased\let\figurescalexscale \figurexscale -\aliased\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 - \globalresetsystemmode\v!figure % todo, also: \v!resource - \else - \globalsetsystemmode \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}% - \ifempty\p_foregroundcolor \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: - -\permanent\protected\def\docheckfigurebuffer #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\getbuffer[#1]}}} -\permanent\protected\def\docheckfiguretex #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\input{#1}}}} -\permanent\protected\def\docheckfigurecld #1{\global\setbox\foundexternalfigure\vbox {\cldprocessfile{#1}}} -\permanent\protected\def\docheckfiguremps #1{\global\setbox\foundexternalfigure\vpack{\convertMPtoPDF{#1}11}} -\permanent\protected\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vpack{\useMPrun{#1}{#2}}} - -\permanent\protected\def\relocateexternalfigure - {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup - % - % The \vss can (!) introduce 1 sp excess visible in xform which in itself - % is not that important but some don't like these cosmetic side effects, for - % instance we can get: - % - % vss : \vbox(845.1575+0.0)x597.23125, glue set 845.15747fil, direction TLT - % vskip : \vbox(845.1575+0.0)x597.23125, direction TLT - % - % or - % - % 1 0 0 1 0 0.00003 cm - % 1 0 0 1 0 0 cm - % - % This is a known property of using glue and can even depend on the architecture - % (float implementation). Anyway, let's for now use a skip. Of course this can - % shift the issue elsewhere, as vss is used a lot elsewhere. - % - % \vss - \vkern\ht\foundexternalfigure - % - \ht\foundexternalfigure\zeropoint - \dp\foundexternalfigure\zeropoint - \hpack to \wd\foundexternalfigure\bgroup - \box\foundexternalfigure - \hss - \egroup - \egroup} - -\permanent\protected\def\startfoundexternalfigure#1#2% ht wd - {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup} - -\permanent\protected\def\stopfoundexternalfigure - {\hss\egroup\egroup} - -\permanent\protected\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 - \orelse\ifcase\figurestatus - % nothing - \else - \the\externalfigurepostprocessors - \box\foundexternalfigure - \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 - \orelse\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 - \inheritedexternalfigureframed{\box\foundexternalfigure}% - \fi - \fi - \fi - \else - % maybe also \the\externalfigurepostprocessors - \iftrialtypesetting \else \feedbackexternalfigure \fi - \fi}} - -\let\feedbackexternalfigure\relax % hook - -\permanent\protected\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} - -\permanent\protected\def\doifelsefigure#1% - {\getfiguredimensions[#1]% so data is available ! - \ifcase\figurestatus - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\aliased\let\doiffigureelse\doifelsefigure - -% No placement, handy for preprocessing: - -\permanent\tolerant\protected\def\registerexternalfigure[#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. - -\permanent\protected\def\dosetfigureobject#1#2% - {\setobject{#1}{#2}\vpack{\box\foundexternalfigure}} - -\permanent\protected\def\doboxfigureobject#1#2% - {\global\setbox\foundexternalfigure\vpack{\getobject{#1}{#2}}} % probably one vbox too many - -% Figure bases - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\def\externalfigurecollectionparameter#1#2% - {\csname - \ifcsname\??externalfigurecollection#1:#2\endcsname - \??externalfigurecollection#1:#2% - \else - \s!empty - \fi - \endcsname} - -\permanent\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth } -\permanent\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth } -\permanent\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight} -\permanent\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight} - -\aliased\let\efcparameter\externalfigurecollectionparameter % still needed ? -\aliased\let\efcminwidth \externalfigurecollectionminwidth % still needed ? -\aliased\let\efcmaxwidth \externalfigurecollectionmaxwidth % still needed ? -\aliased\let\efcminheight\externalfigurecollectionminheight % still needed ? -\aliased\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 - -\permanent\protected\def\overlayfigure#1% - {\externalfigure[#1][\c!width=\d_overlay_width,\c!height=\d_overlay_height]} - -% Experimental (will become cleaner): - -\permanent\tolerant\protected\def\includesvgfile[#1]#*[#2]% - {\dontleavehmode\begingroup - \getdummyparameters[\c!offset=\zeropoint,#2]% - \clf_includesvgfile{#1}\dimexpr\dummyparameter\c!offset\relax - \endgroup} - -\permanent\tolerant\protected\def\includesvgbuffer[#1]#*[#2]% - {\dontleavehmode\begingroup - \getdummyparameters[\c!offset=\zeropoint,#2]% - \clf_includesvgbuffer{#1}\dimexpr\dummyparameter\c!offset\relax - \endgroup} - -% Bonus: - -\useexternalfigure - [\v!buffer] - [\jobname.buffer] - [\c!object=\v!no] - -% Another two: - -\defineexternalfigure - [\v!inline] - [\c!height=\lineheight] - -\definemeasure - [\v!combination] - [(\textwidth - -\effectiveleftskip - -\effectiverightskip - -\numexpr\combinationparameter\c!nx-\plusone\relax\dimexpr\combinationparameter\c!distance\relax - )/\combinationparameter\c!nx] - -\defineexternalfigure - [\v!combination] - [\c!width=\measure{\v!combination}] - -% \startcombination[nx=2,ny=1] -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% \stopcombination - -% \startcombination[nx=2,ny=1] -% {\externalfigure[dummy][width=\measure{combination}]} {} -% {\externalfigure[dummy][width=\measure{combination}]} {} -% \stopcombination - -% \startcombination[nx=2,ny=2] -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% \stopcombination - -% \startcombination[nx=3,ny=1] -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% \stopcombination - -% \startcombination[nx=4,ny=1] -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% {\externalfigure[dummy][combination]} {} -% \stopcombination - -\permanent\protected\def\inlinefigure[#1]% - {\dontleavehmode - \sbox{\externalfigure[#1][\v!inline]}} - -%D Needs to be done global: - -\definelayer[epdfcontent] - -\protect \endinput - -%D Moved here because this already old code is nowhere documents (so I need to check -%D it: -% -% \starttyping -% \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][frame=on,display=u3d:myset:display:2]} -% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:3]} -% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:4]} -% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]} -% -% \stoptext diff --git a/tex/context/base/mkiv/grph-pat.mkxl b/tex/context/base/mkiv/grph-pat.mkxl deleted file mode 100644 index 92fd5ad74..000000000 --- a/tex/context/base/mkiv/grph-pat.mkxl +++ /dev/null @@ -1,119 +0,0 @@ -%D \module -%D [ file=grph-par, -%D version=2016.07.08, -%D title=\CONTEXT\ Graphic Macros, -%D subtitle=Patterns, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This works ok in Okular and MuPDF but somehow xforms don't work in Acrobat -%D (full nor reader). Also the basic offset is kind of unspecified. So \unknown\ -%D we're dealing with a fragile feature. So, don't rely on where the first (ulr) -%D tile occurs. -%D -%D The two commands introduced here are not documented (yet). - -\writestatus{loading}{ConTeXt Graphic Macros / Patterns} - -\unprotect - -\registerctxluafile{grph-pat}{} - -\permanent\tolerant\protected\def\registerpattern[#1]#*[#2]% - {\begingroup - \letdummyparameter\c!name \s!dummy - \letdummyparameter\c!width \v!auto - \letdummyparameter\c!height \v!auto - \letdummyparameter\c!hoffset\zeropoint - \letdummyparameter\c!voffset\zeropoint - \unless\iftok{#2}\emptytoks - \setdummyparameter\c!name{#1}% - \getdummyparameters[#2]% - \orelse\ifhastok={#1}% - \getdummyparameters[#1]% - \else - \setdummyparameter\c!name{#1}% - \fi - \dowithnextboxcs\syst_boxes_registerpattern_indeed\hbox} - -\immutable\edef\v!auto_m{-\v!auto} - -\def\syst_boxes_registerpattern_indeed - {%\finalizeobjectbox\nextbox - \edef\p_width {\dummyparameter\c!width}% - \edef\p_height {\dummyparameter\c!height}% - \edef\p_hoffset{\dummyparameter\c!hoffset}% - \edef\p_voffset{\dummyparameter\c!voffset}% - \scratchwidth \dimexpr\ifx\p_width \v!auto\wd \nextbox\else\p_width \fi\relax - \scratchheight \dimexpr\ifx\p_height \v!auto\htdp\nextbox\else\p_height \fi\relax - \scratchhoffset\dimexpr\ifx\p_hoffset\v!auto\scratchwidth /2\orelse\ifx\p_hoffset\v!auto_m-\scratchwidth /2\else\p_hoffset\fi\relax - \scratchvoffset\dimexpr\ifx\p_voffset\v!auto\scratchheight/2\orelse\ifx\p_voffset\v!auto_m-\scratchheight/2\else\p_voffset\fi\relax - \clf_registerpattern - name {\dummyparameter\c!name} - number \nextbox - width \scratchwidth - height \scratchheight - hoffset \scratchhoffset - voffset \scratchvoffset - \relax - \endgroup} - -\permanent\tolerant\protected\def\applypattern[#1]#*[#2]% - {\hbox\bgroup - \letdummyparameter\c!name \s!dummy - \letdummyparameter\c!width \zeropoint - \letdummyparameter\c!height\zeropoint - \unless\iftok{#2}\emptytoks - \setdummyparameter\c!name{#1}% - \getdummyparameters[#2]% - \orelse\ifhastok={#1}% - \getdummyparameters[#1]% - \else - \setdummyparameter\c!name{#1}% - \fi - \clf_applypattern - name {\dummyparameter\c!name} - number \nextbox - width \dimexpr\dummyparameter\c!width\relax - height \dimexpr\dummyparameter\c!height\relax - \relax - \box\nextbox - \egroup} - -\protect - -\continueifinputfile{grph-pat.mkxl} - -\nopdfcompression - -\starttext - - \registerpattern[demo]{It \darkred Works!} - - \framed[offset=overlay]{\applypattern[demo][width=7cm,height=4cm]} - - \blank - - \registerpattern[name=more,hoffset=0bp,voffset=0pt]{\externalfigure[cow.pdf][width=1cm]} - - \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} - - \blank - - \registerpattern[name=more,hoffset=auto,voffset=auto]{\externalfigure[cow.pdf][width=1cm]} - - \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} - - \blank - - \registerpattern[name=more,hoffset=-auto,voffset=-auto]{\externalfigure[cow.pdf][width=1cm]} - - \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} - -\stoptext - diff --git a/tex/context/base/mkiv/grph-raw.mkxl b/tex/context/base/mkiv/grph-raw.mkxl deleted file mode 100644 index 66194551b..000000000 --- a/tex/context/base/mkiv/grph-raw.mkxl +++ /dev/null @@ -1,64 +0,0 @@ -%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}{} - -\unprotect - -\permanent\protected\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} - -\permanent\protected\def\startbitmapimage[#1]#2\stopbitmapimage - {\bitmapimage[#1]{#2}} - -\aliased\let\stopbitmapimage\relax - -\protect \endinput diff --git a/tex/context/base/mkiv/grph-rul.mkxl b/tex/context/base/mkiv/grph-rul.mkxl deleted file mode 100644 index ef65b1fe4..000000000 --- a/tex/context/base/mkiv/grph-rul.mkxl +++ /dev/null @@ -1,89 +0,0 @@ -%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}{} - -\unprotect - -\permanent\protected\def\frule{\relax\clf_frule} % will become a public implementer - -% 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/tex/context/base/mkiv/grph-trf.mkxl b/tex/context/base/mkiv/grph-trf.mkxl deleted file mode 100644 index 0a423bd6b..000000000 --- a/tex/context/base/mkiv/grph-trf.mkxl +++ /dev/null @@ -1,1011 +0,0 @@ -%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 go away. Some of -%D this is an inheritance of limited backends (some supported fractions, some -%D 1000's, some dimentions) so we calculate all of them. Nowadays scaling is always -%D available so we could simplify the code. On the other hand, we now get some extra -%D values for free. -%D -%D We could move the calculations to \LUA\ and clean up this lot anyway. On the -%D other hand, there is some danger of messing up so it has a real low priority. - -\registerctxluafile{grph-trf}{} - -% 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 - -\newconditional\c_grph_scale_swap_factor - -\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} -\installcorenamespace{scalefact} - -\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] - -\permanent\tolerant\protected\def\scale[#1]#*[#2]% - {\bgroup - % this is quite common so we might make this a helper - \ifarguments - \let\currentscale\empty - \or - \ifhastok={#1}% - \let\currentscale\empty - \setupcurrentscale[#1]% - \else - \edef\currentscale{#1}% - \fi - \or - \edef\currentscale{#1}% - \setupcurrentscale[#2]% - \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\naturalhpack{\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 - % - \glet\finalscaleboxxscale \!!plusone - \glet\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 - \ifdim\d_grph_scale_wd=\wd\nextbox - \ifdim\d_grph_scale_ht=\ht\nextbox - \ifdim\d_grph_scale_dp=\dp\nextbox - % \grph_scale_apply_nop - \else - \grph_scale_apply_yes - \fi - \else - \grph_scale_apply_yes - \fi - \else - \grph_scale_apply_yes - \fi} - -\def\grph_scale_apply_yes - {\setbox\nextbox\naturalhpack - {\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}% - \ifempty\m_grph_scale_stamp_a - \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 - \ifempty\m_grph_scale_stamp_b - % 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% - {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax} - -\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 - \ifempty\finalscaleboxxscale\let\finalscaleboxxscale\!!plusone\fi - \ifempty\finalscaleboxyscale\let\finalscaleboxyscale\!!plusone\fi} - -\let\grph_scale_calculations_report\relax - -\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 - {\ifempty\p_maxwidth \else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi - \ifempty\p_maxheight\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi - \ifempty\p_lines \else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi - \csname\??scalegrid\scaleparameter\c!grid\endcsname} - -\def\grph_scale_by_nature % where ! ! ! ! ! - {\ifempty\p_width \else \global\d_grph_scale_used_x_size\p_width \fi - \ifempty\p_height\else \global\d_grph_scale_used_y_size\p_height\fi - \ifempty\p_scale \else \c_grph_scale_used_x_scale\p_scale - \c_grph_scale_used_y_scale\p_scale \fi - \ifempty\p_xscale\else \c_grph_scale_used_x_scale\p_xscale\fi - \ifempty\p_yscale\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]}} - -%D The \typpe {min} option makes sure that the smallest available space determines -%D the max size (so we can get a bleed on the other axis): -%D -%D \startlinecorrection -%D \startcombination[nx=2,ny=2,distance=4cm] -%D {\externalfigure[hacker][factor=max,maxwidth=6cm,maxheight=6cm]} {} -%D {\externalfigure[mill] [factor=max,maxwidth=6cm,maxheight=6cm]} {} -%D {\externalfigure[hacker][factor=min,maxwidth=6cm,maxheight=6cm]} {} -%D {\externalfigure[mill] [factor=min,maxwidth=6cm,maxheight=6cm]} {} -%D \stopcombination -%D \stoplinecorrection - -\def\m_grph_scale_factor_set{\v!min,\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\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 - {\grph_scale_calculate_fact\p_factor - \settrue\c_grph_scale_scaling_done - \ifconditional\c_grph_scale_limit_factors - \ifdim\d_grph_scale_used_x_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\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 - \orelse\ifdim\d_grph_scale_used_y_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\d_grph_scale_v_size - \global\d_grph_scale_used_x_size\zeropoint - \global\d_grph_scale_used_y_size\d_grph_scale_v_size - \fi - \fi - \grph_scale_by_dimension} - -\def\grph_scale_by_scale - {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}% - \ifempty\m_grph_scale_temp \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 - % - \ifempty\p_maxwidth - \ifempty\p_maxheight - \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\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 - \ifempty\p_maxwidth \else - \ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax - \global\d_grph_scale_used_x_size\p_maxwidth - #2\relax - \fi - \fi - \ifempty\p_maxheight \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} - -\def\grph_scale_calculate_fact#1% - {\csname\??scalefact\ifcsname\??scalefact#1\endcsname#1\else\s!unknown\fi\endcsname} - -%setvalue{\??scalenorm\v!min }#1#2#3#4#5{\global#1#4} -\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} - -\setvalue{\??scalefact\v!min }{\global\settrue \c_grph_scale_swap_factor} -\setvalue{\??scalefact\s!unknown}{\global\setfalse\c_grph_scale_swap_factor} - -% \setvalue{\??scalenorm\v!min }#1#2#3#4#5% an ugly hack -% {\ifdim\d_grph_scale_used_x_size>\d_grph_scale_h_size -% \d_grph_scale_used_y_size\vsize -% \else -% \d_grph_scale_used_x_size\hsize -% \fi} - -\setvalue{\??scalenorm\v!min}#1#2#3#4#5% an ugly hack - {\d_grph_scale_used_x_size\hsize - \d_grph_scale_used_y_size\vsize} - -\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} - -\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 - {% no overflow - \edef#1{\luaexpr - {\number - \ifx#2\empty - \ifempty\p_scale \plusthousand \else - \ifnum \p_scale=\zerocount \plusthousand \else - \p_scale \fi\fi - \orelse\ifnum#2=\zerocount - \ifempty\p_scale \plusthousand \else - \ifnum \p_scale=\zerocount \plusthousand \else - \p_scale \fi\fi - \else - #2% - \fi - /1000}}} - -\def\grph_scale_apply_size - {\ifempty\p_maxheight - \d_grph_scale_outer_v_size\textheight - \ifinner - \d_grph_scale_outer_v_size \vsize % \textheight =\vsize - \scratchdimen\vsize % \scratchdimen=\textheight - \orelse\ifinsidefloat - \d_grph_scale_outer_v_size \vsize % \textheight =\vsize - \scratchdimen\vsize % \scratchdimen=\textheight - \orelse\ifinpagebody - \d_grph_scale_outer_v_size \vsize % \textheight =\vsize - \scratchdimen\vsize % \scratchdimen=\textheight - \orelse\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 - \else - \scratchdimen\p_maxheight - \d_grph_scale_outer_v_size\scratchdimen - \fi - \ifempty\p_height - \d_grph_scale_v_size\scratchdimen - \else - \d_grph_scale_v_size\p_height - \fi - \ifempty\p_width - \d_grph_scale_h_size\hsize - \else - \d_grph_scale_h_size\p_width - \fi} - -% \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 - {\ifempty\p_equalwidth \else - \scratchdimen\p_equalwidth\relax - \ifdim\d_grph_scale_wd<\scratchdimen - \setbox\nextbox\naturalhpack to \scratchdimen{\hss\box\nextbox\hss}% - \fi - \fi - \ifempty\p_equalheight \else - \scratchdimen\p_equalheight\relax - \ifdim\d_grph_scale_ht<\scratchdimen - \setbox\nextbox\naturalvpack to \scratchdimen{\vss\box\nextbox\vss}% - \fi - \fi} - -\permanent\protected\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} - -\permanent\protected\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 - \d_grph_scale_wd\wd\nextbox - \d_grph_scale_ht\ht\nextbox - \d_grph_scale_dp\dp\nextbox - \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 arbitrary content. We can -%D use \METAPOST\ to provide a non 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, 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} - -\permanent\tolerant\protected\def\clip[#1]% nb top->bottom left->right - {\bgroup - \ifparameter#1\or - \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\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\naturalhpack - {\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\naturalhpack - {\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\naturalhpack - {\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. - -\permanent\protected\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\naturalhpack - {\dostartmirroring - \hskip-\wd\nextbox - \box\nextbox - \dostopmirroring}% - \wd\nextbox\scratchdimen - \box\nextbox - \egroup} - -%D A couple of examples, demonstrating how the depth is 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 -%D -%D When we rotate over arbitrary angles, we need to relocate the resulting box -%D because rotation brings that box onto the negative axis. The calculations (mostly -%D sin and cosine) need to be tuned for the way a box is packages (i.e. the refence -%D point). A typical example of drawing, scribbling, and going back to the days of -%D school math. -%D -%D We do a bit more calculations than needed, simply because that way it's easier to -%D debug the code. - -\installcorenamespace {rotate} -\installcorenamespace {rotatelocation} -\installcorenamespace {rotatepreset} - -% todo: scratchcounters - -\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 - -\newdimen\d_grph_rotate_width -\newdimen\d_grph_rotate_height -\newdimen\d_grph_rotate_depth - -\newdimen\d_grph_rotate_saved_width -\newdimen\d_grph_rotate_saved_height -\newdimen\d_grph_rotate_saved_depth - -\newdimen\d_grph_rotate_new_width -\newdimen\d_grph_rotate_new_height -\newdimen\d_grph_rotate_new_depth - -\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 - -\permanent\tolerant\protected\def\rotate[#1]% \bgroup: \rotate kan argument zijn - {\bgroup - \ifparameter#1\or - \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} - -\protected\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 - {\naturalhpack\bgroup - \ifempty\p_rotation_rotation - \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{90}} - -\setvalue{\??rotatepreset\v!right}% - {\edef\p_rotation_rotation{270}} - -\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}% - {} - -\def\grph_rotate_finish_yes - {\begincsname\??rotatepreset\p_rotation_rotation\endcsname - \setbox\nextbox\naturalvpack{\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\naturalhpack{\hskip-.5\wd\nextbox\lower.5\ht\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\naturalvpack{\naturalhpack{\raise\dp\nextbox\box\nextbox}}% can we do without - % - \d_grph_rotate_used_height\ht\nextbox - % - \clf_analyzerotate % rather accurate - \p_rotation_rotation\space - \d_grph_rotate_width - \d_grph_rotate_height - \d_grph_rotate_depth - \d_grph_rotate_used_height - \c_grph_rotate_not_fit - \c_grph_rotate_obey_depth - \relax - % - \setbox\nextbox\naturalvpack to \d_grph_rotate_y_size - {\vfilll - \naturalhpack 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\naturalhpack - {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax - \lower\d_grph_rotate_y_offset - \box\nextbox}% - % - \ifconditional\c_grph_rotate_center - \setbox\nextbox\naturalhpack{\hskip.5\d_grph_rotate_saved_width\lower-.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 - \else - \wd\nextbox\d_grph_rotate_new_width - \ht\nextbox\d_grph_rotate_new_height - \dp\nextbox\d_grph_rotate_new_depth - \fi - % - \boxcursor\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} - -% \def\Test{\ruledhbox{% -% \def\DemoX{\vl\kern.5\emwidth\vl}% -% \kern\emwidth\ruledhpack{\green\rotate[rotation=20] {\ruledhpack{\DemoX}}}% -% \kern\emwidth\ruledhpack{\blue \rotate[rotation=0] {\ruledhpack{\DemoX}}}% -% \kern\emwidth\ruledhpack{\red \rotate[rotation=-20] {\ruledhpack{\DemoX}}}% -% \kern\emwidth\ruledhpack{\green\rotate[rotation=200] {\ruledhpack{\DemoX}}}% -% \kern\emwidth\ruledhpack{\blue \rotate[rotation=180] {\ruledhpack{\DemoX}}}% -% \kern\emwidth\ruledhpack{\red \rotate[rotation=-200]{\ruledhpack{\DemoX}}}% -% \kern\emwidth}} - -% \startTEXpage[offset=10pt,align=middle] -% \setuprotate[location=fit] \Test \par {\infofont\setstrut\strut fit} \par -% \setuprotate[location=depth] \Test \par {\infofont\setstrut\strut depth} \par -% \setuprotate[location=broad] \Test \par {\infofont\setstrut\strut broad} \par -% \setuprotate[location=high] \Test \par {\infofont\setstrut\strut high} \par -% \setuprotate[location=middle] \Test \par {\infofont\setstrut\strut middle} \par -% \setuprotate[location=default] \Test \par {\infofont\setstrut\strut default} \par -% \stopTEXpage - -\protect \endinput diff --git a/tex/context/base/mkiv/hand-ini.mkxl b/tex/context/base/mkiv/hand-ini.mkxl deleted file mode 100644 index 3fd82f239..000000000 --- a/tex/context/base/mkiv/hand-ini.mkxl +++ /dev/null @@ -1,113 +0,0 @@ -%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 Probbaly not yet used by many. - -\permanent\tolerant\protected\def\setupfontexpansion [#1]#*[#2]{\clf_setupfontexpansion {#1}{#2}} -\permanent\tolerant\protected\def\setupfontprotrusion[#1]#*[#2]{\clf_setupfontprotrusion{#1}{#2}} - -% \setupfontprotrusion[quality-upright][vector=quality] -% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5] - -\pushoverloadmode - - \let\adjustspacing\relax \newcount\adjustspacing % a little bit protection - \let\protrudechars\relax \newcount\protrudechars % a little bit protection - -\popoverloadmode - -%D At some point we can introduce extreme expansion, i.e. \type {\normaladjustspacing\plustwo}. - -% 0 = disabled -% 1 = notused (thesis) -% 2 = glyph + kern -% 3 = glyph only (default) - -\def\font_expansion_enable {\normaladjustspacing\plusthree} -\def\font_expansion_enable_k{\normaladjustspacing\plustwo} -%def\font_expansion_enable_n{\normaladjustspacing\plusone} -\def\font_expansion_disable {\normaladjustspacing\zerocount} - -\def\font_protruding_enable_b{\normalprotrudechars\plusthree} % also deal with r2l (experimental lmtx) -\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 -% -% \protected\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen -% \protected\def\definefonthandling {\dotripleempty\dodefinefonthandling} -% \protected\def\setupfonthandling {\dodoubleempty\dosetupfonthandling } -% \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror} -% \def\dosetupfonthandling [#1][#2]{\fonthandlingerror} -% \def\usehandling [#1]{\fonthandlingerror} - -\installcorenamespace{expansion} - -\installcommandhandler \??expansion {expansion} \??expansion - -\appendtoks - \setuevalue{\??expansion:\currentexpansion}% - {\adjustspacingstep \expansionparameter\c!step\relax - \adjustspacingstretch\expansionparameter\c!stretch\relax - \adjustspacingshrink \expansionparameter\c!shrink\relax}% -\to \everydefineexpansion - -\setupexpansion - [\c!step=1, - \c!stretch=40, - \c!shrink=20] - -% \defineexpansion -% [myexpansion] -% [\c!stretch=50, -% \c!shrink=20] - -\permanent\tolerant\protected\def\setexpansion[#1]{\begincsname\??expansion:#1\endcsname} - -%D New in \LMTX: can be used grouped. - -\permanent\protected\def\noexpansion {\bitwiseflip\glyphoptions\noexpansioncode} -\permanent\protected\def\noprotrusion{\bitwiseflip\glyphoptions\noprotrusioncode} - -\protect \endinput diff --git a/tex/context/base/mkiv/java-ini.mkxl b/tex/context/base/mkiv/java-ini.mkxl deleted file mode 100644 index 513dc20e3..000000000 --- a/tex/context/base/mkiv/java-ini.mkxl +++ /dev/null @@ -1,157 +0,0 @@ -%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}{} - -\unprotect - -%D \macros -%D {JS*} -%D -%D Because \JAVASCRIPT's are activated by the user, for instance by activating on a -%D button, their support is closely related to the referencing mechanism. -%D Integration takes 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, the keyword is -%D treated as a normal reference. 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 always loaded, the -%D next definition also tells \CONTEXT\ to actually include the preamble needed. -%D -%D \starttyping -%D \startJScode{uses} used {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 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 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 the first page is -%D shipped out. -%D -%D \macros -%D {setJSpreamble, addtoJSpreamble} -%D -%D In addition to the previous preamble definitions, we can set a preamble \quote -%D {in||line} and add tokens to a preamble. -%D -%D \macros -%D {useJSpreamblenow} -%D -%D This macro can be used to force inclusion of postponed \JAVASCRIPT\ preambles. - -\def\m_java_escape_u{\letterbackslash u} - -\permanent\protected\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}}} - -\aliased\let\stopJScode\relax - -\permanent\protected\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}}} - -\aliased\let\stopJSpreamble\relax - -\permanent\protected\def\setJSpreamble #1#2{\clf_setjavascriptpreamble {#1}{#2}} -\permanent\protected\def\addtoJSpreamble#1#2{\clf_addtojavascriptpreamble{#1}{#2}} - -%D \macros -%D {useJSscripts} -%D -%D In due time, users will build their collections of scripts, which can be used -%D (loaded) when applicable. Although not all public, we will provide some general -%D purpose scripts, 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: - -\permanent\tolerant\protected\def\useJSscripts[#1]#*[#2]% - {\clf_usejavascriptscripts {#1}% two steps as this one calls tex code - \clf_usejavascriptpreamble{#2}}% so this one comes later - -\permanent\tolerant\protected\def\useJSpreamble[#1]% - {\clf_usejavascriptpreamble{#1}}% so this one comes later - -%D Here: - -\definefilesynonym[java-imp-fld.mkiv] [java-imp-fields.mkiv] -\definefilesynonym[java-imp-stp.mkiv] [java-imp-steps.mkiv] -\definefilesynonym[java-imp-fil.mkiv] [java-imp-print.mkiv] -\definefilesynonym[java-imp-rhh.mkiv] [java-imp-highlight.mkiv] -\definefilesynonym[java-imp-exa.mkiv] [java-imp-example.mkiv] - -\protect \endinput diff --git a/tex/context/base/mkiv/lang-dis.lmt b/tex/context/base/mkiv/lang-dis.lmt deleted file mode 100644 index 263225691..000000000 --- a/tex/context/base/mkiv/lang-dis.lmt +++ /dev/null @@ -1,222 +0,0 @@ -if not modules then modules = { } end modules ['lang-dis'] = { - version = 1.001, - comment = "companion to lang-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local concat = table.concat - -local tex = tex -local nodes = nodes - -local tasks = nodes.tasks -local nuts = nodes.nuts - -local enableaction = tasks.enableaction -local setaction = tasks.setaction - -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local getsubtype = nuts.getsubtype -local setsubtype = nuts.setsubtype -local getchar = nuts.getchar -local setchar = nuts.setchar -local getdisc = nuts.getdisc -local setdisc = nuts.setdisc -local getlanguage = nuts.getlanguage -local getboth = nuts.getboth -local setlist = nuts.setlist -local setlink = nuts.setlink -local isglyph = nuts.isglyph - -local copy_node = nuts.copy -local remove_node = nuts.remove -local flush_list = nuts.flush_list -local flush_node = nuts.flush_node - -local nextdisc = nuts.traversers.disc - -local new_disc = nuts.pool.disc - -local nodecodes = nodes.nodecodes -local disccodes = nodes.disccodes - -local disc_code = nodecodes.disc -local glyph_code = nodecodes.glyph - -local explicitdisc_code = disccodes.explicit - -local a_visualize = attributes.private("visualizediscretionary") -local setattribute = tex.setattribute - -local getlanguagedata = languages.getdata -local prehyphenchar = language.prehyphenchar -local posthyphenchar = language.posthyphenchar - -local check_regular = true - -local setlistcolor = nodes.tracers.colors.setlist - -function languages.visualizediscretionaries(head) - for d in nextdisc, head do - if getattr(d,a_visualize) then - local pre, post, replace = getdisc(d) - if pre then - setlistcolor(pre,"darkred") - end - if post then - setlistcolor(post,"darkgreen") - end - if replace then - setlistcolor(replace,"darkblue") - end - end - end - return head -end - -local enabled = false - -function languages.showdiscretionaries(v) - if v == false then - setattribute(a_visualize,unsetvalue) - else -- also nil - if not enabled then - enableaction("processors","languages.visualizediscretionaries") - enabled = true - end - setattribute(a_visualize,1) - end -end - -interfaces.implement { - name = "showdiscretionaries", - actions = languages.showdiscretionaries -} - -do - - local toutf = nodes.listtoutf - local utfchar = utf.char - local f_disc = string.formatters["{%s}{%s}{%s}"] - local replace = lpeg.replacer( { - [utfchar(0x200C)] = "|", - [utfchar(0x200D)] = "|", - }, nil, true) - - local function convert(list) - return list and replace(toutf(list)) or "" - end - - function languages.serializediscretionary(d) -- will move to tracer - local pre, post, replace = getdisc(d) - return f_disc(convert(pre),convert(post),convert(replace)) - end - -end - --- -- - -local wiped = 0 - -local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes - --- if flatten_discretionaries then - - function languages.flatten(head) - local h, n = flatten_discretionaries(head) - wiped = wiped + n - return h, n > 0 - end - --- else --- --- local function wipe(head,delayed) --- local p, n = getboth(delayed) --- local _, _, h, _, _, t = getdisc(delayed,true) --- if p or n then --- if h then --- setlink(p,h) --- setlink(t,n) --- setfield(delayed,"replace") --- else --- setlink(p,n) --- end --- end --- if head == delayed then --- head = h --- end --- wiped = wiped + 1 --- flush_node(delayed) --- return head --- end --- --- function languages.flatten(head) --- local delayed = nil --- for d in nextdisc, head do --- if delayed then --- head = wipe(head,delayed) --- end --- delayed = d --- end --- if delayed then --- return wipe(head,delayed), true --- else --- return head, false --- end --- end --- --- end - -function languages.nofflattened() - return wiped -- handy for testing -end - --- experiment: for now not in not in export mode! - -local flatten = languages.flatten - -nodes.handlers.flattenline = flatten - -function nodes.handlers.flatten(head,where) - if head and (where == "box" or where == "adjusted_hbox") then - return flatten(head) - end - return head -end - -directives.register("hyphenator.flatten",function(v) - -- use with care - setaction("processors","nodes.handlers.flatten",v) - setaction("contributers","nodes.handlers.flattenline",v) -end) - --- moved here: - -function languages.explicithyphen(template) - local pre, post - local disc = new_disc() - if template then - local langdata = getlanguagedata(getlanguage(template)) - local instance = langdata and langdata.instance - if instance then - local prechr = prehyphenchar(instance) - local postchr = posthyphenchar(instance) - if prechr >= 0 then - pre = copy_node(template) - setchar(pre,prechr) - end - if postchr >= 0 then - post = copy_node(template) - setchar(post,postchr) - end - end - end - setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty) - return disc -end diff --git a/tex/context/base/mkiv/lang-hyp.lmt b/tex/context/base/mkiv/lang-hyp.lmt deleted file mode 100644 index c2862f536..000000000 --- a/tex/context/base/mkiv/lang-hyp.lmt +++ /dev/null @@ -1,1806 +0,0 @@ -if not modules then modules = { } end modules ['lang-hyp'] = { - version = 1.001, - comment = "companion to lang-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- In an automated workflow hypenation of long titles can be somewhat problematic --- especially when demands conflict. For that reason I played a bit with a Lua based --- variant of the traditional hyphenation machinery. This mechanism has been extended --- several times in projects, of which a good description can be found in TUGboat, --- Volume 27 (2006), No. 2 — Proceedings of EuroTEX2006: Automatic non-standard --- hyphenation in OpenOffice.org by László Németh. --- --- Being the result of two days experimenting the following implementation is probably --- not completely okay yet. If there is demand I might add some more features and plugs. --- The performance is quite okay but can probably improved a bit, although this is not --- the most critital code. For instance, on a metafun manual run the overhead is about --- 0.3 seconds on 19 seconds which is not that bad. --- --- In the procecess of wrapping up (for the ctx conference proceedings) I cleaned up --- and extended the code a bit. It can be used in production. --- --- . a l g o r i t h m . --- 4l1g4 --- l g o3 --- 1g o --- 2i t h --- 4h1m --- --------------------- --- 4 1 4 3 2 0 4 1 --- a l-g o-r i t h-m - --- . a s s z o n n y a l . --- s1s z/sz=sz,1,3 --- n1n y/ny=ny,1,3 --- ----------------------- --- 0 1 0 0 0 1 0 0 0/sz=sz,2,3,ny=ny,6,3 --- a s-s z o n-n y a l/sz=sz,2,3,ny=ny,6,3 --- --- ab1cd/ef=gh,2,2 : acd - efd (pattern/replacement,start,length --- --- todo : support hjcodes (<32 == length) like luatex does now (no need/demand so far) --- maybe : support hyphenation over range (can alsready be done using attributes/language) --- maybe : reset dictionary.hyphenated when a pattern is added and/or forced reset option --- todo : check subtypes (because they have subtle meanings in the line breaking) --- --- word start (in tex engine): --- --- boundary : yes when wordboundary --- hlist : when hyphenationbounds 1 or 3 --- vlist : when hyphenationbounds 1 or 3 --- rule : when hyphenationbounds 1 or 3 --- dir : when hyphenationbounds 1 or 3 --- whatsit : when hyphenationbounds 1 or 3 --- glue : yes --- math : skipped --- glyph : exhyphenchar (one only) : yes (so no -- ---) --- otherwise : yes --- --- word end (in tex engine): --- --- boundary : yes --- glyph : yes when different language --- glue : yes --- penalty : yes --- kern : yes when not italic (for some historic reason) --- hlist : when hyphenationbounds 2 or 3 --- vlist : when hyphenationbounds 2 or 3 --- rule : when hyphenationbounds 2 or 3 --- dir : when hyphenationbounds 2 or 3 --- whatsit : when hyphenationbounds 2 or 3 --- ins : when hyphenationbounds 2 or 3 --- adjust : when hyphenationbounds 2 or 3 - -local type, rawget, rawset, tonumber, next = type, rawget, rawset, tonumber, next - -local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs -local lpegmatch = lpeg.match - -local context = context - -local concat = table.concat -local insert = table.insert -local remove = table.remove -local formatters = string.formatters -local utfchar = utf.char -local utfbyte = utf.byte - -if not characters then - require("char-ini") -end - -local setmetatableindex = table.setmetatableindex - --- \enabletrackers[hyphenator.steps=silent] will not write to the terminal - -local trace_steps = false trackers.register("hyphenator.steps", function(v) trace_steps = v end) -local trace_visualize = false trackers.register("hyphenator.visualize",function(v) trace_visualize = v end) - -local report = logs.reporter("hyphenator") - -local implement = interfaces and interfaces.implement or function() end - -languages = languages or { } -local hyphenators = languages.hyphenators or { } -languages.hyphenators = hyphenators -local traditional = hyphenators.traditional or { } -hyphenators.traditional = traditional - -local dictionaries = setmetatableindex(function(t,k) - local v = { - patterns = { }, - hyphenated = { }, - specials = { }, - exceptions = { }, - loaded = false, - } - t[k] = v - return v -end) - -hyphenators.dictionaries = dictionaries - -local character = lpeg.patterns.utf8character -local digit = R("09") -local weight = digit/tonumber + Cc(0) -local fence = P(".") -local hyphen = P("-") -local space = P(" ") -local char = character - space -local validcharacter = (character - S("./")) -local keycharacter = character - S("/") ------ basepart = Ct( (Cc(0) * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc(0))^-1) -local specpart = (P("/") * Cf ( Ct("") * - Cg ( Cc("before") * C((1-P("="))^1) * P("=") ) * - Cg ( Cc("after") * C((1-P(","))^1) ) * - ( P(",") * - Cg ( Cc("start") * ((1-P(","))^1/tonumber) * P(",") ) * - Cg ( Cc("length") * ((1-P(-1) )^1/tonumber) ) - )^-1 - , rawset))^-1 - -local make_hashkey_p = Cs((digit/"" + keycharacter)^1) ------ make_pattern_p = basepart * specpart -local make_hashkey_e = Cs((hyphen/"" + keycharacter)^1) -local make_pattern_e = Ct(P(char) * (hyphen * Cc(true) * P(char) + P(char) * Cc(false))^1) -- catch . and char after - - --- local make_hashkey_c = Cs((digit + keycharacter/"")^1) --- local make_pattern_c = Ct((P(1)/tonumber)^1) - --- local cache = setmetatableindex(function(t,k) --- local n = lpegmatch(make_hashkey_c,k) --- local v = lpegmatch(make_pattern_c,n) --- t[k] = v --- return v --- end) --- --- local weight_n = digit + Cc("0") --- local basepart_n = Cs( (Cc("0") * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc("0"))^-1) / cache --- local make_pattern_n = basepart_n * specpart - -local make_pattern_c = Ct((P(1)/tonumber)^1) - --- us + nl: 17664 entries -> 827 unique (saves some 3M) - -local cache = setmetatableindex(function(t,k) - local v = lpegmatch(make_pattern_c,k) - t[k] = v - return v -end) - -local weight_n = digit + Cc("0") -local fence_n = fence / "0" -local char_n = validcharacter / "" -local basepart_n = Cs(fence_n^-1 * (weight_n * char_n)^1 * weight_n * fence_n^-1) / cache -local make_pattern_n = basepart_n * specpart - -local function register_pattern(patterns,specials,str,specification) - local k = lpegmatch(make_hashkey_p,str) - -- local v1, v2 = lpegmatch(make_pattern_p,str) - local v1, v2 = lpegmatch(make_pattern_n,str) - patterns[k] = v1 -- is this key still ok for complex patterns - if specification then - specials[k] = specification - elseif v2 then - specials[k] = v2 - end -end - -local function unregister_pattern(patterns,specials,str) - local k = lpegmatch(make_hashkey_p,str) - patterns[k] = nil - specials[k] = nil -end - -local p_lower = lpeg.patterns.utf8lower - -local function register_exception(exceptions,str,specification) - local l = lpegmatch(p_lower,str) - local k = lpegmatch(make_hashkey_e,l) - local v = lpegmatch(make_pattern_e,l) - exceptions[k] = v -end - -local p_pattern = ((Carg(1) * Carg(2) * C(char^1)) / register_pattern + 1)^1 -local p_exception = ((Carg(1) * C(char^1)) / register_exception + 1)^1 -local p_split = Ct(C(character)^1) - -function traditional.loadpatterns(language,filename) - local dictionary = dictionaries[language] - if not dictionary.loaded then - if not filename or filename == "" then - filename = "lang-" .. language - end - filename = file.addsuffix(filename,"lua") - local fullname = resolvers.findfile(filename) - if fullname and fullname ~= "" then - local specification = dofile(fullname) - if specification then - local patterns = specification.patterns - if patterns then - local data = patterns.data - if data and data ~= "" then - lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) - end - end - local exceptions = specification.exceptions - if exceptions then - local data = exceptions.data - if data and data ~= "" then - lpegmatch(p_exception,data,1,dictionary.exceptions) - end - end - end - end - dictionary.loaded = true - end - return dictionary -end - -local lcchars = characters.lcchars -local uccodes = characters.uccodes -local categories = characters.categories -local nofwords = 0 -local nofhashed = 0 - -local steps = nil -local f_show = formatters["%w%s"] - -local function show_log() - if trace_steps == true then - report() - local w = #steps[1][1] - for i=1,#steps do - local s = steps[i] - report("%s%w%S %S",s[1],w - #s[1] + 3,s[2],s[3] or "") - end - report() - end -end - -local function show_1(wsplit) - local u = concat(wsplit," ") - steps = { { f_show(0,u), f_show(0,u) } } -end - -local function show_2(c,m,wsplit,done,i,spec) - local s = lpegmatch(p_split,c) - local t = { } - local n = #m - local w = #wsplit - for j=1,n do - t[#t+1] = m[j] - t[#t+1] = s[j] - end - local m = 2*i-2 - local l = #t - local s = spec and table.sequenced(spec) or "" - if m == 0 then - steps[#steps+1] = { f_show(m, concat(t,"",2)), f_show(1,concat(done," ",2,#done),s) } - elseif i+1 == w then - steps[#steps+1] = { f_show(m-1,concat(t,"",1,#t-1)), f_show(1,concat(done," ",2,#done),s) } - else - steps[#steps+1] = { f_show(m-1,concat(t)), f_show(1,concat(done," ",2,#done),s) } - end -end - -local function show_3(wsplit,done) - local t = { } - local h = { } - local n = #wsplit - for i=1,n do - local w = wsplit[i] - if i > 1 then - local d = done[i] - t[#t+1] = i > 2 and d % 2 == 1 and "-" or " " - h[#h+1] = d - end - t[#t+1] = w - h[#h+1] = w - end - steps[#steps+1] = { f_show(0,concat(h)), f_show(0,concat(t)) } - show_log() -end - -local function show_4(wsplit,done) - steps = { { concat(wsplit," ") } } - show_log() -end - -function traditional.lasttrace() - return steps -end - --- We could reuse the w table but as we cache the resolved words there is not much gain in --- that complication. --- --- Beware: word can be a table and when n is passed to we can assume reuse so we need to --- honor that n then. --- --- todo: a fast variant for tex ... less lookups (we could check is dictionary has changed) --- ... although due to caching the already done words, we don't do much here - -local function hyphenate(dictionary,word,n) -- odd is okay - nofwords = nofwords + 1 - local hyphenated = dictionary.hyphenated - local isstring = type(word) == "string" - if isstring then - local done = hyphenated[word] - if done ~= nil then - return done - end - elseif n then - local done = hyphenated[concat(word,"",1,n)] - if done ~= nil then - return done - end - else - local done = hyphenated[concat(word)] - if done ~= nil then - return done - end - end - local key - if isstring then - key = word - word = lpegmatch(p_split,word) - if not n then - n = #word - end - else - if not n then - n = #word - end - key = concat(word,"",1,n) - end - local l = 1 - local w = { "." } - -- local d = dictionary.codehash - for i=1,n do - local c = word[i] - -- l = l + (d[c] or 1) - l = l + 1 - w[l] = lcchars[c] or c - end - l = l + 1 - w[l] = "." - local c = concat(w,"",2,l-1) - -- - local done = hyphenated[c] - if done ~= nil then - hyphenated[key] = done - nofhashed = nofhashed + 1 - return done - end - -- - local exceptions = dictionary.exceptions - local exception = exceptions[c] - if exception then - if trace_steps then - show_4(w,exception) - end - hyphenated[key] = exception - nofhashed = nofhashed + 1 - return exception - end - -- - if trace_steps then - show_1(w) - end - -- - local specials = dictionary.specials - local patterns = dictionary.patterns - -- - local spec - for i=1,l do - for j=i,l do - local c = concat(w,"",i,j) - local m = patterns[c] - if m then - local s = specials[c] - if not done then - done = { } - spec = nil - -- the string that we resolve has explicit fences (.) so done starts at - -- the first fence and runs upto the last one so we need one slot less - for i=1,l do - done[i] = 0 - end - end - -- we run over the pattern that always has a (zero) value for each character - -- plus one more as we look at both sides - for k=1,#m do - local new = m[k] - if not new then - break - elseif new == true then - report("fatal error") - break - elseif new > 0 then - local pos = i + k - 1 - local old = done[pos] - if not old then - -- break ? - elseif new > old then - done[pos] = new - if s then - local b = i + (s.start or 1) - 1 - if b > 0 then - local e = b + (s.length or 2) - 1 - if e > 0 then - if pos >= b and pos <= e then - if spec then - spec[pos] = { s, k - 1 } - else - spec = { [pos] = { s, k - 1 } } - end - end - end - end - end - end - end - end - if trace_steps and done then - show_2(c,m,w,done,i,s) - end - end - end - end - if trace_steps and done then - show_3(w,done) - end - if done then - local okay = false - for i=3,#done do - if done[i] % 2 == 1 then - done[i-2] = spec and spec[i] or true - okay = true - else - done[i-2] = false - end - end - if okay then - done[#done] = nil - done[#done] = nil - else - done = false - end - else - done = false - end - hyphenated[key] = done - nofhashed = nofhashed + 1 - return done -end - -function traditional.gettrace(language,word) - if not word or word == "" then - return - end - local dictionary = dictionaries[language] - if dictionary then - local hyphenated = dictionary.hyphenated - hyphenated[word] = nil - hyphenate(dictionary,word) - return steps - end -end - -local methods = setmetatableindex(function(t,k) local v = hyphenate t[k] = v return v end) - -function traditional.installmethod(name,f) - if rawget(methods,name) then - report("overloading %a is not permitted",name) - else - methods[name] = f - end -end - -local s_detail_1 = "-" -local f_detail_2 = formatters["%s-%s"] -local f_detail_3 = formatters["{%s}{%s}{}"] -local f_detail_4 = formatters["{%s%s}{%s%s}{%s}"] - -function traditional.injecthyphens(dictionary,word,specification) - if not word then - return false - end - if not specification then - return word - end - local hyphens = hyphenate(dictionary,word) - if not hyphens then - return word - end - - -- the following code is similar to code later on but here we have strings while there - -- we have hyphen specs - - local word = lpegmatch(p_split,word) - local size = #word - - local leftmin = specification.leftcharmin or 2 - local rightmin = size - (specification.rightcharmin or leftmin) - local leftchar = specification.leftchar - local rightchar = specification.rightchar - - local result = { } - local rsize = 0 - local position = 1 - - while position <= size do - if position >= leftmin and position <= rightmin then - local hyphen = hyphens[position] - if not hyphen then - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - elseif hyphen == true then - rsize = rsize + 1 - result[rsize] = word[position] - rsize = rsize + 1 - if leftchar and rightchar then - result[rsize] = f_detail_3(rightchar,leftchar) - else - result[rsize] = s_detail_1 - end - position = position + 1 - else - local o, h = hyphen[2] - if o then - h = hyphen[1] - else - h = hyphen - o = 1 - end - local b = position - o + (h.start or 1) - local e = b + (h.length or 2) - 1 - if b > 0 and e >= b then - for i=1,b-position do - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - rsize = rsize + 1 - if leftchar and rightchar then - result[rsize] = f_detail_4(h.before,rightchar,leftchar,h.after,concat(word,"",b,e)) - else - result[rsize] = f_detail_2(h.before,h.after) - end - position = e + 1 - else - -- error - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - end - else - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - end - return concat(result) -end - -do - - local word = C((1-space)^1) - local spaces = space^1 - - local u_pattern = (Carg(1) * Carg(2) * word / unregister_pattern + spaces)^1 - local r_pattern = (Carg(1) * Carg(2) * word * Carg(3) / register_pattern + spaces)^1 - local e_pattern = (Carg(1) * word / register_exception + spaces)^1 - - function traditional.registerpattern(language,str,specification) - local dictionary = dictionaries[language] - if specification == false then - lpegmatch(u_pattern,str,1,dictionary.patterns,dictionary.specials) - -- unregister_pattern(dictionary.patterns,dictionary.specials,str) - else - lpegmatch(r_pattern,str,1,dictionary.patterns,dictionary.specials,type(specification) == "table" and specification or false) - -- register_pattern(dictionary.patterns,dictionary.specials,str,specification) - end - end - - function traditional.registerexception(language,str) - lpegmatch(e_pattern,str,1,dictionaries[language].exceptions) - end - -end - --- todo: unicodes or utfhash ? - -if context then - - local nodecodes = nodes.nodecodes - local disccodes = nodes.disccodes - - local glyph_code = nodecodes.glyph - local disc_code = nodecodes.disc - local math_code = nodecodes.math - local hlist_code = nodecodes.hlist - - local automaticdisc_code = disccodes.automatic - local regulardisc_code = disccodes.regular - - local nuts = nodes.nuts - local tonode = nodes.tonode - local nodepool = nuts.pool - - local new_disc = nodepool.disc - local new_penalty = nodepool.penalty - - local getfield = nuts.getfield - local getfont = nuts.getfont - local getid = nuts.getid - local getattr = nuts.getattr - local getnext = nuts.getnext - local getprev = nuts.getprev - local getsubtype = nuts.getsubtype - local getlist = nuts.getlist - local getlanguage = nuts.getlanguage - local getattrlist = nuts.getattrlist - local setattrlist = nuts.setattrlist - local isglyph = nuts.isglyph - local ischar = nuts.ischar - - local setchar = nuts.setchar - local setdisc = nuts.setdisc - local setlink = nuts.setlink - local setprev = nuts.setprev - local setnext = nuts.setnext - - local insert_before = nuts.insert_before - local insert_after = nuts.insert_after - local copy_node = nuts.copy - local copy_list = nuts.copy_list - local remove_node = nuts.remove - local end_of_math = nuts.end_of_math - local node_tail = nuts.tail - - local nexthlist = nuts.traversers.hlist - local nextdisc = nuts.traversers.disc - - local setcolor = nodes.tracers.colors.set - - local variables = interfaces.variables - local v_reset = variables.reset - local v_yes = variables.yes - local v_word = variables.word - local v_all = variables.all - - local settings_to_array = utilities.parsers.settings_to_array - - local unsetvalue = attributes.unsetvalue - local texsetattribute = tex.setattribute - - local prehyphenchar = language.prehyphenchar - local posthyphenchar = language.posthyphenchar - local preexhyphenchar = language.preexhyphenchar - local postexhyphenchar = language.postexhyphenchar - - local a_hyphenation = attributes.private("hyphenation") - - local interwordpenalty = 5000 - - function traditional.loadpatterns(language) - return dictionaries[language] - end - - -- for the moment we use an independent data structure - - setmetatableindex(dictionaries,function(t,k) - if type(k) == "string" then - -- this will force a load if not yet loaded (we need a nicer way) for the moment - -- that will do (nneeded for examples that register a pattern specification - languages.getnumber(k) - end - local specification = languages.getdata(k) - local dictionary = { - patterns = { }, - exceptions = { }, - hyphenated = { }, - specials = { }, - instance = false, - characters = { }, - unicodes = { }, - } - if specification then - local resources = specification.resources - if resources then - local characters = dictionary.characters or { } - local unicodes = dictionary.unicodes or { } - for i=1,#resources do - local r = resources[i] - if not r.in_dictionary then - r.in_dictionary = true - local patterns = r.patterns - if patterns then - local data = patterns.data - if data then - -- regular patterns - lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) - end - local extra = patterns.extra - if extra then - -- special patterns - lpegmatch(p_pattern,extra,1,dictionary.patterns,dictionary.specials) - end - end - local exceptions = r.exceptions - if exceptions then - local data = exceptions.data - if data and data ~= "" then - lpegmatch(p_exception,data,1,dictionary.exceptions) - end - end - local usedchars = lpegmatch(p_split,patterns.characters) - for i=1,#usedchars do - local char = usedchars[i] - local code = utfbyte(char) - local upper = uccodes[code] - characters[char] = code - unicodes [code] = char - if type(upper) == "table" then - for i=1,#upper do - local u = upper[i] - unicodes[u] = utfchar(u) - end - else - unicodes[upper] = utfchar(upper) - end - end - end - end - dictionary.characters = characters - dictionary.unicodes = unicodes - setmetatableindex(characters,function(t,k) local v = k and utfbyte(k) t[k] = v return v end) - end - t[specification.number] = dictionary - dictionary.instance = specification.instance -- needed for hyphenchars - end - t[k] = dictionary - return dictionary - end) - - -- Beware: left and right min doesn't mean that in a 1 mmm hsize there can be snippets - -- with less characters than either of them! This could be an option but such a narrow - -- hsize doesn't make sense anyway. - - -- We assume that featuresets are defined global ... local definitions (also mid paragraph) - -- make not much sense anyway. For the moment we assume no predefined sets so we don't need - -- to store them. Nor do we need to hash them in order to save space ... no sane user will - -- define many of them. - - local featuresets = hyphenators.featuresets or { } - hyphenators.featuresets = featuresets - - storage.shared.noflanguagesfeaturesets = storage.shared.noflanguagesfeaturesets or 0 - - local noffeaturesets = storage.shared.noflanguagesfeaturesets - - storage.register("languages/hyphenators/featuresets",featuresets,"languages.hyphenators.featuresets") - - ----- hash = table.sequenced(featureset,",") -- no need now - - local function register(name,featureset) - noffeaturesets = noffeaturesets + 1 - featureset.attribute = noffeaturesets - featuresets[noffeaturesets] = featureset -- access by attribute - featuresets[name] = featureset -- access by name - storage.shared.noflanguagesfeaturesets = noffeaturesets - return noffeaturesets - end - - local function makeset(...) - -- a bit overkill, supporting variants but who cares - local set = { } - for i=1,select("#",...) do - local list = select(i,...) - local kind = type(list) - local used = nil - if kind == "string" then - if list == v_all then - -- not ok ... now all get ignored - return setmetatableindex(function(t,k) local v = utfchar(k) t[k] = v return v end) - elseif list ~= "" then - used = lpegmatch(p_split,list) - set = set or { } - for i=1,#used do - local char = used[i] - set[utfbyte(char)] = char - end - end - elseif kind == "table" then - if next(list) then - set = set or { } - for byte, char in next, list do - set[byte] = char == true and utfchar(byte) or char - end - elseif #list > 0 then - set = set or { } - for i=1,#list do - local l = list[i] - if type(l) == "number" then - set[l] = utfchar(l) - else - set[utfbyte(l)] = l - end - end - end - end - end - return set - end - - -- category pd (tex also sees --- and -- as hyphens but do we really want that - - local defaulthyphens = { - [0x002D] = true, -- HYPHEN-MINUS - [0x00AD] = 0x002D, -- SOFT HYPHEN (active in ConTeXt) - -- [0x058A] = true, -- ARMENIAN HYPHEN - -- [0x1400] = true, -- CANADIAN SYLLABICS HYPHEN - -- [0x1806] = true, -- MONGOLIAN TODO SOFT HYPHEN - [0x2010] = true, -- HYPHEN - -- [0x2011] = true, -- NON-BREAKING HYPHEN - -- [0x2012] = true, -- FIGURE DASH - [0x2013] = true, -- EN DASH - [0x2014] = true, -- EM DASH - -- [0x2015] = true, -- HORIZONTAL BAR - -- [0x2027] = true, -- HYPHENATION POINT - -- [0x2E17] = true, -- DOUBLE OBLIQUE HYPHEN - -- [0x2E1A] = true, -- HYPHEN WITH DIAERESIS - -- [0x2E3A] = true, -- TWO-EM DASH - -- [0x2E3B] = true, -- THREE-EM DASH - -- [0x2E40] = true, -- DOUBLE HYPHEN - -- [0x301C] = true, -- WAVE DASH - -- [0x3030] = true, -- WAVY DASH - -- [0x30A0] = true, -- KATAKANA-HIRAGANA DOUBLE HYPHEN - -- [0xFE31] = true, -- PRESENTATION FORM FOR VERTICAL EM DASH - -- [0xFE32] = true, -- PRESENTATION FORM FOR VERTICAL EN DASH - -- [0xFE58] = true, -- SMALL EM DASH - -- [0xFE63] = true, -- SMALL HYPHEN-MINUS - -- [0xFF0D] = true, -- FULLWIDTH HYPHEN-MINUS - } - - local defaultjoiners = { - [0x200C] = true, -- nzwj - [0x200D] = true, -- zwj - } - - local function somehyphenchar(c) - c = tonumber(c) - return c ~= 0 and c or nil - end - - local function definefeatures(name,featureset) - local extrachars = featureset.characters -- "[]()" - local hyphenchars = featureset.hyphens - local joinerchars = featureset.joiners - local alternative = featureset.alternative - local rightwordmin = tonumber(featureset.rightwordmin) - local charmin = tonumber(featureset.charmin) -- luatex now also has hyphenationmin - local leftcharmin = tonumber(featureset.leftcharmin) - local rightcharmin = tonumber(featureset.rightcharmin) - local leftchar = somehyphenchar(featureset.leftchar) - local rightchar = somehyphenchar(featureset.rightchar) - local rightchars = featureset.rightchars -local rightedge = featureset.rightedge -local autohyphen = v_yes -- featureset.autohyphen -- insert disc -local hyphenonly = v_yes -- featureset.hyphenonly -- don't hyphenate around - rightchars = rightchars == v_word and true or tonumber(rightchars) - joinerchars = joinerchars == v_yes and defaultjoiners or joinerchars -- table - hyphenchars = hyphenchars == v_yes and defaulthyphens or hyphenchars -- table - -- not yet ok: extrachars have to be ignored so it cannot be all) - featureset.extrachars = makeset(joinerchars or "",extrachars or "") - featureset.hyphenchars = makeset(hyphenchars or "") - featureset.alternative = alternative or "hyphenate" - featureset.rightwordmin = rightwordmin and rightwordmin > 0 and rightwordmin or nil - featureset.charmin = charmin and charmin > 0 and charmin or nil - featureset.leftcharmin = leftcharmin and leftcharmin > 0 and leftcharmin or nil - featureset.rightcharmin = rightcharmin and rightcharmin > 0 and rightcharmin or nil - featureset.rightchars = rightchars - featureset.leftchar = leftchar - featureset.rightchar = rightchar - -- featureset.strict = rightedge == "tex" -featureset.autohyphen = autohyphen == v_yes -featureset.hyphenonly = hyphenonly == v_yes - return register(name,featureset) - end - - local function setfeatures(n) - if not n or n == v_reset then - n = false - else - local f = featuresets[n] - if not f and type(n) == "string" then - local t = settings_to_array(n) - local s = { } - for i=1,#t do - local ti = t[i] - local fs = featuresets[ti] - if fs then - for k, v in next, fs do - s[k] = v - end - end - end - n = register(n,s) - else - n = f and f.attribute - end - end - texsetattribute(a_hyphenation,n or unsetvalue) - end - - traditional.definefeatures = definefeatures - traditional.setfeatures = setfeatures - - implement { - name = "definehyphenationfeatures", - actions = definefeatures, - arguments = { - "string", - { - { "characters" }, - { "hyphens" }, - { "joiners" }, - { "rightchars" }, - { "rightwordmin", "integer" }, - { "charmin", "integer" }, - { "leftcharmin", "integer" }, - { "rightcharmin", "integer" }, - { "leftchar", "integer" }, - { "rightchar", "integer" }, - { "alternative" }, - { "rightedge" }, - } - } - } - - implement { - name = "sethyphenationfeatures", - actions = setfeatures, - arguments = "string" - } - - implement { - name = "registerhyphenationpattern", - actions = traditional.registerpattern, - arguments = { "string", "string", "boolean" } - } - - implement { - name = "registerhyphenationexception", - actions = traditional.registerexception, - arguments = "2 strings", - } - - -- This is a relative large function with local variables and local functions. A previous - -- implementation had the functions outside but this is cleaner and as efficient. The test - -- runs 100 times over tufte.tex, knuth.tex, zapf.tex, ward.tex and darwin.tex in lower - -- and uppercase with a 1mm hsize. - -- - -- language=0 language>0 4 | 3 * slower - -- - -- tex 2.34 | 1.30 2.55 | 1.45 0.21 | 0.15 - -- lua 2.42 | 1.38 3.30 | 1.84 0.88 | 0.46 - -- - -- Of course we have extra overhead (virtual Lua machine) but also we check attributes and - -- support specific local options). The test puts the typeset text in boxes and discards - -- it. If we also flush the runtime is 4.31|2.56 and 4.99|2.94 seconds so the relative - -- difference is (somehow) smaller. The test has 536 pages. There is a little bit of extra - -- overhead because we store the patterns in a different way. - -- - -- As usual I will look for speedups. Some 0.01 seconds could be gained by sharing patterns - -- which is not impressive but it does save some 3M memory on this test. (Some optimizations - -- already brought the 3.30 seconds down to 3.14 but it all depends on aggressive caching.) - - -- As we kick in the hyphenator before fonts get handled, we don't look at implicit (font) - -- kerns or ligatures. - - local starttiming = statistics.starttiming - local stoptiming = statistics.stoptiming - - -- local strictids = { - -- [nodecodes.hlist] = true, - -- [nodecodes.vlist] = true, - -- [nodecodes.rule] = true, - -- [nodecodes.dir] = true, - -- [nodecodes.whatsit] = true, - -- [nodecodes.ins] = true, - -- [nodecodes.adjust] = true, - -- - -- [nodecodes.math] = true, - -- [nodecodes.disc] = true, - -- - -- [nodecodes.accent] = true, -- never used in context - -- } - - -- a lot of overhead when only one char - - function traditional.hyphenate(head) - - local first = head - local tail = nil - local last = nil - local current = first - local dictionary = nil - local instance = nil - local characters = nil - local unicodes = nil - local exhyphenchar = tex.exhyphenchar - local extrachars = nil - local hyphenchars = nil - local language = nil - local lastfont = nil - local start = nil - local stop = nil - local word = { } -- we reuse this table - local size = 0 - local leftchar = false - local rightchar = false -- utfbyte("-") - local leftexchar = false - local rightexchar = false -- utfbyte("-") - local leftmin = 0 - local rightmin = 0 - local charmin = 1 - local leftcharmin = nil - local rightcharmin = nil - ----- leftwordmin = nil - local rightwordmin = nil - local rightchars = nil - local leftchar = nil - local rightchar = nil - local attr = nil - local lastwordlast = nil - local hyphenated = hyphenate - ----- strict = nil - local exhyphenpenalty = tex.exhyphenpenalty - local hyphenpenalty = tex.hyphenpenalty - local autohyphen = false - local hyphenonly = false - - -- We cannot use an 'enabled' boolean (false when no characters or extras) because we - -- can have plugins that set a characters metatable and so) ... it doesn't save much - -- anyway. Using (unicodes and unicodes[code]) and a nil table when no characters also - -- doesn't save much. So there not that much to gain for languages that don't hyphenate. - -- - -- enabled = (unicodes and (next(unicodes) or getmetatable(unicodes))) - -- or (extrachars and next(extrachars)) - -- - -- This can be used to not add characters i.e. keep size 0 but then we need to check for - -- attributes that change it, which costs time too. Not much to gain there. - - starttiming(traditional) - - local function insertpenalty() - local p = new_penalty(interwordpenalty) - setattrlist(p,last) - if trace_visualize then - nuts.setvisual(p,"penalty") - end - last = getprev(last) - first, last = insert_after(first,last,p) - end - - local function synchronizefeatureset(a) - local f = a and featuresets[a] - if f then - hyphenated = methods[f.alternative or "hyphenate"] - extrachars = f.extrachars - hyphenchars = f.hyphenchars - rightwordmin = f.rightwordmin - charmin = f.charmin - leftcharmin = f.leftcharmin - rightcharmin = f.rightcharmin - leftchar = f.leftchar - rightchar = f.rightchar - -- strict = f.strict and strictids - rightchars = f.rightchars - autohyphen = f.autohyphen - hyphenonly = f.hyphenonly - if rightwordmin and rightwordmin > 0 and lastwordlast ~= rightwordmin then - -- so we can change mid paragraph but it's kind of unpredictable then - if not tail then - tail = node_tail(first) - end - last = tail - local inword = false - local count = 0 - while last and rightwordmin > 0 do - local id = getid(last) - if id == glyph_code then - count = count + 1 - inword = true - if trace_visualize then - setcolor(last,"darkgreen") - end - elseif inword then - inword = false - rightwordmin = rightwordmin - 1 - if rightchars == true then - if rightwordmin > 0 then - insertpenalty() - end - elseif rightchars and count <= rightchars then - insertpenalty() - end - end - last = getprev(last) - end - lastwordlast = rightwordmin - end - if not charmin or charmin == 0 then - charmin = 1 - end - else - hyphenated = methods.hyphenate - extrachars = false - hyphenchars = false - rightwordmin = false - charmin = 1 - leftcharmin = false - rightcharmin = false - leftchar = false - rightchar = false - -- strict = false - autohyphen = false - hyphenonly = false - end - - return a - end - - local function flush(hyphens) -- todo: no need for result - - local rightmin = size - rightmin - local result = { } - local rsize = 0 - local position = 1 - - -- todo: remember last dics and don't go back to before that (plus message) ... - -- for simplicity we also assume that we don't start with a dics node - -- - -- there can be a conflict: if we backtrack then we can end up in another disc - -- and get out of sync (dup chars and so) - - while position <= size do - if position >= leftmin and position <= rightmin then - local hyphen = hyphens[position] - if not hyphen then - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - elseif hyphen == true then - rsize = rsize + 1 - result[rsize] = word[position] - rsize = rsize + 1 - result[rsize] = true - position = position + 1 - else - local o, h = hyphen[2] - if o then - -- { hyphen, offset) - h = hyphen[1] - else - -- hyphen - h = hyphen - o = 1 - end - local b = position - o + (h.start or 1) - local e = b + (h.length or 2) - 1 - if b > 0 and e >= b then - for i=1,b-position do - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - rsize = rsize + 1 - result[rsize] = { - h.before or "", -- pre - h.after or "", -- post - concat(word,"",b,e), -- replace - h.right, -- optional after pre - h.left, -- optional before post - } - position = e + 1 - else - -- error - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - end - else - rsize = rsize + 1 - result[rsize] = word[position] - position = position + 1 - end - end - - local function serialize(replacement,leftchar,rightchar) - if not replacement then - return - elseif replacement == true then - local glyph = copy_node(stop) - setchar(glyph,leftchar or rightchar) - return glyph - end - local head = nil - local current = nil - if leftchar then - head = copy_node(stop) - current = head - setchar(head,leftchar) - end - local rsize = #replacement - if rsize == 1 then - local glyph = copy_node(stop) - setchar(glyph,characters[replacement]) - if head then - insert_after(current,current,glyph) - else - head = glyph - end - current = glyph - elseif rsize > 0 then - local list = lpegmatch(p_split,replacement) -- this is an utf split (could be cached) - for i=1,#list do - local glyph = copy_node(stop) - setchar(glyph,characters[list[i]]) - if head then - insert_after(current,current,glyph) - else - head = glyph - end - current = glyph - end - end - if rightchar then - local glyph = copy_node(stop) - insert_after(current,current,glyph) - setchar(glyph,rightchar) - end - return head - end - - local current = start - local attrnode = start -- will be different, just the first char - - for i=1,rsize do - local r = result[i] - if r == true then - local disc = new_disc() - local pre = nil - local post = nil - if rightchar then - pre = serialize(true,rightchar) - end - if leftchar then - post = serialize(true,leftchar) - end - setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty) - if attrnode then - setattrlist(disc,attrnode) - end - -- could be a replace as well - insert_before(first,current,disc) - elseif type(r) == "table" then - local disc = new_disc() - local pre = r[1] - local post = r[2] - local replace = r[3] - local right = r[4] ~= false and rightchar - local left = r[5] ~= false and leftchar - if pre then - if pre ~= "" then - pre = serialize(pre,false,right) - else - pre = nil - end - end - if post then - if post ~= "" then - post = serialize(post,left,false) - else - post = nil - end - end - if replace then - if replace ~= "" then - replace = serialize(replace) - else - replace = nil - end - end - -- maybe regular code - setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty) - if attrnode then - setattrlist(disc,attrnode) - end - insert_before(first,current,disc) - else - setchar(current,characters[r]) - if i < rsize then - current = getnext(current) - end - end - end - if current and current ~= stop then - local current = getnext(current) - local last = getnext(stop) - while current ~= last do - first, current = remove_node(first,current,true) - end - end - - end - - local function inject(leftchar,rightchar,code,attrnode) - if first ~= current then - local disc = new_disc() - first, current, glyph = remove_node(first,current) - first, current = insert_before(first,current,disc) - if trace_visualize then - setcolor(glyph,"darkred") -- these get checked - setcolor(disc,"darkgreen") -- in the colorizer - end - local pre = nil - local post = nil - local replace = glyph - if leftchar and leftchar > 0 then - post = copy_node(glyph) - setchar(post,leftchar) - end - pre = copy_node(glyph) - setchar(pre,rightchar and rightchar > 0 and rightchar or code) - setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? - if attrnode then - setattrlist(disc,attrnode) - end - end - return current - end - - local function injectseries(current,last,next,attrnode) - local disc = new_disc() - local start = current - first, current = insert_before(first,current,disc) - setprev(start) - setnext(last) - if next then - setlink(current,next) - else - setnext(current) - end - local pre = copy_list(start) - local post = nil - local replace = start - setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? - if attrnode then - setattrlist(disc,attrnode) - end - return current - end - - local a = getattr(first,a_hyphenation) - if a ~= attr then - attr = synchronizefeatureset(a) - end - - -- The first attribute in a word determines the way a word gets hyphenated and if - -- relevant, other properties are also set then. We could optimize for silly one-char - -- cases but it has no priority as the code is still not that much slower than the - -- native hyphenator and this variant also provides room for extensions. - - local skipping = false - - -- In "word word word." the sequences "word" and "." can be a different font! - - while current and current ~= last do -- and current - local code, id = isglyph(current) - if code then - if skipping then - current = getnext(current) - else - local lang = getlanguage(current) - local font = getfont(current) - if lang ~= language or font ~= lastfont then - if dictionary and size > charmin and leftmin + rightmin <= size then - -- only german has many words starting with an uppercase character - if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then - -- skip - else - local hyphens = hyphenated(dictionary,word,size) - if hyphens then - flush(hyphens) - end - end - end - lastfont = font - if language ~= lang and lang > 0 then - -- - dictionary = dictionaries[lang] - instance = dictionary.instance - characters = dictionary.characters - unicodes = dictionary.unicodes - -- - local a = getattr(current,a_hyphenation) - attr = synchronizefeatureset(a) - leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more - rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed - leftexchar = (instance and preexhyphenchar (instance)) - rightexchar = (instance and postexhyphenchar(instance)) - leftmin = leftcharmin or getfield(current,"left") - rightmin = rightcharmin or getfield(current,"right") - if not leftchar or leftchar < 0 then - leftchar = false - end - if not rightchar or rightchar < 0 then - rightchar = false - end - -- - local char = unicodes[code] or (extrachars and extrachars[code]) - if char then - word[1] = char - size = 1 - start = current - else - size = 0 - end - else - size = 0 - end - language = lang - elseif language <= 0 then - -- - elseif size > 0 then - local char = unicodes[code] or (extrachars and extrachars[code]) - if char then - size = size + 1 - word[size] = char - elseif dictionary then - if not hyphenonly or code ~= exhyphenchar then - if size > charmin and leftmin + rightmin <= size then - if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then - -- skip - else - local hyphens = hyphenated(dictionary,word,size) - if hyphens then - flush(hyphens) - end - end - end - end - size = 0 - if code == exhyphenchar then -- normally the - - local next = getnext(current) - local last = current - local font = getfont(current) - while next and ischar(next,font) == code do - last = next - next = getnext(next) - end - if not autohyphen then - current = last - elseif current == last then - current = inject(leftexchar,rightexchar,code,current) - else - current = injectseries(current,last,next,current) - end - if hyphenonly then - skipping = true - end - elseif hyphenchars then - local char = hyphenchars[code] - if char == true then - char = code - end - if char then - current = inject(leftchar and char or nil,rightchar and char or nil,char,current) - end - end - end - else - local a = getattr(current,a_hyphenation) - if a ~= attr then - attr = synchronizefeatureset(a) -- influences extrachars - leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more - rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed - leftexchar = (instance and preexhyphenchar (instance)) - rightexchar = (instance and postexhyphenchar(instance)) - leftmin = leftcharmin or getfield(current,"left") - rightmin = rightcharmin or getfield(current,"right") - if not leftchar or leftchar < 0 then - leftchar = false - end - if not rightchar or rightchar < 0 then - rightchar = false - end - end - -- - local char = unicodes[code] or (extrachars and extrachars[code]) - if char then - word[1] = char - size = 1 - start = current - end - end - stop = current - current = getnext(current) - end - else - if skipping then - skipping = false - end - if id == disc_code then - size = 0 - current = getnext(current) - if hyphenonly then - skipping = true - end - -- elseif strict and strict[id] then - -- current = id == math_code and getnext(end_of_math(current)) or getnext(current) - -- size = 0 - else - current = id == math_code and getnext(end_of_math(current)) or getnext(current) - end - if size > 0 then - if dictionary and size > charmin and leftmin + rightmin <= size then - if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then - -- skip - else - local hyphens = hyphenated(dictionary,word,size) - if hyphens then - flush(hyphens) - end - end - end - size = 0 - end - end - end - -- we can have quit due to last so we need to flush the last seen word, we could move - -- this in the loop and test for current but ... messy - if dictionary and size > charmin and leftmin + rightmin <= size then - if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then - -- skip - else - local hyphens = hyphenated(dictionary,word,size) - if hyphens then - flush(hyphens) - end - end - end - - stoptiming(traditional) - - return head - end - - statistics.register("hyphenation",function() - if nofwords > 0 or statistics.elapsed(traditional) > 0 then - return string.format("%s words hyphenated, %s unique, used time %s", - nofwords,nofhashed,statistics.elapsedseconds(traditional) or 0) - end - end) - - local texmethod = "builders.kernel.hyphenation" - local oldmethod = texmethod - local newmethod = texmethod - - -- local newmethod = "languages.hyphenators.traditional.hyphenate" - -- - -- nodes.tasks.prependaction("processors","words",newmethod) - -- nodes.tasks.disableaction("processors",oldmethod) - -- - -- nodes.tasks.replaceaction("processors","words",oldmethod,newmethod) - - -- \enabledirectives[hyphenators.method=traditional] - -- \enabledirectives[hyphenators.method=builtin] - - -- push / pop ? check first attribute - - -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches) - - local hyphenate = language.hyphenate - local hyphenating = nuts.hyphenating - local methods = { } - local usedmethod = false - local stack = { } - - local original = hyphenating and - function(head) - return (hyphenating(head)) - end - or - function(head) - hyphenate(tonode(head)) - return head -- a nut - end - - -- local has_language = language.has_language - -- - -- local function original(head) -- kernel.hyphenation(head) - -- local h = tonode(head) - -- if has_language(h) then - -- hyphenate(h) - -- end - -- return head - -- end - - local getcount = tex.getcount - - hyphenators.methods = methods - local optimize = false - - directives.register("hyphenator.optimize", function(v) optimize = v end) - - function hyphenators.handler(head,groupcode) - if usedmethod then - if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then - if getcount("hyphenstate") > 0 then - forced = false - return usedmethod(head) - else - return head - end - else - return usedmethod(head) - end - else - return head - end - end - - methods.tex = original - methods.original = original - methods.expanded = original -- was expanded before 1.005 - methods.traditional = languages.hyphenators.traditional.hyphenate - methods.none = false -- function(head) return head, false end - - usedmethod = original - - local function setmethod(method) - usedmethod = type(method) == "string" and methods[method] - if usedmethod == nil then - usedmethod = methods.tex - end - end - local function pushmethod(method) - insert(stack,usedmethod) - usedmethod = type(method) == "string" and methods[method] - if usedmethod == nil then - usedmethod = methods.tex - end - end - local function popmethod() - usedmethod = remove(stack) or methods.tex - end - - hyphenators.setmethod = setmethod - hyphenators.pushmethod = pushmethod - hyphenators.popmethod = popmethod - - directives.register("hyphenators.method",setmethod) - - function hyphenators.setup(specification) - local method = specification.method - if method then - setmethod(method) - end - end - - implement { name = "sethyphenationmethod", actions = setmethod, arguments = "string" } - implement { name = "pushhyphenation", actions = pushmethod, arguments = "string" } - implement { name = "pophyphenation", actions = popmethod } - - -- can become a runtime loaded one: - - local context = context - local ctx_NC = context.NC - local ctx_NR = context.NR - local ctx_verbatim = context.verbatim - - function hyphenators.showhyphenationtrace(language,word) - if not word or word == "" then - return - end - local saved = trace_steps - trace_steps = "silent" - local steps = traditional.gettrace(language,word) - trace_steps = saved - if steps then - local n = #steps - if n > 0 then - context.starttabulate { "|r|l|l|l|" } - for i=1,n do - local s = steps[i] - ctx_NC() if i > 1 and i < n then context(i-1) end - ctx_NC() ctx_verbatim(s[1]) - ctx_NC() ctx_verbatim(s[2]) - ctx_NC() ctx_verbatim(s[3]) - ctx_NC() - ctx_NR() - end - context.stoptabulate() - end - end - end - - implement { - name = "showhyphenationtrace", - actions = hyphenators.showhyphenationtrace, - arguments = "2 strings", - } - - function nodes.stripdiscretionaries(head) - for l in nexthlist, head do - for d in nextdisc, getlist(l) do - remove_node(h,false,true) - end - end - return head - end - - -else - - -- traditional.loadpatterns("nl","lang-nl") - -- traditional.loadpatterns("de","lang-de") - -- traditional.loadpatterns("us","lang-us") - - -- traditional.registerpattern("nl","e1ë", { start = 1, length = 2, before = "e", after = "e" } ) - -- traditional.registerpattern("nl","oo7ë", { start = 2, length = 3, before = "o", after = "e" } ) - -- traditional.registerpattern("de","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } ) - - -- local specification = { - -- leftcharmin = 2, - -- rightcharmin = 2, - -- leftchar = "<", - -- rightchar = ">", - -- } - - -- print("reëel", traditional.injecthyphens(dictionaries.nl,"reëel", specification),"r{e>}{}{}{ 32 hyphenated with length 1 - -local function sethjcodes(instance,loaded,what,factor) - local l = loaded[what] - local c = l and l.characters - if c then - local hjcounts = factor and languages.hjcounts or false - -- - local h = loaded.codehash - if not h then - h = { } - loaded.codehash = h - end - -- - local function setcode(l) - local u = uccodes[l] - local s = l - if hjcounts then - local c = hjcounts[l] - if c then - c = c.count - if not c then - -- error, keep as 1 - elseif c <= 0 then - -- counts as 0 i.e. ignored - s = 32 - elseif c >= 31 then - -- counts as 31 - s = 31 - else - -- count c times - s = c - end - end - end - sethjcode(instance,l,s) - h[l] = s - if u ~= l and type(u) == "number" then - sethjcode(instance,u,s) - h[u] = lccodes[l] - end - end - -- - local s = tex.savinghyphcodes - tex.savinghyphcodes = 0 - if type(c) == "table" then - for l in next, c do - setcode(utfbyte(l)) - end - else - for l in utfvalues(c) do - setcode(l) - end - end - tex.savinghyphcodes = s - end -end - --- 2'2 conflicts with 4' ... and luatex barks on it - -local P, R, Cs, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.match, lpeg.patterns - -local utfsplit = utf.split - -local space = lpegpatterns.space -local whitespace = lpegpatterns.whitespace^1 -local nospace = lpegpatterns.utf8char - whitespace -local digit = lpegpatterns.digit ------ endofstring = #whitespace + P(-1) -local endofstring = #whitespace - -local word = (digit/"")^0 * (digit/"" * endofstring + digit/" " + nospace)^1 -local anyword = (1-whitespace)^1 -local analyze = Ct((whitespace + Cs(word))^1) - -local function unique(tag,requested,loaded) - local nofloaded = #loaded - if nofloaded == 0 then - return "" - elseif nofloaded == 1 then - return loaded[1] - else - insert(loaded,1," ") -- no need then for special first word - -- insert(loaded, " ") - loaded = concat(loaded," ") - local t = lpegmatch(analyze,loaded) or { } - local h = { } - local b = { } - for i=1,#t do - local ti = t[i] - local hi = h[ti] - if not hi then - h[ti] = 1 - elseif hi == 1 then - h[ti] = 2 - b[#b+1] = utfsplit(ti," ") - end - end - -- sort - local nofbad = #b - if nofbad > 0 then - local word - for i=1,nofbad do - local bi = b[i] - local p = P(bi[1]) - for i=2,#bi do - p = p * digit * P(bi[i]) - end - if word then - word = word + p - else - word = p - end - report_initialization("language %a, patterns %a, discarding conflict (0-9)%{[0-9]}t(0-9)",tag,requested,bi) - end - t, h, b = nil, nil, nil -- permit gc - local someword = digit^0 * word * digit^0 * endofstring / "" - -- local strip = Cs(someword^-1 * (someword + anyword + whitespace)^1) - local strip = Cs((someword + anyword + whitespace)^1) - return lpegmatch(strip,loaded) or loaded - else - return loaded - end - end -end - -local shared = false - -local function loaddefinitions(tag,specification) - statistics.starttiming(languages) - local data, instance = resolve(tag) - local requested = specification.patterns or "" - local definitions = settings_to_array(requested) - if #definitions > 0 then - if trace_patterns then - report_initialization("pattern specification for language %a: %s",tag,specification.patterns) - end - local ploaded = instance:patterns() - local eloaded = instance:hyphenation() - if not ploaded or ploaded == "" then - ploaded = { } - else - ploaded = { ploaded } - end - if not eloaded or eloaded == "" then - eloaded = { } - else - eloaded = { eloaded } - end - local dataused = data.used - local ok = false - local resources = data.resources or { } - data.resources = resources - if not shared then - local found = resolvers.findfile("lang-exc.lua") - if found then - shared = dofile(found) - if type(shared) == "table" then - shared = concat(shared," ") - else - shared = true - end - else - shared = true - end - end - for i=1,#definitions do - local definition = definitions[i] - if definition == "" then - -- error - elseif definition == v_reset then - if trace_patterns then - report_initialization("clearing patterns for language %a",tag) - end - instance:clear_patterns() - instance:clear_hyphenation() - ploaded = { } - eloaded = { } - elseif not dataused[definition] then - dataused[definition] = definition - local filename = "lang-" .. definition .. ".lua" - local fullname = resolvers.findfile(filename) or "" - if fullname == "" then - fullname = resolvers.findfile(filename .. ".gz") or "" - end - if fullname ~= "" then - if trace_patterns then - report_initialization("loading definition %a for language %a from %a",definition,tag,fullname) - end - local suffix, gzipped = gzip.suffix(fullname) - local loaded = table.load(fullname,gzipped and gzip.load) - if loaded then -- todo: version test - ok, nofloaded = true, nofloaded + 1 - sethjcodes(instance,loaded,"patterns",specification.factor) - sethjcodes(instance,loaded,"exceptions",specification.factor) - local p = validdata(loaded,"patterns",tag) - local e = validdata(loaded,"exceptions",tag) - if p and p ~= "" then - ploaded[#ploaded+1] = p - end - if e and e ~= "" then - eloaded[#eloaded+1] = e - end - resources[#resources+1] = loaded -- so we can use them otherwise - else - report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) - end - elseif trace_patterns then - report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) - end - elseif trace_patterns then - report_initialization("definition %a for language %a already loaded",definition,tag) - end - end - if #ploaded > 0 then - -- why not always clear - instance:clear_patterns() - instance:patterns(unique(tag,requested,ploaded)) - end - if #eloaded > 0 then - -- why not always clear - instance:clear_hyphenation() - instance:hyphenation(concat(eloaded," ")) - end - if type(shared) == "string" then - instance:hyphenation(shared) - end - return ok - elseif trace_patterns then - report_initialization("no definitions for language %a",tag) - end - statistics.stoptiming(languages) -end - -storage.shared.noflanguages = storage.shared.noflanguages or 0 - -local noflanguages = storage.shared.noflanguages - -function languages.define(tag,parent) - noflanguages = noflanguages + 1 - if trace_patterns then - report_initialization("assigning number %a to %a",noflanguages,tag) - end - numbers[noflanguages] = tag - registered[tag] = { - tag = tag, - parent = parent or "", - patterns = "", - loaded = false, - used = { }, - dirty = true, - number = noflanguages, - instance = nil, -- luatex data structure - synonyms = { }, - } - storage.shared.noflanguages = noflanguages -end - -function languages.setsynonym(synonym,tag) -- convenience function - local l = registered[tag] - if l then - l.synonyms[synonym] = true -- maybe some day more info - end -end - -function languages.installed(separator) - return concat(sortedkeys(registered),separator or ",") -end - -function languages.current(n) - return numbers[n and tonumber(n) or currentlanguage()] -end - -function languages.associate(tag,script,language) -- not yet used - associated[tag] = { script, language } -end - -function languages.association(tag) -- not yet used - if not tag then - tag = numbers[currentlanguage()] - elseif type(tag) == "number" then - tag = numbers[tag] - end - local lat = tag and associated[tag] - if lat then - return lat[1], lat[2] - end -end - -function languages.loadable(tag,defaultlanguage) -- hack - local l = registered[tag] -- no synonyms - if l and resolvers.findfile("lang-"..l.patterns..".lua") then - return true - else - return false - end -end - --- a bit messy, we will do all language setting in lua as we can now assign --- and 'patterns' will go away here. - -function languages.unload(tag) - local l = registered[tag] - if l then - l.dirty = true - end -end - -if environment.initex then - - function languages.getnumber() - return 0 - end - -else - - function languages.getnumber(tag,default,patterns,factor) - local l = registered[tag] - if l then - if l.dirty then - l.factor = factor == v_yes and true or false - if trace_patterns then - report_initialization("checking patterns for %a with default %a",tag,default) - end - -- patterns is already resolved to parent patterns if applicable - if patterns and patterns ~= "" then - if l.patterns ~= patterns then - l.patterns = patterns - if trace_patterns then - report_initialization("loading patterns for %a using specification %a",tag,patterns) - end - loaddefinitions(tag,l) - else - -- unchanged - end - elseif l.patterns == "" then - l.patterns = tag - if trace_patterns then - report_initialization("loading patterns for %a using tag",tag) - end - local ok = loaddefinitions(tag,l) - if not ok and tag ~= default then - l.patterns = default - if trace_patterns then - report_initialization("loading patterns for %a using default",tag) - end - loaddefinitions(tag,l) - end - end - l.loaded = true - l.dirty = false - end - return l.number - else - return 0 - end - end - - numbers[0] = "null" - - registered.null = { - number = 0, - instance = new_language(0), - } - -end - --- not that usefull, global values - -function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) end -function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end -function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end -function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end --------- languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end --------- languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end - --- e['implementer']= 'imple{m}{-}{-}menter' --- e['manual'] = 'man{}{}{}' --- e['as'] = 'a-s' --- e['user-friendly'] = 'user=friend-ly' --- e['exceptionally-friendly'] = 'excep-tionally=friend-ly' - -local invalid = { "{", "}", "-" } - -local function collecthjcodes(data,str) - local found = data.extras and data.extras.characters or { } - for s in utfcharacters(str) do - if not found[s] then - found[s] = true - end - end - for i=1,#invalid do -- less checks this way - local c = invalid[i] - if found[c] then - found[c] = nil - end - end - data.extras = { characters = found } - sethjcodes(data.instance,data,"extras",data.factor) -end - -function languages.loadwords(tag,filename) - local data, instance = resolve(tag) - if data then - statistics.starttiming(languages) - local str = io.loaddata(filename) or "" - collecthjcodes(data,str) - instance:hyphenation(str) - statistics.stoptiming(languages) - end -end - - -function languages.setexceptions(tag,str) - local data, instance = resolve(tag) - if data then - str = strip(str) -- we need to strip leading spaces - collecthjcodes(data,str) - instance:hyphenation(str) - end -end - -function languages.hyphenate(tag,str) - -- todo: does this still work? - local data, instance = resolve(tag) - if data then - return instance:hyphenate(str) - else - return str - end -end - --- hyphenation.define ("zerolanguage") --- hyphenation.loadpatterns ("zerolanguage") -- else bug --- hyphenation.loadexceptions("zerolanguage") -- else bug - -languages.logger = languages.logger or { } - -function languages.logger.report() - local result, r = { }, 0 - for tag, l in sortedpairs(registered) do - if l.loaded then - r = r + 1 - result[r] = format("%s:%s:%s",tag,l.parent,l.number) - end - end - return r > 0 and concat(result," ") or "none" -end - --- must happen at the tex end .. will use lang-def.lua - -languages.associate('en','latn','eng') -languages.associate('uk','latn','eng') -languages.associate('nl','latn','nld') -languages.associate('de','latn','deu') -languages.associate('fr','latn','fra') - -statistics.register("loaded patterns", function() - local result = languages.logger.report() - if result ~= "none" then - -- return result - return format("%s, load time: %s",result,statistics.elapsedtime(languages)) - end -end) - --- statistics.register("language load time", function() --- -- often zero so we can merge that in the above --- return statistics.elapsedseconds(languages, format(", nofpatterns: %s",nofloaded)) --- end) - --- interface - -implement { - name = "languagenumber", - actions = { languages.getnumber, context }, - arguments = "4 strings" -} - -implement { - name = "installedlanguages", - actions = { languages.installed, context }, -} - -implement { - name = "definelanguage", - actions = languages.define, - arguments = "2 strings" -} - -implement { - name = "setlanguagesynonym", - actions = languages.setsynonym, - arguments = "2 strings" -} - -implement { - name = "unloadlanguage", - actions = languages.unload, - arguments = "string" -} - -implement { - name = "setlanguageexceptions", - actions = languages.setexceptions, - arguments = "2 strings" -} - -implement { - name = "currentprehyphenchar", - actions = function() - local c = prehyphenchar(tolang()) - if c and c > 0 then - context.char(c) - end - end -} - -implement { - name = "currentposthyphenchar", - actions = function() - local c = posthyphenchar(tolang()) - if c and c > 0 then - context.char(c) - end - end -} diff --git a/tex/context/base/mkiv/lang-ini.mkxl b/tex/context/base/mkiv/lang-ini.mkxl deleted file mode 100644 index 8ca8d7e8e..000000000 --- a/tex/context/base/mkiv/lang-ini.mkxl +++ /dev/null @@ -1,766 +0,0 @@ -%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. - -% We can protect \currentlanguage etc too. - -% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]} - -%D This module implements multi||language support of \CONTEXT, which should not be -%D confused with the multi||lingual interface. This support will be extended when -%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\ -%D files. - -\writestatus{loading}{ConTeXt Language Macros / Initialization} - -\registerctxluafile{lang-ini}{autosuffix} -\registerctxluafile{lang-def}{} -\registerctxluafile{lang-cnt}{} - -\unprotect - -\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi -\ifdefined\frenchspacing \else \let\frenchspacing \relax \fi - -%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table, -%D starting with~0. Switching to a specific table is done by assigning the relevant -%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot -%D of management is delegated to \LUA. - -%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This -%D just one of those situations in which we don't want to spent a real one. Language -%D zero has no patterns, first of all because I like to start numbering at one. It -%D may come in handy for special purposes as well. - -\normallanguage\zerocount \def\loadedlanguage{1} - -%D \macros -%D {currentlanguage, setupcurrentlanguage} -%D -%D Instead of numbers,we are going to use symbolic names for the languages. The -%D current langage is saved in the macro \type {\currentlanguage}. The setup macro -%D is mainly used for cosmetic purposes. -%D -%D \starttyping -%D \dorecurse{3} -%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 -%D We don't use the commandhandler here (yet) because we have a rather special -%D fallback mechanism so quite some compatibility testing is needed. - -\installcorenamespace{language} -\installcorenamespace{languagelinked} - -\def\currentusedlanguage{\currentlanguage} - -\permanent\def\defaultlanguage#1% - {\ifcsname\??language#1\s!default\endcsname - \expandafter\defaultlanguage\lastnamedcs - \else - #1% - \fi} - -\permanent\def\languageparameter#1% - {\ifcsname\??language\currentlanguage#1\endcsname - \lastnamedcs - \orelse\ifcsname\??language\currentlanguage\s!default\endcsname - \expandafter\specificlanguageparameter\lastnamedcs{#1}% - \orelse\ifcsname\??language\s!default#1\endcsname - \lastnamedcs - \fi} - -\permanent\def\specificlanguageparameter#1#2% - {\ifcsname\??language#1#2\endcsname - \lastnamedcs - \orelse\ifcsname\??language#1\s!default\endcsname - \expandafter\specificlanguageparameter\lastnamedcs{#2}% - \orelse\ifcsname\??language\s!default#2\endcsname - \lastnamedcs - \fi} - -\permanent\def\mainlanguageparameter#1% - {\ifcsname\??language\currentmainlanguage#1\endcsname - \lastnamedcs - \orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname - \expandafter\specificlanguageparameter\lastnamedcs{#1}% - \orelse\ifcsname\??language\s!default#1\endcsname - \lastnamedcs - \fi} - -\aliased\let\usedlanguageparameter\languageparameter - -\permanent\def\askedlanguageparameter#1% assumes \currentusedlanguage being set - {\ifcsname\??language\currentusedlanguage#1\endcsname - \lastnamedcs - \orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname - \expandafter\specificlanguageparameter\lastnamedcs{#1}% - \orelse\ifcsname\??language\s!default#1\endcsname - \lastnamedcs - \fi} - -\permanent\protected\def\setusedlanguage#1% - {\edef\currentusedlanguage{\reallanguagetag{#1}}% - \ifempty\currentusedlanguage - \let\currentusedlanguage \currentlanguage - \enforced\let\usedlanguageparameter\languageparameter - \orelse\ifx\currentusedlanguage\v!global - \let\currentusedlanguage \currentmainlanguage - \enforced\let\usedlanguageparameter\mainlanguageparameter - \orelse\ifx\currentusedlanguage\v!local - \let\currentusedlanguage \currentlanguage - \enforced\let\usedlanguageparameter\languageparameter - \else - \enforced\let\usedlanguageparameter\askedlanguageparameter - \fi} - -\permanent\protected\def\setupcurrentlanguage[#1]% - {\setcurrentlanguage\currentmainlanguage{#1}} - -\permanent\protected\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current) - {\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage - \ifempty\xaskedlanguage \else - \ifempty\currentmainlanguage\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi - \let\currentmainlanguage\xaskedlanguage - \setsystemmode{\systemmodeprefix\currentmainlanguage}% - \fi - \edef\xaskedlanguage{#2}% - \ifempty\xaskedlanguage \else - \ifempty\currentlanguage\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 is prepared. The -%D next macro takes care of this loading. A language is specified with -%D -%D \showsetup{installlanguage} -%D -%D When \type {state} equals \type {start}, both patterns and additional hyphenation -%D specifications are loaded. These files are seached for in the patterns path -%D have names like \type {lang-nl.lua}. -%D -%D The \type {spacing} variable specifies how the spaces after punctuation has to be -%D handled. English is by tradition more tolerant to inter||sentence spacing than -%D other languages. -%D -%D This macro also defines \type {\identifier} as a shortcut switch to the language. -%D Furthermore the command defined as being language specific, are executed. With -%D \type {default} we can default to another language (patterns) at format -%D generation time. Patterns are loaded at runtime. - -\newtoks \everysetuplanguage - -\aliased\let\installedlanguages\clf_installedlanguages % no need for \clf_ - -\permanent\protected\def\doifelselanguage#1% - {\ifcsname\??language#1\c!state\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiflanguageelse\doifelselanguage - -\permanent\def\reallanguagetag#1% - {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi} - -% \language[#1] gave unwanted side effect of loading language specifics - -\permanent\tolerant\protected\def\installlanguage[#1]#*[#2]% - {\ifcondition\validassignment{#2}% - \doifelselanguage{#1} - {\getparameters[\??language#1][#2]} - {\setvalue{\??languagelinked#1}{#1}% - \getparameters[\??language#1][\c!state=\v!start,#2]% - \lang_basics_install_indeed{#1}{#1}}% - \edef\currentsetuplanguage{#1}% - \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}% - \the\everysetuplanguage - \else - \setvalue{\??languagelinked#1}{#2}% - \clf_setlanguagesynonym{#1}{#2}% - \lang_basics_install_indeed{#1}{#2}% - \fi} - -\def\lang_basics_install_indeed#1#2% - {\doifnot{\specificlanguageparameter{#1}\c!command}\v!no - {\ifcsname#1\endcsname\else\frozen\instance\setuvalue{#1}{\lang_basics_set_current[#2]}\fi}} - -%D When the second argument is a language identifier, a synonym is created. This -%D feature is present because we used dutch mnemonics in the dutch version, but -%D nowadays conform a standard. - -\permanent\protected\def\doifelsepatterns#1% - {\begingroup % will change - \lang_basics_set_current[#1]% - \ifnum\normallanguage>\zerocount - \endgroup\expandafter\firstoftwoarguments - \else - \endgroup\expandafter\secondoftwoarguments - \fi} - -\aliased\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. - -\ifdefined\lang_basics_synchronize \else - \let\lang_basics_synchronize\relax % be nice for setups till we have one -\fi - -\installmacrostack\currentlanguage - -\permanent\tolerant\protected\def\setuplanguage[#1]#*[#2]% - {\ifarguments - % only synchronize - \or - \let\currentsetuplanguage\currentlanguage - \getparameters[\??language\currentsetuplanguage][#1]% - \the\everysetuplanguage - \or - \push_macro_currentlanguage % can be default - \edef\currentsetuplanguage{\reallanguagetag{#1}}% - \getparameters[\??language\currentsetuplanguage][#2]% - \the\everysetuplanguage - \pop_macro_currentlanguage - %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default) - \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!time={h,:,m}, - \c!date={\v!year,\ ,\v!month,\ ,\v!day}, - \c!text=Ag, - \c!font=] % \v!auto : experimental ! - -% to be tested: -% -% \setuplanguage -% [\s!default] -% [\c!righthyphenchar="AD] - -%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used -%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french -%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like -%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into -%D view \quotation {when we quote} or \quote {quote} something. - -%D \macros -%D {currentdatespecification, currenttimespecification} -%D -%D Just to make things easy we can ask for the current date specification by saying: - -\permanent\def\currentdatespecification{\languageparameter\c!date} -\permanent\def\currenttimespecification{\languageparameter\c!time} - -%D Carefull reading of these macros shows that it's legal to say -%D -%D \starttyping -%D \installlanguage [du] [de] -%D \stoptyping - -%D \macros -%D {language,mainlanguage} -%D -%D Switching to another language (actually another hyphenation pattern) is done -%D with: -%D -%D \starttyping -%D \language[identifier] -%D \stoptyping -%D -%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still -%D support the original meaning, so -%D -%D \starttyping -%D \language=1 -%D \stoptyping -%D -%D is a valid operation, where the relation between number and language depends on -%D the order in installing languages. -%D -%D \showsetup{language} -%D \showsetup{mainlanguage} -%D -%D Both commands take a predefined language identifier as argument. We can use \type -%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the -%D language used for translating labels like {\em figure} and {\em table}. The main -%D language defaults to the current language. - -\newtoks \everylanguage - -\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\letcsname\??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}% - {\languageparameter\c!factor}% - \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 - {\normallanguage\csname\??languagenumbers - \ifcsname\??languagenumbers\currentlanguage\endcsname - \currentlanguage - \fi - \endcsname - \relax - \the\everylanguage - \relax} - -\newcount\hyphenstate -\newcount\hyphenminoffset - -% This is the old implementation: a hack that sets the min values, because we want -% to keep the language set: -% -% \protected\def\nohyphens % nicer for url's -% {\ifx\dohyphens\relax -% \protected\edef\dohyphens -% {\hyphenminoffset\the\hyphenminoffset\relax -% \lang_basics_synchronize_min_max}% -% \fi -% \hyphenminoffset\plusthousand -% \lang_basics_synchronize_min_max} -% -% \let\dohyphens\relax - -% But this one is nicer because we do keep the language set as well as don't mess -% with the min values (it's more efficient too). We might get some more bits in -% this mode (engine specific). - -\exhyphenchar 45 % to permit breaking at explicit hyphens - -% \uchyph\plusone : - -\chardef \completehyphenationmodecode \numexpr - \normalhyphenationmodecode % \discretionary - + \automatichyphenationmodecode % - - + \explicithyphenationmodecode % \- - + \syllablehyphenationmodecode % pattern driven - + \uppercasehyphenationmodecode % replaces \uchyph - + \compoundhyphenationmodecode % replaces \compoundhyphenmode - % \strictstarthyphenationmodecode % replaces \hyphenationbounds (strict = original tex) - % \strictendhyphenationmodecode % replaces \hyphenationbounds (strict = original tex) - + \automaticpenaltyhyphenationmodecode % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty) - + \explicitpenaltyhyphenationmodecode % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty) - + \permitgluehyphenationmodecode % turn glue into kern in \discretionary - + \permitallhyphenationmodecode % okay, let's be even more tolerant - + \permitmathreplacehyphenationmodecode % and again we're more permissive -\relax - -\permanent\protected\def\dohyphens{\hyphenationmode\completehyphenationmodecode} -\permanent\protected\def\nohyphens{\hyphenationmode\zerocount} - -\permanent\protected\def\usehyphensparameter#1% - {\edef\p_hyphens{#1\c!hyphens}% - \ifx\p_hyhens\v!no - \nohyphens - \fi} - -\dohyphens - -%D The rest stays the same as in mkiv: - -\permanent\protected\def\lesshyphens - {\advance\hyphenminoffset\plusone - \lang_basics_synchronize_min_max} - -\permanent\protected\def\morehyphens - {\ifcase\hyphenminoffset \else - \advance\hyphenminoffset\minusone - \fi - \lang_basics_synchronize_min_max} - -\protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end - {% these values are stored along with glyph nodes - \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax - \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax - \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 - -\permanent\protected\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}% - \ifempty\currentlanguagesetups \else - \setups[\currentlanguagesetups]% - \fi -\to \everylanguage - -% new - -\appendtoks - \usebidiparameter\languageparameter -\to \everylanguage - -% this will move to core-spa ! - -\appendtoks - \edef\p_spacing{\languageparameter\c!spacing}% - \ifx\p_spacing\v!broad - \nonfrenchspacing - \else - \frenchspacing - \fi -\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 - -\permanent\protected\def\setuplanguages - {\setuplanguage[\s!default]} - -% \setuplanguages[\c!font=\v!auto] -% \setuplanguage[\s!default][\c!font=\v!auto] -% \setuplanguage[nl][\c!font=\v!auto] - -\appendtoks - \edef\p_language_font{\languageparameter\c!font}% - \ifempty\p_language_font - \orelse\ifx\p_language_font\v!auto - \doaddfeature\currentlanguage - \else - \doaddfeature\p_language_font - \fi -\to \everylanguage - -%D Fast switcher - -\def\lang_basics_switch_asked - {\ifcsname\??languagelinked\askedlanguage\endcsname - \edef\askedlanguage{\lastnamedcs}% - \ifx\currentlanguage\askedlanguage \else - \setcurrentlanguage\currentmainlanguage\askedlanguage - \lang_basics_synchronize - \fi - \fi} - -\permanent\protected\def\uselanguageparameter#1% - {\edef\askedlanguage{#1\c!language}% - \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} - -\permanent\protected\def\douselanguageparameter#1% fast setter - {\edef\askedlanguage{#1}% - \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} - -\protected\def\lang_basics_set_current[#1]% - {\edef\askedlanguage{#1}% - \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} - -\pushoverloadmode - - \permanent\protected\def\language - {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage} - - \let\setlanguage\language % we make these synonyms - - \let\patterns\gobbleoneargument - -\popoverloadmode - -\newcount\mainlanguagenumber - -%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par} -%D inside the group! - -\permanent\protected\def\startlanguage - {\begingroup\language} - -\permanent\let\stoplanguage\endgroup - -\permanent\protected\def\mainlanguage[#1]% - {\edef\askedlanguage{#1}% - \ifempty\askedlanguage - \orelse\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 - \mainlanguagenumber\normallanguage} - -\appendtoks - \normallanguage\mainlanguagenumber -\to \everybeforepagebody - -%D Used at all? - -\permanent\def\splitsequence#1#2% - {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}} - -\permanent\def\splitsymbol#1% - {\splitsequence{#1}{\languageparameter\c!limittext}} - -%D Just like with subsentence boundary symbols, quotes placement depends on the -%D current language, therefore we show the defaults here. -%D -%D \def\ShowLanguageValues [#1] [#2] #3 #4 -%D {\blank -%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 [et] [estonian] ... -%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 loaded in separate files, -%D according to their roots. Here we only take care of (postponed) setting of the -%D current language. -%D -%D \unprotect -%D \placetable{The germanic languages (\type{lang-ger})} -%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 - -\permanent\protected\def\nopatterns{\normallanguage\minusone} - -%D We default to the language belonging to the interface. This is one of the few -%D places outside the interface modules where \type {\startinterface} is used. - -\setupcurrentlanguage[\s!en] - -\permanent\protected\def\initializemainlanguage - {\mainlanguage[\currentlanguage]% - \showmessage\m!languages9\currentlanguage} - -%D New: - -\permanent\let\stopexceptions\relax - -\tolerant\permanent\protected\def\startexceptions[#1]#:#2\stopexceptions - {\begingroup - \edef\askedlanguage{\reallanguagetag{#1}}% - \ifempty\askedlanguage - \let\askedlanguage\currentlanguage - \fi - \clf_setlanguageexceptions{\askedlanguage}{#2}% - \endgroup} - -\pushoverloadmode - -\permanent\protected\def\hyphenation - {\clf_setlanguageexceptions{\currentlanguage}} - -\popoverloadmode - -%D New: - -\permanent\protected\def\traceddiscretionary#1#% - {\dontleavehmode\lang_basics_traced_discretionary{#1}} - -\protected\def\lang_basics_traced_discretionary#1#2#3#4% - {\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}} - -\installtextracker - {discretionaries} - {\enforced\let\discretionary\traceddiscretionary} - {\enforced\let\discretionary\normaldiscretionary} - -\permanent\protected\def\samplediscretionary - {\traceddiscretionary - {pre\clf_currentprehyphenchar}% - {\clf_currentposthyphenchar post}% - {replace}} - -%D Also new: - -\immutable\chardef\nokerningcode \numexpr\noleftkerncode +\norightkerncode \relax -\immutable\chardef\noligaturingcode\numexpr\noleftligaturecode+\norightligaturecode\relax - -\permanent\protected\def\nokerning {\bitwiseflip\glyphoptions\nokerningcode} -\permanent\protected\def\noligaturing{\bitwiseflip\glyphoptions\noligaturingcode} - -\protect \endinput diff --git a/tex/context/base/mkiv/lang-lab.mkxl b/tex/context/base/mkiv/lang-lab.mkxl deleted file mode 100644 index 8968631a0..000000000 --- a/tex/context/base/mkiv/lang-lab.mkxl +++ /dev/null @@ -1,364 +0,0 @@ -%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}{} -\registerctxluafile{lang-txt}{} - -\unprotect - -%D Left-overs: - -\ifdefined\sixperemspace \else - \permanent\def\sixperemspace{\normalUchar"2006} -\fi - -%D In this module we deal with language dependant labels and prefixes, like in {\em -%D Figure~12} and {\em Chapter 1}. In this file we set the default values. Users can -%D easily overrule these. -%D -%D This module is dedicated to the grandfather of Tobias Burnus, who's extensive -%D languages oriented library helped us a lot in finding the right translations. All -%D those labels are collected in files that reflect their common ancestor. -%D -%D Not all languages can be satisfied with the labeling mechanism as provided here. -%D Chinese for instance put a label in front as well as after a part number. This is -%D why the 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 call head and label -%D 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 - -\permanent\tolerant\protected\def\definelabelclass[#1]#*[#2]% - {\normalexpanded - {\lang_labels_define_class_indeed - {#1}% - {\ifchknum#2\or#2\else\zerocount\fi}% - \expandafter\noexpand\csname lang_labels_#1_text_1\endcsname - \expandafter\noexpand\csname #1language\endcsname - \expandafter\noexpand\csname lang_labels_#1_text_2\endcsname - \expandafter\noexpand\csname left#1text\endcsname - \expandafter\noexpand\csname right#1text\endcsname - \expandafter\noexpand\csname #1texts\endcsname - \expandafter\noexpand\csname #1text\endcsname}} - -% hm, not interfaced - -\let\thetextprefix\empty - -\protected\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9% - {\permanent\instance\setuvalue {setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% - \permanent\instance\setuvalue{preset#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% - \permanent\instance\setuvalue {copy#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_copy }% - \permanent\instance\setuvalue {start#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_start[#1]}% - \permanent\instance\letvalue {stop#1text}\relax - \permanent\instance\def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}% - \ifnum#2=\plustwo % used for math and tags - \instance\def#3{#5#4}% - \instance\def#5##1##2% ##1=language - {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname - \lastnamedcs - \orelse\ifcsname\??label#1:##1:##2\endcsname - \lastnamedcs - \orelse\ifcsname\??language##1\s!default\endcsname - \expandafter#5\lastnamedcs{##2}% - \orelse\ifcsname\??label\currentlabelcategory#1:##2\endcsname - \lastnamedcs - \orelse\ifcsname\??label#1:##2\endcsname - \lastnamedcs - \orelse\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname - \lastnamedcs - \orelse\ifcsname\??label#1:\s!en:##2\endcsname - \lastnamedcs - \else - ##2% - \fi}% - \permanent\instance\let#6\gobbleoneargument - \permanent\instance\let#7\gobbleoneargument - \permanent\instance\let#8\gobbletwoarguments - \permanent\instance\let#9#3% - \else - \instance\protected\def#3{#5#4}% - \instance\protected\def#5##1##2% - {\ifcsname\??label#1:##1:##2\endcsname - \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs - \orelse\ifcsname\??language#4\s!default\endcsname - \expandafter#5\lastnamedcs{##2}% - \orelse\ifcsname\??label#1:##2\endcsname - \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs - \orelse\ifcsname\??label#1:\s!en:##2\endcsname - \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs - \else - \enforced\let\thetextprefix\dummytextprefix - \fi}% - \permanent\instance\protected\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% - \permanent\instance\protected\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}% - \permanent\instance\protected\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2 - \permanent\instance\protected\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% - \fi - \appendtoks - \enforced\permanent\instance\let#6\firstofoneargument % to be checked - \enforced\permanent\instance\let#7\firstofoneargument % to be checked - \enforced\permanent\instance\let#8\firstofoneargument % to be checked - \enforced\permanent\instance\let#9\firstofoneargument % to be checked - \to \everysimplifycommands} - -% why not lang_* ? - -\let\flushleftlabelclass \firstoftwoarguments -\let\flushrightlabelclass\secondoftwoarguments - -\permanent\def\flushbothlabelclass#1#2#3{#1#3#2} - -\permanent\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 texts without -%D replacing predefined ones. They are internal macros. - -\appendtoks \enforced\let\labellanguage\currentlanguage \to \everycurrentdate - -\newconstant\protecttextprefixes - -\let\currenttextprefixtag \s!unknown -\let\currenttextprefixclass\s!unknown - -\tolerant\def\lang_labels_text_prefix_start[#1]#*[#2]#*[#3]% class language name - {\ifarguments\or\or - \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% - \edef\currenttextprefixname{#2}% - \else - \edef\currenttextprefixtag{\reallanguagetag{#2}}% - \edef\currenttextprefixname{#3}% - \fi - \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed} - -\def\lang_labels_text_prefix_start_indeed#1% text (not special checking done here yet, only for long texts anyway) - {\edefcsname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname{{\clf_strip{#1}}\empty}} - -\tolerant\def\lang_labels_text_prefix_setup[#1]#*[#2]% - {\ifarguments\or - \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% - \processcommalist[#1]\lang_labels_text_prefix_setup_indeed - \else - \edef\currenttextprefixtag{\reallanguagetag{#1}}% - \processcommalist[#2]\lang_labels_text_prefix_setup_indeed - \fi} - -\def\lang_labels_text_prefix_setup_indeed#1% - {\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 - \defcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1% - \ifempty\m_lang_labels_right - \ifempty\m_lang_labels_left - \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]% - {\defcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}} - -\permanent\protected\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end - {%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}% - \defcsname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right - -\tolerant\def\lang_labels_text_prefix_copy[#1]#*[#2]% - {\ifarguments\or - \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% - \processcommalist[#1]\lang_labels_text_prefix_copy_indeed - \else - \edef\currenttextprefixtag{\reallanguagetag{#1}}% - \processcommalist[#2]\lang_labels_text_prefix_copy_indeed - \fi} - -\def\lang_labels_text_prefix_copy_indeed#1% - {\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} -% -% this delays the aliasing so that we can switch mainlanguage in between - -\def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]% - {\edefcsname\??label\currenttextprefixclass:#1\endcsname - {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#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 be typeset. Such -%D macros can be made (more) language 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 de current language. - -\installcorenamespace{translation} - -\permanent\tolerant\protected\def\translate[#1]% - {\getparameters[\??translation][#1]% - \ifcsname\??translation\currentlanguage\endcsname - \lastnamedcs - \orelse\ifcsname\??translation\s!en\endcsname - \lastnamedcs - \else - [translation #1]% - \fi} - -%D When used without argument, the last defined values are used. This enables -%D 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 translation to a macro. -%D Its form is: -%D -%D \starttyping -%D \assigntranslation[en=something,nl=iets]\to\command -%D \stoptyping - -% nicer is \edef\command{\translated[...]} ... todo - -\permanent\protected\def\assigntranslation[#1]\to#2% bad, this \to - {\getparameters[\??translation][#1]% - \edef#2{\begincsname\??translation\currentlanguage\endcsname}} - -%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 - -\permanent\tolerant\protected\def\commalistsentence[#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): - -\permanent\protected\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases! - -\protect \endinput diff --git a/tex/context/base/mkiv/lang-mis.mkxl b/tex/context/base/mkiv/lang-mis.mkxl deleted file mode 100644 index de15ec526..000000000 --- a/tex/context/base/mkiv/lang-mis.mkxl +++ /dev/null @@ -1,586 +0,0 @@ -%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. - -%D This one will be updated stepwise to \LMTX. See lang-mis.mkiv for previous -%D implementations and removed code. - -\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 -%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. - -% hm why ex - -\ifx\compoundhyphen\undefined - \permanent\protected\def\compoundhyphen{\hbox{-\kern-.10775\emwidth-}} % .25\exheight -\fi - -%D The last two variables are needed for subsentences |<|like this one|>| which we -%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 \permanent\protected\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi -\ifx\postwordbreak\undefined \permanent\protected\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi -\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % will be overloaded - -%frozen\protected\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces -\permanent\protected\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces - -%D \macros -%D {beginofsubsentence,endofsubsentence, -%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. - -%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}2xxx - -\def\lang_discretionaries_hyphen_like#1#2% - {\ifconditional\spaceafterdiscretionary - %prewordbreak\hbox{#1}\relax - \wordboundary\hbox{#1}\relax - \orelse\ifconditional\punctafterdiscretionary - %prewordbreak\hbox{#1}\relax - \wordboundary\hbox{#1}\relax - \else - %\prewordbreak#2\postwordbreak % was prewordbreak - \wordboundary#2\wordboundary - \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 - (\wordboundary - \else - %\prewordbreak\discretionary{}{(-}{(}\prewordbreak - \wordboundary\discretionary{}{(-}{(}\wordboundary - %\discretionary options \plusthree{}{(-}{(}% - \fi} - -\definetextmodediscretionary ~ - %{\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak} - {\wordboundary\discretionary{-}{}{\thinspace}\wordboundary} - %{\discretionary options \plusthree{-}{}{\thinspace}} - -\definetextmodediscretionary ' - %{\prewordbreak\discretionary{-}{}{'}\postwordbreak} - {\wordboundary\discretionary{-}{}{'}\wordboundary} - %{\discretionary options \plusthree{-}{}{'}} - -\definetextmodediscretionary ^ - %{\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% - % \postwordbreak} % bugged - {\wordboundary - \discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% - \wordboundary} % bugged - %{\discretionary options \plusthree{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}} - -\definetextmodediscretionary < - %{\beginofsubsentence\prewordbreak\beginofsubsentencespacing - {\beginofsubsentence\wordboundary\beginofsubsentencespacing - \aftergroup\ignorespaces} % tricky, we need to go over the \nextnextnext - -\definetextmodediscretionary > - {\removeunwantedspaces - %\endofsubsentencespacing\prewordbreak\endofsubsentence} - \endofsubsentencespacing\wordboundary\endofsubsentence} - -\definetextmodediscretionary = - {\removeunwantedspaces - %\prewordbreak\midsentence\prewordbreak - \wordboundary\midsentence\wordboundary - \aftergroup\ignorespaces} - -% french - -%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:} -%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};} -%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?} -%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!} - -\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{:}:} -\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{;};} -\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{?}?} -\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{!}!} - -%definetextmodediscretionary * {\prewordbreak\discretionary{-}{}{\kern.05\emwidth}\prewordbreak} -\definetextmodediscretionary * {\wordboundary\discretionary{-}{}{\kern.05\emwidth}\wordboundary} - -% spanish - -%definetextmodediscretionary ?? {\prewordbreak\questiondown} -%definetextmodediscretionary !! {\prewordbreak\exclamdown} - -\definetextmodediscretionary ?? {\wordboundary\questiondown} -\definetextmodediscretionary !! {\wordboundary\exclamdown} - -%D \installdiscretionary | + -%D \installdiscretionary + = - -\permanent\protected\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 - -\permanent\protected\def\fakecompoundhyphen - {\enforced\permanent\protected\def\|{\mathortext\vert\lang_compounds_fake_hyphen}} - -\def\lang_compounds_fake_hyphen - {\enforced\permanent\protected\def##1|% - {\doifelsenothing{##1}\compoundhyphen{##1}% - \kern\d_lang_discretionaries_breakpoint - \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. - -\permanent\protected\def\midworddiscretionary - {\futurelet\nexttoken\lang_discretionaries_mid_word} - -\def\lang_discretionaries_mid_word - {\ifx\nexttoken\blankspace\orelse - \ifx\nexttoken\bgroup \orelse - \ifx\nexttoken\egroup \orelse - \discretionary{-}{}{}% - \fi} - -\let\ignorecompoundcharacter\relax - -%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 - - \permanent\protected\gdef\compound#1{|#1|} - - \doglobal \appendtoks - \enforced\permanent\protected\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 - -%D Here: -%D -%D \startbuffer -%D {\red somelongword}{\blue \compounddiscretionary}{\green somelongword} -%D \stopbuffer -%D -%D \typebuffer \blank {\hsize3mm\getbuffer\par} \blank - -\permanent\protected\def\compounddiscretionary - {\discretionary - options \plusthree - {\ifnum\prehyphenchar >\zerocount\char\prehyphenchar \fi}% - {\ifnum\posthyphenchar>\zerocount\char\posthyphenchar\fi}% - {\ifnum\posthyphenchar>\zerocount\char\posthyphenchar\fi}} - -\protect \endinput diff --git a/tex/context/base/mkiv/lang-url.mkxl b/tex/context/base/mkiv/lang-url.mkxl deleted file mode 100644 index bb51f838a..000000000 --- a/tex/context/base/mkiv/lang-url.mkxl +++ /dev/null @@ -1,167 +0,0 @@ -%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}{} - -\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 - % - \enforced\let\&\letterampersand - \enforced\let\#\letterhash - \enforced\let\~\lettertilde - \enforced\let\\\letterbackslash - \enforced\let\$\letterdollar - \enforced\let\^\letterhat - \enforced\let\_\letterunderscore - \enforced\let\{\letterleftbrace - \enforced\let\}\letterrightbrace - \enforced\let\|\letterbar - \enforced\let~=\lettertilde - \enforced\let|=\letterbar - \enforced\let\Ux\eUx -\to \everyhyphenatedurl - -\let\hyphenatedurlseparator \empty % \periodcentered -\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} - -\permanent\protected\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 - -\permanent\protected\def\sethyphenatedurlnormal#1{\clf_sethyphenatedurlcharacters{#1}{\v!normal}} -\permanent\protected\def\sethyphenatedurlbefore#1{\clf_sethyphenatedurlcharacters{#1}{\v!before}} -\permanent\protected\def\sethyphenatedurlafter #1{\clf_sethyphenatedurlcharacters{#1}{\v!after }} - -% \sethyphenatedurlafter{ABCDEF} - -\permanent\protected\def\hyphenatedurl#1% - {\dontleavehmode - \begingroup - \the\everyhyphenatedurl - \normallanguage\zerocount % \nohyphens in mkiv - \scratchskipone\zeropoint\s!plus\dimexpr\emwidth/12\s!minus\dimexpr\emwidth/24\relax % 1.00pt @ 12pt - \scratchskiptwo\zeropoint\s!plus\dimexpr\emwidth/48\s!minus\dimexpr\emwidth/96\relax % 0.25pt @ 12pt - \unprotect - \normalexpanded{\noexpand\clf_hyphenatedurl - {\noexpand\detokenize{#1}}% - \hyphenatedurllefthyphenmin - \hyphenatedurlrighthyphenmin - {\hyphenatedurldiscretionary}% - }% - \protect - \endgroup} - -%D \macros -%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 \aliased\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] -% -% \protected\def\WhateverA#1% -% {\dontleavehmode -% \begingroup -% \prehyphenchar"B7\relax -% \setbox\scratchbox\hbox{\tttf#1}% -% \prehyphenchar`-\relax -% \unhbox\scratchbox -% \endgroup} -% -% \protected\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/tex/context/base/mkiv/layo-ini.mkxl b/tex/context/base/mkiv/layo-ini.mkxl deleted file mode 100644 index 4979989cd..000000000 --- a/tex/context/base/mkiv/layo-ini.mkxl +++ /dev/null @@ -1,30 +0,0 @@ -%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 and code from other -%D modules will move here. This will make 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}{} - -\protect \endinput diff --git a/tex/context/base/mkiv/libs-imp-curl.lmt b/tex/context/base/mkiv/libs-imp-curl.lmt deleted file mode 100644 index b30739794..000000000 --- a/tex/context/base/mkiv/libs-imp-curl.lmt +++ /dev/null @@ -1,296 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-curl'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/curl/libcurl.dll - -local libname = "curl" -local libfile = "libcurl" - -local curllib = resolvers.libraries.validoptional(libname) - -if not curllib then return end - --- We're good, so we continue. - -local next, type = next, type -local lower, gsub = string.lower, string.gsub - -local mapping = { - ["acceptencoding"] = 102, - ["accepttimeoutms"] = 212, - ["addressscope"] = 171, - ["append"] = 50, - ["autoreferer"] = 58, - ["buffersize"] = 98, - ["cainfo"] = 65, - ["capath"] = 97, - ["certinfo"] = 172, - -- ["chunkbgnfunction"] = 198, - ["chunkdata"] = 201, - -- ["chunkendfunction"] = 199, - ["closepolicy"] = 72, - ["closesocketdata"] = 209, - -- ["closesocketfunction"] = 208, - ["connectonly"] = 141, - ["connecttimeout"] = 78, - ["connecttimeoutms"] = 156, - -- ["convfromnetworkfunction"] = 142, - -- ["convfromutf8function"] = 144, - -- ["convtonetworkfunction"] = 143, - ["cookie"] = 22, - ["cookiefile"] = 31, - ["cookiejar"] = 82, - ["cookielist"] = 135, - ["cookiesessionv"] = 96, - ["copypostfields"] = 165, - ["crlf"] = 27, - ["crlfile"] = 169, - ["customrequest"] = 36, - ["debugdata"] = 95, - -- ["debugfunction"] = 94, - ["dirlistonly"] = 48, - ["dnscachetimeout"] = 92, - ["dnsinterface"] = 221, - ["dnslocalip4"] = 222, - ["dnslocalip6"] = 223, - ["dnsservers"] = 211, - ["dnsuseglobalcache"] = 91, - ["egdsocket"] = 77, - ["errorbuffer"] = 10, - ["expect100timeoutms"] = 227, - ["failonerror"] = 45, - ["file"] = 1, - ["filetime"] = 69, - ["fnmatchdata"] = 202, - -- ["fnmatchfunction"] = 200, - ["followlocation"] = 52, - ["forbidreuse"] = 75, - ["freshconnect"] = 74, - ["ftpaccount"] = 134, - ["ftpalternativetouser"] = 147, - ["ftpcreatemissingdirs"] = 110, - ["ftpfilemethod"] = 138, - ["ftpresponsetimeout"] = 112, - ["ftpskippasvip"] = 137, - ["ftpsslccc"] = 154, - ["ftpuseeprt"] = 106, - ["ftpuseepsv"] = 85, - ["ftpusepret"] = 188, - ["ftpport"] = 17, - ["ftpsslauth"] = 129, - ["gssapidelegation"] = 210, - ["header"] = 42, - ["headerdata"] = 29, - -- ["headerfunction"] = 79, - ["http200aliases"] = 104, - ["httpcontentdecoding"] = 158, - ["httptransferdecoding"] = 157, - ["httpversion"] = 84, - ["httpauth"] = 107, - ["httpget"] = 80, - ["httpheader"] = 23, - ["httppost"] = 24, - ["httpproxytunnel"] = 61, - ["ignorecontentlength"] = 136, - ["infile"] = 9, - ["infilesize"] = 14, - ["infilesizelarge"] = 115, - ["interface"] = 62, - ["interleavedata"] = 195, - -- ["interleavefunction"] = 196, - ["ioctldata"] = 131, - -- ["ioctlfunction"] = 130, - ["ipresolve"] = 113, - ["issuercert"] = 170, - ["keypasswd"] = 26, - ["krblevel"] = 63, - ["localport"] = 139, - ["localportrange"] = 140, - ["loginoptions"] = 224, - ["lowspeedlimit"] = 19, - ["lowspeedtime"] = 20, - ["mailauth"] = 217, - ["mailfrom"] = 186, - ["mailrcpt"] = 187, - ["maxrecvspeedlarge"] = 146, - ["maxsendspeedlarge"] = 145, - ["maxconnects"] = 71, - ["maxfilesize"] = 114, - ["maxfilesizelarge"] = 117, - ["maxredirs"] = 68, - ["netrc"] = 51, - ["netrcfile"] = 118, - ["newdirectoryperms"] = 160, - ["newfileperms"] = 159, - ["nobody"] = 44, - ["noprogress"] = 43, - ["noproxy"] = 177, - ["nosignal"] = 99, - ["opensocketdata"] = 164, - -- ["opensocketfunction"] = 163, - ["password"] = 174, - ["port"] = 3, - ["post"] = 47, - -- ["postfields"] = 15, - -- ["postfieldsize"] = 60, - -- ["postfieldsizelarge"] = 120, - ["postquote"] = 39, - ["postredir"] = 161, - ["prequote"] = 93, - ["private"] = 103, - ["progressdata"] = 57, - -- ["progressfunction"] = 56, - ["protocols"] = 181, - ["proxy"] = 4, - ["proxytransfermode"] = 166, - ["proxyauth"] = 111, - ["proxypassword"] = 176, - ["proxyport"] = 59, - ["proxytype"] = 101, - ["proxyusername"] = 175, - ["proxyuserpwd"] = 6, - ["put"] = 54, - ["quote"] = 28, - ["randomfile"] = 76, - ["range"] = 7, - ["readdata"] = 9, - -- ["readfunction"] = 12, - ["redirprotocols"] = 182, - ["referer"] = 16, - ["resolve"] = 203, - ["resumefrom"] = 21, - ["resumefromlarge"] = 116, - ["rtspclientcseq"] = 193, - ["rtsprequest"] = 189, - ["rtspservercseq"] = 194, - ["rtspsessionid"] = 190, - ["rtspstreamuri"] = 191, - ["rtsptransport"] = 192, - ["rtspheader"] = 23, - ["saslir"] = 218, - ["seekdata"] = 168, - -- ["seekfunction"] = 167, - ["serverresponsetimeout"] = 112, - ["share"] = 100, - ["sockoptdata"] = 149, - -- ["sockoptfunction"] = 148, - ["socks5gssapinec"] = 180, - ["socks5gssapiservice"] = 179, - ["sshauthtypes"] = 151, - ["sshhostpublickeymd5"] = 162, - ["sshkeydata"] = 185, - -- ["sshkeyfunction"] = 184, - ["sshknownhosts"] = 183, - ["sshprivatekeyfile"] = 153, - ["sshpublickeyfile"] = 152, - ["sslcipherlist"] = 83, - ["sslctxdata"] = 109, - -- ["sslctxfunction"] = 108, - ["sslenablealpn"] = 226, - ["sslenablenpn"] = 225, - ["ssloptions"] = 216, - ["sslsessionidcache"] = 150, - ["sslverifyhost"] = 81, - ["sslverifypeer"] = 64, - ["sslcert"] = 25, - ["sslcerttype"] = 86, - ["sslengine"] = 89, - ["sslenginedefault"] = 90, - ["sslkey"] = 87, - ["sslkeytype"] = 88, - ["sslversion"] = 32, - ["stderr"] = 37, - ["tcpkeepalive"] = 213, - ["tcpkeepidle"] = 214, - ["tcpkeepintvl"] = 215, - ["tcpnodelay"] = 121, - ["telnetoptions"] = 70, - ["tftpblksize"] = 178, - ["timecondition"] = 33, - ["timeout"] = 13, - ["timeoutms"] = 155, - ["timevalue"] = 34, - ["tlsauthpassword"] = 205, - ["tlsauthtype"] = 206, - ["tlsauthusername"] = 204, - ["transferencoding"] = 207, - ["transfertext"] = 53, - ["unrestrictedauth"] = 105, - ["upload"] = 46, - ["url"] = 2, - ["usessl"] = 119, - ["useragent"] = 18, - ["username"] = 173, - ["userpwd"] = 5, - ["verbose"] = 41, - ["wildcardmatch"] = 197, - ["writedata"] = 1, - -- ["writefunction"] = 11, - ["writeheader"] = 29, - ["writeinfo"] = 40, - ["xferinfodata"] = 57, - -- ["xferinfofunction"] = 219, - ["xoauth2bearer"] = 220, -} - -table.setmetatableindex(mapping,function(t,k) - local s = gsub(lower(k),"[^a-z0-9]","") - local v = rawget(t,s) or false - t[k] = v - return v -end) - -local curl_fetch = curllib.fetch -local curl_escape = curllib.escape -local curl_unescape = curllib.unescape -local curl_getversion = curllib.getversion - -local report = logs.reporter(libname) - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local function fetch(options) - if okay() then - local t = type(options) - if t == "table" then - local o = { } - for name, value in next, options do - local index = mapping[name] - if index then - o[index] = value - end - end - return curl_fetch(o) - elseif t == "string" then - return curl_fetch { [mapping.url] = options } - else - report("invalid argument") - end - end -end - -local curl = { - getversion = function () return okay() and curl_getversion() end, - escape = function (s) return okay() and curl_escape (s) end, - unescape = function (s) return okay() and curl_unescape (s) end, - fetch = fetch, -} - --- inspect(curl.fetch("http://www.pragma-ade.com/index.html")) --- inspect(curl.fetch { url = "http://www.pragma-ade.com/index.html" }) - -package.loaded[libname] = curl - -return curl diff --git a/tex/context/base/mkiv/libs-imp-ghostscript.lmt b/tex/context/base/mkiv/libs-imp-ghostscript.lmt deleted file mode 100644 index b129a58c1..000000000 --- a/tex/context/base/mkiv/libs-imp-ghostscript.lmt +++ /dev/null @@ -1,111 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "ghostscript" -local libfile = "gsdll64" -- what on unix? - -local gslib = resolvers.libraries.validoptional(libname) - -if not gslib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local insert = table.insert -local formatters = string.formatters - -local ghostscript = utilities.ghostscript or { } -utilities.ghostscript = ghostscript - -local gs_execute = gslib.execute -local nofruns = 0 -local report = logs.reporter(libname) - -function ghostscript.convert(specification) - if okay() then - -- - nofruns = nofruns + 1 - statistics.starttiming(ghostscript) - -- - local inputname = specification.inputname - if not inputname or inputname == "" then - report("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("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 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("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) - report("") - local done = gslib_execute(options) - report("") - -- - statistics.stoptiming(ghostscript) - if done then - return outputname - else - report("run %s quit with errors",nofruns) - return false - end - end -end - -function ghostscript.statistics(report) - local runtime = statistics.elapsedtime(ghostscript) - if report then - report("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/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt b/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt deleted file mode 100644 index 6f5d1d967..000000000 --- a/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt +++ /dev/null @@ -1,77 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-graphicsmagick'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "graphicsmagick" -local libfile = { "CORE_RL_magick_", "CORE_RL_wand_" } - -local gmlib = resolvers.libraries.validoptional(libname) - -if not gmlib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local graphicsmagick = utilities.graphicsmagick or { } -utilities.graphicsmagick = graphicsmagick -utilities.graphicmagick = graphicsmagick - -local gm_execute = gmlib.execute -local nofruns = 0 -local report = logs.reporter(libname) - -function graphicsmagick.convert(specification) - if okay() then - -- - nofruns = nofruns + 1 - statistics.starttiming(graphicsmagick) - -- - local inputname = specification.inputname - if not inputname or inputname == "" then - report("invalid run %s, no inputname specified",nofruns) - statistics.stoptiming(graphicsmagick) - 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("invalid run %s, input file %a is not found",nofruns,inputname) - statistics.stoptiming(graphicsmagick) - return false - end - -- - report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) - -- - gm_execute { inputfile = inputname, outputfile = outputname } - -- - statistics.stoptiming(graphicsmagick) - end -end - -function graphicsmagick.statistics(report) - local runtime = statistics.elapsedtime(graphicsmagick) - if report then - report("nofruns %s, runtime %s",nofruns,runtime) - else - return { - runtime = runtime, - nofruns = nofruns, - } - end -end - --- graphicsmagick.convert { inputname = "t:/sources/hacker.jpg", outputname = "e:/tmp/hacker.png" } --- graphicsmagick.statistics(true) diff --git a/tex/context/base/mkiv/libs-imp-kpse.lmt b/tex/context/base/mkiv/libs-imp-kpse.lmt deleted file mode 100644 index f8e4a9907..000000000 --- a/tex/context/base/mkiv/libs-imp-kpse.lmt +++ /dev/null @@ -1,58 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-kpse'] = { - version = 1.001, - comment = "companion to luat-imp-kpse.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is an experiment. It might make sense to have this available in case I want --- more runners to use LuaMetaTeX in which case (as with mtxrun using LuaTeX) we --- need to load kpse. - -local libname = "kpse" -local libfile = (os.platform == "win64" and "kpathsea*w64") - or (os.platform == "win32" and "kpathsea*w32") - or "libkpathsea" -local libkpse = resolvers.libraries.validoptional(libname) - -if package.loaded[libname] then - return package.loaded[libname] -end - --- This is a variant that loaded directly: - --- kpse = libkpse -- the library will issue warnings anyway --- --- resolvers.libraries.optionalloaded(libname,libfile) -- no need to chedk if true - --- This variant delays loading and has a bit more protection: - -local function okay() - if libkpse and resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local kpse = { } - -for k, v in next, libkpse do - kpse[k] = function(...) if okay() then return v(...) end end -end - --- We properly register the module: - -package.loaded[libname] = kpse - -optional.loaded.kpse = kpse - --- A simple test: - --- kpse.set_program_name("pdftex") --- print("find file:",kpse.find_file("oeps.tex")) --- print("find file:",kpse.find_file("context.mkii")) - -return kpse diff --git a/tex/context/base/mkiv/libs-imp-kpse.mkxl b/tex/context/base/mkiv/libs-imp-kpse.mkxl deleted file mode 100644 index f76c99029..000000000 --- a/tex/context/base/mkiv/libs-imp-kpse.mkxl +++ /dev/null @@ -1,38 +0,0 @@ -%D \module -%D [ file=libs-imp-kpse, -%D version=2020.05.19, -%D title=\CONTEXT\ System Modules, -%D subtitle=KPSE File Searching, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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 not really a module. It's more some left over from an experiment. Who -%D know when it comes in handy; probably never in a real run, but I might want to -%D make a \LUAMETATEX\ plain format one day, just for the fun of it. - -% \registerctxluafile{libs-imp-kpse}{autosuffix} - -\continueifinputfile{libs-imp-kpse.mkxl} - -\starttext - -\startTEXpage - \startluacode - local kpse = require("libs-imp-kpse") - - kpse.set_program_name("pdftex") - - local name = "context.mkii" - - context("%s: %s",name,kpse.find_file(name)) - \stopluacode -\stopTEXpage - -\stoptext - - diff --git a/tex/context/base/mkiv/libs-imp-mujs.lmt b/tex/context/base/mkiv/libs-imp-mujs.lmt deleted file mode 100644 index 264c8e531..000000000 --- a/tex/context/base/mkiv/libs-imp-mujs.lmt +++ /dev/null @@ -1,126 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-mujs'] = { - version = 1.001, - comment = "companion to luat-imp-mujs.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a --- stepping stone to using \LUA. - --- local ecmascript = optional.mujs.initialize("libmujs") --- local execute = optional.mujs.execute - -local libname = "mujs" -local libfile = "libmujs" - -if package.loaded[libname] then - return package.loaded[libname] -end - -local mujslib = resolvers.libraries.validoptional(libname) - -if not mujslib then - return -end - -local files = { } -local openfile = io.open -local findfile = resolvers.findfile - -local mujs_execute = mujslib.execute -local mujs_dofile = mujslib.dofile -local mujs_reset = mujslib.reset - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - mujs_execute( - "var catcodes = { " .. - "'tex': " .. tex.texcatcodes .. "," .. - "'ctx': " .. tex.ctxcatcodes .. "," .. - "'prt': " .. tex.prtcatcodes .. "," .. - "'vrb': " .. tex.vrbcatcodes .. "," .. - "};" - ) - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -mujslib.setfindfile(findfile) - -mujslib.setopenfile(function(name) - local full = findfile(name) - if full then - local f = openfile(full,"rb") - if f then - for i=1,100 do - if not files[i] then - files[i] = f - return i - end - end - end - end -end) - -mujslib.setclosefile(function(id) - local f = files[id] - if f then - f:close() - files[id] = false - end -end) - -mujslib.setreadfile(function(id,how) - local f = files[id] - if f then - return (f:read(how or "*l")) - end -end) - -mujslib.setseekfile(function(id,whence,offset) - local f = files[id] - if f then - return (f:seek(whence,offset)) - end -end) - -local reporters = { - console = logs.reporter("mujs","console"), - report = logs.reporter("mujs","report"), -} - -mujslib.setconsole(function(category,name) - reporters[category](name) -end) - -local mujs = { - ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, - ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, - ["reset"] = function(n) if okay() then mujs_reset(n) end end, -} - -package.loaded[libname] = mujs - -optional.loaded.mujs = mujs - -interfaces.implement { - name = "ecmacode", - actions = mujs.execute, - arguments = "string", - public = true, -} - -interfaces.implement { - name = "ecmafile", - actions = mujs.dofile, - arguments = "string", - public = true, - protected = true, -} - -return mujs diff --git a/tex/context/base/mkiv/libs-imp-mujs.mkxl b/tex/context/base/mkiv/libs-imp-mujs.mkxl deleted file mode 100644 index a8fe5801f..000000000 --- a/tex/context/base/mkiv/libs-imp-mujs.mkxl +++ /dev/null @@ -1,121 +0,0 @@ -%D \module -%D [ file=libs-imp-mujs, -%D version=2020.02.08, -%D title=\CONTEXT\ Extra Modules, -%D subtitle=MuJS interpreter, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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 an experiment: -%D -%D \starttyping -%D http://mujs.com -%D \stoptyping - -\ifdefined\ecmacode - \expandafter \endinput -\fi - -\registerctxluafile{libs-imp-mujs}{autosuffix} - -\unprotect - -% todo: environment - -\let\stopecmacode\relax - -\protected\def\startecmacode % \stopecmacode - {\begingroup - \obeylualines - \obeyluatokens - \luat_start_ecma_code_indeed} - -\def\luat_start_ecma_code_indeed#1\stopecmacode - {\normalexpanded{\endgroup\noexpand\ecmacode{#1}}} - -\protect - -\continueifinputfile{libs-imp-mujs.mkxl} - -\usemodule[article-basic,abbreviations-logos] - -\starttext - -\startbuffer -\startluacode - local mujs = require("libs-imp-mujs") - - mujs.execute [[ - var MyMax = 1000; - ]] - - mujs.execute [[ - console("Example One!"); - texsprint("\\startpacked"); - for (var i = 1; i <= MyMax; i = i + 1) { - texprint( - "This is a buildbot compilation challenge for Mojca: " - .concat(Math.sqrt(i/MyMax)) - .concat("!\\par") - ); - } - texsprint("\\stoppacked"); - ]] - - -- mujs.execute [[ - -- something very bad: an error - -- ]] -\stopluacode - -\startecmacode - console("Example Two!"); - for (var i = 1; i <= MyMax; i = i + 1) { - texsprint( - "And an opportunity for Alan to attract highschool students to \\TeX: " - .concat(i) - .concat("! ") - ); - } -\stopecmacode - -\ecmacode { - console("Example Three!"); - texprint("And otherwise a way to prototype \\JAVASCRIPT\\ code in \\PDF.") -} - -\startecmacode - var f = File("libs-imp-mujs.mkxl","r"); - console(f); - // var l = f.read(400); - var l = f.read("*a"); - console(l); - f.close(); -\stopecmacode - -\startecmacode - console("Example Four!"); - texsprint("\\startMPcode " - .concat(' fill fullcircle scaled 6cm withcolor "darkred";') - .concat(' fill fullcircle scaled 4cm withcolor "darkgreen";') - .concat(' fill fullcircle scaled 2cm withcolor "darkblue";') - .concat("\\stopMPcode ") - ); -\stopecmacode - -\startluacode - context.startMPcode() - context('fill fullcircle scaled 6cm withcolor "middlecyan";') - context('fill fullcircle scaled 4cm withcolor "middlemagenta";') - context('fill fullcircle scaled 2cm withcolor "middleyellow";') - context.stopMPcode() -\stopluacode -\stopbuffer - -\typebuffer \page \getbuffer - -\stoptext diff --git a/tex/context/base/mkiv/libs-imp-mysql.lmt b/tex/context/base/mkiv/libs-imp-mysql.lmt deleted file mode 100644 index 3e938a6de..000000000 --- a/tex/context/base/mkiv/libs-imp-mysql.lmt +++ /dev/null @@ -1,220 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-mysql'] = { - 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" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/mysql/libmysql.dll - -local libname = "mysql" -local libfile = "libmysql" - -local mysqllib = resolvers.libraries.validoptional(libname) - -if not mysqllib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local lpegmatch = lpeg.match -local setmetatable = setmetatable - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -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 mysql_open = mysqllib.open -local mysql_close = mysqllib.close -local mysql_execute = mysqllib.execute -local mysql_getmessage = mysqllib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local querysplitter = helpers.querysplitter -local cache = { } -local timeout -- = 3600 -- to be tested - -local function connect(specification) - local db = mysql_open( - specification.database or "", - specification.username or "", - specification.password or "", - specification.host or "", - specification.port - ) - if db and timeout then - mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) - end - return db -end - -local function execute_once(specification,retry) - if okay() then - if trace_sql then - report("executing mysql") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - else - query = lpegmatch(querysplitter,query) - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local result = { } - local keys = { } - local id = specification.id - local db = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = connect(specification) - if not db then - report("no session database specified") - else - cache[id] = { - specification = specification, - db = db, - } - end - end - else - db = connect(specification) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if converter then - local convert = converter.mysql - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - for i=1,#query do - local okay = mysql_execute(db,query[i],callback) - if not okay then - if id and retry and i == 1 then - report("error: %s, retrying to connect",mysql_getmessage(db)) - mysql_close(db) - cache[id] = nil - return execute_once(specification,false) - else - report("error: %s",mysql_getmessage(db)) - end - end - end - end - if db and not id then - mysql_close(db) - end - -- bonus - local one = result[1] - if one then - setmetatable(result,{ __index = one } ) - end - -- - return result, keys - else - report("error: ","no library loaded") - end -end - -local function execute(specification) - return execute_once(specification,true) -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(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - --- return function(result) --- if not result then --- return { } --- end --- local nofrows = #result --- if nofrows == 0 then --- return { } --- end --- local target = { } -- no %s needed here --- for i=1,nofrows do --- target[%s] = { --- %s --- } --- end --- return result --- end - -local celltemplate = "cells[%s]" - -methods.mysql = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-ffi"] = methods.mysql -package.loaded["util-sql-imp-mysql"] = methods.mysql -package.loaded["util-sql-imp-library"] = methods.mysql -package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkiv/libs-imp-postgress.lmt b/tex/context/base/mkiv/libs-imp-postgress.lmt deleted file mode 100644 index 629079b01..000000000 --- a/tex/context/base/mkiv/libs-imp-postgress.lmt +++ /dev/null @@ -1,200 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-postgress'] = { - 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" -} - --- Not yet untested ! - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/postgress/libpq.dll - --- we can now share the code between mysql, postgress, sqlite ... todo - -local libname = "postgress" -local libfile = "libpq" - -local postgresslib = resolvers.libraries.validoptional(libname) - -if not postgresslib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local lpegmatch = lpeg.match -local setmetatable = setmetatable - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -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 postgress_open = postgresslib.open -local postgress_close = postgresslib.close -local postgress_execute = postgresslib.execute -local postgress_getmessage = postgresslib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local querysplitter = helpers.querysplitter -- not needed -local cache = { } - -local function connect(specification) - return postgress_open( - specification.database or "", - specification.username or "", - specification.password or "", - specification.host or "", - specification.port - ) -end - -local function execute_once(specification,retry) - if okay() then - if trace_sql then - report("executing postgress") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - else - query = lpegmatch(querysplitter,query) -- not needed - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local result = { } - local keys = { } - local id = specification.id - local db = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = connect(specification) - if not db then - report("no session database specified") - else - cache[id] = { - specification = specification, - db = db, - } - end - end - else - db = connect(specification) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if converter then - local convert = converter.postgress - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - for i=1,#query do - local okay = postgress_execute(db,query[i],callback) - if not okay then - if id and retry and i == 1 then - report("error: %s, retrying to connect",postgress_getmessage(db)) - postgress_close(db) - cache[id] = nil - return execute_once(specification,false) - else - report("error: %s",postgress_getmessage(db)) - end - end - end - end - if db and not id then - postgress_close(db) - end - -- bonus - local one = result[1] - if one then - setmetatable(result,{ __index = one } ) - end - -- - return result, keys - else - report("error: ","no library loaded") - end -end - -local function execute(specification) - return execute_once(specification,true) -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(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - -local celltemplate = "cells[%s]" - -methods.postgress = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-postgress"] = methods.postgress -package.loaded[libname] = methods.postgress diff --git a/tex/context/base/mkiv/libs-imp-sqlite.lmt b/tex/context/base/mkiv/libs-imp-sqlite.lmt deleted file mode 100644 index 5d38986f3..000000000 --- a/tex/context/base/mkiv/libs-imp-sqlite.lmt +++ /dev/null @@ -1,187 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-sqlite'] = { - 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" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/sqlite/sqlite3.dll - -local libname = "sqlite" -local libfile = "sqlite3" - -local sqlitelib = resolvers.libraries.validoptional(libname) - -if not sqlitelib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local next, tonumber = next, tonumber -local setmetatable = setmetatable -local formatters = string.formatters - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -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 sqlite_open = sqlitelib.open -local sqlite_close = sqlitelib.close -local sqlite_execute = sqlitelib.execute -local sqlite_getmessage = sqlitelib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local cache = { } - --- synchronous journal_mode locking_mode 1000 logger inserts --- --- normal normal normal 6.8 --- off off normal 0.1 --- normal off normal 2.1 --- normal persist normal 5.8 --- normal truncate normal 4.2 --- normal truncate exclusive 4.1 - -local f_preamble = formatters[ [[ -ATTACH `%s` AS `%s` ; -PRAGMA `%s`.synchronous = normal ; -]] ] - -local function execute(specification) - if okay() then - if trace_sql then - report("executing sqlite") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local filename = file.addsuffix(base,"db") - local result = { } - local keys = { } - local id = specification.id - local db = nil - local preamble = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = sqlite_open(filename) - preamble = f_preamble(filename,base,base) - if not db then - report("no session database specified") - else - cache[id] = { - name = filename, - db = db, - } - end - end - else - db = open_db(filename) - preamble = f_preamble(filename,base,base) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if preamble then - query = preamble .. query -- only needed in open - end - if converter then - local convert = converter.sqlite - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - local okay = sqlite_execute(db,query,callback) - if not okay then - report("error: %s",sqlite_getmessage(db)) - -- elseif converter then - -- result = converter.sqlite(result) - end - end - if db and not id then - sqlite_close(db) - end - return result, keys - else - report("error: ","no library loaded") - end -end - -local wraptemplate = [[ -local converters = utilities.sql.converters -local deserialize = utilities.sql.deserialize - -local tostring = tostring -local tonumber = tonumber -local booleanstring = string.booleanstring - -%s - -return function(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - -local celltemplate = "cells[%s]" - -methods.sqlite = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-sqlite"] = methods.sqlite -package.loaded[libname] = methods.sqlite - -return methods.sqlite diff --git a/tex/context/base/mkiv/libs-imp-zint.lmt b/tex/context/base/mkiv/libs-imp-zint.lmt deleted file mode 100644 index 2c346ae7d..000000000 --- a/tex/context/base/mkiv/libs-imp-zint.lmt +++ /dev/null @@ -1,161 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "zint" -local libfile = "libzint" -- what on unix? --- local libfile = "/usr/local/lib/libzint.so" - -local zintlib = resolvers.libraries.validoptional(libname) - -if not zintlib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local zint = utilities.zint or { } -utilities.zint = zint - -local zintlib_execute = zintlib.execute - -local next, type, unpack = next, type, unpack -local lower, gsub = string.lower, string.gsub - -local mapping = { - ["code 11"] = 1, ["pharma one-track"] = 51, ["aztec code"] = 92, - ["standard 2of5"] = 2, ["pzn"] = 52, ["daft code"] = 93, - ["interleaved 2of5"] = 3, ["pharma two-track"] = 53, ["micro qr code"] = 97, - ["iata 2of5"] = 4, ["pdf417"] = 55, ["hibc code 128"] = 98, - ["data logic"] = 6, ["pdf417 trunc"] = 56, ["hibc code 39"] = 99, - ["industrial 2of5"] = 7, ["maxicode"] = 57, ["hibc data matrix"] = 102, - ["code 39"] = 8, ["qr code"] = 58, ["hibc qr code"] = 104, - ["extended code 39"] = 9, ["code 128-b"] = 60, ["hibc pdf417"] = 106, - ["ean"] = 13, ["ap standard customer"] = 63, ["hibc micropdf417"] = 108, - ["ean + check"] = 14, ["ap reply paid"] = 66, ["hibc codablock-f"] = 110, - ["gs1-128"] = 16, ["ap routing"] = 67, ["hibc aztec code"] = 112, - ["codabar"] = 18, ["ap redirection"] = 68, ["dotcode"] = 115, - ["code 128"] = 20, ["isbn"] = 69, ["han xin code"] = 116, - ["leitcode"] = 21, ["rm4scc"] = 70, ["rm mailmark"] = 121, - ["identcode"] = 22, ["data matrix"] = 71, ["aztec runes"] = 128, - ["code 16k"] = 23, ["ean-14"] = 72, ["code 32"] = 129, - ["code 49"] = 24, ["vin (north america)"] = 73, ["comp ean"] = 130, - ["code 93"] = 25, ["codablock-f"] = 74, ["comp gs1-128"] = 131, - ["flattermarken"] = 28, ["nve-18"] = 75, ["comp databar omni"] = 132, - ["gs1 databar omni"] = 29, ["japanese post"] = 76, ["comp databar ltd"] = 133, - ["gs1 databar ltd"] = 30, ["korea post"] = 77, ["comp databar expom"] = 134, - ["gs1 databar expom"] = 31, ["gs1 databar stack"] = 79, ["comp upc-a"] = 135, - ["telepen alpha"] = 32, ["gs1 databar stack omni"] = 80, ["comp upc-e"] = 136, - ["upc-a"] = 34, ["gs1 databar eso"] = 81, ["comp databar stack"] = 137, - ["upc-a + check"] = 35, ["planet"] = 82, ["comp databar stack omni"] = 138, - ["upc-e"] = 37, ["micropdf"] = 84, ["comp databar eso"] = 139, - ["upc-e + check"] = 38, ["usps onecode"] = 85, ["channel code"] = 140, - ["postnet"] = 40, ["uk plessey"] = 86, ["code one"] = 141, - ["msi plessey"] = 47, ["telepen numeric"] = 87, ["grid matrix"] = 142, - ["fim"] = 49, ["itf-14"] = 89, ["upnqr"] = 143, - ["logmars"] = 50, ["kix code"] = 90, ["rmqr"] = 145, -} - -table.setmetatableindex(mapping,function(t,k) - local s = gsub(lower(k),"[^a-z0-9]","") - local v = rawget(t,s) or false - t[k] = v - return v -end) - -local report = logs.reporter("zint") -local context = context -local shown = false - ------ f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] - -local function execute(specification) - if okay() then - local code = specification.code - local text = specification.text - if code then - local id = mapping[code] - if id then - specification.code = id - local result = zintlib_execute(specification) - if result then - -- not that fast but if needed we can speed it up - context.startMPcode() - local rectangles = result.rectangles - local hexagons = result.hexagons - local circles = result.circles - local strings = result.strings - if rectangles then - local n = #rectangles - for i=1,n do - local r = rectangles[i] - context("%sofill unitsquare xysized (%N,%N) shifted (%N,%N);", - i == n and "d" or "n",r[3],r[4],r[1],r[2]) - -- rectangles[i] = f_rectangle(i == n and "d" or "n",r[3],r[4],r[1],r[2]) - end - -- context("% t",rectangles) - end - if hexagons then - local n = #hexagons - for i=1,#hexagons do - context("%sofill (%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--cycle;", - i == n and "d" or "n",unpack(hexagons[i])) - end - end - if circles then - local n = #circles - for i=1,#circles do - local c = circles[i] - context("%sofill unitcircle scaled %N shifted (%N,%N);", - i == n and "d" or "n",c[3],c[1],c[2]) - end - end - if strings then - -- We set the font at the encapsulating level. - for i=1,#strings do - local s = strings[i] - context('draw textext("%s") scaled (%N/10) shifted (%N,%N);', - s[4],s[3],s[1],s[2]) - end - end - context.stopMPcode() - end - else - report("unknown barcode alternative %a",code) - if not shown then - report("") - report("valid barcode alternatives:") - report("") - local list = table.sortedkeys(mapping) - for i=1,#list do - report(" %s", list[i]) - end - report("") - shown = true - end - end - end - end -end - -optional.loaded.zint = { execute = execute } - -interfaces.implement { - name = "zint", - actions = execute, - arguments = { - { - { "code" }, - { "text" }, - } - } -} diff --git a/tex/context/base/mkiv/libs-imp-zint.mkxl b/tex/context/base/mkiv/libs-imp-zint.mkxl deleted file mode 100644 index fbea52888..000000000 --- a/tex/context/base/mkiv/libs-imp-zint.mkxl +++ /dev/null @@ -1,64 +0,0 @@ -%D \module -%D [ file=m-zint, -%D version=2010.12.07, -%D title=\CONTEXT\ Extra Modules, -%D subtitle=Zint Barcode Generator, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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 Using \type {zint} seems to be the easiest way to generate -%D (PDF417) barcodes so therefore we now have this module. There -%D are proper (also windows) binaries at: -%D -%D \starttyping -%D http://www.zint.org.uk -%D \stoptyping -%D -%D There is a bit more code than needed as we want to be able to -%D feed names. - -\registerctxluafile{libs-imp-zint}{autosuffix} - -\unprotect - -\definefont[usedzintfont][dejavusansmono at 10bp] - -\unexpanded\def\barcode[#1]% [alternative=,text=] - {\bgroup - \usedzintfont - \getdummyparameters - [\c!alternative=,\c!text=,#1]% - \scale - [#1]% - {\clf_zint - code {\dummyparameter\c!alternative} - text {\dummyparameter\c!text} - \relax} - \egroup} - -\protect - -\continueifinputfile{libs-imp-zint.mkxl} - -\starttext - -% \dorecurse{1000}{ - \startTEXpage - \barcode[alternative=PDF417,text={Hans Hagen}]% - \blank - \barcode[alternative=PDF417,text={Ton Otten}]% - \blank - \barcode[alternative=ISBN,text=9789490688011]% - \blank - \barcode[alternative=isbn,text=9789490688011,width=3cm]% - \stopTEXpage -% } - -\stoptext - - diff --git a/tex/context/base/mkiv/libs-ini.mkxl b/tex/context/base/mkiv/libs-ini.mkxl deleted file mode 100644 index e04c7c193..000000000 --- a/tex/context/base/mkiv/libs-ini.mkxl +++ /dev/null @@ -1,32 +0,0 @@ -%D \module -%D [ file=libs-ini, -%D version=2020.01.02, -%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. - -\registerctxluafile{libs-ini}{} % shared with mkiv - -\registerctxluafile{libs-imp-curl}{autosuffix} -\registerctxluafile{libs-imp-ghostscript}{autosuffix} -\registerctxluafile{libs-imp-graphicsmagick}{autosuffix} - -% These are loaded on demand: - -% \registerctxluafile{libs-imp-mysql}{autosuffix} -% \registerctxluafile{libs-imp-sqlite}{autosuffix} -% \registerctxluafile{libs-imp-postgress}{autosuffix} -% \registerctxluafile{libs-imp-kpse}{autosuffix} - -\unprotect - -% \unexpanded\def\uselibrary[#1]% -% {\clf_uselibrary{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/lpdf-emb.lmt b/tex/context/base/mkiv/lpdf-emb.lmt deleted file mode 100644 index d2da4473a..000000000 --- a/tex/context/base/mkiv/lpdf-emb.lmt +++ /dev/null @@ -1,2236 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-ini'] = { - version = 1.001, - optimize = true, - 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" -} - --- vkgoeswild: Pink Floyd - Shine on You Crazy Diamond - piano cover (around that --- time I redid the code, a reminder so to say) - --- At some point I wanted to have access to the shapes so that we could use them in --- metapost. So, after looking at the cff and ttf specifications, I decided to write --- parsers. At somepoint we needed a cff parser anyway in order to calculate the --- dimensions. Then variable fonts came around and a option was added to recreate --- streams of operators and a logical next step was to do all inclusion that way. It --- was only then that I found out that some of the juggling also happens in the the --- backend, but spread over places, so I could have saved myself some time --- deciphering the specifications. Anyway, here we go. --- --- Color fonts are a bit messy. Catching issues with older fonts will break new ones --- so I don't think that it's wise to build in too many catches (like for fonts with --- zero boundingboxes, weird dimensions, transformations that in a next version are --- fixed, etc.). Better is then to wait till something gets fixed. If a spec doesn't --- tell me how to deal with it ... I'll happily wait till it does. After all we're --- not in a hurry as these fonts are mostly meant for the web or special purposes --- with manual tweaking in desk top publishing applications. Keep in mind that Emoji --- can have funny dimensions (e.g. to be consistent within a font, so no tight ones). - --- When we have moved to lmtx I will document a bit more. Till then it's experimental --- and subjected to change. - -local next, type, unpack, rawget = next, type, unpack, rawget -local char, byte, gsub, sub, match, rep, gmatch = string.char, string.byte, string.gsub, string.sub, string.match, string.rep, string.gmatch -local formatters = string.formatters -local format = string.format -local concat, sortedhash, sort = table.concat, table.sortedhash, table.sort -local utfchar = utf.char -local random, round, max, abs, ceiling = math.random, math.round, math.max, math.abs, math.ceiling -local extract, lshift, rshift, band, bor = bit32.extract, bit32.lshift, bit32.rshift, bit32.band, bit32.bor -local idiv = number.idiv -local setmetatableindex = table.setmetatableindex - -local pdfnull = lpdf.null -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfconstant = lpdf.constant -local pdfstring = lpdf.string -local pdfreference = lpdf.reference -local pdfreserveobject = lpdf.reserveobject -local pdfflushobject = lpdf.flushobject -local pdfflushstreamobject = lpdf.flushstreamobject - -local report_fonts = logs.reporter("backend","fonts") - -local trace_fonts = false -local trace_details = false - -local dimenfactors = number.dimenfactors -local bpfactor = dimenfactors.bp -local ptfactor = dimenfactors.pt - -trackers.register("backend.pdf.fonts",function(v) trace_fonts = v end) - -local readers = fonts.handlers.otf.readers -local getinfo = readers.getinfo - -local setposition = utilities.files.setposition -local readstring = utilities.files.readstring -local openfile = utilities.files.open -local closefile = utilities.files.close - - --- needs checking: signed vs unsigned - -local tocardinal1 = char - -local function tocardinal2(n) - return char(extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal3(n) - return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal4(n) - return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tointeger2(n) - return char(extract(n,8,8),extract(n,0,8)) -end - -local function tointeger3(n) - return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tointeger4(n) - return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal8(n) - local l = idiv(n,0x100000000) - local r = n % 0x100000000 - return char(extract(l,24,8),extract(l,16,8),extract(l,8,8),extract(l,0,8), - extract(r,24,8),extract(r,16,8),extract(r,8,8),extract(r,0,8)) -end - --- A couple of shared helpers. - -local tounicodedictionary, widtharray, collectindices, subsetname, includecidset, forcecidset, tocidsetdictionary - -do - - -- Because we supply tounicodes ourselves we only use bfchar mappings (as in the - -- backend). In fact, we can now no longer pass the tounicodes to the frontend but - -- pick them up from the descriptions. - - local f_mapping_2 = formatters["<%02X> <%s>"] - local f_mapping_4 = formatters["<%04X> <%s>"] - - local tounicode = fonts.mappings.tounicode - -local tounicode_template = [[ -%%!PS-Adobe-3.0 Resource-CMap -%%%%DocumentNeededResources: ProcSet (CIDInit) -%%%%IncludeResource: ProcSet (CIDInit) -%%%%BeginResource: CMap (TeX-%s-0) -%%%%Title: (TeX-%s-0 TeX %s 0)| -%%%%Version: 1.000 -%%%%EndComments -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo - << /Registry (TeX) /Ordering (%s) /Supplement 0 >> - def - /CMapName - /TeX-Identity-%s - def - /CMapType - 2 - def - 1 begincodespacerange - <%s> <%s> - endcodespacerange - %i beginbfchar -%s - endbfchar - endcmap - CMapName currentdict /CMap defineresource pop - end -end -%%%%EndResource -%%%%EOF]] - - tounicodedictionary = function(details,indices,maxindex,name,wide) - local mapping = { } - local length = 0 - if maxindex > 0 then - local f_mapping = wide and f_mapping_4 or f_mapping_2 - for index=1,maxindex do - local data = indices[index] - if data then - length = length + 1 - local unicode = data.unicode - if unicode then - unicode = tounicode(unicode) - else - unicode = "FFFD" - end - mapping[length] = f_mapping(index,unicode) - end - end - end - local name = gsub(name,"%+","-") -- like luatex does - local first = wide and "0000" or "00" - local last = wide and "FFFF" or "FF" - local blob = format(tounicode_template,name,name,name,name,name,first,last,length,concat(mapping,"\n")) - return blob - end - - widtharray = function(details,indices,maxindex,units) - local widths = pdfarray() - local length = 0 - local factor = 10000 / units - if maxindex > 0 then - local lastindex = -1 - local sublist = nil - for index=1,maxindex do - local data = indices[index] - if data then - local width = data.width -- hm, is inaccurate for cff, so take from elsewhere - if width then - -- width = round(width * 10000 / units) / 10 - width = round(width * factor) / 10 - else - width = 0 - end - if index == lastindex + 1 then - sublist[#sublist+1] = width - else - if sublist then - length = length + 1 - widths[length] = sublist - end - sublist = pdfarray { width } - length = length + 1 - widths[length] = index - end - lastindex = index - end - end - length = length + 1 - widths[length] = sublist - end - return widths - end - - collectindices = function(descriptions,indices) - local minindex = 0xFFFF - local maxindex = 0 - local reverse = { } - -- todo: already at definition time trigger copying streams - -- and add extra indices ... first i need a good example of - -- a clash - -- for unicode, data in next, descriptions do - -- local i = data.index or unicode - -- if reverse[i] then - -- print("CLASH") - -- else - -- reverse[i] = data - -- end - -- end - for unicode, data in next, descriptions do - reverse[data.index or unicode] = data - end - for index in next, indices do - if index > maxindex then - maxindex = index - end - if index < minindex then - minindex = index - end - indices[index] = reverse[index] - end - if minindex > maxindex then - minindex = maxindex - end - return indices, minindex, maxindex - end - - includecidset = false - forcecidset = false -- for private testing only - - directives.register("backend.pdf.forcecidset",function(v) - forcecidset = v - end) - - tocidsetdictionary = function(indices,min,max) - if includecidset or forcecidset then - local b = { } - local m = idiv(max+7,8) - for i=0,max do - b[i] = 0 - end - b[0] = bor(b[0],lshift(1,7)) -- force notdef into the file - for i=min,max do - if indices[i] then - local bi = idiv(i,8) - local ni = i % 8 - b[bi] = bor(b[bi],lshift(1,7-ni)) - end - end - b = char(unpack(b,0,#b)) - return pdfreference(pdfflushstreamobject(b)) - end - end - - -- Actually we can use the same as we only embed once. - - -- subsetname = function(name) - -- return "CONTEXT" .. name - -- end - - local prefixes = { } -- todo: set fixed one - - subsetname = function(name) - local prefix - while true do - prefix = utfchar(random(65,90),random(65,90),random(65,90),random(65,90),random(65,90),random(65,90)) - if not prefixes[prefix] then - prefixes[prefix] = true - break - end - end - return prefix .. "+" .. name - end - -end - --- Map file mess. - -local loadmapfile, loadmapline, getmapentry do - - -- We only need to pick up the filename and optionally the enc file - -- as we only use them for old school virtual math fonts. We might as - -- we drop this completely. - - local find, match, splitlines = string.find, string.match, string.splitlines - - - local mappings = { } - - loadmapline = function(n) - if trace_fonts then - report_fonts("mapline: %s",n) - end - local name, fullname, encfile, pfbfile = match(n,"(%S+)%s+(%S+).-<(.-%.enc).-<(.-%.pfb)") - if name then - mappings[name] = { fullname, encfile, pfbfile } - end - end - - loadmapfile = function(n) - local okay, data = resolvers.loadbinfile(n,"map") - if okay and data then - data = splitlines(data) - for i=1,#data do - local d = data[i] - if d ~= "" and not find(d,"^[#%%]") then - loadmapline(d) - end - end - end - end - - getmapentry = function(n) - local n = file.nameonly(n) - local m = mappings[n] - if m then - local encfile = m[2] - local encoding = fonts.encodings.load(encfile) - if not encoding then - return - end - local pfbfile = resolvers.findfile(m[3],"pfb") - if not pfbfile or pfbfile == "" then - return - end - return encoding, pfbfile, encfile - end - end - - lpdf.getmapentry = getmapentry - -end - --- The three writers: opentype, truetype and type1. - -local mainwriters = { } - -do - - -- advh = os2.ascender - os2.descender - -- tsb = default_advh - os2.ascender - - -- truetype has the following tables: - - -- head : mandate - -- hhea : mandate - -- vhea : mandate - -- hmtx : mandate - -- maxp : mandate - -- glyf : mandate - -- loca : mandate - -- - -- cvt : if needed (but we flatten) - -- fpgm : if needed (but we flatten) - -- prep : if needed (but we flatten) - -- PCLT : if needed (but we flatten) - -- - -- name : not needed for T2: backend does that - -- post : not needed for T2: backend does that - -- OS/2 : not needed for T2: backend does that - -- cmap : not needed for T2: backend does that - - local streams = utilities.streams - local openstring = streams.openstring - local readcardinal2 = streams.readcardinal2 - ----- readcardinal4 = streams.readcardinal4 - - local otfreaders = fonts.handlers.otf.readers - - local function readcardinal4(f) -- this needs to be sorted out - local a = readcardinal2(f) - local b = readcardinal2(f) - if a and b then - return a * 0x10000 + b - end - end - - -- -- -- - - local tablereaders = { } - local tablewriters = { } - local tablecreators = { } - local tableloaders = { } - - local openfontfile, closefontfile, makefontfile, makemetadata do - - local details = { - details = true, - platformnames = true, - platformextras = true, - } - - -- .022 sec on luatex manual, neglectable: - - -- local function checksum(data) - -- local s = openstring(data) - -- local n = 0 - -- local d = #data - -- while true do - -- local c = readcardinal4(s) - -- if c then - -- n = (n + c) % 0x100000000 - -- else - -- break - -- end - -- end - -- return n - -- end - - local function checksum(data) - local s = openstring(data) - local n = 0 - local d = #data - while true do - local a = readcardinal2(s) - local b = readcardinal2(s) - if b then - n = (n + a * 0x10000 + b) % 0x100000000 - else - break - end - end - return n - end - - openfontfile = function(details) - return { - offset = 0, - order = { }, - used = { }, - details = details, - streams = details.streams, - } - end - - closefontfile = function(fontfile) - for k, v in next, fontfile do - fontfile[k] = nil -- so it can be collected asap - end - end - - local metakeys = { - "uniqueid", "version", - "copyright", "license", "licenseurl", - "manufacturer", "vendorurl", - "family", "subfamily", - "typographicfamily", "typographicsubfamily", - "fullname", "postscriptname", - } - - local template = [[ - - - - - -%s - - - - -]] - - makemetadata = function(fontfile) - local names = fontfile.streams.names - local list = { } - local f_name = formatters["%s"] - for i=1,#metakeys do - local m = metakeys[i] - local n = names[m] - if n then - list[#list+1] = f_name(m,n,m) - end - end - return format(template,concat(list,"\n")) - end - - makefontfile = function(fontfile) - local order = fontfile.order - local used = fontfile.used - local count = 0 - for i=1,#order do - local tag = order[i] - local data = fontfile[tag] - if data and #data > 0 then - count = count + 1 - else - fontfile[tag] = false - end - end - local offset = 12 + (count * 16) - local headof = 0 - local list = { - "" -- placeholder - } - local i = 1 - local k = 0 - while i <= count do - i = lshift(i,1) - k = k + 1 - end - local searchrange = lshift(i,3) - local entryselector = k - 1 - local rangeshift = lshift(count,4) - lshift(i,3) - local index = { - tocardinal4(0x00010000), -- tables.version - tocardinal2(count), - tocardinal2(searchrange), - tocardinal2(entryselector), - tocardinal2(rangeshift), - } - -- - local ni = #index - local nl = #list - for i=1,#order do - local tag = order[i] - local data = fontfile[tag] - if data then - local csum = checksum(data) - local dlength = #data - local length = idiv(dlength+3,4) * 4 - local padding = length - dlength - nl = nl + 1 ; list[nl] = data - for i=1,padding do - nl = nl + 1 ; list[nl] = "\0" - end - if #tag == 3 then - tag = tag .. " " - end - ni = ni + 1 ; index[ni] = tag -- must be 4 chars - ni = ni + 1 ; index[ni] = tocardinal4(csum) - ni = ni + 1 ; index[ni] = tocardinal4(offset) - ni = ni + 1 ; index[ni] = tocardinal4(dlength) - used[i] = offset -- not used - if tag == "head" then - headof = offset - end - offset = offset + length - end - end - list[1] = concat(index) - local off = #list[1] + headof + 1 + 8 - list = concat(list) - local csum = (0xB1B0AFBA - checksum(list)) % 0x100000000 - list = sub(list,1,off-1) .. tocardinal4(csum) .. sub(list,off+4,#list) - return list - end - - local function register(fontfile,name) - local u = fontfile.used - local o = fontfile.order - if not u[name] then - o[#o+1] = name - u[name] = true - end - end - - local function create(fontfile,name) - local t = { } - fontfile[name] = t - return t - end - - local function write(fontfile,name) - local t = fontfile[name] - if not t then - return - end - register(fontfile,name) - if type(t) == "table" then - if t[0] then - fontfile[name] = concat(t,"",0,#t) - elseif #t > 0 then - fontfile[name] = concat(t) - else - fontfile[name] = false - end - end - end - - tablewriters.head = function(fontfile) - register(fontfile,"head") - local t = fontfile.streams.fontheader - fontfile.head = concat { - tocardinal4(t.version), - tocardinal4(t.fontversionnumber), - tocardinal4(t.checksum), - tocardinal4(t.magic), - tocardinal2(t.flags), - tocardinal2(t.units), - tocardinal8(t.created), - tocardinal8(t.modified), - tocardinal2(t.xmin), - tocardinal2(t.ymin), - tocardinal2(t.xmax), - tocardinal2(t.ymax), - tocardinal2(t.macstyle), - tocardinal2(t.smallpixels), - tocardinal2(t.directionhint), - tocardinal2(t.indextolocformat), - tocardinal2(t.glyphformat), - } - end - - tablewriters.hhea = function(fontfile) - register(fontfile,"hhea") - local t = fontfile.streams.horizontalheader - local n = t and fontfile.nofglyphs or 0 - fontfile.hhea = concat { - tocardinal4(t.version), - tocardinal2(t.ascender), - tocardinal2(t.descender), - tocardinal2(t.linegap), - tocardinal2(t.maxadvancewidth), - tocardinal2(t.minleftsidebearing), - tocardinal2(t.minrightsidebearing), - tocardinal2(t.maxextent), - tocardinal2(t.caretsloperise), - tocardinal2(t.caretsloperun), - tocardinal2(t.caretoffset), - tocardinal2(t.reserved_1), - tocardinal2(t.reserved_2), - tocardinal2(t.reserved_3), - tocardinal2(t.reserved_4), - tocardinal2(t.metricdataformat), - tocardinal2(n) -- t.nofmetrics - } - end - - tablewriters.vhea = function(fontfile) - local t = fontfile.streams.verticalheader - local n = t and fontfile.nofglyphs or 0 - register(fontfile,"vhea") - fontfile.vhea = concat { - tocardinal4(t.version), - tocardinal2(t.ascender), - tocardinal2(t.descender), - tocardinal2(t.linegap), - tocardinal2(t.maxadvanceheight), - tocardinal2(t.mintopsidebearing), - tocardinal2(t.minbottomsidebearing), - tocardinal2(t.maxextent), - tocardinal2(t.caretsloperise), - tocardinal2(t.caretsloperun), - tocardinal2(t.caretoffset), - tocardinal2(t.reserved_1), - tocardinal2(t.reserved_2), - tocardinal2(t.reserved_3), - tocardinal2(t.reserved_4), - tocardinal2(t.metricdataformat), - tocardinal2(n) -- t.nofmetrics - } - end - - tablewriters.maxp = function(fontfile) - register(fontfile,"maxp") - local t = fontfile.streams.maximumprofile - local n = fontfile.nofglyphs - -- if fontfile.streams.cffinfo then - -- error - -- end - fontfile.maxp = concat { - tocardinal4(0x00010000), - tocardinal2(n), - tocardinal2(t.points), - tocardinal2(t.contours), - tocardinal2(t.compositepoints), - tocardinal2(t.compositecontours), - tocardinal2(t.zones), - tocardinal2(t.twilightpoints), - tocardinal2(t.storage), - tocardinal2(t.functiondefs), - tocardinal2(t.instructiondefs), - tocardinal2(t.stackelements), - tocardinal2(t.sizeofinstructions), - tocardinal2(t.componentelements), - tocardinal2(t.componentdepth), - } - end - - tablecreators.loca = function(fontfile) return create(fontfile,"loca") end - tablewriters .loca = function(fontfile) return write (fontfile,"loca") end - - tablecreators.glyf = function(fontfile) return create(fontfile,"glyf") end - tablewriters .glyf = function(fontfile) return write (fontfile,"glyf") end - - tablecreators.hmtx = function(fontfile) return create(fontfile,"hmtx") end - tablewriters .hmtx = function(fontfile) return write (fontfile,"hmtx") end - - tablecreators.vmtx = function(fontfile) return create(fontfile,"vmtx") end - tablewriters .vmtx = function(fontfile) return write (fontfile,"vmtx") end - - tableloaders .cmap = function(fontfile) return read (fontfile,"cmap") end - tablewriters .cmap = function(fontfile) return write (fontfile,"cmap") end - - tableloaders .name = function(fontfile) return read (fontfile,"name") end - tablewriters .name = function(fontfile) return write (fontfile,"name") end - - tableloaders .post = function(fontfile) return read (fontfile,"post") end - tablewriters .post = function(fontfile) return write (fontfile,"post") end - - end - - mainwriters["truetype"] = function(details) - -- - local fontfile = openfontfile(details) - local basefontname = details.basefontname - local streams = details.streams - local blobs = streams.streams - local fontheader = streams.fontheader - local horizontalheader = streams.horizontalheader - local verticalheader = streams.verticalheader - local maximumprofile = streams.maximumprofile - local names = streams.names - local descriptions = details.rawdata.descriptions - local metadata = details.rawdata.metadata - local indices = details.indices - local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } - local indices, - minindex, - maxindex = collectindices(descriptions,indices) - local glyphstreams = tablecreators.glyf(fontfile) - local locations = tablecreators.loca(fontfile) - local horizontals = tablecreators.hmtx(fontfile) - local verticals = tablecreators.vmtx(fontfile) - -- - local zero2 = tocardinal2(0) - local zero4 = tocardinal4(0) - -- - local horizontal = horizontalheader.nofmetrics > 0 - local vertical = verticalheader.nofmetrics > 0 - -- - local streamoffset = 0 - local lastoffset = zero4 - local g, h, v = 0, 0, 0 - -- - -- todo: locate notdef - -- - if minindex > 0 then - local blob = blobs[0] - if blob and #blob > 0 then - locations[0] = lastoffset - g = g + 1 ; glyphstreams[g] = blob - h = h + 1 ; horizontals [h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - else - report_fonts("missing .notdef in font %a",basefontname) - end - -- todo: use a rep for h/v - for index=1,minindex-1 do - locations[index] = lastoffset - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - end - end - for index=minindex,maxindex do - locations[index] = lastoffset - local data = indices[index] - if data then - local blob = blobs[index] -- we assume padding - if blob and #blob > 0 then - g = g + 1 ; glyphstreams[g] = blob - h = h + 1 ; horizontals [h] = tocardinal2(data.width or 0) - h = h + 1 ; horizontals [h] = tocardinal2(data.boundingbox[1]) - if vertical then - v = v + 1 ; verticals[v] = tocardinal2(data.height or 0) - v = v + 1 ; verticals[v] = tocardinal2(data.boundingbox[3]) - end - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - else - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - report_fonts("missing blob for index %i in font %a",index,basefontname) - end - else - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - end - end - locations[maxindex+1] = lastoffset -- cf spec - -- - local nofglyphs = maxindex + 1 -- include zero - -- - fontheader.checksum = 0 - fontheader.indextolocformat = 1 - maximumprofile.nofglyphs = nofglyphs - -- - fontfile.format = "tff" - fontfile.basefontname = basefontname - fontfile.nofglyphs = nofglyphs - -- - tablewriters.head(fontfile) - tablewriters.hhea(fontfile) - if vertical then - tablewriters.vhea(fontfile) - end - tablewriters.maxp(fontfile) - - tablewriters.loca(fontfile) - tablewriters.glyf(fontfile) - - tablewriters.hmtx(fontfile) - if vertical then - tablewriters.vmtx(fontfile) - end - -- - local fontdata = makefontfile(fontfile) - local fontmeta = makemetadata(fontfile) - -- - fontfile = closefontfile(fontfile) - -- - local units = metadata.units - local basefont = pdfconstant(basefontname) - local widths = widtharray(details,indices,maxindex,units) - local object = details.objectnumber - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) - local tocidset = tocidsetdictionary(indices,minindex,maxindex) - local metabbox = metadata.boundingbox or { 0, 0, 0, 0 } - local fontbbox = pdfarray { unpack(metabbox) } - local ascender = metadata.ascender - local descender = metadata.descender - local capheight = metadata.capheight or fontbbox[4] - local stemv = metadata.weightclass - local italicangle = metadata.italicangle - local xheight = metadata.xheight or fontbbox[4] - -- - if stemv then - stemv = (stemv/65)^2 + 50 - end - -- - local function scale(n) - if n then - return round((n) * 10000 / units) / 10 - else - return 0 - end - end - -- - local reserved = pdfreserveobject() - local child = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("CIDFontType2"), - BaseFont = basefont, - FontDescriptor = pdfreference(reserved), - W = pdfreference(pdfflushobject(widths)), - CIDToGIDMap = pdfconstant("Identity"), - CIDSystemInfo = pdfdictionary { - Registry = pdfstring("Adobe"), - Ordering = pdfstring("Identity"), - Supplement = 0, - } - } - local descendants = pdfarray { - pdfreference(pdfflushobject(child)), - } - local descriptor = pdfdictionary { - Type = pdfconstant("FontDescriptor"), - FontName = basefont, - Flags = 4, - FontBBox = fontbbox, - Ascent = scale(ascender), - Descent = scale(descender), - ItalicAngle = round(italicangle or 0), - CapHeight = scale(capheight), - StemV = scale(stemv), - XHeight = scale(xheight), - FontFile2 = pdfreference(pdfflushstreamobject(fontdata)), - CIDSet = tocidset, - Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type0"), - Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), - BaseFont = basefont, - DescendantFonts = descendants, - ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(reserved,descriptor) - pdfflushobject(object,parent) - -- - -- if trace_details then - -- local name = "temp.ttf" - -- report_fonts("saving %a",name) - -- io.savedata(name,fontdata) - -- inspect(fonts.handlers.otf.readers.loadfont(name)) - -- end - -- - end - - do - -- todo : cff2 - - local details = { - details = true, - platformnames = true, - platformextras = true, - } - - tablecreators.cff = function(fontfile) - fontfile.charstrings = { } - fontfile.charmappings = { } - fontfile.cffstrings = { } - fontfile.cffhash = { } - return fontfile.charstrings , fontfile.charmappings - end - - local todictnumber, todictreal, todictinteger, todictoffset do - - local maxnum = 0x7FFFFFFF - local minnum = - 0x7FFFFFFF - 1 - local epsilon = 1.0e-5 - - local int2tag = "\28" - local int4tag = "\29" - local realtag = "\30" - - todictinteger = function(n) - if not n then - return char(band(139,0xFF)) - elseif n >= -107 and n <= 107 then - return char(band(n + 139,0xFF)) - elseif n >= 108 and n <= 1131 then - n = 0xF700 + n - 108 - return char(band(rshift(n,8),0xFF),band(n,0xFF)) - elseif n >= -1131 and n <= -108 then - n = 0xFB00 - n - 108 - return char(band(rshift(n,8),0xFF),band(n,0xFF)) - elseif n >= -32768 and n <= 32767 then - -- return int2tag .. tointeger2(n) - return char(28,extract(n,8,8),extract(n,0,8)) - else - -- return int4tag .. tointeger4(n) - return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) - end - end - - -- -- not called that often - -- - -- local encoder = readers.cffencoder - -- - -- todictinteger = function(n) - -- if not n then - -- return encoder[0] - -- elseif n >= -1131 and n <= 1131 then - -- return encoder[n] - -- elseif n >= -32768 and n <= 32767 then - -- -- return int2tag .. tointeger2(n) - -- return char(28,extract(n,8,8),extract(n,0,8)) - -- else - -- -- return int4tag .. tointeger4(n) - -- return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) - -- end - -- end - - todictoffset = function(n) - return int4tag .. tointeger4(n) - end - - local e = false - local z = byte("0") - local dp = 10 - local ep = 11 - local em = 12 - local mn = 14 - local es = 15 - - local fg = formatters["%g"] - - todictreal = function(v) - local s = fg(v) - local t = { [0] = realtag } - local n = 0 - for s in gmatch(s,".") do - if s == "e" or s == "E" then - e = true - elseif s == "+" then - -- skip - elseif s == "-" then - n = n + 1 - if e then - t[n] = em - e = false - else - t[n] = mn - end - else - if e then - n = n + 1 - t[n] = ep - e = false - end - n = n + 1 - if s == "." then - t[n] = dp - else - t[n] = byte(s) - z - end - end - end - n = n + 1 - t[n] = es - if (n % 2) ~= 0 then - n = n + 1 - t[n] = es - end - local j = 0 - for i=1,n,2 do - j = j + 1 - t[j] = char(t[i]*0x10+t[i+1]) - end - t = concat(t,"",0,j) - return t - end - - todictnumber = function(n) - if not n or n == 0 then - return todictinteger(0) - elseif (n > maxnum or n < minnum or (abs(n - round(n)) > epsilon)) then - return todictreal(n) - else - return todictinteger(n) - end - end - - end - - local todictkey = char - - local function todictstring(fontfile,value) - if not value then - value = "" - end - local s = fontfile.cffstrings - local h = fontfile.cffhash - local n = h[value] - if not n then - n = #s + 1 - s[n] = value - h[value] = n - end - return todictinteger(390+n) - end - - local function todictboolean(b) - return todictinteger(b and 1 or 0) - end - - local function todictdeltas(t) - local r = { } - for i=1,#t do - r[i] = todictnumber(t[i]-(t[i-1] or 0)) - end - return concat(r) - end - - local function todictarray(t) - local r = { } - for i=1,#t do - r[i] = todictnumber(t[i]) - end - return concat(r) - end - - local function writestring(target,source,offset,what) - target[#target+1] = source - -- report_fonts("string : %-11s %06i # %05i",what,offset,#source) - return offset + #source - end - - local function writetable(target,source,offset,what) - source = concat(source) - target[#target+1] = source - -- report_fonts("table : %-11s %06i # %05i",what,offset,#source) - return offset + #source - end - - local function writeindex(target,source,offset,what) - local n = #source - local t = #target - t = t + 1 ; target[t] = tocardinal2(n) - if n > 0 then - local data = concat(source) - local size = #data -- assume the worst - local offsetsize, tocardinal - if size < 0xFF then - offsetsize, tocardinal = 1, tocardinal1 - elseif size < 0xFFFF then - offsetsize, tocardinal = 2, tocardinal2 - elseif size < 0xFFFFFF then - offsetsize, tocardinal = 3, tocardinal3 - elseif size < 0xFFFFFFFF then - offsetsize, tocardinal = 4, tocardinal4 - end - -- report_fonts("index : %-11s %06i # %05i (%i entries with offset size %i)",what,offset,#data,n,offsetsize) - offset = offset + 2 + 1 + (n + 1) * offsetsize + size - -- bytes per offset - t = t + 1 ; target[t] = tocardinal1(offsetsize) - -- list of offsets (one larger for length calculation) - local offset = 1 -- mandate - t = t + 1 ; target[t] = tocardinal(offset) - for i=1,n do - offset = offset + #source[i] - t = t + 1 ; target[t] = tocardinal(offset) - end - t = t + 1 ; target[t] = data - else - -- report_fonts("index : %-11s %06i # %05i (no entries)",what,offset,0) - offset = offset + 2 - end - -- print("offset",offset,#concat(target)) - return offset - end - - tablewriters.cff = function(fontfile) - -- - local streams = fontfile.streams - local cffinfo = streams.cffinfo or { } - local names = streams.names or { } - local fontheader = streams.fontheader or { } - local basefontname = fontfile.basefontname - -- - local offset = 0 - local dictof = 0 - local target = { } - -- - local charstrings = fontfile.charstrings - local nofglyphs = #charstrings + 1 - local fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 } -- todo - local fontbbox = fontfile.fontbbox - local defaultwidth = cffinfo.defaultwidth or 0 - local nominalwidth = cffinfo.nominalwidth or 0 - local bluevalues = cffinfo.bluevalues - local otherblues = cffinfo.otherblues - local familyblues = cffinfo.familyblues - local familyotherblues = cffinfo.familyotherblues - local bluescale = cffinfo.bluescale - local blueshift = cffinfo.blueshift - local bluefuzz = cffinfo.bluefuzz - local stdhw = cffinfo.stdhw - local stdvw = cffinfo.stdvw - -- - if defaultwidth == 0 then defaultwidth = nil end - if nomimalwidth == 0 then nominalwidth = nil end - if bluevalues then bluevalues = todictarray(bluevalues) end - if otherblues then otherblues = todictarray(otherblues) end - if familyblues then familyblues = todictarray(familyblues) end - if familyotherblues then familyotherblues = todictarray(familyotherblues) end - if bluescale then bluescale = todictnumber(bluescale) end - if blueshift then blueshift = todictnumber(blueshift) end - if bluefuzz then bluefuzz = todictnumber(bluefuzz) end - if stdhw then stdhw = todictdeltas(stdhw) end - if stdvw then stdvw = todictdeltas(stdvw) end - -- - local fontversion = todictstring(fontfile,fontheader.fontversion or "uknown version") - local familyname = todictstring(fontfile,cffinfo.familyname or names.family or basefontname) - local fullname = todictstring(fontfile,cffinfo.fullname or basefontname) - local weight = todictstring(fontfile,cffinfo.weight or "Normal") - local fontbbox = todictarray(fontbbox) - local strokewidth = todictnumber(cffinfo.strokewidth) - local monospaced = todictboolean(cffinfo.monospaced) - local italicangle = todictnumber(cffinfo.italicangle) - local underlineposition = todictnumber(cffinfo.underlineposition) - local underlinethickness = todictnumber(cffinfo.underlinethickness) - local charstringtype = todictnumber(2) - local fontmatrix = todictarray(fontmatrix) - local ros = todictstring(fontfile,"Adobe") -- registry - .. todictstring(fontfile,"Identity") -- identity - .. todictnumber(0) -- supplement - local cidcount = todictnumber(fontfile.nofglyphs) - local fontname = todictstring(fontfile,basefontname) - local fdarrayoffset = todictoffset(0) - local fdselectoffset = todictoffset(0) - local charstringoffset = todictoffset(0) - local charsetoffset = todictoffset(0) - local privateoffset = todictoffset(0) - -- - local defaultwidthx = todictnumber(defaultwidth) - local nominalwidthx = todictnumber(nominalwidth) - local private = "" - .. (defaultwidthx and (defaultwidthx .. todictkey(20)) or "") - .. (nominalwidthx and (nominalwidthx .. todictkey(21)) or "") - .. (bluevalues and (bluevalues .. todictkey(6)) or "") - .. (otherblues and (otherblues .. todictkey(7)) or "") - .. (familyblues and (familyblues .. todictkey(8)) or "") - .. (familyotherblues and (familyotherblues .. todictkey(9)) or "") - .. (bluescale and (bluescale .. todictkey(12,9)) or "") - .. (blueshift and (blueshift .. todictkey(12,10)) or "") - .. (bluefuzz and (bluefuzz .. todictkey(12,11)) or "") - .. (stdhw and (stdhw .. todictkey(12,12)) or "") - .. (stdvw and (stdvw .. todictkey(12,13)) or "") - local privatesize = todictnumber(#private) - local privatespec = privatesize .. privateoffset - -- - -- header (fixed @ 1) - -- - local header = - tocardinal1(1) -- major - .. tocardinal1(0) -- minor - .. tocardinal1(4) -- header size - .. tocardinal1(4) -- offset size - -- - offset = writestring(target,header,offset,"header") - -- - -- name index (fixed @ 2) (has to be sorted) - -- - local names = { - basefontname, - } - -- - offset = writeindex(target,names,offset,"names") - -- - -- topdict index (fixed @ 3) - -- - local topvars = - charstringoffset .. todictkey(17) - .. charsetoffset .. todictkey(15) - .. fdarrayoffset .. todictkey(12,36) - .. fdselectoffset .. todictkey(12,37) - .. privatespec .. todictkey(18) - -- - local topdict = { - ros .. todictkey(12,30) -- first - .. cidcount .. todictkey(12,34) - .. familyname .. todictkey( 3) - .. fullname .. todictkey( 2) - .. weight .. todictkey( 4) - .. fontbbox .. todictkey( 5) - .. monospaced .. todictkey(12, 1) - .. italicangle .. todictkey(12, 2) - .. underlineposition .. todictkey(12, 3) - .. underlinethickness .. todictkey(12, 4) - .. charstringtype .. todictkey(12, 6) - .. fontmatrix .. todictkey(12, 7) - .. strokewidth .. todictkey(12, 8) - .. topvars - } - -- - offset = writeindex(target,topdict,offset,"topdict") - dictof = #target - -- - -- string index (fixed @ 4) - -- - offset = writeindex(target,fontfile.cffstrings,offset,"strings") - -- - -- global subroutine index (fixed @ 5) - -- - offset = writeindex(target,{},offset,"globals") - -- - -- Encoding (cff1) - -- - -- offset = writeindex(target,{},offset,"encoding") - -- - -- Charsets - -- - charsetoffset = todictoffset(offset) - offset = writetable(target,fontfile.charmappings,offset,"charsets") - -- - -- fdselect - -- - local fdselect = - tocardinal1(3) -- format - .. tocardinal2(1) -- n of ranges - -- entry 1 - .. tocardinal2(0) -- first gid - .. tocardinal1(0) -- fd index - -- entry 2 --- .. tocardinal2(fontfile.sparsemax-1) -- sentinel - .. tocardinal2(fontfile.sparsemax) -- sentinel - -- - fdselectoffset = todictoffset(offset) - offset = writestring(target,fdselect,offset,"fdselect") - -- - -- charstrings - -- - charstringoffset = todictoffset(offset) - offset = writeindex(target,charstrings,offset,"charstrings") - -- - -- font dict - -- - -- offset = writeindex(target,{},offset,"fontdict") - -- - -- private - -- - privateoffset = todictoffset(offset) - privatespec = privatesize .. privateoffset - offset = writestring(target,private,offset,"private") - -- - local fdarray = { - fontname .. todictkey(12,38) - .. privatespec .. todictkey(18) - } - fdarrayoffset = todictoffset(offset) - offset = writeindex(target,fdarray,offset,"fdarray") - -- - topdict = target[dictof] - topdict = sub(topdict,1,#topdict-#topvars) - topvars = - charstringoffset .. todictkey(17) - .. charsetoffset .. todictkey(15) - .. fdarrayoffset .. todictkey(12,36) - .. fdselectoffset .. todictkey(12,37) - .. privatespec .. todictkey(18) - target[dictof] = topdict .. topvars - -- - target = concat(target) - -- if trace_details then - -- local name = "temp.cff" - -- report_fonts("saving %a",name) - -- io.savedata(name,target) - -- inspect(fonts.handlers.otf.readers.cffcheck(name)) - -- end - return target - end - - end - - -- todo: check widths (missing a decimal) - - mainwriters["opentype"] = function(details) - -- - local fontfile = openfontfile(details) - local basefontname = details.basefontname - local streams = details.streams - local blobs = streams.streams - local fontheader = streams.fontheader - local maximumprofile = streams.maximumprofile - local names = streams.names - local descriptions = details.rawdata.descriptions - local metadata = details.rawdata.metadata - local indices = details.indices - local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } - local correction = 1 - - -- (*) We share code with type1 and when we have old school tfm with - -- pfb but without descriptions we're kind of toast. - - if not descriptions or not next(descriptions) then - -- This is good enough, we only need indices and widths. - descriptions = details.fontdata.characters - -- This is a hack, we have no basepoints. - correction = details.fontdata.parameters.size / 1000 - -- And this needs checking. - correction = correction * bpfactor / ptfactor - metadata = { } - end - - -- - - local indices, - minindex, - maxindex = collectindices(descriptions,indices) - local streamoffset = 0 - local glyphstreams, - charmappings = tablecreators.cff(fontfile) - -- - local zero2 = tocardinal2(0) - local zero4 = tocardinal4(0) - -- - -- we need to locate notdef (or store its unicode someplace) - -- - local blob = blobs[0] or "\14" - local sparsemax = 1 - local lastoffset = zero4 - glyphstreams[sparsemax] = blob - charmappings[sparsemax] = tocardinal1(0) -- format 0 - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - if minindex == 0 then - minindex = 1 - end - for index=minindex,maxindex do - if indices[index] then - local blob = blobs[index] or "\14" - sparsemax = sparsemax + 1 - glyphstreams[sparsemax] = blob - charmappings[sparsemax] = tocardinal2(index) - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - end - end - -- - fontfile.nofglyphs = maxindex + 1 - fontfile.sparsemax = sparsemax - fontfile.format = "cff" - fontfile.basefontname = basefontname - fontfile.fontbbox = metabbox - -- - local fontdata = tablewriters.cff(fontfile) - local fontmeta = makemetadata(fontfile) - -- - fontfile = closefontfile(fontfile) - -- - local units = fontheader.units or metadata.units - - local basefont = pdfconstant(basefontname) - local widths = widtharray(details,indices,maxindex,units * correction) - local object = details.objectnumber - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) - local tocidset = tocidsetdictionary(indices,minindex,maxindex) - local fontbbox = pdfarray { unpack(metabbox) } - local ascender = metadata.ascender or 0 - local descender = metadata.descender or 0 - local capheight = metadata.capheight or fontbbox[4] - local stemv = metadata.weightclass - local italicangle = metadata.italicangle - local xheight = metadata.xheight or fontbbox[4] - if stemv then - stemv = (stemv/65)^2 + 50 - else --- stemv = 2 - end - -- - local function scale(n) - if n then - return round((n) * 10000 / units) / 10 - else - return 0 - end - end - -- - local reserved = pdfreserveobject() - local child = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("CIDFontType0"), - BaseFont = basefont, - FontDescriptor = pdfreference(reserved), - W = pdfreference(pdfflushobject(widths)), - CIDSystemInfo = pdfdictionary { - Registry = pdfstring("Adobe"), - Ordering = pdfstring("Identity"), - Supplement = 0, - } - } - local descendants = pdfarray { - pdfreference(pdfflushobject(child)), - } - local fontstream = pdfdictionary { - Subtype = pdfconstant("CIDFontType0C"), - } - local descriptor = pdfdictionary { - Type = pdfconstant("FontDescriptor"), - FontName = basefont, - Flags = 4, - FontBBox = fontbbox, - Ascent = scale(ascender), - Descent = scale(descender), - ItalicAngle = round(italicangle or 0), - CapHeight = scale(capheight), - StemV = scale(stemv), - XHeight = scale(xheight), - CIDSet = tocidset, - FontFile3 = pdfreference(pdfflushstreamobject(fontdata,fontstream())), - Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type0"), - Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), - BaseFont = basefont, - DescendantFonts = descendants, - ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(reserved,descriptor) - pdfflushobject(object,parent) - end - - mainwriters["type1"] = function(details) - -- We abuse the cff includer which is ok but for special cases like - -- tfm -> pfb we don't have the right descriptions and scale so this - -- is why we cheat elsewhere. Maybe I should just drop that kind of - -- support and assume afm files to be present. See (*) above. - local s = details.streams - local m = details.rawdata.metadata - if m then - local h = s.horizontalheader - local c = s.cffinfo - local n = s.names - h.ascender = m.ascender or h.ascender - h.descender = m.descender or h.descender - n.copyright = m.copyright or n.copyright - n.family = m.familyname or n.familyname - n.fullname = m.fullname or n.fullname - n.fontname = m.fontname or n.fontname - n.subfamily = m.subfamilyname or n.subfamilyname - n.version = m.version or n.version - setmetatableindex(h,m) - setmetatableindex(c,m) - setmetatableindex(n,m) - end - mainwriters["opentype"](details) - end - - do - - -- The methods might become plugins. - - local methods = { } - - local pdfimage = lpdf.epdf.image - local openpdf = pdfimage.open - local closepdf = pdfimage.close - local copypage = pdfimage.copy - - local embedimage = images.embed - - local f_glyph = formatters["G%d"] - local f_char = formatters["BT /V%d 1 Tf [<%04X>] TJ ET"] - local f_width = formatters["%.6N 0 d0"] - local f_index = formatters["I%d"] - local f_image_xy = formatters["%.6N 0 d0 1 0 0 1 %.6N %.6N cm /%s Do"] - local f_image_c = formatters["/%s Do"] - local f_image_c_xy = formatters["%.6N 0 0 %.6N %.6N %.6N cm /%s Do"] - local f_image_w = formatters["%.6N 0 d0 %s"] - local f_image_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm /%s Do"] - local f_stream = formatters["%.6N 0 d0 %s"] - local f_stream_c = formatters["%.6N 0 0 0 0 0 d1 %s"] - local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm %s"] - - -- A type 3 font has at most 256 characters and Acrobat also wants a zero slot - -- to be filled. We can share a mandate zero slot character. We also need to - -- make sure that we use bytes as index in the page stream as well as in the - -- tounicode vector. - - local c_notdef = nil - local r_notdef = nil - local w_notdef = nil - local fontbbox = nil - - -- pk inclusion (not really tested but not really used either) - - function methods.pk(filename) - local pkfullname = resolvers.findpk(basedfontname,resolution) - if not pkfullname or pkfullname == "" then - return - end - local readers = fonts.handlers.tfm.readers - local result = readers.loadpk(pkfullname) - local convert = readers.pktopdf - if not result or result.error then - return - end - local resolution = 600 - local widthfactor = resolution / 72 - local scalefactor = 72 / resolution / 10 - local factor = widthfactor / 65536 - local function pktopdf(glyph,data) - return convert(glyph,data,factor) -- return pdfcode, width - end - return result.glyphs, scalefactor, pktopdf, false, false - end - - -- pdf inclusion - - local used = setmetatableindex("table") - - function methods.pdf(filename,details) - local properties = details.properties - local pdfshapes = properties.indexdata[1] - local pdfdoc = openpdf(pdfshapes.filename) - local xforms = pdfdictionary() - local nofglyphs = 0 - if pdfdoc then - local scale = 10 * details.parameters.size/details.parameters.designsize - local units = details.parameters.units - local factor = units * bpfactor / scale - local fixdepth = pdfshapes.fixdepth - local useddoc = used[pdfdoc] - local function pdftopdf(glyph,data) - local width = (data.width or 0) * factor - local image = useddoc[glyph] - local reference = nil - if not image then - image = embedimage(copypage(pdfdoc,glyph)) - nofglyphs = nofglyphs + 1 - local name = f_glyph(nofglyphs) - local stream = nil - if fixdepth then - local depth = data.depth or 0 - local height = data.height or 0 - if depth ~= 0 or height ~= 0 then - local d = data.dropin.descriptions[data.index] - local b = d.boundingbox - local l = b[1] - local r = b[3] - local w = r - l - local scale = w / d.width - local x = l - local y = - b[4] - b[2] - d.depth - local scale = w / (image.width * bpfactor) - stream = f_image_c_xy(scale,scale,x,y,name) - else - stream = f_image_c(name) - end - else - stream = f_image_c(name) - end - useddoc[glyph] = image - image.embedded_name = name - image.embedded_stream = stream - image.embedded_reference = pdfreference(image.objnum) - end - xforms[image.embedded_name] = image.embedded_reference - return f_image_w(width,image.embedded_stream), width - end - local function closepdf() - -- closepdf(pdfdoc) - end - local function getresources() - return pdfdictionary { XObject = xforms } - end - return pdfshapes, 1/units, pdftopdf, closepdf, getresources - end - end - - -- mps inclusion - - local decompress = gzip.decompress - local metapost = metapost - local simplemprun = metapost.simple - local setparameterset = metapost.setparameterset - - function methods.mps(filename,details) - local properties = details.properties - local parameters = details.parameters - local mpshapes = properties.indexdata[1] -- indexdata will change - if mpshapes then - local scale = 10 * parameters.size/parameters.designsize - local units = mpshapes.units or parameters.units - local factor = units * bpfactor / scale - local fixdepth = mpshapes.fixdepth - local usecolor = mpshapes.usecolor - local specification = mpshapes.specification or { } - local shapedefinitions = mpshapes.shapes - local instance = mpshapes.instance - -- - simplemprun(instance,"begingroup;",true,true) - setparameterset("mpsfont",specification) - specification.scale = specification.scale or scale - specification.parameters = parameters - specification.properties = properties - specification.parentdata = details.fontdata.parentdata - -------------.characters = details.fontdata.characters - -------------.descriptions = details.fontdata.descriptions - if shapedefinitions then - local preamble = shapedefinitions.parameters.preamble - if preamble then - simplemprun(instance,preamble,true,true) - end - end - -- - local function mpstopdf(mp,data) - local width = data.width - if decompress then - mp = decompress(mp) - end - local pdf = simplemprun(instance,mp,true) -- can be sped up, minifun - local width = width * factor - if usecolor then - return f_stream_c(width,pdf), width - elseif fixdepth then - local depth = data.depth or 0 - local height = data.height or 0 - if depth ~= 0 or height ~= 0 then - return f_stream_d(width,(-height-depth)*factor,pdf), width - end - end - return f_stream(width,pdf), width - end - -- - local function resetmps() - setparameterset("mpsfont") - simplemprun(instance,"endgroup;",true,true) - specification.parameters = nil - specification.properties = nil - specification.parentdata = nil - -------------.characters = nil - -------------.descriptions = nil - end - -- - local function getresources() - return lpdf.collectedresources { - serialize = false, - } - end - -- - return mpshapes, 1/units, mpstopdf, resetmps, getresources - end - end - - -- png inclusion - - -- With d1 the image mask is used when given and obeys color. So it is needed for pure bw - -- bitmap fonts, so here we really need d0. - -- - -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat - -- reader crashes. We really need to add a notdef! - - local files = utilities.files - local openfile = files.open - local closefile = files.close - local setposition = files.setposition - local readstring = files.readstring - - function methods.png(filename,details) - local properties = details.properties - local pngshapes = properties.indexdata[1] - if pngshapes then - local parameters = details.parameters - local png = properties.png - local hash = png.hash - local xforms = pdfdictionary() - local nofglyphs = 0 - local scale = 10 * parameters.size/parameters.designsize - local factor = bpfactor / scale - -- local units = parameters.units -- / 1000 - local units = 1000 - local filehandle = openfile(details.filename,true) - local function pngtopdf(glyph,data) - -- local info = graphics.identifiers.png(glyph.data,"string") - local offset = glyph.o - local size = glyph.s - local pdfdata = nil - if offset and size then - setposition(filehandle,offset) - local blob = readstring(filehandle,size) - local info = graphics.identifiers.png(blob,"string") - info.enforcecmyk = pngshapes.enforcecmyk - local image = lpdf.injectors.png(info,"string") - local width = (data.width or 0) * factor - if image then - embedimage(image) - nofglyphs = nofglyphs + 1 - local xoffset = (glyph.x or 0) / units - local yoffset = (glyph.y or 0) / units - local name = f_glyph(nofglyphs) - xforms[name] = pdfreference(image.objnum) - pdfdata = f_image_xy(width,xoffset,yoffset,name) - end - end - return pdfdata or f_stream(width), width - end - local function closepng() - if filehandle then - closefile(filehandle) - end - pngshapes = nil - end - local function getresources() - return pdfdictionary { XObject = xforms } - end - return pngshapes, 1, pngtopdf, closepng, getresources - end - end - - function methods.color(filename,details) - local colrshapes = details.properties.indexdata[1] - local colrvalues = details.properties.indexdata[2] - local usedfonts = { } - local function colrtopdf(description,data) - -- descriptions by index - local colorlist = description.colors - if colorlist then - local dropdata = data.dropin - local dropid = dropdata.properties.id - local dropunits = dropdata.parameters.units -- shared - local descriptions = dropdata.descriptions - usedfonts[dropid] = dropid - local w = description.width or 0 - local s = #colorlist - local l = nil - local t = { f_width(w) } - local n = 1 - local d = colrvalues[#colrvalues] - for i=1,s do - local entry = colorlist[i] - local v = colrvalues[entry.class] or d - if v and l ~= v then - n = n + 1 ; t[n] = v - l = v - end - local e = descriptions[entry.slot] - if e then - n = n + 1 ; t[n] = f_char(dropid,e.index) - end - end - return concat(t," "), w / dropunits - end - end - local function getresources() - return lpdf.collectedresources { - serialize = false, - fonts = usedfonts, - fontprefix = "V", - } - end - return colrshapes, 1, colrtopdf, false, getresources - end - - mainwriters["type3"] = function(details) - local properties = details.properties - local basefontname = details.basefontname or properties.name - local askedmethod = properties.method or "pk" - local method = methods[askedmethod] or methods.pk - if not method then - return - end - local glyphs, scalefactor, glyphtopdf, reset, getresources = method(basedfontname,details) - if not glyphs then - return - end - local parameters = details.parameters - local object = details.objectnumber - local factor = parameters.factor -- normally 1 - local fontmatrix = pdfarray { scalefactor, 0, 0, scalefactor, 0, 0 } - local indices, - minindex, - maxindex = collectindices(details.fontdata.characters,details.indices) - local widths = pdfarray() - local differences = pdfarray() - local charprocs = pdfdictionary() - local basefont = pdfconstant(basefontname) - local d = 0 - local w = 0 - local forcenotdef = minindex > 0 - local lastindex = -0xFF - if forcenotdef then - widths[0] = 0 - minindex = 0 - lastindex = 0 - d = 2 - if not c_notdef then - w_notdef = 0 - c_notdef = pdfconstant(".notdef") - r_notdef = pdfreference(pdfflushstreamobject("0 0 d0")) - end - differences[1] = w_notdef - differences[2] = c_notdef - charprocs[".notdef"] = r_notdef - end - - for i=1,maxindex-minindex+1 do - widths[i] = 0 - end - - for index, data in sortedhash(indices) do - local name = f_index(index) - local glyph = glyphs[index] - if glyph then - local stream, width = glyphtopdf(glyph,data) - if stream then - if index - 1 ~= lastindex then - d = d + 1 differences[d] = index - end - lastindex = index - d = d + 1 differences[d] = pdfconstant(name) - charprocs[name] = pdfreference(pdfflushstreamobject(stream)) - widths[index-minindex+1] = width - end - else - report_fonts("missing glyph %i in type3 font %a",index,basefontname) - end - end - if not fontbbox then - -- The specification permits zero values and these are actually also more - -- robust as then there are no assumptions and no accuracy is needed. - fontbbox = pdfarray { 0, 0, 0, 0 } - end - local encoding = pdfdictionary { - Type = pdfconstant("Encoding"), - Differences = differences, - } - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,false) - local resources = getresources and getresources() - if not resources or not next(resources) then - -- resources = lpdf.procset(true) - resources = nil - end - local descriptor = pdfdictionary { - -- most is optional in type3 - Type = pdfconstant("FontDescriptor"), - FontName = basefont, - Flags = 4, - ItalicAngle = 0, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type3"), - Name = basefont, - FontBBox = fontbbox, - FontMatrix = fontmatrix, - CharProcs = pdfreference(pdfflushobject(charprocs)), - Encoding = pdfreference(pdfflushobject(encoding)), - FirstChar = minindex, - LastChar = maxindex, - Widths = pdfreference(pdfflushobject(widths)), - FontDescriptor = pdfreference(pdfflushobject(descriptor)), - Resources = resources, - ToUnicode = tounicode and pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(object,parent) - if reset then - reset() - end - end - - end - -end - --- writingmode - -local usedfonts = fonts.hashes.identifiers -- for now -local noffonts = 0 - --- The main injector. - --- here we need to test for sharing otherwise we reserve too many --- objects - -local getstreamhash = fonts.handlers.otf.getstreamhash -local loadstreamdata = fonts.handlers.otf.loadstreamdata - --- we can actually now number upwards (so not use fontid in /F) - -local objects = setmetatableindex(function(t,k) - local v - if type(k) == "number" then - local h = getstreamhash(k) - v = rawget(t,h) - if not v then - v = pdfreserveobject() - t[h] = v - end - if trace_fonts then - report_fonts("font id %i bound to hash %s and object %i",k,h,v) - end - else - -- no problem as it can be svg only - -- report_fonts("fatal error, hash %s asked but not used",k,h,v) - v = pdfreserveobject() - t[k] = v - end - return v -end) - -local n = 0 - -local names = setmetatableindex(function(t,k) - local v - if type(k) == "number" then - local h = getstreamhash(k) - v = rawget(t,h) - if not v then - n = n + 1 - v = n - t[h] = v - end - if trace_fonts then - report_fonts("font id %i bound to hash %s and name %i",k,h,n) - end - end - t[k] = v - return v -end) - -function lpdf.flushfonts() - - local mainfonts = { } - - statistics.starttiming(objects) - - for fontid, used in sortedhash(lpdf.usedcharacters) do - - -- for a bitmap we need a different hash unless we stick to a fixed high - -- resolution which makes much sense - - local hash = getstreamhash(fontid) - if hash then - local parent = mainfonts[hash] - if not parent then - local fontdata = usedfonts[fontid] - local rawdata = fontdata.shared and fontdata.shared.rawdata - local resources = fontdata.resources - local properties = fontdata.properties -- writingmode and type3 - local parameters = fontdata.parameters -- used in type3 - if not rawdata then - -- we have a virtual font that loaded directly ... at some point i will - -- sort this out (in readanddefine we need to do a bit more) .. the problem - -- is that we have a hybrid font then - for xfontid, xfontdata in next, fonts.hashes.identifiers do - if fontid ~= xfontid then - local xhash = getstreamhash(xfontid) - if hash == xhash then - rawdata = xfontdata.shared and xfontdata.shared.rawdata - if rawdata then - resources = xfontdata.resources - properties = xfontdata.properties - parameters = xfontdata.parameters - break - end - end - end - end - end - if rawdata then - parent = { - hash = hash, - fontdata = fontdata, - filename = resources.filename or properties.filename or "unset", - indices = { }, - rawdata = rawdata, - properties = properties, -- we assume consistency - parameters = parameters, -- we assume consistency - streams = { }, - objectnumber = objects[hash], - basefontname = subsetname(properties.psname or properties.name or "unset"), - name = names[hash], - } - mainfonts[hash] = parent - noffonts = noffonts + 1 - end - end - if parent then - local indices = parent.indices - for k in next, used do - indices[k] = true - end - end - end - end - - -- this is no not yet ok for tfm / type 1 .. we need to move the nested blobs ourside the loop - - for hash, details in sortedhash(mainfonts) do - local filename = details.filename - if next(details.indices) then - if trace_fonts then - report_fonts("embedding %a hashed as %a",filename,hash) - end - local properties = details.properties - local bitmap = properties.usedbitmap - local method = properties.method -- will be pk | pdf | svg | ... - if bitmap or method then - local format = "type3" - local writer = mainwriters[format] - if writer then - if trace_fonts then - report_fonts("using main writer %a",format) - end - writer(details) - end - else - local format = properties.format - local writer = mainwriters[format] - if not writer then - -- This will move to the tpk module where we will also deal - -- with bitmaps then. - local encoding, pfbfile, encfile = getmapentry(filename) - if trace_fonts then - report_fonts("file %a resolved to encoding %a and file %a",filename,encoding,pfbfile) - end - if encoding and pfbfile then - filename = pfbfile - format = "type1" - -- - -- another (temp) hack - local size = details.fontdata.parameters.size - local factor = details.fontdata.parameters.factor - local descriptions = { } - local characters = details.fontdata.characters - -- - local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) - local reverse = table.swapped(names) - local vector = encoding.vector - local indices = details.indices - local remapped = { } - local factor = bpfactor * size / 65536 - for k, v in next, indices do - local name = vector[k] - local index = reverse[name] or 0 - local width = factor * (characters[k].width or 0) - descriptions[k] = { - width = width, - index = index, - name = name, - } - remapped[index] = true - end - details.indices = remapped - -- - details.rawdata.descriptions = descriptions - details.filename = filename - details.rawdata.metadata = { } - -- - properties.filename = filename - properties.format = format - writer = mainwriters[format] - end - end - if not writer then - local pfbfile = file.replacesuffix(filename,"pfb") - if encoding and pfbfile then - filename = pfbfile - format = "type1" - -- - -- another (temp) hack - local size = details.fontdata.parameters.size - local factor = details.fontdata.parameters.factor - local descriptions = { } - local characters = details.fontdata.characters - -- - local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) - local reverse = table.swapped(names) - local vector = encoding.vector - local indices = details.indices - local remapped = { } - local factor = bpfactor * size / 65536 - for k, v in next, indices do - local name = vector[k] - local index = reverse[name] or 0 - local width = factor * (characters[k].width or 0) - descriptions[k] = { - width = width, - index = index, - name = name, - } - remapped[index] = true - end - details.indices = remapped - -- - details.rawdata.descriptions = descriptions - details.filename = filename - details.rawdata.metadata = { } - -- - properties.filename = filename - properties.format = format - writer = mainwriters[format] - end - end - if writer then - if trace_fonts then - report_fonts("using main writer %a",format) - end - -- better move this test to the writers .. cleaner - local streams = loadstreamdata(details.fontdata) - if streams and streams.fontheader and streams.names then - details.streams = streams - writer(details) - details.streams = { } - elseif trace_fonts then - -- can be ok for e.g. emoji - report_fonts("no streams in %a",filename) - end - -- free some memory - else -- if trace_fonts then - report_fonts("no %a writer for %a",format,filename) - end - end - else -- not problem for svg ... - -- report_fonts("no indices for %a",filename) - end - if trace_fonts then - report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) - end - mainfonts[details.hash] = false -- done - end - - statistics.stoptiming(objects) - -end - -statistics.register("font embedding time",function() - if noffonts > 0 then - return format("%s seconds, %s fonts", statistics.elapsedtime(objects),noffonts) - end -end) - --- this is temporary - -local done = false - -updaters.register("backend.update.pdf",function() - if not done then - function pdf.getfontobjnum (k) return objects[k] end - function pdf.getfontname (k) return names [k] end - function pdf.includechar () end -- maybe, when we need it - function pdf.includefont () end -- maybe, when we need it - function pdf.includecharlist () end -- maybe, when we need it - function pdf.setomitcidset (v) includecidset = not toboolean(v) end - function pdf.setomitcharset () end -- we don't need that in lmtx - function pdf.setsuppressoptionalinfo() end -- we don't need that in lmtx - function pdf.mapfile (n) loadmapfile(n) end - function pdf.mapline (n) loadmapline(n) end - -- this will change - lpdf.registerdocumentfinalizer(lpdf.flushfonts,1,"wrapping up fonts") - done = true - end -end) diff --git a/tex/context/base/mkiv/lpdf-img.lmt b/tex/context/base/mkiv/lpdf-img.lmt deleted file mode 100644 index fc53740f6..000000000 --- a/tex/context/base/mkiv/lpdf-img.lmt +++ /dev/null @@ -1,1341 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-img'] = { - version = 1.001, - optimize = true, - comment = "companion to lpdf-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This started as an experiment but has potential for some (cached) optimizations. --- At some point we can also use it for fonts. For small images performance is ok --- with pure lua but for bigger images we can use some helpers. Normally in a --- typesetting workflow non-interlaced images are used. One should convert --- interlaced images to more efficient non-interlaced ones (ok, we can cache --- them if needed). --- --- The \LUA\ code is slightly optimized so we could have done with less lines if --- we wanted but best gain a little. The idea is that we collect striped (in stages) --- so that we can play with substitutions. - -local type = type -local concat, move = table.concat, table.move -local ceil, min = math.ceil, math.min -local char, byte, find, gmatch = string.char, string.byte, string.find, string.gmatch -local idiv = number.idiv -local band, rshift = bit32.band, bit32.rshift - -local loaddata = io.loaddata -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters - -local streams = utilities.streams -local openstring = streams.openstring -local readstring = streams.readstring -local readbytetable = streams.readbytetable - -local newreader = io.newreader - -local tobytetable = string.bytetable - -local lpdf = lpdf or { } -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfconstant = lpdf.constant -local pdfstring = lpdf.string -local pdfflushstreamobject = lpdf.flushstreamobject -local pdfreference = lpdf.reference -local pdfverbose = lpdf.verbose - -local pdfmajorversion = lpdf.majorversion -local pdfminorversion = lpdf.minorversion - -local createimage = images.create - -local zlibcompress = (xzip or zlib).compress -local zlibdecompress = (xzip or zlib).decompress - -local trace = false - -local report_jpg = logs.reporter("graphics","jpg") -local report_jp2 = logs.reporter("graphics","jp2") -local report_png = logs.reporter("graphics","png") - -trackers.register("graphics.backend", function(v) trace = v end) - -local injectors = { } -lpdf.injectors = injectors - --- todo: load from a virtual file - -local function loadcontent(filename,method) - return method == "string" and filename or loaddata(filename) -end - -local function newcontent(filename,method) - return newreader(filename,method) -end - --- - -local chars = setmetatableindex(function(t,k) -- share this one - local v = (k <= 0 and "\000") or (k >= 255 and "\255") or char(k) - t[k] = v - return v -end) - -do - - function injectors.jpg(specification,method) - if specification.error then - return - end - local filename = specification.filename - if not filename then - return - end - local colorspace = specification.colorspace or jpg_gray - local decodearray = nil - ----- procset = colorspace == 0 and "image b" or "image c" - if colorspace == 1 then - colorspace = "DeviceGray" - elseif colorspace == 2 then - colorspace = "DeviceRGB" - elseif colorspace == 3 then - colorspace = "DeviceCMYK" - decodearray = pdfarray { 1, 0, 1, 0, 1, 0, 1, 0 } - end - -- todo: set filename - local xsize = specification.xsize - local ysize = specification.ysize - local colordepth = specification.colordepth - local content = loadcontent(filename,method) - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - -- BBox = pdfarray { 0, 0, xsize, ysize }, - Width = xsize, - Height = ysize, - BitsPerComponent = colordepth, - Filter = pdfconstant("DCTDecode"), - ColorSpace = pdfconstant(colorspace), - Decode = decodearray, - Length = #content, -- specification.length - } + specification.attr - if trace then - report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content) - end - return createimage { - bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate - transform = specification.transform, - nolength = true, - nobbox = true, - notype = true, - stream = content, - attr = xobject(), - } - end - -end - -do - - function injectors.jp2(specification,method) - if specification.error then - return - end - local filename = specification.filename - if not filename then - return - end - -- todo: set filename - local xsize = specification.xsize - local ysize = specification.ysize - local content = loadcontent(filename,method) - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - BBox = pdfarray { 0, 0, xsize, ysize }, - Width = xsize, - Height = ysize, - Filter = pdfconstant("JPXDecode"), - Length = #content, -- specification.length - } + specification.attr - if trace then - report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content) - end - return createimage { - bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate - transform = specification.transform, - nolength = true, - nobbox = true, - notype = true, - stream = content, - attr = xobject(), - } - end - -end - -do - - -- We don't like interlaced files. You can deinterlace them beforehand because otherwise - -- each run you add runtime. Actually, even masked images can best be converted to PDF - -- beforehand. - - -- The amount of code is larger that I like and looks somewhat redundant but we sort of - -- optimize a few combinations that happen often. - - local pngapplyfilter = pngdecode.applyfilter - local pngsplitmask = pngdecode.splitmask - local pnginterlace = pngdecode.interlace - local pngexpand = pngdecode.expand - local pngtocmyk = pngdecode.tocmyk - - local filtermask, decodemask, decodestrip, transpose, expand, tocmyk - - local newindex = lua.newindex - local newtable = lua.newtable - - local function newoutput(size) - if newindex then - return newindex(size,0) - end - local t = newtable and newtable(size,0) or { } - for i=1,size do - t[i] = 0 - end - return t - end - - local function convert(t) - if type(t) == "table" then - for i=1,#t do - local ti = t[i] - if ti ~= "" then -- soon gone - t[i] = chars[ti] - end - end - return concat(t) - else - return t - end - end - - local function zero(t,k) - return 0 - end - - local function applyfilter(t,xsize,ysize,bpp) - local len = xsize * bpp + 1 - local n = 1 - local m = len - 1 - for i=1,ysize do - local filter = t[n] - t[n] = "" - if filter == 0 then - elseif filter == 1 then - for j=n+bpp+1,n+m do - t[j] = (t[j] + t[j-bpp]) % 256 - end - elseif filter == 2 then - for j=n+1,n+m do - t[j] = (t[j] + t[j-len]) % 256 - end - elseif filter == 3 then - for j=n+1,n+bpp do - t[j] = (t[j] + idiv(t[j-len],2)) % 256 - end - for j=n+bpp+1,n+m do - t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256 - end - elseif filter == 4 then - for j=n+1,n+bpp do - local p = j - len - local b = t[p] - if b > 0 then - t[j] = (t[j] + b) % 256 - end - end - for j=n+bpp+1,n+m do - local p = j - len - local a = t[j-bpp] - local b = t[p] - local c = t[p-bpp] - local pa = b - c - local pb = a - c - local pc = pa + pb - if pa < 0 then pa = - pa end - if pb < 0 then pb = - pb end - if pc < 0 then pc = - pc end - t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 - end - end - n = n + len - end - return t - end - - local filtermask_l = function (content,xsize,ysize,colordepth,colorspace,hasfilter) - local mask = { } - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local length = #content - local size = ysize * xsize * ((bpp+1)*bytes + (hasfilter and 1 or 0)) - local n = 1 - local l = 1 - if bytes == 2 then - if bpp == 1 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - elseif bpp == 3 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - else - return "", "" - end - else - if bpp == 1 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - elseif bpp == 3 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - else - return "", "" - end - end - return concat(content), concat(mask) - end - - local decodemask_l = function(content,xsize,ysize,colordepth,colorspace) - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local slice = bytes*(bpp+1) - local length = #content - local size = ysize * xsize * ((bpp+1)*bytes + 1) -- assume filter - content = openstring(content) - content = readbytetable(content,length) - setmetatableindex(content,zero) - applyfilter(content,xsize,ysize,slice) - content, mask = filtermask(content,xsize,ysize,colordepth,colorspace,true) - return content, mask - end - - local filtermask_c = function(content,xsize,ysize,colordepth,colorspace) - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - return pngsplitmask(content,xsize,ysize,bpp,bytes) - end - - local decodemask_c = function(content,xsize,ysize,colordepth,colorspace) - local mask = true - local filter = false - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local slice = bytes * (bpp + 1) -- always a mask - content = pngapplyfilter(content,xsize,ysize,slice) - return pngsplitmask(content,xsize,ysize,bpp,bytes,mask,filter) - end - - local function decodestrip_l(s,nx,ny,slice) - local input = readbytetable(s,ny*(nx*slice+1)) - setmetatableindex(input,zero) - applyfilter(input,nx,ny,slice) - return input, true - end - - local function decodestrip_c(s,nx,ny,slice) - local input = readstring(s,ny*(nx*slice+1)) - input = pngapplyfilter(input,nx,ny,slice) - return input, false - end - - local xstart = { 0, 4, 0, 2, 0, 1, 0 } - local ystart = { 0, 0, 4, 0, 2, 0, 1 } - local xstep = { 8, 8, 4, 4, 2, 2, 1 } - local ystep = { 8, 8, 8, 4, 4, 2, 2 } - - local xblock = { 8, 4, 4, 2, 2, 1, 1 } - local yblock = { 8, 8, 4, 4, 2, 2, 1 } - - local function transpose_l(xsize,ysize,slice,pass,input,output,filter) - local xstart = xstart[pass] - local xstep = xstep[pass] - local ystart = ystart[pass] - local ystep = ystep[pass] - local nx = idiv(xsize + xstep - xstart - 1,xstep) - local ny = idiv(ysize + ystep - ystart - 1,ystep) - local offset = filter and 1 or 0 - local xstep = xstep * slice - local xstart = xstart * slice - local xsize = xsize * slice - local target = ystart * xsize + xstart + 1 - local ystep = ystep * xsize - local start = 1 - local plus = nx * xstep - local step = plus - xstep - if not output then - output = newoutput(xsize*(parts or slice)*ysize) - end - if slice == 1 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - start = start + slice - end - end - elseif slice == 2 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - start = start + slice - end - end - elseif slice == 3 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - output[target+2] = input[start+2] - start = start + slice - end - end - elseif slice == 4 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - output[target+2] = input[start+2] - output[target+3] = input[start+3] - start = start + slice - end - end - else - local delta = slice - 1 - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - move(input,start,start+delta,target,output) - start = start + slice - end - end - end - return output; - end - - local transpose_c = pnginterlace - - -- print(band(rshift(v,4),0x03),extract(v,4,2)) - -- print(band(rshift(v,6),0x03),extract(v,6,2)) - - local function expand_l(t,xsize,ysize,parts,run,factor,filter) - local size = ysize * xsize + 1 -- a bit of overshoot, needs testing, probably a few bytes us ok - local xline = filter and (run+1) or run - local f = filter and 1 or 0 - local l = xline - 1 - local n = 1 - local o = newoutput(size) - local k = 0 - if factor then - if parts == 4 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 2 - else - k = k + 1 ; o[k] = extract4(v,4) * 0x11 - k = k + 1 ; o[k] = extract4(v,0) * 0x11 - end - end - k = i * xsize - n = n + xline - end - elseif parts == 2 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 4 - else - k = k + 1 ; o[k] = extract2(v,6) * 0x55 - k = k + 1 ; o[k] = extract2(v,4) * 0x55 - k = k + 1 ; o[k] = extract2(v,2) * 0x55 - k = k + 1 ; o[k] = extract2(v,0) * 0x55 - end - end - k = i * xsize - n = n + xline - end - else - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 8 - else - k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,7) * 0xFF - k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,6) * 0xFF - k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,5) * 0xFF - k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,4) * 0xFF - k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,3) * 0xFF - k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,2) * 0xFF - k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,1) * 0xFF - k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,0) * 0xFF - end - end - k = i * xsize - n = n + xline - end - end - else - if parts == 4 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 2 - else - k = k + 1 ; o[k] = extract4(v,4) - k = k + 1 ; o[k] = extract4(v,0) - end - end - k = i * xsize - n = n + xline - end - elseif parts == 2 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 4 - else - k = k + 1 ; o[k] = extract2(v,6) - k = k + 1 ; o[k] = extract2(v,4) - k = k + 1 ; o[k] = extract2(v,2) - k = k + 1 ; o[k] = extract2(v,0) - end - end - k = i * xsize - n = n + xline - end - else - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 8 - else - k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,7) - k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,6) - k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,5) - k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,4) - k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,3) - k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,2) - k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,1) - k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,0) - end - end - k = i * xsize - n = n + xline - end - end - end - for i=size,xsize * ysize +1,-1 do - o[i] = nil - end - return o, false - end - - local expand_c = pngexpand - - local function analyze(colordepth,colorspace,palette,mask) - -- return bytes, parts, factor - if palette then - if colordepth == 16 then - return 2, false, false - elseif colordepth == 8 then - return 1, false, false - elseif colordepth == 4 then - return 1, 4, false - elseif colordepth == 2 then - return 1, 2, false - elseif colordepth == 1 then - return 1, 1, false - end - elseif colorspace == "DeviceGray" then - if colordepth == 16 then - return mask and 4 or 2, false, false - elseif colordepth == 8 then - return mask and 2 or 1, false, false - elseif colordepth == 4 then - return 1, 4, true - elseif colordepth == 2 then - return 1, 2, true - elseif colordepth == 1 then - return 1, 1, true - end - else - if colordepth == 16 then - return mask and 8 or 6, false, false - elseif colordepth == 8 then - return mask and 4 or 3, false, false - elseif colordepth == 4 then - return 3, 4, true - elseif colordepth == 2 then - return 3, 2, true - elseif colordepth == 1 then - return 3, 1, true - end - end - return false, false, false - end - - -- 1 6 4 6 2 6 4 6 - -- 7 7 7 7 7 7 7 7 - -- 5 6 5 6 5 6 5 6 - -- 7 7 7 7 7 7 7 7 - -- 3 6 4 6 3 6 4 6 - -- 7 7 7 7 7 7 7 7 - -- 5 6 5 6 5 6 5 6 - -- 7 7 7 7 7 7 7 7 - - local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) - local slice, parts, factor = analyze(colordepth,colorspace,palette,mask) - if slice then - content = openstring(zlibdecompress(content)) - local filter = false - local output = false - for pass=1,7 do - local xstart = xstart[pass] - local xstep = xstep[pass] - local ystart = ystart[pass] - local ystep = ystep[pass] - local nx = idiv(xsize + xstep - xstart - 1,xstep) - local ny = idiv(ysize + ystep - ystart - 1,ystep) - if nx > 0 and ny > 0 then - local input, filter - if parts then - local nxx = ceil(nx*parts/8) - input, filter = decodestrip(content,nxx,ny,slice) - input, filter = expand(input,nx,ny,parts,nxx,factor,filter) - else - input, filter = decodestrip(content,nx,ny,slice) - end - output = transpose(xsize,ysize,slice,pass,input,output,filter) - end - -- if pass == 3 then - -- break -- still looks ok, could be nice for a preroll - -- end - end - return output, parts and 8 or false - end - end - - -- 1 (palette used), 2 (color used), and 4 (alpha channel used) - - -- paeth: - -- - -- p = a + b - c - -- pa = abs(p - a) => a + b - c - a => b - c - -- pb = abs(p - b) => a + b - c - b => a - c - -- pc = abs(p - c) => a + b - c - c => a + b - c - c => a - c + b - c => pa + pb - - local function full(t,k) local v = "\xFF" t[k] = v return v end - - local function expandvector(transparent) - local s = openstring(transparent) - local n = #transparent - local r = { } - for i=0,n-1 do - r[i] = readstring(s,1) -- readchar - end - setmetatableindex(r,full) - return r - end - - local function createmask_l(content,palette,transparent,xsize,ysize,colordepth,colorspace) - if palette then - local r = expandvector(transparent) - local size = xsize*ysize - local len = ceil(xsize*colordepth/8) + 1 - local o = newoutput(xsize*ysize) - local u = setmetatableindex(zero) - content = zlibdecompress(content) - content = openstring(content) - for i=0,ysize-1 do - local t = readbytetable(content,len) - local k = i * xsize - local filter = t[1] - if filter == 0 then - elseif filter == 1 then - for j=3,len do - t[j] = (t[j] + t[j-1]) % 256 - end - elseif filter == 2 then - for j=2,len do - t[j] = (t[j] + u[j]) % 256 - end - elseif filter == 3 then - local j = 2 - t[j] = (t[j] + idiv(u[j],2)) % 256 - for j=3,len do - t[j] = (t[j] + idiv(t[j-1] + u[j],2)) % 256 - end - elseif filter == 4 then - local j = 2 - local p = j - len - local b = t[p] - if b < 0 then - b = - b - end - if b > 0 then - t[j] = (t[j] + b) % 256 - end - for j=3,len do - local p = j - len - local a = t[j-1] - local b = t[p] - local c = t[p-1] - local pa = b - c - local pb = a - c - local pc = pa + pb - if pa < 0 then pa = - pa end - if pb < 0 then pb = - pb end - if pc < 0 then pc = - pc end - t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 - end - end - if colordepth == 8 then - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[v] - end - elseif colordepth == 4 then - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract4(v,4)] - k = k + 1 ; o[k] = r[extract4(v,0)] - end - elseif colordepth == 2 then - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract2(v,6)] - k = k + 1 ; o[k] = r[extract2(v,4)] - k = k + 1 ; o[k] = r[extract2(v,2)] - k = k + 1 ; o[k] = r[extract2(v,0)] - end - else - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract1(v,7)] - k = k + 1 ; o[k] = r[extract1(v,6)] - k = k + 1 ; o[k] = r[extract1(v,5)] - k = k + 1 ; o[k] = r[extract1(v,4)] - k = k + 1 ; o[k] = r[extract1(v,3)] - k = k + 1 ; o[k] = r[extract1(v,2)] - k = k + 1 ; o[k] = r[extract1(v,1)] - k = k + 1 ; o[k] = r[extract1(v,0)] - end - end - u = t - end - return concat(o,"",1,size) - end - end - - local function createmask_c(content,palette,transparent,xsize,ysize,colordepth,colorspace) - if palette then - local r = expandvector(transparent) - local size = xsize*ysize - local len = ceil(xsize*colordepth/8) - local o = newoutput(size) - content = zlibdecompress(content) - content = pngapplyfilter(content,len,ysize,1) -- nostrip (saves copy) - content = openstring(content) - for i=0,ysize-1 do - local t = readbytetable(content,len) - local k = i * xsize - if colordepth == 8 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[v] - end - elseif colordepth == 4 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract4(v,4)] - k = k + 1 ; o[k] = r[extract4(v,0)] - end - elseif colordepth == 2 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract2(v,6)] - k = k + 1 ; o[k] = r[extract2(v,4)] - k = k + 1 ; o[k] = r[extract2(v,2)] - k = k + 1 ; o[k] = r[extract2(v,0)] - end - else - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract1(v,7)] - k = k + 1 ; o[k] = r[extract1(v,6)] - k = k + 1 ; o[k] = r[extract1(v,5)] - k = k + 1 ; o[k] = r[extract1(v,4)] - k = k + 1 ; o[k] = r[extract1(v,3)] - k = k + 1 ; o[k] = r[extract1(v,2)] - k = k + 1 ; o[k] = r[extract1(v,1)] - k = k + 1 ; o[k] = r[extract1(v,0)] - end - end - end - return concat(o,"",1,size) - end - end - - local function tocmyk_l(content,colordepth) - local l = #content - local t = { } - local n = 0 - if colordepth == 8 then - for i=1,l,3 do - local r, g, b = byte(content,i,i+2) - n = n + 1 ; t[n] = char(255-r,255-g,255-b,0) -- a tad faster than chars[...] - end - else - for i=1,l,6 do - local r1, r2, g1, g2, b1, b2 = byte(content,i,i+5) - n = n + 1 ; t[n] = char(255-r1,255-r2,255-g1,255-g2,255-b1,255-b2,0,0) - end - end - return concat(t) - end - - local tocmyk_c = pngtocmyk or tocmyk_l - - local function converttocmyk(content,colorspace,colordepth) - if colorspace == "DeviceRGB" and colordepth == 8 or colordepth == 16 then - local done = tocmyk(content,colordepth) - if done then - content = done - colorspace = "DeviceCMYK" - end - end - return content, colorspace - end - - local function switch(v) - if v then - filtermask = filtermask_l - decodemask = decodemask_l - decodestrip = decodestrip_l - transpose = transpose_l - expand = expand_l - createmask = createmask_l - tocmyk = tocmyk_l - else - filtermask = filtermask_c - decodemask = decodemask_c - decodestrip = decodestrip_c - transpose = transpose_c - expand = expand_c - createmask = createmask_c - tocmyk = tocmyk_c - end - end - - if pngapplyfilter then - switch(false) - directives.register("graphics.png.purelua",switch) - else - switch(true) - end - - local alwaysdecode = false -- trucky with palettes - local compresslevel = 3 - - directives.register("graphics.png.recompress", function(v) - alwaysdecode = v - end) - - directives.register("graphics.png.compresslevel", function(v) - v = tonumber(v) - if compresslevel >= 0 or compresslevel <= 9 then - compresslevel = v - end - end) - - function injectors.png(specification,method) -- todo: method in specification - if specification.error then - return - end - local filename = specification.filename - if not filename then - return - end - local colorspace = specification.colorspace - if not colorspace then - return - end - local interlace = specification.interlace or 0 - if interlace == 1 then - interlace = true - elseif interlace == 0 then - interlace = false - else - report_png("unknown interlacing %i",interlace) - return - end - local tables = specification.tables - if not tables then - return - end - local idat = tables.idat - if not idat then - return - end - local pngfile = newcontent(filename,method) - if not pngfile then - return - end - local content = idat(pngfile,true) - tables.idat = false - -- - -- if tables.gama then - -- report_png("ignoring gamma correction") - -- end - -- - local xsize = specification.xsize - local ysize = specification.ysize - local colordepth = specification.colordepth or 8 - local mask = false - local transparent = false - local palette = false - local enforcecmyk = specification.enforcecmyk - local colors = 1 - if colorspace == 0 then -- gray | image b - colorspace = "DeviceGray" - transparent = true - elseif colorspace == 2 then -- rgb | image c - colorspace = "DeviceRGB" - colors = 3 - transparent = true - elseif colorspace == 3 then -- palette | image c+i - colorspace = "DeviceRGB" - palette = true - transparent = true - elseif colorspace == 4 then -- gray | alpha | image b - colorspace = "DeviceGray" - mask = true - elseif colorspace == 6 then -- rgb | alpha | image c - colorspace = "DeviceRGB" - colors = 3 - mask = true - else - report_png("unknown colorspace %i",colorspace) - return - end - -- - if transparent then - local trns = tables.trns - if trns then - transparent = trns(pngfile,true) - if transparent == "" then - transparent = false - end - tables.trns = false - else - transparent = false - end - end - -- - local decode = alwaysdecode -- tricky, might go away - local filter = pdfconstant("FlateDecode") - local major = pdfmajorversion() - local minor = pdfminorversion() - if major > 1 then - -- we're okay - elseif minor < 5 and colordepth == 16 then - report_png("16 bit colordepth not supported in pdf < 1.5") - return - elseif minor < 4 and (mask or transparent) then - report_png("alpha channels not supported in pdf < 1.4") - return - elseif minor < 2 then - report_png("you'd better use a version > 1.2") - return - -- decode = true - end - -- - -- todo: compresslevel (or delegate) - -- - if palette then - local plte = tables.plte - if plte then - palette = plte(pngfile,true) - if palette == "" then - palette = false - end - tables.plte = false - else - palette = false - end - end - -- - if interlace then - local r, p = deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) - if not r then - return - end - if p then - colordepth = p - end - if mask then - if not (colordepth == 8 or colordepth == 16) then - report_png("mask can't be split from the image") - return - end -- get rid of bpp: - content, mask = filtermask(r,xsize,ysize,colordepth,colorspace,false) - else - content = convert(r) -- can be in deinterlace if needed - end - if enforcecmyk then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - decode = true - elseif mask then - if not (colordepth == 8 or colordepth == 16) then - report_png("mask can't be split from the image") - return - end - content = zlibdecompress(content) - content, mask = decodemask(content,xsize,ysize,colordepth,colorspace) - if enforcecmyk and not palette then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - decode = true -- we don't copy the filter byte - elseif transparent then - -- in test suite - -- how about decode/recompress here - if palette then - mask = createmask(content,palette,transparent,xsize,ysize,colordepth,colorspace) - else - pallette = false - end - elseif decode or (enforcecmyk and not palette) then - -- this one needs checking - local bytes = analyze(colordepth,colorspace) - if bytes then - content = zlibdecompress(content) - content = decodestrip(openstring(content),xsize,ysize,bytes) - if enforcecmyk and not palette then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - else - return - end - decode = true -- due to enforcecmyk - else - -- print("PASS ON") - end - if palette then - local colorspace = "DeviceRGB" - local nofbytes = 3 - if enforcecmyk then - palette = converttocmyk(palette,colorspace,8) - colorspace = "DeviceCMYK" - nofbytes = 4 - end - palette = pdfarray { - pdfconstant("Indexed"), - pdfconstant(colorspace), - idiv(#palette,nofbytes), - pdfreference(pdfflushstreamobject(palette)), - } - end - pngfile:close() - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - -- BBox = pdfarray { 0, 0, xsize, ysize }, - Width = xsize, - Height = ysize, - BitsPerComponent = colordepth, - Filter = filter, - ColorSpace = palette or pdfconstant(colorspace), - Length = #content, - } + specification.attr - if mask then - local d = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - Width = xsize, - Height = ysize, - BitsPerComponent = palette and 8 or colordepth, - ColorSpace = pdfconstant("DeviceGray"), - } - xobject.SMask = pdfreference(pdfflushstreamobject(mask,d())) - end - if not decode then - xobject.DecodeParms = pdfdictionary { - Colors = colors, - Columns = xsize, - BitsPerComponent = colordepth, - Predictor = 15, - } - end - if trace then - report_png("%s: width %i, height %i, colordepth %i, size %i, palette %l, mask %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode) - end - if specification.colorref then - xobject.ColorSpace = pdfreference(specification.colorref) - end - local width = specification.width or xsize * 65536 - local height = specification.height or ysize * 65536 - return createimage { - bbox = { 0, 0, width/xsize, height/ysize }, -- mandate - transform = specification.transform, - nolength = true, - nobbox = true, - notype = true, - stream = content, - attr = xobject(), - } - end - -end - -do - - local function pack(specification,what) - local t = { } - local n = 0 - local s = specification.colorspace - local d = specification.data - local x = specification.xsize - local y = specification.ysize - if what == "mask" then - d = specification.mask - s = 1 - elseif what == "indexed" then - s = 1 - elseif what == "index" then - d = specification.index - s = - s - end - if s > 0 then - if s == 1 then - for i=1,y do - local r = d[i] - for j=1,x do - n = n + 1 ; t[n] = chars[r[j]] - end - end - elseif s == 2 then - for i=1,y do - local r = d[i] - for j=1,x do - local c = r[j] - n = n + 1 ; t[n] = chars[c[1]] - n = n + 1 ; t[n] = chars[c[2]] - n = n + 1 ; t[n] = chars[c[3]] - -- n = n + 1 ; t[n] = char(c[1],c[2],c[3]) -- test this - end - end - elseif s == 3 then - for i=1,y do - local r = d[i] - for j=1,x do - local c = r[j] - n = n + 1 ; t[n] = chars[c[1]] - n = n + 1 ; t[n] = chars[c[2]] - n = n + 1 ; t[n] = chars[c[3]] - n = n + 1 ; t[n] = chars[c[4]] - -- n = n + 1 ; t[n] = char(c[1],c[2],c[3],c[4]) -- test this - end - end - end - return concat(t) - else - local z = d[0] and 0 or 1 - if s == -1 then - local f = formatters["%02X"] - for i=z,#d do - n = n + 1 ; t[n] = f(d[i]) - end - elseif s == -2 then - local f = formatters["%02X%02X%02X"] - for i=z,#d do - local c = d[i] - n = n + 1 ; t[n] = f(c[1],c[2],c[3]) - end - elseif s == -3 then - local f = formatters["%02X%02X%02X%02X"] - for i=z,#d do - local c = d[i] - n = n + 1 ; t[n] = f(c[1],c[2],c[3],c[4]) - end - end - return "<" .. concat(t," ") .. ">" - end - return "" - end - - function injectors.bitmap(specification) - local data = specification.data - if not data then - return - end - local xsize = specification.xsize or 0 - local ysize = specification.ysize or 0 - if xsize == 0 or ysize == 0 then - return - end - local colorspace = specification.colorspace or 1 - if colorspace == 1 then - colorspace = "DeviceGray" - elseif colorspace == 2 then - colorspace = "DeviceRGB" - elseif colorspace == 3 then - colorspace = "DeviceCMYK" - end - local colordepth = (specification.colordepth or 2) == 16 or 8 - local index = specification.index - local content = pack(specification,index and "indexed" or "data") - local mask = specification.mask - local colorspace = pdfconstant(colorspace) - if index then - colorspace = pdfarray { - pdfconstant("Indexed"), - colorspace, - #index + (index[0] and 0 or -1), -- upper index - pdfverbose(pack(specification,"index")) - } - end - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - BBox = pdfarray { 0, 0, xsize, ysize }, - Width = xsize, - Height = ysize, - BitsPerComponent = colordepth, - ColorSpace = colorspace, - Length = #content, -- specification.length - } - if mask then - local d = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - Width = xsize, - Height = ysize, - BitsPerComponent = colordepth, - ColorSpace = pdfconstant("DeviceGray"), - } - xobject.SMask = pdfreference(pdfflushstreamobject(pack(specification,"mask"),d())) - end - return createimage { - bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate - -- nolength = true, - nobbox = true, - notype = true, - stream = content, - attr = xobject(), - } - end - - backends.pdf.codeinjections.bitmap = injectors.bitmap - -end - --- local function validcompression(data) --- local d = utilities.streams.openstring(data) --- local b1 = utilities.streams.readbyte(d) --- local b2 = utilities.streams.readbyte(d) --- print(b1,b2) --- if (b1 * 256 + b2) % 31 ~= 0 then --- return false, "no zlib compressed file" --- end --- local method = band(b1,15) --- if method ~= 8 then --- return false, "method 8 expected" --- end --- local detail = band(rshift(b1,4),15) --- if detail > 7 then --- return false, "window 32 expected" --- end --- local preset = band(rshift(b2,5),1) --- if preset ~= 0 then --- return false, "unexpected preset dictionary" --- end --- return true --- end diff --git a/tex/context/base/mkiv/lpdf-lmt.lmt b/tex/context/base/mkiv/lpdf-lmt.lmt deleted file mode 100644 index 2bbf5ba61..000000000 --- a/tex/context/base/mkiv/lpdf-lmt.lmt +++ /dev/null @@ -1,2840 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-lmt'] = { - version = 1.001, - optimize = true, - 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 code below was originally in back-lpd.lua but it makes more sense in --- this namespace. I will rename variables. --- --- There is no way that a lua based backend can compete with the original one --- for relative simple text runs. And we're talking seconds here on say 500 --- pages with paragraphs alternativng between three fonts and colors. But such --- documents are rare so in practice we are quite okay, especially because in --- ConTeXt we can gain quite a bit elsewhere. So, when we loose 30% on such --- simple documents, we break even on for instance the manual, and gain 30% on --- Thomas's turture test (also for other reasons). But .. who knows what magic --- I can cook up in due time. - --- If you consider this complex, watch: --- --- https://www.youtube.com/watch?v=6H-cAzfB2qo --- --- or in distractionmode: --- --- https://www.youtube.com/watch?v=TYuTE_1jvvE --- https://www.youtube.com/watch?v=nnicGKX3lvM --- --- For the moment we have to support the built in backend as well as the alternative. So --- the next interface is suboptimal and will change at some time. At that moment I will --- also optimize and extend. - -local type, next, unpack, tonumber, rawget = type, next, unpack, tonumber, rawget -local char, rep, find = string.char, string.rep, string.find -local formatters, splitupstring = string.formatters, string.splitup -local band, extract = bit32.band, bit32.extract -local concat, sortedhash = table.concat, table.sortedhash -local setmetatableindex = table.setmetatableindex -local loaddata = io.loaddata - -local bpfactor = number.dimenfactors.bp - -local md5HEX = md5.HEX -local osuuid = os.uuid -local zlibcompress = (xzip or zlib).compress - -local nuts = nodes.nuts -local tonut = nodes.tonut - -local getdata = nuts.getdata -local getsubtype = nuts.getsubtype -local getwhd = nuts.getwhd -local flushlist = nuts.flush_list - -local pdfincludeimage = lpdf.includeimage -local pdfgetfontname = lpdf.getfontname -local pdfgetfontobjnumber = lpdf.getfontobjnumber - -local pdfreserveobject = lpdf.reserveobject -local pdfpagereference = lpdf.pagereference -local pdfflushobject = lpdf.flushobject -local pdfsharedobject = lpdf.shareobjectreference -local pdfreference = lpdf.reference -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfconstant = lpdf.constant -local pdfflushstreamobject = lpdf.flushstreamobject -local pdfliteral = lpdf.literal -- not to be confused with a whatsit! - -local pdf_pages = pdfconstant("Pages") -local pdf_page = pdfconstant("Page") -local pdf_xobject = pdfconstant("XObject") -local pdf_form = pdfconstant("Form") - -local fonthashes = fonts.hashes -local characters = fonthashes.characters -local descriptions = fonthashes.descriptions -local parameters = fonthashes.parameters -local properties = fonthashes.properties - -local report = logs.reporter("backend") - --- used variables - -local pdf_h, pdf_v -local need_tm, need_tf, cur_tmrx, cur_factor, cur_f, cur_e -local need_width, need_mode, done_width, done_mode -local mode -local f_pdf_cur, f_pdf, fs_cur, fs, f_cur -local tj_delta, cw -local usedfonts, usedxforms, usedximages, usedxgroups -local getxformname, getximagename -local boundingbox, shippingmode, objectnumber -local tmrx, tmry, tmsx, tmsy, tmtx, tmty -local cmrx, cmry, cmsx, cmsy, cmtx, cmty -local tmef - -local function usefont(t,k) -- a bit redundant hash - local v = pdfgetfontname(k) - t[k] = v - return v -end - -local function reset_variables(specification) - pdf_h, pdf_v = 0, 0 - cmrx, cmry = 1.0, 1.0 - cmsx, cmsy = 0.0, 0.0 - cmtx, cmty = 0.0, 0.0 - tmrx, tmry = 1.0, 1.0 - tmsx, tmsy = 0.0, 0.0 - tmtx, tmty = 0.0, 0.0 - tmef = 1.0 - need_tm = false - need_tf = false - need_width = 0 - need_mode = 0 - done_width = false - done_mode = false - mode = "page" - shippingmode = specification.shippingmode - objectnumber = specification.objectnumber - cur_tmrx = 0.0 - f_cur = 0 - f_pdf_cur = 0 -- nullfont - f_pdf = 0 -- nullfont - fs_cur = 0 - fs = 0 - cur_factor = 0 - cur_f = false - cur_e = false - tj_delta = 0.0 - cw = 0.0 - usedfonts = setmetatableindex(usefont) - usedxforms = { } - usedximages = { } - -- usedxgroups = { } - boundingbox = specification.boundingbox -end - --- buffer - -local buffer = lua.newtable(1024,0) -- { } -local b = 0 - -local function reset_buffer() - b = 0 -end - --- fonts - -local fontcharacters -local fontdescriptions -local fontparameters -local fontproperties -local usedcharacters = setmetatableindex("table") -local pdfcharacters - -local horizontalmode = true ------ widefontmode = true -local scalefactor = 1 -local threshold = 655360 -local thresfactor = 100 -local tjfactor = 100 / 65536 - -lpdf.usedcharacters = usedcharacters - -local function updatefontstate(font) - fontcharacters = characters[font] - fontdescriptions = descriptions[font] - fontparameters = parameters[font] - fontproperties = properties[font] - local size = fontparameters.size -- or bad news - local designsize = fontparameters.designsize or size - pdfcharacters = usedcharacters[font] - horizontalmode = fontparameters.writingmode ~= "vertical" - -- widefontmode = fontproperties.encodingbytes == 2 - scalefactor = (designsize/size) * tjfactor - local fthreshold = fontproperties.threshold - threshold = (fthreshold and (size * fthreshold / 100)) or 655360 - -- when we bolden the threshold should be smaller .. a hack .. i need to redo all this - if (fontparameters.extendfactor or 1) == 1 then - -- we're probably okay - elseif fontparameters.hshift or fontparameters.vshift then - -- we could be okay - else - -- some vf magic going on - threshold = threshold / 5 - end -end - --- helpers - -local f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] -local f_tm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N Tm"] - -local saved_text_pos_v = 0 -local saved_text_pos_h = 0 - -local function begin_text() - saved_text_pos_h = pdf_h - saved_text_pos_v = pdf_v - b = b + 1 ; buffer[b] = "BT" - need_tf = true - need_width = 0 - need_mode = 0 - mode = "text" -end - -local function end_text() - if done_width then - b = b + 1 ; buffer[b] = "0 w" - done_width = false - end - if done_mode then - b = b + 1 ; buffer[b] = "0 Tr" - done_mode = false - end - b = b + 1 ; buffer[b] = "ET" - pdf_h = saved_text_pos_h - pdf_v = saved_text_pos_v - mode = "page" -end - -local saved_chararray_pos_h -local saved_chararray_pos_v - -local saved_b = 0 - -local function begin_chararray() - saved_chararray_pos_h = pdf_h - saved_chararray_pos_v = pdf_v - cw = horizontalmode and saved_chararray_pos_h or - saved_chararray_pos_v - tj_delta = 0 - saved_b = b - b = b + 1 ; buffer[b] = " [" - mode = "chararray" -end - -local function end_chararray() - b = b + 1 ; buffer[b] = "] TJ" - buffer[saved_b] = concat(buffer,"",saved_b,b) - b = saved_b - pdf_h = saved_chararray_pos_h - pdf_v = saved_chararray_pos_v - mode = "text" -end - -local function begin_charmode() - b = b + 1 ; buffer[b] = "<" - mode = "char" -end - -local function end_charmode() - b = b + 1 ; buffer[b] = ">" - mode = "chararray" -end - -local function calc_pdfpos(h,v) - -- mostly char - if mode == "page" then - cmtx = h - pdf_h - cmty = v - pdf_v - return h ~= pdf_h or v ~= pdf_v - elseif mode == "text" then - tmtx = h - saved_text_pos_h - tmty = v - saved_text_pos_v - return h ~= pdf_h or v ~= pdf_v - elseif horizontalmode then - tmty = v - saved_text_pos_v - tj_delta = cw - h - return tj_delta ~= 0 or v ~= pdf_v - else - tmtx = h - saved_text_pos_h - tj_delta = cw + v - return tj_delta ~= 0 or h ~= pdf_h - end -end - -local function pdf_set_pos(h,v) - local move = calc_pdfpos(h,v) - if move then - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - pdf_h = pdf_h + cmtx - pdf_v = pdf_v + cmty - end -end - -local function pdf_reset_pos() - if mode == "page" then - cmtx = - pdf_h - cmty = - pdf_v - if pdf_h == 0 and pdf_v == 0 then - return - end - elseif mode == "text" then - tmtx = - saved_text_pos_h - tmty = - saved_text_pos_v - if pdf_h == 0 and pdf_v == 0 then - return - end - elseif horizontalmode then - tmty = - saved_text_pos_v - tj_delta = cw - if tj_delta == 0 and pdf_v == 0 then - return - end - else - tmtx = - saved_text_pos_h - tj_delta = cw - if tj_delta == 0 and pdf_h == 0 then - return - end - end - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - pdf_h = pdf_h + cmtx - pdf_v = pdf_v + cmty -end - -local function pdf_set_pos_temp(h,v) - local move = calc_pdfpos(h,v) - if move then - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - end -end - --- these dummy returns makes using them a bit faster - -local function pdf_end_string_nl() - if mode == "char" then - end_charmode() - return end_chararray() - elseif mode == "chararray" then - return end_chararray() - end -end - -local function pdf_goto_textmode() - if mode == "page" then - pdf_reset_pos() - return begin_text() - elseif mode ~= "text" then - if mode == "char" then - end_charmode() - return end_chararray() - else -- if mode == "chararray" then - return end_chararray() - end - end -end - -local function pdf_goto_pagemode() - if mode ~= "page" then - if mode == "char" then - end_charmode() - end_chararray() - return end_text() - elseif mode == "chararray" then - end_chararray() - return end_text() - elseif mode == "text" then - return end_text() - end - end -end - -local function pdf_goto_fontmode() - if mode == "char" then - end_charmode() - end_chararray() - end_text() - elseif mode == "chararray" then - end_chararray() - end_text() - elseif mode == "text" then - end_text() - end - pdf_reset_pos() - mode = "page" -end - --- characters - -local flushcharacter do - - local round = math.round - - -- across pages ... todo: clean up because we don't need to pass the font - -- as fontparameters already has checked / set it we can also have a variable - -- for it so - - local naturalwidth = nil - local hshift = false - local vshift = false - - -- local naturalwidths = setmetatableindex(function(t,font) - -- local d = descriptions[font] - -- local c = characters[font] - -- local f = parameters[font].hfactor - -- local v = setmetatableindex(function(t,char) - -- local w - -- local e = d and d[char] - -- if e then - -- w = e.width - -- if w then - -- w = w * f - -- end - -- end - -- if not w then - -- e = c[char] - -- if e then - -- w = e.width or 0 - -- end - -- end - -- if not w then - -- w = 0 - -- end - -- t[char] = w - -- return w - -- end) - -- t[font] = v - -- return v - -- end) - - local naturalwidths = setmetatableindex(function(t,font) - local d = descriptions[font] - local c = characters[font] - local f = parameters[font].hfactor - local v = setmetatableindex(function(t,char) - local w - local e = c[char] - if e then - w = e.width or 0 - end - if not w then - e = d and d[char] - if e then - w = e.width - if w then - w = w * f - end - end - end - if not w then - w = 0 - end - t[char] = w - return w - end) - t[font] = v - return v - end) - - local function setup_fontparameters(font,factor,f,e) - local slant = fontparameters.slantfactor or 0 - local extend = fontparameters.extendfactor or 1 - local squeeze = fontparameters.squeezefactor or 1 - local expand = 1 + factor / 1000000 - local format = fontproperties.format - if e then - extend = extend * e - end - tmef = expand - tmrx = expand * extend - tmsy = slant - tmry = squeeze - need_width = fontparameters.width or 0 - need_mode = fontparameters.mode or 0 - f_cur = font - f_pdf = usedfonts[font] -- cache - cur_factor = factor - cur_f = f - cur_e = e - tj_delta = 0 - fs = fontparameters.size * bpfactor - if f then - fs = fs * f - end - -- kind of special: - if format == "opentype" or format == "type1" then - fs = fs * 1000 / fontparameters.units -- can we avoid this ? - end - -- - naturalwidth = naturalwidths[font] - -- - hshift = fontparameters.hshift - vshift = fontparameters.vshift - end - - local f_width = formatters["%.6N w"] - local f_mode = formatters["%i Tr"] -- can be hash - local f_font = formatters["/F%i %.6N Tf"] -- can be hash - - local s_width = "0 w" - local s_mode = "0 Tr" - - local width_factor = 72.27 / 72000.0 - - local function set_font() - -- if need_width and need_width ~= 0 then - if need_width ~= 0 then - b = b + 1 ; buffer[b] = f_width(width_factor*need_width) - done_width = true - elseif done_width then - b = b + 1 ; buffer[b] = s_width - done_width = false - end - -- if need_mode and need_mode ~= 0 then - if need_mode ~= 0 then - b = b + 1 ; buffer[b] = f_mode(need_mode) - done_mode = true - elseif done_mode then - b = b + 1 ; buffer[b] = s_mode - done_mode = false - end - b = b + 1 ; buffer[b] = f_font(f_pdf,fs) - f_pdf_cur = f_pdf - fs_cur = fs - need_tf = false - need_tm = true - end - - local function set_textmatrix(h,v) - local move = calc_pdfpos(h,v) - if need_tm or move then - b = b + 1 ; buffer[b] = f_tm(tmrx, tmsx, tmsy, tmry, tmtx*bpfactor, tmty*bpfactor) - pdf_h = saved_text_pos_h + tmtx - pdf_v = saved_text_pos_v + tmty - need_tm = false - end - cur_tmrx = tmrx - end - - local f_hex_4 = formatters["%04X"] - local f_hex_2 = formatters["%02X"] - - local h_hex_4 = setmetatableindex(function(t,k) -- we already have this somewhere - if k < 256 then -- maybe 512 - -- not sparse in this range - for i=0,255 do - t[i] = f_hex_4(i) - end - return t[k] - else - local v = f_hex_4(k) - t[k] = v - return v - end - end) - local h_hex_2 = setmetatableindex(function(t,k) -- we already have this somewhere - local v = k < 256 and f_hex_2(k) or "00" - t[k] = v - return v - end) - - -- local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) - - -- local f_skip = formatters["%.2N"] - - -- I will redo this mess ... we no longer have the mkiv pdf generator that we used in - -- luatex (a precursor to lmtx and also for comparison) but only in lmtx now so ... - -- time to move on I guess. - - flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then - pdf_goto_textmode() - setup_fontparameters(font,factor,f,e) - set_font() - elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then - setup_fontparameters(font,factor,f,e) - need_tm = true - end - local move = calc_pdfpos(pos_h,pos_v) - - -- if trace_threshold then - -- report( - -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", - -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw - -- ) - -- end - - if move or need_tm then - if not need_tm then - if horizontalmode then - if (saved_text_pos_v + tmty) ~= pdf_v then - need_tm = true - elseif tj_delta >= threshold or tj_delta <= -threshold then - need_tm = true - end - else - if (saved_text_pos_h + tmtx) ~= pdf_h then - need_tm = true - elseif tj_delta >= threshold or tj_delta <= -threshold then - need_tm = true - end - end - end - - if hshift then pos_h = pos_h + hshift end - if vshift then pos_v = pos_v - vshift end - - if need_tm then - pdf_goto_textmode() - set_textmatrix(pos_h,pos_v) - begin_chararray() - move = calc_pdfpos(pos_h,pos_v) - end - if move then - local d = tj_delta * scalefactor - if d <= -0.5 or d >= 0.5 then - if mode == "char" then - end_charmode() - end - b = b + 1 ; buffer[b] = round(d) -- or f_skip(d) - end - cw = cw - tj_delta - end - end - - if mode == "chararray" then - begin_charmode() - end - - cw = cw + naturalwidth[char] * tmef - - local index = data.index or char - - b = b + 1 ; buffer[b] = font > 0 and h_hex_4[index] or h_hex_2[index] - - if not pdfcharacters[index] then - pdfcharacters[index] = true - end - - end - - flushfontchar = function(font,char,data) - local dummy = usedfonts[font] - local index = data.index or char - if not pdfcharacters[index] then - pdfcharacters[index] = true - end - return dummy - end - -end - --- literals - -local flushliteral do - - local nodeproperties = nodes.properties.data - local literalvalues = nodes.literalvalues - - local originliteral_code = literalvalues.origin - local pageliteral_code = literalvalues.page - local alwaysliteral_code = literalvalues.always - local rawliteral_code = literalvalues.raw - local textliteral_code = literalvalues.text - local fontliteral_code = literalvalues.font - - flushliteral = function(current,pos_h,pos_v,mode,str) - if mode then - if not str then - mode, str = originliteral_code, mode - elseif mode == "mode" then - mode = literalvalues[str] - if mode == originliteral_code then - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - end - return - else - mode = literalvalues[mode] - end - else - local p = nodeproperties[current] - if p then - str = p.data - mode = p.mode - else - str, mode = getdata(current) - end - end - if str and str ~= "" then - if mode == originliteral_code then - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - else - report("check literal") - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - end - b = b + 1 ; buffer[b] = str - end - end - - updaters.register("backend.update.pdf",function() - function pdf.print(mode,str) - -- This only works inside objects, don't change this to flush - -- in between. It's different from luatex but okay. - if str then - mode = literalvalues[mode] - else - mode, str = originliteral_code, mode - end - if str and str ~= "" then - if mode == originliteral_code then - pdf_goto_pagemode() - -- pdf_set_pos(pdf_h,pdf_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - else - pdf_goto_pagemode() - -- pdf_set_pos(pdf_h,pdf_v) - end - b = b + 1 ; buffer[b] = str - end - end - end) - -end - --- grouping & orientation - -local flushsave, flushrestore, flushsetmatrix do - - local matrices = { } - local positions = { } - local nofpositions = 0 - local nofmatrices = 0 - - local f_matrix = formatters["%s 0 0 cm"] - - flushsave = function(current,pos_h,pos_v) - nofpositions = nofpositions + 1 - positions[nofpositions] = { pos_h, pos_v, nofmatrices } - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "q" - end - - flushrestore = function(current,pos_h,pos_v) - if nofpositions < 1 then - return - end - local t = positions[nofpositions] - -- local h = pos_h - t[1] - -- local v = pos_v - t[2] - if shippingmode == "page" then - nofmatrices = t[3] - end - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "Q" - nofpositions = nofpositions - 1 - end - - local function pdf_set_matrix(str,pos_h,pos_v) - if shippingmode == "page" then - local rx, sx, sy, ry = splitupstring(str," ") - if rx and ry and sx and ry then - rx, sx, sy, ry = tonumber(rx), tonumber(sx), tonumber(sy), tonumber(ry) - local tx = pos_h * (1 - rx) - pos_v * sy - local ty = pos_v * (1 - ry) - pos_h * sx - if nofmatrices > 0 then - local t = matrices[nofmatrices] - local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6] - rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y - sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y - tx, ty = tx * r_x + ty * s_y, tx * s_x + ty * r_y - end - nofmatrices = nofmatrices + 1 - matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty } - end - end - end - - local nodeproperties = nodes.properties.data - - flushsetmatrix = function(current,pos_h,pos_v) - local str - if type(current) == "string" then - str = current - else - local p = nodeproperties[current] - if p then - str = p.matrix - else - str = getdata(current) -- for the moment - end - end - if str and str ~= "" then - pdf_set_matrix(str,pos_h,pos_v) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = f_matrix(str) - end - end - - do - - local function hasmatrix() - return nofmatrices > 0 - end - - local function getmatrix() - if nofmatrices > 0 then - return unpack(matrices[nofmatrices]) - else - return 1, 0, 0, 1, 0, 0 - end - end - - updaters.register("backend.update.pdf",function() - pdf.hasmatrix = hasmatrix - pdf.getmatrix = getmatrix - end) - - end - - pushorientation = function(orientation,pos_h,pos_v,pos_r) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "q" - if orientation == 1 then - b = b + 1 ; buffer[b] = "0 -1 1 0 0 0 cm" -- 90 - elseif orientation == 2 then - b = b + 1 ; buffer[b] = "-1 0 0 -1 0 0 cm" -- 180 - elseif orientation == 3 then - b = b + 1 ; buffer[b] = "0 1 -1 0 0 0 cm" -- 270 - end - end - - poporientation = function(orientation,pos_h,pos_v,pos_r) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "Q" - end - - -- pushorientation = function(orientation,pos_h,pos_v,pos_r) - -- flushsave(false,pos_h,pos_v) - -- if orientation == 1 then - -- flushsetmatrix("0 -1 1 0",pos_h,pos_v) - -- elseif orientation == 2 then - -- flushsetmatrix("-1 0 0 -1",pos_h,pos_v) - -- elseif orientation == 3 then - -- flushsetmatrix("0 1 -1 0",pos_h,pos_v) - -- end - -- end - - -- poporientation = function(orientation,pos_h,pos_v,pos_r) - -- flushrestore(false,pos_h,pos_v) - -- end - -end - --- rules - -local flushedxforms = { } -- actually box resources but can also be direct -local localconverter = nil -- will be set - -local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do - - local rulecodes = nodes.rulecodes - local newrule = nodes.pool.rule - - local setprop = nuts.setprop - local getprop = nuts.getprop - - local normalrule_code = rulecodes.normal - local boxrule_code = rulecodes.box - local imagerule_code = rulecodes.image - local emptyrule_code = rulecodes.empty - local userrule_code = rulecodes.user - local overrule_code = rulecodes.over - local underrule_code = rulecodes.under - local fractionrule_code = rulecodes.fraction - local radicalrule_code = rulecodes.radical - local outlinerule_code = rulecodes.outline - - local rule_callback = callbacks.functions.process_rule - - local f_fm = formatters["/Fm%d Do"] - local f_im = formatters["/Im%d Do"] - local f_gr = formatters["/Gp%d Do"] - - local s_b = "q" - local s_e = "Q" - - local f_v = formatters["[] 0 d 0 J %.6N w 0 0 m %.6N 0 l S"] - local f_h = formatters["[] 0 d 0 J %.6N w 0 0 m 0 %.6N l S"] - - local f_f = formatters["0 0 %.6N %.6N re f"] - local f_o = formatters["[] 0 d 0 J 0 0 %.6N %.6N re S"] - local f_w = formatters["[] 0 d 0 J %.6N w 0 0 %.6N %.6N re S"] - - local f_b = formatters["%.6N w 0 %.6N %.6N %.6N re f"] - local f_x = formatters["[] 0 d 0 J %.6N w %.6N %.6N %.6N %.6N re S"] - - -- Historically the index is an object which is kind of bad. - - local boxresources, n = { }, 0 - - getxformname = function(index) - local l = boxresources[index] - if l then - return l.name - else - report("no box resource %S",index) - end - end - - updaters.register("backend.update.pdf",function() - pdf.getxformname = getxformname - end) - - local function saveboxresource(box,attributes,resources,immediate,kind,margin) - n = n + 1 - local immediate = true - local margin = margin or 0 -- or dimension - local objnum = pdfreserveobject() - local list = tonut(type(box) == "number" and tex.takebox(box) or box) - -- - local width, height, depth = getwhd(list) - -- - local l = { - width = width, - height = height, - depth = depth, - margin = margin, - attributes = attributes, - resources = resources, - list = nil, - type = kind, - name = n, - index = objnum, - objnum = objnum, - } - boxresources[objnum] = l - if immediate then - localconverter(list,"xform",objnum,l) - flushedxforms[objnum] = { true , objnum } - flushlist(list) - else - l.list = list - end - return objnum - end - - local function useboxresource(index,wd,ht,dp) - local l = boxresources[index] - if l then - if wd or ht or dp then - wd, ht, dp = wd or 0, ht or 0, dp or 0 - else - wd, ht, dp = l.width, l.height, l.depth - end - local rule = newrule(wd,ht,dp) -- newboxrule - rule.subtype = boxrule_code - setprop(tonut(rule),"index",index) - return rule, wd, ht, dp - else - report("no box resource %S",index) - end - end - - local function getboxresourcedimensions(index) - local l = boxresources[index] - if l then - return l.width, l.height, l.depth, l.margin - else - report("no box resource %S",index) - end - end - - local function getboxresourcebox(index) - local l = boxresources[index] - if l then - return l.list - end - end - - updaters.register("backend.update.tex",function() - tex.saveboxresource = saveboxresource - tex.useboxresource = useboxresource - tex.getboxresourcedimensions = getboxresourcedimensions - tex.getboxresourcebox = getboxresourcebox - end) - - -- a bit of a mess: index is now objnum but that has to change to a proper index - -- ... an engine inheritance - - local function flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) - -- object properties - local objnum = getprop(current,"index") - local name = getxformname(objnum) - local info = flushedxforms[objnum] - local r = boxresources[objnum] - if not info then - info = { false , objnum } - flushedxforms[objnum] = info - end - local wd, ht, dp = getboxresourcedimensions(objnum) - -- or: wd, ht, dp = r.width, r.height, r.depth - -- sanity check - local htdp = ht + dp - if wd == 0 or size_h == 0 or htdp == 0 or size_v == 0 then - return - end - -- calculate scale - local rx, ry = 1, 1 - if wd ~= size_h or htdp ~= size_v then - rx = size_h / wd - ry = size_v / htdp - end - -- flush the reference - usedxforms[objnum] = true - pdf_goto_pagemode() - calc_pdfpos(pos_h,pos_v) - tx = cmtx * bpfactor - ty = cmty * bpfactor - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,0,0,ry,tx,ty) - b = b + 1 ; buffer[b] = f_fm(name) - b = b + 1 ; buffer[b] = s_e - end - - -- place image also used in vf but we can use a different one if we need it - - local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream - local img_none = imagetypes.none - local img_pdf = imagetypes.pdf - local img_stream = imagetypes.stream - local img_memstream = imagetypes.memstream - - local one_bp = 65536 * bpfactor - - local imageresources, n = { }, 0 - - getximagename = function(index) - local l = imageresources[index] - if l then - return l.name - else - report("no image resource %S",index) - end - end - - updaters.register("backend.update.pdf",function() - pdf.getximagename = getximagename - end) - - -- Groups are flushed immediately but we can decide to make them into a - -- specific whatsit ... but not now. We could hash them if needed when - -- we use lot sof them in mp ... but not now. - - usedxgroups = { } - local groups = 0 - local group = nil - - flushgroup = function(content,bbox) - if not group then - group = pdfdictionary { - Type = pdfconstant("Group"), - S = pdfconstant("Transparency"), - } - end - local wrapper = pdfdictionary { - Type = pdf_xobject, - Subtype = pdf_form, - FormType = 1, - Group = group, - BBox = pdfarray(bbox), - Resources = lpdf.collectedresources { serialize = false }, - } - local objnum = pdfflushstreamobject(content,wrapper,false) - groups = groups + 1 - usedxgroups[groups] = objnum - return f_gr(groups) - end - - lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps - - -- end of experiment - - local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) - - local width, - height, - depth = getwhd(current) - local total = height + depth - local transform = getprop(current,"transform") or 0 -- we never set it ... so just use rotation then - local index = getprop(current,"index") or 0 - local kind, - xorigin, - yorigin, - xsize, - ysize, - rotation, -- transform / orientation / rotation : it's a mess (i need to redo this) - objnum, - groupref = pdfincludeimage(index) -- needs to be sorted out, bad name (no longer mixed anyway) - - if not kind then - report("invalid image %S",index) - return - end - - local rx, sx, sy, ry, tx, ty = 1, 0, 0, 1, 0, 0 - - -- tricky: xsize and ysize swapped - - if kind == img_pdf or kind == img_stream or kind == img_memstream then - rx, ry, tx, ty = 1/xsize, 1/ysize, xorigin/xsize, yorigin/ysize - else - -- if kind == img_png then - -- -- if groupref > 0 and img_page_group_val == 0 then - -- -- img_page_group_val = groupref - -- -- end - -- end - rx, ry = bpfactor, bpfactor - end - - if band(transform,7) > 3 then - -- mirror - rx, tx = -rx, -tx - end - local t = band(transform + rotation,3) - if t == 0 then - -- nothing - elseif t == 1 then - -- rotation over 90 degrees (counterclockwise) - rx, sx, sy, ry, tx, ty = 0, rx, -ry, 0, -ty, tx - elseif t == 2 then - -- rotation over 180 degrees (counterclockwise) - rx, ry, tx, ty = -rx, -ry, -tx, -ty - elseif t == 3 then - -- rotation over 270 degrees (counterclockwise) - rx, sx, sy, ry, tx, ty = 0, -rx, ry, 0, ty, -tx - end - - rx = rx * width - sx = sx * total - sy = sy * width - ry = ry * total - tx = pos_h - tx * width - ty = pos_v - ty * total - - local t = transform + rotation - - if band(transform,7) > 3 then - t = t + 1 - end - - t = band(t,3) - - if t == 0 then - -- no transform - elseif t == 1 then - -- rotation over 90 degrees (counterclockwise) - tx = tx + width - elseif t == 2 then - -- rotation over 180 degrees (counterclockwise) - tx = tx + width - ty = ty + total - elseif t == 3 then - -- rotation over 270 degrees (counterclockwise) - ty = ty + total - end - - -- a flaw in original, can go: - -- - -- if img_page_group_val == 0 then - -- img_page_group_val = group_ref - -- end - - usedximages[index] = objnum -- hm - - pdf_goto_pagemode() - - calc_pdfpos(tx,ty) - - tx = cmtx * bpfactor - ty = cmty * bpfactor - - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) - b = b + 1 ; buffer[b] = f_im(index) - b = b + 1 ; buffer[b] = s_e - end - - flushimage = function(index,width,height,depth,pos_h,pos_v) - - -- used in vf characters - - local total = height + depth - local kind, - xorigin, yorigin, - xsize, ysize, - rotation, - objnum, - groupref = pdfincludeimage(index) - - local rx = width / xsize - local sx = 0 - local sy = 0 - local ry = total / ysize - local tx = pos_h - -- to be sorted out - -- local ty = pos_v - depth - local ty = pos_v -- we assume that depth is dealt with in the caller (for now) - - usedximages[index] = objnum - - pdf_goto_pagemode() - - calc_pdfpos(tx,ty) - - tx = cmtx * bpfactor - ty = cmty * bpfactor - - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) - b = b + 1 ; buffer[b] = f_im(index) - b = b + 1 ; buffer[b] = s_e - end - - -- For the moment we need this hack because the engine checks the 'image' - -- command in virtual fonts (so we use lua instead). - -- - -- These will be replaced by a new more advanced one ... some day ... or - -- never because the next are like the other engines and compensate for - -- small sizes which is needed for inaccurate viewers. - - flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) - - if subtype == emptyrule_code then - return - elseif subtype == boxrule_code then - return flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) - elseif subtype == imagerule_code then - return flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) - end - if subtype == userrule_code or subtype >= overrule_code and subtype <= radicalrule_code then - pdf_goto_pagemode() - b = b + 1 ; buffer[b] = s_b - pdf_set_pos_temp(pos_h,pos_v) - rule_callback(current,size_h,size_v,pos_r) -- so we pass direction - b = b + 1 ; buffer[b] = s_e - return - end - - pdf_goto_pagemode() - - -- local saved_b = b - - b = b + 1 ; buffer[b] = s_b - - local dim_h = size_h * bpfactor - local dim_v = size_v * bpfactor - local rule - - if dim_v <= one_bp then - pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) - rule = f_v(dim_v,dim_h) - elseif dim_h <= one_bp then - pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) - rule = f_h(dim_h,dim_v) - else - pdf_set_pos_temp(pos_h,pos_v) - if subtype == outlinerule_code then - local linewidth = getdata(current) - if linewidth > 0 then - rule = f_w(linewidth * bpfactor,dim_h,dim_v) - else - rule = f_o(dim_h,dim_v) - end - else - rule = f_f(dim_h,dim_v) - end - end - - b = b + 1 ; buffer[b] = rule - b = b + 1 ; buffer[b] = s_e - - -- buffer[saved_b] = concat(buffer," ",saved_b,b) - -- b = saved_b - - end - - flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v) - pdf_goto_pagemode() - - b = b + 1 ; buffer[b] = s_b - - local dim_h = size_h * bpfactor - local dim_v = size_v * bpfactor - local rule - - if dim_v <= one_bp then - pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) - rule = f_v(dim_v,dim_h) - elseif dim_h <= one_bp then - pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) - rule = f_h(dim_h,dim_v) - else - pdf_set_pos_temp(pos_h,pos_v) - rule = f_f(dim_h,dim_v) - end - - b = b + 1 ; buffer[b] = rule - b = b + 1 ; buffer[b] = s_e - end - - flushspecialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline) - pdf_goto_pagemode() - - b = b + 1 ; buffer[b] = s_b - - local width = bpfactor * width - local height = bpfactor * height - local depth = bpfactor * depth - local total = height + depth - local line = bpfactor * line - local half = line / 2 - local rule - - if outline then - rule = f_x(line,half,-depth+half,width-line,total-line) - else - rule = f_b(line,-depth,width,total) - end - pdf_set_pos_temp(pos_h,pos_v) - - b = b + 1 ; buffer[b] = rule - b = b + 1 ; buffer[b] = s_e - end - -end - ---- basics - -local wrapup, registerpage do - - local pages = { } - local maxkids = 10 - local nofpages = 0 - local pagetag = "unset" - - registerpage = function(object) - nofpages = nofpages + 1 - local objnum = pdfpagereference(nofpages) - pages[nofpages] = { - page = nofpages, -- original number, only for diagnostics - objnum = objnum, - object = object, - tag = pagetag, - } - end - - function lpdf.setpagetag(tag) - pagetag = tag or "unset" - end - - function lpdf.getnofpages() - return nofpages - end - - function lpdf.getpagetags() - local list = { } - for i=1,nofpages do - list[i] = pages[i].tag - end - return list - end - - function lpdf.setpageorder(mapping) - -- mapping can be a hash so: - local list = table.sortedkeys(mapping) - local n = #list - if n == nofpages then - local done = { } - local hash = { } - for i=1,n do - local order = mapping[list[i]] - if hash[order] then - report("invalid page order, duplicate entry %i",order) - return - elseif order < 1 or order > nofpages then - report("invalid page order, no page %i",order) - return - else - done[i] = pages[order] - hash[order] = true - end - end - pages = done - else - report("invalid page order, %i entries expected",nofpages) - end - end - - -- We can have this, but then via codeinjections etc. Later. - - -- function structures.pages.swapthem() - -- local n = lpdf.getnofpages() - -- local t = { } - -- for i=1,n do - -- t[i] = i - -- end - -- for i=2,math.odd(n) and n or (n-1),2 do - -- t[i] = i+1 - -- t[i+1] = i - -- end - -- lpdf.setpageorder(t) - -- end - - wrapup = function(driver) - - -- hook (to reshuffle pages) - local pagetree = { } - local parent = nil - local minimum = 0 - local maximum = 0 - local current = 0 - if #pages > 1.5 * maxkids then - repeat - local plist, pnode - if current == 0 then - plist, minimum = pages, 1 - elseif current == 1 then - plist, minimum = pagetree, 1 - else - plist, minimum = pagetree, maximum + 1 - end - maximum = #plist - if maximum > minimum then - local kids - for i=minimum,maximum do - local p = plist[i] - if not pnode or #kids == maxkids then - kids = pdfarray() - parent = pdfreserveobject() - pnode = pdfdictionary { - objnum = parent, - Type = pdf_pages, - Kids = kids, - Count = 0, - } - pagetree[#pagetree+1] = pnode - end - kids[#kids+1] = pdfreference(p.objnum) - pnode.Count = pnode.Count + (p.Count or 1) - p.Parent = pdfreference(parent) - end - end - current = current + 1 - until maximum == minimum - -- flush page tree - for i=1,#pagetree do - local entry = pagetree[i] - local objnum = entry.objnum - entry.objnum = nil - pdfflushobject(objnum,entry) - end - else - -- ugly - local kids = pdfarray() - local list = pdfdictionary { - Type = pdf_pages, - Kids = kids, - Count = nofpages, - } - parent = pdfreserveobject() - for i=1,nofpages do - local page = pages[i] - kids[#kids+1] = pdfreference(page.objnum) - page.Parent = pdfreference(parent) - end - pdfflushobject(parent,list) - end - for i=1,nofpages do - local page = pages[i] - local object = page.object - object.Parent = page.Parent - pdfflushobject(page.objnum,object) - end - lpdf.addtocatalog("Pages",pdfreference(parent)) - - end - -end - -pdf_h, pdf_v = 0, 0 - -local function initialize(driver,details) - reset_variables(details) - reset_buffer() -end - --- This will all move and be merged and become less messy. - --- todo: more clever resource management: a bit tricky as we can inject --- stuff in the page stream - -local compact = false - -do - - -- This is more a convenience feature and it might even be not entirely robust. - -- It removes redundant color directives which makes the page stream look a bit - -- nicer (also when figuring out issues). I might add more here but there is - -- some additional overhead involved so runtime can be impacted. - - local P, R, S, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs, lpeg.match - - local p_ds = (R("09") + S(" ."))^1 - ----- p_nl = S("\n\r")^1 - local p_nl = S("\n")^1 - local p_eg = P("Q") - - local p_cl = p_ds * (P("rg") + P("g") + P("k")) * p_ds * (P("RG") + P("G") + P("K")) - ----- p_cl = (p_ds * (P("rg") + P("g") + P("k") + P("RG") + P("G") + P("K")))^1 - local p_tr = P("/Tr") * p_ds * P("gs") - - local p_no_cl = (p_cl * p_nl) / "" - local p_no_tr = (p_tr * p_nl) / "" - local p_no_nl = 1 - p_nl - - local p_do_cl = p_cl * p_nl - local p_do_tr = p_tr * p_nl - - local p_do_eg = p_eg * p_nl - - local pattern = Cs( ( - (p_no_cl + p_no_tr)^0 * p_do_eg -- transparencies and colors before Q - + p_no_tr * p_no_cl * p_do_tr * p_do_cl -- transparencies and colors before others - + p_no_cl * p_do_cl -- successive colors - + p_no_tr * p_do_tr -- successive transparencies - + p_no_nl^1 - + 1 - )^1 ) - - local oldsize = 0 - local newsize = 0 - - directives.register("pdf.compact", function(v) - compact = v and function(s) - oldsize = oldsize + #s - s = lpegmatch(pattern,s) or s - newsize = newsize + #s - return s - end - end) - - statistics.register("pdf pagestream",function() - if oldsize ~= newsize then - return string.format("old size: %i, new size %i",oldsize,newsize) - end - end) - - -end - -local flushdeferred -- defined later - -local level = 0 - -local finalize do - - local f_font = formatters["F%d"] - - local f_form = formatters["Fm%d"] - local f_group = formatters["Gp%d"] - local f_image = formatters["Im%d"] - - finalize = function(driver,details) - - level = level + 1 - - pdf_goto_pagemode() -- for now - - local objnum = details.objnum - local specification = details.specification - - local content = concat(buffer,"\n",1,b) - - if compact then - content = compact(content) - end - - local fonts = nil - local xforms = nil - - if next(usedfonts) then - fonts = pdfdictionary { } - for k, v in next, usedfonts do - fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing - end - end - - -- messy: use real indexes for both ... so we need to change some in the - -- full luatex part - - if next(usedxforms) or next(usedximages) or next(usedxgroups) then - xforms = pdfdictionary { } - for k in sortedhash(usedxforms) do - -- xforms[f_form(k)] = pdfreference(k) - xforms[f_form(getxformname(k))] = pdfreference(k) - end - for k, v in sortedhash(usedximages) do - xforms[f_image(k)] = pdfreference(v) - end - for k, v in sortedhash(usedxgroups) do - xforms[f_group(k)] = pdfreference(v) - end - end - - reset_buffer() - - -- finish_pdfpage_callback(shippingmode == "page") - - if shippingmode == "page" then - - local pageproperties = lpdf.getpageproperties() - - local pageresources = pageproperties.pageresources - local pageattributes = pageproperties.pageattributes - local pagesattributes = pageproperties.pagesattributes - - pageresources.Font = fonts - pageresources.XObject = xforms - pageresources.ProcSet = lpdf.procset() - - local xorigin, yorigin, relocated = backends.codeinjections.getpageorigin() -- for now here - - local bbox = pdfarray { - (boundingbox[1] + xorigin) * bpfactor, - (boundingbox[2] + yorigin) * bpfactor, - (boundingbox[3] + xorigin) * bpfactor, - (boundingbox[4] + yorigin) * bpfactor, - } - - if relocated then - content = formatters["1 0 0 1 %.6N %.6N cm\n%s"](bbox[1],bbox[2],content) - end - - local contentsobj = pdfflushstreamobject(content,false,false) - - pageattributes.Type = pdf_page - pageattributes.Contents = pdfreference(contentsobj) - pageattributes.Resources = pageresources - -- pageattributes.Resources = pdfreference(pdfflushobject(pageresources)) - -- pageattributes.MediaBox = bbox - pageattributes.MediaBox = pdfsharedobject(bbox) - pageattributes.Parent = nil -- precalculate - pageattributes.Group = nil -- todo - - -- resources can be indirect - - registerpage(pageattributes) - - lpdf.finalizepage(true) - - local TrimBox = pageattributes.TrimBox - local CropBox = pageattributes.CropBox - local BleedBox = pageattributes.BleedBox - - if relocated then - if TrimBox then TrimBox = box end - if CropBox then CropBox = box end - if BleedBox then BleedBox = box end - end - - -- Indirect objects don't work in all viewers. - - if TrimBox then pageattributes.TrimBox = pdfsharedobject(TrimBox ) end - if CropBox then pageattributes.CropBox = pdfsharedobject(CropBox ) end - if BleedBox then pageattributes.BleedBox = pdfsharedobject(BleedBox) end - - else - - local xformtype = specification.type or 0 - local margin = specification.margin or 0 - local attributes = specification.attributes or "" - local resources = specification.resources or "" - - local wrapper = nil - - if xformtype == 0 then - wrapper = pdfdictionary { - Type = pdf_xobject, - Subtype = pdf_form, - FormType = 1, - BBox = nil, - Matrix = nil, - Resources = nil, - } - else - wrapper = pdfdictionary { - BBox = nil, - Matrix = nil, - Resources = nil, - } - end - if xformtype == 0 or xformtype == 1 or xformtype == 3 then - wrapper.BBox = pdfarray { - -margin * bpfactor, - -margin * bpfactor, - (boundingbox[3] + margin) * bpfactor, - (boundingbox[4] + margin) * bpfactor, - } - end - if xformtype == 0 or xformtype == 2 or xformtype == 3 then - -- can be shared too - wrapper.Matrix = pdfarray { 1, 0, 0, 1, 0, 0 } - end - - -- todo: additional = resources - - local boxresources = lpdf.collectedresources { serialize = false } - boxresources.Font = fonts - boxresources.XObject = xforms - - -- todo: maybe share them - -- wrapper.Resources = pdfreference(pdfflushobject(boxresources)) - - if resources ~= "" then - boxresources = boxresources + resources - end - if attributes ~= "" then - wrapper = wrapper + attributes - end - - wrapper.Resources = next(boxresources) and boxresources or nil - wrapper.ProcSet = lpdf.procset() - - -- pdfflushstreamobject(content,wrapper,false,objectnumber) - pdfflushstreamobject(content,wrapper,false,specification.objnum) - - end - - for objnum in sortedhash(usedxforms) do - local f = flushedxforms[objnum] - if f[1] == false then - f[1] = true - local objnum = f[2] -- specification.objnum - local specification = boxresources[objnum] - local list = specification.list - localconverter(list,"xform",f[2],specification) - end - end - - pdf_h, pdf_v = 0, 0 - - if level == 1 then - flushdeferred() - end - level = level - 1 - - end - -end - -updaters.register("backend.update.pdf",function() - job.positions.registerhandlers { - getpos = drivers.getpos, - getrpos = drivers.getrpos, - gethpos = drivers.gethpos, - getvpos = drivers.getvpos, - } -end) - -updaters.register("backend.update",function() - local saveboxresource = tex.boxresources.save - -- - -- also in lpdf-res .. brrr .. needs fixing - -- - backends.codeinjections.registerboxresource = function(n,offset) - local r = saveboxresource(n,nil,nil,false,0,offset or 0) - return r - end -end) - --- now comes the pdf file handling - -local objects = { } -local streams = { } -- maybe just parallel to objects (no holes) -local nofobjects = 0 -local offset = 0 -local f = false -local flush = false -local threshold = 40 -- also #("/Filter /FlateDecode") (compression threshold) -local objectstream = true -local compress = true -local cache = false -local info = "" -local catalog = "" -local lastdeferred = false -local majorversion = 1 -local minorversion = 7 -local trailerid = true - -directives.register("backend.pdf.threshold",function(v) - if v then - threshold = tonumber(v) or 40 - else - threshold = -1000 - end -end) - -local f_object = formatters["%i 0 obj\010%s\010endobj\010"] -local f_stream_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010%s\010endstream\010endobj\010"] - ------ f_object_b = formatters["%i 0 obj\010"] -local f_stream_b_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010"] -local f_stream_b_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010"] -local f_stream_b_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010"] -local f_stream_b_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010"] -local f_stream_b_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010"] - ------ s_object_e = "\010endobj\010" -local s_stream_e = "\010endstream\010endobj\010" - -do - - local function setinfo() end -- we get it - local function setcatalog() end -- we get it - - local function settrailerid(v) - trailerid = v or false - end - - local function setmajorversion(v) majorversion = tonumber(v) or majorversion end - local function setminorversion(v) minorversion = tonumber(v) or minorversion end - - local function getmajorversion(v) return majorversion end - local function getminorversion(v) return minorversion end - - local function setcompresslevel (v) compress = v and v ~= 0 and true or false end - local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end - - local function getcompresslevel (v) return compress and 3 or 0 end - local function getobjcompresslevel(v) return objectstream and 1 or 0 end - - local function setpageresources () end -- needs to be sorted out - local function setpageattributes () end - local function setpagesattributes() end - - updaters.register("backend.update.pdf",function() - pdf.setinfo = setinfo - pdf.setcatalog = setcatalog - pdf.settrailerid = settrailerid - pdf.setmajorversion = setmajorversion - pdf.setminorversion = setminorversion - pdf.getmajorversion = getmajorversion - pdf.getminorversion = getminorversion - pdf.setcompresslevel = setcompresslevel - pdf.setobjcompresslevel = setobjcompresslevel - pdf.getcompresslevel = getcompresslevel - pdf.getobjcompresslevel = getobjcompresslevel - pdf.setpageresources = setpageresources - pdf.setpageattributes = setpageattributes - pdf.setpagesattributes = setpagesattributes - end) - -end - -local addtocache, flushcache, cache do - - local data, d = { }, 0 - local list, l = { }, 0 - local coffset = 0 - local indices = { } - - local maxsize = 32 * 1024 -- uncompressed - local maxcount = 0xFF - - addtocache = function(n,str) - local size = #str - if size == 0 then - -- todo: message - return - end - if coffset + size > maxsize or d == maxcount then - flushcache() - end - if d == 0 then - nofobjects = nofobjects + 1 - objects[nofobjects] = false - streams[nofobjects] = indices - cache = nofobjects - end - objects[n] = - cache - indices[n] = d - d = d + 1 - -- can have a comment n 0 obj as in luatex - data[d] = str - l = l + 1 ; list[l] = n - l = l + 1 ; list[l] = coffset - coffset = coffset + size + 1 - end - - local p_ObjStm = pdfconstant("ObjStm") - - flushcache = function() -- references cannot be stored - if l > 0 then - list = concat(list," ") - data[0] = list - data = concat(data,"\010",0,d) - local strobj = pdfdictionary { - Type = p_ObjStm, - N = d, - First = #list + 1, - } - objects[cache] = offset - local b = nil - local e = s_stream_e - if compress then - local comp = zlibcompress(data,3) - if comp and #comp < #data then - data = comp - b = f_stream_b_d_c(cache,strobj(),#data) - else - b = f_stream_b_d_u(cache,strobj(),#data) - end - else - b = f_stream_b_d_u(cache,strobj(),#data) - end - flush(f,b) - flush(f,data) - flush(f,e) - offset = offset + #b + #data + #e - data, d = { }, 0 - list, l = { }, 0 - coffset = 0 - indices = { } - end - end - -end - -local function pdfreserveobj() - nofobjects = nofobjects + 1 - objects[nofobjects] = false - return nofobjects -end - -local pages = table.setmetatableindex(function(t,k) - local v = pdfreserveobj() - t[k] = v - return v -end) - -local function getpageref(n) - return pages[n] -end - -local function refobj() - -- not needed, as we have auto-delay -end - -local function flushnormalobj(data,n) - if not n then - nofobjects = nofobjects + 1 - n = nofobjects - end - data = f_object(n,data) - if level == 0 then - objects[n] = offset - offset = offset + #data - flush(f,data) - else - if not lastdeferred then - lastdeferred = n - elseif n < lastdeferred then - lastdeferred = n - end - objects[n] = data - end - return n -end - -local function flushstreamobj(data,n,dict,comp,nolength) - if not data then - report("no data for %S",dict) - return - end - if not n then - nofobjects = nofobjects + 1 - n = nofobjects - end - local size = #data - if level == 0 then - local b = nil - local e = s_stream_e - if nolength then - b = f_stream_b_d_r(n,dict) - elseif comp ~= false and compress and size > threshold then - local compdata = zlibcompress(data,3) - if compdata then - local compsize = #compdata - if compsize > size - threshold then - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - else - data = compdata - b = dict and f_stream_b_d_c(n,dict,compsize) or f_stream_b_n_c(n,compsize) - end - else - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - end - else - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - end - flush(f,b) - flush(f,data) - flush(f,e) - objects[n] = offset - offset = offset + #b + #data + #e - else - if nolength then - data = f_stream_d_r(n,dict,data) - elseif comp ~= false and compress and size > threshold then - local compdata = zlibcompress(data,3) - if compdata then - local compsize = #compdata - if compsize > size - threshold then - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - else - data = dict and f_stream_d_c(n,dict,compsize,compdata) or f_stream_n_c(n,compsize,compdata) - end - else - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - end - else - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - end - if not lastdeferred then - lastdeferred = n - elseif n < lastdeferred then - lastdeferred = n - end - objects[n] = data - end - return n -end - -flushdeferred = function() -- was forward defined - if lastdeferred then - for n=lastdeferred,nofobjects do - local o = objects[n] - if type(o) == "string" then - objects[n] = offset - offset = offset + #o - flush(f,o) - end - end - lastdeferred = false - end -end - --- n = pdf.obj([n,] objtext) --- n = pdf.obj([n,] "file", filename) --- n = pdf.obj([n,] "stream", streamtext [, attrtext]) --- n = pdf.obj([n,] "streamfile", filename [, attrtext]) --- --- n = pdf.obj { --- type = , -- raw|stream --- immediate = , --- objnum = , --- attr = , --- compresslevel = , --- objcompression = , --- file = , --- string = , --- nolength = , --- } - -local function obj(a,b,c,d) - local kind --, immediate - local objnum, data, attr, filename - local compresslevel, objcompression, nolength - local argtype = type(a) - if argtype == "table" then - kind = a.type -- raw | stream - -- immediate = a.immediate - objnum = a.objnum - attr = a.attr - compresslevel = a.compresslevel - objcompression = a.objcompression - filename = a.file - data = a.string or a.stream or "" - nolength = a.nolength - if kind == "stream" then - if filename then - data = loaddata(filename) or "" - end - elseif kind == "raw"then - if filename then - data = loaddata(filename) or "" - end - elseif kind == "file"then - kind = "raw" - data = filename and loaddata(filename) or "" - elseif kind == "streamfile" then - kind = "stream" - data = filename and loaddata(filename) or "" - end - else - if argtype == "number" then - objnum = a - a, b, c = b, c, d - else - nofobjects = nofobjects + 1 - objnum = nofobjects - end - if b then - if a == "stream" then - kind = "stream" - data = b - elseif a == "file" then - -- kind = "raw" - data = loaddata(b) - elseif a == "streamfile" then - kind = "stream" - data = loaddata(b) - else - data = "" -- invalid object - end - attr = c - else - -- kind = "raw" - data = a - end - end - if not objnum then - nofobjects = nofobjects + 1 - objnum = nofobjects - end - -- todo: immediate - if kind == "stream" then - flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) - elseif objectstream and objcompression ~= false then - addtocache(objnum,data) - else - flushnormalobj(data,objnum) - end - return objnum -end - -updaters.register("backend.update.pdf",function() - pdf.reserveobj = pdfreserveobj - pdf.getpageref = getpageref - pdf.refobj = refobj - pdf.flushstreamobj = flushstreamobj - pdf.flushnormalobj = flushnormalobj - pdf.obj = obj - pdf.immediateobj = obj -end) - --- In lua 5.4 the methods are now moved one metalevel deeper so we need to get them --- from mt.__index instead. (I did get that at first.) It makes for a slightly (imo) --- nicer interface but no real gain in speed as we don't flush that often. - -local openfile, closefile do - - -- I used to do but then figured out that when I open and save a file in a mode - -- that removes trailing spaces, the xref becomes invalid. The problem was then that a - -- reconstruction of the file by a viewer gives weird effects probably because percent symbols - -- gets interpreted then. Thanks to Ross Moore for noticing this side effect! - - local f_used = formatters["%010i 00000 n\013\010"] - local f_link = formatters["%010i 00000 f\013\010"] - local f_first = formatters["%010i 65535 f\013\010"] - - local f_pdf = formatters["%%PDF-%i.%i\010"] - local f_xref = formatters["xref\0100 %i\010"] - local f_trailer_id = formatters["trailer\010<< %s /ID [ <%s> <%s> ] >>\010startxref\010%i\010%%%%EOF"] - local f_trailer_no = formatters["trailer\010<< %s >>\010startxref\010%i\010%%%%EOF"] - local f_startxref = formatters["startxref\010%i\010%%%%EOF"] - - local inmemory = false - local close = false - local update = false - - -- local removefile = os.remove - - openfile = function(filename) - if inmemory then - local n = 0 - f = { } - flush = function(f,s) - n = n + 1 f[n] = s - -- offset = offset + #s - end - close = function(f) - f = concat(f) - io.savedata(filename,f) - f = false - end - update = function(f,s) - f[1] = s - end - -- local n = 0 - -- f = { - -- write = function(self,s) - -- n = n + 1 f[n] = s - -- end, - -- close = function(self) - -- f = concat(f) - -- io.savedata(filename,f) - -- f = false - -- end, - -- } - else - f = io.open(filename,"wb") - if not f then - -- message - os.exit() - end - -- f:setvbuf("full",64*1024) - local m = getmetatable(f) - flush = m.write or m.__index.write - close = m.close or m.__index.close - update = function(f,s) - f:seek("set",0) - f:write(s) - end - end - local v = f_pdf(majorversion,minorversion) - -- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128) - local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128) - flush(f,v) - flush(f,b) - offset = offset + #v + #b - end - - closefile = function(abort) - if abort then - close(f) - if not environment.arguments.nodummy then - f = io.open(abort,"wb") - if f then - local name = resolvers.findfile("context-lmtx-error.pdf") - if name then - local data = io.loaddata(name) - if data then - f:write(data) - f:close() - return - end - end - f:close() - end - end - os.remove(abort) - else - local xrefoffset = offset - local lastfree = 0 - local noffree = 0 - local catalog = lpdf.getcatalog() - local info = lpdf.getinfo() - if trailerid == true then - trailerid = md5HEX(osuuid()) - elseif trailerid and #trailerid > 32 then - trailerid = md5HEX(trailerid) - else - trailerid = false - end - if objectstream then - flushdeferred() - flushcache() - -- - xrefoffset = offset - -- - nofobjects = nofobjects + 1 - objects[nofobjects] = offset -- + 1 - -- - -- combine these three in one doesn't really give less code so - -- we go for the efficient ones - -- - local nofbytes = 4 - local c1, c2, c3, c4 - if offset <= 0xFFFF then - nofbytes = 2 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,8,8) - c2 = extract(o,0,8) - if strm then - objects[i] = char(2,c1,c2,streams[o][i]) - else - objects[i] = char(1,c1,c2,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,8,8) - local f2 = extract(lastfree,0,8) - objects[i] = char(0,f1,f2,0) - lastfree = i - end - end - end - elseif offset <= 0xFFFFFF then - nofbytes = 3 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,16,8) - c2 = extract(o, 8,8) - c3 = extract(o, 0,8) - if strm then - objects[i] = char(2,c1,c2,c3,streams[o][i]) - else - objects[i] = char(1,c1,c2,c3,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,16,8) - local f2 = extract(lastfree, 8,8) - local f3 = extract(lastfree, 0,8) - objects[i] = char(0,f1,f2,f3,0) - lastfree = i - end - end - end - else - nofbytes = 4 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,24,8) - c2 = extract(o,16,8) - c3 = extract(o, 8,8) - c4 = extract(o, 0,8) - if strm then - objects[i] = char(2,c1,c2,c3,c4,streams[o][i]) - else - objects[i] = char(1,c1,c2,c3,c4,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,24,8) - local f2 = extract(lastfree,16,8) - local f3 = extract(lastfree, 8,8) - local f4 = extract(lastfree, 0,8) - objects[i] = char(0,f1,f2,f3,f4,0) - lastfree = i - end - end - end - end - objects[0] = rep("\0",1+nofbytes+1) - local data = concat(objects,"",0,nofobjects) - local xref = pdfdictionary { - Type = pdfconstant("XRef"), - Size = nofobjects + 1, - W = pdfarray { 1, nofbytes, 1 }, - Root = catalog, - Info = info, - ID = trailerid and pdfarray { pdfliteral(trailerid,true), pdfliteral(trailerid,true) } or nil, - } - if compress then - local comp = zlibcompress(data,3) - if comp then - data = comp - flush(f,f_stream_b_d_c(nofobjects,xref(),#data)) - else - flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) - end - else - flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) - end - flush(f,data) - flush(f,s_stream_e) - flush(f,f_startxref(xrefoffset)) - else - flushdeferred() - xrefoffset = offset - flush(f,f_xref(nofobjects+1)) - local trailer = pdfdictionary { - Size = nofobjects+1, - Root = catalog, - Info = info, - } - for i=1,nofobjects do - local o = objects[i] - if o then - objects[i] = f_used(o) - end - end - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - objects[i] = f_link(lastfree) - lastfree = i - end - end - objects[0] = f_first(lastfree) - flush(f,concat(objects,"",0,nofobjects)) - trailer.Size = nofobjects + 1 - if trailerid then - flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset)) - else - flush(f,f_trailer_no(trailer(),xrefoffset)) - end - end - update(f,f_pdf(majorversion,minorversion)) - close(f) - end - io.flush() - closefile = function() end - end - -end - --- For the moment we overload it here, although back-fil.lua eventually will --- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so. - -updaters.register("backend.update.pdf",function() - - -- We overload img but at some point it will even go away, so we just - -- reimplement what we need in context. This will change completely i.e. - -- we will drop the low level interface! - - local codeinjections = backends.pdf.codeinjections - - local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream - local img_none = imagetypes.none - - local rulecodes = nodes.rulecodes - - local setprop = nodes.nuts.setprop - - local report_images = logs.reporter("backend","images") - - local lastindex = 0 - local indices = { } - - local bpfactor = number.dimenfactors.bp - local imagerule_code = rulecodes.image - - function codeinjections.newimage(specification) - return specification - end - - function codeinjections.copyimage(original) - return setmetatableindex(original) - end - - function codeinjections.scanimgage(specification) - return specification - end - - local function embedimage(specification) - if specification then - lastindex = lastindex + 1 - index = lastindex - specification.index = index - local xobject = pdfdictionary { } - if not specification.notype then - xobject.Type = pdf_xobject - xobject.Subtype = pdf_form - xobject.FormType = 1 - end - local bbox = specification.bbox - if bbox and not specification.nobbox then - xobject.BBox = pdfarray { - bbox[1] * bpfactor, - bbox[2] * bpfactor, - bbox[3] * bpfactor, - bbox[4] * bpfactor, - } - end - xobject = xobject + specification.attr - if bbox and not specification.width then - specification.width = bbox[3] - end - if bbox and not specification.height then - specification.height = bbox[4] - end - local dict = xobject() - -- - nofobjects = nofobjects + 1 - local objnum = nofobjects - local nolength = specification.nolength - local stream = specification.stream or specification.string - -- - -- We cannot set type in native img so we need this hack or - -- otherwise we need to patch too much. Better that i write - -- a wrapper then. Anyway, it has to be done better: a key that - -- tells either or not to scale by xsize/ysize when flushing. - -- - if not specification.type then - local kind = specification.kind - if kind then - -- take that one - elseif attr and find(attr,"BBox") then - kind = img_stream - else - -- hack: a bitmap - kind = img_none - end - specification.type = kind - specification.kind = kind - end - local compress = compresslevel and compresslevel > 0 or nil - flushstreamobj(stream,objnum,dict,compress,nolength) - specification.objnum = objnum - specification.rotation = specification.rotation or 0 - specification.orientation = specification.orientation or 0 - specification.transform = specification.transform or 0 - specification.stream = nil - specification.attr = nil - specification.type = specification.kind or specification.type or img_none - indices[index] = specification -- better create a real specification - return specification - end - end - - codeinjections.embedimage = embedimage - - function codeinjections.wrapimage(specification) - -- - local index = specification.index - if not index then - embedimage(specification) - end - -- - local width = specification.width or 0 - local height = specification.height or 0 - local depth = specification.depth or 0 - -- newimagerule - local n = nodes.pool.rule(width,height,depth) - n.subtype = imagerule_code - setprop(tonut(n),"index",specification.index) - return n - end - - function pdf.includeimage(index) - local specification = indices[index] - if specification then - local bbox = specification.bbox - local xorigin = bbox[1] - local yorigin = bbox[2] - local xsize = bbox[3] - xorigin -- we need the original ones, not the 'rotated' ones - local ysize = bbox[4] - yorigin -- we need the original ones, not the 'rotated' ones - local transform = specification.transform or 0 - local objnum = specification.objnum or pdfreserveobj() - local groupref = nil - local kind = specification.kind or specification.type or img_none -- determines scaling type - return - kind, - xorigin, yorigin, - xsize, ysize, - transform, - objnum, - groupref - end - end - -end) - -updaters.register("backend.update.lpdf",function() - - -- todo: an md5 or sha2 hash can save space - -- todo: make a type 3 font instead - -- todo: move to lpdf namespace - - local pdfimage = lpdf.epdf.image - local newpdf = pdfimage.new - local openpdf = pdfimage.open - local closepdf = pdfimage.close - local copypage = pdfimage.copy - - local embedimage = images.embed - - local nofstreams = 0 - local topdf = { } - local toidx = { } - - local function storedata_s(pdf) - local idx = toidx[pdf] - if not idx then - nofstreams = nofstreams + 1 - idx = nofstreams - toidx[pdf] = nofstreams - topdf[idx] = pdf - end - return idx - end - - local function vfimage_s(id,wd,ht,dp,pos_h,pos_v) - local index = topdf[id] - if type(index) == "string" then - local pdfdoc = newpdf(index,#index) - local image = copypage(pdfdoc) - local bbox = image.bbox - image.width = bbox[3] - bbox[1] - image.height = bbox[4] - bbox[2] - embedimage(image) - index = image.index - topdf[id] = index - end - -- pdf.print or pdf.literal - flushimage(index,wd,ht,dp,pos_h,pos_v) - end - - local function storedata_n(name,page) - local idx = toidx[pdf] - if not idx then - nofstreams = nofstreams + 1 - idx = nofstreams - toidx[pdf] = nofstreams - topdf[idx] = pdf - end - return idx - end - - -- We need to have a way to close such a pdf ... esp for fonts. - - local pdfdocs = { } - - local function vfimage_n(name,page,wd,ht,dp,pos_h,pos_v) - local d = pdfdocs[name] - if not d then - d = { doc = openpdf(name), pages = { } } - pdfdocs[name] = d - end - local index = d.pages[page] - if not index then - local image = copypage(d.doc,page) - local bbox = image.bbox - image.width = bbox[3] - bbox[1] - image.height = bbox[4] - bbox[2] - embedimage(image) - index = image.index - d.pages[page] = index - end - flushimage(index,wd,ht,dp,pos_h,pos_v) - end - - local function pdfvfimage(wd,ht,dp,data,name) - if type(data) == "number" then - return { "lua", function(font,char,pos_h,pos_v) - vfimage_n(name,data,wd,ht,dp,pos_h,pos_v) - end } - else - return { "lua", function(font,char,pos_h,pos_v) - local id = storedata_s(data) - vfimage_s(id,wd,ht,dp,pos_h,pos_v) - end } - end - end - - lpdf.vfimage = pdfvfimage - -end) - --- The driver. - -do - - -- local addsuffix = file.addsuffix - local texgetbox = tex.getbox - - local pdfname = nil - local converter = nil - local useddriver = nil -- a bit of a hack - - local function outputfilename(driver) - return pdfname - end - - -- todo: prevent twice - - local function prepare(driver) - if not environment.initex then - -- install new functions in pdf namespace - updaters.apply("backend.update.pdf") - -- install new functions in lpdf namespace - updaters.apply("backend.update.lpdf") - -- adapt existing shortcuts to lpdf namespace - updaters.apply("backend.update.tex") - -- adapt existing shortcuts to tex namespace - updaters.apply("backend.update") - -- - -- if rawget(pdf,"setforcefile") then - -- pdf.setforcefile(false) -- default anyway - -- end - -- - -- pdfname = file.addsuffix(tex.jobname,"pdf") - pdfname = tex.jobname .. ".pdf" - openfile(pdfname) - -- - luatex.registerstopactions(1,function() - if pdfname then - lpdf.finalizedocument() - closefile() - end - end) - -- - luatex.registerpageactions(1,function() - if pdfname then - lpdf.finalizepage(true) - end - end) - -- -- - lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up") - -- - end - -- - environment.lmtxmode = CONTEXTLMTXMODE - -- - converter = drivers.converters.lmtx - useddriver = driver - end - - local function wrapup(driver) - if pdfname then - closefile() - pdfname = nil - end - end - - local function cleanup(driver) - if pdfname then - closefile(pdfname) - pdfname = nil - end - end - - local function convert(driver,boxnumber) - converter(driver,texgetbox(boxnumber),"page") - end - - localconverter = function(...) - converter(useddriver,...) - end - - drivers.install { - name = "pdf", - flushers = { - character = flushcharacter, - fontchar = flushfontchar, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - pushorientation = pushorientation, - poporientation = poporientation, - -- - literal = flushliteral, - setmatrix = flushsetmatrix, - save = flushsave, - restore = flushrestore, - image = flushimage, - group = flushgroup, - -- - updatefontstate = updatefontstate, - }, - actions = { - prepare = prepare, - wrapup = wrapup, - cleanup = cleanup, - -- - initialize = initialize, - convert = convert, - finalize = finalize, - -- - outputfilename = outputfilename, - }, - } - -end diff --git a/tex/context/base/mkiv/lpdf-vfc.lmt b/tex/context/base/mkiv/lpdf-vfc.lmt deleted file mode 100644 index 65b863203..000000000 --- a/tex/context/base/mkiv/lpdf-vfc.lmt +++ /dev/null @@ -1,40 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-vfc'] = { - 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 setmetatableindex = table.setmetatableindex - -local defaultline = 16384 -local vfspecials = backends.pdf.tables.vfspecials - -vfspecials.backgrounds = setmetatableindex(function(t,h) - local v = setmetatableindex(function(t,d) - local v = setmetatableindex(function(t,w) - local v = { "frame", w, h, d, defaultline, true, true } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -vfspecials.outlines = setmetatableindex(function(t,h) - local v = setmetatableindex(function(t,d) - local v = setmetatableindex(function(t,w) - local v = { "frame", w, h, d, defaultline, false, true } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) diff --git a/tex/context/base/mkiv/luat-cod.lmt b/tex/context/base/mkiv/luat-cod.lmt deleted file mode 100644 index e4432345e..000000000 --- a/tex/context/base/mkiv/luat-cod.lmt +++ /dev/null @@ -1,304 +0,0 @@ -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, tonumber = type, loadfile, tonumber -local match, gsub, find, format, gmatch = string.match, string.gsub, string.find, string.format, string.gmatch - -local texconfig, lua = texconfig, lua - --- maybe pick up from commandline: --- --- texconfig.interaction: 0=batchmode 1=nonstopmode 2=scrollmode 3=errornonstopmode 4=normal - --- some basic housekeeping - -texconfig.kpse_init = false -- not needed in lmtx -texconfig.shell_escape = 't' -- not needed in lmtx - -texconfig.max_in_open = 2000 -texconfig.nest_size = 10000 -texconfig.param_size = 100000 -texconfig.save_size = 500000 -texconfig.stack_size = 100000 -texconfig.buffer_size = 10000000 -texconfig.token_size = 10000000 -texconfig.node_size = 50000000 - -texconfig.max_print_line = 100000 -texconfig.max_strings = 500000 -texconfig.max_pool = 10000000 - -texconfig.hash_extra = 200000 - -texconfig.expand_depth = 10000 -texconfig.function_size = 32768 -texconfig.properties_size = 10000 -texconfig.error_line = 250 -texconfig.half_error_line = 125 - --- registering bytecode chunks - -local bytedata = lua.bytedata or { } -local bytedone = lua.bytedone or { } - ----.bytecode = bytecode -lua.bytedata = bytedata -lua.bytedone = bytedone - -local setbytecode = lua.setbytecode ------ getbytecode = lua.getbytecode - -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.* and utilities.parsers.* functions yet - -local strip = false if arg then for i=-1,#arg do if arg[i] == "--c:strip" then strip = true break end end end - -function lua.registercode(filename,options) - local barename = gsub(filename,"%.[%a%d]+$","") - local basename = match(barename,"^.+[/\\](.-)$") or barename - if not bytedone[basename] then - local opts = { } - if type(options) == "string" and options ~= "" then - for s in gmatch(options,"([a-z]+)") do - opts[s] = true - end - end - if barename == filename then - filename = filename .. (opts.autosuffix and CONTEXTLMTXMODE > 0 and ".lmt" or ".lua") - end - local code = environment.luafilechunk(filename,false,opts.optimize) - if code then - bytedone[basename] = true - if environment.initex and not opts.initexonly then - local n = lua.lastbytecode + 1 - bytedata[n] = { name = barename, options = opts } - if strip or opts.strip then - setbytecode(n,code,true) - else - setbytecode(n,code) - end - lua.lastbytecode = n - end - elseif environment.initex then - texio.write_nl(format("\nerror loading file: %s (aborting)",filename)) - 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) - --- traditionally the revision has been a one character string and only --- pdftex went beyond "9" but anyway we test for it - -if LUATEXENGINE == nil then - LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) - or (find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") -end - -if LUATEXVERSION == nil then - LUATEXVERSION = status.luatex_version/100 - + tonumber(status.luatex_revision)/10000 -end - -if CONTEXTLMTXMODE == nil then - CONTEXTLMTXMODE = LUATEXENGINE == "luametatex" and 1 or 0 -end - -if LUATEXFUNCTIONALITY == nil then - LUATEXFUNCTIONALITY = status.development_id or 6346 -end - -if LUATEXFORMATID == nil then - LUATEXFORMATID = status.format_id or 0 -end - -if JITSUPPORTED == nil then - JITSUPPORTED = LUATEXENGINE == "luajittex" or jit -- "or jit" can go -end - -if INITEXMODE == nil then - INITEXMODE = status.ini_version -end - -environment.luatexengine = LUATEXENGINE -environment.luatexversion = LUATEXVERSION -environment.luatexfunctionality = LUATEXFUNCTIONALITY -environment.jitsupported = JITSUPPORTED -environment.initex = INITEXMODE -environment.initexmode = INITEXMODE - --- if INITEXMODE then --- -- we have about that amount so we preallocate then which gives less --- -- reallocations (we're talking tiny record so no real gain) --- lua.setbytecode(1024,nil) --- -- but we don't want to lie about the amount either so ... --- end - -if not environment.luafilechunk then - - function environment.luafilechunk(filename) - local fullname = filename - if sourcepath ~= "" then - fullname = sourcepath .. "/" .. filename - end - local data = loadfile(fullname) - texio.write("terminal_and_logfile","<",data and "+ " or "- ",fullname,">") - if data then --- package.loaded[gsub(filename,"%..-$"] = - 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. - --- print("!!!!!!!!!!!!!!!!!!!!!!",lfs.isfile) os.exit() - -if not lfs.isfile then - - local attributes = lfs.attributes - - function lfs.isdir(name) - return attributes(name,"mode") == "directory" - end - - function lfs.isfile(name) - local a = attributes(name,"mode") - return a == "file" or a == "link" or nil - end - -end - -local isfile = lfs.isfile - -local function source_file(name) - 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_log_file(name) - return target_file(name) -end - -local function find_data_file(name) - return source_file(name) -end - -local function open_data_file(name) - local fullname = source_file(name) - if fullname then - local f = io.open(fullname,'rb') - return { - reader = function() - return f:read("*line") - end - } - else - return false - end -end - -callback.register('find_log_file', find_log_file) -callback.register('find_data_file' , find_data_file ) -callback.register('open_data_file' , open_data_file ) - -callback.register("trace_memory", function(what,success) - success = success and "succeeded" or "failed" - if logs then - logs.report("tex memory","bumping category %a %s, details: %s", - what,success,table.sequenced(status["get"..what.."state"]())) - elseif texio then - texio.write_nl(format("bumping tex '%s' memory %s", - what,success)) - end - -- os.exit() -end) diff --git a/tex/context/base/mkiv/luat-cod.mkxl b/tex/context/base/mkiv/luat-cod.mkxl deleted file mode 100644 index fec88aecd..000000000 --- a/tex/context/base/mkiv/luat-cod.mkxl +++ /dev/null @@ -1,45 +0,0 @@ -%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 - -\newif\ifproductionrun - -\permanent\let\ctxdirectlua \directlua -\permanent\let\ctxlatelua \latelua -\permanent\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens -\permanent\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens -\permanent\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens -\permanent\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens -\permanent\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens -\permanent\def\ctxreport #1{\directlua{logs.writer[[#1]]}} - -%D Take your choice \unknown - -\aliased\let\ctxlua \ctxdirectlua -\aliased\let\luacode \ctxdirectlua -\aliased\let\lateluacode \ctxlatelua -\aliased\let\directluacode\ctxdirectlua - -%D Reporting the version of \LUA\ that we use is done as follows: - -\permanent\def\luaversion{\ctxwrite{LUAVERSION}} - -\permanent\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}} -\permanent\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}} - -\registerctxluafile{luat-cod.lmt}{autosuffix} - -\protect \endinput diff --git a/tex/context/base/mkiv/luat-fio.lmt b/tex/context/base/mkiv/luat-fio.lmt deleted file mode 100644 index c70ed54e4..000000000 --- a/tex/context/base/mkiv/luat-fio.lmt +++ /dev/null @@ -1,107 +0,0 @@ -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 - -texconfig.kpse_init = false -- can go away -texconfig.shell_escape = 't' -- can go away -texconfig.max_print_line = 100000 -- can go away -texconfig.max_in_open = 1000 -- can go away - -if not resolvers.initialized() then - - resolvers.reset() - - -- we now load the file database as we might need files other than - -- tex and lua file on the given path - - resolvers.load() - - if callback then - - local findbinfile = resolvers.findbinfile - local findtexfile = resolvers.findtexfile - local opentexfile = resolvers.opentexfile - local register = callbacks.register - - local ioflush = io.flush - local ioread = io.read - local writenl = texio.write_nl - - local function terminal() - writenl("\ntex console > ") - ioflush() - local line = ioread() - writenl("") - ioflush() - return line - end - - -- local function find_data_file(name) - -- if not name or name == "" then - -- return "context terminal" - -- else - -- return findbinfile(name,"tex") - -- end - -- end - -- - -- local function open_data_file(name) - -- if not name or name == "" or name == "context terminal" then - -- return { - -- reader = terminal, - -- noflines = 1, - -- filename = name, - -- } - -- else - -- name = opentexfile(name) - -- return name ~= "" and name or false - -- end - -- end - - local function open_data_file(name) - if not name or name == "" then - return { - reader = terminal, - noflines = 1, - filename = "context terminal" - } - else - local fullname = findbinfile(name,"tex") - if fullname then - return opentexfile(fullname) - else - return false - end - end - end - - local function find_any_file(name) - return name - end - - register('find_log_file' , find_any_file, true) - register('find_format_file', find_any_file, true) - -- register('find_data_file' , find_data_file, true) - register('open_data_file' , open_data_file, 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.foundintrees(), - #scandata.paths > 0 and concat(scandata.paths," ") or "" - ) -end) diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv index 053e2ea4d..09014ad86 100644 --- a/tex/context/base/mkiv/luat-ini.mkiv +++ b/tex/context/base/mkiv/luat-ini.mkiv @@ -130,7 +130,6 @@ \protected\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}} \def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax} \def\getdocumentargument #1{\clf_getdocumentargument{#1}{}} -\protected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} \def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}} % seldom used so no need for speedy variants: diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv index e89747de7..6dbcdaf54 100644 --- a/tex/context/base/mkiv/luat-lib.mkiv +++ b/tex/context/base/mkiv/luat-lib.mkiv @@ -45,10 +45,6 @@ \registerctxluafile{util-soc-imp-http} {} \registerctxluafile{util-soc-imp-tp} {} -\ifcase\contextlmtxmode\else - \registerctxluafile{util-zip}{} -\fi - \registerctxluafile{data-ini}{} \registerctxluafile{data-exp}{} \registerctxluafile{data-env}{} @@ -73,10 +69,6 @@ \registerctxluafile{data-use}{} \registerctxluafile{data-aux}{} -% \ifcase\contextlmtxmode -% \registerctxluafile{util-lib}{} -% \fi - \registerctxluafile{luat-cbk}{} \registerctxluafile{luat-run}{} \registerctxluafile{luat-fio}{autosuffix} @@ -99,8 +91,8 @@ \registerctxluafile{lxml-aux}{} \registerctxluafile{lxml-mis}{} -\frozen\overloaded\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}} -\frozen\overloaded\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}} -\frozen\overloaded\protected\def\writeline {\ctxlua{logs.newline()}} +\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}} +\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}} +\protected\def\writeline {\ctxlua{logs.newline()}} \endinput diff --git a/tex/context/base/mkiv/luat-log.lmt b/tex/context/base/mkiv/luat-log.lmt deleted file mode 100644 index 684b2ac8d..000000000 --- a/tex/context/base/mkiv/luat-log.lmt +++ /dev/null @@ -1,739 +0,0 @@ -if not modules then modules = { } end modules ['luat-log'] = { - version = 1.001, - comment = "companion to trac-log.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- In fact all writes could go through lua and we could write the console and --- terminal handler in lua then. Ok, maybe it's slower then, so a no-go. - --- This used to be combined in trac-log but as we also split between mkiv and lmtx --- we now have dedicated files. A side effect is a smaller format and a smaller --- mtxrun. --- --- We use different targets: "terminal" "logfile", "both" and have no number --- channel. - -local next, type, select, print = next, type, select, print -local format, gmatch, find = string.format, string.gmatch, string.find -local concat, insert, remove = table.concat, table.insert, table.remove -local topattern = string.topattern -local utfchar = utf.char -local datetime = os.date -local openfile = io.open - -local write_nl = texio.write_nl -local write = texio.write - -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local settings_to_hash = utilities.parsers.settings_to_hash -local sortedkeys = table.sortedkeys - --- variant is set now - -local variant = "default" ------ variant = "ansi" - -logs = logs or { } -local logs = logs - --- we extend the formatters: - -formatters.add ( - formatters, "unichr", - [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] -) - -formatters.add ( - formatters, "chruni", - [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] -) - --- basic loggers - -local function ignore() end - -setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) - -local report, subreport, status, settarget, setformats, settranslations - -local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline - --- we use formatters but best check for % then because for simple messages but --- we don't want this overhead for single messages (not that there are that --- many; we could have a special weak table) - -local function ansisupported(specification) - if specification ~= "ansi" and specification ~= "ansilog" then - return false - elseif os and os.enableansi then - return os.enableansi() - else - return false - end -end - -do - - if arg and ansisupported then - -- we're don't have environment.arguments yet - for k, v in next, arg do -- k can be negative ! - if v == "--ansi" or v == "--c:ansi" then - if ansisupported("ansi") then - variant = "ansi" - end - break - elseif v == "--ansilog" or v == "--c:ansilog" then - if ansisupported("ansilog") then - variant = "ansilog" - end - break - end - end - end - - local whereto = "both" - local target = nil - local targets = nil - - local formats = table.setmetatableindex("self") - local translations = table.setmetatableindex("self") - - local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes - local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop - - local variants = { - default = { - formats = { - report_yes = formatters["%-15s > %s\n"], - report_nop = formatters["%-15s >\n"], - direct_yes = formatters["%-15s > %s"], - direct_nop = formatters["%-15s >"], - subreport_yes = formatters["%-15s > %s > %s\n"], - subreport_nop = formatters["%-15s > %s >\n"], - subdirect_yes = formatters["%-15s > %s > %s"], - subdirect_nop = formatters["%-15s > %s >"], - status_yes = formatters["%-15s : %s\n"], - status_nop = formatters["%-15s :\n"], - }, - targets = setmetatableindex( { - logfile = "logfile", - log = "logfile", - file = "logfile", - console = "terminal", - terminal = "terminal", - both = "terminal_and_logfile", - }, function(t,k) t[k] = "terminal_and_logfile" end), - }, - ansi = { - formats = { - report_yes = formatters["%-15s > %s\n"], - report_nop = formatters["%-15s >\n"], - direct_yes = formatters["%-15s > %s"], - direct_nop = formatters["%-15s >"], - subreport_yes = formatters["%-15s > %s > %s\n"], - subreport_nop = formatters["%-15s > %s >\n"], - subdirect_yes = formatters["%-15s > %s > %s"], - subdirect_nop = formatters["%-15s > %s >"], - status_yes = formatters["%-15s : %s\n"], - status_nop = formatters["%-15s :\n"], - }, - targets = setmetatableindex( { - logfile = false, - log = false, - file = false, - console = "terminal", - terminal = "terminal", - both = "terminal", - }, function(t,k) t[k] = "terminal" end), - } - } - - variants.ansilog = { - formats = variants.ansi.formats, - targets = variants.default.targets, - } - - logs.flush = io.flush - - writer = function(...) - if target then - write_nl(target,...) - end - end - - newline = function() - if target then - write_nl(target,"\n") - end - end - - report = function(a,b,c,...) - if not target then - -- ignore - elseif c ~= nil then - write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,report_yes(translations[a],formats[b])) - elseif a then - write_nl(target,report_nop(translations[a])) - else - write_nl(target,"\n") - end - end - - direct = function(a,b,c,...) - if not target then - return "" - elseif c ~= nil then - return direct_yes(translations[a],formatters[formats[b]](c,...)) - elseif b then - return direct_yes(translations[a],formats[b]) - elseif a then - return direct_nop(translations[a]) - else - return "" - end - end - - subreport = function(a,s,b,c,...) - if not target then - -- ignore - elseif c ~= nil then - write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) - elseif a then - write_nl(target,subreport_nop(translations[a],translations[s])) - else - write_nl(target,"\n") - end - end - - subdirect = function(a,s,b,c,...) - if not target then - return "" - elseif c ~= nil then - return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) - elseif b then - return subdirect_yes(translations[a],translations[s],formats[b]) - elseif a then - return subdirect_nop(translations[a],translations[s]) - else - return "" - end - end - - status = function(a,b,c,...) - if not target then - -- ignore - elseif c ~= nil then - write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,status_yes(translations[a],formats[b])) - elseif a then - write_nl(target,status_nop(translations[a])) - else - write_nl(target,"\n") - end - end - - settarget = function(askedwhereto) - whereto = askedwhereto or whereto or "both" - target = targets[whereto] - if not target then - whereto = "both" - target = targets[whereto] - end - if target == "terminal" or target == "terminal_and_logfile" then - logs.flush = io.flush - else - logs.flush = ignore - end - end - - local stack = { } - - pushtarget = function(newtarget) - insert(stack,target) - settarget(newtarget) - end - - poptarget = function() - if #stack > 0 then - settarget(remove(stack)) - end - end - - setformats = function(f) - formats = f - end - - settranslations = function(t) - translations = t - end - - setprocessor = function(f) - local writeline = write_nl - write_nl = function(target,...) - if target then - writeline(target,f(...)) - end - end - end - - setformatters = function(specification) - local t = nil - local f = nil - local d = variants.default - if not specification then - -- - elseif type(specification) == "table" then - t = specification.targets - f = specification.formats or specification - else - if not ansisupported(specification) then - specification = "default" - end - local v = variants[specification] - if v then - t = v.targets - f = v.formats - variant = specification - end - end - targets = t or d.targets - target = targets[whereto] - if f then - d = d.formats - else - f = d.formats - d = f - end - setmetatableindex(f,d) - report_yes = f.report_yes - report_nop = f.report_nop - subreport_yes = f.subreport_yes - subreport_nop = f.subreport_nop - direct_yes = f.direct_yes - direct_nop = f.direct_nop - subdirect_yes = f.subdirect_yes - subdirect_nop = f.subdirect_nop - status_yes = f.status_yes - status_nop = f.status_nop - settarget(whereto) - end - - setformatters(variant) - - setlogfile = ignore - settimedlog = ignore - -end - -logs.report = report -logs.subreport = subreport -logs.status = status -logs.settarget = settarget -logs.pushtarget = pushtarget -logs.poptarget = poptarget -logs.setformats = setformats -logs.settranslations = settranslations - -logs.setlogfile = setlogfile -logs.settimedlog = settimedlog -logs.setprocessor = setprocessor -logs.setformatters = setformatters - -logs.direct = direct -logs.subdirect = subdirect -logs.writer = writer -logs.newline = newline - -local data = { } -local states = nil -local force = false - -function logs.reporter(category,subcategory) - local logger = data[category] - if not logger then - local state = states == true - if not state and type(states) == "table" then - for c, _ in next, states do - if find(category,c) then - state = true - break - end - end - end - logger = { - reporters = { }, - state = state, - } - data[category] = logger - end - local reporter = logger.reporters[subcategory or "default"] - if not reporter then - if subcategory then - reporter = function(...) - if force or not logger.state then - subreport(category,subcategory,...) - end - end - logger.reporters[subcategory] = reporter - else - local tag = category - reporter = function(...) - if force or not logger.state then - report(category,...) - end - end - logger.reporters.default = reporter - end - end - return reporter -end - -logs.new = logs.reporter -- for old times sake - --- context specicific: this ends up in the macro stream - -local ctxreport = logs.writer - -function logs.setmessenger(m) - ctxreport = m -end - -function logs.messenger(category,subcategory) - -- we need to avoid catcode mess (todo: fast context) - if subcategory then - return function(...) - ctxreport(subdirect(category,subcategory,...)) - end - else - return function(...) - ctxreport(direct(category,...)) - end - end -end - --- so far - -local function setblocked(category,value) -- v.state == value == true : disable - if category == true or category == "all" then - -- lock all - category, value = "*", true - elseif category == false then - -- unlock all - category, value = "*", false - elseif value == nil then - -- lock selective - value = true - end - if category == "*" then - states = value - for k, v in next, data do - v.state = value - end - else - alllocked = false - states = settings_to_hash(category,type(states)=="table" and states or nil) - for c in next, states do - local v = data[c] - if v then - v.state = value - else - c = topattern(c,true,true) - for k, v in next, data do - if find(k,c) then - v.state = value - end - end - end - end - end -end - -function logs.disable(category,value) - setblocked(category,value == nil and true or value) -end - -function logs.enable(category) - setblocked(category,false) -end - -function logs.categories() - return sortedkeys(data) -end - -function logs.show() - local n, c, s, max = 0, 0, 0, 0 - for category, v in table.sortedpairs(data) do - n = n + 1 - local state = v.state - local reporters = v.reporters - local nc = #category - if nc > c then - c = nc - end - for subcategory, _ in next, reporters do - local ns = #subcategory - if ns > c then - s = ns - end - local m = nc + ns - if m > max then - max = m - end - end - local subcategories = concat(sortedkeys(reporters),", ") - if state == true then - state = "disabled" - elseif state == false then - state = "enabled" - else - state = "unknown" - end - -- no new here - report("logging","category %a, subcategories %a, state %a",category,subcategories,state) - end - report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) -end - -local delayed_reporters = { } - -setmetatableindex(delayed_reporters,function(t,k) - local v = logs.reporter(k.name) - t[k] = v - return v -end) - -function utilities.setters.report(setter,...) - delayed_reporters[setter](...) -end - -directives.register("logs.blocked", function(v) - setblocked(v,true) -end) - -directives.register("logs.target", function(v) - settarget(v) -end) - -do - - local report = logs.reporter("pages") -- not needed but saves checking when we grep for it - local texgetcount = tex and tex.getcount - - local real, user, sub = 0, 0, 0 - - function logs.start_page_number() - real = texgetcount("realpageno") - user = texgetcount("userpageno") - sub = texgetcount("subpageno") - end - - local timing = false - local usage = false - local lasttime = nil - - logs.private = { - enablepagetiming = function() - usage = true - end, - getpagetiming = function() - return type(usage) == "table" and usage - end, - } - - trackers.register("pages.timing", function() timing = "" end) - - function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average - if timing or usage then - local elapsed = statistics.currenttime(statistics) - local average, page - if not lasttime or real < 2 then - average = elapsed - page = elapsed - else - average = elapsed / (real - 1) - page = elapsed - lasttime - end - lasttime = elapsed - if timing then - timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) - end - if usage then - usage = { - page = { - real = real, - user = user, - sub = sub, - }, - time = { - elapsed = elapsed, - page = page, - average = average, - } - } - end - end - if real <= 0 then - report("flushing page%s",timing) - elseif user <= 0 then - report("flushing realpage %s%s",real,timing) - elseif sub <= 0 then - report("flushing realpage %s, userpage %s%s",real,user,timing) - else - report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) - end - logs.flush() - end - -end - --- we don't have show_open and show_close callbacks yet - -do - local texerror = tex and tex.error or print - local formatters = string.formatters - - function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here - texerror(first and formatters[fmt](first,...) or fmt) - end - -end - --- this is somewhat slower but prevents out-of-order messages when print is mixed --- with texio.write - --- io.stdout:setvbuf('no') --- io.stderr:setvbuf('no') - --- windows: > nul 2>&1 --- unix : > null 2>&1 - -if package.helpers.report then - package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun -end - -do - - local finalactions = { } - local fatalerrors = { } - local possiblefatal = { } - local loggingerrors = false - - function logs.loggingerrors() - return loggingerrors - end - - directives.register("logs.errors",function(v) - loggingerrors = v - if type(v) == "string" then - fatalerrors = settings_to_hash(v) - else - fatalerrors = { } - end - end) - - function logs.registerfinalactions(...) - insert(finalactions,...) -- so we can force an order if needed - end - - local what = nil - local report = nil - local state = nil - local target = nil - - local function startlogging(t,r,w,s) - target = t - state = force - force = true - report = type(r) == "function" and r or logs.reporter(r) - what = w - pushtarget(target) - newline() - if s then - report("start %s: %s",what,s) - else - report("start %s",what) - end - if target == "logfile" then - newline() - end - return report - end - - local function stoplogging() - if target == "logfile" then - newline() - end - report("stop %s",what) - if target == "logfile" then - newline() - end - poptarget() - state = oldstate - end - - function logs.startfilelogging(...) - return startlogging("logfile", ...) - end - - logs.stopfilelogging = stoplogging - - local done = false - - function logs.starterrorlogging(r,w,...) - if not done then - pushtarget("terminal") - newline() - logs.report("error logging","start possible issues") - poptarget() - done = true - end - if fatalerrors[w] then - possiblefatal[w] = true - end - return startlogging("terminal",r,w,...) - end - - logs.stoperrorlogging = stoplogging - - function logs.finalactions() - if #finalactions > 0 then - for i=1,#finalactions do - finalactions[i]() - end - if done then - pushtarget("terminal") - newline() - logs.report("error logging","stop possible issues") - poptarget() - end - return next(possiblefatal) and sortedkeys(possiblefatal) or false - end - end - -end - --- just in case we load from context - -local dummy = function() end - -function logs.application(t) - return { - name = t.name or tex.jobname, - banner = t.banner, - report = logs.reporter(t.name), - moreinfo = dummy, - export = dummy, - help = dummy, - identify = dummy, - version = dummy, - } -end diff --git a/tex/context/base/mkiv/lxml-css.mkxl b/tex/context/base/mkiv/lxml-css.mkxl deleted file mode 100644 index c7c8d8afd..000000000 --- a/tex/context/base/mkiv/lxml-css.mkxl +++ /dev/null @@ -1,76 +0,0 @@ -%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}{} - -\unprotect - -\permanent\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 - -% \startxmlsetups html:settings -% \xmlsetsetup{#1}{p}{html:p} -% \stopxmlsetups -% -% \xmlmapvalue{ctx-before} {one} {\page BEFORE\par} -% \xmlmapvalue{ctx-after} {two} {\par AFTER\page} -% \xmlmapvalue{text-decoration}{underline}{U} -% \xmlmapvalue{text-decoration}{overline} {O} -% -% \startxmlsetups html:p -% \testfeatureonce{100000}{ -% \edef\foo{\xmlcssstylevalue{#1}{ctx-before}\xmlcssstylevalue{#1}{ctx-after}} -% } -% \page {\tttf style="\xmlatt{#1}{style}"} : \elapsedtime\ s \page -% \xmlvalue{ctx-before}{\xmlcssstylevalue{#1}{ctx-before}}{} -% \xmlflush{#1} -% (\xmlcssstylevalue{#1}{text-decoration}) -% (\xmlcssmappedstylevalue{#1}{text-decoration}{text-decoration}) -% \xmlvalue{ctx-after} {\xmlcssstylevalue{#1}{ctx-after}}{} -% \stopxmlsetups -% -% \startbuffer[temp] -% -%

foo 1

-%

foo 2

-% -% \stopbuffer -% -% \xmlregistersetup{html:settings} -% \xmlprocessbuffer{main}{temp}{} - -% \xmlcssstylevalue % defined at lua end -% \xmlcssmappedstylevalue % defined at lua end - -\protect \endinput - diff --git a/tex/context/base/mkiv/lxml-ctx.mkxl b/tex/context/base/mkiv/lxml-ctx.mkxl deleted file mode 100644 index f4b2edc79..000000000 --- a/tex/context/base/mkiv/lxml-ctx.mkxl +++ /dev/null @@ -1,58 +0,0 @@ -%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}{} - -\unprotect - -\settrue \xmllshowbuffer -\setfalse\xmllshowtitle -\settrue \xmllshowwarning - -\definehead - [lshowtitle] - [subsubsubsubsubject] - -\setuphead - [lshowtitle] - [\c!style=\tta] - -\permanent\protected\def\xmllshow#1% - {\ctxlua{xml.ctx.tshow { - pattern = \!!bs\detokenize{#1}\!!es, - \ifconditional\xmllshowtitle - title = "lshowtitle", - \fi - \ifconditional\xmllshowwarning - warning = true, - \fi - } }} - -\permanent\protected\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/tex/context/base/mkiv/lxml-ini.mkxl b/tex/context/base/mkiv/lxml-ini.mkxl deleted file mode 100644 index e8d017bf3..000000000 --- a/tex/context/base/mkiv/lxml-ini.mkxl +++ /dev/null @@ -1,544 +0,0 @@ -%D \module -%D [ file=lxml-ini, -%D version=2007.08.17, -%D title=\CONTEXT\ \XML\ Support, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D Todo: auto apply setups (manage at lua end) -%D Todo: manuak: \xmlinclusion \xmlinclusions - -\writestatus{loading}{ConTeXt XML Support / Initialization} - -%registerctxluafile{lxml-tab}{} % loader -%registerctxluafile{lxml-lpt}{} % parser -%registerctxluafile{lxml-xml}{} % xml finalizers -%registerctxluafile{lxml-aux}{} % extras using parser -%registerctxluafile{lxml-mis}{} % extras independent of parser -\registerctxluafile{lxml-ent}{} % entity hacks -\registerctxluafile{lxml-tex}{} % tex finalizers -\registerctxluafile{lxml-dir}{} % ctx hacks -\registerctxluafile{lxml-ini}{} % interface - -\unprotect - -% todo: { } mandate so that we can alias - -% undocumented: - -\def\ctxlxml #1{\ctxlua{lxml.#1}} - -% for now indirect .. this will change when we have updated luatex (scan_argument) - -\permanent\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}} -\permanent\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}} - -%D Maybe I should add \type {\protected} here: - -\permanent\def\xmlloadfile #1#2{\clf_xmlloadfile {#1}{#2}{\directxmlparameter\c!compress}} -\permanent\def\xmlloadbuffer#1#2{\clf_xmlloadbuffer{#1}{#2}{\directxmlparameter\c!compress}} -\permanent\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}} - -\aliased\let\xmlload\xmlloadfile - -% aliased - -%let\xmlall \clf_xmlall -%let\xmlatt \clf_xmlatt -%let\xmlattdef \clf_xmlattdef -%let\xmlattribute \clf_xmlattribute -%let\xmlattributedef \clf_xmlattributedef -%let\xmlbadinclusions \clf_xmlbadinclusions -%let\xmlchainatt \clf_xmlchainatt -%let\xmlchainattdef \clf_xmlchainattdef -%let\xmlchecknamespace \clf_xmlchecknamespace -%let\xmlcommand \clf_xmlcommand -%let\xmlcontext \clf_xmlcontext -%let\xmlcount \clf_xmlcount -%let\xmldelete \clf_xmldelete -%let\xmldirect \clf_xmldirect % in loops, not dt but root -%let\xmldirectives \clf_xmldirectives -%let\xmldirectivesafter \clf_xmldirectivesafter -%let\xmldirectivesbefore \clf_xmldirectivesbefore -%let\xmldisplayverbatim \clf_xmldisplayverbatim -%let\xmlelement \clf_xmlelement -%let\xmlfilter \clf_xmlfilter -%let\xmlfilterlist \clf_xmlfilterlist -%let\xmlfirst \clf_xmlfirst -%let\xmlflush \clf_xmlflush -%let\xmlflushcontext \clf_xmlflushcontext -%let\xmlflushlinewise \clf_xmlflushlinewise -%let\xmlflushpure \clf_xmlflushpure -%let\xmlflushspacewise \clf_xmlflushspacewise -%let\xmlflushtext \clf_xmlflushtext -%let\xmlfunction \clf_xmlfunction -%let\xmlinclude \clf_xmlinclude -%let\xmlincludeoptions \clf_xmlincludeoptions -%let\xmlinclusion \clf_xmlinclusion -%let\xmlinclusionbase \clf_xmlinclusionbase -%let\xmlinclusions \clf_xmlinclusions -%let\xmlindex \clf_xmlindex -%let\xmlinlineverbatim \clf_xmlinlineverbatim -%let\xmllast \clf_xmllast -%let\xmllastatt \clf_xmllastatt -%let\xmllastmatch \clf_xmllastmatch -%let\xmllastpar \clf_xmllastpar -%let\xmlloaddirectives \clf_xmlloaddirectives -%let\xmlmain \clf_xmlmain -%let\xmlmatch \clf_xmlmatch -%let\xmlname \clf_xmlname -%let\xmlnamespace \clf_xmlnamespace -%let\xmlnonspace \clf_xmlnonspace -%let\xmlpar \clf_xmlpar -%let\xmlparam \clf_xmlparam -%let\xmlpath \clf_xmlpath -%let\xmlpopmatch \clf_xmlpopmatch -%let\xmlpos \clf_xmlpos -%let\xmlpure \clf_xmlpure -%let\xmlpushmatch \clf_xmlpushmatch -%let\xmlraw \clf_xmlraw -%let\xmlrefatt \clf_xmlrefatt -%let\xmlregisterns \clf_xmlregisterns % document -%let\xmlremapname \clf_xmlremapname % element -%let\xmlremapnamespace \clf_xmlremapnamespace % document -%let\xmlsave \clf_xmlsave -%let\xmlsetatt \clf_xmlsetatt -%let\xmlsetattribute \clf_xmlsetattribute -%let\xmlsetpar \clf_xmlsetpar -%let\xmlsetparam \clf_xmlsetparam -%let\xmlsetsetup \clf_xmlsetsetup -%let\xmlsnippet \clf_xmlsnippet -%let\xmlstrip \clf_xmlstrip -%let\xmlstripanywhere \clf_xmlstripanywhere -%let\xmlstripnolines \clf_xmlstripnolines -%let\xmlstripped \clf_xmlstripped -%let\xmlstrippednolines \clf_xmlstrippednolines -%let\xmltag \clf_xmltag -%let\xmltext \clf_xmltext -%let\xmltobuffer \clf_xmltobuffer % id pattern name -%let\xmltobuffertextonly \clf_xmltobuffertextonly % id pattern name -%let\xmltobufferverbose \clf_xmltobufferverbose % id pattern name -%let\xmltofile \clf_xmltofile % id pattern filename -%let\xmltoparameters \clf_xmltoparameters -%let\xmlverbatim \clf_xmlverbatim - -\let\xmlposition \xmlindex - -\permanent\protected\def\xmlinfo#1{\hbox{\ttxx[\xmlname{#1}]}} -\permanent\protected\def\xmlshow#1{\startpacked\ttx\xmlverbatim{#1}\stoppacked} - -% the next one is handy for mode runs because it enforces a consistent -% #1 indexing (needed when using \xmltext{main:123}{...} like calls - -%let\xmladdindex \clf_xmladdindex - -% we need to pass the last argument as function, so - -\protected\def\xmlsetfunction#1#2#3{\ctxcommand{xmlsetfunction("#1",\!!bs#2\!!es,#3)}} - -% goodie: - -\immutable\def\xmltempbuffername{xml-temp} - -\permanent\protected\def\prettyprintbuffer#1#2% only used here - {\ifdefined\scitebuffer - \scitebuffer[#2][#1]% - \else - \typebuffer[#1][\c!option=#2]% - \fi} - -\permanent\protected\def\xmlprettyprint#1#2% - {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% - \prettyprintbuffer\xmltempbuffername{#2}} - -\permanent\protected\def\xmlprettyprinttext#1#2% - {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% - \prettyprintbuffer\xmltempbuffername{#2}} - -\permanent\protected\def\inlineprettyprintbuffer#1#2% only used here - {\ifdefined\sciteinlinebuffer - \sciteinlinebuffer[#2][#1]% - \else - \typeinlinebuffer[#1][\c!option=#2]% - \fi} - -\permanent\protected\def\xmlinlineprettyprint#1#2% - {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% - \inlineprettyprintbuffer\xmltempbuffername{#2}} - -\permanent\protected\def\xmlinlineprettyprinttext#1#2% - {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% - \inlineprettyprintbuffer\xmltempbuffername{#2}} - -% kind of special: - -\aliased\let\xmlstartraw\clf_xmlstartraw -\aliased\let\xmlstopraw \clf_xmlstopraw - -\aliased\let\startxmlraw\clf_xmlstartraw -\aliased\let\stopxmlraw \clf_xmlstopraw - -% these are expandable! todo: \xmldoifelseattribute - -%let\xmldoif \clf_xmldoif -%let\xmldoifnot \clf_xmldoifnot -%let\xmldoifelse \clf_xmldoifelse -%let\xmldoiftext \clf_xmldoiftext -%let\xmldoifnottext \clf_xmldoifnottext -%let\xmldoifelsetext \clf_xmldoifelsetext - -%let\xmldoifatt \clf_xmldoifatt -%let\xmldoifnotatt \clf_xmldoifnotatt -%let\xmldoifelseatt \clf_xmldoifelseatt - -%let\xmldoifempty \clf_xmldoifempty -%let\xmldoifnotempty \clf_xmldoifnotempty -%let\xmldoifelseempty \clf_xmldoifelseempty -%let\xmldoifselfempty \clf_xmldoifselfempty -%let\xmldoifnotselfempty \clf_xmldoifnotselfempty -%let\xmldoifelseselfempty \clf_xmldoifelseselfempty - -\aliased\let\xmldoiftextelse \xmldoifelsetext -\aliased\let\xmldoifemptyelse \xmldoifelseempty -\aliased\let\xmldoifselfemptyelse \xmldoifelseselfempty - -% \startxmlsetups xml:include -% \xmlinclude{main}{include}{filename|href} -% \stopxmlsetups -% -% \xmlprependsetup{xml:include} - -% \let\xmlgrab\xmlsetsetup % obsolete -% \let\xmlself\s!unknown % obsolete - -\aliased\let\xmlsetup\setupwithargumentswapped -\aliased\let\xmls \setupwithargumentswapped % hardly any faster -\aliased\let\xmlw \setupwithargument % hardly any faster - -% todo: 1:xml:whatever always before 3:xml:something - -\permanent\protected\def\xmlprependsetup #1{\clf_xmlprependsetup{*}{#1}} -\permanent\protected\def\xmlappendsetup #1{\clf_xmlappendsetup {*}{#1}} -\permanent\protected\def\xmlbeforesetup #1#2{\clf_xmlbeforesetup {*}{#1}{#2}} -\permanent\protected\def\xmlaftersetup #1#2{\clf_xmlaftersetup {*}{#1}{#2}} -\permanent\protected\def\xmlremovesetup #1{\clf_xmlremovesetup {*}{#1}} -\permanent\protected\def\xmlresetsetups {\clf_xmlresetsetups {*}} - -\permanent\protected\def\xmlprependdocumentsetup #1#2{\clf_xmlprependsetup{#1}{#2}} -\permanent\protected\def\xmlappenddocumentsetup #1#2{\clf_xmlappendsetup {#1}{#2}} -\permanent\protected\def\xmlbeforedocumentsetup #1#2#3{\clf_xmlbeforesetup {#1}{#2}{#3}} -\permanent\protected\def\xmlafterdocumentsetup #1#2#3{\clf_xmlaftersetup {#1}{#2}{#3}} -\permanent\protected\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}} -\permanent\protected\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}} - -\permanent\protected\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply * -\permanent\protected\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2 - -\aliased\let\xmlregistersetup \xmlappendsetup -\aliased\let\xmlregisterdocumentsetup\xmlappenddocumentsetup - -\def\xmldocument{main} - -\permanent\protected\def\xmlregisteredsetups - {\xmlstarttiming - \xmlflushsetups\xmldocument - \xmldefaulttotext\xmldocument % after include - \xmlstoptiming} - -\permanent\protected\def\xmlregistereddocumentsetups#1#2% id setups - {\xmlstarttiming - % todo: test for duplicates ! - \xmlflushdocumentsetups{#1}{#2}% - \xmldefaulttotext{#1}% after include - \xmlstoptiming} - -\permanent\protected\def\xmlstarttiming{\clf_xmlstarttiming} % undocumented -\permanent\protected\def\xmlstoptiming {\clf_xmlstoptiming} % undocumented - -\def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup - {\begingroup - \edef\xmldocument{#3}% #2 can be \xmldocument and set as such - %xmlpushdocument{#3}% - #2{#3}{#4}% - \setcatcodetable\notcatcodes - \doifelsenothing{#5}% - {\xmlsetup{#3}{xml:process}}% - {\xmlsetup{#3}{#5}}% - %xmlpopdocument - \endgroup} - -\permanent\protected\def\xmlprocessfile {\lxml_process\plusone \xmlload} -\permanent\protected\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} -\permanent\protected\def\xmlprocessbuffer{\lxml_process\zerocount\xmlloadbuffer} -\aliased \let\xmlprocess \xmlprocessfile - -\startxmlsetups xml:flush - \xmlflush{#1} -\stopxmlsetups - -\startxmlsetups xml:process - \xmlregistereddocumentsetups{#1}{#1} - \xmlmain{#1} -\stopxmlsetups - -\permanent\protected\def\xmlloadonly#1#2#3% - {\xmlload{#1}{#2}% - \xmlregistereddocumentsetups{#1}{#3}} - -% replaced by concat -% -% \protected\def\xmlconnect#1#2#3% inefficient -% {\scratchcounter\xmlcount{#1}{#2}\relax -% \ifcase\scratchcounter \or -% \xmlall{#1}{#2}% -% \else -% \dorecurse \scratchcounter -% {\ifnum\recurselevel>\plusone#3\fi -% \xmlidx{#1}{#2}\recurselevel}% -% \fi} - -\permanent\protected\def\xmlcdataobeyedline {\obeyedline} -\permanent\protected\def\xmlcdataobeyedspace{\strut\obeyedspace} -\permanent\protected\def\xmlcdatabefore {\begingroup\tt} -\permanent\protected\def\xmlcdataafter {\endgroup} - -% verbatim (dodo:pre/post whitespace, maybe splot verbatim and -% cdata commands), experimental: -% -% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim} -% \xmlsetfunction{main}{verb} {lxml.inlineverbatim} - -% we use an xml: namespace so one has to define a suitable verbatim, say -% -% \definetyping[xml:verbatim][typing] -% -% this is experimental! - -\permanent\tolerant\protected\def\startxmldisplayverbatim[#1]% - {\startpacked - \edef\currenttyping{#1}% - \ifempty\currenttyping - \let\currenttyping\v!typing - \else % maybe test for existence - \edef\currenttyping{xml:\currenttyping}% - \fi - \protected\def\stopxmldisplayverbatim - {\endofverbatimlines - \stoppacked}% - \doinitializeverbatim - \beginofverbatimlines} - -\let\stopxmldisplayverbatim\relax - -\permanent\tolerant\protected\def\startxmlinlineverbatim[#1]% - {\begingroup - \edef\currenttype{#1}% - \ifempty\currenttype - \let\currenttype\v!type - \else % maybe test for existence - \edef\currenttype{xml:\currenttype}% - \fi - \let\stopxmlinlineverbatim\endgroup - \doinitializeverbatim} - -\let\stopxmlinlineverbatim\relax - -% processing instructions - -\permanent\protected\def\xmlinstalldirective#1#2% - {\clf_xmlinstalldirective{#1}{\csstring#2}} - -% an example: - -% - -\appendtoks - \xmlinstalldirective{tex}{xmltexcommand}% -\to \everyjob - -\permanent\def\xmltexcommand#1{\begincsname#1\endcsname} - -% \def\xmlcontextdirective#1% kind class key value -% {\executeifdefined{xml#1directive}\gobblethreearguments} - -% setting up xml: -% -% \setupxml[\c!default=] % mkiv only == text -% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden -% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text - -% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}} - -\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden - -\installcorenamespace{xml} -\installcorenamespace{xmldefaults} -\installcorenamespace{xmlmapvalue} - -\installdirectcommandhandler \??xml {xml} - -\letvalue{\??xmldefaults\v!normal}\zerocount -\letvalue{\??xmldefaults\v!none }\zerocount -\letvalue{\??xmldefaults\v!text }\plusone -\letvalue{\??xmldefaults\v!hidden}\plustwo - -\permanent\protected\def\xmldefaulttotext - {\ifcase\xmlprocessingmode - \expandafter\gobbleoneargument % 0 (none) - \or - \expandafter\clf_xmlsetcommandtotext % 1 (normal) - \or - \expandafter\clf_xmlsetcommandtonone % 2 (hidden) - \else - \expandafter\gobbleoneargument % (none) - \fi} - -\appendtoks - \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone -\to \everysetupxml - -\setupxml - [\c!default=, % flush all - \c!compress=\v!no, % strip comment - \c!entities=\v!no] % load big entity file - -\appendtoks - \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities -\to \everysetupxml - -\permanent\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces -\permanent\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} - -\permanent\def\xmlvalue#1#2% #3 - {\ifcsname\??xmlmapvalue#1:#2\endcsname - \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\def\xmlmappedvalue#1#2#3% - {\ifcsname\??xmlmapvalue#1:#2\endcsname - \expandafter\lastnamedcs - \else - \csname\??xmlmapvalue#1:#3\expandafter\endcsname - \fi} - -\aliased\let\xmldoifvalueelse\xmldoifelsevalue - -\aliased\let\xmlmapval\xmlmapvalue -\aliased\let\xmlval \xmlvalue - -%D Experimental: - -\permanent\def\xmlgetindex #1{\clf_xmlgetindex {\xmldocument}{#1}} -\permanent\def\xmlwithindex #1#2{\clf_xmlwithindex{\xmldocument}{#1}{#2}} -\permanent\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}} - -%D Entities: -%D -%D \starttyping -%D \xmlsetentity{tex}{\TEX{}} % {} needed -%D \stoptyping - -\permanent\protected\def\xmlsetentity#1#2{\clf_xmlsetentity{#1}{\detokenize{#2}}} -\permanent\protected\def\xmltexentity#1#2{\clf_xmltexentity{#1}{\detokenize{#2}}} - -%D The following might change (or even disappear) so we keep it undocumented. - -\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower - -\permanent\protected\def\xmle - {\ifcase\xmlautoentities - \expandafter\lxml_e_none - \or - \expandafter\lxml_e_upper - \or - \expandafter\lxml_e_upperlower - \else - \expandafter\lxml_e_none - \fi} - -\def\lxml_e_none#1#2% safe - {#1} - -\def\lxml_e_upper#1#2% can be abbreviation - {\ifcsname#2\endcsname - \csname#2\expandafter\endcsname - \else - #1% - \fi} - -\def\lxml_e_upperlower#1#2% can be anything, so unsafe - {\ifcsname#2\endcsname - \csname#2\expandafter\endcsname - \orelse\ifcsname#1\endcsname - \csname#1\expandafter\endcsname - \else - #1% - \fi} - -%D We keep these around as there are also MP, LUA and TEX variants but they are not -%D the same as in \MKII. - -\permanent\tolerant\protected\def\processXMLbuffer[#1]{\xmlprocessbuffer{temp}{#1}{}} -\permanent \protected\def\processXMLfile #1{\xmlprocessfile {temp}{#1}{}} -\permanent \protected\def\XMLdata #1{\xmlprocessdata {temp}{#1}{}} - -\aliased\let\processxmlbuffer\processXMLbuffer -\aliased\let\processxmlfile \processXMLfile -\aliased\let\xmldata \XMLdata - -\permanent\protected\def\xmlsetinjectors [#1]{\clf_xmlsetinjectors{#1}} -\permanent\protected\def\xmlresetinjectors {\clf_xmlresetinjectors{}} - -% \def\xmlinjector#1{\executeifdefined{#1}\donothing} - -\permanent\def\xmlinjector#1{\fastsetup{xml:directive:injector:#1}} - -\startsetups xml:directive:injector:page - \page -\stopsetups - -\startsetups xml:directive:injector:column - \column -\stopsetups - -\startsetups xml:directive:injector:blank - \blank -\stopsetups - -\startsetups xml:directive:injector:noline - \vskip-\lineheight -\stopsetups - -\aliased\let\xmlapplyselectors\clf_xmlapplyselectors - -% \let\xmlcatcodes\notcatcodes - -\protect \endinput - -% \newcount\charactersactiveoffset \charactersactiveoffset="10000 -% -% \startextendcatcodetable\ctxcatcodes -% \catcode\numexpr\charactersactiveoffset+`<\relax=13 -% \catcode\numexpr\charactersactiveoffset+`&\relax=13 -% \catcode\numexpr\charactersactiveoffset+`>\relax=13 -% \stopextendcatcodetable -% -% \startextendcatcodetable\xmlcatcodes % not needed -% \catcode\numexpr\charactersactiveoffset+`<\relax=13 -% \catcode\numexpr\charactersactiveoffset+`&\relax=13 -% \catcode\numexpr\charactersactiveoffset+`>\relax=13 -% \stopextendcatcodetable -% -% \ctxlua { % entities are remembered in the format -% commands.remapentity("<",characters.activeoffset + utf.byte("<")) -% commands.remapentity("&",characters.activeoffset + utf.byte("&")) -% commands.remapentity(">",characters.activeoffset + utf.byte(">")) -% } diff --git a/tex/context/base/mkiv/lxml-sor.mkxl b/tex/context/base/mkiv/lxml-sor.mkxl deleted file mode 100644 index 798047e04..000000000 --- a/tex/context/base/mkiv/lxml-sor.mkxl +++ /dev/null @@ -1,99 +0,0 @@ -%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}{} - -\unprotect - -%D The flusher is unexpandable so that it can be used in tables (noalign -%D interferences). - -% todo: public implementors - -\permanent\protected\def\xmlresetsorter #1{\ctxlxml{sorters.reset("#1")}} -\permanent\protected\def\xmladdsortentry#1#2#3{\ctxlxml{sorters.add("#1","#2",\!!bs#3\!!es)}} -\permanent\protected\def\xmlshowsorter #1{\ctxlxml{sorters.show("#1")}} -\permanent \def\xmlflushsorter #1#2{\ctxlxml{sorters.flush("#1","#2")}} -\permanent\protected\def\xmlsortentries #1{\ctxlxml{sorters.sort("#1")}} - -\protect \endinput - -\startbuffer[test] - - - one - alpha - alpha indeed - - - one - gamma - gamma indeed - - - one - beta - beta indeed - - - two - alpha - alpha again - - - two - gamma - gamma again - - - two - beta - beta again - - -\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/tex/context/base/mkiv/m-mkivmkxl.mkxl b/tex/context/base/mkiv/m-mkivmkxl.mkxl deleted file mode 100644 index 9aea14eb2..000000000 --- a/tex/context/base/mkiv/m-mkivmkxl.mkxl +++ /dev/null @@ -1,3 +0,0 @@ -% mkiv spacing before figure - -% \let\checkprevdepth\baselinecorrection diff --git a/tex/context/base/mkiv/math-ali.mkxl b/tex/context/base/mkiv/math-ali.mkxl deleted file mode 100644 index e5c693f98..000000000 --- a/tex/context/base/mkiv/math-ali.mkxl +++ /dev/null @@ -1,1898 +0,0 @@ -%D \module -%D [ file=math-ali, -%D version=2008.10.20, -%D title=\CONTEXT\ Math Macros, -%D subtitle=Math Alignments, -%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan}, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Math Macros / Math Alignments} - -\unprotect - -%D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code -%D is not gathered in files with the same name. In the meantime this code has been -%D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the -%D fact that alignments are tricky with rspect to tagging. - -% export: -% -% alignment : ok -% cases : -% matrix : ok -% substack : - -%D \macros -%D {definemathalignment, setupmathalignment, startmathalignment} -%D -%D Modules may provide additional alignment features. The following mechanisms are -%D provided by the core. - -\newtoks\t_math_align_a -\newtoks\t_math_align_b -\newtoks\t_math_align_c - -\newskip\d_math_eqalign_distance - -\protected\def\math_eqalign_distance - {\relax - \ifdim\d_math_eqalign_distance>\zeropoint - % \hskip\d_math_eqalign_distance - \tabskip\d_math_eqalign_distance - \fi - \mathalignmentparameter\c!separator - \relax} - -\def\displayopenupvalue{.25\bodyfontsize} - -\def\math_build_eqalign - {\scratchtoks\emptytoks - \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax - \scratchcounterone\mathalignmentparameter\c!m - \scratchcountertwo\mathalignmentparameter\c!n - \etoksapp\scratchtoks{\the\t_math_align_a}% - \scratchcounter\plusone - \dorecurse{\numexpr\scratchcounterone*\scratchcountertwo-\plusone\relax} - {\ifnum\scratchcounter=\scratchcountertwo - \scratchcounter\plusone - \etoksapp\scratchtoks{\math_eqalign_distance}% - \else - \advance\scratchcounter\plusone - \fi - \etoksapp\scratchtoks{\the\t_math_align_b}}% - \etoksapp\scratchtoks{\the\t_math_align_c}} - -\def\math_math_in_eqalign#1% - {\startforceddisplaymath - \tabskip\zeropoint - \everycr\emptytoks - {{}#1{}}% - \stopforceddisplaymath} - -\def\math_text_in_eqalign#1% - {\startimath - \tabskip\zeropoint - \everycr\emptytoks - #1% - \stopimath} - -\def\eqalign#1% why no halign here, probably because of displaywidth - {\emptyhbox - \mskip\thinmuskip - \vcenter - {\math_openup\displayopenupvalue % was: \openup\jot - \mathsurround\zeropoint - \ialign{% - \strut - \hfil - \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath - \aligntab - \startforceddisplaymath{{}\alignmark\alignmark{}}\stopforceddisplaymath - \hfil\crcr - #1\crcr}% - }% - \mskip\thinmuskip} - -% preamble is scanned for tabskips so we need the span to prevent an error message - -\setnewconstant\eqalignmode\plusone - -% use zeroskipplusfill - -\def\math_prepare_r_eqalign_no - {\t_math_align_a - {\strut - \tabskip\zeropoint - \alignmark\alignmark % for picking up the number - \aligntab - \math_first_in_eqalign - \hfil - \math_left_of_eqalign - \span - \math_math_in_eqalign{\alignmark\alignmark}% - \math_right_of_eqalign - \tabskip\zeropoint}% - \t_math_align_b - {\aligntab - \math_next_in_eqalign - \math_left_of_eqalign - \span - \math_math_in_eqalign{\alignmark\alignmark}% - \math_right_of_eqalign - \tabskip\zeropoint}% - \ifnum\mathraggedstatus=\plusone - \t_math_align_c - {\hfil - \aligntab - \span - \math_text_in_eqalign{\alignmark\alignmark}% - \tabskip\zeropoint}% - \orelse\ifnum\mathraggedstatus=\plusthree - \t_math_align_c - {\hfil - \tabskip\zeropoint\s!plus 1\s!fill - \aligntab - \span - \math_text_in_eqalign{\alignmark\alignmark}% - \tabskip\zeropoint}% - \else - \t_math_align_c - {\hfil - \tabskip\centering - \aligntab - \span - \llap{\math_text_in_eqalign{\alignmark\alignmark}}% - \tabskip\zeropoint}% - \fi - \math_build_eqalign - \the\mathdisplayaligntweaks - \tabskip\centering} - -\def\math_prepare_l_eqalign_no % \checkeddisplaymath - {\t_math_align_a - {\strut - \tabskip\zeropoint - \alignmark\alignmark % for picking up the number - \aligntab - \math_first_in_eqalign - \hfil - \math_left_of_eqalign - \span - \math_math_in_eqalign{\alignmark\alignmark}% - \math_right_of_eqalign - \tabskip\zeropoint}% - \t_math_align_b - {\aligntab - \math_next_in_eqalign - \math_left_of_eqalign - \span - \math_math_in_eqalign{\alignmark\alignmark}% - \math_right_of_eqalign - \tabskip\zeropoint}% - \ifnum\mathraggedstatus=\plusone - \t_math_align_c - {\hfil - \aligntab - \kern-\displaywidth - \span - \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% - \tabskip\displaywidth}% - \orelse\ifnum\mathraggedstatus=\plusthree - \t_math_align_c - {\hfil - \tabskip\zeropoint\s!plus 1\s!fill - \aligntab - \kern-\displaywidth - \span - \math_rlap{\math_text_in_eqalign{\alignmark\alignmark}}% - \tabskip\displaywidth}% - \else - \t_math_align_c - {\hfil - \tabskip\centering - \aligntab - \kern-\displaywidth - \span - \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% - \tabskip\displaywidth}% - \fi - \math_build_eqalign - \the\mathdisplayaligntweaks - \tabskip\centering} - -\def\math_halign_checked - {\halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi} - -\def\math_both_eqalign_no_normal#1#2% - {\ifmmode - \the\mathdisplayaligntweaks - \vcenter\bgroup - \enforced\let\math_finish_eqalign_no\egroup - \else - \enforced\let\math_finish_eqalign_no\relax - \fi - #1% - \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr#2\crcr\egroup - \math_finish_eqalign_no} - -\installcorenamespace {mathalignlocation} - -\setvalue{\??mathalignlocation\v!top }{\let\math_alignment_halign_method\halign\tpack} -\setvalue{\??mathalignlocation\v!bottom}{\let\math_alignment_halign_method\halign\vpack} -\setvalue{\??mathalignlocation\v!center}{\let\math_alignment_halign_method\halign\vcenter} - -\def\math_both_eqalign_no_aligned#1% - {\let\math_alignment_halign_method\math_halign_checked - \ifmmode - \the\mathdisplayaligntweaks - \global\mathnumberstatus\plusone - \ifcase\mathraggedstatus - \def\math_finish_eqalign_no{\crcr\egroup}% - \else % we're in a mathbox - \ifcsname\??mathalignlocation\mathalignmentparameter\c!location\endcsname - \lastnamedcs % top|bottom|center as suggested by HM - \else - \vcenter - \fi - \bgroup - \def\math_finish_eqalign_no{\crcr\egroup\egroup}% - \fi - \fi - #1% - \math_alignment_halign_method\expandafter\bgroup\the\scratchtoks\crcr} - -\def\math_rlap#1% - {\setbox\scratchbox\hbox{#1}% - \ifdim\wd\scratchbox>\d_math_number_correction - \global\d_math_number_correction\wd\scratchbox - \fi - \box\scratchbox - \global\mathnumberstatus\plustwo} - -\def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no} -\def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no} -\def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no} -\def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no} -\def\math_finish_eqalign_no {\crcr\egroup} - -\let\reqalignno\relax -\let\leqalignno\relax -\let\eqalignno \relax - -%D Here we implement the user interface part. We start with basic math alignments: - -\newcount \c_math_eqalign_column -\newconditional\c_math_eqalign_first - -\newtoks \everymathalignment -\newtoks \everymathalignmentdone - -\permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]% - {\aligntab - \strc_formulas_place_number_nested{#1}{#2}} - -\permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]% - {\aligntab - \dostoptagged % finish cell - \strc_formulas_place_number_nested{#1}{#2}% - \math_number_right_of_eqalign - \global\settrue\c_math_eqalign_first - \crcr - \dostoptagged} % finish row - -\permanent\protected\def\math_alignment_NC - {\relax - \ifconditional\c_math_eqalign_first - \ifx\p_math_alignment_number\v!auto - \strc_formulas_place_number_nested{+}{}% - \fi - \global\setfalse\c_math_eqalign_first - \fi - \math_number_left_of_eqalign - \aligntab} - -\permanent\protected\def\math_alignment_EQ - {\NC=} - -\noaligned\tolerant\protected\def\math_common_TB[#1]% - {\noalign{\blank[#1]}} - -\installmacrostack\NC % maybe more to shared table definitions -\installmacrostack\NN % maybe more to shared table definitions -\installmacrostack\EQ % maybe more to shared table definitions -\installmacrostack\NR % maybe more to shared table definitions -\installmacrostack\BC % maybe more to shared table definitions -\installmacrostack\EC % maybe more to shared table definitions -\installmacrostack\TB % maybe more to shared table definitions - -\appendtoks - \push_macro_NC - \push_macro_NN - \push_macro_EQ - \push_macro_NR - \push_macro_TB - \enforced\let\NC\math_alignment_NC - \enforced\let\NN\math_alignment_NN - \enforced\let\EQ\math_alignment_EQ - \enforced\let\NR\math_alignment_NR - \enforced\let\TB\math_common_TB - \global\settrue\c_math_eqalign_first -\to \everymathalignment - -\appendtoks - \pop_macro_TB - \pop_macro_NR - \pop_macro_EQ - \pop_macro_NN - \pop_macro_NC -\to \everymathalignmentdone - -\let\math_alignment_snap_start\relax -\let\math_alignment_snap_stop \relax - -% % experimental: -% -% \def\math_alignment_snap_start -% {\ifgridsnapping -% \edef\p_math_alignment_grid{\mathalignmentparameter\c!grid}% -% \ifx\p_math_alignment_grid\v!no\else -% \snaptogrid[\p_math_alignment_grid]\vbox\bgroup -% \fi -% \fi} -% -% \def\math_alignment_snap_stop -% {\ifgridsnapping -% \ifx\p_math_alignment_grid\v!no\else -% \egroup -% \fi -% \fi} -% -% % doesn't work well, so: - -\let\math_alignment_snap_start\relax -\let\math_alignment_snap_stop \relax - -% end of experimental - -\newconditional\c_math_alignment_auto_number - -% \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex - -\permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]% - {\edef\currentmathalignment{#1}% - \ifarguments\or\or - \setupmathalignment[#1][#2]% bad! ungrouped - \fi - \math_alignment_snap_start - \the\everymathalignment - \c_math_eqalign_column\zerocount - \edef\p_math_alignment_number{\mathalignmentparameter\c!number}% - \processcommacommand - [\mathalignmentparameter\c!align]% - {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument - \global\c_math_eqalign_column\plusone - \dostarttagged\t!math\empty - \dostarttagged\t!mtable\currentmathalignment - \numberedeqalign} - -\def\math_alignment_stop % can be protected - {\math_finish_eqalign_no - \dostoptagged - \dostoptagged - \the\everymathalignmentdone - \math_alignment_snap_stop} - -\installcorenamespace{mathalignment} -\installcorenamespace{mathalignmentvariant} - -\installcommandhandler \??mathalignment {mathalignment} \??mathalignment - -\appendtoks - \setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}% - \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}% -\to \everydefinemathalignment - -\setupmathalignment - [\c!n=2, - \c!m=1, - \c!distance=\emwidth, - \c!grid=\v!math] - -\definemathalignment[align] % default case (this is what amstex users expect) -\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing) - -% special case.. in case one mistypes .. - -\ifdefined \startalignment - - \let\align_math_normal_start\startalign - \let\align_math_normal_stop \stopalign - - \let\align_text_normal_start\startalignment - \let\align_text_normal_stop \stopalignment - - \permanent\overloaded\protected\def\startalign - {\ifmmode - \enforced\let\stopalign\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align - \expandafter\align_math_normal_start - \orelse\ifinformula - \enforced\let\stopalign\align_math_normal_stop - \expandafter\align_math_normal_start - \else - \enforced\let\stopalign\align_text_normal_stop - \expandafter\align_text_normal_start - \fi} - - \overloaded\let\stopalign\relax - - \permanent\overloaded\protected\def\startalignment - {\ifmmode - \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align - \expandafter\align_math_normal_start - \orelse\ifinformula - \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align - \expandafter\align_math_normal_start - \else - \enforced\let\stopalignment\align_text_normal_stop - \expandafter\align_text_normal_start - \fi} - - \overloaded\let\stopalignment\relax - -\fi - -% - -\permanent\protected\def\numberedeqalign - {\doifelse{\formulaparameter\c!location}\v!left - \math_handle_eqalign_no_l_aligned - \math_handle_eqalign_no_r_aligned} - -\def\math_first_in_eqalign - {\global\c_math_eqalign_column\plusone - \dostarttagged\t!mtablerow \empty - \dostarttagged\t!mtablecell\empty} - -\def\math_next_in_eqalign - {\global\advance\c_math_eqalign_column\plusone - \dostoptagged % finish cell - \dostarttagged\t!mtablecell\empty} - -\def\math_left_of_eqalign - {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname - \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi - \fi} - -\def\math_right_of_eqalign - {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname - \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi - \fi} - -\newconditional\c_math_alignment_local_number % not used but when true puts in front (todo) - -\def\math_number_right_of_eqalign - {\ifcase\wd\b_strc_formulas_number\else - \ifconditional\c_math_alignment_local_number - \ifcase\c_strc_math_number_location\or\or - \box\b_strc_formulas_number - \fi - \else - \box\b_strc_formulas_number - \fi - \fi} - -\def\math_number_left_of_eqalign - {\ifcase\wd\b_strc_formulas_number\else - \ifconditional\c_math_alignment_local_number - \ifcase\c_strc_math_number_location\or - \box\b_strc_formulas_number - \fi - \fi - \fi} - -\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) - {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname - \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} - -\letvalue{\??mathalignmentvariant\v!normal}\zerocount -\letvalue{\??mathalignmentvariant\v!left }\plusone -\letvalue{\??mathalignmentvariant\v!right }\plustwo -\letvalue{\??mathalignmentvariant\v!middle}\plusthree - -\permanent\protected\def\math_align_NR_generic[#1][#2]% - {\strc_formulas_place_number_nested{#1}{#2}\crcr} - -%D \starttyping -%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0] -%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1] -%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2] -%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3] -%D \stoptyping - -%D \startbuffer -%D \placeformula \startformula \eqalignno { -%D a &= b & \formulanumber \cr -%D c &= d \cr -%D &= e \cr -%D &= f & \formulanumber -%D } \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign -%D \NC a \EQ b \NR[+] -%D \NC c \EQ d \NR -%D \NC \EQ f \NR[for:demo-a-1] -%D \NC \EQ g \NR[for:demo-a-2][a] -%D \NC \EQ h \NR[for:demo-a-3][b] -%D \NC \EQ i \NR -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign -%D \NC a \EQ b \NR[+] -%D \NC c \EQ d \NR -%D \NC \EQ f \NR -%D \NC \EQ g \NR -%D \NC \EQ h \NR -%D \NC \EQ i \NR[+] -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign -%D \NC a \NC \eq b \NR[+] -%D \NC c \NC \neq d \NR -%D \NC \NC \neq f \NR[for:demo-b-1] -%D \NC \NC \geq g \NR[for:demo-b-2][a] -%D \NC \NC \leq h \NR[for:demo-b-3][b] -%D \NC \NC \neq i \NR -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign[n=3,align={left,middle,right}] -%D \NC l \NC = \NC r \NR -%D \NC left \NC = \NC right \NR -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign[n=3,align={right,middle,left}] -%D \NC l \NC = \NC r \NR -%D \NC left \NC = \NC right \NR -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}] -%D \NC l \NC = \NC r \NR -%D \NC left \NC = \NC right \NR -%D \stopalign \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula -%D \startformula -%D \startalign[n=3,align={middle,middle,middle}] -%D \NC a \NC = \NC b \NR[+] -%D \NC 2a \NC = \NC 2b \NR -%D \stopalign -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula -%D \startformulas -%D \setupmathalignment[n=3,align={middle,middle,middle}]% -%D \startformula -%D \startalign -%D \NC a \NC = \NC b \NR[+] -%D \NC 2a \NC = \NC 2b \NR -%D \stopalign -%D \stopformula -%D \startformula -%D \startalign -%D \NC a \NC = \NC b \NR[+] -%D \NC 2a \NC = \NC 2b \NR -%D \stopalign -%D \stopformula -%D \stopformulas -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula -%D \startformulas -%D \dorecurse{5}{\startformula -%D \startalign[n=3,align={middle,middle,middle}] -%D \NC a \NC = \NC b \NR[+] -%D \NC 2a \NC = \NC 2b \NR -%D \stopalign -%D \stopformula} -%D \stopformulas -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \macros -%D {definemathcases, setupmathcases, startmathcases} -%D -%D Another wish \unknown - -\installcorenamespace{mathcases} - -\installcommandhandler \??mathcases {mathcases} \??mathcases - -\setupmathcases - [\c!distance=\emwidth, - \c!strut=\v!yes, % new - \c!numberdistance=2.5\emwidth, - \c!left={\left\{\mskip\thinmuskip}, - \c!right={\right.}] - -\appendtoks - \setuevalue{\e!start\currentmathcases}{\math_cases_start[\currentmathcases]}% - \setvalue {\e!stop \currentmathcases}{\math_cases_stop}% -\to \everydefinemathcases - -\permanent\protected\def\math_cases_NC_zero - {\math_cases_NC} - -\permanent\protected\def\math_cases_MC_zero - {\math_cases_NC - \ifmmode\else - \startimath - \enforced\let\math_cases_end_math\stopimath - \fi} - -\let\math_cases_end_math\relax - -\permanent\protected\def\math_cases_NR_zero - {\unskip - \math_cases_end_math - \aligntab - \global\enforced\let\math_cases_NC\math_cases_NC_first - \dodirectdoubleempty\math_cases_NR} - -\permanent\protected\def\math_cases_NC_first - {\global\enforced\let\math_cases_NC\math_cases_NC_second} - -\permanent\protected\def\math_cases_NC_second - {\math_cases_end_math\aligntab} - -\let\math_cases_NR\math_align_NR_generic - -\installmacrostack\math_cases_NC - -\permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]% - {\begingroup - \edef\currentmathcases{#1}% - \ifarguments\or\or - \setupcurrentmathcases[#2]% - \fi - \edef\p_strut{\mathcasesparameter\c!strut}% - \ifx\p_strut\v!yes - \enforced\let\math_cases_strut\strut - \else - \enforced\let\math_cases_strut\relax - \fi - \mathcasesparameter\c!left - \vcenter\bgroup - \push_macro_math_cases_NC - \enforced\let\endmath\relax - \enforced\let\NC\math_cases_NC_zero - \enforced\let\MC\math_cases_MC_zero - \enforced\let\NR\math_cases_NR_zero - \enforced\let\TB\math_common_TB - \global\enforced\let\math_cases_NC\math_cases_NC_first - \normalbaselines - \mathsurround\zeropoint - \everycr\emptytoks - \tabskip\zeropoint - \global\c_math_eqalign_column\plusone - \halign\bgroup - \startimath - \mathcasesparameter\c!style - \alignmark\alignmark - \stopimath - \hfil - \aligntab - \hskip\mathcasesparameter\c!distance\relax - \pop_macro_math_cases_NC - \math_cases_strut % looks better - \alignmark\alignmark - \hfil - \aligntab - \hskip\mathcasesparameter\c!numberdistance\relax - \let\formuladistance\!!zeropoint - \span\math_text_in_eqalign{\alignmark\alignmark}% - \crcr} % todo: number - -% When we have just protected we get an extra row but we can no flag -% this as a proper alignment related command which means that uit gets -% expanded. - -\noaligned\permanent\protected\def\math_cases_stop - {\crcr - \egroup - \pop_macro_math_cases_NC - \egroup - \mathcasesparameter\c!right - \endgroup} - -\definemathcases[cases] -\definemathcases[\v!mathcases] - -%D \startbuffer -%D \placeformula \startformula \startcases -%D \NC 2 \NC $ y > 0 $ \NR -%D \NC 7 \NC $ x = 7 $ \NR[+] -%D \NC 4 \NC otherwise \NR -%D \stopcases \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula x \startcases -%D \NC 2 \NC $ y > 0 $ \NR[+] -%D \NC 7 \NC $ x = 7 $ \NR -%D \NC 4 \NC otherwise \NR -%D \stopcases \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula \startcases -%D \NC 2 \NC $ y > 0 $ \NR -%D \NC 7 \NC $ x = 7 $ \NR -%D \NC 4 \NC otherwise \NR -%D \stopcases \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \placeformula \startformula x \startcases -%D \NC 2 \NC $ y > 0 $ \NR -%D \NC 7 \NC $ x = 7 $ \NR -%D \NC 4 \NC otherwise \NR -%D \stopcases \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \macros -%D {definemathmatrix, setupmathmatrix, startmathmatrix} -%D -%D Yet another one \unknown. This time we implement the lot a bit -%D different which is a side effect of getting the tagging right. In -%D retrospect the main alignment could be done this way but \unknown - -\installcorenamespace{mathmatrix} - -\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix - -\setupmathmatrix - [\c!distance=\emwidth, - \c!left=, - \c!right=, - \c!align=\v!middle] - -\appendtoks - \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}% - \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem -\to \everydefinemathmatrix - -\def\math_matrix_start_table - {\global\c_math_eqalign_column\zerocount - \dostarttagged\t!math\empty - \dostarttagged\t!mtable\empty} - -\def\math_matrix_stop_table - {\dostoptagged - \dostoptagged} - -\def\math_matrix_start_row - {\noalign{\global\c_math_eqalign_column\zerocount}% - \dostarttagged\t!mtablerow\empty} - -\def\math_matrix_stop_row - {\dostoptagged} - -\protected\def\math_matrix_start_cell - {\dostarttagged\t!mtablecell\empty - \hss - \math_left_of_eqalign - \startimath - \math_matrix_set_style - \tabskip\zeropoint - \everycr\emptytoks} - -\protected\def\math_matrix_stop_cell - {\stopimath - \math_right_of_eqalign - \hss - \dostoptagged} - -% We could construct a preamble with alignment and such embedded but the number -% of matrices with many rows is normally so low that it doesn't pay of at all. - -\protected\def\math_matrix_distance - {\relax - \ifdim\d_math_eqalign_distance>\zeropoint - \hskip\d_math_eqalign_distance - \fi - \relax} - -\def\math_matrix_preamble - {\math_matrix_strut - \global\advance\c_math_eqalign_column\plusone - \math_matrix_start_cell - \alignmark\alignmark - \math_matrix_stop_cell - \aligntab - \aligntab - \math_matrix_distance - \global\advance\c_math_eqalign_column\plusone - \math_matrix_start_cell - \alignmark\alignmark - \math_matrix_stop_cell} - -\newconditional\c_math_matrix_first - -\permanent\protected\def\math_matrix_NR - {\aligntab\omit - \math_matrix_stop_row - \math_matrix_pickup - \crcr - \math_matrix_start_row} - -\permanent\protected\def\math_matrix_NC - {\ifconditional\c_math_matrix_first - \expandafter\math_matrix_NC_yes - \else - \expandafter\math_matrix_NC_nop - \fi} - -\permanent\protected\def\math_matrix_pickup{\global\settrue \c_math_matrix_first} -\permanent\protected\def\math_matrix_NC_yes{\global\setfalse\c_math_matrix_first} -\permanent\protected\def\math_matrix_NC_nop{\aligntab} % avoids lookahead - -% \def\math_matrix_stop_wrapup -% {\crcr -% \strut -% \crcr -% \noalign{\vskip-\struthtdp}} - -\def\math_matrix_start_processing - {\dontleavehmode - \bgroup - \tabskip\zeropoint - \math_matrix_pickup - \enforced\let\NR\math_matrix_NR - \enforced\let\NC\math_matrix_NC - \enforced\let\MC\math_matrix_NC - \enforced\let\TB\math_common_TB - % - \enforced\let\endmath\relax - % - \setbox\nextbox\vbox\bgroup - \math_matrix_start_table - \halign \bgroup - % preamble - \span\math_matrix_preamble - % done - \crcr - \math_matrix_start_row} - -\def\math_matrix_stop_processing - {%\math_matrix_stop_wrapup % optional - \math_matrix_stop_row - \egroup - \math_matrix_stop_table - \egroup - \mathmatrixleft - \math_matrix_finish_nextbox - \mathmatrixright - \egroup} - -\let\math_matrix_strut \strut -\let\math_matrix_set_style\relax - -\def\math_matrix_check_settings - {\edef\p_strut{\mathmatrixparameter\c!strut}% - \ifx\p_strut\v!no - \enforced\let\math_matrix_strut\relax - \else - \enforced\let\math_matrix_strut\strut - \ifx\p_strut\v!yes\else - \spacing\p_strut - \fi - \fi - \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax - \edef\math_matrix_set_style{\mathmatrixparameter\c!style}} - -\def\math_matrix_set_defaults - {\normalbaselines % hm, spacing ? - \mathsurround\zeropoint - \tabskip\zeropoint} - -\def\math_matrix_set_columns_step - {\advance\c_math_eqalign_column\plusone - %\c_math_matrix_columns\c_math_eqalign_column - \math_eqalign_set_column} - -\def\math_matrix_set_columns - {\c_math_eqalign_column\zerocount - \rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step} - -\newcount\c_math_eqalign_column_saved - -% \installglobalmacrostack\c_math_matrix_first - -\tolerant\protected\def\math_matrix_start[#1]#*[#2]% - {\begingroup - \globalpushmacro\c_math_matrix_first % hm, does that work? - \c_math_eqalign_column_saved\c_math_eqalign_column - \globalpushmacro\c_math_eqalign_first - \edef\currentmathmatrix{#1}% - \setupcurrentmathmatrix[#2]% - \math_matrix_check_settings - \math_matrix_set_defaults - \math_matrix_set_columns - \math_matrix_start_processing} - -\def\math_matrix_stop - {\math_matrix_stop_processing - \globalpushmacro\c_math_eqalign_first - \global\c_math_eqalign_column\c_math_eqalign_column_saved - \globalpopmacro\c_math_matrix_first - \endgroup} - -% vcenter: -% -% delta = (height(v) + depth(v))/2 -% axis = math_axis_size(cur_size) -% height(v) = delta + axis -% depth(v) = delta - axis - -\installcorenamespace{mathmatrixalignlocation} - -\let\mathmatrixleft \empty % experimental hook -\let\mathmatrixright\empty % experimental hook - -\setvalue{\??mathmatrixalignlocation\v!top }{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} -\setvalue{\??mathmatrixalignlocation\v!high }{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax} -\setvalue{\??mathmatrixalignlocation\v!center}{\relax} -\setvalue{\??mathmatrixalignlocation\v!lohi} {\relax} -\setvalue{\??mathmatrixalignlocation\v!normal}{\relax} -\setvalue{\??mathmatrixalignlocation\v!bottom}{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} -\setvalue{\??mathmatrixalignlocation\v!low }{\lower\dimexpr(\nextboxdp-\nextboxht)/2\relax} - -\def\math_matrix_finish_nextbox - {\begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup - \normalstartimath - \mathmatrixparameter\c!left - \vcenter{\box\nextbox}% - \mathmatrixparameter\c!right - \normalstopimath - \egroup} - -\definemathmatrix[matrix] -\definemathmatrix[\v!mathmatrix] - -%D \startbuffer -%D \placeformula \startformula[-] \startmatrix -%D \NC 1 \NC x \NC a \NR -%D \NC 2 \NC y \NC b \NR -%D \NC 3 \NC z \NC c \NR -%D \stopmatrix \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25] -%D -%D \startbuffer -%D \placeformula \startformula[-] \startbmatrix -%D \NC 1 \NC x \NC a \NR -%D \NC 2 \NC y \NC b \NR -%D \NC 3 \NC z \NC c \NR -%D \stopbmatrix \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D Taco added some code (dedicated to Aditya Mahajan) that gives more -%D control over aligments: - -%D \startbuffer -%D \startformula -%D \startmatrix -%D \NC a + x \NC = \NC a + d \NR -%D \NC y \NC = \NC d \NR -%D \stopmatrix -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \startbuffer -%D \startformula -%D \startmatrix [distance=3pt,align={right,left}] -%D \NC a + x \NC = a + d \NR -%D \NC y \NC = d \NR -%D \stopmatrix -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \startbuffer -%D \startformula -%D \startmatrix [left=\left(,right=\right)] -%D \NC a + x \NR -%D \NC y \NR -%D \stopmatrix -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D A bit more complex code: -%D -%D \startbuffer -%D \startformula -%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}} -%D \left\{ (R_1, R_2) : -%D \startmatrix[distance=1em,align={left,left,right}] -%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR -%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR -%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR -%D \stopmatrix -%D \right\} -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \macros -%D {startmatrices} -%D -%D Just a handy keystroke safer: - -\permanent\protected\def\startmatrices - {\begingroup - \setupmathmatrix} - -\permanent\protected\def\stopmatrices - {\endgroup} - -%D \startbuffer -%D \startformula -%D \startmatrix[left={\left(},right={\right)}] -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D = -%D \startmatrix[left={\left(},right={\right)},location=low] -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D = -%D \startmatrix[left={\left(},right={\right)},location=high] -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \startformula -%D \startmatrices[left={\left(},right={\right)}] -%D \startmatrix -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D = -%D \startmatrix[location=bottom] -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D = -%D \startmatrix[location=top] -%D \NC A \NC B \NR \NC C \NC D \NR -%D \stopmatrix -%D \stopmatrices -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer % does not run well: \getbuffer - -%D Handy for the \type {m-matrix} module: - -\permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#2]% - {\begingroup - \edef\currentmathmatrix{#1}% - \setupcurrentmathmatrix[#2]% - \math_matrix_start[\currentmathmatrix]} - -\permanent\protected\def\stopnamedmatrix - {\math_matrix_stop - \endgroup} - -%D The following code is derived from Aditya's simplematrix prototype but -%D adapted to regular mathmatrices (which saves some code so it can go into -%D the core): - -\def\math_matrix_simple_row#1% - {\rawprocesscommalist[#1]\math_matrix_simple_col - \toksapp\scratchtoks{\NR}} - -\def\math_matrix_simple_col#1% - {\toksapp\scratchtoks{\NC#1}} - -\permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% - {\begingroup - \edef\currentmathmatrix{#1}% - \setupcurrentmathmatrix[#2]% - \scratchtoks\emptytoks - \processlist[];\math_matrix_simple_row[#3]% - \math_matrix_start[\currentmathmatrix]% - \the\scratchtoks - \math_matrix_stop - \endgroup} - -%D We hook it into the normal mathmatrix code: - -\appendtoks - \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}% - \ifempty\p_simplecommand\else - \setuevalue{\p_simplecommand}{\math_matrix_simple[\currentmathmatrix]}% - \fi -\to \everydefinemathmatrix - -%D And predefine some matrices: - -\definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle] -\definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle] -\definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle] - -\definemathmatrix[thematrix][matrix:parentheses][\c!simplecommand=thematrix] - -%D \startbuffer -%D \startformula -%D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12} -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D \startbuffer -%D \startformula -%D \startthematrix -%D \NC 1\NC 2\NC 3\NC 4\NR -%D \NC 5\NC 6\NC 7\NC 8\NR -%D \NC 9\NC10\NC11\NC12\NR -%D \stopthematrix -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -%D \macros -%D {startintertext} -%D -%D Preliminary feature: -%D -%D {\em example code} -%D -%D The intertext commands have to be expandable (in aligment lookahead) so -%D we cannot use \type {\protected}. - -\permanent\def\startintertext#1\stopintertext - {\noalign{\math_intertext{#1}}} - -\permanent\let\stopintertext\relax - -\permanent\def\intertext#1% - {\noalign{\math_intertext{#1}}} - -\protected\def\math_intertext#1% - {\penalty\postdisplaypenalty - \afterdisplayspace - \vbox{\forgetall\noindent#1\par}% - \penalty\predisplaypenalty - \beforedisplayspace} - -%D \macros -%D {substack} -%D -%D Preliminary code: -%D -%D \startbuffer -%D \startformula -%D \sum_{% -%D \startsubstack -%D i = 1 \NR -%D i \neq n \NR -%D i \neq m -%D \stopsubstack -%D }a_i -%D \stopformula -%D \stopbuffer -%D -%D \getbuffer which was typed as \typebuffer -%D -%D Notice that these macros give the correct spacing for -%D subscripts. Compare for example -%D -%D \startbuffer -%D \startformula -%D \sum_{\startsubstack a \NR b \NR \stopsubstack} -%D \text{ and } -%D \sum_{\scriptstyle a \atop \scriptstyle} -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer which gives \getbuffer - -% no tagging yet : how is it supposed to be coded? - -\permanent\protected\def\startsubstack - {\begingroup - \vcenter\bgroup - \baselineskip\mathstacktotal - \lineskip\mathstackvgap - \lineskiplimit\lineskip - \mathsurround\zeropoint - \everycr\emptytoks - \enforced\let\NC\relax - \enforced\let\MC\relax - \enforced\let\NR\crcr - \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr} - -\noaligned\permanent\protected\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 -% -% \protected\def\bordermatrix -% {\begingroup -% \setbox\scratchbox\hbox{\mr\char"239C}% -% \global\mathparentwd\wd\scratchbox -% \endgroup -% \normalbordermatrix} -% -% \def\bordermatrix -% {\begingroup -% \mr -% \global\mathparentwd\fontcharwd\font"239C\relax -% \endgroup -% \normalbordermatrix} - -%D \macros{overset, underset} -%D -%D The macros \type{\overset} and \type{\underset} are provided by -%D \AMS\ packages in \LATEX. These macro allows you to place a symbol -%D above or below another symbol, irrespective of whether the other -%D symbol is a relation or something else, and without influencing the -%D spacing. For most cases there is a better way to do such things -%D (declaring a math command with limop option, or using accents), but -%D occasionally these macros can be useful, for example: -%D -%D \startbuffer -%D \startformula -%D \overset{*}{X} \underset{*}{X} -%D \stopformula -%D \stopbuffer -%D \typebuffer \getbuffer -%D -%D Use these macros sparingly. Remember, \TEX\ was designed for -%D mathematics, so there is usually a proper method for typesetting -%D common math notation. -%D -%D These macros are a cleaner version of \type {\binrel@} and -%D \type {\binrel@@} macros in \AMSTEX\ packages. - -\def\math_binrel_apply#1% - {\begingroup - \setbox\scratchbox\hbox - {\thinmuskip 0mu - \medmuskip -1mu - \thickmuskip -1mu - \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}% - \kern-\wd\scratchbox - \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}% - \ifdim\wd\scratchbox<\zeropoint - \endgroup - \expandafter\mathbin - \orelse\ifdim\wd\scratchbox>\zeropoint - \endgroup - \doubleexpandafter\mathrel - \else - \endgroup - \doubleexpandafter\firstofoneargument - \fi} - -\permanent\protected\def\overset#1#2% - {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}} - -\permanent\protected\def\underset#1#2% - {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}} - -%D The following code comes from \type {math-str.mkiv}. -%D -%D Here we implement a basic math alignment mechanism. Numbers are also handled. The macros -%D \type {\startinnermath} and \type {\stopinnermath} can be overloaded in specialized -%D modules. - -\installcorenamespace{mathinnerstart} -\installcorenamespace{mathinnerstop} - -% \protected\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname} -% \protected\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname} - -\permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal} -\permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal} - -\permanent\protected\def\mathinnerstrut - {\doif{\formulaparameter\c!strut}\v!yes\strut} - -\permanent\protected\def\defineinnermathhandler#1#2#3% - {\setvalue{\??mathinnerstart#1}{#2}% - \setvalue{\??mathinnerstop #1}{#3}} - -\installtextracker - {formulas.boxes} - {\enforced\let\math_hbox\ruledhbox} - {\enforced\let\math_hbox\hbox} - -\let\math_hbox\hbox - -\newconstant\mathraggedstatus % normal left center right -\newconstant\mathnumberstatus % nothing normal shift_right - -\newdimen\d_math_number_correction - -\def\math_box_llapped_math_no - {\ifcase\mathraggedstatus\or - \box\b_strc_formulas_number - \or - \llap{\box\b_strc_formulas_number}% - \or - \llap{\box\b_strc_formulas_number}% - \fi} - -\def\math_box_rlapped_math_no - {\ifcase\mathraggedstatus\or - \rlap{\box\b_strc_formulas_number}% - \or - \rlap{\box\b_strc_formulas_number}% - \or - \box\b_strc_formulas_number - \fi} - -\newconditional\c_strc_math_has_number -\newconditional\c_strc_math_display_overflow -\newconstant \c_strc_math_number_location -\newdimen \d_strc_math_number_width -\newdimen \d_strc_math_display_width -\newbox \b_strc_math_display -\newconstant \c_strc_formulas_frame_mode -\newdimen \d_strc_math_indent -\newconditional\c_strc_math_indent - -\newdimen\d_strc_math_framed_width - -\setvalue{\??formulaoption\v!frame}% - {\edef\p_frame{\formulaparameter\c!frame}% - \ifx\p_frame\v!number - \c_strc_formulas_frame_mode\plustwo % inside frame - \else - \c_strc_formulas_frame_mode\plusone % outside frame - \fi} - -% mode: 0=no frame | 1=number inside frame | 2=number outside frame - -\def\strc_math_flush_aligned - {\ifcase\c_strc_math_vertical - \ifcase\mathraggedstatus\or\hfill\or\hfill\fi - \box\b_strc_math_display - \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi - \else - \ifconditional\c_strc_math_indent - \ifzeropt\d_strc_math_indent\else - \hangafter\plusone - \hangindent\d_strc_math_indent - \fi - \fi - \edef\p_interlinespace{\formulaparameter\c!interlinespace}% - \ifempty\p_interlinespace\else\baselineskip\p_interlinespace\fi - \global\d_strc_math_indent\zeropoint - \ifcase\mathraggedstatus\or\raggedleft\or\raggedcenter\or\raggedright\fi - \unhbox\b_strc_math_display - \fi} - -\def\strc_math_flush_box_normal - {\ifcase\c_strc_math_vertical - \hbox to \displaywidth\bgroup - \strc_math_flush_aligned - \egroup - \else - \strc_math_flush_aligned - \fi} - -\def\strc_math_flush_box_framed_common - {\d_strc_math_framed_width\displaywidth - \setformulaframedparameter\c!align{\formulaparameter\c!align}% - \letformulaframedparameter\c!strut\v!no - \d_framed_formula\ht\b_strc_math_display - \ifcase\mathraggedstatus\or\hfill\or\hfill \fi - \inheritedformulaframedframed{\box\b_strc_math_display}% - \ifcase\mathraggedstatus\or \or\hfill\or\hfill\fi} - -\def\strc_math_flush_box_framed_display - {\let\currentformulaframed\currentformula - \letformulaframedparameter\c!location\v!formula - \setformulaframedparameter\c!width{\d_strc_math_framed_width}% - \strc_math_flush_box_framed_common} - -\def\strc_math_flush_box_framed_fit_inline - {\let\currentformulaframed\currentformula - \letformulaframedparameter\c!location\empty - \letformulaframedparameter\c!width\v!fit - \strc_math_flush_box_framed_common} - -\def\strc_math_flush_box_framed_fit_display - {\let\currentformulaframed\currentformula - \letformulaframedparameter\c!location\v!formula - \letformulaframedparameter\c!width\v!fit - \strc_math_flush_box_framed_common} - -% combiners - -\def\strc_math_flush_box - {\ifcase\c_strc_formulas_frame_mode - \strc_math_flush_box_normal - \else - \strc_math_flush_box_framed_display - \fi} - -\def\strc_math_number_right_normal - {\strc_math_flush_aligned - \hss % hss makes room for number - \math_box_llapped_math_no} - -\def\strc_math_number_left_normal - {\math_box_rlapped_math_no - \strc_math_flush_aligned - \hss} % hss makes room for number - -\def\strc_math_number_right_normal_outside - {\ifconditional\c_strc_formulas_tight - \strc_math_flush_box_framed_fit_display - \else - \strc_math_flush_box_framed_display - \fi - \hss % hss makes room for number - \math_box_llapped_math_no} - -\def\strc_math_number_left_normal_outside - {\math_box_rlapped_math_no - \hss % hss makes room for number - \ifconditional\c_strc_formulas_tight - \strc_math_flush_box_framed_fit_display - \else - \strc_math_flush_box_framed_display - \fi} - -\def\strc_math_number_right_normal_inside - {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup - \strc_math_flush_aligned - \hss - \math_box_llapped_math_no - \egroup - \strc_math_flush_box_framed_fit_inline} - -\def\strc_math_number_left_normal_inside - {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup - \math_box_rlapped_math_no - \hss - \strc_math_flush_aligned - \egroup - \strc_math_flush_box_framed_fit_inline} - -\def\strc_math_number_right_overflow - {\vpack\bgroup - \strc_math_flush_box - \par - \hpack to \displaywidth\bgroup - \hss - \math_box_llapped_math_no - \egroup - \egroup} - -\def\strc_math_number_left_overflow - {\vpack\bgroup - \hpack to \displaywidth\bgroup - \math_box_rlapped_math_no - \hss - \egroup - \strc_math_flush_box - \egroup} - -\def\strc_math_number_right_overflow_outside - {\vpack\bgroup - \strc_math_flush_box_framed_fit_inline - %\hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why - \hpack to \displaywidth\bgroup - \hss - \math_box_llapped_math_no - \egroup - \egroup} - -\def\strc_math_number_left_overflow_outside - {\vpack\bgroup - \hpack to \dimexpr\displaywidth-\d_framed_locator_lo\relax\bgroup - \math_box_rlapped_math_no - \hss - \egroup - \hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why - \strc_math_flush_box_framed_fit_inline - \egroup} - -\def\strc_math_number_right_overflow_inside - {\setbox\b_strc_math_display\vpack\bgroup - \box\b_strc_math_display - \hpack to \displaywidth\bgroup - \hss - \math_box_llapped_math_no - \hskip\d_framed_locator_ro - \egroup - \egroup - \strc_math_flush_box_framed_fit_inline} - -\def\strc_math_number_left_overflow_inside - {\setbox\b_strc_math_display\vpack\bgroup - \hpack to \displaywidth\bgroup - % \hskip\d_framed_locator_lo - \math_box_rlapped_math_no - \hss - \egroup - \box\b_strc_math_display - \egroup - \strc_math_flush_box_framed_fit_inline} - -% checkers - -\def\strc_math_number_check - {\d_strc_math_display_width\wd\b_strc_math_display - \ifconditional\c_strc_formulas_tight - \ifdim\d_strc_math_display_width>\displaywidth - \settrue\c_strc_math_display_overflow - \else - \displaywidth\d_strc_math_display_width - \setfalse\c_strc_math_display_overflow - \fi - \else - \ifdim\d_strc_math_display_width>\displaywidth - \settrue\c_strc_math_display_overflow - \else - \setfalse\c_strc_math_display_overflow - \fi - \fi} - -\def\strc_math_number_check_outside - {\d_strc_math_display_width\naturalwd\b_strc_math_display - \ifdim\dimexpr\d_strc_math_display_width+\d_framed_locator_lo+\d_framed_locator_ro\relax>\displaywidth - \settrue\c_strc_math_display_overflow - \else - \setfalse\c_strc_math_display_overflow - \fi - % still ok? - \ifnum\mathraggedstatus=\plustwo - \d_strc_math_framed_width\dimexpr\displaywidth-2\wd\b_strc_formulas_number\relax - \else - \d_strc_math_framed_width\dimexpr\displaywidth- \wd\b_strc_formulas_number\relax - \fi} - -\let\strc_math_number_check_inside\strc_math_number_check_outside - -% offsets - -\def\strc_math_number_check_offsets - {\begingroup - \setbox\scratchbox\hbox - {\inheritedformulaframedframed - {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}% - \endgroup} - -% tracing - -\def\strc_math_traced_state_yes - {\llap{\setbox\scratchbox\hbox{\infofont - \ifcase\mathraggedstatus unset\or right\or middle\or left\fi - \space - \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi - \space - \ifconditional\c_strc_math_display_overflow overflow\else fit\fi - \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}} - -\let\strc_math_traced_state\relax - -\installtextracker - {formulas.framed} - {\let\strc_math_traced_state\strc_math_traced_state_yes} - {\let\strc_math_traced_state\relax} - -% packaging - -\protected\def\strc_math_box_start#1% - {\hsize\displaywidth % \checkeddisplaymath - \global\mathnumberstatus\plusone - \mathraggedstatus#1\relax - % - \global\d_math_number_correction\zeropoint - % - \edef\p_location{\formulaparameter\c!location}% - \useformulacolorparameter\c!color - \c_strc_math_number_location\ifx\p_location\v!left\plusone\orelse\ifx\p_location\v!right\plustwo\else\zerocount\fi - % - %\strc_formulas_place_number % not here as we can have inner alignment numbers - \dontcomplain - \setbox\b_strc_math_display\math_hbox\bgroup % \checkeddisplaymath - \mathinnerstrut - \startforceddisplaymath} - -\def\strc_math_flush_number_no - {\ifcase\c_strc_math_vertical - \ifconditional\c_strc_math_display_overflow - \ifcase\c_strc_formulas_frame_mode - \strc_math_flush_box_normal - \else - \strc_math_flush_box_framed_fit_inline - \fi - \else - \ifcase\c_strc_formulas_frame_mode - %\ifconditional\c_strc_formulas_tight - % \strc_math_flush_box_normal - %\else - \strc_math_flush_box_normal - %\fi - \else - \ifconditional\c_strc_formulas_tight - \strc_math_flush_box_framed_fit_inline - \else - \strc_math_flush_box_framed_display - \fi - \fi - \fi - \else - \strc_math_flush_box - \fi} - -\def\strc_math_flush_number_left - {\ifcase\c_strc_math_vertical - \ifconditional\c_strc_math_display_overflow - \ifcase\c_strc_formulas_frame_mode - \strc_math_number_left_overflow - \or - \strc_math_number_left_overflow_outside - \or - \strc_math_number_left_overflow_inside - \fi - \else - \ifcase\c_strc_formulas_frame_mode - \strc_math_number_left_normal - \or - \strc_math_number_left_normal_outside - \or - \strc_math_number_left_normal_inside - \fi - \fi - \else - \box\b_strc_formulas_number - \hfill - \strc_math_flush_aligned - \fi} - -\def\strc_math_flush_number_right - {\ifcase\c_strc_math_vertical - \ifconditional\c_strc_math_display_overflow - \ifcase\c_strc_formulas_frame_mode - \strc_math_number_right_overflow - \or - \strc_math_number_right_overflow_outside - \or - \strc_math_number_right_overflow_inside - \fi - \else - \ifcase\c_strc_formulas_frame_mode - \strc_math_number_right_normal - \or - \strc_math_number_right_normal_outside - \or - \strc_math_number_right_normal_inside - \fi - \fi - \else - \strc_math_flush_aligned - \hfill - \box\b_strc_formulas_number - \fi} - -\protected\def\strc_math_box_stop - {\stopforceddisplaymath - \egroup - % check number - \d_strc_math_number_width\wd\b_strc_formulas_number - % - \ifcase\mathnumberstatus - \setfalse\c_strc_math_has_number - \or\ifzeropt\d_strc_math_number_width - \setfalse\c_strc_math_has_number - \else - \settrue\c_strc_math_has_number - \fi\fi - % preroll left and right offsets - \ifcase\c_strc_formulas_frame_mode - % no frame - \else - \strc_math_number_check_offsets - \fi - \ifcase\c_strc_formulas_frame_mode - \strc_math_number_check - \or - \strc_math_number_check_outside - \else - \strc_math_number_check_inside - \fi - \noindent % \noindentation % not \dontleavehmode - \hskip\d_strc_formulas_display_margin_left % was kern but that doesn't indent - \strc_math_traced_state - \ifcase\c_strc_math_vertical - \hbox to \displaywidth \bgroup - \or - \vbox \bgroup \hsize\displaywidth - \or - \bgroup \hsize\displaywidth - \fi - \ifcase\mathnumberstatus - \strc_math_flush_box - \or % status 1 - \ifcase\c_strc_math_number_location - \strc_math_flush_box - \or % number left - \ifzeropt\wd\b_strc_formulas_number - \strc_math_flush_number_no - \else - \strc_math_flush_number_left - \fi - \else % number right - \ifzeropt\wd\b_strc_formulas_number - \strc_math_flush_number_no - \else - \strc_math_flush_number_right - \fi - \fi - \or % status 2 - \hskip\d_math_number_correction % probably no longer used - \strc_math_flush_box - \hss - \else - \strc_math_flush_box - \fi - \ifcase\c_strc_math_vertical - \or - \or - \par - \fi - \egroup} - -\defineinnermathhandler\v!left {\strc_math_box_start\plusone }{\strc_math_box_stop} -\defineinnermathhandler\v!middle {\strc_math_box_start\plustwo }{\strc_math_box_stop} -\defineinnermathhandler\v!right {\strc_math_box_start\plusthree}{\strc_math_box_stop} -\defineinnermathhandler\v!flushleft {\strc_math_box_start\plusthree}{\strc_math_box_stop} -\defineinnermathhandler\v!center {\strc_math_box_start\plustwo }{\strc_math_box_stop} -\defineinnermathhandler\v!flushright{\strc_math_box_start\plusone }{\strc_math_box_stop} -\defineinnermathhandler\v!normal {\strc_math_box_start\plustwo }{\strc_math_box_stop} - -%D Some inline math tweak. - -\appendtoks - \ifcase\mathnestinglevel\or - % 4=disable 6=only when no spaces - \mathsurroundskip\mathematicsparameter\c!textdistance\relax - \ifzeropt\mathsurroundskip - \ifzeropt\gluestretch\mathsurroundskip - \ifzeropt\glueshrink\mathsurroundskip - \mathsurroundmode\plussix - \else - \mathsurroundskip\zeropoint - \mathsurroundmode\plusfour - \fi - \else - \mathsurroundmode\plussix - \fi - \else - \mathsurroundmode\plussix - \fi - \else - \mathsurroundmode\plusfour - \mathsurroundskip\zeropoint - \fi -\to \everymathematics - -\setupmathematics - [\c!textdistance=\zeropoint] - -%D This is an experiment. No fancy spacing and alignments here. If we ever -%D go that route it might result in incompatible rendering. - -\permanent\protected\def\startsplitformula - {\ifhmode - \par - \fi - \begingroup - \beforedisplayspace - % subset of \everydisplay: - \c_attr_mathmode\plusone - \settrue \indisplaymath - % end of subset - \informulatrue} - -\permanent\protected\def\stopsplitformula - {\afterdisplayspace - \endgroup} - -\protect \endinput - -% \placeformula \startformula[-] \startmatrix -% \NC 1 \NC x \NC a \NR -% \NC 2 \NC y \NC b \NR -% \NC 3 \NC z \NC c \NR -% \stopmatrix \stopformula - -% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}] - -% \placeformula \startformula[-] \startbordermatrix -% \NC 1 \NC x \NC a \NR -% \NC 2 \NC y \NC b \NR -% \NC 3 \NC z \NC c \NR -% \stopbordermatrix \stopformula diff --git a/tex/context/base/mkiv/math-fen.mkxl b/tex/context/base/mkiv/math-fen.mkxl deleted file mode 100644 index 4d19fb210..000000000 --- a/tex/context/base/mkiv/math-fen.mkxl +++ /dev/null @@ -1,829 +0,0 @@ -%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 - -% maybe always "method=auto" for: -% -% \switchtobodyfont[cambria] -% \ruledhbox{$f(x)$} -% \ruledhbox{\mathdelimitersmode6$f\left(x\right)$} -% \ruledhbox{\mathdelimitersmode7$f\left(x\right)$} -% \ruledhbox{$f\left(\frac{1}{x}\right)$} - -% 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 - -\aliased\let\setupmathfences\setupmathfence - -\setupmathfences - [\c!method=, % maybe always \v!auto - \c!left=, - \c!right=, - \c!middle=, - \c!mathstyle=, - \c!color=, - \c!command=, - \c!mathclass=, - \c!factor=\v!auto] - -\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 - -%D So we can do: -%D -%D \starttyping -%D $ a + \fenced[bar][size=1] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=2] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=3] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=4] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=big] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=Big] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=bigg]{\frac {b} {c}} + d $ -%D $ a + \fenced[bar][size=Bigg]{\frac {b} {c}} + d $ -%D $ a + \fenced[bar][factor=1] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][factor=2] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar][factor=4] {\frac {b} {c}} + d $ -%D $ a + \fenced[bar] {\frac {b} {c}} + d $ -%D \stoptyping - -\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror -\newconditional\c_math_fenced_sized \setfalse\c_math_fenced_sized - -\installcorenamespace {mathfencesize} - -\setvalue{\??mathfencesize big}{1} -\setvalue{\??mathfencesize Big}{2} -\setvalue{\??mathfencesize bigg}{3} -\setvalue{\??mathfencesize Bigg}{4} - -\def\math_fenced_force_size#1#2% - {\c_attr_mathsize\numexpr - #1*\plushundred - +\ifcsname\??mathfencesize#2\endcsname\lastnamedcs\else#2\fi - \relax} - -\protected\def\math_fenced_inject#1#2#3#4% - {\ifx#1\empty - #2.% - \else - \edef\p_mathclass{\mathfenceparameter\c!mathclass}% - \ifconditional\c_math_fenced_sized - \let\p_factor\v!fixed - \else - \edef\p_factor{\mathfenceparameter\c!factor}% - \fi - \ifempty\p_factor - \ifempty\p_mathclass - #2% - \else - #3% - \s!class\p_mathclass - \fi - \orelse\ifx\p_factor\v!auto - \ifempty\p_mathclass - #2% - \else - #3% - \s!class\p_mathclass - \fi - \orelse\ifx\p_factor\v!none - #3% - \s!height\zeropoint - \s!depth\zeropoint - \ifempty\p_mathclass\else - \s!class\p_mathclass - \fi - \s!axis - % #2% - \else - \scratchdimen\ifx\p_factor\v!fixed\scaledpoint\else\dimexpr\p_factor\bodyfontsize/2\relax\fi - #3% - \s!height\scratchdimen - \s!depth\scratchdimen - \ifempty\p_mathclass\else - \s!class\p_mathclass - \fi - \s!axis - \fi - \Udelimiter#4\fam#1\relax - \fi} - -\permanent\def\math_fenced_left - {\edef\p_left - {\ifconditional\c_math_fenced_mirror - \ifconditional\c_math_right_to_left - \mathfenceparameter\c!right - \else - \mathfenceparameter\c!left - \fi - \else - \mathfenceparameter\c!left - \fi}% - \math_fenced_color_push - \math_fenced_inject\p_left\normalleft\Uleft\plusfour - \math_fenced_color_pop} - -\permanent\def\math_fenced_middle - {\edef\p_middle{\mathfenceparameter\c!middle}% - \mskip\thinmuskip - \math_fenced_color_push - \math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour - \math_fenced_color_pop - \mskip\thinmuskip} - -\permanent\def\math_fenced_right - {\edef\p_right - {\ifconditional\c_math_fenced_mirror - \ifconditional\c_math_right_to_left - \mathfenceparameter\c!left - \else - \mathfenceparameter\c!right - \fi - \else - \mathfenceparameter\c!right - \fi}% - \math_fenced_color_push - \math_fenced_inject\p_right\normalright\Uright\plusfive - \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 - -\aliased\let\fence \relax -\aliased\let\fenced\relax - -\newcount\c_math_fenced_nesting - -\protected\def\math_fenced_fenced_common - {\startusemathstyleparameter\mathfenceparameter - \enforced\let\fence\math_fenced_middle - \edef\p_math_fenced_color{\mathfenceparameter\c!color}% - \ifempty\p_math_fenced_color - \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} - -\protected\def\math_fenced_fenced_start#1% - {\advance\c_math_fenced_nesting\plusone - \begingroup - \edef\currentmathfence{#1}% - \math_fenced_fenced_common - \math_fenced_left} - -\protected\def\math_fenced_fenced_stop#1% - {\edef\currentmathfence{#1}% - \math_fenced_right - \stopusemathstyleparameter - \endgroup - \advance\c_math_fenced_nesting\minusone} - -\tolerant\protected\def\math_fenced_fenced[#1]#*[#2]% - {\advance\c_math_fenced_nesting\plusone - \begingroup - \edef\currentmathfence{#1}% - \ifparameter#2\or\setupcurrentmathfence[#2]\fi - \math_fenced_fenced_common - \edef\p_size{\mathfenceparameter\c!size}% - \ifempty\p_size - \expandafter\math_fenced_fenced_indeed_adapt - \else - \expandafter\math_fenced_fenced_indeed_fixed - \fi} - -\protected\def\math_fenced_fenced_indeed_finish - {\stopusemathstyleparameter - \endgroup - \advance\c_math_fenced_nesting\minusone} - -\protected\def\math_fenced_fenced_indeed_fixed#1% - {\math_fenced_force_size\bigmathdelimitervariant\p_size - \settrue\c_math_fenced_sized - \math_fenced_left - \setfalse\c_math_fenced_sized - #1% - \settrue\c_math_fenced_sized - \math_fenced_right - \setfalse\c_math_fenced_sized - \math_fenced_fenced_indeed_finish} - -\protected\def\math_fenced_fenced_indeed_adapt#1% - {\setfalse\c_math_fenced_sized - \math_fenced_left - #1% - \setfalse\c_math_fenced_sized - \math_fenced_right - \math_fenced_fenced_indeed_finish} - -\appendtoks - \enforced\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: - -\pushoverloadmode - -\immutable\protected\def\Lparenthesis {\math_fenced_fenced_start{parenthesis}} \immutable\protected\def\Rparenthesis {\math_fenced_fenced_stop {parenthesis}} -\immutable\protected\def\Lbracket {\math_fenced_fenced_start{bracket}} \immutable\protected\def\Rbracket {\math_fenced_fenced_stop {bracket}} -\immutable\protected\def\Lbrace {\math_fenced_fenced_start{brace}} \immutable\protected\def\Rbrace {\math_fenced_fenced_stop {brace}} -\immutable\protected\def\Langle {\math_fenced_fenced_start{angle}} \immutable\protected\def\Rangle {\math_fenced_fenced_stop {angle}} -\immutable\protected\def\Ldoubleangle {\math_fenced_fenced_start{doubleangle}} \immutable\protected\def\Rdoubleangle {\math_fenced_fenced_stop {doubleangle}} -\immutable\protected\def\Lbar {\math_fenced_fenced_start{bar}} \immutable\protected\def\Rbar {\math_fenced_fenced_stop {bar}} -\immutable\protected\def\Ldoublebar {\math_fenced_fenced_start{doublebar}} \immutable\protected\def\Rdoublebar {\math_fenced_fenced_stop {doublebar}} -\immutable\protected\def\Ltriplebar {\math_fenced_fenced_start{triplebar}} \immutable\protected\def\Rtriplebar {\math_fenced_fenced_stop {triplebar}} -\immutable\protected\def\Lsolidus {\math_fenced_fenced_start{solidus}} \immutable\protected\def\Rsolidus {\math_fenced_fenced_stop {solidus}} -\immutable\protected\def\Lfloor {\math_fenced_fenced_start{floor}} \immutable\protected\def\Rfloor {\math_fenced_fenced_stop {floor}} -\immutable\protected\def\Lceiling {\math_fenced_fenced_start{ceiling}} \immutable\protected\def\Rceiling {\math_fenced_fenced_stop {ceiling}} -\immutable\protected\def\Lmoustache {\math_fenced_fenced_start{moustache}} \immutable\protected\def\Rmoustache {\math_fenced_fenced_stop {moustache}} -\immutable\protected\def\Luppercorner {\math_fenced_fenced_start{uppercorner}} \immutable\protected\def\Ruppercorner {\math_fenced_fenced_stop {uppercorner}} -\immutable\protected\def\Llowercorner {\math_fenced_fenced_start{lowercorner}} \immutable\protected\def\Rlowercorner {\math_fenced_fenced_stop {lowercorner}} -\immutable\protected\def\Lgroup {\math_fenced_fenced_start{group}} \immutable\protected\def\Rgroup {\math_fenced_fenced_stop {group}} -\immutable\protected\def\Lopenbracket {\math_fenced_fenced_start{openbracket}} \immutable\protected\def\Ropenbracket {\math_fenced_fenced_stop {openbracket}} -\immutable\protected\def\Lnothing {\math_fenced_fenced_start{nothing}} \immutable\protected\def\Rnothing {\math_fenced_fenced_stop {nothing}} - -\immutable\protected\def\Lparenthesismirrored {\math_fenced_fenced_stop {mirroredparenthesis}} \immutable\protected\def\Rparenthesismirrored {\math_fenced_fenced_start{mirroredparenthesis}} -\immutable\protected\def\Lbracketmirrored {\math_fenced_fenced_stop {mirroredbracket}} \immutable\protected\def\Rbracketmirrored {\math_fenced_fenced_start{mirroredbracket}} -\immutable\protected\def\Lbracemirrored {\math_fenced_fenced_stop {mirroredbrace}} \immutable\protected\def\Rbracemirrored {\math_fenced_fenced_start{mirroredbrace}} -\immutable\protected\def\Langlemirrored {\math_fenced_fenced_stop {mirroredangle}} \immutable\protected\def\Ranglemirrored {\math_fenced_fenced_start{mirroredangle}} -\immutable\protected\def\Ldoubleanglemirrored {\math_fenced_fenced_stop {mirroreddoubleangle}} \immutable\protected\def\Rdoubleanglemirrored {\math_fenced_fenced_start{mirroreddoubleangle}} -\immutable\protected\def\Lbarmirrored {\math_fenced_fenced_stop {mirroredbar}} \immutable\protected\def\Rbarmirrored {\math_fenced_fenced_start{mirroredbar}} -\immutable\protected\def\Ldoublebarmirrored {\math_fenced_fenced_stop {mirroreddoublebar}} \immutable\protected\def\Rdoublebarmirrored {\math_fenced_fenced_start{mirroreddoublebar}} -\immutable\protected\def\Ltriplebarmirrored {\math_fenced_fenced_stop {mirroredtriplebar}} \immutable\protected\def\Rtriplebarmirrored {\math_fenced_fenced_start{mirroredtriplebar}} -\immutable\protected\def\Lsolidusmirrored {\math_fenced_fenced_stop {mirroredsolidus}} \immutable\protected\def\Rsolidusmirrored {\math_fenced_fenced_start{mirroredsolidus}} -\immutable\protected\def\Lfloormirrored {\math_fenced_fenced_stop {mirroredfloor}} \immutable\protected\def\Rfloormirrored {\math_fenced_fenced_start{mirroredfloor}} -\immutable\protected\def\Lceilingmirrored {\math_fenced_fenced_stop {mirroredceiling}} \immutable\protected\def\Rceilingmirrored {\math_fenced_fenced_start{mirroredceiling}} -\immutable\protected\def\Lmoustachemirrored {\math_fenced_fenced_stop {mirroredmoustache}} \immutable\protected\def\Rmoustachemirrored {\math_fenced_fenced_start{mirroredmoustache}} -\immutable\protected\def\Luppercornermirrored {\math_fenced_fenced_stop {mirroreduppercorner}} \immutable\protected\def\Ruppercornermirrored {\math_fenced_fenced_start{mirroreduppercorner}} -\immutable\protected\def\Llowercornermirrored {\math_fenced_fenced_stop {mirroredlowercorner}} \immutable\protected\def\Rlowercornermirrored {\math_fenced_fenced_start{mirroredlowercorner}} -\immutable\protected\def\Lgroupmirrored {\math_fenced_fenced_stop {mirroredgroup}} \immutable\protected\def\Rgroupmirrored {\math_fenced_fenced_start{mirroredgroup}} -\immutable\protected\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}} \immutable\protected\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}} -\immutable\protected\def\Lnothingmirrored {\math_fenced_fenced_stop {mirrorednothing}} \immutable\protected\def\Rnothingmirrored {\math_fenced_fenced_start{mirrorednothing}} - -\definemathfence [interval] [\c!left="2997,\c!right="2998] -\definemathfence [openinterval] [interval] [\c!left="2998,\c!right="2998] -\definemathfence [leftopeninterval] [interval] [\c!left="2997,\c!right="2997] -\definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998] - -\immutable\protected\def\Linterval {\math_fenced_fenced_start{interval}} -\immutable\protected\def\Lointerval {\math_fenced_fenced_start{openinterval}} -\immutable\protected\def\Llointerval {\math_fenced_fenced_start{leftopeninterval}} -\immutable\protected\def\Lrointerval {\math_fenced_fenced_start{rightopeninterval}} - -\immutable\protected\def\Rinterval {\math_fenced_fenced_stop {interval}} -\immutable\protected\def\Rointerval {\math_fenced_fenced_stop {openinterval}} -\immutable\protected\def\Rlointerval {\math_fenced_fenced_stop {leftopeninterval}} -\immutable\protected\def\Rrointerval {\math_fenced_fenced_stop {rightopeninterval}} - -% \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 - -\popoverloadmode - -\installcorenamespace{mathleft} -\installcorenamespace{mathright} -\installcorenamespace{mathmiddle} - -\pushoverloadmode - -\protected\def\left {\afterassignment\math_left \let\nexttoken} -\protected\def\right {\afterassignment\math_right \let\nexttoken} -\protected\def\middle{\afterassignment\math_middle\let\nexttoken} - -\popoverloadmode - -\let\leftorright\relax - -\newconditional\c_math_fenced_done -\newconditional\c_math_fenced_unknown \settrue\c_math_fenced_unknown - -\protected\def\installmathfencepair#1#2#3#4% - {\letcsname\??mathleft \normalmeaning#1\endcsname#2% - \letcsname\??mathright\normalmeaning#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\normalmeaning\nexttoken\endcsname - \expandafter\lastnamedcs - \else - \expandafter\math_unknown_left - \fi} - -\def\math_right - {\settrue\c_math_fenced_done - \ifcsname\??mathright\normalmeaning\nexttoken\endcsname - \expandafter\lastnamedcs - \else - \expandafter\math_unknown_right - \fi} - -\def\math_middle - {\settrue\c_math_fenced_done - \ifcsname\??mathmiddle\normalmeaning\nexttoken\endcsname - \expandafter\lastnamedcs - \else - \expandafter\math_unknown_middle - \fi} - -\protected\def\lfence#1% - {\settrue\c_math_fenced_done - \let\nexttoken#1% - \ifcsname\??mathleft\normalmeaning\nexttoken\endcsname - \expandafter\lastnamedcs - \else - \expandafter\math_unknown_left - \fi} - -\protected\def\rfence#1% - {\settrue\c_math_fenced_done - \let\nexttoken#1% - \ifcsname\??mathright\normalmeaning\nexttoken\endcsname - \expandafter\lastnamedcs - \else - \expandafter\math_unknown_right - \fi} - -\protected\def\mfence#1% - {\settrue\c_math_fenced_done - \let\nexttoken#1% - \ifcsname\??mathmiddle\normalmeaning\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 ) \Rparenthesismirrored ( \Lparenthesismirrored - -\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 - -\installmathfencepair ⦗ \Linterval ⦘ \Rinterval - -\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): - -\pushoverloadmode - -\aliased\let\lbrack \lbracket -\aliased\let\rbrack \rbracket -\aliased\let\lceiling \lceil -\aliased\let\rceiling \rceil -\aliased\let\lparenthesis\lparent -\aliased\let\rparenthesis\rparent -\aliased\let\lparen \lparent -\aliased\let\rparen \rparent - -% Just defined: - -\aliased\let\Lceil \Lceiling -\aliased\let\Rceil \Rceiling -\aliased\let\Lparent\Lparenthesis -\aliased\let\Rparent\Rparenthesis -\aliased\let\Lparen \Lparenthesis -\aliased\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 - -\installmathfencepair \linterval \Linterval \rinterval \Rinterval -%installmathfencepair \linterv \Linterval \rinterv \Rinterval -\installmathfencepair \lointerval \Linterval \rointerval \Rinterval -\installmathfencepair \llointerval \Llointerval \rlointerval \Rlointerval -\installmathfencepair \lrointerval \Lrointerval \rrointerval \Rrointerval - -\aliased\let\textlbar\lbar \aliased\let\mathlbar\Lbar -\aliased\let\textrbar\lbar \aliased\let\mathrbar\Rbar - -\immutable\protected\def\lbar{\mathortext\mathlbar\textlbar} -\immutable\protected\def\rbar{\mathortext\mathrbar\textrbar} - -% \setupmathfences[color=darkgreen] - -\permanent\protected\def\{{\mathortext\lbrace \letterleftbrace } % or maybe a chardef -\permanent\protected\def\}{\mathortext\rbrace \letterrightbrace } % or maybe a chardef -\permanent\protected\def\[{\mathortext\lbracket \letterleftbracket } % or maybe a chardef -\permanent\protected\def\]{\mathortext\rbracket \letterrightbracket } % or maybe a chardef -\permanent\protected\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef -\permanent\protected\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef -\permanent\protected\def\|{\mathortext\vert \letterbar } % or maybe a chardef -%permanent\protected\def\/{\mathortext\solidus \letterslash } % or maybe a chardef - -\installmathfencepair \{ \Lbrace \} \Rbrace -\installmathfencepair \[ \Lbracket \] \Rbracket -\installmathfencepair \( \Lparenthesis \) \Rparenthesis -\installmathfencepair \< \Langle \> \Rangle -\installmathfencepair \| \Lbar \| \Rbar - -\popoverloadmode - -%D As we have overloaded \type {\left} and \type {\right} we also need a more -%D clever version of the following: - -% 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 - -\protected\def\plainbigdelimiters % traditional method - {\bigmathdelimitermethod\plustwo} - -\plainbigdelimiters % is default for the moment but not so nice - -% \setconstant\bigmathdelimitermethod\plusone - -\installcorenamespace{mathbig} - -\setvalue{\??mathbig1}{0.85} -\setvalue{\??mathbig2}{1.15} -\setvalue{\??mathbig3}{1.45} -\setvalue{\??mathbig4}{1.75} - -\protected\def\choosemathbig#1#2% so we accept \big{||} as well - {{\naturalhbox\bgroup - \startimath - \ifcase\bigmathdelimitermethod - \math_fenced_step#2\relax - \or - \math_fenced_force_size\bigmathdelimitervariant{#1}\relax - \math_fenced_step#2\relax - \else - \math_fenced_step#2{\vpack to\csname\??mathbig#1\endcsname\bodyfontsize{}}% - \fi - \nulldelimiterspace\zeropoint\relax - \mathsurround\zeropoint - \stopimath - \egroup}} - -% needs testing: -% -% \protected\def\choosemathbig#1#2% so we accept \big{||} as well -% {{\naturalhbox\bgroup -% \startimath -% \ifcase\bigmathdelimitermethod -% \Uvextensible#2\relax -% \or -% \math_fenced_force_size\bigmathdelimitervariant{#1}\relax -% \Uvextensible#2\relax -% \else -% \scratchdimen.5\dimexpr\csname\??mathbig\number#1\endcsname\bodyfontsize+1.1\exheight\relax -% \Uvextensible\s!axis \s!depth \scratchdimen \s!height \scratchdimen #2\relax -% \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} - -\protected\def\mathdelimiterstep#1#2% - {\begingroup - \math_fenced_force_size\plusone{#1}% - \math_fenced_step#2\relax - \endgroup} - -\definemathcommand [big] {\choosemathbig1} -\definemathcommand [Big] {\choosemathbig2} -\definemathcommand [bigg] {\choosemathbig3} -\definemathcommand [Bigg] {\choosemathbig4} - -\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] -% -% \protected\def\Lintegral {\math_fenced_fenced_start{integral}} -% \protected\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 The nested fences recovery code is needed for mathml and the original -%D code can still be found in the mkiv file. - -\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 - -\protected\def\math_fences_auto_left #1{\c_attr_mathautofence\plusone #1\c_attr_mathautofence\attributeunsetvalue} -\protected\def\math_fences_auto_right #1{\c_attr_mathautofence\plustwo #1\c_attr_mathautofence\attributeunsetvalue} -\protected\def\math_fences_auto_middle#1{\c_attr_mathautofence\plusthree#1\c_attr_mathautofence\attributeunsetvalue} -\protected\def\math_fences_auto_both #1{\c_attr_mathautofence\plusfour #1\c_attr_mathautofence\attributeunsetvalue} - -\permanent\let\autofenceopen \math_fences_auto_left % for testing -\permanent\let\autofenceclose \math_fences_auto_right % for testing -\permanent\let\autofenceleft \math_fences_auto_left % for testing -\permanent\let\autofenceright \math_fences_auto_right % for testing -\permanent\let\autofencemiddle\math_fences_auto_middle % for testing -\permanent\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 - -\protected\def\enableautofences - {\clf_enableautofences - \glet\clf_enableautofences\relax % onlyonce anyway - \protected\gdef\enableautofences{\settrue\c_math_fences_auto}% - \enableautofences} - -\protected\def\disableautofences - {\setfalse\c_math_fences_auto} - -\protected\def\math_fences_used_left - {\ifconditional\c_math_fences_auto - \expandafter\math_fences_auto_left - \else - \expandafter\math_fences_normal_left - \fi} - -\protected\def\math_fences_used_right - {\ifconditional\c_math_fences_auto - \expandafter\math_fences_auto_right - \else - \expandafter\math_fences_normal_right - \fi} - -\protected\def\math_fences_used_middle - {\ifconditional\c_math_fences_auto - \expandafter\math_fences_auto_middle - \else - \expandafter\math_fences_normal_middle - \fi} - -\protected\def\math_fences_used_both - {\ifconditional\c_math_fences_auto - \expandafter\math_fences_auto_both - \else - \expandafter\math_fences_normal_both - \fi} - -\permanent\let\left \math_fences_used_left -\permanent\let\right \math_fences_used_right -\permanent\let\middle \math_fences_used_middle -\permanent\let\leftorright\math_fences_used_both - -% wrappers - -\protected\def\startcheckedfences - {\begingroup - \enableautofences} - -\protected\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 - \ifempty\currentmathfence - \doifelse{\mathfenceparameter\c!state}\v!auto\enableautofences\disableautofences - \fi -\to \everysetupmathfence - -\newconstant\c_math_fences_delimiters_mode \c_math_fences_delimiters_mode"16 % \numexpr"02+"04+"10\relax - -%unexpanded\def\enableautofencemode {\mathdelimitersmode\plussix} % the shift (1) is too fragile -\protected\def\enableautofencemode {\mathdelimitersmode\c_math_fences_delimiters_mode} - -\protected\def\disableautofencemode{\mathdelimitersmode\zerocount} - -\appendtoks - \ifempty\currentmathfence - \doifelse{\mathfenceparameter\c!method}\v!auto\enableautofencemode\disableautofencemode - \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/tex/context/base/mkiv/math-frc.mkxl b/tex/context/base/mkiv/math-frc.mkxl deleted file mode 100644 index b232868cd..000000000 --- a/tex/context/base/mkiv/math-frc.mkxl +++ /dev/null @@ -1,833 +0,0 @@ -%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. - -\permanent\protected\def\topstrut{\vrule\s!width\zeropoint\s!height\strutht\s!depth\zeropoint\relax} -\permanent\protected\def\botstrut{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp\relax} - -\permanent\protected\def\mathtopstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\ht\scratchbox\s!depth\zeropoint\relax} -\permanent\protected\def\mathbotstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\dp\scratchbox\relax} - -%D This module is reimplemented in \MKIV\ style. - -\registerctxluafile{math-frc}{} - -%D \macros -%D {frac, xfrac, xxfrac} -%D -%D This is another one Tobias asked for. It replaces the primitive \type -%D {\over}. We also take the opportunity to handle math style restoring, -%D which makes sure units and chemicals come out ok. The \type {\frac} -%D macro kind of replaces the awkward \type {\over} primitive. Say that -%D we have the following formulas: -%D -%D \startbuffer[sample] -%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$ -%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$ -%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$ -%D \stopbuffer -%D -%D \typebuffer[sample] -%D -%D With the most straightforward definitions, we get: -%D -%D \startbuffer[code] -%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}} -%D -%D \def\frac {\dofrac\mathstyle} -%D \def\xfrac {\dofrac\scriptstyle} -%D \def\xxfrac{\dofrac\scriptscriptstyle} -%D \stopbuffer -%D -%D \typebuffer[code] \getbuffer[code,sample] -%D -%D Since this does not work well, we can try: -%D -%D \startbuffer[code] -%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}} -%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}} -%D \stopbuffer -%D -%D \typebuffer[code] \getbuffer[code,sample] -%D -%D This for sure looks better than: -%D -%D \startbuffer[code] -%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}} -%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}} -%D \stopbuffer -%D -%D \typebuffer[code] \getbuffer[code,sample] -%D -%D So we stick to the next definitions (watch the local overloading of -%D \type {\xfrac}). -%D -%D In the meantime, in \LUATEX, we have better control over styles so the -%D following macros are different from the \MKII\ ones. - -% obsolete, is now c!mathstyle -% -% 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle -% -% $\mathfracmode0 \frac{1}{2}$ -% $\mathfracmode1 \frac{1}{2}$ -% $\mathfracmode2 \frac{1}{2}$ -% $\mathfracmode3 \frac{1}{2}$ -% $\mathfracmode4 \frac{1}{2}$ -% $\mathfracmode5 \frac{1}{2}$ -% -% we keep the constant for a while - -\setnewconstant\mathfracmode\zerocount - -\installcorenamespace{mathfractions} -\installcorenamespace{mathfractionstyle} -\installcorenamespace{mathfractionalternative} - -\installcommandhandler \??mathfractions {mathfraction} \??mathfractions - -\aliased\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 - \instance\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 - -\protected\def\math_fraction_set_distance_top - {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top - \relax} - -\protected\def\math_fraction_set_distance_bot - {\Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot - \relax} - -\protected\def\math_fraction_set_distance_all - {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top - \Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot - \relax} - -\appendtoks - \ifempty\currentmathfraction - \edef\m_math_fraction_distance_top{\mathfractionparameter\c!topdistance}% - \edef\m_math_fraction_distance_bot{\mathfractionparameter\c!bottomdistance}% - \ifempty\m_math_fraction_distance_top - \ifempty\m_math_fraction_distance_bot - \let\math_fraction_set_distance\relax - \else - \let\math_fraction_set_distance\math_fraction_set_distance_bot - \fi - \else - \ifempty\m_math_fraction_distance_bot - \let\math_fraction_set_distance\math_fraction_set_distance_top - \else - \let\math_fraction_set_distance\math_fraction_set_distance_all - \fi - \fi - \fi -\to \everysetupmathfraction - -% So far for control. - -\installcorenamespace{mathfractionstrut} - -\def\math_frac_no_strut - {\enforced\let\m_fractions_strut_top\relax - \enforced\let\m_fractions_strut_bot\relax} - -\setvalue{\??mathfractionstrut\v!yes}% - {\enforced\let\m_fractions_strut_top\mathstrut - \enforced\let\m_fractions_strut_bot\mathstrut} - -\setvalue{\??mathfractionstrut\v!math}% - {\enforced\let\m_fractions_strut_top\mathstrut - \enforced\let\m_fractions_strut_bot\mathstrut} - -\letvalue{\??mathfractionstrut\v!no}\math_frac_no_strut - -\setvalue{\??mathfractionstrut\v!tight}% - {\enforced\let\m_fractions_strut_top\mathbotstrut % indeed swapped name - \enforced\let\m_fractions_strut_bot\mathtopstrut} % indeed swapped name - -\math_frac_no_strut - -\newdimen\d_math_fraction_margin - -\protected\def\math_frac#1% - {\begingroup - \edef\currentmathfraction{#1}% - % - \edef\p_math_fraction_fences{\mathfractionparameter\c!fences}% - \ifempty\p_math_fraction_fences \else - \math_fenced_fenced_start\p_math_fraction_fences - \fi - % - \d_math_fraction_margin\mathfractionparameter\c!margin - % - \edef\p_math_fractions_color{\mathfractionparameter\c!color}% - % - \edef\p_math_fractions_strut{\mathfractionparameter\c!strut}% - \ifcsname\??mathfractionstrut\p_math_fractions_strut\endcsname - \lastnamedcs - \else - \math_frac_no_strut - \fi - % - \ifempty\p_math_fractions_color - \expandafter\math_frac_normal - \else - \expandafter\math_frac_colored - \fi} - -\protected\def\math_frac_wrapup - {\ifempty\p_math_fraction_fences \else - \math_fenced_fenced_stop\p_math_fraction_fences - \fi - \endgroup} - -\protected\def\math_frac_colored#1#2% - {\savecolor - \colo_helpers_activate\p_math_fractions_color - \math_frac_normal{\restorecolor#1}{\restorecolor#2}} - -\protected\def\math_frac_normal - {\expandnamespaceparameter\??mathfractionalternative\mathfractionparameter\c!alternative\v!inner} - -% we use utfchar anyway so we can as well do all at the lua end - -\def\math_frac_no_delim{0x2E} - -\def\math_frac_command - {\clf_mathfraction - {\mathfractionparameter\c!rule}% - \ifempty\p_math_fraction_fences - \mathfractionparameter\c!left \space - \mathfractionparameter\c!right\space - \else - \math_frac_no_delim\space - \math_frac_no_delim\space - \fi - \dimexpr\mathfractionparameter\c!rulethickness\relax - \relax} - -% Having a \withmarginornot{#1}{#2} makes not much sense nor do 4 tests or 4 redundant -% kerns (longer node lists plus possible interference). A split in normal and margin -% also makes testing easier. When left and right margins are needed we might merge the -% variants again. After all, these are not real installers. - -% the denominator is in cramped! - -\setvalue{\??mathfractionalternative\v!inner}% - {\ifcase\d_math_fraction_margin - \expandafter\math_fraction_inner_normal - \else - \expandafter\math_fraction_inner_margin - \fi} - -\setvalue{\??mathfractionalternative\v!outer}% - {\ifcase\d_math_fraction_margin - \expandafter\math_fraction_outer_normal - \else - \expandafter\math_fraction_outer_margin - \fi} - -\setvalue{\??mathfractionalternative\v!both}% - {\ifcase\d_math_fraction_margin - \expandafter\math_fraction_both_normal - \else - \expandafter\math_fraction_both_margin - \fi} - -% todo: store first state and reuse second time - -% \def\math_fraction_inner_normal#1#2% -% {\Ustack{% -% {% -% {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}% -% \math_frac_command -% {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}% -% }% -% }% -% \math_frac_wrapup} -% -% \def\math_fraction_outer_normal#1#2% -% {\Ustack{% -% \usemathstyleparameter\mathfractionparameter -% {% -% {\m_fractions_strut_top#1}% -% \math_frac_command -% {\m_fractions_strut_bot#2}% -% }% -% }% -% \math_frac_wrapup} -% -% \def\math_fraction_both_normal#1#2% -% {\Ustack{% -% \usemathstyleparameter\mathfractionparameter -% {% -% {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}% -% \math_frac_command -% {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}% -% }% -% }% -% \math_frac_wrapup} -% -% \def\math_fraction_inner_margin#1#2% -% {\Ustack{% -% {% -% {\kern\d_math_fraction_margin -% \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}% -% \kern\d_math_fraction_margin}% -% \math_frac_command -% {\kern\d_math_fraction_margin -% \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}% -% \kern\d_math_fraction_margin}% -% }% -% }% -% \math_frac_wrapup} -% -% \def\math_fraction_outer_margin#1#2% -% {\Ustack{% -% \usemathstyleparameter\mathfractionparameter -% {% -% {\kern\d_math_fraction_margin -% \m_fractions_strut_top#1% -% \kern\d_math_fraction_margin}% -% \math_frac_command -% {\kern\d_math_fraction_margin -% \m_fractions_strut_bot#2% -% \kern\d_math_fraction_margin}% -% }% -% }% -% \math_frac_wrapup} -% -% \def\math_fraction_both_margin#1#2% -% {\Ustack{% -% \usemathstyleparameter\mathfractionparameter -% {% -% {\kern\d_math_fraction_margin -% \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1% -% \kern\d_math_fraction_margin}% -% \math_frac_command -% {\kern\d_math_fraction_margin -% \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2% -% \kern\d_math_fraction_margin}% -% }% -% }% -% \math_frac_wrapup} - -\def\math_frac_command_u - {\clf_umathfraction - {\mathfractionparameter\c!rule}% - \ifx\p_math_fraction_fences\empty - \mathfractionparameter\c!left \space - \mathfractionparameter\c!right\space - \else - \math_frac_no_delim\space - \math_frac_no_delim\space - \fi - \dimexpr\mathfractionparameter\c!rulethickness\relax - \relax} - -\def\math_fraction_inner_normal#1#2% - {\Ustack{% forces num style - \math_frac_command_u - {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}% - {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}% - }% - \math_frac_wrapup} - -\def\math_fraction_outer_normal#1#2% - {\Ustack{% forces num style - \usemathstyleparameter\mathfractionparameter - \math_frac_command_u - {\m_fractions_strut_top#1}% - {\m_fractions_strut_bot#2}% - }% - \math_frac_wrapup} - -\def\math_fraction_both_normal#1#2% - {\Ustack{% forces num style - \usemathstyleparameter\mathfractionparameter - \math_frac_command_u - {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}% - {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}% - }% - \math_frac_wrapup} - -\def\math_fraction_inner_margin#1#2% - {\Ustack{% - {% - \math_frac_command_u - {\kern\d_math_fraction_margin - \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}% - \kern\d_math_fraction_margin}% - {\kern\d_math_fraction_margin - \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}% - \kern\d_math_fraction_margin}% - }% - }% - \math_frac_wrapup} - -\def\math_fraction_outer_margin#1#2% - {\Ustack{% - \usemathstyleparameter\mathfractionparameter - {% - \math_frac_command_u - {\kern\d_math_fraction_margin - \m_fractions_strut_top#1% - \kern\d_math_fraction_margin}% - {\kern\d_math_fraction_margin - \m_fractions_strut_bot#2% - \kern\d_math_fraction_margin}% - }% - }% - \math_frac_wrapup} - -\def\math_fraction_both_margin#1#2% - {\Ustack{% - \usemathstyleparameter\mathfractionparameter - {% - \math_frac_command_u - {\kern\d_math_fraction_margin - \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1% - \kern\d_math_fraction_margin}% - {\kern\d_math_fraction_margin - \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2% - \kern\d_math_fraction_margin}% - }% - }% - \math_frac_wrapup} - -\definemathfraction[xfrac] [\c!alternative=\v!inner,\c!mathstyle=\s!script] -\definemathfraction[xxfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] - -\let\normalxfrac\xfrac - -\protected\def\xfrac#1#2{\normalxfrac{\let\xfrac\xxfrac#1}{\let\xfrac\xxfrac#2}} - -%D Spacing (sensitive for definition of \triggermathstyle: - -% \ifcase\contextlmtxmode - -\permanent\protected\def\nomathfractiongaps {\normalexpanded{\math_no_fraction_gaps \mathstyletrigger\mathstyle}} % maybe collect settings -\permanent\protected\def\overlaymathfractiongaps{\normalexpanded{\math_overlay_fraction_gaps\mathstyletrigger\mathstyle}} % maybe collect settings - -\protected\def\math_no_fraction_gaps#1% - {\Umathfractionnumup #1\zeropoint - \Umathfractiondenomdown#1\zeropoint} - -\protected\def\math_overlay_fraction_gaps#1% - {\Umathfractionnumup #1\zeropoint - \Umathfractionnumvgap #1\zeropoint - %Umathfractionrule #1\zeropoint - \Umathfractiondenomvgap#1\zeropoint - \Umathfractiondenomdown#1\zeropoint} - -% \else - -% \protected\def\math_no_fraction_gaps -% {\Umathfractionnumup \mathstyle\zeropoint -% \Umathfractiondenomdown\mathstyle\zeropoint} -% -% \protected\def\math_overlay_fraction_gaps -% {\Umathfractionnumup \mathstyle\zeropoint -% \Umathfractionnumvgap \mathstyle\zeropoint -% %Umathfractionrule \mathstyle\zeropoint -% \Umathfractiondenomvgap\mathstyle\zeropoint -% \Umathfractiondenomdown\mathstyle\zeropoint} - -% \fi - -\installcorenamespace{mathfractiondistance} - -\letvalue{\??mathfractiondistance\v!none }\nomathfractiongaps -\letvalue{\??mathfractiondistance\v!no }\nomathfractiongaps -\letvalue{\??mathfractiondistance\v!overlay}\overlaymathfractiongaps - -\setupmathfractions - [\c!distance=\v!none] - -\appendtoks - \edef\p_distance{\rootmathfractionparameter\c!distance}% - \ifempty\p_distance\else - \ifcsname\??mathfractiondistance\p_distance\endcsname - \lastnamedcs - \fi - \fi -\to \everymathematics - -% theshold is new! - -\let\math_fraction_set_threshold_inline \relax -\let\math_fraction_set_threshold_display\relax - -\appendtoks - \math_fraction_set_threshold_inline - \math_fraction_set_threshold_display -\to \everymathematics - -\appendtoks - \ifempty\currentmathfraction - \edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% - \ifempty\p_threshold - \let\math_fraction_set_threshold_inline\relax - \orelse\ifx\p_threshold\v!auto - \let\math_fraction_set_threshold_inline\relax - \else - \let\math_fraction_set_threshold_inline\math_fraction_set_theshold_inline - \fi - \edef\p_threshold{\mathfractionparameter\c!displaythreshold}% - \ifempty\p_threshold - \let\math_fraction_set_threshold_display\relax - \orelse\ifx\p_threshold\v!auto - \let\math_fraction_set_threshold_display\relax - \else - \let\math_fraction_set_threshold_display\math_fraction_set_theshold_display - \fi - \fi -\to \everysetupmathfraction - -\def\math_fraction_set_theshold_inline - {\edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% - \Umathfractiondelsize\textstyle \p_threshold\dimexpr\textface\relax - \Umathfractiondelsize\scriptstyle \p_threshold\dimexpr\scriptface\relax - \Umathfractiondelsize\scriptscriptstyle\p_threshold\dimexpr\scriptscriptface\relax} - -\def\math_fraction_set_theshold_display - {\edef\p_threshold{\mathfractionparameter\c!displaythreshold}% - \Umathfractiondelsize\displaystyle \p_threshold\dimexpr\textface\relax} - -%D \macros -%D {dfrac, tfrac, frac, dbinom, tbinom, binom} -%D -%D \startbuffer -%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$ -%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$ -%D \stopbuffer -%D -%D \typebuffer -%D \getbuffer - -% $$ -% {{a}\over{b}} + -% {{a}\overwithdelims(){b}} + -% {{a}\atopwithdelims(){b}} + -% {{a}\abovewithdelims()\zeropoint{b}} + -% \left({{a}\over{b}}\right) -% $$ - -% \dorecurse {10} { % weird -% $$ {{a}\abovewithdelims()#1pt{b}} $$ -% } - -\definemathfraction[i:frac] [\c!alternative=\v!inner,\c!mathstyle=] % was script and then small but nothing needed -\definemathfraction[i:tfrac][\c!alternative=\v!inner,\c!mathstyle=\s!text] % was script (before luatex fix) -\definemathfraction[i:sfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] -\definemathfraction[i:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] - -\definemathfraction[d:frac] [\c!alternative=\v!inner,\c!mathstyle=\s!cramped] % was cramped,text -\definemathfraction[d:tfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!text}] % was cramped,script (before luatex fix) -\definemathfraction[d:sfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!scriptscript}] -\definemathfraction[d:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] - -%D \protected\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 - -\permanent\protected\def\frac {\csname\inlineordisplaymath id:frac\endcsname} -\permanent\protected\def\tfrac{\csname\inlineordisplaymath id:tfrac\endcsname} -\permanent\protected\def\sfrac{\csname\inlineordisplaymath id:sfrac\endcsname} -\permanent\protected\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}] - -\permanent\protected\def\ctxfrac{\csname\inlineordisplaymath id:frac\endcsname} -\permanent\protected\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}% - {\enforced\let\frac\amsfrac}% - {\enforced\let\frac\ctxfrac}% -\to \everysetupmathematics - -% \definemathfraction[ddfrac][\c!mathstyle=\s!display] -% \definemathfraction[ttfrac][\c!mathstyle=\s!text] -% \definemathfraction[ssfrac][\c!mathstyle=\s!script] - -% \protected\def\binom #1#2{{\Ustack {{#1}\normalabovewithdelims()\zeropoint{#2}}}} -% \protected\def\dbinom#1#2{{\displaystyle{{#1}\normalabovewithdelims()\zeropoint{#2}}}} -% \protected\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}} - -\definemathfraction - [binom] - [\c!alternative=\v!outer, - \c!rule=\v!no, - \c!left=0x28, - \c!right=0x29, - \c!mathstyle=\s!auto] - -\definemathfraction - [dbinom] - [binom] - [\c!mathstyle=\s!display] - -\definemathfraction - [tbinom] - [binom] - [\c!mathstyle=\s!text] - -%D \macros -%D {cfrac} -%D -%D \startbuffer -%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ -%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ -%D \stopbuffer -%D -%D \typebuffer -%D -%D \getbuffer -%D -%D Now we can align every combination we want: -%D -%D \startbuffer -%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ -%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ -%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$ -%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$ -%D \stopbuffer -%D -%D \typebuffer -%D -%D \getbuffer - -\permanent\protected\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. - -\protected\def\splitfrac #1#2{{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}} -\protected\def\splitdfrac#1#2{{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}} - -%D For testing: - -% \protected\def\ShowMathFractions#1#2% -% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}} - -%D More fracking (for Alan): - -\protected\def\math_frac_colored_vulgar#1#2% - {\savecolor - \colo_helpers_activate\p_math_fractions_color - {\restorecolor#1}\Uskewed/{\restorecolor#2}} - -\protected\def\math_frac_normal_vulgar#1#2% - {{#1}\Uskewed/{#2}} - -\permanent\protected\def\vfrac#1#2% - {\bgroup - \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}% - \ifempty\p_math_fractions_color - \expandafter\math_frac_normal_vulgar - \else - \expandafter\math_frac_colored_vulgar - \fi - {#1}% - {#2}% - \egroup} - -\appendtoks - \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}% - \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}% - \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle - \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle - \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle - \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle - \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle - \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle -\to \everysetupmathfraction - -\setupmathfraction - [\s!vfrac] - [\c!hfactor=.2, - \c!vfactor=.1] - -\protect \endinput - -% I have no clue what \mthfrac and \mthsqrt are supposed to do but -% I guess that it can be done with tweaking luatex's math parameters. -% Otherwise I'll write something from scratch. - -% \def\math_stylebuilders_frac#1#2#3#4#5#6#7% -% {\begingroup -% \mathsurround\zeropoint -% \setbox0\hbox{$#1 #6$}% -% \setbox2\hbox{$#1 #7$}% -% \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi -% \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}% -% \mathord{\vcenter{{\offinterlineskip -% \hbox to \dimen0{\hss\box0\hss}% -% \kern\ht4% -% \hbox to \dimen0{\hss\copy4\hss}% -% \kern\ht4% -% \hbox to \dimen0{\hss\box2\hss}}}}% -% \endgroup} -% -% \def\math_stylebuilders_sqrt#1#2#3#4#5% -% {\begingroup -% \mathsurround\zeropoint -% \setbox0\hbox{$#1 #5$}% -% \ht0\dimexpr1.05\ht0+\onepoint\relax -% \dp0\dimexpr1.05\dp0+\onepoint\relax -% \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}% -% \delimitershortfall\zeropoint -% \nulldelimiterspace\zeropoint -% \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point? -% \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}% -% \endgroup} -% -% \def\mthfrac#1#2#3#4#5{\mathchoice -% {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}% -% {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}% -% {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}% -% {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}} -% -% \def\mthsqrt#1#2#3{\mathchoice -% {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}% -% {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}% -% {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}% -% {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}} - -% \protected\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]} -% \protected\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]} - -% used for prototyping \Uskewed -% -% \protected\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 -% } -% -% \protected\def\skewedfractionb#1#2{% -% \raise -% \Umathskewedfractionvgap\textstyle -% \hbox\bgroup -% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax$% -% \egroup -% \hbox to \zeropoint\bgroup -% \hss$\textstyle/$\hss -% \egroup -% \lower -% \Umathskewedfractionvgap\textstyle -% \hbox\bgroup -% $\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax\scriptstyle#2$% -% \egroup -% } -% -% $\skewedfractiona{1}{2}$ -% $\skewedfractionb{1}{2}$ diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua index 4f7e803d0..b5c4581b7 100644 --- a/tex/context/base/mkiv/math-ini.lua +++ b/tex/context/base/mkiv/math-ini.lua @@ -231,37 +231,38 @@ local setmathcharacter = function(class,family,slot,unicode,mset,dset) 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 ]] ] +-- todo: make nice setters for this in lua + +local f_accent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] +local f_topaccent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] +local f_botaccent = formatters[ [[\defUmathbotaccent \%s{%X}{%X}{%X}]] ] +local f_over = formatters[ [[\defUdelimiterover \%s{%X}{%X}{%X}]] ] +local f_under = formatters[ [[\defUdelimiterunder\%s{%X}{%X}{%X}]] ] +local f_fence = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] +local f_delimiter = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] +local f_radical = formatters[ [[\defUradical \%s{%X}{%X}]] ] +local f_root = formatters[ [[\defUroot \%s{%X}{%X}]] ] +local f_char = formatters[ [[\defUmathchar \%s{%X}{%X}{%X}]] ] local texmathchardef = tex.mathchardef local setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing if class == classes.accent then - ctx_sprint(f_accent(name,family,slot)) + ctx_sprint(f_topaccent(name,0,family,slot)) elseif class == classes.topaccent then - ctx_sprint(f_topaccent(name,family,slot)) + ctx_sprint(f_topaccent(name,0,family,slot)) elseif class == classes.botaccent then - ctx_sprint(f_botaccent(name,family,slot)) + ctx_sprint(f_botaccent(name,0,family,slot)) elseif class == classes.over then - ctx_sprint(f_over(name,family,slot)) + ctx_sprint(f_over(name,0,family,slot)) elseif class == classes.under then - ctx_sprint(f_under(name,family,slot)) + ctx_sprint(f_under(name,0,family,slot)) elseif class == open_class or class == close_class or class == middle_class then setdelcode("global",slot,{family,slot,0,0}) ctx_sprint(f_fence(name,class,family,slot)) elseif class == classes.delimiter then setdelcode("global",slot,{family,slot,0,0}) - ctx_sprint(f_delimiter(name,family,slot)) + ctx_sprint(f_delimiter(name,0,family,slot)) elseif class == classes.radical then ctx_sprint(f_radical(name,family,slot)) elseif class == classes.root then diff --git a/tex/context/base/mkiv/math-ini.mkxl b/tex/context/base/mkiv/math-ini.mkxl deleted file mode 100644 index ad3ad4b20..000000000 --- a/tex/context/base/mkiv/math-ini.mkxl +++ /dev/null @@ -1,3032 +0,0 @@ -%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 - -% a bit tricky way to set ... no (pseudo) registers but math hash values: -% -% \normalexpanded{\Umathlimitabovevgap\displaystyle=40\dimexpr\the\Umathlimitabovevgap\displaystyle\relax} - -% 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 -% -% \protected\def\Umathshow#1% -% {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}} - -%D This module provides namespaces for math fonts, thereby permitting mixed usage of -%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}{} -\registerctxluafile{math-dim}{} -\registerctxluafile{math-act}{} -\registerctxluafile{math-ext}{} -\registerctxluafile{math-vfu}{} -\registerctxluafile{math-ttv}{} -\registerctxluafile{math-map}{optimize} -\registerctxluafile{math-ren}{} -\registerctxluafile{math-noa}{autosuffix,optimize} -\registerctxluafile{math-tag}{autosuffix} -\registerctxluafile{math-fbk}{} -\registerctxluafile{math-dir}{} -\registerctxluafile{math-spa}{} - -%D A starter: -%D -%D \startbuffer -%D \mathsurround 10pt -%D \mathsurroundskip30pt -%D x $x + \ruledhbox{$x$} + x$ x -%D \stopbuffer -%D -%D \typebuffer -%D -%D \start \blank \getbuffer \blank \stop - -\newcount\mathnestinglevel - -\appendtoks - \advance\mathnestinglevel\plusone -\to \everymathematics - -%D A few compatibility helpers: - -\permanent\def\Umathbotaccent{\Umathaccent \s!bottom } -\permanent\def\Umathtopaccent{\Umathaccent \s!top } -\permanent\def\Umathaccents {\Umathaccent \s!both } % strange highlighting - -\ifdefined\Umathcharclass \else - \permanent\def\Umathcharclass{\numexpr\cldcontext{tex.getmathcode(token.scan_int())[1]}\relax} - \permanent\def\Umathcharfam {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[2]}\relax} - \permanent\def\Umathcharslot {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[3]}\relax} -\fi - -%D The attributes that we will use (todo: pack some into one but uglier code): - -\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[mathkernpairs] [public] -\definesystemattribute[mathbidi] [public] -\definesystemattribute[mathdomain] [public] -\definesystemattribute[mathcollapsing] [public] -\definesystemattribute[mathunstack] [public] - -\definesystemattribute[displaymath] [public] - -\mathflattenmode 31 - -\ifdefined\ordlimits\else - \let\ordlimits\limits -\fi - -\appendtoks - \c_attr_mathmode\plusone -\to \everydisplay - -\appendtoks - \c_attr_mathmode \plusone - \c_attr_displaymath\plusone -\to \everybeforedisplayformula - -\defaultmathfamily \zerocount % 255 - -\permanent\protected\def\resetmathattributes{\clf_resetmathattributes} - -% handy - -\newconditional\indisplaymath - -\appendtoks - \setfalse\indisplaymath -\to \everymath - -\appendtoks - \settrue\indisplaymath -\to \everydisplay - -\permanent\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} - -\permanent\protected\def\forcedisplaymath - {\ifmmode - \displaystyle - \settrue\indisplaymath - \fi} - -\permanent\protected\def\startforceddisplaymath - {\startimath - \displaystyle - \begingroup - \settrue\indisplaymath} - -\permanent\protected\def\stopforceddisplaymath - {\endgroup - \stopimath} - -\permanent\protected\def\startpickupmath % for the moment private - {\ifconditional\indisplaymath - \startforceddisplaymath - \let\stoppickupmath\stopforceddisplaymath - \else - \startimath - \let\stoppickupmath\stopimath - \fi} - -\let\stoppickupmath\relax - -% \protected\def\rawmathcharacter#1% slow but only for tracing -% {\begingroup -% \ifmmode -% \resetmathattributes\Uchar#1% -% \else -% \startimath\resetmathattributes\Uchar#1\stopimath -% \fi -% \endgroup} - -\permanent\protected\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 - -\permanent\protected\def\startmathematics % no grouping, if ever then also an optional second - {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop} - -\installmacrostack\currentmathematics - -\protected\def\math_mathematics_start_yes[#1]% - {\push_macro_currentmathematics - \edef\currentmathematics{#1}% check for valid - \the\everyswitchmathematics} - -\protected\def\math_mathematics_start_nop - {\push_macro_currentmathematics - \let\currentmathematics\empty - \the\everyswitchmathematics} - -\permanent\protected\def\stopmathematics - {\pop_macro_currentmathematics - \the\everyswitchmathematics} - -\definemathematics[\v!default] % not needed, but nicer when nesting back to normal - -% Now we redefine \type {\mathematics} and \type {\m}: - -\pushoverloadmode - - \permanent\protected\def\mathematics{\doifelsenextoptionalcs\math_m_yes\math_m_nop} - - \aliased\let\m \mathematics % we keep the simple versions - \aliased\let\math\mathematics % we keep the simple versions - -\popoverloadmode - -\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 - \ifcondition\validassignment{#1}% - \setupcurrentmathematics[#1]% - \else - \edef\currentmathematics{#1}% check for valid - \fi - \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 - \the\everyswitchmathematics\relax - \normalstartimath - #1% - \normalstopimath - \egroup - \ifdim\ht\scratchbox>\strutht - \math_inline_openup_start_yes - \orelse\ifdim\dp\scratchbox>\strutdp - \math_inline_openup_start_yes - \else - \math_inline_openup_start_nop - \fi - \unhbox\scratchbox % \normalstartimath#1\normalstopimath - \math_inline_openup_stop - \endgroup} - -\def\math_m_yes_text_normal#1% - {\the\everyswitchmathematics\relax - \normalstartimath - #1% - \normalstopimath - \endgroup} - -\def\math_m_nop#1% - {\relax - \ifmmode - #1% - \else - \normalstartimath - #1% - \normalstopimath - \fi} - -% 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 -\newcount \defaultprerelpenalty \defaultprerelpenalty -100 -\newcount \defaultprebinoppenalty \defaultprebinoppenalty -100 - -% we need to control these otherwise: -% -% \prerelpenalty \defaultprerelpenalty -% \prebinoppenalty\defaultprebinoppenalty - -\startsetups math:spacing:default - \thickmuskip \defaultthickmuskip - \medmuskip \defaultmedmuskip - \thinmuskip \defaultthinmuskip - \relpenalty \defaultrelpenalty - \binoppenalty \defaultbinoppenalty - \prebinoppenalty\maxdimen - \prerelpenalty \maxdimen -\stopsetups - -\startsetups math:spacing:split - \thickmuskip \defaultthickmuskip - \medmuskip \defaultmedmuskip - \thinmuskip \defaultthinmuskip - \relpenalty \defaultrelpenalty - \binoppenalty \defaultbinoppenalty - \prebinoppenalty\defaultprebinoppenalty - \prerelpenalty \defaultprerelpenalty -\stopsetups - -\startsetups math:spacing:half - \thickmuskip \halfthickmuskip - \medmuskip \halfmedmuskip - \thinmuskip \halfthinmuskip - \relpenalty \defaultrelpenalty - \binoppenalty \defaultbinoppenalty - \prebinoppenalty\maxdimen - \prerelpenalty \maxdimen -\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 - \prebinoppenalty\maxdimen - \prerelpenalty \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 - \prebinoppenalty\maxdimen - \prerelpenalty \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) - -\protected\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi} -\protected\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi} -\protected\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi} -\protected\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi} - -\installcorenamespace{mathstylealternative} % might become a setuphandler - -\protected\def\math_set_font_style_alternate#1% - {\ifcsname\??mathstylealternative\fontclass:#1\endcsname - \expandafter\math_set_font_alternate\lastnamedcs - \orelse\ifcsname\??mathstylealternative#1\endcsname - \expandafter\math_set_font_alternate\lastnamedcs - \fi} - -\protected\def\setupmathrendering % the name might change - {\dodoubleargument\math_setup_rendering} - -\def\math_setup_rendering[#1][#2]% - {\ifsecondargument - \getparameters[\??mathstylealternative#1:][#2]% - \else - \getparameters[\??mathstylealternative][#1]% - \fi} - -\appendtoks - \edef\p_stylealternative{\mathematicsparameter\c!stylealternative}% - \ifempty\p_stylealternative\else - \clf_presetmathalternate\defaultmathfamily{\p_stylealternative}% - \fi -\to \everymathematics - -% 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 - -% \enabletrackers[math.alternates] -% \setupbodyfont[lucidaot] -% -% \startTEXpage -% \setupmathematics[stylealternative={reset}]$x+\mathcal A$\par -% \setupmathematics[stylealternative={reset,calligraphic}]$x+\mathcal A$\par -% \setupmathematics[stylealternative={reset,italic}]$x+\mathcal A$\par -% \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$ -% \stopTEXpage - -% no longer needed now we have enforce so the next few lines will go - -\pushoverloadmode - \enforced\let\dotlessi\dotlessi - \enforced\let\dotlessj\dotlessj -\popoverloadmode - -\permanent\protected\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file -\permanent\protected\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file -\permanent\protected\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic -\permanent\protected\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic -\permanent\protected\def\mathdotlessi {\begingroup\mathdotless i\endgroup} -\permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup} - -\aliased\let\mathaltcal\mathaltcalligraphic -\aliased\let\mathaltit \mathaltitalic - -%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero} -\aliased\let\textdotlessi \dotlessi \permanent\protected\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi} -\aliased\let\textdotlessj \dotlessj \permanent\protected\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj} - -\appendtoks - %enforced\let\slashedzero\autoslashedzero - \enforced\let\dotlessi\autodotlessi - \enforced\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\setmathfontalternative \math_set_font_alternate -\let\setmathfontstylealternate \math_set_font_style_alternate -\let\setmathfontstylealternative\math_set_font_style_alternate - -\let\mathalternate \math_set_font_alternate - -\permanent\protected\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it} -\permanent\protected\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script} -\permanent\protected\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur} -\permanent\protected\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\s!blackboard} - -\permanent\protected\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\s!tf} - -\permanent\protected\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl -\permanent\protected\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} - -\permanent\protected\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf} -\permanent\protected\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl -\permanent\protected\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} - -\let\mathdefault\mathitalic - -\appendtoks - \edef\p_default{\mathematicsparameter\c!default}% - \ifx\p_default\v!normal - \enforced\let\mathdefault\mathupright - \else - \enforced\let\mathdefault\mathitalic - \fi -\to \everysetupmathematics - -\setupmathematics - [\c!default=\v!italic] - -\aliased\let\tfmath\mathtf % maybe a grouped command -\aliased\let\slmath\mathsl -\aliased\let\itmath\mathit - -\aliased\let\bfmath\mathbf -\aliased\let\bsmath\mathbs -\aliased\let\bimath\mathbi - -\aliased\let\Bbb\mathblackboard - -\permanent\protected\def\frak {\ifmmode\expandafter\mathfraktur \fi} -\permanent\protected\def\cal {\ifmmode\expandafter\mathscript \fi} -\permanent\protected\def\bbd {\ifmmode\expandafter\mathblackboard\fi} -\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard\fi} -\permanent\protected\def\fraktur {\ifmmode\expandafter\mathfraktur \fi} -\permanent\protected\def\gothic {\ifmmode\expandafter\mathfraktur \fi} - -\permanent\protected\def\mathcal #1{{\mathscript #1}} % for AMS compatibility -\permanent\protected\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility -\permanent\protected\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility - -\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\mathtf\else\normaltf\fi} -\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\mathbf\else\normalbf\fi} -\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\mathit\else\normalit\fi} -\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\mathsl\else\normalsl\fi} -\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\mathbi\else\normalbi\fi} -\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\mathbs\else\normalbs\fi} - -\permanent\protected\def\rm{\ifmmode\mathrm\else\normalrm\fi} -\permanent\protected\def\ss{\ifmmode\mathss\else\normalss\fi} -\permanent\protected\def\tt{\ifmmode\mathtt\else\normaltt\fi} - -\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent -\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent - -% 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 - \c_attr_mathrendering\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 - -\permanent\protected\def\boldsymbol - {\mathortext\mathboldsymbol\bold} - -%D Helpers - -\permanent\def\utfmathclass #1{\clf_utfmathclass {#1}} -\permanent\def\utfmathstretch#1{\clf_utfmathstretch{#1}} -\permanent\def\utfmathcommand#1{\clf_utfmathcommand{#1}} -\permanent\def\utfmathfiller #1{\clf_utfmathfiller {#1}} - -\permanent\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}} -\permanent\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}} -\permanent\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}} - -\permanent\protected\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}} -\permanent\protected\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}} -\permanent\protected\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}} -\permanent\protected\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}} -\permanent\protected\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}} - -\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent -\aliased\let\doifutfmathaboveelse \doifelseutfmathabove -\aliased\let\doifutfmathbelowelse \doifelseutfmathbelow -\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller -\aliased\let\doifutfmathlimopelse \doifelseutfmathlimop - -%D Not used that much: - -\installcorenamespace{mathcodecommand} - -\permanent\protected\def\mathlimop#1{\mathop{#1}} %no \limits -\permanent\protected\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath} -\permanent\protected\def\mathnolop#1{\mathop{#1}\nolimits} - -\let\mathnothing\firstofoneunexpanded -\let\mathalpha \firstofoneunexpanded - -\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 - -\permanent \def\mathcodenumber #1{\the\csname math#1code\endcsname} -\permanent\protected\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname} -\permanent \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi} - -% \startlines -% $\mathopnolimits{\rm d}x$ -% $\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} - -% todo: define these commands as frozen! - -\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning - {\ifparameter#3\or - \edef\nofmathcommandarguments{#3}% make this one m_arguments - \ifx\nofmathcommandarguments\v!one - \frozen\setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}% - \orelse\ifx\nofmathcommandarguments\v!two - \frozen\setuvalue{\??mathcommand#1}##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}% - \else - \frozen\setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}% - \fi - \orelse\ifparameter#2\or - \frozen\setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}% - \else - \frozen\setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}% - \fi - \ifparameter#1\or % safeguard - \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname - \fi} - -\permanent\protected\def\mathcommand#1% - {\begincsname\??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 - -\protected\def\math_strut_htdp#1% - {\s!height\fontcharht#1\c_math_strut - \s!depth \fontchardp#1\c_math_strut} - -\protected\def\math_strut_normal - {\vrule - \s!width \zeropoint - \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}% - \relax} - -\protected\def\math_strut_visual - {\hskip-.01\emwidth - \vrule - \s!width .02\emwidth - \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}% - \relax - \hskip-.01\emwidth} - -\protected\def\showmathstruts % let's not overload \math_strut_normal - {\enforced\let\math_strut\math_strut_visual} - -\let\math_strut\math_strut_normal - -% \protected\def\mathstrut{\mathcodecommand{nothing}{\math_strut}} - -\pushoverloadmode - - \definemathcommand [mathstrut] {\math_strut} - -\popoverloadmode - -%D We could have a arg variant \unknown\ but not now. - -\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} -\permanent\protected\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}} - -%D Moved from font-ini.mkiv: -%D -%D \macros -%D {mf,mbox,enablembox,mathop} -%D -%D Todo: - -\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen - -% \let\normalmathop\mathop % already defined - -% no longer needed as we no longer switch fonts -% -% \protected\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 ? - -\permanent\protected\def\normalmbox - {\normalhbox\bgroup - \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new - \dowithnextboxcs\math_mbox_finish\normalhbox} - -\def\math_mbox_finish - {\flushnextbox - \egroup} - -\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible - {\ifmmode\normalmbox\else\normalhbox\fi} - -\permanent\protected\def\enablembox - {\toksapp\everymathematics{\math_enable_mbox}} - -\permanent\def\math_enable_mbox % brrrr - {\enforced\let\hbox\mbox} - -\permanent\protected\def\snappedmath#1% sort of \struttedbox - {\dontleavehmode - \begingroup - \setbox\scratchbox\normalhbox\bgroup - \startimath#1\stopimath - \egroup - \ht\scratchbox\strutht - \dp\scratchbox\strutdp - \box\scratchbox - \endgroup} - -\permanent\protected\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 - -\protected\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup} -\protected\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup} - -% Once this is stable we can store the number at the tex end which is -% faster. Functions getnumbers >= 1000. - -% \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=] - -\protected\def\math_mfunction_styled - {\begingroup - \usemathematicscolorparameter\c!functioncolor - \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}% - \ifempty\p_functionstyle - \expandafter\math_mfunction_styled_none - \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname - \doubleexpandafter\math_mfunction_styled_text - \else - \doubleexpandafter\math_mfunction_styled_math - \fi} - -\protected\def\math_mfunction_styled_text#1% - %{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}% - {\expandafter\mathoptext\expandafter{\lastnamedcs#1}% - \endgroup} - -\protected\def\math_mfunction_styled_math#1% - {\p_functionstyle - #1% - \endgroup} - -\protected\def\math_mfunction_styled_none#1% - {\mathupright - #1% - \endgroup} - -\permanent\protected\def\mfunction#1% - {\begingroup - \math_tags_mfunctiontxt{#1}\c_apply_function - \math_mfunction_styled{#1}% - \endgroup} - -\permanent\protected\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 - -\permanent\protected\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup} -\permanent\protected\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup} -\permanent\protected\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup} -\permanent\protected\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext - -\newconditional\c_apply_function - -\permanent\protected\def\math_tags_apply#1#2% - {\begingroup - \settrue\c_apply_function - #1% - \endgroup - \begingroup - % todo: auto () - #2% - \endgroup} - -\appendtoks - \enforced\let\math_tags_mfunctiontxt\clf_tagmfunctiontxt - \enforced\let\math_tags_mfunctionlab\clf_tagmfunctionlab - \enforced\let\math_tags_mo \math_tags_mo_indeed - \enforced\let\math_tags_mi \math_tags_mi_indeed - \enforced\let\math_tags_mn \math_tags_mn_indeed - \enforced\let\math_tags_ms \math_tags_ms_indeed -\to \everyenableelements - -\appendtoks - \enforced\let\mo \math_tags_mo - \enforced\let\mi \math_tags_mi - \enforced\let\mn \math_tags_mn - \enforced\let\ms \math_tags_ms - \enforced\let\apply\math_tags_apply -\to\everymathematics - -% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}} -% \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 -% -% \protected\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits} -% \protected\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}} -% \protected\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}} -% -% \protected\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 - -\permanent\protected\def\mscaledtext#1% - {\mathchoice - {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} - {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} - {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}} - {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}} - -\permanent\protected\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 - -\permanent\protected\def\activatemathcharacter#1% - {\appendtoks - \global\mathcode#1=\activemathcharcode - \to \activatedmathcharacters} - -\permanent\def\activatemathcharacters - {\the\activatedmathcharacters} - -% beware, not runtime, so has to happen at format generation - -\activatemathcharacter\circumflexasciicode -\activatemathcharacter\underscoreasciicode -\activatemathcharacter\ampersandasciicode - -\appendtoks - \edef\p_ampersand{\mathematicsparameter\s!ampersand}% - \ifx\p_ampersand\v!normal - \let\specialmathaligntab\normalmathaligntab - \else - \let\specialmathaligntab\mathampersand - \fi -\to \everysetupmathematics - -%D A simplified version of this code is: -%D -%D \starttyping -%D \catcode"26=12 -%D -%D \bgroup -%D \global\mathcode"26="8000 -%D -%D \catcode"26=4 -%D -%D \xdef\normalmathaligntab{&} -%D -%D \catcode"26=13 -%D -%D \global\everymath{\def&{\normalmathaligntab}} -%D \egroup -%D \stoptyping -%D -%D The following works okay: -%D -%D \starttyping -%D A & B -%D \stoptyping -%D -%D As does: -%D -%D \starttyping -%D $A \Umathchar"2"0"26 B$ -%D \stoptyping -%D -%D But the next code: -%D -%D \starttyping -%D $A \char"26 B$ -%D \stoptyping -%D -%D fails with: \type{Misplaced alignment tab character &} and here is the -%D reason. -%D -%D When we have a letter or other category a check happens for an active -%D character and when it has one then it gets expanded and fed back into the -%D scanner (sort of). -%D -%D A \type {\char} is also fed back as raw character and again when it's letter -%D of other goes through the same process. -%D -%D This means that we cannot have a definition like: -%D -%D \starttyping -%D \def\AND{\char"26\relax} -%D \stoptyping -%D -%D that can be used in math mode, which is why the cweb macros do: -%D -%D \starttyping -%D \def\AND{\def\AND{\mathchar"2026\relax}\AND} -%D \stoptyping -%D -%D Maybe we need an option to treat chars like chars. - -% \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 \glet\othercircumflextoken ^ } -{ \catcode\circumflexasciicode\superscriptcatcode \glet\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 -% -% \protected\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 - -% $\char26$ gives an error because it expands to an active character that -% then becomes an & which is then seen as an alignment character; anyway, -% even when we switch like this the different meaning only happens when -% we're in math mode which can be delayed till we're in a cell - -\bgroup - - \catcode\underscoreasciicode\activecatcode - \catcode\circumflexasciicode\activecatcode - \catcode\ampersandasciicode \activecatcode - - \glet\specialmathaligntab\normalmathaligntab - - \permanent\protected\gdef\obeymathcatcodes - {\let _\normalsubscript - \let ^\normalsuperscript - \def &\specialmathaligntab - } - - \doglobal\appendtoks - \enforced\let _\normalsubscript - \enforced\let ^\normalsuperscript - \enforced\let &\specialmathaligntab - \to \everymathematics - - % \permanent\protected\gdef\normalmathampersands - % {\let\specialmathaligntab\mathampersand} - -\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) - -% \protected\def\enableasciimode -% {\ctxlua{resolvers.macros.enablecomment()}% -% \glet\enableasciimode\relax} -% -% \protected\def\asciimode -% {\catcodetable\txtcatcodes -% \enableasciimode -% \nonknuthmode} -% -% \protected\def\startasciimode -% {\pushcatcodetable -% \catcodetable\txtcatcodes -% \enableasciimode -% \nonknuthmode} -% -% \protected\def\stopasciimode -% {\popcatcodetable -% \ifconditional\knuthmode\else\donknuthmode\fi} - -\permanent\protected\def\enableasciimode - {\clf_enableasciimode} % relaxes itself - -\permanent\protected\def\asciimode - {\catcodetable\txtcatcodes - \clf_enableasciimode} - -\permanent\protected\def\startasciimode - {\pushcatcodetable - \catcodetable\txtcatcodes - \clf_enableasciimode} - -\permanent\protected\def\stopasciimode - {\popcatcodetable} - -%D Needed for unicode: - -\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}} - -%D Memory saver: - -\def\math_basics_check_compact - {\doifelse{\mathematicsparameter\c!compact}\v!yes - \enabledirectives\disabledirectives[math.virtual.optional]} - -\appendtoks - \ifempty\currentmathematics - \math_basics_check_compact % less tracing - \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 - -% We will use proper constants when we go numbers instead of XXX. - -\newconditional\c_math_right_to_left - -\installcorenamespace{mathaligndirection} - -\setvalue{\??mathaligndirection r2l}{\settrue\c_math_right_to_left} -\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left} - -\appendtoks - \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname - \lastnamedcs - \else - \setfalse\c_math_right_to_left - \fi -\to \everyswitchmathematics - -\protected\def\math_basics_synchronize_direction - {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi} - -% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode -% kludge now (should be a property of beginmath nodes and passed to callbacks). - -\appendtoks - \math_basics_synchronize_direction -\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}% still needed ? - \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi -\to \everysetupmathematics - -\appendtoks - \c_attr_mathbidi\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 - -\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax} -\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax} -\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax} - -\let\mathgreeknormal\mathgreekupright -\let\mathgreeknone \mathgreekdefault - -\appendtoks - \c_attr_mathgreek\c_math_greek_attribute -\to \everymathematics - -\setupmathematics - [\s!sygreek=\v!normal, - \s!lcgreek=\v!italic, - \s!ucgreek=\v!normal] % was: none - -%D Math collapsing (ligatures) - -\installcorenamespace{mathcollapsing} - -\setnewconstant\c_math_collapsing_attribute\attributeunsetvalue - -\letvalue{\??mathcollapsing 1}\plusone % specials -\letvalue{\??mathcollapsing 2}\plustwo % specials + mathlist -\letvalue{\??mathcollapsing 3}\plusthree % mathlist + specials -\letvalue{\??mathcollapsing\v!none }\attributeunsetvalue -\letvalue{\??mathcollapsing\v!reset}\attributeunsetvalue - -\def\math_collapsing_initialize - {\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else - \clf_initializemathcollapsing % one time - \glet\math_collapsing_initialize\relax - \fi} - -\appendtoks - \edef\p_collapsing{\mathematicsparameter\s!collapsing}% - \c_math_collapsing_attribute - \ifcsname\??mathcollapsing\p_collapsing\endcsname\lastnamedcs\else\attributeunsetvalue\fi - \relax -\to \everyswitchmathematics % only in mathematics - -\appendtoks - \math_collapsing_initialize - \c_attr_mathcollapsing\c_math_collapsing_attribute -\to \everymathematics - -\setupmathematics - [\s!collapsing=1] % so that we at least do primes - -%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 - \glet\math_italics_initialize\relax - \fi} - -\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 - \c_attr_mathitalics\c_math_italics_attribute -\to \everymathematics - -% \setupmathematics % done later -% [\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 Math kerns (experiment) - -\installcorenamespace{mathkernpairs} - -\setnewconstant\c_math_kernpairs_attribute\attributeunsetvalue % no real need for an extra constant - -\def\math_kernpairs_initialize - {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else - \clf_initializemathkernpairs % one time - \glet\math_kernpairs_initialize\relax - \fi} - -\appendtoks - \edef\p_kernpairs{\mathematicsparameter\s!kernpairs}% - \c_math_kernpairs_attribute\ifx\p_kernpairs\v!yes\plusone\else\attributeunsetvalue\fi\relax -\to \everyswitchmathematics % only in mathematics - -\appendtoks - \math_kernpairs_initialize - \c_attr_mathkernpairs\c_math_kernpairs_attribute -\to \everymathematics - -\setupmathematics - [\s!kernpairs=\v!no] - -%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 -% -% \protected\def\enablemathpunctuation {\settrue \automathpunctuation} -% \protected\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} -% -% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next} -% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next} -% -% \setnewconstant\c_math_comma "002C -% \setnewconstant\c_math_period "002E -% \setnewconstant\c_math_special"8000 -% -% \bgroup -% -% \catcode\c_math_comma \activecatcode -% \catcode\c_math_period\activecatcode -% -% \protected\gdef\math_punctuation_initialize_indeed -% {\mathcode\c_math_comma \c_math_special -% \mathcode\c_math_period\c_math_special -% \let,\math_punctuation_comma -% \let.\math_punctuation_period -% \c_attr_mathpunctuation\plustwo} -% -% \protected\gdef\math_punctuation_initialize_yes -% {\c_attr_mathpunctuation\plustwo} -% -% \protected\gdef\math_punctuation_initialize_nop -% {\c_attr_mathpunctuation\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}} -% -% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}} -% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}} -% -% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} -% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next} -% -% \let\math_punctuation_yes_comma \math_punctuation_all_comma -% \let\math_punctuation_yes_period\math_punctuation_nop_period -% -% 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_colon "003A -\setnewconstant\c_math_semicolon"003B -\setnewconstant\c_math_special "8000 - -% todo: use \Umathclass\c_math_comma\mathpunctcode etc for temporary switching - -\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} -\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_semicolon{\Umathcode\c_math_semicolon\mathordcode \zerocount\c_math_semicolon} -\def\math_set_p_semicolon{\Umathcode\c_math_semicolon\mathpunctcode\zerocount\c_math_semicolon} - -\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} - -\protected\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup} -\protected\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup} -\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup} - -% todo: use new lookahead stuff - -\protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} -\protected\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next} -\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next} - - \let\math_punctuation_yes_comma \math_punctuation_all_comma - \let\math_punctuation_yes_period \math_punctuation_nop_period - \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon - -\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} -\def\math_punctuation_semicolon_next{\begingroup\Umathcode\c_math_semicolon\ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_semicolon;\endgroup} - -\installcorenamespace {mathautopunctuation} - -\bgroup - - \catcode\c_math_comma \activecatcode - \catcode\c_math_period \activecatcode - \catcode\c_math_semicolon\activecatcode - - \setgvalue{\??mathautopunctuation\v!no}% - {\let,\math_punctuation_nop_comma - \let.\math_punctuation_nop_period - \let;\math_punctuation_nop_semicolon} - - % 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 - \let;\math_punctuation_nop_semicolon} - - \setgvalue{\??mathautopunctuation\v!all}% - {\let,\math_punctuation_all_comma - \let.\math_punctuation_all_period - \let;\math_punctuation_nop_semicolon} - - \setgvalue{\??mathautopunctuation comma}% - {\let,\math_punctuation_yes_comma - \let.\math_punctuation_yes_period - \let;\math_punctuation_nop_semicolon} - - \setgvalue{\??mathautopunctuation\v!yes\string,semicolon}% - {\let,\math_punctuation_yes_comma - \let.\math_punctuation_yes_period - \let;\math_punctuation_yes_semicolon} - - \setgvalue{\??mathautopunctuation comma\string,semicolon}% - {\let,\math_punctuation_yes_comma - \let.\math_punctuation_yes_period - \let;\math_punctuation_yes_semicolon} - - \setgvalue{\??mathautopunctuation\v!all\string,semicolon}% - {\let,\math_punctuation_all_comma - \let.\math_punctuation_all_period - \let;\math_punctuation_all_semicolon} - -\egroup - -% \appendtoks -% \global\mathcode\c_math_comma \c_math_special -% \global\mathcode\c_math_period \c_math_special -% \global\mathcode\c_math_semicolon\c_math_special -% \to \everyjob - -% \activatemathcharacter\c_math_comma -% \activatemathcharacter\c_math_period -% \activatemathcharacter\c_math_semicolon - -\appendtoks - \mathcode\c_math_comma \c_math_special - \mathcode\c_math_period \c_math_special - \mathcode\c_math_semicolon\c_math_special - \begincsname\??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 | comma | yes,semicolon | all,semicolon - -%D The consequences of setting this are as follows: -%D -%D \def\TestA#1#2#3% -%D {\ifnum#1=0 \type{#2}\else\setupmathematics[autopunctuation={#2}]$#3$\fi} -%D \def\TestB#1#2% -%D {\NC \TestA{#1}{no} {#2} -%D \NC \TestA{#1}{yes} {#2} -%D \NC \TestA{#1}{yes,semicolon}{#2} -%D \NC \TestA{#1}{all} {#2} -%D \NC \TestA{#1}{all,semicolon}{#2} -%D \NC \NR} -%D \starttabulate[|c|c|c|c|c|] -%D \TestB{0}{} -%D \TestB{1}{(1,2)=(1, 2)} -%D \TestB{1}{(1.2)=(1. 2)} -%D \TestB{1}{(1;2)=(1; 2)} -%D \stoptabulate - -%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 - -\permanent\def\uncramped#1% - {{\ifmathstyle - \or \displaystyle \or - \or \textstyle \or - \or \scriptstyle \or - \or \scriptscriptstyle \fi - #1}} - -\permanent\def\cramped#1% - {{\ifmathstyle - \crampeddisplaystyle \or \or % 0 -> 1 - \crampedtextstyle \or \or % 2 -> 3 - \crampedscriptstyle \or \or % 4 -> 5 - \crampedscriptscriptstyle \fi % 6 -> 7 - #1}} - -\permanent\def\triggermathstyle#1{\Ustyle\numexpr#1\relax} -%permanent\def\mathstyletrigger#1{\numexpr#1\relax} -\permanent\let\mathstyletrigger \firstofoneargument - -\permanent\def\triggeredmathstyleparameter#1% to bypass the relax - {\ifcase\numexpr\normalmathstyle\relax - #1\displaystyle \or % 0 - #1\crampeddisplaystyle \or % 1 - #1\textstyle \or % 2 - #1\crampedtextstyle \or % 3 - #1\scriptstyle \or % 4 - #1\crampedscriptstyle \or % 5 - #1\scriptscriptstyle \or % 6 - #1\crampedscriptscriptstyle \else - % error - \fi} - -\permanent\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\fam} % was \zerocount - -\permanent\def\somemathstylefont#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} - -\permanent\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\fam} % was \zerocount - -\permanent\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} - -\permanent\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} - -\permanent\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} - -% \permanent\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} - -\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle) - {{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax - display\or % 0 - crampeddisplay\or % 1 - text\or % 2 - crampedtext\or % 3 - script\or % 4 - crampedscript\or % 5 - scriptscript\or % 6 - crampedscriptscript\else % 7 - unknown\fi]}}} - -\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle} - -%D Handy too: - -\permanent\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle} -\permanent\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle} -\permanent\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle} - -%D Some dimension fun: - -\let\mathexheight \exheight % also in math-ini.mkiv -\def\mathemwidth {\Umathquad\normalmathstyle} % also in math-ini.mkiv - -%D A plain inheritance: - -\permanent\def\mathpalette#1#2% - {\mathchoice - {#1\displaystyle {#2}}% - {#1\textstyle {#2}}% - {#1\scriptstyle {#2}}% - {#1\scriptscriptstyle{#2}}} - -%D \macros -%D {cramedllap, crampedrlap, crampedclap} -%D -%D In many cases, one wants to use the \tex {clap} macro in math mode while using -%D subscripts. Normally, subscripts are in cramped mode, and these macros allow you -%D to go to 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 This used to be in \type {supp-math.mkxl}: - -\permanent\protected\def\crampedllap#1{\llap{\cramped#1}} -\permanent\protected\def\crampedrlap#1{\rlap{\cramped#1}} -\permanent\protected\def\crampedclap#1{\clap{\cramped#1}} - -%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 - -% \protected\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b} -% {\normalexpanded{\hbox\bgroup -% \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} - -\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b} - {\math_style_hbox{#1}} - -\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b} - {\normalexpanded{\hbox#1\bgroup - \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup} - -\permanent\protected\def\mathstylevbox#1% - {\normalexpanded{\vbox\bgroup - \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} - -\permanent\protected\def\mathstylevcenter#1% - {\normalexpanded{\vcenter\bgroup - \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} - -\permanent\protected\def\mathstylevcenteredhbox#1% - {\normalexpanded{\vcenter\bgroup\hbox\bgroup - \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} - -\permanent\protected\def\mathstylevcenteredvbox#1% - {\normalexpanded{\vcenter\bgroup\vbox\bgroup - \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} - -\permanent\protected\def\setmathsmalltextbox#1#2#% - {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}% - \setbox#1#2\bgroup - \font_basics_switchtobodyfont\m_math_text_choice_face - \let\next} - -\permanent\protected\def\setmathtextbox#1#2#% - {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% - \setbox#1#2\bgroup - \font_basics_switchtobodyfont\m_math_text_choice_face - \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 - -\permanent\def\triggerdisplaystyle - {\ifmathstyle - \displaystyle \or - \crampeddisplaystyle \or - \displaystyle \or - \crampeddisplaystyle \or - \displaystyle \or - \crampeddisplaystyle \or - \displaystyle \or - \crampeddisplaystyle \or - \fi} - -\permanent\def\triggertextstyle - {\ifmathstyle - \textstyle \or - \crampedtextstyle \or - \textstyle \or - \crampedtextstyle \or - \textstyle \or - \crampedtextstyle \or - \textstyle \or - \crampedtextstyle \else - \fi} - -\permanent\def\triggerscriptstyle - {\ifmathstyle - \scriptstyle \or - \crampedscriptstyle \or - \scriptstyle \or - \crampedscriptstyle \or - \scriptstyle \or - \crampedscriptstyle \or - \scriptstyle \or - \crampedscriptstyle \or - \fi} - -\permanent\def\triggerscriptscriptstyle - {\ifmathstyle - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \fi} - -\permanent\def\triggeruncrampedstyle - {\ifmathstyle - \or \displaystyle \or - \or \textstyle \or - \or \scriptstyle \or - \or \scriptscriptstyle \fi} - -\permanent\def\triggercrampedstyle - {\ifmathstyle - \crampeddisplaystyle \or \or - \crampedtextstyle \or \or - \crampedscriptstyle \or \or - \crampedscriptscriptstyle \fi} - -\permanent\def\triggersmallstyle - {\ifmathstyle - \scriptstyle \or - \crampedscriptstyle \or - \scriptstyle \or - \crampedscriptstyle \or - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \scriptscriptstyle \or - \crampedscriptscriptstyle \or - \fi} - -\permanent\def\triggeruncrampedsmallstyle - {\ifmathstyle - \scriptstyle \or - \scriptstyle \or - \scriptstyle \or - \scriptstyle \or - \scriptscriptstyle \or - \scriptscriptstyle \or - \scriptscriptstyle \or - \scriptscriptstyle \or - \fi} - -\permanent\def\triggercrampedsmallstyle - {\ifmathstyle - \crampedscriptstyle \or - \crampedscriptstyle \or - \crampedscriptstyle \or - \crampedscriptstyle \or - \crampedscriptscriptstyle \or - \crampedscriptscriptstyle \or - \crampedscriptscriptstyle \or - \crampedscriptscriptstyle \or - \fi} - -\permanent\def\triggerbigstyle - {\ifmathstyle - \displaystyle \or - \crampeddisplaystyle \or - \textstyle \or - \crampedtextstyle \or - \textstyle \or - \crampedtextstyle \or - \scriptstyle \or - \crampedscriptstyle \or - \fi} - -\permanent\def\triggeruncrampedbigstyle - {\ifmathstyle - \displaystyle \or - \displaystyle \or - \textstyle \or - \textstyle \or - \textstyle \or - \textstyle \or - \scriptstyle \or - \scriptstyle \or - \fi} - -\permanent\def\triggercrampedbigstyle - {\ifmathstyle - \crampeddisplaystyle \or - \crampeddisplaystyle \or - \crampedtextstyle \or - \crampedtextstyle \or - \crampedtextstyle \or - \crampedtextstyle \or - \crampedscriptstyle \or - \crampedscriptstyle \or - \fi} - -\newcount\c_math_saved_style - -\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup - {\c_math_saved_style\mathstyle} - -\permanent\protected\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 -} - -\protected\def\math_style_set#1% - {\edef\m_math_style_asked{#1}% - \ifempty\m_math_style_asked \else - \math_style_set_indeed - \fi} - -\let\setmathstyle\math_style_set - -\permanent\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} - -\permanent\protected\def\setupmathstyle[#1]% - {\edef\m_math_style_asked{#1}% - \ifempty\m_math_style_asked \else - \math_style_set_indeed - \fi} - -\permanent\protected\def\usemathstyleparameter#1% faster local variant - {\edef\m_math_style_asked{#1\c!mathstyle}% - \ifempty\m_math_style_asked \else - \math_style_set_indeed - \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} - -\permanent\tolerant\protected\def\definemathstyle[#1]#*[#2]% - {\c_math_styles_state_style \zerocount - \c_math_styles_state_cramped\zerocount - \c_math_styles_state_size \zerocount - \rawprocesscommacommand[#2]\math_style_collect - \letcsname\??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 -% \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% -% \csname\??mathstylecache\m_math_style_asked\endcsname} - -\def\math_style_set_indeed - {\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 - \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% - \csname\??mathstylecache\m_math_style_asked\endcsname} - -\letvalue{\??mathstyle \??mathstyle }\math_style_set_mathstyle_mathstyle % still needed? -\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 - -\permanent\protected\def\startmathstyle[#1]% - {\edef\m_math_style_asked{#1}% - \ifempty\m_math_style_asked - \let\stopmathstyle\relax - \else - \bgroup - \math_style_set_indeed - \let\stopmathstyle\egroup - \fi} - -\let\stopmathstyle\relax - -\permanent\protected\def\startusemathstyleparameter#1% - {\edef\m_math_style_asked{#1\c!mathstyle}% - \ifempty\m_math_style_asked - \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#2#% -% {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% -% \hbox#2\bgroup -% \font_basics_switchtobodyfont\m_math_text_choice_face -% #1% -% \let\next} - -% \def\math_text_choice_word#1#2#% -% {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% -% \hbox#2\bgroup -% \font_basics_switchtobodyfont\m_math_text_choice_face -% #1% -% \nospacing % \normalnospaces\plusone -% \let\next} - -%D We accept a low level box specification so that one can make helpers: -%D -%D \startbuffer -%D \startformula -%D \startalign[m=2,align={middle}] -%D \NC \text to 6cm{One\hfill} \NC a = 1 \NR -%D \NC \text to 6cm{One Two\hfill} \NC b = 2 \NR -%D \NC \text to 6cm{One Two Three\hfill} \NC c = 3 \NR -%D \stopalign -%D \stopformula -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\def\math_text_choice_font#1#2#% - {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% - \hbox#2\bgroup - \bgroup - \aftergroup\hss - \aftergroup\egroup - \hss - \font_basics_switchtobodyfont\m_math_text_choice_face - #1% - \let\next} - -\def\math_text_choice_word#1#2#% - {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% - \hbox#2\bgroup - \bgroup - \aftergroup\hss - \aftergroup\egroup - \hss - \font_basics_switchtobodyfont\m_math_text_choice_face - #1% - \nospacing % \normalnospaces\plusone - \let\next} - -% \ruledhbox{$\mathtext{abc ffi}$} -% \ruledhbox{$\mathword{abc ffi}$} - -% I need to decide: -% -%mathscriptboxmode \zerocount % no kerning -%mathscriptboxmode \plusone % lists -\mathscriptboxmode \plustwo % lists and boxes -\mathscriptcharmode \plusone % lists and boxes -%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo) -\mathrulethicknessmode\plusone % adaptive - -\permanent\protected\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox} -\permanent\protected\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox} - -\permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox} -\permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox} -\permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox} -\permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox} -\permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox} -\permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox} - -\permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox} -\permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox} -\permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox} -\permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox} -\permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox} -\permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox} - -%D Safeguard against redefinitions: - -\appendtoks - \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore -\to \everymathematics - -%D Because we may overload \type {\text} in other (structuring) macros, we say: - -\appendtoks - \enforced\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 - -% this can become an option: - -\protected\def\math_display_align_hack % I don't like the global, maybe we should push and pop - {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip - \math_openup\displayopenupvalue % was \math_openup\jot - \everycr{\noalign{\math_display_align_hack_indeed}}} - -\def\math_display_align_hack_remove_skip - {\ifdim\prevdepth>-\thousandpoint - \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax - \fi - \glet\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: - -\permanent\protected\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 - -% \protected\def\mathoptext#1{\mathop{\text{#1}}} - -\permanent\protected\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}% - \ifempty\p_setups\else - \directsetup\p_setups - \fi -\to \everyswitchmathematics - -% new: - -\permanent\protected\def\smallmathsymbol#1% - {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath - \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1% - \normalstopimath}}}}} - -% this should be a primitive: - -\permanent\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax} -\permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax} - -% experimental: - -%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} - -\protected\def\math_inline_openup_normal_start - {\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax - \scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax - \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax - \begingroup - \let\math_inline_openup_stop\math_inline_openup_normal_stop} - -\protected\def\math_inline_openup_normal_stop - {\endgroup - \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax} - -\protected\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} - -\protected\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} - -\permanent\protected\def\openedupimath - {\dontleavehmode - \begingroup - \ifmmode - \expandafter\openedupimath_math - \else - \expandafter\openedupimath_text - \fi} - -\protected\def\openedupimath_math#1% - {\setbox\scratchbox\mathstylehbox{#1}% - \ifdim\ht\scratchbox>\strutht - \math_inline_openup_start_yes - \orelse\ifdim\dp\scratchbox>\strutdp - \math_inline_openup_start_yes - \else - \math_inline_openup_start_nop - \fi - #1% - \math_inline_openup_stop - \endgroup} - -\protected\def\openedupimath_text#1% - {\setbox\scratchbox\hbox{\startimath#1\stopimath}% - \ifdim\ht\scratchbox>\strutht - \math_inline_openup_start_yes - \orelse\ifdim\dp\scratchbox>\strutdp - \math_inline_openup_start_yes - \else - \math_inline_openup_start_nop - \fi - \startimath - #1% - \stopimath - \math_inline_openup_stop - \endgroup} - -% Also handy, especially for units: -% -% 0x002B=plus 0x2212=minus 0x2013=endash - -\permanent\protected\def\mathplus {+} -\permanent\protected\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi} -\permanent\protected\def\mathplusminus{±} - -%D The \type {\displaywidth} is only known inside a display formula, so we need to catch -%D it when still zero. - -\permanent\def\checkeddisplaywidth % hsize if zero - {\dimexpr - \ifzeropt\displaywidth - \hsize - \else - \displaywidth - \fi - \relax} - -\permanent\def\maximizeddisplaywidth % larger than zero but within hsize - {\dimexpr - \ifzeropt\displaywidth - \hsize - \orelse\ifdim\displaywidth>\hsize - \hsize - \else - \displaywidth - \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 - \glet\math_domain_initialize\relax - \fi} - -\appendtoks - \edef\p_domain{\mathematicsparameter\c!domain}% - \ifempty\p_domain - \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 - \c_attr_mathdomain\c_math_domain_attribute -\to \everymathematics - -\setupmathematics - [\s!italics=3] % for the moment only this one makes sense .. still experimental - -%D For special purposed we set this one: - -\installcorenamespace{mathrules} - -\permanent\protected\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone} - -\appendtoks - \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname - \lastnamedcs - \else - \zerocount - \fi - \mathrulesfam\zerocount -\to \everymathematics - -%D Maybe: - -% \starttabulate[|||c|c|] -% \BC positive \BC negative \BC text \BC math \NC \NR -% \NC \tex {f1} \tex {hairspace} \tex{,} \NC \tex {b1} \tex {neghairspace} \NC {\darkred\vl}\f1{\darkblue\vl} \NC ${\darkred\vl}\f1{\darkblue\vl}$ \NC \NR -% \NC \tex {f2} \tex {thinspace} \tex{:} \NC \tex {b2} \tex {negthinspace} \tex{!} \NC {\darkred\vl}\f2{\darkblue\vl} \NC ${\darkred\vl}\f2{\darkblue\vl}$ \NC \NR -% \NC \tex {f3} \tex {medspace} \tex{;} \NC \tex {b3} \tex {negmedspace} \NC {\darkred\vl}\f3{\darkblue\vl} \NC ${\darkred\vl}\f3{\darkblue\vl}$ \NC \NR -% \NC \tex {f4} \tex {thickspace} \NC \tex {b4} \tex {negthickspace} \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR -% \NC \tex {f5} \tex {enspace} \NC \tex {b5} \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR -% \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR -% \stoptabulate - -% \protected\def\negenspace{\kern-.5\emwidth} -% \protected\def\negemspace{\kern- \emwidth} -% -% \protected\def\math_f#1% -% {\ifcase#1\or -% \hairspace -% \or -% \thinspace -% \or -% \medspace -% \or -% \thickspace -% \or -% \enspace -% \or -% \emspace -% \fi} -% -% \protected\def\math_b#1% -% {\ifcase#1\or -% \neghairspace -% \or -% \negthinspace -% \or -% \negmedspace -% \or -% \negthickspace -% \or -% \negenspace -% \or -% \negemspace -% \fi} -% -% \appendtoks -% \let\f\math_f -% \let\b\math_b -% \to \everymathematics - -%D Experiment - -\permanent\protected\def\math_scripts_stack - {\c_attr_mathunstack\attributeunsetvalue} - -\permanent\protected\def\math_scripts_unstack - {\clf_enablescriptunstacking - \c_attr_mathunstack\plusone} - -\appendtoks - \enforced\let\stackscripts \math_scripts_stack - \enforced\let\unstackscripts\math_scripts_unstack -\to \everymathematics - -%D Expensive (tracing and inject) but a primitive (using factors) is tricky as we -%D want this frozen support. - -% \def\math_openup_parameter#1#2% -% {\ifzeropt#1\displaystyle \orelse\ifdim#1\displaystyle =\maxdimen\else\frozen#1\displaystyle #2#1\displaystyle \fi -% \ifzeropt#1\crampeddisplaystyle \orelse\ifdim#1\crampeddisplaystyle =\maxdimen\else\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi -% \ifzeropt#1\textstyle \orelse\ifdim#1\textstyle =\maxdimen\else\frozen#1\textstyle #2#1\textstyle \fi -% \ifzeropt#1\crampedtextstyle \orelse\ifdim#1\crampedtextstyle =\maxdimen\else\frozen#1\crampedtextstyle #2#1\crampedtextstyle \fi -% \ifzeropt#1\scriptstyle \orelse\ifdim#1\scriptstyle =\maxdimen\else\frozen#1\scriptstyle #2#1\scriptstyle \fi -% \ifzeropt#1\crampedscriptstyle \orelse\ifdim#1\crampedscriptstyle =\maxdimen\else\frozen#1\crampedscriptstyle #2#1\crampedscriptstyle \fi -% \ifzeropt#1\scriptscriptstyle \orelse\ifdim#1\scriptscriptstyle =\maxdimen\else\frozen#1\scriptscriptstyle #2#1\scriptscriptstyle \fi -% \ifzeropt#1\crampedscriptscriptstyle\orelse\ifdim#1\crampedscriptscriptstyle=\maxdimen\else\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi} - -% \def\mdim#1#2% -% {\ifcase\ifzeropt#1#2\plusone\orelse\ifdim#1#2=\maxdimen\plusone\else\zerocount\fi} -% -% \def\mdim -% {\afterassignment\mmdim\scratchdimen} -% -% \def\mmdim -% {\ifcase\ifzeropt\scratchdimen\plusone\orelse\ifdim\scratchdimen=\maxdimen\plusone\else\zerocount\fi} -% -% \def\math_openup_parameter#1#2% -% {\ifcondition\mdim#1\displaystyle \frozen#1\displaystyle #2\dimexpr#1\displaystyle \relax\fi -% \ifcondition\mdim#1\crampeddisplaystyle \frozen#1\crampeddisplaystyle #2\dimexpr#1\crampeddisplaystyle \relax\fi -% \ifcondition\mdim#1\textstyle \frozen#1\textstyle #2\dimexpr#1\textstyle \relax\fi -% \ifcondition\mdim#1\crampedtextstyle \frozen#1\crampedtextstyle #2\dimexpr#1\crampedtextstyle \relax\fi -% \ifcondition\mdim#1\scriptstyle \frozen#1\scriptstyle #2\dimexpr#1\scriptstyle \relax\fi -% \ifcondition\mdim#1\crampedscriptstyle \frozen#1\crampedscriptstyle #2\dimexpr#1\crampedscriptstyle \relax\fi -% \ifcondition\mdim#1\scriptscriptstyle \frozen#1\scriptscriptstyle #2\dimexpr#1\scriptscriptstyle \relax\fi -% \ifcondition\mdim#1\crampedscriptscriptstyle\frozen#1\crampedscriptscriptstyle#2\dimexpr#1\crampedscriptscriptstyle\relax\fi} - -% \ifmathparameter : 0=zero, 1=set, 2=unset (les stracing clutter this way) - -%D New stuff: -%D -%D \starttyping -%D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$ -%D \stoptyping - -\permanent\protected\def\mathopenupparameter#1#2% - {\ifmathparameter#1\displaystyle \or\frozen#1\displaystyle #2#1\displaystyle \fi - \ifmathparameter#1\crampeddisplaystyle \or\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi - \ifmathparameter#1\textstyle \or\frozen#1\textstyle #2#1\textstyle \fi - \ifmathparameter#1\crampedtextstyle \or\frozen#1\crampedtextstyle #2#1\crampedtextstyle \fi - \ifmathparameter#1\scriptstyle \or\frozen#1\scriptstyle #2#1\scriptstyle \fi - \ifmathparameter#1\crampedscriptstyle \or\frozen#1\crampedscriptstyle #2#1\crampedscriptstyle \fi - \ifmathparameter#1\scriptscriptstyle \or\frozen#1\scriptscriptstyle #2#1\scriptscriptstyle \fi - \ifmathparameter#1\crampedscriptscriptstyle\or\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi} - -%D New stuff: -%D -%D \startbuffer -%D $x\mathopen {!}+123+\mathclose {!}x$ -%D $x\tomathopen ! +123+\tomathclose ! x$ -%D $x\mathclose {!}+123+\mathopen {!}x$ -%D $x\tomathclose ! +123+\tomathopen ! x$ -%D $x ! +123+ ! x$ -%D \stopbuffer -%D -%D \typebuffer -%D -%D \startlines -%D \getbuffer -%D \stoplines - -\permanent\protected\def\tomathord {\Umathclass\zerocount} -\permanent\protected\def\tomathop {\Umathclass\plusone } % \mathinfix -\permanent\protected\def\tomathbin {\Umathclass\plustwo } -\permanent\protected\def\tomathrel {\Umathclass\plusthree} -\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix -\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix -\permanent\protected\def\tomathpunct{\Umathclass\plussix } - -%D Prescripts. These work in \CONTEXT\ because we have the super- and subscript -%D triggers enabled as active characters but when we would have -%D -%D \starttyping -%D \catcode\underscoreasciicode\subscriptcatcode -%D \catcode\circumflexasciicode\superscriptcatcode -%D \stoptyping -%D -%D we also need the next line to disable character escaping via \type {^} in -%D math mode: -%D -%D \startbuffer -%D \blank \hbox{ -%D \ruledhbox{${\tf X} ^1 _2 ^^3 __4$} -%D \ruledhbox{${\tf X} ^1 $} -%D \ruledhbox{${\tf X} _2 $} -%D \ruledhbox{${\tf X} ^^3 $} -%D \ruledhbox{${\tf X} __4$} -%D \ruledhbox{${\tf X} ^1 _2 $} -%D \ruledhbox{${\tf X} ^1 ^^3 $} -%D \ruledhbox{${\tf X} ^1 __4$} -%D \ruledhbox{${\tf X} _2 ^^3 $} -%D \ruledhbox{${\tf X} _2 __4$} -%D \ruledhbox{${\tf X} ^1 _2 ^^3 $} -%D \ruledhbox{${\tf X} ^1 _2 __4$} -%D \ruledhbox{${\tf X} _2 ^^3 $} -%D \ruledhbox{${\tf X} _2 ^^3 __4$} -%D \ruledhbox{${\tf X} ^^3 __4$} -%D } \blank -%D -%D \typebuffer \getbuffer - -\normalsupmarkmode\plusone % 2 also disable ^[^+] in text mode - -\protect \endinput - -% % not used (yet) -% -% \newtoks \everystartimath -% \newtoks \everystopimath -% -% \protected\def\startimath{\Ustartmath\the\everystartimath} -% \protected\def\stopimath {\the\everystopimath\Ustopmath} -% -% \protected\def\m% -% {\relax -% \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi} -% -% \protected\def\math_m_math#1% -% {\startimath#1\stopimath} -% -% \let\math_m_stay\firstofoneargument diff --git a/tex/context/base/mkiv/math-noa.lmt b/tex/context/base/mkiv/math-noa.lmt deleted file mode 100644 index 25e1823e2..000000000 --- a/tex/context/base/mkiv/math-noa.lmt +++ /dev/null @@ -1,2399 +0,0 @@ -if not modules then modules = { } end modules ['math-noa'] = { - version = 1.001, - optimize = true, - comment = "companion to math-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- beware: this is experimental code and there will be a more generic (attribute value --- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will --- start cleaning up as by then the bigger picture is clear and code has been used for --- years; the main handlers will get some extensions) --- --- we will also make dedicated processors (faster) --- --- beware: names will change as we wil make noads.xxx.handler i.e. xxx --- subnamespaces - --- 20D6 -> 2190 --- 20D7 -> 2192 - --- todo: most is mathchar_code so we can have simple dedicated loops - --- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types) - -local next, tonumber = next, tonumber -local utfchar, utfbyte = utf.char, utf.byte -local formatters, gmatch = string.formatters, string.gmatch -local sortedhash = table.sortedhash -local insert, remove = table.insert, table.remove -local div, round = math.div, math.round -local bor, band = bit32.bor, bit32.band - -local fonts = fonts -local nodes = nodes -local node = node -local mathematics = mathematics -local context = context - -local otf = fonts.handlers.otf -local otffeatures = fonts.constructors.features.otf -local registerotffeature = otffeatures.register - -local privateattribute = attributes.private -local registertracker = trackers.register -local registerdirective = directives.register -local logreporter = logs.reporter -local setmetatableindex = table.setmetatableindex - -local colortracers = nodes.tracers.colors - -local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end) -local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end) -local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end) -local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end) -local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end) -local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end) -local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end) -local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end) -local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end) -local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end) -local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end) -local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end) -local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end) -local trace_families = false registertracker("math.families", function(v) trace_families = v end) -local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end) -local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end) - -local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end) - -local report_processing = logreporter("mathematics","processing") -local report_remapping = logreporter("mathematics","remapping") -local report_normalizing = logreporter("mathematics","normalizing") -local report_collapsing = logreporter("mathematics","collapsing") -local report_fixing = logreporter("mathematics","fixing") -local report_patching = logreporter("mathematics","patching") -local report_goodies = logreporter("mathematics","goodies") -local report_variants = logreporter("mathematics","variants") -local report_alternates = logreporter("mathematics","alternates") -local report_italics = logreporter("mathematics","italics") -local report_kernpairs = logreporter("mathematics","kernpairs") -local report_domains = logreporter("mathematics","domains") -local report_families = logreporter("mathematics","families") -local report_fences = logreporter("mathematics","fences") -local report_unstacking = logreporter("mathematics","unstack") - -local a_mathrendering = privateattribute("mathrendering") -local a_exportstatus = privateattribute("exportstatus") - -local nuts = nodes.nuts -local nodepool = nuts.pool -local tonut = nuts.tonut -local nutstring = nuts.tostring - -local setfield = nuts.setfield -local setlink = nuts.setlink -local setlist = nuts.setlist -local setnext = nuts.setnext -local setprev = nuts.setprev -local setchar = nuts.setchar -local setfam = nuts.setfam -local setsubtype = nuts.setsubtype -local setattr = nuts.setattr -local setattrlist = nuts.setattrlist -local setwidth = nuts.setwidth -local setheight = nuts.setheight -local setdepth = nuts.setdepth - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getboth = nuts.getboth -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getfont = nuts.getfont -local getfam = nuts.getfam -local getattr = nuts.getattr -local getattrs = nuts.getattrs -local getlist = nuts.getlist -local getwidth = nuts.getwidth -local getheight = nuts.getheight -local getdepth = nuts.getdepth - -local getnucleus = nuts.getnucleus -local getsub = nuts.getsub -local getsup = nuts.getsup -local getsubpre = nuts.getsubpre -local getsuppre = nuts.getsuppre - -local setnucleus = nuts.setnucleus -local setsub = nuts.setsub -local setsup = nuts.setsup -local setsubpre = nuts.setsubpre -local setsuppre = nuts.setsuppre - -local flush_node = nuts.flush -local copy_node = nuts.copy -local slide_nodes = nuts.slide -local set_visual = nuts.setvisual - -local mlist_to_hlist = nuts.mlist_to_hlist - -local new_kern = nodepool.kern -local new_submlist = nodepool.submlist -local new_noad = nodepool.noad -local new_delimiter = nodepool.delimiter -local new_fence = nodepool.fence - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local fontcharacters = fonthashes.characters -local fontitalics = fonthashes.italics - -local variables = interfaces.variables -local texsetattribute = tex.setattribute -local texgetattribute = tex.getattribute -local getfontoffamily = tex.getfontoffamily -local unsetvalue = attributes.unsetvalue -local implement = interfaces.implement - -local v_reset = variables.reset - -local chardata = characters.data - -noads = noads or { } -- todo: only here -local noads = noads - -noads.processors = noads.processors or { } -local processors = noads.processors - -noads.handlers = noads.handlers or { } -local handlers = noads.handlers - -local tasks = nodes.tasks -local enableaction = tasks.enableaction -local setaction = tasks.setaction - -local nodecodes = nodes.nodecodes -local noadcodes = nodes.noadcodes -local fencecodes = nodes.fencecodes - -local ordnoad_code = noadcodes.ord -local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits -local oplimitsnoad_code = noadcodes.oplimits -local opnolimitsnoad_code = noadcodes.opnolimits -local binnoad_code = noadcodes.bin -local relnode_code = noadcodes.rel -local opennoad_code = noadcodes.open -local closenoad_code = noadcodes.close -local punctnoad_code = noadcodes.punct -local innernoad_code = noadcodes.inner -local undernoad_code = noadcodes.under -local overnoad_code = noadcodes.over -local vcenternoad_code = noadcodes.vcenter -local ordlimitsnoad_code = noadcodes.ordlimits or oplimitsnoad_code - -local noad_code = nodecodes.noad -- attr nucleus sub sup -local accent_code = nodecodes.accent -- attr nucleus sub sup accent -local radical_code = nodecodes.radical -- attr nucleus sub sup left degree -local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right -local subbox_code = nodecodes.subbox -- attr list -local submlist_code = nodecodes.submlist -- attr list -local mathchar_code = nodecodes.mathchar -- attr fam char -local mathtextchar_code = nodecodes.mathtextchar -- attr fam char -local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char ------ style_code = nodecodes.style -- attr style ------ parameter_code = nodecodes.parameter -- attr style -local math_choice = nodecodes.choice -- attr display text script scriptscript -local fence_code = nodecodes.fence -- attr subtype - -local leftfence_code = fencecodes.left -local middlefence_code = fencecodes.middle -local rightfence_code = fencecodes.right - --- local mathclasses = mathematics.classes --- local fenceclasses = { --- [leftfence_code] = mathclasses.open, --- [middlefence_code] = mathclasses.middle, --- [rightfence_code] = mathclasses.close, --- } - --- this initial stuff is tricky as we can have removed and new nodes with the same address --- the only way out is a free-per-page list of nodes (not bad anyway) - --- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt --- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st - -local function process(start,what,n,parent) - - if n then - n = n + 1 - else - n = 0 - end - -- - local initial = start - -- - slide_nodes(start) -- we still miss a prev in noads -- fences test code - -- - while start do - local id = getid(start) - if trace_processing then - if id == noad_code then - report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)]) - elseif id == mathchar_code then - local char = getchar(start) - local font = getfont(start) - local fam = getfam(start) - report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char) - else - report_processing("%w%S",n*2,nutstring(start)) - end - end - local proc = what[id] - if proc then - -- report_processing("start processing") - local done, newstart, newinitial = proc(start,what,n,parent) -- prev is bugged: or getprev(start) - if newinitial then - initial = newinitial -- temp hack .. we will make all return head - if newstart then - start = newstart - -- report_processing("stop processing (new start)") - else - -- report_processing("quit processing (done)") - break - end - else - if newstart then - start = newstart - -- report_processing("stop processing (new start)") - else - -- report_processing("stop processing") - end - end - elseif id == noad_code then - -- single characters are like this - local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list - noad = getsup (start) if noad then process(noad,what,n,start) end -- list - noad = getsub (start) if noad then process(noad,what,n,start) end -- list - if getsubpre then - noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list - noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list - end - elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then - break - elseif id == subbox_code or id == submlist_code then - local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !) - elseif id == fraction_code then - local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter - noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter - elseif id == math_choice then - local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list - elseif id == fence_code then - local noad = getfield(start,"delimiter") if noad then process(noad,what,n,start) end -- delimiter - elseif id == radical_code then - local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list - noad = getsup (start) if noad then process(noad,what,n,start) end -- list - noad = getsub (start) if noad then process(noad,what,n,start) end -- list - if getsubpre then - noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list - noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list - end - noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter - noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list - elseif id == accent_code then - local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list - noad = getsup (start) if noad then process(noad,what,n,start) end -- list - noad = getsub (start) if noad then process(noad,what,n,start) end -- list - if getsubpre then - noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list - noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list - end - noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list - -- elseif id == style_code then - -- -- has a next - -- elseif id == parameter_code then - -- -- has a next - -- else - -- -- glue, penalty, etc - end - start = getnext(start) - end - if not parent then - return initial -- only first level -- for now - end -end - -local function processnested(current,what,n) - local noad = nil - local id = getid(current) - if id == noad_code then - noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list - noad = getsup (current) if noad then process(noad,what,n,current) end -- list - noad = getsub (current) if noad then process(noad,what,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list - end - elseif id == subbox_code or id == submlist_code then - noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !) - elseif id == fraction_code then - noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter - noad = getfield(current,"right") if noad then process(noad,what,n,current) end -- delimiter - elseif id == math_choice then - noad = getfield(current,"display") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list - elseif id == fence_code then - noad = getfield(current,"delimiter") if noad then process(noad,what,n,current) end -- delimiter - elseif id == radical_code then - noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list - noad = getsup (current) if noad then process(noad,what,n,current) end -- list - noad = getsub (current) if noad then process(noad,what,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list - end - noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter - noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list - elseif id == accent_code then - noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list - noad = getsup (current) if noad then process(noad,what,n,current) end -- list - noad = getsub (current) if noad then process(noad,what,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list - end - noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list - noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list - end -end - -local function processstep(current,process,n,id) - local noad = nil - local id = id or getid(current) - if id == noad_code then - noad = getnucleus(current) if noad then process(noad,n,current) end -- list - noad = getsup (current) if noad then process(noad,n,current) end -- list - noad = getsub (current) if noad then process(noad,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,n,current) end -- list - end - elseif id == subbox_code or id == submlist_code then - noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !) - elseif id == fraction_code then - noad = getfield(current,"num") if noad then process(noad,n,current) end -- list - noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list - noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter - noad = getfield(current,"right") if noad then process(noad,n,current) end -- delimiter - elseif id == math_choice then - noad = getfield(current,"display") if noad then process(noad,n,current) end -- list - noad = getfield(current,"text") if noad then process(noad,n,current) end -- list - noad = getfield(current,"script") if noad then process(noad,n,current) end -- list - noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list - elseif id == fence_code then - noad = getfield(current,"delimiter") if noad then process(noad,n,current) end -- delimiter - elseif id == radical_code then - noad = getnucleus(current) if noad then process(noad,n,current) end -- list - noad = getsup (current) if noad then process(noad,n,current) end -- list - noad = getsub (current) if noad then process(noad,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,n,current) end -- list - end - noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter - noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list - elseif id == accent_code then - noad = getnucleus(current) if noad then process(noad,n,current) end -- list - noad = getsup (current) if noad then process(noad,n,current) end -- list - noad = getsub (current) if noad then process(noad,n,current) end -- list - if getsubpre then - noad = getsuppre (current) if noad then process(noad,n,current) end -- list - noad = getsubpre (current) if noad then process(noad,n,current) end -- list - end - noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list - noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list - end -end - -local function processnoads(head,actions,banner) - if trace_processing then - report_processing("start %a",banner) - head = process(head,actions) - report_processing("stop %a",banner) - else - head = process(head,actions) - end - return head -end - -noads.process = processnoads -noads.processnested = processnested -noads.processouter = process - --- experiment (when not present fall back to fam 0) -- needs documentation - -local unknowns = { } -local checked = { } -- simple case -local tracked = false trackers.register("fonts.missing", function(v) tracked = v end) -local cached = setmetatableindex("table") -- complex case - -local function errorchar(font,char) - local done = unknowns[char] - if done then - unknowns[char] = done + 1 - else - unknowns[char] = 1 - end - if tracked then - -- slower as we check each font too and we always replace as math has - -- more demands than text - local fake = cached[font][char] - if fake then - return fake - else - local kind, fake = fonts.checkers.placeholder(font,char) - if not fake or kind ~= "char" then - fake = 0x3F - end - cached[font][char] = fake - return fake - end - else - -- only simple checking, report at the end so one should take - -- action anyway ... we can miss a few checks but that is ok - -- as there is at least one reported - if not checked[char] then - if trace_normalizing then - report_normalizing("character %C is not available",char) - end - checked[char] = true - end - return 0x3F - end -end - --- 0-2 regular --- 3-5 bold --- 6-8 pseudobold - --- this could best be integrated in the remapper, and if we run into problems, we --- might as well do this - -do - - local families = { } - local a_mathfamily = privateattribute("mathfamily") - local boldmap = mathematics.boldmap - - local familymap = { [0] = - "regular", - "regular", - "regular", - "bold", - "bold", - "bold", - "pseudobold", - "pseudobold", - "pseudobold", - } - - families[fraction_code] = function(pointer,what,n,parent) - local a = getattr(pointer,a_mathfamily) - if a and a >= 0 then - if a > 0 then - setattr(pointer,a_mathfamily,0) - if a > 5 then - a = a - 3 - end - end - setfam(pointer,a) - end - processnested(pointer,families,n+1) - end - - families[noad_code] = function(pointer,what,n,parent) - local a = getattr(pointer,a_mathfamily) - if a and a >= 0 then - if a > 0 then - setattr(pointer,a_mathfamily,0) - if a > 5 then - a = a - 3 - end - end - setfam(pointer,a) - end - processnested(pointer,families,n+1) - end - - families[mathchar_code] = function(pointer) - if getfam(pointer) == 0 then - local a = getattr(pointer,a_mathfamily) - if a and a > 0 then - setattr(pointer,a_mathfamily,0) - if a > 5 then - local char = getchar(pointer) - local bold = boldmap[char] - local newa = a - 3 - if not bold then - if trace_families then - report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) - end - setfam(pointer,newa) - elseif not fontcharacters[getfontoffamily(newa)][bold] then - if trace_families then - report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) - end - if newa > 3 then - setfam(pointer,newa-3) - end - else - setattr(pointer,a_exportstatus,char) - setchar(pointer,bold) - if trace_families then - report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) - end - setfam(pointer,newa) - end - else - local char = getchar(pointer) - if not fontcharacters[getfontoffamily(a)][char] then - if trace_families then - report_families("no bold replacement for %C",char) - end - else - if trace_families then - report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) - end - setfam(pointer,a) - end - end - end - end - end - families[delimiter_code] = function(pointer) - if getfield(pointer,"small_fam") == 0 then - local a = getattr(pointer,a_mathfamily) - if a and a > 0 then - setattr(pointer,a_mathfamily,0) - if a > 5 then - -- no bold delimiters in unicode - a = a - 3 - end - local char = getfield(pointer,"small_char") - local okay = fontcharacters[getfontoffamily(a)][char] - if okay then - setfield(pointer,"small_fam",a) - elseif a > 2 then - setfield(pointer,"small_fam",a-3) - end - local char = getfield(pointer,"large_char") - local okay = fontcharacters[getfontoffamily(a)][char] - if okay then - setfield(pointer,"large_fam",a) - elseif a > 2 then - setfield(pointer,"large_fam",a-3) - end - else - setfield(pointer,"small_fam",0) - setfield(pointer,"large_fam",0) - end - end - end - - -- will become: - - -- families[delimiter_code] = function(pointer) - -- if getfam(pointer) == 0 then - -- local a = getattr(pointer,a_mathfamily) - -- if a and a > 0 then - -- setattr(pointer,a_mathfamily,0) - -- if a > 5 then - -- -- no bold delimiters in unicode - -- a = a - 3 - -- end - -- local char = getchar(pointer) - -- local okay = fontcharacters[getfontoffamily(a)][char] - -- if okay then - -- setfam(pointer,a) - -- elseif a > 2 then - -- setfam(pointer,a-3) - -- end - -- else - -- setfam(pointer,0) - -- end - -- end - -- end - - families[mathtextchar_code] = families[mathchar_code] - - function handlers.families(head,style,penalties) - processnoads(head,families,"families") - return true -- not needed - end - -end - --- character remapping - -do - - local a_mathalphabet = privateattribute("mathalphabet") - local a_mathgreek = privateattribute("mathgreek") - - local relocate = { } - - local remapalphabets = mathematics.remapalphabets - local fallbackstyleattr = mathematics.fallbackstyleattr - local setnodecolor = colortracers.set - - local function report_remap(tag,id,old,new,extra) - report_remapping("remapping %s in font (%s,%s) from %C to %C%s", - tag,id,fontdata[id].properties.fontname or "",old,new,extra) - end - - local function checked(pointer) - local char = getchar(pointer) - local font = getfont(pointer) - local data = fontcharacters[font] - if not data[char] then - local specials = characters.data[char].specials - if specials and (specials[1] == "char" or specials[1] == "font") then - local newchar = specials[#specials] - if trace_remapping then - report_remap("fallback",font,char,newchar) - end - if trace_analyzing then - setnodecolor(pointer,"font:isol") - end - setattr(pointer,a_exportstatus,char) -- testcase: exponentiale - setchar(pointer,newchar) - return true - end - end - end - - -- We can optimize this if we really think that math is a bottleneck which it never - -- really is. - - relocate[mathchar_code] = function(pointer) - local g = getattr(pointer,a_mathgreek) or 0 - local a = getattr(pointer,a_mathalphabet) or 0 - -- local g, a = getattrs(pointer,a_mathgreek,a_mathalphabet) - -- if not a then a = 0 end - -- if not g then g = 0 end - local char = getchar(pointer) - local font = getfont(pointer) - local characters = fontcharacters[font] - if a > 0 or g > 0 then - if a > 0 then - -- not really critital but we could use properties - setattr(pointer,a_mathgreek,0) - end - if g > 0 then - -- not really critital but we could use properties - setattr(pointer,a_mathalphabet,0) - end - local newchar = remapalphabets(char,a,g) - if newchar then - local newchardata = characters[newchar] - if newchardata then - if trace_remapping then - report_remap("char",font,char,newchar,newchardata.commands and " (virtual)" or "") - end - if trace_analyzing then - setnodecolor(pointer,"font:isol") - end - setchar(pointer,newchar) - return true - else - local fallback = fallbackstyleattr(a) - if fallback then - local newchar = remapalphabets(char,fallback,g) - if newchar then - if characters[newchar] then - if trace_remapping then - report_remap("char",font,char,newchar," (fallback remapping used)") - end - if trace_analyzing then - setnodecolor(pointer,"font:isol") - end - setchar(pointer,newchar) - return true - elseif trace_remapping then - report_remap("char",font,char,newchar," fails (no fallback character)") - end - elseif trace_remapping then - report_remap("char",font,char,newchar," fails (no fallback remap character)") - end - elseif trace_remapping then - report_remap("char",font,char,newchar," fails (no fallback style)") - end - end - elseif trace_remapping then - local chardata = characters[char] - if chardata and chardata.commands then - report_remap("char",font,char,char," (virtual)") - end - end - end - if not characters[char] then - setchar(pointer,errorchar(font,char)) - end - if trace_analyzing then - setnodecolor(pointer,"font:medi") - end - if check_coverage then - return checked(pointer) - end - end - - relocate[mathtextchar_code] = function(pointer) - if trace_analyzing then - setnodecolor(pointer,"font:init") - end - end - - relocate[delimiter_code] = function(pointer) - if trace_analyzing then - setnodecolor(pointer,"font:fina") - end - end - - function handlers.relocate(head,style,penalties) - processnoads(head,relocate,"relocate") - return true -- not needed - end - -end - --- rendering (beware, not exported) - -do - - local render = { } - - local rendersets = mathematics.renderings.numbers or { } -- store - - render[mathchar_code] = function(pointer) - local attr = getattr(pointer,a_mathrendering) - if attr and attr > 0 then - local char = getchar(pointer) - local renderset = rendersets[attr] - if renderset then - local newchar = renderset[char] - if newchar then - local font = getfont(pointer) - local characters = fontcharacters[font] - if characters and characters[newchar] then - setchar(pointer,newchar) - setattr(pointer,a_exportstatus,char) - end - end - end - end - end - - function handlers.render(head,style,penalties) - processnoads(head,render,"render") - return true -- not needed - end - -end - --- some resize options (this works ok because the content is --- empty and no larger next will be forced) --- --- beware: we don't use \delcode but \Udelcode and as such have --- no large_fam; also, we need to check for subtype and/or --- small_fam not being 0 because \. sits in 0,0 by default --- --- todo: just replace the character by an ord noad --- and remove the right delimiter as well - -do - - local a_mathsize = privateattribute("mathsize") -- this might move into other fence code - local resize = { } - - resize[fence_code] = function(pointer) - local subtype = getsubtype(pointer) - if subtype == leftfence_code or subtype == rightfence_code then - local a = getattr(pointer,a_mathsize) - if a and a > 0 then - local method = div(a,100) - local size = a % 100 - setattr(pointer,a_mathsize,0) - local delimiter = getfield(pointer,"delimiter") - local chr = getchar(delimiter) - if chr > 0 then - local fam = getfam(delimiter) - local id = getfontoffamily(fam) - if id > 0 then - local data = fontdata[id] - local char = mathematics.big(data,chr,size,method) - local ht = getheight(pointer) - local dp = getdepth(pointer) - if ht == 1 or dp == 1 then -- 1 scaled point is a signal - local chardata = data.characters[char] - if ht == 1 then - setheight(pointer,chardata.height) - end - if dp == 1 then - setdepth(pointer,chardata.depth) - end - end - if trace_fences then - report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size) - end - setchar(delimiter,char) - end - end - end - end - end - - function handlers.resize(head,style,penalties) - processnoads(head,resize,"resize") - return true -- not needed - end - -end - --- still not perfect: - -do - - local a_autofence = privateattribute("mathautofence") - local autofences = { } - local dummyfencechar = 0x2E - - local function makefence(what,char) - local d = new_delimiter() -- todo: attr - local f = new_fence() -- todo: attr - if char then - local sym = getnucleus(char) - local chr = getchar(sym) - local fam = getfam(sym) - if chr == dummyfencechar then - chr = 0 - end - setchar(d,chr) - setfam(d,fam) - flush_node(sym) - end - setattrlist(d,char) - setattrlist(f,char) - setsubtype(f,what) - setfield(f,"delimiter",d) - setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what] - return f - end - - local function show(where,pointer) - print("") - local i = 0 - for n in nuts.traverse(pointer) do - i = i + 1 - print(i,where,nuts.tonode(n)) - end - print("") - end - - local function makelist(middle,noad,f_o,o_next,c_prev,f_c) --- report_fences( --- "middle %s, noad %s, open %s, opennext %s, closeprev %s, close %s", --- middle or "?", --- noad or "?", --- f_o or "?", --- o_next or "?", --- c_prev or "?", --- f_c or "?" --- ) - local list = new_submlist() - setsubtype(noad,innernoad_code) - setnucleus(noad,list) - setlist(list,f_o) - setlink(f_o,o_next) -- prev of list is nil - setlink(c_prev,f_c) -- next of list is nil --- show("list",f_o) - if middle and next(middle) then - local prev = f_o - local current = o_next - while current ~= f_c do - local midl = middle[current] - local next = getnext(current) - if midl then - local fence = makefence(middlefence_code,current) - setnucleus(current) - flush_node(current) - middle[current] = nil - -- replace_node - setlink(prev,fence,next) - prev = fence - else - prev = current - end - current = next - end - end - return noad - end - - -- relinking is now somewhat overdone - - local function convert_both(open,close,middle) - local o_next = getnext(open) - if o_next == close then - return close - else - local c_prev, c_next = getboth(close) - local f_o = makefence(leftfence_code,open) - local f_c = makefence(rightfence_code,close) - makelist(middle,open,f_o,o_next,c_prev,f_c) - setnucleus(close) - flush_node(close) - -- open is now a list - setlink(open,c_next) - return open - end - end - - local function convert_open(open,last,middle) -- last is really last (final case) - local f_o = makefence(leftfence_code,open) - local f_c = makefence(rightfence_code) - local o_next = getnext(open) - makelist(middle,open,f_o,o_next,last,nil) - -- open is now a list - setlink(open,l_next) - return open - end - - local function convert_close(first,close,middle) - local f_o = makefence(leftfence_code) - local f_c = makefence(rightfence_code,close) - local c_prev = getprev(close) - local f_next = getnext(first) - makelist(middle, close, f_o,f_next,c_prev,f_c) - -- close is now a list - if c_prev ~= first then - setlink(first,close) - end - return close - end - - local stacks = setmetatableindex("table") - - -- 1=open 2=close 3=middle 4=both - - local function processfences(pointer,n,parent) - local current = pointer - local last = pointer - local start = pointer - local done = false - local initial = pointer - local stack = nil - local middle = nil -- todo: use properties - while current do --- show("before",pointer) - local id = getid(current) - if id == noad_code then - local a = getattr(current,a_autofence) - if a and a > 0 then - local stack = stacks[n] - setattr(current,a_autofence,0) -- hm, better use a property - local level = #stack - if a == 1 then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"open","open") - end - insert(stack,current) - elseif a == 2 then - local open = remove(stack) - if open then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"close","both") - end - current = convert_both(open,current,middle) - elseif current == start then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"close","skip") - end - else - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"close","close") - end - current = convert_close(initial,current,middle) - if not parent then - initial = current - end - end - elseif a == 3 then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"middle","middle") - end - if middle then - middle[current] = last - else - middle = { [current] = last } - end - elseif a == 4 then - if not stack or #stack == 0 then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"both","open") - end - insert(stack,current) - else - local open = remove(stack) - if open then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"both","both") - end - current = convert_both(open,current,middle) - elseif current == start then - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"both","skip") - end - else - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,level,"both","close") - end - current = convert_close(initial,current,middle) - if not parent then - initial = current - end - end - end - end - done = true - else - processstep(current,processfences,n+1,id) - end - else - -- next at current level - processstep(current,processfences,n,id) - end --- show("after",pointer) - last = current - current = getnext(current) - end - if done then - local stack = stacks[n] - local s = #stack - if s > 0 then - for i=1,s do - local open = remove(stack) - if trace_fences then - report_fences("%2i: level %i, handling %s, action %s",n,#stack,"flush","open") - end - last = convert_open(open,last,middle) - end --- show("done",pointer) - end - end - end - - -- we can have a first changed node .. an option is to have a leading dummy node in math - -- lists like the par node as it can save a lot of mess - - local enabled = false - - implement { - name = "enableautofences", - onlyonce = true, - actions = function() - enableaction("math","noads.handlers.autofences") - enabled = true - end - } - - function handlers.autofences(head,style,penalties) - if enabled then -- tex.modes.c_math_fences_auto - -- inspect(nodes.totree(head)) - processfences(head,1) - -- inspect(nodes.totree(head)) - end - end - -end - --- normalize scripts - -do - - local unscript = { } noads.processors.unscript = unscript - local superscripts = characters.superscripts - local subscripts = characters.subscripts - local fractions = characters.fractions - local replaced = { } - - local function replace(pointer,what,n,parent) - pointer = parent -- we're following the parent list (chars trigger this) - local next = getnext(pointer) - local start_super, stop_super, start_sub, stop_sub - local mode = "unset" - while next and getid(next) == noad_code do - local nextnucleus = getnucleus(next) - if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then - local char = getchar(nextnucleus) - local s = superscripts[char] - if s then - if not start_super then - start_super = next - mode = "super" - elseif mode == "sub" then - break - end - stop_super = next - next = getnext(next) - setchar(nextnucleus,s) - replaced[char] = (replaced[char] or 0) + 1 - if trace_normalizing then - report_normalizing("superscript %C becomes %C",char,s) - end - else - local s = subscripts[char] - if s then - if not start_sub then - start_sub = next - mode = "sub" - elseif mode == "super" then - break - end - stop_sub = next - next = getnext(next) - setchar(nextnucleus,s) - replaced[char] = (replaced[char] or 0) + 1 - if trace_normalizing then - report_normalizing("subscript %C becomes %C",char,s) - end - else - break - end - end - else - break - end - end - if start_super then - if start_super == stop_super then - setsup(pointer,getnucleus(start_super)) - else - local list = new_submlist() -- todo attr - setlist(list,start_super) - setsup(pointer,list) - end - if mode == "super" then - setnext(pointer,getnext(stop_super)) - end - setnext(stop_super) - end - if start_sub then - --- if mode == "sub" then --- local sup = getsup(pointer) --- if sup and not getsub(pointer) then --- local nxt = getnext(pointer) --- local new = new_noad(pointer) --- setnucleus(new,new_submlist()) --- setlink(pointer,new,nxt) --- pointer = new --- end --- end - - if start_sub == stop_sub then - setsub(pointer,getnucleus(start_sub)) - else - local list = new_submlist() -- todo attr - setlist(list,start_sub) - setsub(pointer,list) - end - if mode == "sub" then - setnext(pointer,getnext(stop_sub)) - end - setnext(stop_sub) - end - -- we could return stop - end - - unscript[mathchar_code] = replace -- not noads as we need to recurse - - function handlers.unscript(head,style,penalties) - processnoads(head,unscript,"unscript") - return true -- not needed - end - -end - -do - - local unstack = { } noads.processors.unstack = unstack - local enabled = false - local a_unstack = privateattribute("mathunstack") - - unstack[noad_code] = function(pointer) - if getattr(pointer,a_unstack) then - local sup = getsup(pointer) - local sub = getsub(pointer) - if sup and sub then - -- if trace_unstacking then - -- report_unstacking() -- todo ... what to show ... - -- end - local nxt = getnext(pointer) - local new = new_noad(pointer) - setnucleus(new,new_submlist()) - setsub(pointer) - setsub(new,sub) - setlink(pointer,new,nxt) - end - end - end - - function handlers.unstack(head,style,penalties) - if enabled then - processnoads(head,unstack,"unstack") - return true -- not needed - end - end - - implement { - name = "enablescriptunstacking", - onlyonce = true, - actions = function() - enableaction("math","noads.handlers.unstack") - enabled = true - end - } - -end - -do - - local function collected(list) - if list and next(list) then - local n, t = 0, { } - for k, v in sortedhash(list) do - n = n + 1 - t[n] = formatters["%C"](k) - end - return formatters["% t (n=%s)"](t,n) - end - end - - statistics.register("math script replacements", function() - return collected(replaced) - end) - - statistics.register("unknown math characters", function() - return collected(unknowns) - end) - -end - --- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$) --- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$) - --- todo: set alternate for specific symbols --- todo: no need to do this when already loaded --- todo: use a fonts.hashes.mathalternates - -do - - local last = 0 - - local known = setmetatableindex(function(t,k) - local v = bor(0,2^last) - t[k] = v - last = last + 1 - return v - end) - - local defaults = { - dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, - -- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet) - } - - local function initializemathalternates(tfmdata) - local goodies = tfmdata.goodies - local autolist = defaults -- table.copy(defaults) - - local function setthem(newalternates) - local resources = tfmdata.resources -- was tfmdata.shared - local mathalternates = resources.mathalternates - local alternates, attributes, registered, presets - if mathalternates then - alternates = mathalternates.alternates - attributes = mathalternates.attributes - registered = mathalternates.registered - else - alternates, attributes, registered = { }, { }, { } - mathalternates = { - attributes = attributes, - alternates = alternates, - registered = registered, - presets = { }, - resets = { }, - hashes = setmetatableindex("table") - } - resources.mathalternates = mathalternates - end - -- - for name, data in sortedhash(newalternates) do - if alternates[name] then - -- ignore - else - local attr = known[name] - attributes[attr] = data - alternates[name] = attr - registered[#registered+1] = attr - end - end - end - - if goodies then - local done = { } - for i=1,#goodies do - -- first one counts - -- we can consider sharing the attributes ... todo (only once scan) - local mathgoodies = goodies[i].mathematics - local alternates = mathgoodies and mathgoodies.alternates - if alternates then - if trace_goodies then - report_goodies("loading alternates for font %a",tfmdata.properties.name) - end - for k, v in next, autolist do - if not alternates[k] then - alternates[k] = v - end - end - setthem(alternates) - return - end - end - end - - if trace_goodies then - report_goodies("loading default alternates for font %a",tfmdata.properties.name) - end - setthem(autolist) - - end - - registerotffeature { - name = "mathalternates", - description = "additional math alternative shapes", - initializers = { - base = initializemathalternates, - node = initializemathalternates, - } - } - - -- local getalternate = otf.getalternate (runtime new method so ...) - - -- todo: not shared but copies ... one never knows - - local a_mathalternate = privateattribute("mathalternate") - local alternate = { } -- processors.alternate = alternate - local fontdata = fonts.hashes.identifiers - local fontresources = fonts.hashes.resources - - local function getalternate(fam,tag,current) - local resources = fontresources[getfontoffamily(fam)] - local attribute = unsetvalue - if resources then - local mathalternates = resources.mathalternates - if mathalternates then - local presets = mathalternates.presets - if presets then - local resets = mathalternates.resets - attribute = presets[tag] - if not attribute then - attribute = 0 - local alternates = mathalternates.alternates - for s in gmatch(tag,"[^, ]+") do - if s == v_reset then - resets[tag] = true - current = unsetvalue - else - local a = alternates[s] -- or known[s] - if a then - attribute = bor(attribute,a) - end - end - end - if attribute == 0 then - attribute = unsetvalue - end - presets[tag] = attribute - elseif resets[tag] then - current = unsetvalue - end - end - end - end - if attribute > 0 and current and current > 0 then - return bor(current,attribute) - else - return attribute - end - end - - local function presetalternate(fam,tag) - texsetattribute(a_mathalternate,getalternate(fam,tag)) - end - - implement { - name = "presetmathalternate", - actions = presetalternate, - arguments = { "integer", "string" } - } - - local function setalternate(fam,tag) - local a = texgetattribute(a_mathalternate) - local v = getalternate(fam,tag,a) - texsetattribute(a_mathalternate,v) - end - - implement { - name = "setmathalternate", - actions = setalternate, - arguments = { "integer", "string" } - } - - alternate[mathchar_code] = function(pointer) -- slow - local a = getattr(pointer,a_mathalternate) - if a and a > 0 then - setattr(pointer,a_mathalternate,0) - local fontid = getfont(pointer) - local resources = fontresources[fontid] - if resources then - local mathalternates = resources.mathalternates - if mathalternates then - local attributes = mathalternates.attributes - local registered = mathalternates.registered - local hashes = mathalternates.hashes - for i=1,#registered do - local r = registered[i] - if band(a,r) ~= 0 then - local char = getchar(pointer) - local alt = hashes[i][char] - if alt == nil then - local what = attributes[r] - alt = otf.getalternate(fontdata[fontid],char,what.feature,what.value) or false - if alt == char then - alt = false - end - hashes[i][char] = alt - end - if alt then - if trace_alternates then - local what = attributes[r] - report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U", - tostring(what.feature),tostring(what.value),getchar(pointer),alt) - end - setchar(pointer,alt) - break - end - end - end - end - end - end - end - - function handlers.alternates(head,style,penalties) - processnoads(head,alternate,"alternate") - return true -- not needed - end - -end - --- italics: we assume that only characters matter --- --- = we check for correction first because accessing nodes is slower --- = the actual glyph is not that important (we can control it with numbers) - --- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on --- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all --- those heuristics. We want to deal with it ourselves also in the perspective of mixed math --- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and --- real ones. - --- in opentype the italic correction of a limop is added to the width and luatex does --- some juggling that we want to avoid but we need to do something here (in fact, we could --- better fix the width of the character) - -do - - local a_mathitalics = privateattribute("mathitalics") - - local italics = { } - local default_factor = 1/20 - - local setcolor = colortracers.set - local resetcolor = colortracers.reset - local italic_kern = new_kern - - local c_positive_d = "trace:dg" - local c_negative_d = "trace:dr" - - local function insert_kern(current,kern) - local sub = new_submlist() -- todo: attr - local noad = new_noad() -- todo: attr - setlist(sub,kern) - setnext(kern,noad) - setnucleus(noad,current) - return sub - end - - registertracker("math.italics.visualize", function(v) - if v then - italic_kern = function(k) - local n = new_kern(k) -- todo: attr - set_visual(n,"italic") - return n - end - else - italic_kern = new_kern - end - end) - - local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) - - local visual = chardata[char].visual - - if method == 1 then - -- check on state - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual - end - end - end - elseif method == 2 then - -- no check - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual - end - end - elseif method == 3 then - -- check on visual - if visual == "it" or visual == "bi" then - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual - end - end - end - elseif method == 4 then - -- combination of 1 and 3 - local italics = fontitalics[font] - if italics and (visual == "it" or visual == "bi") then - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual - end - end - end - end - - end - - italics[mathchar_code] = function(pointer,what,n,parent) - local method = getattr(pointer,a_mathitalics) - if method and method > 0 and method < 100 then - local char = getchar(pointer) - local font = getfont(pointer) - local correction, visual = getcorrection(method,font,char) - if correction and correction ~= 0 then - local next_noad = getnext(parent) - if not next_noad then - if n == 1 then - -- only at the outer level .. will become an option (always,endonly,none) - if trace_italics then - report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) - end - if correction > 0 then - correction = correction + 100 - else - correction = correction - 100 - end - correction = round(correction) - setattr(pointer,a_mathitalics,correction) - setattr(parent,a_mathitalics,correction) - return -- so no reset later on - end - end - end - end - setattr(pointer,a_mathitalics,unsetvalue) - end - - function handlers.italics(head,style,penalties) - processnoads(head,italics,"italics") - return true -- not needed - end - - local enable = function() - enableaction("math", "noads.handlers.italics") - if trace_italics then - report_italics("enabling math italics") - end - -- we enable math (unless already enabled elsewhere) - typesetters.italics.enablemath() - enable = false - end - - -- best do this only on math mode (less overhead) - - function mathematics.setitalics(name) - if enable then - enable() - end - texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none - end - - function mathematics.getitalics(name) - if enable then - enable() - end - context(name and name ~= v_reset and tonumber(name) or unsetvalue) - end - - function mathematics.resetitalics() - texsetattribute(a_mathitalics,unsetvalue) - end - - implement { - name = "initializemathitalics", - actions = enable, - onlyonce = true, - } - - implement { - name = "setmathitalics", - actions = mathematics.setitalics, - arguments = "string", - } - - implement { - name = "getmathitalics", - actions = mathematics.getitalics, - arguments = "string", - } - - implement { - name = "resetmathitalics", - actions = mathematics.resetitalics - } - -end - -do - - -- math kerns (experiment) in goodies: - -- - -- mathematics = { - -- kernpairs = { - -- [0x1D44E] = { - -- [0x1D44F] = 400, -- 𝑎𝑏 - -- } - -- }, - -- } - - local a_kernpairs = privateattribute("mathkernpairs") - local kernpairs = { } - - local function enable() - enableaction("math", "noads.handlers.kernpairs") - if trace_kernpairs then - report_kernpairs("enabling math kern pairs") - end - enable = false - end - - implement { - name = "initializemathkernpairs", - actions = enable, - onlyonce = true, - } - - local hash = setmetatableindex(function(t,font) - local g = fontdata[font].goodies - local m = g and g[1] and g[1].mathematics - local k = m and m.kernpairs - t[font] = k - return k - end) - - -- no correction after prime because that moved to a superscript - - kernpairs[mathchar_code] = function(pointer,what,n,parent) - if getattr(pointer,a_kernpairs) == 1 then - local font = getfont(pointer) - local list = hash[font] - if list then - local first = getchar(pointer) - local found = list[first] - if found then - local next = getnext(parent) - if next and getid(next) == noad_code then - pointer = getnucleus(next) - if pointer then - if getfont(pointer) == font then - local second = getchar(pointer) - local kern = found[second] - if kern then - kern = kern * fonts.hashes.parameters[font].hfactor - if trace_kernpairs then - report_kernpairs("adding %p kerning between %C and %C",kern,first,second) - end - setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr - end - end - end - end - end - end - end - end - - function handlers.kernpairs(head,style,penalties) - processnoads(head,kernpairs,"kernpairs") - return true -- not needed - end - -end - --- primes and such - -do - - -- is validpair stil needed? - - local a_mathcollapsing = privateattribute("mathcollapsing") - local collapse = { } - local mathlists = characters.mathlists - local validpair = { - [ordnoad_code] = true, - [opdisplaylimitsnoad_code] = true, - [oplimitsnoad_code] = true, - [opnolimitsnoad_code] = true, - [binnoad_code] = true, -- new - [relnode_code] = true, - [opennoad_code] = true, -- new - [closenoad_code] = true, -- new - [punctnoad_code] = true, -- new - [innernoad_code] = false, - [undernoad_code] = false, - [overnoad_code] = false, - [vcenternoad_code] = false, - [ordlimitsnoad_code] = true, - } - - local reported = setmetatableindex("table") - - collapse[mathchar_code] = function(pointer,what,n,parent) - - if parent and mathlists[getchar(pointer)] then - local found, last, lucleus, lsup, lsub, category - local tree = mathlists - local current = parent - while current and validpair[getsubtype(current)] do - local nucleus = getnucleus(current) -- == pointer - local sub = getsub(current) - local sup = getsup(current) - local char = getchar(nucleus) - if char then - local match = tree[char] - if match then - local method = getattr(current,a_mathcollapsing) - if method and method > 0 and method <= 3 then - local specials = match.specials - local mathlist = match.mathlist - local ligature - if method == 1 then - ligature = specials - elseif method == 2 then - ligature = specials or mathlist - else -- 3 - ligature = mathlist or specials - end - if ligature then - category = mathlist and "mathlist" or "specials" - found = ligature - last = current - lucleus = nucleus - lsup = sup - lsub = sub - end - tree = match - if sub or sup then - break - else - current = getnext(current) - end - else - break - end - else - break - end - else - break - end - end - if found and last and lucleus then - local id = getfont(lucleus) - local characters = fontcharacters[id] - local replace = characters and characters[found] - if not replace then - if not reported[id][found] then - reported[id][found] = true - report_collapsing("%s ligature %C from %s","ignoring",found,category) - end - elseif trace_collapsing then - report_collapsing("%s ligature %C from %s","creating",found,category) - end - setchar(pointer,found) - local l = getnext(last) - local c = getnext(parent) - if lsub then - setsub(parent,lsub) - setsub(last) - end - if lsup then - setsup(parent,lsup) - setsup(last) - end - while c ~= l do - local n = getnext(c) - flush_node(c) - c = n - end - setlink(parent,l) - end - end - end - - function noads.handlers.collapse(head,style,penalties) - processnoads(head,collapse,"collapse") - return true -- not needed - end - - local enable = function() - enableaction("math", "noads.handlers.collapse") - if trace_collapsing then - report_collapsing("enabling math collapsing") - end - enable = false - end - - implement { - name = "initializemathcollapsing", - actions = enable, - onlyonce = true, - } - -end - -do - -- inner under over vcenter - - local fixscripts = { } - local movesub = { - -- primes - [0x2032] = 0xFE932, - [0x2033] = 0xFE933, - [0x2034] = 0xFE934, - [0x2057] = 0xFE957, - -- reverse primes - [0x2035] = 0xFE935, - [0x2036] = 0xFE936, - [0x2037] = 0xFE937, - } - - mathematics.virtualize(movesub) - - local options_supported = tokens.defined("Unosuperscript") - - local function fixsupscript(parent,current,current_char,new_char) - if new_char ~= current_char and new_char ~= true then - setchar(current,new_char) - if trace_fixing then - report_fixing("fixing subscript, replacing superscript %U by %U",current_char,new_char) - end - else - if trace_fixing then - report_fixing("fixing subscript, superscript %U",current_char) - end - end - if options_supported then - setfield(parent,"options",0x08+0x22) - end - end - - -- local function movesubscript(parent,current_nucleus,oldchar,newchar) - -- local prev = getprev(parent) - -- if prev and getid(prev) == noad_code then - -- local psup = getsup(prev) - -- local psub = getsub(prev) - -- if not psup and not psub then - -- fixsupscript(prev,current_nucleus,oldchar,newchar) - -- local nucleus = getnucleus(parent) - -- local sub = getsub(parent) - -- setsup(prev,nucleus) - -- setsub(prev,sub) - -- local dummy = copy_node(nucleus) - -- setchar(dummy,0) - -- setnucleus(parent,dummy) - -- setsub(parent) - -- elseif not psup then - -- fixsupscript(prev,current_nucleus,oldchar,newchar) - -- local nucleus = getnucleus(parent) - -- setsup(prev,nucleus) - -- local dummy = copy_node(nucleus) - -- setchar(dummy,0) - -- setnucleus(parent,dummy) - -- end - -- end - -- end - - local function move_none_none(parent,prev,nuc,oldchar,newchar) - fixsupscript(prev,nuc,oldchar,newchar) - local sub = getsub(parent) - setsup(prev,nuc) - setsub(prev,sub) - local dummy = copy_node(nuc) - setchar(dummy,0) - setnucleus(parent,dummy) - setsub(parent) - end - - local function move_none_psub(parent,prev,nuc,oldchar,newchar) - fixsupscript(prev,nuc,oldchar,newchar) - setsup(prev,nuc) - local dummy = copy_node(nuc) - setchar(dummy,0) - setnucleus(parent,dummy) - end - - fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off - if parent then - local oldchar = getchar(pointer) - local newchar = movesub[oldchar] - if newchar then - local nuc = getnucleus(parent) - if pointer == nuc then - local sub = getsub(pointer) - local sup = getsup(pointer) - if sub then - if sup then - -- print("[char] sub sup") - else - -- print("[char] sub ---") - end - elseif sup then - -- print("[char] --- sup") - else - local prev = getprev(parent) - if prev and getid(prev) == noad_code then - local psub = getsub(prev) - local psup = getsup(prev) - if psub then - if psup then - -- print("sub sup [char] --- ---") - else - -- print("sub --- [char] --- ---") - move_none_psub(parent,prev,nuc,oldchar,newchar) - end - elseif psup then - -- print("--- sup [char] --- ---") - else - -- print("[char] --- ---") - move_none_none(parent,prev,nuc,oldchar,newchar) - end - else - -- print("no prev [char]") - end - end - else - -- print("[char]") - end - end - end - end - - function noads.handlers.fixscripts(head,style,penalties) - processnoads(head,fixscripts,"fixscripts") - return true -- not needed - end - -end - --- variants - -do - - local variants = { } - local validvariants = { -- fast check on valid - [0x2229] = 0xFE00, [0x222A] = 0xFE00, - [0x2268] = 0xFE00, [0x2269] = 0xFE00, - [0x2272] = 0xFE00, [0x2273] = 0xFE00, - [0x228A] = 0xFE00, [0x228B] = 0xFE00, - [0x2293] = 0xFE00, [0x2294] = 0xFE00, - [0x2295] = 0xFE00, - [0x2297] = 0xFE00, - [0x229C] = 0xFE00, - [0x22DA] = 0xFE00, [0x22DB] = 0xFE00, - [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00, - [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00, - [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00, - [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, - } - - variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value - local char = getchar(pointer) - local selector = validvariants[char] - if selector then - local next = getnext(parent) - if next and getid(next) == noad_code then - local nucleus = getnucleus(next) - if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then - local variant - local tfmdata = fontdata[getfont(pointer)] - local mathvariants = tfmdata.resources.variants -- and variantdata - if mathvariants then - mathvariants = mathvariants[selector] - if mathvariants then - variant = mathvariants[char] - end - end - if variant then - setchar(pointer,variant) - setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup - if trace_variants then - report_variants("variant (%U,%U) replaced by %U",char,selector,variant) - end - else - if trace_variants then - report_variants("no variant (%U,%U)",char,selector) - end - end - setprev(next,pointer) - setnext(parent,getnext(next)) - flush_node(next) - end - end - end - end - - function handlers.variants(head,style,penalties) - processnoads(head,variants,"unicode variant") - return true -- not needed - end - -end - --- for manuals - -do - - local classes = { } - local colors = { - [relnode_code] = "trace:dr", - [ordnoad_code] = "trace:db", - [binnoad_code] = "trace:dg", - [opennoad_code] = "trace:dm", - [closenoad_code] = "trace:dm", - [punctnoad_code] = "trace:dc", - -- [opdisplaylimitsnoad_code] = "", - -- [oplimitsnoad_code] = "", - -- [opnolimitsnoad_code] = "", - -- [ordlimitsnoad_code] = "", - -- [innernoad_code = "", - -- [undernoad_code] = "", - -- [overnoad_code] = "", - -- [vcenternoad_code] = "", - } - - local setcolor = colortracers.set - local resetcolor = colortracers.reset - - classes[mathchar_code] = function(pointer,what,n,parent) - local color = colors[getsubtype(parent)] - if color then - setcolor(pointer,color) - else - resetcolor(pointer) - end - end - - function handlers.classes(head,style,penalties) - processnoads(head,classes,"classes") - return true -- not needed - end - - registertracker("math.classes",function(v) - setaction("math","noads.handlers.classes",v) - end) - -end - --- experimental - -do - - -- mathematics.registerdomain { - -- name = "foo", - -- parents = { "bar" }, - -- characters = { - -- [0x123] = { char = 0x234, class = binary }, - -- }, - -- } - - local domains = { } - local categories = { } - local numbers = { } - local a_mathdomain = privateattribute("mathdomain") - mathematics.domains = categories - local permitted = { - ordinary = ordnoad_code, - binary = binnoad_code, - relation = relnode_code, - punctuation = punctnoad_code, - inner = innernoad_code, - } - - function mathematics.registerdomain(data) - local name = data.name - if not name then - return - end - local attr = #numbers + 1 - categories[name] = data - numbers[attr] = data - data.attribute = attr - -- we delay hashing - return attr - end - - local enable - - enable = function() - enableaction("math", "noads.handlers.domains") - if trace_domains then - report_domains("enabling math domains") - end - enable = false - end - - function mathematics.setdomain(name) - if enable then - enable() - end - local data = name and name ~= v_reset and categories[name] - texsetattribute(a_mathdomain,data and data.attribute or unsetvalue) - end - - function mathematics.getdomain(name) - if enable then - enable() - end - local data = name and name ~= v_reset and categories[name] - context(data and data.attribute or unsetvalue) - end - - implement { - name = "initializemathdomain", - actions = enable, - onlyonce = true, - } - - implement { - name = "setmathdomain", - arguments = "string", - actions = mathematics.setdomain, - } - - implement { - name = "getmathdomain", - arguments = "string", - actions = mathematics.getdomain, - } - - local function makehash(data) - local hash = { } - local parents = data.parents - if parents then - local function merge(name) - if name then - local c = categories[name] - if c then - local hash = c.hash - if not hash then - hash = makehash(c) - end - for k, v in next, hash do - hash[k] = v - end - end - end - end - if type(parents) == "string" then - merge(parents) - elseif type(parents) == "table" then - for i=1,#parents do - merge(parents[i]) - end - end - end - local characters = data.characters - if characters then - for k, v in next, characters do - -- local chr = n.char - local cls = v.class - if cls then - v.code = permitted[cls] - else - -- invalid class - end - hash[k] = v - end - end - data.hash = hash - return hash - end - - domains[mathchar_code] = function(pointer,what,n,parent) - local attr = getattr(pointer,a_mathdomain) - if attr then - local domain = numbers[attr] - if domain then - local hash = domain.hash - if not hash then - hash = makehash(domain) - end - local char = getchar(pointer) - local okay = hash[char] - if okay then - local chr = okay.char - local cls = okay.code - if chr and chr ~= char then - setchar(pointer,chr) - end - if cls and cls ~= getsubtype(parent) then - setsubtype(parent,cls) - end - end - end - end - end - - function handlers.domains(head,style,penalties) - processnoads(head,domains,"domains") - return true -- not needed - end - -end - --- just for me - -function handlers.showtree(head,style,penalties) - inspect(nodes.totree(tonut(head))) -end - -registertracker("math.showtree",function(v) - setaction("math","noads.handlers.showtree",v) -end) - --- also for me - -do - - local applyvisuals = nuts.applyvisuals - local visual = false - - function handlers.makeup(head) - applyvisuals(head,visual) - end - - registertracker("math.makeup",function(v) - visual = v - setaction("math","noads.handlers.makeup",v) - end) - -end - --- the normal builder - -do - - local force_penalties = false - - -- registertracker("math.penalties",function(v) - -- force_penalties = v - -- end) - - function builders.kernel.mlist_to_hlist(head,style,penalties) - return mlist_to_hlist(head,style,force_penalties or penalties) - end - - -- function builders.kernel.mlist_to_hlist(head,style,penalties) - -- local h = mlist_to_hlist(head,style,force_penalties or penalties) - -- inspect(nodes.totree(h,true,true,true)) - -- return h - -- end - - implement { - name = "setmathpenalties", - arguments = "integer", - actions = function(p) - force_penalties = p > 0 - end, - } - -end - -local actions = tasks.actions("math") -- head, style, penalties - -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming - -function processors.mlist_to_hlist(head,style,penalties) - starttiming(noads) - head = actions(head,style,penalties) - stoptiming(noads) - return head -end - -callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list") - --- tracing - -statistics.register("math processing time", function() - return statistics.elapsedseconds(noads) -end) diff --git a/tex/context/base/mkiv/math-pln.mkxl b/tex/context/base/mkiv/math-pln.mkxl deleted file mode 100644 index 2e090c224..000000000 --- a/tex/context/base/mkiv/math-pln.mkxl +++ /dev/null @@ -1,245 +0,0 @@ -%D \module -%D [ file=math-pln, -%D version=2001.11.16, -%D title=\CONTEXT\ Math Macros, -%D subtitle=Plain Helpers, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D Here we collect some Plain \TEX\ leftovers. - -\writestatus{loading}{ConTeXt Math Macros / Plain Helpers} - -\unprotect - -% we need proper unicode: - -\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to - -% might change - -\protected\def\hrulefill{\leaders\hrule\hfill} -\protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill} - -% will move - -\def\oalign#1% - {\leavevmode % plain tex uses this - \vtop - {\baselineskip\zeroskip - \lineskip.25\exheight - \ialign{\alignmark\alignmark\crcr#1\crcr}}} - -\def\ooalign % chars over each other - {\lineskiplimit-\maxdimen - \oalign} - -% needs checking - -\def\choose{\atopwithdelims()} -\def\brack {\atopwithdelims[]} -\def\brace {\atopwithdelims\{\}} - -% needs checking - -\protected\def\buildrel#1\over#2% - {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}} - -\protected\def\bmod - {\nonscript - \mskip-\medmuskip - \mkern5mu - \mfunction{mod}% - \penalty900 - \mkern5mu - \nonscript - \mskip-\medmuskip} - -\protected\def\pmod#1% - {\allowbreak - \mkern18mu - (\mfunction{mod}\mskip\medmuskip#1)} - -\protected\def\cases#1% - {\left\{% - \mskip\thinmuskip - \vcenter - {\normalbaselines - \mathsurround\zeropoint - \ialign{% - \normalstartimath\alignmark\alignmark\hfil\normalstopimath - \aligntab - \quad\alignmark\alignmark\hfil - \crcr - #1% - \crcr}}% - \right.} - -\protected\def\matrix#1% - {\emptyhbox - \mskip\thinmuskip - \vcenter - {\normalbaselines - \mathsurround\zeropoint - \ialign{% - \hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil - \aligntab - \aligntab - \quad\hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil - \crcr - \mathstrut - \crcr - \noalign{\kern-\baselineskip} - #1\crcr - \mathstrut - \crcr - \noalign{\kern-\baselineskip}}}% - \mskip\thinmuskip} - -\protected\def\pmatrix#1% - {\left(\matrix{#1}\right)} - -% \protected\def\openup -% {\afterassignment\math_openup\scratchdimen=} -% -% \def\math_openup -% {\advance\lineskip \scratchdimen -% \advance\baselineskip \scratchdimen -% \advance\lineskiplimit\scratchdimen} - -\let\math_closeup\relax - -\protected\def\math_openup - {\afterassignment\math_openup_indeed\scratchdimen} - -\def\math_openup_indeed - {\protected\edef\math_closeup - {\lineskip \the\lineskip - \baselineskip \the\baselineskip - \lineskiplimit\the\lineskiplimit - \relax}% - \advance \lineskip \scratchdimen - \advance \baselineskip \scratchdimen - \advance \lineskiplimit \scratchdimen} - -\let\openup \math_openup -\def\closeup{\math_closeup} % dynamic - -\protected\def\displaylines#1% - {\the\mathdisplayaligntweaks - \tabskip\zeroskip - \halign - {\hbox to \displaywidth{% - \normalstartimath\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle\alignmark\alignmark\hfil\normalstopimath}\crcr - #1\crcr}} - -%D This comes from plain but I gave it a \CONTEXT\ touch: - -\permanent\def\math_border_NC_indeed - {\enforced\global\def\math_border_NC{\aligntab}} - -\aliased\let\math_border_NC\math_border_NC_indeed - -\permanent\def\math_border_NR - {\enforced\global\let\math_border_NC\math_border_NC_indeed - \cr} - -\protected\def\math_border_matrix#1#2#3% adapted plain - {\begingroup - % - \setbox\scratchbox\hbox\bgroup - \mr B% - \egroup - \scratchdimenone\wd\scratchbox - % - \scratchdimentwo.2\bodyfontsize - % - \mathsurround\zeropoint - % - \enforced\def\NC{\math_border_NC}% - \enforced\def\NR{\math_border_NR}% - % - \gdef\m_math_border_matrix - {\kern\scratchdimentwo - \glet\m_math_border_matrix\relax}% - % - \setbox\scratchboxone\vbox\bgroup - \everycr{\noalign\bgroup\m_math_border_matrix\egroup}% - \tabskip \zeroskip - \halign{% \ialign resets everycr - \startimath\alignmark\alignmark\stopimath - \hfil - \kern\dimexpr\scratchdimentwo+\scratchdimenone\relax - \aligntab - \thinspace - \hfil - \startimath\alignmark\alignmark\stopimath - \hfil - \aligntab - \aligntab - \quad - \hfil - \startimath\alignmark\alignmark\stopimath - \hfil - \crcr - \omit - \strut - \hfil - \crcr - \noalign{\kern-\baselineskip}% - #3\crcr - \omit - \strut - \cr}% - \egroup - \setbox\scratchboxtwo\vbox\bgroup - \unvcopy\scratchboxone - \global\setbox\globalscratchbox\lastbox - \egroup - \setbox\scratchboxtwo\hbox\bgroup - \unhbox\globalscratchbox - \unskip - \global\setbox\globalscratchbox\lastbox - \egroup - \setbox\scratchboxtwo\hbox\bgroup - \startimath - \kern\dimexpr\wd\globalscratchbox-\scratchdimenone\relax - \left#1\relax - \kern-\wd\globalscratchbox - \global\setbox\globalscratchbox\vbox\bgroup - \box\globalscratchbox - \kern\scratchdimentwo - \egroup - \vcenter\bgroup - \kern-\ht\globalscratchbox - \unvbox\scratchboxone - \kern-\baselineskip - \egroup - \thinspace - \right#2\relax - \stopimath - \egroup - \null - \thickspace - \vbox\bgroup - \kern\ht\globalscratchbox - \box\scratchboxtwo - \egroup - % - \endgroup} - -\permanent\protected\def\bordermatrix {\math_border_matrix()} -\permanent\protected\def\bbordermatrix{\math_border_matrix[]} - -\permanent\protected\def\startbordermatrix #1\stopbordermatrix {\math_border_matrix(){#1}} -\permanent\protected\def\startbbordermatrix#1\stopbbordermatrix{\math_border_matrix[]{#1}} - -\permanent\let\stopbordermatrix \relax -\permanent\let\stopbbordermatrix\relax - -\protect \endinput diff --git a/tex/context/base/mkiv/math-stc.mklx b/tex/context/base/mkiv/math-stc.mklx deleted file mode 100644 index 1ee8e85a2..000000000 --- a/tex/context/base/mkiv/math-stc.mklx +++ /dev/null @@ -1,1390 +0,0 @@ -%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 -%D rather special because the order in mathml matters, so we flush in [base under -%D over] order. We also do some analysis at the \TEX\ end (passing the right -%D variant). It's easy in the export to deal with it but in the pdf stream less -%D trivial as we don't actually analyze there. -%D -%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 -%D The width of the extensible need to adapt itself automatically. -%D \stopitem -%D \startitem -%D We need to be able to control horizontal and vertical offsets. -%D \stopitem -%D \startitem -%D We best have a math as well as a text variant (which is handy for chemistry). -%D \stopitem -%D \startitem -%D For historic reasons we need to deal with optional arguments in a special -%D (reverse) way. -%D \stopitem -%D \startitem -%D We need alternatives for extensibles on top, in the middle and at the bottom. -%D \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 -%D dimensions, but fillers (like \type {\rightarrowfil} don't work with \OPENTYPE\ -%D extensibles yet because there is no way to let them stretch like leaders. At some -%D point \LUATEX\ might provide a auto||fit||to||encapsulated||box and if not I will -%D cook up a \LUA\ 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 as well. -%D A nice evening job with Joe Bonamassa performing live on the big screen (real -%D 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_fallback - {\mathstylehbox to \scratchwidth{\usemathstackerscolorparameter\c!color - \hss - \hskip\mathstackersparameter\c!topoffset\relax % for manual italic correction - \ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname - \lastnamedcs - \else - \Umathchar \fam \zerocount \scratchunicode - \fi - \hss}} - -\def\math_stackers_regular - {\mathstylehbox{\usemathstackerscolorparameter\c!color - \hskip\d_math_stackers_offset_l - \Umathaccent\fam\zerocount\scratchunicode - {\hskip\dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% - \hskip\d_math_stackers_offset_r - }} - -\def\math_stackers_stretch % we don't have that one yet - {\mathstylehbox{\usemathstackerscolorparameter\c!color - \hskip\d_math_stackers_offset_l - \Umathaccent\fam\zerocount\scratchunicode - {\hskip\dimexpr\hsize-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% - \hskip\d_math_stackers_offset_r - }} - -% 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}% - {\hpack{\vrule\s!width\scratchwidth\s!height.1\mathexheight\s!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!mstackermid\empty\hbox\bgroup}% - \def\math_stackers_start_tagged_top{\dostarttagged\t!mstackertop\empty\hbox\bgroup}% - \def\math_stackers_start_tagged_bot{\dostarttagged\t!mstackerbot\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!voffset=.25\mathexheight, - \c!hoffset=\zeropoint, - \c!topoffset=\zeropoint, % for manual italic correction - \c!distance=\mathstackersparameter\c!voffset, % distance between symbol and base (can be different from voffset) - \c!minheight=\mathexheight, - \c!mindepth=\zeropoint, - \c!minwidth=.5\mathemwidth, - \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 - -\setupmathstackers - [\c!mp=math:stacker:\number\scratchunicode, - \c!mpheight=\mathcharht\scratchunicode, - \c!mpdepth=\mathchardp\scratchunicode, - \c!mpoffset=.25\mathexheight] - -\setvalue{\??mathstackersalternative\v!mp}% - {\normalexpanded{\math_stackers_mp_box - {\the\dimexpr\mathstackersparameter\c!mpheight}% - {\the\dimexpr\mathstackersparameter\c!mpdepth}% - {\the\dimexpr\mathstackersparameter\c!mpoffset}% - {\the\dimexpr\triggeredmathstyleparameter\Umathfractionrule}% - {\the\dimexpr\triggeredmathstyleparameter\Umathaxis}% - {\the\mathexheight}% - {\the\mathemwidth}% - }} - -\protected\def\math_stackers_mp_box#1#2#3#4#5#6#7% - {\hpack\bgroup % todo: add code key + tag - % we can speed up \mathexheight expansion a bit - \d_overlay_width \scratchwidth - \d_overlay_height #1\relax - \d_overlay_depth #2\relax - \d_overlay_offset #3\relax - \d_overlay_linewidth#4\relax - \edef\overlaylinecolor{\mathstackersparameter\c!color}% - \edef\p_mp{\mathstackersparameter\c!mp}% - \uniqueMPgraphic{\p_mp}{axis=#5,ex=#6,em=#7}% - \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 - \orelse\ifx\p_offset\v!min - % heads/tails - hoffset - \advance\scratchleftoffset -\scratchhoffset - \advance\scratchrightoffset-\scratchhoffset - \else % \v!normal - % hoffset - \scratchleftoffset\zeropoint - \scratchrightoffset\zeropoint - \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} - -\protected\def\math_stackers_triplet#method#category#codepoint#toptext#bottomtext% - %{\math_stackers_start_group{#category}% - {\begingroup - \edef\currentmathstackers{#category}% - \mathstackersparameter\c!left\relax - \dostarttagged\t!mstacker\currentmathstackers - \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi - {\edef\p_offset {\mathstackersparameter\c!offset}% - \edef\p_location {\mathstackersparameter\c!location}% - \edef\p_strut {\mathstackersparameter\c!strut}% - \edef\p_alternative{\mathstackersparameter\c!alternative}% - % \ifx\p_order\v!reverse - % \ifsecondargument - % \edef\m_math_stackers_text_top {#bottomtext}% - % \edef\m_math_stackers_text_bottom{#toptext}% - % \else - % \edef\m_math_stackers_text_top {#toptext}% - % \let\m_math_stackers_text_bottom \empty - % \fi - % \else - % \edef\m_math_stackers_text_top {#toptext}% - % \edef\m_math_stackers_text_bottom{#bottomtext}% - % \fi - \edef\m_math_stackers_text_top {#toptext}% - \edef\m_math_stackers_text_bottom{#bottomtext}% - \ifparameter#bottomtext\or - \edef\p_order{\mathstackersparameter\c!order}% - \ifx\p_order\v!reverse - \swapmacros\m_math_stackers_text_top\m_math_stackers_text_bottom - \fi - \fi - \scratchleftoffset \zeropoint - \scratchrightoffset\zeropoint - \ifcase#method\relax - \math_stackers_check_unicode{#codepoint}% - \else - \edef\m_math_stackers_text_middle{#codepoint}% - \fi - \ifempty\m_math_stackers_text_top - \setbox\scratchboxone\emptyhbox - \else - \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}% - \fi - \ifempty\m_math_stackers_text_bottom - \setbox\scratchboxtwo\emptyhbox - \else - \setmathsmalltextbox\scratchboxtwo\hbox{\math_stackers_bottomtext}% - \fi - % - \ifcase#method\relax - % e.g. extensible - %\scratchwidth\wd - % \ifdim\wd\scratchboxone>\wd\scratchboxtwo - % \scratchboxone - % \else - % \scratchboxtwo - % \fi - %\relax - \scratchwidth\mathcharwd\scratchunicode - \ifdim\wd\scratchboxone>\scratchwidth - \scratchwidth\wd\scratchboxone - \orelse\ifdim\wd\scratchboxtwo>\scratchwidth - \scratchwidth\wd\scratchboxtwo - \fi - \else - \ifempty\m_math_stackers_text_middle - \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 - \orelse\ifdim\wd\scratchboxtwo>\wd\scratchboxthree - \scratchboxtwo - \else - \scratchboxthree - \fi - \relax - \fi - % - \scratchdimen\mathstackersparameter\c!minwidth\relax - \ifdim\scratchwidth<\scratchdimen - \scratchwidth\scratchdimen - \fi - \advance\scratchwidth2\scratchhoffset - % - \ifcase#method\relax - \dostarttagged\t!mstackermid\empty - \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname - \dostoptagged - \fi - % - \ifdim\wd\scratchboxone<\scratchwidth - \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work - \fi - \ifdim\wd\scratchboxtwo<\scratchwidth - \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}% - \fi - \ifdim\wd\scratchboxthree<\scratchwidth - \setbox\scratchboxthree\hpack 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\hpack{\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_stop_group} - -\permanent\tolerant\protected\def\definemathextensible[#1]#*[#2]#*[#3]% category name unicode - {\ifarguments\or\or - \frozen\setuevalue{#1}{\math_stackers_auto_normal\noexpand\currentmathstackers{\number#2}}% - \or - \frozen\setuevalue{#2}{\math_stackers_auto_normal{#1}{\number#3}}% - \fi} - -\tolerant\protected\def\math_stackers_auto_normal#1#2#*[#3]#:#=#*#=% - {\begingroup - \scratchcounter#2\relax - \edef\currentmathstackers{\ifparameter#3\or#3\else#1\fi}% - \math_stackers_triplet\zerocount\currentmathstackers\scratchcounter{#4}{#5}% - \endgroup} - -%D A few direct accessors (in the meantime we redefined \mathextensible so we renamed the -%D following): - -\permanent\tolerant\protected\def\directmathextensible[#category]% - {\begingroup - \math_stackers_handle_extensible{\ifparameter#category\or#category\else\v!mathematics\fi}} % will be defined later on - -\permanent\tolerant\protected\def\directtextextensible[#category]% - {\begingroup - \math_stackers_handle_extensible{\ifparameter#category\or#category\else\v!text\fi}} % will be defined later on - -\aliased\let\mathstacker\directmathextensible -\aliased\let\textstacker\directtextextensible - -\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 - -\protected\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\ordlimits}% - \mathop\bgroup - \else - \let\math_stackers_stop_group\endgroup - \fi} - -\newconstant\c_math_stackers_top -\newconstant\c_math_stackers_bottom -\newconstant\c_math_stackers_codepoint -\newconstant\c_math_stackers_extracode -\newdimen \d_math_stackers_offset_l -\newdimen \d_math_stackers_offset_r - -\setupmathstackers[lt=\zeropoint,rt=\zeropoint,lb=\zeropoint,rb=\zeropoint] - -\tolerant\protected\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#spacer[#settings]#:#text% - {\math_stackers_start_group{#category}% - \c_math_stackers_top #top\relax - \c_math_stackers_bottom #bottom\relax - \c_math_stackers_codepoint#codepoint\relax - \c_math_stackers_extracode#codeextra\relax - \ifparameter#settings\or - \setupcurrentmathstackers[#settings]% - \fi - \mathstackersparameter\c!left\relax - \dostarttagged\t!mstacker\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\c_math_stackers_codepoint - % - \ifempty\math_stackers_middle - \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 - % - %\scratchunicode\c_math_stackers_codepoint - \ifcase\c_math_stackers_bottom - \d_math_stackers_offset_l\mathstackersparameter{lt}% - \d_math_stackers_offset_r\mathstackersparameter{rt}% - \orelse\ifcase\c_math_stackers_top - \d_math_stackers_offset_l\mathstackersparameter{lb}% - \d_math_stackers_offset_r\mathstackersparameter{rb}% - \else - \d_math_stackers_offset_l\mathstackersparameter{lt}% - \d_math_stackers_offset_r\mathstackersparameter{rt}% - \fi - \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname - \setbox\scratchboxthree\hpack to \scratchwidth{\hss\box\scratchboxthree\hss}% - % - \ifcase\c_math_stackers_extracode\else - \scratchunicode\c_math_stackers_extracode - \d_math_stackers_offset_l\mathstackersparameter{lb}% - \d_math_stackers_offset_r\mathstackersparameter{rb}% - \setbox\scratchboxone\csname\??mathstackersalternative\p_alternative\endcsname - \fi - % - \math_stackers_normalize_three - % analysis - \ifcase\c_math_stackers_bottom - \ifcase\c_math_stackers_top - \dosettagproperty\s!subtype\t!munderover - \else - \dosettagproperty\s!subtype\t!mover - \fi - \else - \ifcase\c_math_stackers_top - \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\c_math_stackers_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\c_math_stackers_top - \box\scratchboxtwo - \else - \box\scratchboxone - \fi - \egroup - \math_stackers_stop_tagged - \fi - \ifcase\c_math_stackers_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} - -\permanent\tolerant\protected\def\definemathoverextensible[#1]#*[#2]#*[#3]% - {\ifparameter#3\or - \frozen\setuevalue{#2}{\math_stackers_make_double\plusone \zerocount{#1}{\number#3}{0}}% - \else - \frozen\setuevalue{#1}{\math_stackers_make_double\plusone \zerocount\noexpand\currentmathstackers{\number#2}{0}}% - \fi} - -\permanent\tolerant\protected\def\definemathunderextensible[#1]#*[#2]#*[#3]% - {\ifparameter#3\or - \frozen\setuevalue{#2}{\math_stackers_make_double\zerocount\plusone{#1}{\number#3}{0}}% - \else - \frozen\setuevalue{#1}{\math_stackers_make_double\zerocount\plusone\noexpand\currentmathstackers{\number#2}{0}}% - \fi} - -\permanent\tolerant\protected\def\definemathdoubleextensible[#1]#*[#2]#*[#3]#*[#4]% - {\ifparameter#4\or - \frozen\setuevalue{#2}{\math_stackers_make_double\plusone \plusone{#1}{\number#3}{\number#4}}% - \else - \frozen\setuevalue{#1}{\math_stackers_make_double\plusone \plusone\noexpand\currentmathstackers{\number#2}{\number#3}}% - \fi} - -\permanent\tolerant\protected\def\definemathover[#category]#spacer[#command]#spacer[#topcode]% - {\frozen\setuvalue{#command}{\math_stackers_handle_direct\plusone\zerocount{#category}{#topcode}{0}}} - -\permanent\tolerant\protected\def\definemathunder[#category]#spacer[#command]#spacer[#bottomcode]% - {\frozen\setuvalue{#command}{\math_stackers_handle_direct\zerocount\plusone{#category}{#bottomcode}{0}}} - -\permanent\tolerant\protected\def\definemathdouble[#category]#spacer[#command]#spacer[#topcode]#spacer[#bottomcode]% - {\frozen\setuvalue{#command}{\math_stackers_handle_direct\plusone\plusone{#category}{#topcode}{#bottomcode}}} - -\permanent\tolerant\protected\def\mathover[#category]#spacer[#settings]#:#topcode#text% - {\begingroup - \edef\currentmathstackers{\ifparameter#category\or#category\else\v!top\fi}% - \ifparameter#settings\or - \setupcurrentmathstackers[#settings]% - \fi - \math_stackers_make_double\plusone\zerocount - {\currentmathstackers}% - {#topcode}% - {0}% - {#text}% - \endgroup} - -\permanent\tolerant\protected\def\mathunder[#category]#spacer[#settings]#:#bottomcode#text% - {\begingroup - \edef\currentmathstackers{\ifparameter#category\or#category\else\v!bottom\fi}% - \ifparameter#settings\or - \setupcurrentmathstackers[#settings]% - \fi - \math_stackers_make_double\zerocount\plusone - {\currentmathstackers}% - {#bottomcode}% - {0}% - {#text}% - \endgroup} - -\permanent\tolerant\protected\def\mathdouble[#category]#spacer[#settings]#:#topcode#bottomcode#text% - {\begingroup - \edef\currentmathstackers{\ifparameter#category\or#category\else\v!both\fi}% - \ifparameter#settings\or - \setupcurrentmathstackers[#settings]% - \fi - \math_stackers_make_double\plusone\plusone - {\currentmathstackers}% - {#topcode}% - {#bottomcode}% - {#text}% - \endgroup} - -\def\math_stackers_handle_direct#top#bottom#category#topcode#bottomcode#text% - {\begingroup - \math_stackers_make_double#top#bottom{#category}{#topcode}{#bottomcode}{#text}% - \endgroup} - -%D A relative new one is a combination of accents and text (as needed in mathml): - -\protected\def\math_stackers_make_double_text#where#category#codepoint#text#extra% - {\math_stackers_start_group{#category}% - \mathstackersparameter\c!left\relax - \dostarttagged\t!mstacker\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 - % - \ifempty\math_stackers_middle - \setbox\scratchboxthree\emptyhbox - \else - \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}% - \fi - % - \ifcase#where\relax - \edef\m_math_stackers_text_top{#extra}% - \ifempty\math_stackers_top - \setbox\scratchboxone\emptyhbox - \else - \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}% - \fi - \else - \edef\m_math_stackers_text_bottom{#extra}% - \ifempty\math_stackers_bottom - \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\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% - \fi - \ifdim\wd\scratchboxthree<\scratchwidth - \setbox\scratchboxthree\hpack 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} - -\permanent\tolerant\protected\def\definemathovertextextensible[#1]#*[#2]#*[#3]% - {\ifparameter#3\or - \frozen\setuevalue{#2}{\math_stackers_make_double_text\plusone{#1}{\number#3}}% - \else - \frozen\setuevalue{#1}{\math_stackers_make_double_text\plusone\noexpand\currentmathstackers{\number#2}}% - \fi} - -\permanent\tolerant\protected\def\definemathundertextextensible[#1]#*[#2]#*[#3]% - {\ifparameter#3\or - \frozen\setuevalue{#2}{\math_stackers_make_double_text\zerocount{#1}{\number#3}}% - \else - \frozen\setuevalue{#1}{\math_stackers_make_double_text\zerocount\noexpand\currentmathstackers{\number#2}}% - \fi} - -\permanent\tolerant\protected\def\mathovertext[#category]% - {\begingroup - \math_stackers_direct_double_text\plusone {\ifargument#category\or#category\else\v!top\fi}} - -\permanent\tolerant\protected\def\mathundertext[#category]% - {\begingroup - \math_stackers_direct_double_text\zerocount{\ifargument#category\or#category\else\v!bottom\fi}} - -\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. - -\permanent\tolerant\protected\def\mathtriplet[#category]#:#middletext#toptext#bottomtext% - {\begingroup - \math_stackers_triplet\plusone{\ifargument#category\or#category\else\currentmathstackers\fi}{#middletext}{#toptext}{#bottomtext}% - \endgroup} - -\permanent\tolerant\protected\def\definemathtriplet[#1]#*[#2]#*[#3]% category name default - {\ifarguments\or - \frozen\setuevalue{#1}{\math_stackers_auto_triplet_nop[\noexpand\currentmathstackers]}% - \or - \frozen\setuevalue{#2}{\math_stackers_auto_triplet_nop[#1]}% - \or - \frozen\setuevalue{#2}{\math_stackers_auto_triplet_yes[#1][#3]}% - \fi} - -\tolerant\protected\def\math_stackers_auto_triplet_yes[#1][#2]#*[#3]#:#=#*#=% [#2]% #2 gobble spaces - {\begingroup - \edef\currentmathstackers{#1}% - \def \m_math_stackers_text_middle{#2}% - \ifarguments#3\or\edef\currentmathstackers{#3}\fi - \math_stackers_triplet\plusone\currentmathstackers\m_math_stackers_text_middle{#4}{#5}% - \endgroup} - -\tolerant\protected\def\math_stackers_auto_triplet_nop[#1]#*[#2]#:#=#*#=#*#=% [#2]% #2 gobble spaces% - {\begingroup - \edef\currentmathstackers{#1}% - \ifarguments#2\or\edef\currentmathstackers{#2}\fi - \math_stackers_triplet\plusone\currentmathstackers{#3}{#4}{#5}% - \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 - -\immutable\protected\def\normaldoublebrace {\Umathaccents 0 \defaultmathfamily "23DE 0 \defaultmathfamily "23DF } -\immutable\protected\def\normaldoubleparent{\Umathaccents 0 \defaultmathfamily "23DC 0 \defaultmathfamily "23DD } - -% let's keep this - -\aliased\let\normaloverbrace \overbrace -\aliased\let\normalunderbrace \underbrace -\aliased\let\normaloverparent \overparent -\aliased\let\normalunderparent \underparent -\aliased\let\normaloverbracket \overbracket -\aliased\let\normalunderbracket \underbracket -\aliased\let\normalunderleftarrow \underleftarrow -\aliased\let\normaloverleftarrow \overleftarrow -\aliased\let\normalunderrightarrow\underrightarrow -\aliased\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\mathemwidth] % the default -\definemathstackers [\v!small] [\v!mathematics] [\c!hoffset=1\mathemwidth] -\definemathstackers [\v!medium] [\v!mathematics] [\c!hoffset=1.5\mathemwidth] -\definemathstackers [\v!big] [\v!mathematics] [\c!hoffset=2\mathemwidth] - -\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] - -%D We don't use overline and underline. This is one of the overlooked aspects of -%D unicode cq. opentype math: why treat rules different than e.g. arrows and -%D accents. It is a bit unfortunate that the opportunity to move math to new -%D technologies happened outside the tex domain (and/or some aspects were kept while -%D in fact they were side effects of limitations of traditional fonts). From the -%D unicode aware tex engines' implementation point of view things could have been -%D done a bit nicer but then: the community didn't seem to care too much and just -%D has to follow now. -%D -%D Anyhow, we use a character based approach so that at least we get unicode stuff -%D in the backend (okay, we still need to deal with some cut and paste issues but at -%D least we now know what we deal with. - -% alternatively we can move the original to FE* - -\definemathoverextensible [\v!vfenced] [overbar] ["FE33E] % ["203E] -\definemathunderextensible [\v!vfenced] [underbar] ["FE33F] % ["203E] -\definemathdoubleextensible [\v!vfenced] [doublebar] ["FE33E] ["FE33F] - -\definemathoverextensible [\v!vfenced] [overbrace] ["FE3DE] % ["023DE] -\definemathunderextensible [\v!vfenced] [underbrace] ["FE3DF] % ["023DF] -\definemathdoubleextensible [\v!vfenced] [doublebrace] ["FE3DE] ["FE3DF] - -\definemathoverextensible [\v!vfenced] [overparent] ["FE3DC] % ["023DC] -\definemathunderextensible [\v!vfenced] [underparent] ["FE3DD] % ["023DD] -\definemathdoubleextensible [\v!vfenced] [doubleparent] ["FE3DC] ["FE3DD] - -\definemathoverextensible [\v!vfenced] [overbracket] ["FE3B4] % ["023B4] -\definemathunderextensible [\v!vfenced] [underbracket] ["FE3B5] % ["023B5] -\definemathdoubleextensible [\v!vfenced] [doublebracket] ["FE3B4] ["FE3B5] - -% \protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} - -%D For mathml: - -\definemathdoubleextensible [\v!both] [overbarunderbar] ["FE33E] ["FE33F] -\definemathdoubleextensible [\v!both] [overbraceunderbrace] ["FE3DE] ["FE3DF] -\definemathdoubleextensible [\v!both] [overparentunderparent] ["FE3DC] ["FE3DD] -\definemathdoubleextensible [\v!both] [overbracketunderbracket] ["FE3B4] ["FE3B5] - -\definemathovertextextensible [\v!bothtext] [overbartext] ["FE33E] -\definemathundertextextensible [\v!bothtext] [underbartext] ["FE33F] -\definemathovertextextensible [\v!bothtext] [overbracetext] ["FE3DE] -\definemathundertextextensible [\v!bothtext] [underbracetext] ["FE3DF] -\definemathovertextextensible [\v!bothtext] [overparenttext] ["FE3DC] -\definemathundertextextensible [\v!bothtext] [underparenttext] ["FE3DD] -\definemathovertextextensible [\v!bothtext] [overbrackettext] ["FE3B4] -\definemathundertextextensible [\v!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\mathemwidth] - -\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 - -\immutable\protected\def\rightarrowfill {\math_stackers_hacked_fill \relbar \relbar \rightarrow} -\immutable\protected\def\leftarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \relbar } -\immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillleftend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillrightend} -\immutable\protected\def\equalfill {\math_stackers_hacked_fill \Relbar \Relbar \Relbar} -\immutable\protected\def\Rightarrowfill {\math_stackers_hacked_fill \Relbar \Relbar \Rightarrow} -\immutable\protected\def\Leftarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Relbar} -\immutable\protected\def\Leftrightarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Rightarrow} -\immutable\protected\def\leftrightarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \rightarrow} -\immutable\protected\def\mapstofill {\math_stackers_hacked_fill{\mapstochar\relbar} \relbar \rightarrow} -\immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar \relbar \twoheadrightarrow} -\immutable\protected\def\twoheadleftarrowfill {\math_stackers_hacked_fill \twoheadleftarrow \relbar \relbar} -\immutable\protected\def\rightharpoondownfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoondown} -\immutable\protected\def\rightharpoonupfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoonup} -\immutable\protected\def\leftharpoondownfill {\math_stackers_hacked_fill \leftharpoondown \relbar \relbar} -\immutable\protected\def\leftharpoonupfill {\math_stackers_hacked_fill \leftharpoonup \relbar \relbar} -\immutable\protected\def\hookleftfill {\math_stackers_hacked_fill \leftarrow \relbar {\relbar\joinrel\rhook}} -\immutable\protected\def\hookrightfill {\math_stackers_hacked_fill{\lhook\joinrel\relbar} \relbar \rightarrow} -\immutable\protected\def\relfill {\math_stackers_hacked_fill \relbar \relbar \relbar} -\immutable\protected\def\triplerelfill {\math_stackers_hacked_fill \equiv \equiv \equiv} - -% \permanent\protected\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}} -% \permanent\protected\def\doublebond{{\xequal}} -% \permanent\protected\def\triplebond{{\xtriplerel}} - -%D For the moment (needs checking): - -\permanent\tolerant\protected\def\defineextensiblefiller[#1]#*[#2]% - {\immutable\letcsname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname - %\immutable\letcsname#1\expandafter\endcsname\csname#1\endcsname - } % huh? - -\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[Rightleftarrowfill] [.....] - -% These are fishy ... we need to check this because now these commands relax (there -% are some entries in char-def.) -% -% %definemathoverextensible [overbarfill] ["FE33E] -% %definemathunderextensible [underbarfill] ["FE33F] -% \definemathoverextensible [overbracefill] ["FE3DE] -% \definemathunderextensible [underbracefill] ["FE3DF] -% \definemathoverextensible [overparentfill] ["FE3DC] -% \definemathunderextensible [underparentfill] ["FE3DD] -% \definemathoverextensible [overbracketfill] ["FE3B4] -% \definemathunderextensible [underbracketfill] ["FE3B5] -% -% %defineextensiblefiller [overbarfill] ["FE33E] -% %defineextensiblefiller [underbarfill] ["FE33F] -% \defineextensiblefiller [overbracefill] ["FE3DE] -% \defineextensiblefiller [underbracefill] ["FE3DF] -% \defineextensiblefiller [overparentfill] ["FE3DC] -% \defineextensiblefiller [underparentfill] ["FE3DD] -% \defineextensiblefiller [overbracketfill] ["FE3B4] -% \defineextensiblefiller [underbracketfill] ["FE3B5] - -%D Extra: - -\permanent\protected\edef\singlebond{\mathematics{\mathsurround\zeropoint\char\number"002D\relax}} -\permanent\protected\edef\doublebond{\mathematics{\mathsurround\zeropoint\char\number"003D\relax}} -\permanent\protected\edef\triplebond{\mathematics{\mathsurround\zeropoint\char\number"2261\relax}} - -% \mathchardef\singlebond"002D -% \mathchardef\doublebond"003D -% \mathchardef\triplebond"2261 - -%D Also handy: - -\permanent\tolerant\protected\def\definemathunstacked[#1]#*[#2]#*[#3]% category name unicode - {\ifarguments\or\or - \frozen\setuevalue{#1}{\math_stackers_unstacked_normal\noexpand\currentmathstackers{\number#2}}% - \else - \frozen\setuevalue{#2}{\math_stackers_unstacked_normal{#1}{\number#3}}% - \fi} - -\protected\def\math_stackers_unstacked_normal#category#codepoint% - {\begingroup - \edef\currentmathstackers{#category}% - \edef\p_moffset{\mathstackersparameter\c!moffset}% - \ifempty\p_moffset \else - \mskip\p_moffset\relax - \fi - \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi - {\usemathstackerscolorparameter\c!color - \Umathchar\zerocount\defaultmathfamily#codepoint}% - \ifempty\p_moffset \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\;} - -% New (an example of using \mathexheight): - -\definemathstackers - [\v!symbol] - [\c!voffset=-.3\mathexheight, - \c!hoffset=\zeropoint, - \c!mathclass=ord, - \c!topoffset=.4\mathemwidth, % poor man's italic correction - \c!middlecommand=\mathematics] - -\definemathover[\v!symbol][interiorset]["2218] - -\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/tex/context/base/mkiv/math-tag.lmt b/tex/context/base/mkiv/math-tag.lmt deleted file mode 100644 index eb58b5450..000000000 --- a/tex/context/base/mkiv/math-tag.lmt +++ /dev/null @@ -1,596 +0,0 @@ -if not modules then modules = { } end modules ['math-tag'] = { - version = 1.001, - comment = "companion to math-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo: have a local list with local tags that then get appended --- todo: use tex.getmathcodes (no table) - --- use lpeg matchers - -local find, match = string.find, string.match -local insert, remove, concat = table.insert, table.remove, table.concat - -local attributes = attributes -local nodes = nodes - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getchar = nuts.getchar -local getfont = nuts.getfont -local getlist = nuts.getlist -local getfield = nuts.getfield -local getdisc = nuts.getdisc -local getsubtype = nuts.getsubtype -local getattr = nuts.getattr -local getattrlist = nuts.getattrlist -local setattr = nuts.setattr ------ getcomponents = nuts.getcomponents -- not really needed -local getwidth = nuts.getwidth - -local getnucleus = nuts.getnucleus -local getsub = nuts.getsub -local getsup = nuts.getsup - -local set_attributes = nuts.setattributes - -local nextnode = nuts.traversers.node - -local nodecodes = nodes.nodecodes - -local noad_code = nodecodes.noad -- attr nucleus sub sup -local accent_code = nodecodes.accent -- attr nucleus sub sup accent -local radical_code = nodecodes.radical -- attr nucleus sub sup left degree -local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right -local subbox_code = nodecodes.subbox -- attr list -local submlist_code = nodecodes.submlist -- attr list -local mathchar_code = nodecodes.mathchar -- attr fam char -local mathtextchar_code = nodecodes.mathtextchar -- attr fam char -local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char -local style_code = nodecodes.style -- attr style -local choice_code = nodecodes.choice -- attr display text script scriptscript -local fence_code = nodecodes.fence -- attr subtype - -local accentcodes = nodes.accentcodes -local fencecodes = nodes.fencecodes - -local fixedtopaccent_code = accentcodes.fixedtop -local fixedbottomaccent_code = accentcodes.fixedbottom -local fixedbothaccent_code = accentcodes.fixedboth - -local leftfence_code = fencecodes.left -local middlefence_code = fencecodes.middle -local rightfence_code = fencecodes.right - -local kerncodes = nodes.kerncodes - -local fontkern_code = kerncodes.fontkern -local italickern_code = kerncodes.italickern - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local math_code = nodecodes.math - -local processnoads = noads.process - -local a_tagged = attributes.private('tagged') -local a_mathcategory = attributes.private('mathcategory') -local a_mathmode = attributes.private('mathmode') - -local tags = structures.tags - -local start_tagged = tags.start -local restart_tagged = tags.restart -local stop_tagged = tags.stop -local taglist = tags.taglist - -local chardata = characters.data - -local getmathcodes = tex.getmathcodes -local mathcodes = mathematics.codes -local ordinary_mathcode = mathcodes.ordinary -local variable_mathcode = mathcodes.variable - -local fromunicode16 = fonts.mappings.fromunicode16 -local fontcharacters = fonts.hashes.characters - -local report_tags = logs.reporter("structure","tags") - -local process - -local function processsubsup(start) - -- At some point we might need to add an attribute signaling the - -- super- and subscripts because TeX and MathML use a different - -- order. The mrows are needed to keep mn's separated. - local nucleus = getnucleus(start) - local sup = getsup(start) - local sub = getsub(start) - if sub then - if sup then - setattr(start,a_tagged,start_tagged("msubsup")) - -- start_tagged("mrow") - process(nucleus) - -- stop_tagged() - start_tagged("mrow", { subscript = true }) - process(sub) - stop_tagged() - start_tagged("mrow", { superscript = true }) - process(sup) - stop_tagged() - stop_tagged() - else - setattr(start,a_tagged,start_tagged("msub")) - -- start_tagged("mrow") - process(nucleus) - -- stop_tagged() - start_tagged("mrow") - process(sub) - stop_tagged() - stop_tagged() - end - elseif sup then - setattr(start,a_tagged,start_tagged("msup")) - -- start_tagged("mrow") - process(nucleus) - -- stop_tagged() - start_tagged("mrow") - process(sup) - stop_tagged() - stop_tagged() - else - process(nucleus) - end -end - --- todo: check function here and keep attribute the same - --- todo: variants -> original - -local actionstack = { } -local fencesstack = { } - --- glyph nodes and such can happen in under and over stuff - --- local function getunicode(n) -- instead of getchar --- local char = getchar(n) --- -- local font = getfontoffamily(getfield(n,"fam")) --- local font = getfont(n) --- local data = fontcharacters[font][char] --- return data.unicode or char --- end - -local function getunicode(n) -- instead of getchar - -- local char, font = isglyph(n) -- no, we have a mathchar - local char, font = getchar(n), getfont(n) - local data = fontcharacters[font][char] - return data.unicode or char -- can be a table but unlikely for math characters -end - -------------------- - -local content = { } -local found = false - -content[mathchar_code] = function() found = true end - -local function hascontent(head) - found = false - processnoads(head,content,"content") - return found -end - --------------------- - --- todo: use properties - --- local function showtag(n,id,old) --- local attr = getattr(n,a_tagged) --- local curr = tags.current() --- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)", --- old and "before" or "after ", --- nodecodes[id], --- getattrlist(n), --- attr or "?",attr and taglist[attr].tagname or "?", --- curr or "?",curr and taglist[curr].tagname or "?" --- ) --- end - -process = function(start) -- we cannot use the processor as we have no finalizers (yet) - local mtexttag = nil - while start do - local id = getid(start) --- showtag(start,id,true) - if id == glyph_code or id == disc_code then - if not mtexttag then - mtexttag = start_tagged("mtext") - end - setattr(start,a_tagged,mtexttag) - elseif mtexttag and id == kern_code and (getsubtype(start) == fontkern_code or getsubtype(start) == italickern_code) then -- italickern - setattr(start,a_tagged,mtexttag) - else - if mtexttag then - stop_tagged() - mtexttag = nil - end - if id == mathchar_code then - local char = getchar(start) - local code = getmathcodes(char) - local tag - if code == ordinary_mathcode or code == variable_mathcode then - local ch = chardata[char] - local mc = ch and ch.mathclass - if mc == "number" then - tag = "mn" - elseif mc == "variable" or not mc then -- variable is default - tag = "mi" - else - tag = "mo" - end - else - tag = "mo" - end - local a = getattr(start,a_mathcategory) - if a then - setattr(start,a_tagged,start_tagged(tag,{ mathcategory = a })) - else - setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory - end - stop_tagged() - -- showtag(start,id,false) - break -- okay? - elseif id == mathtextchar_code then -- or id == glyph_code - -- check for code - local a = getattr(start,a_mathcategory) - if a then - setattr(start,a_tagged,start_tagged("ms",{ mathcategory = a })) -- mtext - else - setattr(start,a_tagged,start_tagged("ms")) -- mtext - end - stop_tagged() - -- showtag(start,id,false) - break - elseif id == delimiter_code then - -- check for code - setattr(start,a_tagged,start_tagged("mo")) - stop_tagged() - -- showtag(start,id,false) - break - elseif id == style_code then - -- has a next - elseif id == noad_code then - -- setattr(start,a_tagged,tags.current()) - processsubsup(start) - elseif id == subbox_code or id == hlist_code or id == vlist_code then - -- keep an eye on subbox_code and see what ends up in there - local attr = getattr(start,a_tagged) - if not attr then - -- just skip - else - local specification = taglist[attr] - if specification then - local tag = specification.tagname - if tag == "formulacaption" then - -- skip - elseif tag == "mstacker" then - local list = getlist(start) - if list then - process(list) - end - else - if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then - tag = "mtext" - end - local text = start_tagged(tag) - setattr(start,a_tagged,text) - local list = getlist(start) - if not list then - -- empty list - elseif not attr then - -- box comes from strange place - set_attributes(list,a_tagged,text) -- only the first node ? - else - -- Beware, the first node in list is the actual list so we definitely - -- need to nest. This approach is a hack, maybe I'll make a proper - -- nesting feature to deal with this at another level. Here we just - -- fake structure by enforcing the inner one. - -- - -- todo: have a local list with local tags that then get appended - -- - local tagdata = specification.taglist - local common = #tagdata + 1 - local function runner(list,depth) -- quite inefficient - local cache = { } -- we can have nested unboxed mess so best local to runner - local keep = nil - -- local keep = { } -- win case we might need to move keep outside - for n, id, subtype in nextnode, list do - local mth = id == math_code and subtype - if mth == 0 then -- hm left_code - -- insert(keep,text) - keep = text - text = start_tagged("mrow") - common = common + 1 - end - local aa = getattr(n,a_tagged) - if aa then - local ac = cache[aa] - if not ac then - local tagdata = taglist[aa].taglist - local extra = #tagdata - if common <= extra then - for i=common,extra do - ac = restart_tagged(tagdata[i]) -- can be made faster - end - for i=common,extra do - stop_tagged() -- can be made faster - end - else - ac = text - end - cache[aa] = ac - end - setattr(n,a_tagged,ac) - else - setattr(n,a_tagged,text) - end - if id == hlist_code or id == vlist_code then - runner(getlist(n),depth+1) - elseif id == glyph_code then - -- this should not be needed - -- local components = getcomponents(n) -- unlikely set - -- if components then - -- runner(getcomponent,depth+1) - -- end - elseif id == disc_code then - -- this should not be needed - local pre, post, replace = getdisc(n) - if pre then - runner(pre,depth+1) - end - if post then - runner(post,depth+1) - end - if replace then - runner(replace,depth+1) - end - end - if mth == 1 then - stop_tagged() - -- text = remove(keep) - text = keep - common = common - 1 - end - end - end - runner(list,0) - end - stop_tagged() - end - end - end - elseif id == submlist_code then -- normally a hbox - local list = getlist(start) - if list then - local attr = getattr(start,a_tagged) - local last = attr and taglist[attr] - if last then - local tag = last.tagname - local detail = last.detail - if tag == "maction" then - if detail == "" then - setattr(start,a_tagged,start_tagged("mrow")) - process(list) - stop_tagged() - elseif actionstack[#actionstack] == action then - setattr(start,a_tagged,start_tagged("mrow")) - process(list) - stop_tagged() - else - insert(actionstack,action) - setattr(start,a_tagged,start_tagged("mrow",{ detail = action })) - process(list) - stop_tagged() - remove(actionstack) - end - elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then - -- looks like it gets processed twice - -- do we still end up here ? - setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute - process(list) - stop_tagged() - else - setattr(start,a_tagged,start_tagged("mrow")) - process(list) - stop_tagged() - end - else -- never happens, we're always document - setattr(start,a_tagged,start_tagged("mrow")) - process(list) - stop_tagged() - end - end - elseif id == fraction_code then - local num = getfield(start,"num") - local denom = getfield(start,"denom") - local left = getfield(start,"left") - local right = getfield(start,"right") - if left then - setattr(left,a_tagged,start_tagged("mo")) - process(left) - stop_tagged() - end - setattr(start,a_tagged,start_tagged("mfrac")) - process(num) - process(denom) - stop_tagged() - if right then - setattr(right,a_tagged,start_tagged("mo")) - process(right) - stop_tagged() - end - elseif id == choice_code then - local display = getfield(start,"display") - local text = getfield(start,"text") - local script = getfield(start,"script") - local scriptscript = getfield(start,"scriptscript") - if display then - process(display) - end - if text then - process(text) - end - if script then - process(script) - end - if scriptscript then - process(scriptscript) - end - elseif id == fence_code then - local subtype = getsubtype(start) - local delim = getfield(start,"delimiter") - if subtype == leftfence_code then - -- left - local properties = { } - insert(fencesstack,properties) - setattr(start,a_tagged,start_tagged("mfenced",properties)) -- needs checking - if delim then - start_tagged("ignore") - local chr = getchar(delim) - if chr ~= 0 then - properties.left = chr - end - process(delim) - stop_tagged() - end - start_tagged("mrow") -- begin of subsequence - elseif subtype == middlefence_code then - -- middle - if delim then - start_tagged("ignore") - local top = fencesstack[#fencesstack] - local chr = getchar(delim) - if chr ~= 0 then - local mid = top.middle - if mid then - mid[#mid+1] = chr - else - top.middle = { chr } - end - end - process(delim) - stop_tagged() - end - stop_tagged() -- end of subsequence - start_tagged("mrow") -- begin of subsequence - elseif subtype == rightfence_code then - local properties = remove(fencesstack) - if not properties then - report_tags("missing right fence") - properties = { } - end - if delim then - start_tagged("ignore") - local chr = getchar(delim) - if chr ~= 0 then - properties.right = chr - end - process(delim) - stop_tagged() - end - stop_tagged() -- end of subsequence - stop_tagged() - else - -- can't happen - end - elseif id == radical_code then - local left = getfield(start,"left") - local degree = getfield(start,"degree") - if left then - start_tagged("ignore") - process(left) -- root symbol, ignored - stop_tagged() - end - if degree and hascontent(degree) then - setattr(start,a_tagged,start_tagged("mroot")) - processsubsup(start) - process(degree) - stop_tagged() - else - setattr(start,a_tagged,start_tagged("msqrt")) - processsubsup(start) - stop_tagged() - end - elseif id == accent_code then - local subtype = getsubtype(start) - local accent = getfield(start,"accent") - local bot_accent = getfield(start,"bot_accent") - if bot_accent then - if accent then - setattr(start,a_tagged,start_tagged("munderover", { - accent = true, - top = getunicode(accent), - bottom = getunicode(bot_accent), - topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, - bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, - })) - processsubsup(start) - process(bot_accent) - process(accent) - stop_tagged() - else - setattr(start,a_tagged,start_tagged("munder", { - accent = true, - bottom = getunicode(bot_accent), - bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, - })) - processsubsup(start) - process(bot_accent) - stop_tagged() - end - elseif accent then - setattr(start,a_tagged,start_tagged("mover", { - accent = true, - top = getunicode(accent), - topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, - })) - processsubsup(start) - process(accent) - stop_tagged() - else - processsubsup(start) - end - elseif id == glue_code then - -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) })) - setattr(start,a_tagged,start_tagged("mspace")) - stop_tagged() - else - setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] })) - stop_tagged() - end - end --- showtag(start,id,false) - start = getnext(start) - end - if mtexttag then - stop_tagged() - end -end - -function noads.handlers.tags(head,style,penalties) - start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" }) - setattr(head,a_tagged,start_tagged("mrow")) --- showtag(head,getid(head),true) - process(head) --- showtag(head,getid(head),false) - stop_tagged() - stop_tagged() -end diff --git a/tex/context/base/mkiv/math-toy.mkxl b/tex/context/base/mkiv/math-toy.mkxl deleted file mode 100644 index 510872e3b..000000000 --- a/tex/context/base/mkiv/math-toy.mkxl +++ /dev/null @@ -1,54 +0,0 @@ -%D \module -%D [ file=math-toy, -%D version=2020.08.31, -%D title=\CONTEXT\ Math Macros, -%D subtitle=Toy 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 Math Macros / Toy} - -\unprotect - -%D Just an example: -%D -%D \starttyping -%D \enabletrackers[math.toysymbol] -%D -%D \definemathtoysymbol[Plus] [bin][+] -%D \definemathtoysymbol[Minus][bin][-] -%D \definemathtoysymbol[Equal][rel][=] -%D -%D $\dorecurse{199}{x_{#1} \ifodd#1\relax\Plus\else\Minus\fi} x_{200} \Equal n$ \blank -%D \stoptyping - -\permanent\tolerant\protected\def\definemathtoysymbol[#1]#*[#2]#*[#3]% - {\ifarguments\or\or\or - \setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}% - \fi} - -\protected\def\math_toy_define_symbol_traced#1#2% - {\normalexpanded{\discretionary class #1 % - {$\Ustyle\number\mathstyle \darkred #2$}% - {$\Ustyle\number\mathstyle \darkblue #2$}% - {$\Ustyle\number\mathstyle \darkgreen #2$}}} - -\protected\def\math_toy_define_symbol_normal#1#2% - {\normalexpanded{\discretionary class #1 % - {$\Ustyle\number\mathstyle #2$}% - {$\Ustyle\number\mathstyle #2$}% - {$\Ustyle\number\mathstyle #2$}}} - -\installtextracker - {math.toysymbol} - {\let\math_toy_define_symbol_indeed\math_toy_define_symbol_traced} - {\let\math_toy_define_symbol_indeed\math_toy_define_symbol_normal} - -\let\math_toy_define_symbol_indeed\math_toy_define_symbol_normal - -\protect diff --git a/tex/context/base/mkiv/meta-imp-experiments.mkxl b/tex/context/base/mkiv/meta-imp-experiments.mkxl deleted file mode 100644 index 644a8fff0..000000000 --- a/tex/context/base/mkiv/meta-imp-experiments.mkxl +++ /dev/null @@ -1,358 +0,0 @@ -%D \module -%D [ file=meta-imp-experiments, -%D version=2020.03.18, -%D title=\METAPOST\ Graphics, -%D subtitle=Experimental 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. - -%D This library implements some experimental functionality that eventually -%D might end up someplace else. - -\startluacode - - -- I decided to play with this kind of graphics after I read an article in a Dutch - -- popular science journal. It was an article about virusus in the mids of the time - -- when covid raged, so it also was a distraction. - - -- This is a typical case of first prototyping it in Lua using the 'context' command - -- to generate MetaPost code and when that worked okay do it the following way. The - -- way data is passed is a bit messy. - - do - - local function sum(t) - local n = 0 - for i=1,#t do - n = n + t[i] - end - return n - end - - local function checked(data) - if data then - local n = #data - for i=1,n do - data[i][i] = 0 - end - for i=1,n do - local di = data[i] - for j=i+1,n do - local dj = data[j] - local dji = dj[i] - if not dji then - dji = 0 - dj[i] = 0 - end - di[j] = dji - end - end - return data - else - return { } - end - end - - local data, list = nil, nil - - function mp.lmt_overlap_prepare() - data = checked(metapost.getparameter { "data" }) - list = { } - for i=1,#data do - list[i] = sum(data[i]) - end - end - - function mp.lmt_overlap_reset() - data = nil - list = nil - end - - function mp.lmt_overlap_n() - return #list - end - - function mp.lmt_overlap_data(i, j) - if j then - return data[i][j] - else - return list[i] - end - end - - local injectstring = mp.inject.string - - function mp.lmt_overlap_text(i, j) - injectstring(data[i][j] or "") - end - - function mp.lmt_overlap_label(i) - local labels = metapost.getparameter { "labels" } - injectstring(labels and labels[i] or "") - end - - function mp.lmt_overlap_color(i) - local colors = metapost.getparameter { "colors" } - injectstring(colors and colors[i] or "darkgray") - end - - function mp.lmt_overlap_total() - return sum(list) - end - - end -\stopluacode - -\startMPextensions - -presetparameters "overlap" [ - options = "paths,lines", - gap = 4, - subgap = 2, - offset = 8, - color = "darkgray", - alternative = "circular", - colors = { - "darkred", - "darkgreen", - "darkblue", - "darkyellow", - "darkmagenta", - "darkcyan" - }, -] ; - -def lmt_overlap = applyparameters "overlap" "lmt_do_overlap" enddef ; - -vardef lmt_do_overlap_circular = - - astep := 360 / steps ; - - p := fullcircle scaled steps ; - r := origin -- (2*steps,0) ; - - start := 0 ; - stop := 0 ; - for i=1 upto n: - stop := start + lua.mp.lmt_overlap_data(i) ; - first := start ; - last := stop ; - for j=1 upto n: - if i <> j : - last := first + lua.mp.lmt_overlap_data(i,j) ; - a := p intersectionpoint (r rotated (first * astep + 0.1)) ; % the 0.1 is somehow needed, why - b := p intersectionpoint (r rotated (last * astep - 0.1)) ; % the 0.1 is somehow needed, why - qq[i][j] := (p cutafter b) cutbefore a ; - first := last + subgap ; - fi ; - endfor ; - start := stop + gap + (n - 1) * subgap ; - endfor ; - - if hasoption "options" "paths" : - - for i=1 upto n : - for j=1 upto n : - if i <> j : - q := qq[i][j] ; - freelabeloffset := getparameter "offset" ; - freelabel(lua.mp.lmt_overlap_text(i,j), point .5 along q, origin) ; - if i < j : - s := qq[j][i] ; - a := point length(q) of q ; - b := point 0 of s ; - c := point length(s) of s ; - d := point 0 of q ; - q := q & a .. controls origin and origin .. b & s & c .. controls origin and origin .. d -- cycle ; - fill q withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; - fi ; - fi ; - endfor ; - endfor ; - - fi ; - - if hasoption "options" "lines" : - - start := 0 ; - stop := 0 ; - for i=1 upto n: - stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; - a := p intersectionpoint (r rotated (start * astep)) ; - b := p intersectionpoint (r rotated (stop * astep)) ; - q := (p cutbefore a) cutafter b ; - freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; - freelabel(lua.mp.lmt_overlap_label(i), point .5 along q, origin) ; - draw q withcolor white withpen pencircle scaled 5 ; - draw q withcolor getparameter "color" withpen pencircle scaled 5 ; - start := stop + gap + subgap ; - endfor ; - - fi ; - -enddef ; - -vardef lmt_do_overlap_linear = - astep := 1 ; % 1.25 - - p := origin -- (astep * steps,0) ; - r := origin -- (0,astep * steps) ; - - start := 0 ; - stop := 0 ; - for i=1 upto n: - stop := start + lua.mp.lmt_overlap_data(i) ; - first := start ; - last := stop ; - for j=1 upto n: - if i <> j : - last := first + lua.mp.lmt_overlap_data(i,j) ; - qq[i][j] := (first * astep,0) -- (last * astep,0) ; - first := last + subgap ; - fi ; - endfor ; - start := stop + gap + (n - 1) * subgap ; - endfor ; - - if hasoption "options" "paths" : - - for i=1 upto n : - for j=1 upto n : - if i < j : - qq[i][j] := qq[i][j] { up } .. { down } qq[j][i] { up } .. { down} cycle ; - fill qq[i][j] withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; - fi ; - endfor ; - endfor ; - - for i=1 upto n : - for j=1 upto n : - if i < j : - t := thelabel(lua.mp.lmt_overlap_text(i,j), (center topboundary qq[i][j]) ) ; - fill boundingbox t enlarged (ExHeight/2) withcolor white ; - draw t ; - fi ; - endfor ; - endfor ; - - fi ; - - if hasoption "options" "lines" : - - start := 0 ; - stop := 0 ; - for i=1 upto n: - stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; - q := (start * astep,0) -- (stop * astep,0) ; - freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; - label.bot(lua.mp.lmt_overlap_label(i), (point .5 along q) shifted (0,- freelabeloffset/4)) ; - draw q withcolor white withpen pencircle scaled 5 ; - draw q withcolor getparameter "color" withpen pencircle scaled 5 ; - start := stop + gap + subgap ; - endfor ; - - fi ; - -enddef ; - -vardef lmt_do_overlap = - image ( - - pushparameters "overlap" ; - - save p, q, r, s, qq, a, b, c, d, t, n, gap, subgap, steps, astep, start, stop, first, last ; - path p, q, r, s, qq[][] ; - pair a, b, c, d ; - picture t ; - numeric n, gap, subgap, steps, astep, start, stop, first, last ; - save freelabeloffset; freelabeloffset := 8 ; - interim linecap := butt; - interim linejoin := squared; - - lua.mp.lmt_overlap_prepare() ; - - n := lua.mp.lmt_overlap_n(); - gap := getparameter "gap" ; - subgap := getparameter "subgap" ; - steps := lua.mp.lmt_overlap_total() + (n * gap) + n * (n - 1) * subgap ; - - if ((getparameter "alternative") = "linear") or ((getparameter "alternative") = "line") : - lmt_do_overlap_linear ; - else : - lmt_do_overlap_circular ; - fi ; - - lua.mp.lmt_overlap_reset() ; - - popparameters ; - ) -enddef ; - -\stopMPextensions - -\continueifinputfile{meta-imp-experiments.mkxl} - -% \useMPlibrary[experiments] - -\usemodule[article-basic] - -\starttext - -% todo: datafile: { data = { }, labels = { } } - -% % data = { -% % { 0, 10, 30, 10, 20 }, -% % { 10, 0, 10, 20, 10 }, -% % { 30, 10, 0, 5, 15 }, -% % { 10, 20, 5, 0, 5 }, -% % { 20, 10, 15, 5, 0 } -% % }, -% % data = { -% % { 0 }, -% % { 10, 0 }, -% % { 30, 10, 0 }, -% % { 10, 20, 5, 0 }, -% % { 20, 10, 15, 5, 0 } -% % }, -% data = { -% { }, -% { 10 }, -% { 30, 10 }, -% { 10, 20, 5 }, -% { 20, 10, 15, 5 } -% }, - -\startbuffer -\startMPcode{doublefun} - draw lmt_overlap [ - alternative = "circular", - data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, - labels = { "one", "two", "three", "four", "five" } - ] ; -\stopMPcode -\stopbuffer - -\startlinecorrection[blank] - \getbuffer -\stoplinecorrection - -\startbuffer -\startMPcode{doublefun} - draw lmt_overlap [ - alternative = "linear", - data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, - labels = { "one", "two", "three", "four", "five" } - ] ; -\stopMPcode -\stopbuffer - -\startlinecorrection[blank] - \getbuffer -\stoplinecorrection - -\stoptext diff --git a/tex/context/base/mkiv/meta-imp-gamesymbols.mkxl b/tex/context/base/mkiv/meta-imp-gamesymbols.mkxl deleted file mode 100644 index d79e59f69..000000000 --- a/tex/context/base/mkiv/meta-imp-gamesymbols.mkxl +++ /dev/null @@ -1,349 +0,0 @@ -%D \module -%D [ file=meta-imp-gamesymbols, -%D version=2019.10.10, -%D title=\METAPOST\ Graphics, -%D subtitle=Game 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 The \METAFUN\ code here is not optimal and efficient but as it serves as an -%D example I decided to keep it simple. Also, performance is not really an issue -%D here anyway. Inspired by the classic \quote {Concrete Mathematics} by Don Knuth -%D we define dice and dominos, which happen to be \UNICODE\ characters now. We -%D use this opportunity to demonstrate slightly different approached. - -%D Each dice gets it's own macro at the \METAPOST\ end. Watch how we use the \type -%D {simplefun} instance in combination with a calculation wrapper. This will just -%D execute the code and leave no traces in the text flow. The code itself is not -%D that spectacular: - -\startMPcalculation{simplefun} - - def DiceFrame = - pickup pencircle scaled 1/2 ; - draw unitsquare scaled 8 ; - pickup pencircle scaled 3/2 ; - enddef ; - - vardef DiceOne = - DiceFrame ; - draw (4,4) ; - enddef ; - vardef DiceTwoA = - DiceFrame ; - draw (2,6) ; draw (6,2) ; - enddef ; - vardef DiceTwoB = - DiceFrame ; - draw (6,6) ; draw (2,2) ; - enddef ; - vardef DiceTwo = - if hasoption "mpsfont" "option" "reverse" : - DiceTwoB - else : - DiceTwoA - fi ; - enddef ; - vardef DiceThreeA = - DiceFrame ; - draw (2,6) ; draw (4,4) ; draw (6,2) ; - enddef ; - vardef DiceThreeB = - DiceFrame ; - draw (6,6) ; draw (4,4) ; draw (2,2) ; - enddef ; - vardef DiceThree = - if hasoption "mpsfont" "option" "reverse" : - DiceThreeB - else : - DiceThreeA - fi ; - enddef ; - vardef DiceFour = - DiceFrame ; - draw (2,6) ; draw (6,6) ; draw (2,2) ; draw (6,2) ; - enddef ; - vardef DiceFive = - DiceFrame ; - draw (2,6) ; draw (6,6) ; draw (4,4) ; draw (2,2) ; draw (6,2) ; - enddef ; - vardef DiceSix = - DiceFrame ; - draw (2,6) ; draw (6,6) ; draw (2,4) ; draw (6,4) ; draw (2,2) ; draw (6,2) ; - enddef ; - - vardef DiceBad = - pickup pencircle scaled 1/2 ; - draw unitsquare scaled 8 ; - draw (1,7) -- (7,1) ; draw (1,1) -- (7,7) ; - enddef ; - - lmt_registerglyphs [ - name = "dice", - units = 12, - width = 8, - height = 8, - depth = 0, - usecolor = true, - ] ; - - lmt_registerglyph [ category = "dice", unicode = "0x2680", code = "DiceOne;" ] ; - lmt_registerglyph [ category = "dice", unicode = "0x2681", code = "DiceTwo;" ] ; - lmt_registerglyph [ category = "dice", unicode = "0x2682", code = "DiceThree;" ] ; - lmt_registerglyph [ category = "dice", unicode = "0x2683", code = "DiceFour;" ] ; - lmt_registerglyph [ category = "dice", unicode = "0x2684", code = "DiceFive;" ] ; - lmt_registerglyph [ category = "dice", unicode = "0x2685", code = "DiceSix;" ] ; - - lmt_registerglyph [ category = "dice", private = "invaliddice", code = "DiceBad;" ] ; - -\stopMPcalculation - -%D At the \TEX\ end we define three features. The reverse is just there for fun. The -%D digits features will map digits onto dice. - -\definefontfeature - [dice:normal] - [default] - [metapost={category=dice}] - -\definefontfeature - [dice:reverse] - [default] - [metapost={category=dice,option=reverse}] - -\definefontfeature - [dice:digits] - [dice:digits=yes] - -%D The mapping to dice happens here: - -\startluacode - - -- local invalid = fonts.helpers.privateslot("invaliddice") - - fonts.handlers.otf.addfeature("dice:digits", { - type = "substitution", - order = { "dice:digits" }, - nocheck = true, - data = { - [0x30] = "invaliddice", - [0x31] = 0x2680, - [0x32] = 0x2681, - [0x33] = 0x2682, - [0x34] = 0x2683, - [0x35] = 0x2684, - [0x36] = 0x2685, - [0x37] = "invaliddice", - [0x38] = "invaliddice", - [0x39] = "invaliddice", - }, - } ) - -\stopluacode - -%D An example is given at the the end of this file so we now move forward with -%D the dominos. - -\startMPcalculation{simplefun} - - %D Because there are so many dominos we predefine the shapes and then register - %D the lot in a loop. - - picture Dominos[] ; - - Dominos[0] := image() ; - Dominos[1] := image(draw(4,4);) ; - Dominos[2] := image(draw(2,6);draw(6,2);); - Dominos[3] := image(draw(2,6);draw(4,4);draw(6,2);); - Dominos[4] := image(draw(2,6);draw(6,6);draw(2,2);draw(6,2);); - Dominos[5] := image(draw(2,6);draw(6,6);draw(4,4);draw(2,2);draw(6,2);); - Dominos[6] := image(draw(2,6);draw(4,6);draw(6,6);draw(2,2);draw(4,2);draw(6,2);); - % Dominos[7] := Dominos[0] ; - % Dominos[8] := Dominos[0] ; - % Dominos[9] := Dominos[0] ; - - %D Defining the font properties is straightforward: - - lmt_registerglyphs [ - name = "dominos", - units = 12, - width = 16, - height = 8, - depth = 0, - usecolor = true, - ] ; - - %D We have horizontal dominos: - - def DrawDominoH(expr a, b) = - draw image ( - pickup pencircle scaled 1/2 ; - if (getparameterdefault "mpsfont" "color" "") = "black" : - fillup unitsquare xyscaled (16,8) ; - draw (8,.5) -- (8,7.5) withcolor white ; - pickup pencircle scaled 3/2 ; - draw Dominos[a] - withpen currentpen - withcolor white ; - draw Dominos[b] shifted (8,0) - withpen currentpen - withcolor white ; - else : - draw unitsquare xyscaled (16,8) ; - draw (8,0) -- (8,8) ; - pickup pencircle scaled 3/2 ; - draw Dominos[a] - withpen currentpen ; - draw Dominos[b] shifted (8,0) - withpen currentpen ; - fi ; - ) ; - enddef ; - - %D and vertical ones. We could use the above macro and rotate and shift and reflect - %D but why bother with it: - - def DrawDominoV(expr a, b) = % is H rotated and shifted - draw image ( - pickup pencircle scaled 1/2 ; - if (getparameterdefault "mpsfont" "color" "") = "black" : - fillup unitsquare xyscaled (8,16) ; - draw (.5,8) -- (7.5,8) withcolor white ; - pickup pencircle scaled 3/2 ; - draw Dominos[a] rotatedaround(center Dominos[a],90) - withpen currentpen - withcolor white ; - draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) - withpen currentpen - withcolor white ; - else : - draw unitsquare xyscaled (8,16) ; - draw (0,8) -- (8,8) ; - pickup pencircle scaled 3/2 ; - draw Dominos[a] rotatedaround(center Dominos[a],90) - withpen currentpen ; - draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) - withpen currentpen ; - fi ; - ) ; - enddef ; - - %D We have two simple loops that define the horizontal range: - - save unicode ; numeric unicode ; unicode := 127025 ; % 1F031 - - for i=0 upto 6 : - for j=0 upto 6 : - lmt_registerglyph [ - category = "dominos", - unicode = unicode, - code = "DrawDominoH(" & decimal i & "," & decimal j & ");", - width = 16, - height = 8, - ] ; - unicode := unicode + 1 ; - endfor ; - endfor ; - - %D and the vertical range: - - save unicode ; numeric unicode ; unicode := 127075 ; - - for i=0 upto 6 : - for j=0 upto 6 : - lmt_registerglyph [ - category = "dominos", - unicode = unicode, - code = "DrawDominoV(" & decimal i & "," & decimal j & ");", - width = 8, - height = 16, - ] ; - unicode := unicode + 1 ; - endfor ; - endfor ; - - %D Now we're done at the \METAFUN\ end. - -\stopMPcalculation - -%D We predefine two features: - -\definefontfeature - [dominos:white] - [default] - [metapost={category=dominos}] - -\definefontfeature - [dominos:black] - [default] - [metapost={category=dominos,color=black}] - -\definefontfeature - [dominos:digits] - [dominos:digits=yes] - -%D This last feature is yet to be defined. We could deal with the invalid -%D dominos with some substitution trickery but let's keep it simple. - -\startluacode - - local ligatures = { } - local unicode = 127025 - - for i=0x30,0x36 do - for j=0x30,0x36 do - ligatures[unicode] = { i, j } - unicode = unicode + 1 ; - end - end - - fonts.handlers.otf.addfeature("dominos:digits", { - type = "ligature", - order = { "dominos:digits" }, - nocheck = true, - data = ligatures, - } ) - -\stopluacode - -\continueifinputfile{meta-imp-gamesymbols.mkxl} - -\starttext - - \definefont[DominoW][Serif*dominos:white] - \definefont[DominoB][Serif*dominos:black] - \definefont[DominoD][Serif*dominos:white,dominos:digits] - - \startTEXpage[offset=3pt] - \DominoW - \char"1F043\quad 🀱\quad - \char"1F052\quad 🀲\quad - \char"1F038\quad 🀳\quad - \darkgreen\char"1F049\quad \char"1F07B\quad - \DominoB - \char"1F087\quad - \char"1F088\quad - \char"1F089\quad - \DominoD - \darkred 12\quad56\quad64% - \stopTEXpage - - \definefont[DiceN][Serif*dice:normal] - \definefont[DiceR][Serif*dice:reverse] - \definefont[DiceD][Serif*dice:normal,dice:digits] - - \startTEXpage[offset=3pt] - \DiceN - \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% - \DiceN - \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% - \DiceD - \darkblue 2\quad5\quad3\quad0 - \stopTEXpage - -\stoptext diff --git a/tex/context/base/mkiv/meta-imp-symbols.mkxl b/tex/context/base/mkiv/meta-imp-symbols.mkxl deleted file mode 100644 index f88fd6f87..000000000 --- a/tex/context/base/mkiv/meta-imp-symbols.mkxl +++ /dev/null @@ -1,99 +0,0 @@ -%D \module -%D [ file=meta-imp-symbols, -%D version=2019.10.01, -%D title=\METAPOST\ Graphics, -%D subtitle=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 is an (experimental) prelude to more. - -\startMPcalculation{simplefun} - - pen SymbolPen ; SymbolPen := pencircle scaled 1/4 ; - - vardef SymbolBullet = fill unitcircle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x2022 • - vardef SymbolDash = draw (origin--right) scaled 3 shifted (1.5,3.0) withpen SymbolPen scaled 2 enddef ; % 0x2013 – - vardef SymbolTriangle = draw unittriangle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25B6 ⊳ - vardef SymbolCircle = fill unitcircle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x2218 ∘ - vardef SymbolSquare = draw unitsquare scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25A1 □ - vardef SymbolDiamond = draw unitdiamond scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x22C4 ⋄ - vardef SymbolBlackTriangle = fillup unittriangle scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25B6 ▶ - vardef SymbolBlackSquare = fillup unitsquare scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25A0 ■ - vardef SymbolBlackDiamond = fillup unitdiamond scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25C6 ◆ - - vardef SymbolNotDef = - draw center unitcircle - scaled 3 - shifted (1.5,1.5) - withpen SymbolPen scaled 4 - enddef ; - - vardef SymbolStar = % 0x22C6 % ⋆ - SymbolNotDef - enddef ; - - vardef SymbolCheckmark = % 0x2713 ✓ - SymbolNotDef - enddef ; - - vardef SymbolAsterisk = % 0x2217 ∗ - SymbolNotDef - enddef ; - - % We could set code directly to the meaning of the macro. - - lmt_registerglyphs [ - name = "symbols", - units = 10, - usecolor = true, - width = 6, - height = 6, - depth = 0, - code = "SymbolNotDef ;", - ] ; - - lmt_registerglyph [ category = "symbols", unicode = "0x2022", code = "SymbolBullet ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x2013", code = "SymbolDash ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x22C6" ] ; % , code = "SymbolStar ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x22B3", code = "SymbolTriangle ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x2218", code = "SymbolCircle ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x25A1", code = "SymbolSquare ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x22C4", code = "SymbolDiamond ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x2713" ] ; % , code = "SymbolCheckmark ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x2217" ] ; % , code = "SymbolAsterisk ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x25B6", code = "SymbolBlackTriangle ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x25A0", code = "SymbolBlackSquare ;" ] ; - lmt_registerglyph [ category = "symbols", unicode = "0x25C6", code = "SymbolBlackDiamond ;" ] ; - -\stopMPcalculation - -\continueifinputfile{meta-imp-symbols.mkxl} - -\usemodule[article-basic] \setupbodyfont[pagella] - -\starttext - -\definefontfeature[metasymbols][metapost=symbols] - -\definefont[MyFont] [Serif*default,metasymbols sa 1] - -Some metasymbols: - -\startitem {\MyFont • □ ◆}\quad Regular rendering. \stopitem -\startitem {\MyFont\red • □ ◆}\quad Rendering with color. \stopitem -\startitem {\MyFont\blue\showglyphs • □ ◆}\quad Idem but with boundingboxes shown. \stopitem - -And some more: - -\startlines - • – ⋆ ⊳ ∘ □ ⋄ ✓ ∗ ▶ ■ ◆ - {\MyFont • – ⋆ ⊳ ∘ □ ⋄ ✓ ∗ ▶ ■ ◆} -\stoplines - -\stoptext diff --git a/tex/context/base/mkiv/meta-imp-threesix.mkxl b/tex/context/base/mkiv/meta-imp-threesix.mkxl deleted file mode 100644 index 56a400b45..000000000 --- a/tex/context/base/mkiv/meta-imp-threesix.mkxl +++ /dev/null @@ -1,246 +0,0 @@ -%D \module -%D [ file=meta-imp-threesix, -%D version=2019.00.00, -%D title=\METAPOST\ Graphics, -%D subtitle=Don Knuths ThreeSix font, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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 design of the font is if course by Don Knuth and can be found in facs9b.ps. I -%D wish I was clever enough to understand all the good stuff in there. - -\startluacode - local unpack = unpack - local concat = table.concat - local gsub, gmatch, utfbyte = string.gsub, string.gmatch, utf.byte - - local font36 = { - ["0"] = [[00111100 01111110 11000011 11000011 11000011 11000011 01111110 00111100]], - ["1"] = [[00011100 11111100 11101100 00001100 00001100 00001100 11111111 11111111]], - ["2"] = [[00111110 01110011 01110011 00000011 00001110 00111000 11110001 11111111]], - ["3"] = [[01111110 01100110 00000110 00111100 00000110 11100111 11100111 01111110]], - ["4"] = [[00001110 00011110 00110110 01100110 11111111 11111111 00000110 00001110]], - ["5"] = [[01111110 01111110 01000000 01111100 01000111 00000011 11000111 11111110]], - ["6"] = [[01111110 01100110 11000000 11011100 11100110 11000011 01100011 01111110]], - ["7"] = [[11111111 11111111 10000111 10001110 00011100 00011100 00011100 00011100]], - ["8"] = [[01111110 01100110 01100110 00111100 11000011 11000011 11000011 01111110]], - ["9"] = [[01111110 11000110 11000011 01100111 00111011 00000011 01100110 01111110]], - ["A"] = [[000110000 000111000 001111100 001101100 011001110 011111110 010000110 111100111]], - ["B"] = [[1111100 1110110 0110110 0111100 0110011 0110011 1110011 1111100]], - ["C"] = [[01111101 11110011 11100001 11100001 11100000 11100000 11100001 01111110]], - ["D"] = [[11111100 11100010 01100011 01100011 01100011 01100011 11100010 11111100]], - ["E"] = [[1111111 1110001 0110101 0111100 0110100 0110001 1110001 1111111]], - ["F"] = [[11111111 11100001 01100101 01111100 01100100 01100000 11111000 11111000]], - ["G"] = [[01111010 11100110 11100010 11100000 11100111 11100010 11100010 01111100]], - ["H"] = [[11100111 11100111 01000010 01111110 01000010 01000010 11100111 11100111]], - ["I"] = [[1111111 1111111 0011000 0011000 0011000 0011000 1111111 1111111]], - ["J"] = [[01111111 01111111 00000110 00000110 11110110 01100110 01100110 00111100]], - ["K"] = [[11101110 11100100 01101000 01110000 01111000 01101100 11100110 11101111]], - ["L"] = [[111111000 111111000 011000000 011000000 011000000 011000011 111000011 111111111]], - ["M"] = [[1100000011 1110000111 0111111110 0100110010 0100110010 0100000010 1100000011 1100000011]], - ["N"] = [[11000011 11100011 01110010 01111010 01011110 01001110 11100110 11100010]], - ["O"] = [[01111110 11000011 11000011 11000011 11000011 11000011 11000011 01111110]], - ["P"] = [[11111110 11100011 01100011 01111110 01100000 01100000 11111000 11111000]], - ["Q"] = [[01111100 11000110 11000110 11000110 11000110 11001110 11000110 01111101]], - ["R"] = [[11111100 11100110 01100110 01111100 01101000 01100100 11100010 11100111]], - ["S"] = [[01111110 11100001 11100001 01111000 00011110 10000111 11000011 10111110]], - ["T"] = [[1111111111 1100110011 1100110011 0000110000 0000110000 0000110000 0001111000 0001111000]], - ["U"] = [[111101111 111101111 011000010 011000010 011000010 011000010 011000010 001111100]], - ["V"] = [[11111000111 11111000111 01110000010 00110000100 00111000100 00011001000 00001101000 00001110000]], - ["W"] = [[111000000111 111000000111 110000000010 011000000100 011001000100 001101101000 001101101000 000110110000]], - ["X"] = [[1111001110 1111000110 0001101000 0000110000 0000110000 0001011000 0110001111 0111001111]], - ["Y"] = [[111100011 111100011 011000010 001110100 000111000 000011000 001111110 001111110]], - ["Z"] = [[11111111 10000111 00001110 00011100 00111000 01110000 11100001 11111111]], - } - - local f_code = string.formatters["ThreeSix(%s);"] - local replace = { ["0"] = "N;", ["1"] = "Y;", [" "] = "L;" } - - local function remap(str) - -- permit abundant spacing (bonus) - str = gsub(str,"%s+", " ") - -- remap what we got to macro calls - str = gsub(str,".",replace) - -- return the result - return str - end - - function MP.registerthreesix(name) - fonts.dropins.registerglyphs { - name = name, - units = 12, - usecolor = true, - preamble = "InitializeThreeSix;", - } - for u, v in table.sortedhash(font36) do - local data = remap(v) - local ny = 8 - local nx = ((#v + 1) // ny) - 1 - local height = ny * 1.1 - 0.1 - local width = nx * 1.1 - 0.1 - fonts.dropins.registerglyph { - category = name, - unicode = utfbyte(u), - width = width, - height = height, - code = f_code(data), - } - end - end - MP.registerthreesix("fontthreesix") -\stopluacode - -\startMPcalculation{simplefun} - def InitializeThreeSix = - save Y, N, L, S ; - save shape, fillcolor, mypen, random, threesixpen, spread, hoffset ; - string shape, fillcolor, mypen ; boolean random ; pen threesixpen ; - shape := getparameterdefault "mpsfont" "shape" "circle" ; - random := hasoption "mpsfont" "random" "true" ; - fillcolor := getparameterdefault "mpsfont" "color" "" ; - mypen := getparameterdefault "mpsfont" "pen" "" ; - spread := getparameterdefault "mpsfont" "spread" 0 ; - hoffset := 12 * spread / 2 ; - threesixpen := pencircle - if mypen = "fancy" : - xscaled 1/20 yscaled 2/20 rotated 45 - else : - scaled 1/20 - fi ; - if shape == "square" : - def S = - unitsquare if random : randomized 1/10 fi - shifted (nx,ny) - enddef ; - elseif shape = "diamond" : - def S = - unitdiamond if random : randomized 1/10 fi - shifted (nx,ny) - enddef ; - else : - def S = - unitcircle if random : randomizedcontrols 1/20 fi - shifted (nx,ny) - enddef ; - fi ; - if fillcolor = "" : - def N = - nx := nx + dx ; - draw S ; - enddef ; - else : - def N = - nx := nx + dx ; - draw S withcolor "lightgray" ; - enddef ; - fi ; - if fillcolor = "random" : - def Y = - nx := nx + dx ; - fillup S withcolor white randomized (2/3,2/3,2/3) ; - enddef ; - elseif fillcolor = "" : - def Y = - nx := nx + dx ; - fillup S ; - enddef ; - else : - def Y = - nx := nx + dx ; - fillup S withcolor fillcolor ; - enddef ; - fi ; - def L = - nx := - dx ; - ny := ny + dy ; - enddef ; - enddef ; - - vardef ThreeSix (text code) = - save dx, dy, nx, ny ; - dx := 11/10 ; - dy := - 11/10 ; - nx := - dx ; - ny := 0 ; - pickup threesixpen ; - draw image (code) shifted (hoffset,-ny) ; - enddef ; -\stopMPcalculation - -\definefontfeature % black and white, with some spread - [fontthreesix] - [default] - [metapost=fontthreesix] - -\definefontfeature % color, with some spread - [fontthreesix-tweak] - [default] - [metapost={category=fontthreesix,spread=.1}] - -\definefontfeature % color, with some spread - [fontthreesix-color] - [default] - [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1}] - -\definefontfeature % color, tight - [fontthreesix-initial] - [metapost={category=fontthreesix,color=random,shape=circle}] % units? - -\definefont[DEKFontA][Serif*fontthreesix] -\definefont[DEKFontB][Serif*fontthreesix-color] -\definefont[DEKFontC][Serif*fontthreesix-initial] -\definefont[DEKFontD][Serif*fontthreesix-tweak] - -\continueifinputfile{meta-imp-threesix.mkxl} - -\starttext - -\definefontfeature % color, with some spread - [fontthreesix-color] - [default] - [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1,random=yes}] - -\definefont[DEKFontA][Serif*fontthreesix-color @ 200pt] -\definefont[DEKFontB][Serif*fontthreesix-color @ 60pt] - -% Or course: - -\startTEXpage - \DEKFontA TEX -\stopTEXpage - -\startTEXpage - \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX -\stopTEXpage - -% One of the \CONTEXT\ 2020 posters (inspired by NewYork State AC's press -% conferences as these keywords apply quite well to the audience of the -% meeting): - -% \startTEXpage[align={lohi,middle,nothyphenated},offset=20pt] -% \offinterlineskip \vskip10pt -% \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX \vskip60pt -% \DEKFontB TOUGH \vskip20pt -% SMART \vskip20pt -% UNITED \vskip20pt -% DISCIPLINED \vskip20pt -% LOVING \vskip10pt -% \stopTEXpage - -\startpagemakeup - \setupalign[middle,nothyphenated] - \offinterlineskip \vfil\vfil - \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX \vfil\vfil\vfil - \DEKFontB TOUGH \vfil - SMART \vfil - UNITED \vfil - DISCIPLINED \vfil - LOVING \vfil -\stoppagemakeup - -\stoptext diff --git a/tex/context/base/mkiv/meta-ini.mkxl b/tex/context/base/mkiv/meta-ini.mkxl deleted file mode 100644 index 3e1c54d53..000000000 --- a/tex/context/base/mkiv/meta-ini.mkxl +++ /dev/null @@ -1,1385 +0,0 @@ -%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. - -%D Some lmtx upgrading work needs to be done here. - -% 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}{} - -\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{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 - -%D The next command is, of course, dedicated to Mojca, who needs it for gnuplot. -%D Anyway, the whole multiple engine mechanism is to keep her gnuplot from -%D interfering. - -\permanent\tolerant\protected\def\startMPdefinitions#=#:#2\stopMPdefinitions - {\let\m_meta_saved_instance\currentMPinstance - \edef\currentMPinstance{#1}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \gtoksapp\t_meta_definitions{#2}% - \let\currentMPinstance\m_meta_saved_instance} - -\permanent\let\stopMPdefinitions\relax - -\permanent\tolerant\protected\def\startMPextensions#=#:#2\stopMPextensions % we could use buffers instead - {\clf_setmpextensions{#1}{#2}} - -\permanent\let\stopMPextensions\relax - -\permanent\protected\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled - {\gtoksapp\t_meta_initializations{#1}} - -\permanent\let\stopMPinitializations\relax - -\permanent\tolerant\protected\def\startMPinclusions[#1]#*#=#:#3\stopMPinclusions - {\let\m_meta_saved_instance\currentMPinstance % \pushmacro - \edef\currentMPinstance{#2}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \iftok{#1}{+}\else - \global\t_meta_inclusions\emptytoks - \fi - \gtoksapp\t_meta_inclusions{#3}% - \let\currentMPinstance\m_meta_saved_instance} % \popmacro - -\permanent\let\stopMPinclusions\relax - -% The next was broken since we added instances so it will go away! - -\permanent\tolerant\protected\def\MPinclusions[#1]#:#*#=#:#*#=% - {\let\m_meta_saved_instance\currentMPinstance - \iftok{#1}{+}\else - \global\t_meta_inclusions\emptytoks - \fi - \ifparameter#3\or - \edef\currentMPinstance{#2}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \gtoksapp\t_meta_inclusions{#3}% - \else - \let\currentMPinstance\defaultMPinstance - \gtoksapp\t_meta_inclusions{#2}% - \fi - \let\currentMPinstance\m_meta_saved_instance} - -% so far - -\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 - -\permanent\protected\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} - -\protected\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance :: - {\edef\currentMPgraphicname{#2}% - \ifempty\currentMPgraphicname - \edef\currentMPgraphicname{#1}% - \let\currentMPinstance\defaultMPinstance - \orelse\ifcsname\??mpdefinitions#1\endcsname - \edef\currentMPinstance{#1}% - \else - \let\currentMPinstance\defaultMPinstance - \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[minifun] [\s!format=minifun,\s!extensions=\v!yes,\s!initializations=\v!yes] -\defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] -\defineMPinstance[lessfun] [\s!format=metafun] -\defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double] -\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[simplefun] [\s!format=metafun,\c!method=\s!double] % maybe use minifun - -%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} - -\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 - \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}% - \ifempty\p_setups \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 - {\pushMPboundingbox - \setbox\b_meta_graphic\hpack\bgroup} - -\let\meta_relocate_graphic\relax % experimental hook - -\def\meta_process_graphic_stop - {\egroup - \meta_place_graphic - \meta_relocate_graphic - \popMPboundingbox} - -\protected\def\meta_process_graphic_instance#1% - {\edef\currentMPinstance{#1}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \edef\currentMPformat{\MPinstanceparameter\s!format}% - \meta_process_graphic} - -\protected\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}% - namespace {\??graphicvariable\currentmpvariableclass:}% - \relax}% - \meta_process_graphic_stop - \meta_stop_current_graphic} - -\let\meta_process_graphic_figure_start\relax -\let\meta_process_graphic_figure_stop \relax - -\permanent\protected\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages - {\begingroup - \let\normal_meta_process_graphic_start\meta_process_graphic_start - \let\normal_meta_process_graphic_stop \meta_process_graphic_stop - \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} - -%D Calling up previously defined graphics. - -% \def\includeMPgraphic#1% gets expanded ! -% {\ifcsname\??mpgraphic#1\endcsname -% \csname\??mpgraphic#1\endcsname ; % ; is safeguard -% \fi} -% -% \protected\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: - -\permanent\def\includeMPgraphic#1% gets expanded ! - {\ifcsname\??mpgraphic#1\endcsname - \doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard - \fi} - -\let\meta_enable_include\relax - -%D Drawings (stepwise built): - -\newif\ifMPdrawingdone \MPdrawingdonefalse - -\permanent\protected\def\finalizeMPdrawing - {\MPdrawingdonetrue} - -\let\MPdrawingdata\empty - -\permanent\protected\def\resetMPdrawing - {\glet\MPdrawingdata\empty - \global\MPdrawingdonefalse} - -\permanent\protected\def\pushMPdrawing - {\globalpushmacro\MPdrawingdata - \glet\MPdrawingdata\empty} - -\permanent\protected\def\popMPdrawing - {\globalpopmacro\MPdrawingdata} - -\permanent\protected\def\getMPdrawing - {\ifMPdrawingdone - \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed? - \fi} - -\permanent\tolerant\def\startMPdrawing[#1]% todo: use pickup #: - {\meta_start_drawing#1} - -\def\meta_start_drawing#1#2\stopMPdrawing - {\relax - \bgroup - \meta_enable_include - \doifelse{#1}{-} - {\xdef\MPdrawingdata{\MPdrawingdata\detokenize{#2}}}% - {\xdef\MPdrawingdata{\MPdrawingdata#2}}% - \egroup} - -\permanent\let\stopMPdrawing\relax - -\permanent\def\MPdrawing#1% - {\relax - \bgroup - \meta_enable_include - \xdef\MPdrawingdata{\MPdrawingdata#1}% - \egroup} - -\permanent\protected\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less - {\setgvalue{\??mpclip#1}{#2}} - -\permanent\let\stopMPclip\relax - -\protected\def\meta_grab_clip_path#1#2#3% - {\begingroup - \d_overlay_width #2\relax - \d_overlay_height#3\relax - \edef\width {\the\d_overlay_width \space}% - \edef\height{\the\d_overlay_height\space}% - \edef\currentMPclip{#1}% - \ifcsname\??mpclip\currentMPclip\endcsname - \meta_grab_clip_path_yes - \else - \meta_grab_clip_path_nop - \fi - \endgroup} - -\def\meta_grab_clip_path_yes - {\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}% - width \d_overlay_width - height \d_overlay_height - \relax}% - \meta_stop_current_graphic} - -\def\meta_grab_clip_path_nop - {\clf_mpsetclippath - width \d_overlay_width - height \d_overlay_height - \relax} - -%D Since we want labels to follow the document settings, we also set the font -%D related variables. - -\permanent\protected\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 - -%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 background and buttons, -%D the need for passing settings arises. By (mis|)|using the local prefix that -%D belongs to \type {\framed}, we get a rather natural interface to backgrounds. To -%D prevent conflicts, we will use the \type {-} in \METAPOST\ specific variables, -%D 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 - -%D Currently the inheritance of backgrounds does not work and we might drop it -%D 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 ... - -\permanent\tolerant\protected\def\setupMPvariables[#1]#*[#2]% - {\ifarguments - \or - \getrawparameters[\??graphicvariable:][#1]% - \else - \getrawparameters[\??graphicvariable#1:][#2]% - \fi} - -\permanent\tolerant\protected\def\presetMPvariable[#1]#*[#2=#3]% - {\ifcsname\??graphicvariable#1:#2\endcsname \else - \setvalue{\??graphicvariable#1:#2}{#3}% - \fi} - -\permanent\def\MPrawvar#1#2% no checking - {\begincsname\??graphicvariable#1:#2\endcsname} - -\permanent\def\MPvariable#1% todo: could be a framed chain - {\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname} - -\permanent\tolerant\protected\def\useMPvariables[#1]#*[#2]% - {\edef\currentmpvariableclass{#1}% - \meta_prepare_variables{#2}} - -\protected\def\meta_prepare_variables#1% - {\processcommalist[#1]\meta_prepare_variable} - -\protected\def\meta_prepare_variable#1% - {\edef\m_meta_current_variable_template - {\??graphicvariable\currentmpvariableclass:#1}% - \edef\m_meta_current_variable - {\begincsname\m_meta_current_variable_template\endcsname}% - \ifempty\m_meta_current_variable - \expandafter\meta_prepare_variable_nop - \else - \expandafter\meta_prepare_variable_yes - \fi} - -\protected\def\meta_prepare_instance_variables - {\expandafter\processcommalist\expandafter[\m_meta_instance_variables]\meta_prepare_instance_variable} - -\protected\def\meta_prepare_instance_variable#1% - {\edef\m_meta_current_variable_template - {\??graphicvariable\currentmpvariableclass:#1}% - \edef\m_meta_current_variable - {\ifcsname\m_meta_current_variable_template\endcsname - \lastnamedcs - \else - \begincsname\??graphicvariable\currentMPgraphicname:#1\endcsname - \fi}% - \ifempty\m_meta_current_variable - \expandafter\meta_prepare_variable_nop - \else - \expandafter\meta_prepare_variable_yes - \fi} - -\def\meta_prepare_variable_nop - {\expandafter\letcsname\m_meta_current_variable_template\endcsname\meta_prepare_variable_default} - -\def\meta_prepare_variable_color % we use the attribute so we dont' go through namedcolor (why not) - {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\MPcolor\m_meta_current_variable}} - -\def\meta_prepare_variable_number - {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\number\m_meta_current_variable}}% also accepts 0.number - -\def\meta_prepare_variable_dimension - {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}} - -\def\meta_prepare_variable_yes - {\ifchkdim\m_meta_current_variable\or - \meta_prepare_variable_dimension - \orelse\ifchknum\m_meta_current_variable\or - \meta_prepare_variable_number - \else - \doifelsecolor\m_meta_current_variable - \meta_prepare_variable_color - \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 to use graphics that -%D adapt themselves. The next \METAPOST\ kind of graphic is both unique and reused -%D when possible. -%D -%D \starttyping -%D \defineoverlay[example][\uniqueMPgraphic{test}] -%D -%D \startuniqueMPgraphic {test} -%D draw OverlayBox ; -%D \stopuniqueMPgraphic -%D -%D \startuniqueMPgraphic {test} -%D draw OverlayBox ; -%D \stopuniqueMPgraphic -%D \stoptyping - -% todo: frozen or not? - -\def\overlaystamp % watch the \MPcolor, since colors can be redefined - {\the\d_overlay_width :% - \the\d_overlay_height :% - \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 in determining the -%D uniqueness. In the next macro, the second, optional, argument is used to -%D guarantee the 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 convenient use in overlay -%D definitions, we use \type {{}} 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? - -\protected\def\meta_obey_box_depth - {\setbox\b_meta_graphic\hpack\bgroup - \raise\MPlly\box\b_meta_graphic - \egroup} - -\protected\def\meta_ignore_box_depth - {\normalexpanded - {\meta_obey_box_depth % hence the \protected - \wd\b_meta_graphic\the\wd\b_meta_graphic - \ht\b_meta_graphic\the\ht\b_meta_graphic - \dp\b_meta_graphic\the\dp\b_meta_graphic}} - -\protected\def\meta_obey_box_origin - {\setbox\b_meta_graphic\hpack\bgroup - \kern\MPllx\raise\MPlly\box\b_meta_graphic - \egroup} - -\permanent\protected\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth} -\permanent\protected\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth} -\permanent\protected\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin} -\permanent\protected\def\normalMPboxdepth{\let\meta_relocate_box\relax} - -\let\meta_relocate_box\relax - -\protected\def\meta_place_graphic % the converter also displaces so in fact we revert - {\meta_relocate_box - \box\b_meta_graphic} - -\protected\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens - {\MPllx#2\MPlly#3\MPurx#4\MPury#5% - \hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent - -\protected\def\meta_use_box - {\setunreferencedobject{MP}} - -\def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although, - {\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 - \lastnamedcs - \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}}% - \csname\??mpgraphic\overlaystamp:#1\endcsname\empty - \fi - \endgroup} - -% todo: we partially expand - -\protected\def\startuniqueMPgraphic - {\dodoublegroupempty\meta_start_unique_graphic} - -\permanent\let\stopuniqueMPgraphic\relax - -\def\meta_start_unique_graphic#1% - {\normalexpanded{\meta_start_unique_graphic_indeed{#1}}} - -\permanent\protected\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic - {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}} - -\permanent\tolerant\protected\def\uniqueMPgraphic#=#*#=% - {\meta_begin_graphic_group{#1}% - \setupMPvariables[#1][#2]% - \begincsname\??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}% - \ifempty\m_meta_instance_variables \else - \meta_prepare_instance_variables - \fi - \meta_enable_include % redundant - \meta_process_graphic{#3}% - \endgroup} - -\permanent\protected\def\startuseMPgraphic % todo, modernize - {\dodoublegroupempty\meta_start_use_graphic} - -\permanent\let\stopuseMPgraphic\relax - -\def\meta_start_use_graphic#1% - {\normalexpanded{\meta_start_use_graphic_indeed{#1}}} - -\protected\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic - {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} - -\permanent\protected\def\startusableMPgraphic % redundant but handy % todo, modernize - {\dodoublegroupempty\meta_start_usable_graphic} - -\permanent\let\stopusableMPgraphic\relax - -\def\meta_start_usable_graphic#1% - {\normalexpanded{\meta_start_usable_graphic_indeed{#1}}} - -\protected\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic - {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} - -\def\meta_handle_reusable_graphic#1#2#3% - {\begingroup - \edef\currentmpvariableclass{#1}% - \edef\m_meta_instance_variables{#2}% - \ifempty\m_meta_instance_variables \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} - -\permanent\protected\def\startreusableMPgraphic % todo, modernize - {\dodoublegroupempty\meta_start_reusable_graphic} - -\permanent\let\stopreusableMPgraphic\relax - -\def\meta_start_reusable_graphic#1% - {\normalexpanded{\meta_start_reusable_graphic_indeed{#1}}} - -\protected\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic - {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}} - -\permanent\tolerant\protected\def\useMPgraphic#=#*#=% - {\meta_begin_graphic_group{#1}% - \ifcsname\??mpgraphic#1\endcsname - \edef\usedMPgraphicname{#1}% - \orelse\ifcsname\??mpgraphic\currentMPgraphicname\endcsname - \let\usedMPgraphicname\currentMPgraphicname - \else - \let\usedMPgraphicname\empty - \fi - \ifempty\usedMPgraphicname - % message - \else - \doifsomething{#2}{\setupMPvariables[\usedMPgraphicname][#2]}% - \csname\??mpgraphic\usedMPgraphicname\endcsname - \fi - \meta_end_graphic_group} - -\aliased\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed -\aliased\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed - -%D \macros -%D {startuniqueMPpagegraphic,uniqueMPpagegraphic} -%D -%D Experimental. - -\def\m_meta_page_prefix{\doifelseoddpage oe} - -\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} - -\permanent\tolerant\protected\def\startuniqueMPpagegraphic % todo the modern way - {\dodoublegroupempty\meta_start_unique_page_graphic} - -\permanent\let\stopuniqueMPpagegraphic\relax - -\def\meta_start_unique_page_graphic#1% - {\normalexpanded{\meta_start_unique_page_graphic_indeed{#1}}} - -\protected\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage - {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state - \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined - -\permanent\tolerant\protected\def\uniqueMPpagegraphic#=#=% - {\meta_begin_graphic_group{#1}% - \let\overlaystamp\overlaypagestamp - \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 -%D Since we need to feed \METAPOST\ with expanded dimensions, we introduce a -%D dedicated expansion engine. We redefine \type {\extendMPoverlaystamp} to - -\permanent\protected\def\extendMPoverlaystamp#1% - {\processcommalist[#1]\meta_extend_overlay_stamp} - -\def\meta_extend_overlay_stamp#1% - {\meta_prepare_instance_variable{#1}% - \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}} - -\permanent\protected\def\getMPdata {\clf_getMPdata} - \let\rawMPdata \clf_getMPdata % we need frozen at the lua end - -\permanent\protected\def\getMPstored{\clf_getMPstored} - \let\rawMPstored \clf_getMPstored % we need frozen at the lua end - -%D We need this trick because we need to make sure that the tex scanner sees -%D newlines and does not quit. Also, we do need to flush the buffer under a normal -%D catcode regime in order to expand embedded tex macros. As usual with buffers, -%D \type {#1} can be a list. - -\permanent\tolerant\protected\def\processMPbuffer[#1]% - {\meta_begin_graphic_group{#1}% - \meta_process_graphic{\clf_feedback{\currentMPgraphicname}}% - \meta_end_graphic_group} - -\permanent\tolerant\protected\def\runMPbuffer[#1]% - {\startnointerference\meta_process_buffer[#1]\stopnointerference} - -%D \macros -%D {startMPenvironment, resetMPenvironment} -%D -%D In order to synchronize the main \TEX\ run and the runs local to \METAPOST, -%D environments can be passed. - -\protected\def\startMPenvironment - {\begingroup - \catcode\endoflineasciicode\ignorecatcode - \meta_start_environment} - -\tolerant\def\meta_start_environment[#1]#:#2\stopMPenvironment - {\endgroup - \edef\m_meta_option{#1} - \ifx\m_meta_option\s!reset - \resetMPenvironment % reset mp toks - \orelse\ifx\m_meta_option\v!global - #2% % use in main doc too - \orelse\ifx\m_meta_option\!!plustoken - #2% % use in main doc too - \fi - \clf_mptexset{\detokenize{#2}}} - -\permanent\let\stopMPenvironment\relax - -\protected\def\resetMPenvironment - {\clf_mptexreset} - -\protected\def\useMPenvironmentbuffer[#1]% - {\clf_mptexsetfrombuffer{#1}} - -%D This command takes \type {[reset]} as optional 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: - -\permanent\tolerant\protected\def\startMPcode#=#:#2\stopMPcode - {\begingroup - \edef\currentMPinstance{#1}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \let\currentMPgraphicname\empty - \edef\currentMPformat{\MPinstanceparameter\s!format}% - \meta_enable_include - \meta_process_graphic{#2}% - \endgroup} - -\permanent\let\stopMPcode\relax - -%D This one is not optimized because it's only used for small snippets, if it -%D is used at all. - -\permanent\tolerant\protected\def\MPcode#=#:#*#=% - {\ifparameter#1\or - \meta_begin_graphic_group{#1}% - \meta_enable_include - \meta_process_graphic{#2}% - \meta_end_graphic_group - \else - \let\currentMPinstance\defaultMPinstance - \meta_enable_include - \meta_process_graphic{#1}% - \fi} - -% 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 - -\permanent\protected\def\useMPrun#1#2% name n - {\begingroup - \def\MPaskedfigure{#2}% - \normalexpanded{\useMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}% - \endgroup} - -\permanent\tolerant\protected\def\startMPrun#=#:#2\stopMPrun - {\normalexpanded{\startuseMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}#2\stopuseMPgraphic} - -\permanent\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: - -\permanent\protected\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} - -\permanent\protected\def\setMPtext#1#2{\dodoglobal\edefcsname\??mptext#1\endcsname{\detokenize{#2}}} -\permanent \def\MPtext #1{\begincsname\??mptext#1\endcsname\empty} -\permanent \def\MPstring #1{"\begincsname\??mptext#1\endcsname\empty"} -\permanent \def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex} - -%D In order to communicate conveniently with the \TEX\ engine, we introduce some -%D typesetting variables. - -% \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 - -%D A dirty trick, ** in colo-ini.lua (mpcolor). We cannot use a vardef, because -%D that fails with spot colors. - -\startMPinitializations - def OverlayLineColor=\ifempty\overlaylinecolor black \else\MPcolor{\overlaylinecolor} \fi enddef; - def OverlayColor =\ifempty\overlaycolor 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 \c_attr_colormodel -% \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 - \enforced\let\#\letterhash - \enforced\let\_\letterunderscore - \enforced\let\&\letterampersand - \enforced\let\{\letteropenbrace - \enforced\let\}\letterclosebrace -\to \everyMPgraphic - -%D \macros -%D {PDFMPformoffset} -%D -%D In \PDF, forms are clipped and therefore we have to take precautions to get this -%D right. Since this is related to objects, we use the same offset as used there. - -\def\PDFMPformoffset{\objectoffset} - -\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 don't use the normal figure -%D inclusion macros any longer. - -\appendtoks - \externalfigurepostprocessors\emptytoks % safeguard -\to \everyinsertMPfile - -%D We also take care of disabling fancy figure features, that can terribly interfere -%D when dealing with symbols, background graphics and running (postponed) graphics. -%D You won't believe me if I tell you what funny side effects can occur. One took me -%D over a day to uncover when processing the screen version of the \METAFUN\ manual. - -\permanent\def\doifelseMPgraphic#1% - {\ifcsname\??mpgraphic #1\endcsname\expandafter\firstoftwoarguments \orelse - \ifcsname\??mpgraphic o:#1\endcsname\expandafter\firstoftwoarguments \orelse - \ifcsname\??mpgraphic e:#1\endcsname\expandafter\firstoftwoarguments \else - \expandafter\secondoftwoarguments\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 something changed. Here is -%D 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 - -\permanent\protected\def\startstaticMPfigure#1#2\stopstaticMPfigure - {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic} - -\permanent\tolerant\protected\def\startstaticMPgraphic#=#:#=#:#3\stopstaticMPgraphic - {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic} - -\permanent\let\stopstaticMPfigure \relax -\permanent\let\stopstaticMPgraphic\relax - -\permanent\tolerant\protected\def\usestaticMPfigure[#1]#*[#2]% - {\ifarguments\or - \reuseMPgraphic{\??mpstaticgraphic#1}% - \else - \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% - \fi} - -%D Goody for preventing overflows: - -%frozen\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} -\permanent\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax} - -%D There is no way to distinguish the black color that you get when you issue a -%D \type {draw} without color specification from a color that has an explicit black -%D specification unless you set the variable \type {defaultcolormodel} to 1. -%D Hoewever, in that case you cannot distinguish that draw from one with a \type -%D {withoutcolor} specification. This means that we have to provide multiple -%D variants of inheritance. -%D -%D In any case we need to tell the converter what the inherited color is to start -%D with. Case~3 is kind of unpredictable as it closely relates to the order in which -%D paths are flushed. If you want to inherit automatically from the surrounding, you -%D can best stick to 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 - \c_attr_colormodel\space - \c_attr_color\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 - -\permanent\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar -\permanent\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number -\permanent\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset - -\prependtoks \clf_mppushvariables \to \everybeforepagebody -\appendtoks \clf_mppopvariables \to \everyafterpagebody - -\let\MPpushvariables\clf_mppushvariables -\let\MPpopvariables \clf_mppopvariables - -%D We also provide an outputless run: - -\permanent\tolerant\protected\def\startMPcalculation#=#:#2\stopMPcalculation - {\begingroup - \setbox\nextbox\hpack\bgroup - \edef\currentMPinstance{#1}% - \ifempty\currentMPinstance - \let\currentMPinstance\defaultMPinstance - \fi - \let\currentMPgraphicname\empty - \edef\currentMPformat{\MPinstanceparameter\s!format}% - \meta_enable_include - \meta_process_graphic{#2;draw origin}% - \egroup - \endgroup} - -\permanent\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 {global} we -%D get the outer color automatically. If you change this setting, you should do it -%D grouped in order not to make other graphics 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}}% - \ifempty\p_mpy \else - \let\MPdataMPYfile\p_mpy - \clf_registermpyfile{\p_mpy}% - \fi -\to \everysetupMPgraphics - -%D Some more helpers (see \type {meta-grd.mkiv} for an example of usage): - -\permanent\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty} -\permanent\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty} -\permanent\def\MPspar#1#2{"#1#2"} - -%D Done. - -\protect \endinput diff --git a/tex/context/base/mkiv/meta-mac.mkxl b/tex/context/base/mkiv/meta-mac.mkxl deleted file mode 100644 index 76b7396ae..000000000 --- a/tex/context/base/mkiv/meta-mac.mkxl +++ /dev/null @@ -1,45 +0,0 @@ -%D \module -%D [ file=meta-scn, -%D version=2019.07.19, -%D title=\METAPOST\ Graphics, -%D subtitle=LMTX 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. - -\unprotect - -\permanent\protected\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}} -\permanent\protected\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}} -\permanent\protected\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}} - -\permanent\tolerant\protected\def\useMPmacro[#1]#*[#2]#*[#3]% - {\ifarguments\or - \let\currentMPinstance\defaultMPinstance - \meta_enable_include - \meta_process_graphic{lmt_#1;}% - \or - \doifelseassignment{#2} - {\let\currentMPinstance\defaultMPinstance - \meta_enable_include - \clf_lmt_parameters_preset{#1}[#2]% - \meta_process_graphic{lmt_#1;}% - \clf_lmt_parameters_reset{#1}}% - {\meta_begin_graphic_group{#1}% - \meta_enable_include - \meta_process_graphic{lmt_#1;}% - \meta_end_graphic_group}% - \or - \meta_begin_graphic_group{#1}% - \meta_enable_include - \clf_lmt_parameters_preset{#2}[#3]% - \meta_process_graphic{lmt_#2;}% - \clf_lmt_parameters_reset{#2}% - \meta_end_graphic_group - \fi} - -\protect diff --git a/tex/context/base/mkiv/meta-pag.mkxl b/tex/context/base/mkiv/meta-pag.mkxl deleted file mode 100644 index 86de11eeb..000000000 --- a/tex/context/base/mkiv/meta-pag.mkxl +++ /dev/null @@ -1,26 +0,0 @@ -%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 {core-mps} file, later changed -%D into \type {meta-ini}, but keeping them separate is cleaner. In the meantime not -%D that much is left here. - -\writestatus{loading}{MetaPost Graphics / Page Data Management} - -\unprotect - -\prependtoks - \calculatereducedvsizes % bah, this is really needed -\to \everyMPgraphic - -\protect \endinput diff --git a/tex/context/base/mkiv/mlib-cnt.lmt b/tex/context/base/mkiv/mlib-cnt.lmt deleted file mode 100644 index 667384ed7..000000000 --- a/tex/context/base/mkiv/mlib-cnt.lmt +++ /dev/null @@ -1,2022 +0,0 @@ -if not modules then modules = { } end modules ['mlib-cnt'] = { - version = 1.001, - optimize = true, - 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", -} - --- The only useful reference that I could find about this topic is in wikipedia: --- --- https://en.wikipedia.org/wiki/Marching_squares --- --- I derived the edge code from: --- --- https://physiology.arizona.edu/people/secomb/contours --- --- and also here: --- --- https://github.com/secomb/GreensV4 --- --- which has the banner: --- --- TWS, November 1989. Converted to C September 2007. Revised February 2009. --- --- and has a liberal licence. I optimized the code so that it runs a bit faster in Lua and --- there's probably more room for optimization (I tried several variants). For instance I --- don't use that many tables because access is costly. We don't have a compiler that does --- some optimizing (even then the c code can probably be made more efficient). --- --- We often have the same node so it's cheaper to reuse the wsp tables and reconstruct --- the point in the path then to alias the original point. We can be more clever: --- straighten, but it's more work so maybe I will do that later; for now I only added --- a test for equality. There are some experiments in this file too and not all might --- work. It's a playground for me. --- --- The code is meant for metafun so it is not general purpose. The bitmap variant is --- relatively fast and bitmaps compress well. When all is settled I might make a couple --- of helpers in C for this purpose but not now. --- --- I removed optimization code (more aggressive flattening and such because it didn't really --- pay off now that we use combined paths with just line segments. I also moved some other --- code to a experimental copy. So we now only have the bare helpers needed here. - --- Todo: look into zero case (lavel 1) for shapes ... omiting the background calculation --- speeds up quite a bit. - -local next, type, tostring = next, type, tostring -local round, abs, min, max, floor = math.round, math.abs, math.min, math.max, math.floor -local concat, move = table.concat, table.move - -local bor = bit32.bor -- it's really time to ditch support for luajit - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming -local elapsedtime = statistics.elapsedtime - -local formatters = string.formatters -local setmetatableindex = table.setmetatableindex -local sortedkeys = table.sortedkeys -local sequenced = table.sequenced - -local metapost = metapost or { } -local mp = mp or { } - -local getparameterset = metapost.getparameterset - -local mpflush = mp.flush -local mpcolor = mp.color -local mpstring = mp.string -local mpdraw = mp.draw -local mpfill = mp.fill -local mpflatten = mp.flatten - -local report = logs.reporter("mfun contour") - -local version = 0.007 - --- we iterate using integers so that we get a better behaviour at zero - -local f_function_n = formatters [ [[ - local math = math - local round = math.round - %s - return function(data,nx,ny,nxmin,nxmax,xstep,nymin,nymax,ystep) - local sx = nxmin - for mx=1,nx do - local dx = data[mx] - local x = sx * xstep - local sy = nymin - for my=1,ny do - local y = sy * ystep - dx[my] = %s - sy = sy + 1 - end - sx = sx + 1 - end - return 0 - end -]] ] - -local f_function_y = formatters [ [[ - local math = math - local round = math.round - local nan = NaN - local inf = math.huge - %s - return function(data,nx,ny,nxmin,nxmax,xstep,nymin,nymax,ystep,dnan,dinf,report) - local sx = nxmin - local er = 0 - for mx=nxmin,nxmax do - local dx = data[mx] - local x = sx * xstep - local sy = nymin - for my=nymin,nymax do - local y = sy * ystep - local n = %s - if n == nan then - er = er + 1 - if er < 10 then - report("nan at (%s,%s)",x,y) - end - n = dnan - elseif n == inf then - er = er + 1 - if er < 10 then - report("inf at (%s,%s)",x,y) - end - n = dinf - end - dx[my] = n - sy = sy + 1 - end - sx = sx + 1 - end - return er - end -]] ] - -local f_color = formatters [ [[ - local math = math - local min = math.min - local max = math.max - local n = %s - local minz = %s - local maxz = %s - - local color_value = 0 - local color_step = mp.lmt_color_functions.step - local color_shade = mp.lmt_color_functions.shade - - local function step(...) - return color_step(color_value,n,...) - end - local function shade(...) - return color_shade(color_value,n,...) - end - local function lin(l) - return l/n - end - %s - return function(l) - color_value = l - return %s - end -]] ] - -local inbetween = attributes and attributes.colors.helpers.inbetween - -mp.lmt_color_functions = { - step = function(l,n,r,g,b,s) - if not s then - s = 1 - end - local f = l / n - local r = s * 1.5 - 4 * abs(f-r) - local g = s * 1.5 - 4 * abs(f-g) - local b = s * 1.5 - 4 * abs(f-b) - return min(max(r,0),1), min(max(g,0),1), min(max(b,0),1) - end, - shade = function(l,n,one,two) - local f = l / n - local r = inbetween(one,two,1,f) - local g = inbetween(one,two,2,f) - local b = inbetween(one,two,3,f) - return min(max(r,0),1), min(max(g,0),1), min(max(b,0),1) - end, -} - -local f_box = formatters [ [[draw rawtexbox("contour",%s) xysized (%s,%s) ;]] ] - -local n_box = 0 - --- todo: remove old one, so we need to store old hashes - -local nofcontours = 0 - --- We don't want cosmetics like axis and labels to trigger a calculation, --- especially a slow one. - -local hashfields = { - "xmin", "xmax", "xstep", "ymin", "ymax", "ystep", - "levels", "colors", "level", "preamble", "function", "functions", "color", "values", - "background", "foreground", "linewidth", "backgroundcolor", "linecolor", -} - -local function prepare(p) - local h = { } - for i=1,#hashfields do - local f = hashfields[i] - h[f] = p[f] - end - local hash = md5.HEX(sequenced(h)) - local name = formatters["%s-m-c-%03i.lua"](tex.jobname,nofcontours) - return name, hash -end - -local function getcache(p) - local cache = p.cache - if cache then - local name, hash = prepare(p) - local data = table.load(name) - if data and data.hash == hash and data.version == version then - p.result = data - return true - else - return false, hash, name - end - end - return false, nil, nil -end - -local function setcache(p) - local result = p.result - local name = result.name - if name then - if result.bitmap then - result.bitmap = nil - else - result.data = nil - end - result.color = nil - result.action = nil - result.cached = nil - io.savedata(name, table.fastserialize(result)) - else - os.remove((prepare(p))) - end -end - -function mp.lmt_contours_start() - - starttiming("lmt_contours") - - nofcontours = nofcontours + 1 - - local p = getparameterset() - - local xmin = p.xmin - local xmax = p.xmax - local ymin = p.ymin - local ymax = p.ymax - local xstep = p.xstep - local ystep = p.ystep - local levels = p.levels - local colors = p.colors - local nx = 0 - local ny = 0 - local means = setmetatableindex("number") - local values = setmetatableindex("number") - local data = setmetatableindex("table") - local minmean = false - local maxmean = false - - local cached, hash, name = getcache(p) - - local function setcolors(preamble,levels,minz,maxz,color,nofvalues) - if colors then - local function f(k) - return #colors[1] == 1 and 0 or { 0, 0, 0 } - end - setmetatableindex(colors, function(t,k) - local v = f(k) - t[k] = v - return v - end) - local c = { } - local n = 1 - for i=1,nofvalues do - c[i] = colors[n] - n = n + 1 - end - return c, f - else - local tcolor = f_color(levels,minz,maxz,preamble,color) - local colors = { } - local fcolor = load(tcolor) - if type(fcolor) ~= "function" then - report("error in color function, case %i: %s",1,color) - fcolor = false - else - fcolor = fcolor() - if type(fcolor) ~= "function" then - report("error in color function, case %i: %s",2,color) - fcolor = false - end - end - if not fcolor then - local color_step = mp.lmt_color_functions.step - fcolor = function(l) - return color_step(l,levels,0.25,0.50,0.75) - end - end - for i=1,nofvalues do - colors[i] = { fcolor(i) } - end - if attributes.colors.model == "cmyk" then - for i=1,#colors do - local c = colors[i] - colors[i] = { 1 - c[1], 1 - c[2], 1 - c[3], 0 } - end - end - return colors, fcolor - end - end - - if cached then - local result = p.result - local colors, color = setcolors( - p.preamble, - p.levels, - result.minz, - result.maxz, - p.color, - result.nofvalues - ) - result.color = color - result.colors = colors - result.cached = true - return - end - - local functioncode = p["function"] - local functionrange = p.range - local functionlist = functionrange and p.functions - local preamble = p.preamble - - if xstep == 0 then xstep = (xmax - xmin)/100 end - if ystep == 0 then ystep = (ymax - ymin)/100 end - - local nxmin = round(xmin/xstep) - local nxmax = round(xmax/xstep) - local nymin = round(ymin/ystep) - local nymax = round(ymax/ystep) - local nx = nxmax - nxmin + 1 - local ny = nymax - nymin + 1 - - local function executed(data,code) - local fcode = p.check and f_function_y or f_function_n - fcode = fcode(preamble,code) - fcode = load(fcode) - if type(fcode) == "function" then - fcode = fcode() - end - if type(fcode) == "function" then - local er = fcode( - data, nx, ny, - nxmin, nxmax, xstep, - nymin, nymax, ystep, - p.defaultnan, p.defaultinf, report - ) - if er > 0 then - report("%i errors in: %s",er,code) - end - return true - else - return false -- fatal error - end - end - - -- for i=1,nx do - -- data[i] = lua.newtable(ny,0) - -- end - - if functionlist then - - local datalist = { } - local minr = functionrange[1] - local maxr = functionrange[2] or minr - local size = #functionlist - - for l=1,size do - - local func = setmetatableindex("table") - if not executed(func,functionlist[l]) then - report("error in executing function %i from functionlist",l) - return - end - - local bit = l -- + 1 - - if l == 1 then - for i=1,nx do - local di = data[i] - local fi = func[i] - for j=1,ny do - local f = fi[j] - if f >= minr and f <= maxr then - di[j] = bit - else - di[j] = 0 - end - end - end - else - for i=1,nx do - local di = data[i] - local fi = func[i] - for j=1,ny do - local f = fi[j] - if f >= minr and f <= maxr then - di[j] = bor(di[j],bit) - end - end - end - end - - end - - -- we can simplify the value mess below - - elseif functioncode then - - if not executed(data,functioncode) then - report("error in executing function") - return -- fatal error - end - - else - - report("no valid function(s)") - return -- fatal error - - end - - minz = data[1][1] - maxz = minz - - for i=1,nx do - local d = data[i] - for j=1,ny do - local v = d[j] - if v < minz then - minz = v - elseif v > maxz then - maxz = v - end - end - end - - if functionlist then - - for i=minz,maxz do - values[i] = i - end - - levels = maxz - - minmean = minz - maxmean = maxz - - else - - local snap = (maxz - minz + 1) / levels - - for i=1,nx do - local d = data[i] - for j=1,ny do - local dj = d[j] - local v = round((dj - minz) / snap) - values[v] = values[v] + 1 - means [v] = means [v] + dj - d[j] = v - end - end - - local list = sortedkeys(values) - local count = values - local remap = { } - - values = { } - - for i=1,#list do - local v = list[i] - local m = means[v] / count[v] - remap [v] = i - values[i] = m - if not minmean then - minmean = m - maxmean = m - elseif m < minmean then - minmean = m - elseif m > maxmean then - maxmean = m - end - end - - for i=1,nx do - local d = data[i] - for j=1,ny do - d[j] = remap[d[j]] - end - end - - end - - -- due to rounding we have values + 1 so we can have a floor, ceil, round - -- option as well as levels -1 - - local nofvalues = #values - - local colors = setcolors( - p.preamble,levels,minz,maxz,p.color,nofvalues - ) - - p.result = { - version = version, - values = values, - nofvalues = nofvalues, - minz = minz, - maxz = maxz, - minmean = minmean, - maxmean = maxmean, - data = data, - color = color, - nx = nx, - ny = ny, - colors = colors, - name = name, - hash = hash, - islist = functionlist and true or false, - } - - report("index %i, nx %i, ny %i, levels %i", nofcontours, nx, ny, nofvalues) -end - -function mp.lmt_contours_stop() - local p = getparameterset() - local e = stoptiming("lmt_contours") - setcache(p) - p.result = nil - local f = p["function"] - local l = p.functions - report("index %i, %0.3f seconds for: %s", - nofcontours, e, "[ " .. concat(l or { f } ," ] [ ") .. " ]" - ) -end - -function mp.lmt_contours_bitmap_set() - local p = getparameterset() - local result = p.result - - local values = result.values - local nofvalues = result.nofvalues - local rawdata = result.data - local nx = result.nx - local ny = result.ny - local colors = result.colors - local depth = #colors[1] -- == 3 and "rgb" or "gray" - - -- i need to figure out this offset of + 1 - - local bitmap = graphics.bitmaps.new( - nx, ny, - (depth == 3 and "rgb") or (depth == 4 and "cmyk") or "gray", - 1, false, true - ) - - local palette = bitmap.index or { } -- has to start at 0 - local data = bitmap.data - local p = 0 - - if depth == 3 or depth == 4 then - for i=1,nofvalues do - local c = colors[i] - local r = round((c[1] or 0) * 255) - local g = round((c[2] or 0) * 255) - local b = round((c[3] or 0) * 255) - local k = depth == 4 and round((c[4] or 0) * 255) or nil - palette[p] = { - (r > 255 and 255) or (r < 0 and 0) or r, - (g > 255 and 255) or (g < 0 and 0) or g, - (b > 255 and 255) or (b < 0 and 0) or b, - k - } - p = p + 1 - end - else - for i=1,nofvalues do - local s = colors[i][1] - local s = round((s or 0) * 255) - palette[p] = ( - (s > 255 and 255) or (s < 0 and 0) or s - ) - p = p + 1 - end - end - - -- As (1,1) is the left top corner so we need to flip of we start in - -- the left bottom (we cannot loop reverse because we want a properly - -- indexed table. - - local k = 0 - for y=ny,1,-1 do - k = k + 1 - local d = data[k] - for x=1,nx do - d[x] = rawdata[x][y] - 1 - end - end - - result.bitmap = bitmap -end - -function mp.lmt_contours_bitmap_get() - local p = getparameterset() - local result = p.result - local bitmap = result.bitmap - local box = nodes.hpack(graphics.bitmaps.flush(bitmap)) - n_box = n_box + 1 - nodes.boxes.savenode("contour",tostring(n_box),box) - return f_box(n_box,bitmap.xsize,bitmap.ysize) -end - -function mp.lmt_contours_cleanup() - nodes.boxes.reset("contour") - n_box = 0 -end - -function mp.lmt_contours_edge_set() - local p = getparameterset() - local result = p.result - - if result.cached then return end - - local values = result.values - local nofvalues = result.nofvalues - local data = result.data - local nx = result.nx - local ny = result.ny - - local xmin = p.xmin - local xmax = p.xmax - local ymin = p.ymin - local ymax = p.ymax - local xstep = p.xstep - local ystep = p.ystep - - local wsp = { } - local edges = { } - - for value=1,nofvalues do - - local iwsp = 0 - local di = data[1] - local dc - local edge = { } - local e = 0 - -- the next loop is fast - for i=1,nx do - local di1 = data[i+1] - local dij = di[1] - local d = dij - value - local dij1 - for j=1,ny do - if j < ny then - dij1 = di[j+1] - dc = dij1 - value - if (d >= 0 and dc < 0) or (d < 0 and dc >= 0) then - iwsp = iwsp + 1 - local y = (d * (j+1) - dc * j) / (d - dc) - if i == 1 then - wsp[iwsp] = { i, y, 0, (i + (j-1)*nx) } - elseif i == nx then - wsp[iwsp] = { i, y, (i - 1 + (j-1)*nx), 0 } - else - local jx = (i + (j-1)*nx) - wsp[iwsp] = { i, y, jx - 1, jx } - end - end - end - if i < nx then - local dc = di1[j] - value - if (d >= 0 and dc < 0) or (d < 0 and dc >= 0) then - iwsp = iwsp + 1 - local x = (d * (i+1) - dc * i) / (d - dc) - if j == 1 then - wsp[iwsp] = { x, j, 0, (i + (j-1)*nx) } - elseif j == ny then - wsp[iwsp] = { x, j, (i + (j-2)*nx), 0 } - else - local jx = i + (j-1)*nx - wsp[iwsp] = { x, j, jx - nx, jx } - end - end - end - dij = dij1 - d = dc - end - di = di1 - end - -- the next loop takes time - for i=1,iwsp do - local wspi = wsp[i] - for isq=3,4 do - local nsq = wspi[isq] - if nsq ~= 0 then - local px = wspi[1] - local py = wspi[2] - local p = { px, py } - local pn = 2 - wspi[isq] = 0 - while true do - for ii=1,iwsp do - local w = wsp[ii] - local n1 = w[3] - local n2 = w[4] - if n1 == nsq then - local x = w[1] - local y = w[2] - if x ~= px or y ~= py then - pn = pn + 1 - p[pn] = x - pn = pn + 1 - p[pn] = y - px = x - py = y - end - nsq = n2 - w[3] = 0 - w[4] = 0 - if nsq == 0 then - if pn == 1 then - pn = pn + 1 - p[pn] = w - end - goto flush - end - elseif n2 == nsq then - local x = w[1] - local y = w[2] - if x ~= px or y ~= py then - pn = pn + 1 - p[pn] = x - pn = pn + 1 - p[pn] = y - px = x - py = y - end - nsq = n1 - w[3] = 0 - w[4] = 0 - if nsq == 0 then - goto flush - end - end - end - end - ::flush:: - e = e + 1 - edge[e] = p - if mpflatten then - mpflatten(p) - end - end - end - end - - - edges[value] = edge - - end - - result.edges = edges - -end - -function mp.lmt_contours_shade_set(edgetoo) - local p = getparameterset() - local result = p.result - - if result.cached then return end - - local values = result.values - local nofvalues = result.nofvalues - local data = result.data - local nx = result.nx - local ny = result.ny - local color = result.color - - local edges = setmetatableindex("table") - local shades = setmetatableindex("table") - - local sqtype = setmetatableindex("table") - - local xspoly = { 0, 0, 0, 0, 0, 0 } - local yspoly = { 0, 0, 0, 0, 0, 0 } - local xrpoly = { } - local yrpoly = { } - - local xrpoly = { } -- lua.newtable(2000,0) - local yrpoly = { } -- lua.newtable(2000,0) - - -- for i=1,2000 do - -- xrpoly[i] = 0 - -- yrpoly[i] = 0 - -- end - - -- Unlike a c compiler lua will not optimize loops to run in parallel so we expand - -- some of the loops and make sure we don't calculate when not needed. Not that nice - -- but not that bad either. Maybe I should just write this from scratch. - --- local i = 0 --- local j = 0 - - -- Analyze each rectangle separately. Overwrite lower colors - - -- Unrolling the loops and copying code and using constants is faster and doesn't - -- produce much more code in the end, also because we then can leave out the not - -- seen branches. One can argue about the foundit2* blobs but by stepwise optimizing - -- this is the result. - - shades[1] = { { 0, 0, nx - 1, 0, nx - 1, ny - 1, 0, ny - 1 } } - edges [1] = { { } } - - -- this is way too slow ... i must have messed up some loop .. what is this with value 1 - - for value=1,nofvalues do --- for value=2,nofvalues do - - local edge = { } - local nofe = 0 - local shade = { } - local nofs = 0 - - for i=1,nx-1 do - local s = sqtype[i] - for j=1,ny-1 do - s[j] = 0 - end - end - - local nrp = 0 - - local function addedge(a,b,c,d) - nofe = nofe + 1 edge[nofe] = a - nofe = nofe + 1 edge[nofe] = b - nofe = nofe + 1 edge[nofe] = c - nofe = nofe + 1 edge[nofe] = d - end - while true do - -- search for a square of type 0 with >= 1 corner above contour level - local i - local j - local d0 = data[1] - local d1 = data[2] - for ii=1,nx do - local s = sqtype[ii] - for jj=1,ny do - if s[jj] == 0 then - if d0[jj] > value then i = ii j = jj goto foundit end - if d1[jj] > value then i = ii j = jj goto foundit end - local j1 = jj + 1 - if d1[j1] > value then i = ii j = jj goto foundit end - if d0[j1] > value then i = ii j = jj goto foundit end - end - end - d0 = d1 - d1 = data[ii+1] - end - break - ::foundit:: - -- initialize r-polygon (nrp seems to be 1 or 2) - nrp = nrp + 1 - - local first = true - local nrpoly = 0 - local nspoly = 0 - local nrpm = -nrp - -- this is the main loop - while true do - -- search for a square of type -nrp - if first then - first = false - if sqtype[i][j] == 0 then -- true anyway - goto foundit1 - end - end - for ii=1,nx do - local s = sqtype[ii] - for jj=1,ny do - if s[jj] == nrpm then - i = ii - j = jj - goto foundit1 - end - end - end - break - ::foundit1:: - while true do - - -- search current then neighboring squares for square type 0, with a corner in common with current square above contour level - - -- top/bottom ... a bit cheating here - - local i_l, i_c, i_r -- i left current right - local j_b, j_c, j_t -- j bottom current top - - local i_n = i + 1 -- i next (right) - local j_n = j + 1 -- j next (top) - - local i_p = i - 1 -- i previous (bottom) - local j_p = j - 1 -- j previous (right) - - local d_c = data[i] - local d_r = data[i_n] - - local sq - - i_c = i ; j_c = j ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then - if d_c[j_c] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit21 end - if d_c[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit22 end - if d_r[j_c] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit23 end - if d_r[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit24 end - end end - - i_c = i_n ; j_c = j ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then - if d_r[j_c] > value then i_l = i ; i_r = i_n + 1 ; j_b = j_p ; j_t = j_n ; d_c = d_r ; d_r = data[i_r] ; goto foundit21 end - if d_r[j_n] > value then i_l = i ; i_r = i_n + 1 ; j_b = j_p ; j_t = j_n ; d_c = d_r ; d_r = data[i_r] ; goto foundit22 end - end end - - i_c = i ; j_c = j_n ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then - if d_c[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j ; j_t = j_n + 1 ; goto foundit21 end - if d_r[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j ; j_t = j_n + 1 ; goto foundit23 end - end end - - i_c = i_p ; j_c = j ; if i_c > 0 and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then - if d_c[j_c] > value then i_l = i_p - 1 ; i_r = i ; j_b = j_p ; j_t = j_n ; d_r = d_c ; d_c = data[i_p] ; goto foundit23 end - if d_c[j_n] > value then i_l = i_p - 1 ; i_r = i ; j_b = j_p ; j_t = j_n ; d_r = d_c ; d_c = data[i_p] ; goto foundit24 end - end end - - i_c = i ; j_c = j_p ; if i < nx and j_c > 0 then sq = sqtype[i_c] if sq[j_c] == 0 then - if d_c[j] > value then i_l = i_p ; i_r = i_n ; j_b = j_p - 1 ; j_t = j ; goto foundit22 end - if d_r[j] > value then i_l = i_p ; i_r = i_n ; j_b = j_p - 1 ; j_t = j ; goto foundit24 end - end end - - -- not found - - sqtype[i][j] = nrp - - break - - -- define s-polygon for found square (i_c,j_c) - may have up to 6 sides - - ::foundit21:: -- 1 2 3 4 - - sq[j_c] = nrpm - - xspoly[1] = i_l ; yspoly[1] = j_b - xspoly[2] = i_c ; yspoly[2] = j_b - if d_r[j_c] > value then -- dd2 - xspoly[3] = i_c ; yspoly[3] = j_c - if d_r[j_t] > value then -- dd3 - xspoly[4] = i_l ; yspoly[4] = j_c - if d_c[j_t] > value then -- dd4 - nspoly = 4 - else - xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 - end - elseif d_c[j_t] > value then -- dd4 - xspoly[4] = i_c ; yspoly[4] = j_c ; - xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 - else - xspoly[4] = i_l ; yspoly[4] = j_c ; nspoly = 4 - if edgetoo then addedge(i_c, j_c, i_l, j_c) end - end - elseif d_r[j_t] > value then -- dd3 - xspoly[3] = i_c ; yspoly[3] = j_b - xspoly[4] = i_c ; yspoly[4] = j_c - if d_c[j_t] > value then -- dd4 - xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 - else - xspoly[5] = i_l ; yspoly[5] = j_c ; - xspoly[6] = i_l ; yspoly[6] = j_c ; nspoly = 6 - end - elseif d_c[j_t] > value then -- dd4 - if edgetoo then addedge(i_c, j_b, i_c, j_c) end - xspoly[3] = i_c ; yspoly[3] = j_c ; - xspoly[4] = i_l ; yspoly[4] = j_c ; nspoly = 4 - else - if edgetoo then addedge(i_c, j_b, i_l, j_c) end - xspoly[3] = i_l ; yspoly[3] = j_c ; nspoly = 3 - end - goto done - - ::foundit22:: -- 4 1 2 3 - - sq[j_c] = nrpm - - xspoly[1] = i_l ; yspoly[1] = j_c - xspoly[2] = i_l ; yspoly[2] = j_b - if d_c[j_c] > value then -- dd2 - xspoly[3] = i_c ; yspoly[3] = j_b - if d_r[j_c] > value then -- dd3 - xspoly[4] = i_c ; yspoly[4] = j_c - if d_r[j_t] > value then -- dd4 - nspoly = 4 - else - xspoly[5] = i_c ; yspoly[5] = j_c ; nspoly = 5 -- suspicious, the same - end - elseif d_r[j_t] > value then -- dd4 - xspoly[4] = i_c ; yspoly[4] = j_b ; - xspoly[5] = i_c ; yspoly[5] = j_c ; nspoly = 5 - else - if edgetoo then addedge(i_c, j_b, i_c, j_c) end - xspoly[4] = i_c ; yspoly[4] = j_c ; nspoly = 4 - end - elseif d_r[j_c] > value then -- dd3 - xspoly[3] = i_l ; yspoly[3] = j_b - xspoly[4] = i_c ; yspoly[4] = j_b - xspoly[5] = i_c ; yspoly[5] = j_c - if d_r[j_t] > value then -- dd4 - nspoly = 5 - else - xspoly[6] = i_c ; yspoly[6] = j_c ; nspoly = 6 - end - elseif d_r[j_t] > value then -- dd4 - if edgetoo then addedge(i_l, j_b, i_c, j_b) end - xspoly[3] = i_c ; yspoly[3] = j_b - xspoly[4] = i_c ; yspoly[4] = j_c ; nspoly = 4 - else - if edgetoo then addedge(i_l, j_b, i_c, j_c) end - xspoly[3] = i_c ; yspoly[3] = j_c ; nspoly = 3 - end - goto done - - ::foundit23:: -- 2 3 4 1 - - sq[j_c] = nrpm - - xspoly[1] = i_c ; yspoly[1] = j_b - xspoly[2] = i_c ; yspoly[2] = j_c - if d_r[j_t] > value then -- dd2 - xspoly[3] = i_l ; yspoly[3] = j_c - if d_c[j_t] > value then -- dd3 - xspoly[4] = i_l ; yspoly[4] = j_b - if d_c[j_c] > value then -- dd4 - nspoly = 4 - else - xspoly[5] = i_l ; yspoly[5] = j_b ; nspoly = 5 - end - elseif d_c[j_c] > value then -- dd4 - xspoly[4] = i_l ; yspoly[4] = j_c - xspoly[5] = i_l ; yspoly[5] = j_b ; nspoly = 5 - else - if edgetoo then addedge(i_l, j_c, i_l, j_b) end - xspoly[4] = i_l ; yspoly[4] = j_b ; nspoly = 4 - end - elseif d_c[j_t] > value then -- dd3 - xspoly[3] = i_c ; yspoly[3] = j_c - xspoly[4] = i_l ; yspoly[4] = j_c - xspoly[5] = i_l ; yspoly[5] = j_b - if d_c[j_c] > value then -- dd4 - nspoly = 5 - else - xspoly[6] = i_l ; yspoly[6] = j_b ; nspoly = 6 - end - elseif d_c[j_c] > value then -- dd4 - if edgetoo then addedge(i_c, j_c, i_l, j_c) end - xspoly[3] = i_l ; yspoly[3] = j_c ; - xspoly[4] = i_l ; yspoly[4] = j_b ; nspoly = 4 - else - if edgetoo then addedge(i_c, j_c, i_l, j_b) end - xspoly[3] = i_l ; yspoly[3] = j_b ; nspoly = 3 - end - goto done - - ::foundit24:: -- 3 4 1 2 - - sq[j_c] = nrpm - - xspoly[1] = i_c ; yspoly[1] = j_c - xspoly[2] = i_l ; yspoly[2] = j_c - if d_c[j_t] > value then -- dd2 - if d_c[j_c] > value then -- dd3 - xspoly[3] = i_l ; yspoly[3] = j_b - xspoly[4] = i_c ; yspoly[4] = j_b - if d_r[j_c] > value then -- dd4 - nspoly = 4 - else - xspoly[5] = i_c ; yspoly[5] = j_b ; nspoly = 5 - end - else - xspoly[3] = i_l ; yspoly[3] = j_b - if d_r[j_c] > value then -- dd4 - - local xv34 = (dd3*i_c-dd4*i_l)/(dd3 - dd4) -- probably i_l - print("4.4 : xv34",xv34,i_c,i_l) - - -- if edgetoo then addedge(i_l, j_b, xv34, j_b) end - xspoly[4] = xv34 ; yspoly[4] = j_b ; - xspoly[5] = i_c ; yspoly[5] = j_b ; nspoly = 5 - else - if edgetoo then addedge(i_l, j_b, i_c, j_b) end - xspoly[4] = i_c ; yspoly[4] = j_b ; nspoly = 4 - end - end - elseif d_c[j_c] > value then -- dd3 - xspoly[3] = i_l ; yspoly[3] = j_b - xspoly[4] = i_l ; yspoly[4] = j_b - xspoly[5] = i_c ; yspoly[5] = j_b - if d_r[j_c] > value then -- dd4 - nspoly = 5 - else - xspoly[6] = i_c ; yspoly[6] = j_b ; nspoly = 6 - end - elseif d_r[j_c] > value then -- dd4 - if edgetoo then addedge(i_l, j_c, i_l, j_b) end - xspoly[3] = i_l ; yspoly[3] = j_b - xspoly[4] = i_c ; yspoly[4] = j_b ; nspoly = 4 - else - if edgetoo then addedge(i_l, j_c, i_c, j_b) end - xspoly[3] = i_c ; yspoly[3] = j_b ; nspoly = 3 - end - -- goto done - - ::done:: - -- combine s-polygon with existing r-polygon, eliminating redundant segments - - if nrpoly == 0 then - -- initiate r-polygon - for i=1,nspoly do - xrpoly[i] = xspoly[i] - yrpoly[i] = yspoly[i] - end - nrpoly = nspoly - else - -- search r-polygon and s-polygon for one side that matches - -- - -- this is a bottleneck ... we keep this variant here but next go for a faster - -- alternative - -- - -- local ispoly, irpoly - -- for r=nrpoly,1,-1 do - -- local r1 - -- for s=1,nspoly do - -- local s1 = s % nspoly + 1 - -- if xrpoly[r] == xspoly[s1] and yrpoly[r] == yspoly[s1] then - -- if not r1 then - -- r1 = r % nrpoly + 1 - -- end - -- if xrpoly[r1] == xspoly[s] and yrpoly[r1] == yspoly[s] then - -- ispoly = s - -- irpoly = r - -- goto foundit3 - -- end - -- end - -- end - -- end - -- - -- local ispoly, irpoly - -- local xr1 = xrpoly[1] - -- local yr1 = yrpoly[1] - -- for r0=nrpoly,1,-1 do - -- for s0=1,nspoly do - -- if xr1 == xspoly[s0] and yr1 == yspoly[s0] then - -- if s0 == nspoly then - -- if xr0 == xspoly[1] and yr0 == yspoly[1] then - -- ispoly = s0 - -- irpoly = r0 - -- goto foundit3 - -- end - -- else - -- local s1 = s0 + 1 - -- if xr0 == xspoly[s1] and yr0 == yspoly[s1] then - -- ispoly = s0 - -- irpoly = r0 - -- goto foundit3 - -- end - -- end - -- end - -- end - -- xr1 = xrpoly[r0] - -- yr1 = yrpoly[r0] - -- end - -- - -- but ... - -- - local minx = xspoly[1] - local miny = yspoly[1] - local maxx = xspoly[1] - local maxy = yspoly[1] - for i=1,nspoly do - local y = yspoly[i] - if y < miny then - miny = y - elseif y > maxy then - maxy = y - end - local x = xspoly[i] - if x < minx then - minx = y - elseif x > maxx then - maxx = x - end - end - -- we can delay accessing y ... - local ispoly, irpoly - local xr1 = xrpoly[1] - local yr1 = yrpoly[1] - for r0=nrpoly,1,-1 do - if xr1 >= minx and xr1 <= maxx and yr1 >= miny and yr1 <= maxy then - local xr0 = xrpoly[r0] - local yr0 = yrpoly[r0] - for s0=1,nspoly do - if xr1 == xspoly[s0] and yr1 == yspoly[s0] then - if s0 == nspoly then - if xr0 == xspoly[1] and yr0 == yspoly[1] then - ispoly = s0 - irpoly = r0 - goto foundit3 - end - else - local s1 = s0 + 1 - if xr0 == xspoly[s1] and yr0 == yspoly[s1] then - ispoly = s0 - irpoly = r0 - goto foundit3 - end - end - end - end - xr1 = xr0 - yr1 = yr0 - else - xr1 = xrpoly[r0] - yr1 = yrpoly[r0] - end - end - -- - goto nomatch3 - ::foundit3:: - local match1 = 0 - local rpoly1 = irpoly + nrpoly - local spoly1 = ispoly - 1 - for i=2,nspoly-1 do - -- search for further matches nearby - local ir = (rpoly1 - i) % nrpoly + 1 - local is = (spoly1 + i) % nspoly + 1 - if xrpoly[ir] == xspoly[is] and yrpoly[ir] == yspoly[is] then - match1 = match1 + 1 - else - break -- goto nomatch1 - end - end - ::nomatch1:: - local match2 = 0 - local rpoly2 = irpoly - 1 - local spoly2 = ispoly + nspoly - for i=2,nspoly-1 do - -- search other way for further matches nearby - local ir = (rpoly2 + i) % nrpoly + 1 - local is = (spoly2 - i) % nspoly + 1 - if xrpoly[ir] == xspoly[is] and yrpoly[ir] == yspoly[is] then - match2 = match2 + 1 - else - break -- goto nomatch2 - end - end - ::nomatch2:: - -- local dnrpoly = nspoly - 2 - 2*match1 - 2*match2 - local dnrpoly = nspoly - 2*(match1 + match2 + 1) - local ispolystart = (ispoly + match1) % nspoly + 1 -- first node of s-polygon to include - local irpolyend = (rpoly1 - match1 - 1) % nrpoly + 1 -- last node of s-polygon to include - if dnrpoly ~= 0 then - local irpolystart = (irpoly + match2) % nrpoly + 1 -- first node of s-polygon to include - if irpolystart > irpolyend then - -- local ispolyend = (spoly1 - match2 + nspoly)%nspoly + 1 -- last node of s-polygon to include - if dnrpoly > 0 then - -- expand the arrays xrpoly and yrpoly - for i=nrpoly,irpolystart,-1 do - local k = i + dnrpoly - xrpoly[k] = xrpoly[i] - yrpoly[k] = yrpoly[i] - end - else -- if dnrpoly < 0 then - -- contract the arrays xrpoly and yrpoly - for i=irpolystart,nrpoly do - local k = i + dnrpoly - xrpoly[k] = xrpoly[i] - yrpoly[k] = yrpoly[i] - end - end - end - nrpoly = nrpoly + dnrpoly - end - if nrpoly < irpolyend then - for i=irpolyend,nrpoly+1,-1 do - -- otherwise these values get lost! - local k = i - nrpoly - xrpoly[k] = xrpoly[i] - yrpoly[k] = yrpoly[i] - end - end - local n = nspoly - 2 - match1 - match2 - if n == 1 then - local irpoly1 = irpolyend % nrpoly + 1 - local ispoly1 = ispolystart % nspoly + 1 - xrpoly[irpoly1] = xspoly[ispoly1] - yrpoly[irpoly1] = yspoly[ispoly1] - elseif n > 0 then - -- often 2 - for i=1,n do - local ii = i - 1 - local ir = (irpolyend + ii) % nrpoly + 1 - local is = (ispolystart + ii) % nspoly + 1 - xrpoly[ir] = xspoly[is] - yrpoly[ir] = yspoly[is] - end - end - ::nomatch3:: - end - end - end - - if nrpoly > 0 then - local t = { } - local n = 0 - for i=1,nrpoly do - n = n + 1 t[n] = xrpoly[i] - n = n + 1 t[n] = yrpoly[i] - end - if mpflatten then - mpflatten(t) -- maybe integrate - end - nofs = nofs + 1 - shade[nofs] = t - -- print(value,nrpoly,#t,#t-nrpoly*2) - end - - end - - edges [value+1] = edge - shades[value+1] = shade --- edges [value] = edge --- shades[value] = shade - end - - result.shades = shades - result.shapes = edges - -end - --- accessors - -function mp.lmt_contours_nx (i) return getparameterset().result.nx end -function mp.lmt_contours_ny (i) return getparameterset().result.ny end - -function mp.lmt_contours_nofvalues() return getparameterset().result.nofvalues end -function mp.lmt_contours_value (i) return getparameterset().result.values[i] end - -function mp.lmt_contours_minz (i) return getparameterset().result.minz end -function mp.lmt_contours_maxz (i) return getparameterset().result.maxz end - -function mp.lmt_contours_minmean (i) return getparameterset().result.minmean end -function mp.lmt_contours_maxmean (i) return getparameterset().result.maxmean end - -function mp.lmt_contours_xrange () local p = getparameterset() mpstring(formatters["x = [%.3N,%.3N] ;"](p.xmin,p.xmax)) end -function mp.lmt_contours_yrange () local p = getparameterset() mpstring(formatters["y = [%.3N,%.3N] ;"](p.ymin,p.ymax)) end - -function mp.lmt_contours_format() - local p = getparameterset() - return mpstring(p.result.islist and "@i" or p.zformat or p.format) -end - -function mp.lmt_contours_function() - local p = getparameterset() - return mpstring(p.result.islist and concat(p["functions"], ", ") or p["function"]) -end - -function mp.lmt_contours_range() - local p = getparameterset() - local r = p.result.islist and p.range - if not r or #r == 0 then - return mpstring("") - elseif #r == 1 then - return mpstring(r[1]) - else - return mpstring(formatters["z = [%s,%s]"](r[1],r[2])) - end -end - -function mp.lmt_contours_edge_paths(value) - mpdraw(getparameterset().result.edges[value],true) - mpflush() -end - -function mp.lmt_contours_shape_paths(value) - mpdraw(getparameterset().result.shapes[value],false) - mpflush() -end - -function mp.lmt_contours_shade_paths(value) - mpfill(getparameterset().result.shades[value],true) - mpflush() -end - -function mp.lmt_contours_color(value) - local p = getparameterset() - local color = p.result.colors[value] - if color then - mpcolor(color) - end -end - --- The next code is based on the wikipedia page. It was a bit tedius job to define the --- coordinates but hupefully I made no errors. I rendered all shapes independently and --- tripple checked bit one never knows ... - --- maybe some day write from scatch, like this (axis are swapped): - -local d = 1/2 - -local paths = { - { 0, d, d, 0 }, - { 1, d, d, 0 }, - { 0, d, 1, d }, - { 1, d, d, 1 }, - { 0, d, d, 1, d, 0, 1, d }, -- saddle - { d, 0, d, 1 }, - { 0, d, d, 1 }, - { 0, d, d, 1 }, - { d, 0, d, 1 }, - { 0, d, d, 0, 1, d, d, 1 }, -- saddle - { 1, d, d, 1 }, - { 0, d, 1, d }, - { d, 0, 1, d }, - { d, 0, 0, d }, -} - -local function whatever(data,nx,ny,threshold) - local edges = { } - local e = 0 - local d0 = data[1] - for j=1,ny-1 do - local d1 = data[j+1] - local k = j + 1 - for i=1,nx-1 do - local v = 0 - local l = i + 1 - local c1 = d0[i] - if c1 < threshold then - v = v + 8 - end - local c2 = d0[l] - if c2 < threshold then - v = v + 4 - end - local c3 = d1[l] - if c3 < threshold then - v = v + 2 - end - local c4 = d1[i] - if c4 < threshold then - v = v + 1 - end - if v > 0 and v < 15 then - if v == 5 or v == 10 then - local a = (c1 + c2 + c3 + c4) / 4 - if a < threshold then - v = v == 5 and 10 or 5 - end - local p = paths[v] - e = e + 1 edges[e] = k - p[2] - e = e + 1 edges[e] = i + p[1] - e = e + 1 edges[e] = k - p[4] - e = e + 1 edges[e] = i + p[3] - e = e + 1 edges[e] = k - p[6] - e = e + 1 edges[e] = i + p[5] - e = e + 1 edges[e] = k - p[8] - e = e + 1 edges[e] = i + p[7] - else - local p = paths[v] - e = e + 1 edges[e] = k - p[2] - e = e + 1 edges[e] = i + p[1] - e = e + 1 edges[e] = k - p[4] - e = e + 1 edges[e] = i + p[3] - end - end - end - d0 = d1 - end - return edges -end - --- todo: just fetch when needed, no need to cache - -function mp.lmt_contours_edge_set_by_cell() - local p = getparameterset() - local result = p.result - - if result.cached then return end - - local values = result.values - local nofvalues = result.nofvalues - local data = result.data - local nx = result.nx - local ny = result.ny - local lines = { } - result.lines = lines - for value=1,nofvalues do - lines[value] = whatever(data,ny,nx,value) - end -end - -function mp.lmt_contours_edge_get_cell(value) - mpdraw(getparameterset().result.lines[value]) - mpflush() -end - -local singles = { - { d, 0, 0, 0, 0, d }, -- 1 0001 - { d, 0, 0, d }, -- 2 0002 - { 1, d, 1, 0, d, 0 }, -- 3 0010 - { 1, d, 1, 0, 0, 0, 0, d }, -- 4 0011 - { 1, d, 1, 0, d, 0, 0, d }, -- 5 0012 - { 1, d, d, 0 }, -- 6 0020 - { 1, d, d, 0, 0, 0, 0, d }, -- 7 0021 - { 1, d, 0, d }, -- 8 0022 - { d, 1, 1, 1, 1, d }, -- 9 0100 - false, -- 10 0101 - false, -- 11 0102 - { d, 1, 1, 1, 1, 0, d, 0 }, -- 12 0110 - { d, 1, 1, 1, 1, 0, 0, 0, 0, d }, -- 13 0111 - { d, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 14 0112 - { d, 1, 1, 1, 1, d, d, 0 }, -- 15 0120 - { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, -- 16 0121 - { d, 1, 1, 1, 1, d, 0, d }, -- 17 0122 - { d, 1, 1, d }, -- 18 0200 - false, -- 19 0201 - false, -- 20 0202 - { d, 1, 1, d, 1, 0, d, 0 }, -- 21 0210 - { d, 1, 1, d, 1, 0, 0, 0, 0, d }, -- 22 0211 - false, -- 23 0212 - { d, 1, d, 0 }, -- 24 0220 - { d, 1, d, 0, 0, 0, 0, d }, -- 25 0221 - { d, 1, 0, d }, -- 26 0222 - { 0, 1, d, 1, 0, d }, -- 27 1000 - { 0, 1, d, 1, d, 0, 0, 0 }, -- 28 1001 - { 0, 1, d, 1, d, 0, 0, d }, -- 29 1002 - false, -- 30 1010 - { 0, 1, d, 1, 1, d, 1, 0, 0, 0 }, -- 31 1011 - { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, -- 32 1012 - false, -- 33 1020 - { 0, 1, d, 1, 1, d, d, 0, 0, 0 }, -- 34 1021 - { 0, 1, d, 1, 1, d, 0, d }, -- 35 1022 - { 0, 1, 1, 1, 1, d, 0, d }, -- 36 1100 - { 0, 1, 1, 1, 1, d, d, 0, 0, 0 }, -- 37 1101 - { 0, 1, 1, 1, 1, d, d, 0, 0, d }, -- 38 1102 - { 0, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 39 1110 - { 0, 1, 1, 1, 1, 0, 0, 0 }, -- 40 1111 - { 0, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 41 1112 - { 0, 1, 1, 1, 1, d, d, 0, 0, d }, -- 42 1120 - { 0, 1, 1, 1, 1, d, d, 0, 0, 0 }, -- 43 1121 - { 0, 1, 1, 1, 1, d, 0, d }, -- 44 1122 - { 0, 1, d, 1, 1, d, 0, d }, -- 45 1200 - { 0, 1, d, 1, 1, d, d, 0, 0, 0 }, -- 46 1201 - false, -- 47 1202 - { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, -- 48 1210 - { 0, 1, d, 1, 1, d, 1, 0, 0, 0 }, -- 49 1211 - false, -- 50 1212 - { 0, 1, d, 1, d, 0, 0, d }, -- 51 1220 - { 0, 1, d, 1, d, 0, 0, 0 }, -- 52 1221 - { 0, 1, d, 1, 0, d }, -- 53 1222 - { d, 1, 0, d }, -- 54 2000 - { d, 1, d, 0, 0, 0, 0, d }, -- 55 2001 - { d, 1, d, 0 }, -- 56 2002 - false, -- 57 2010 - { d, 1, 1, d, 1, 0, 0, 0, 0, d }, -- 58 2011 - { d, 1, 1, d, 1, 0, d, 0 }, -- 59 2012 - false, -- 60 2020 - false, -- 61 2021 - { d, 1, 1, d }, -- 62 2022 - { d, 1, 1, 1, 1, d, 0, d }, -- 63 2100 - { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, -- 64 2101 - { d, 1, 1, 1, 1, d, d, 0 }, -- 65 2102 - { d, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 66 2110 - { d, 1, 1, 1, 1, 0, 0, 0, 0, d }, -- 67 2111 - { d, 1, 1, 1, 1, 0, d, 0 }, -- 68 2112 - false, -- 69 2120 - false, -- 70 2121 - { d, 1, 1, 1, 1, d }, -- 71 2122 - { 1, d, 0, d }, -- 72 2200 - { 1, d, d, 0, 0, 0, 0, d }, -- 73 2201 - { 1, d, d, 0 }, -- 74 2202 - { 1, d, 1, 0, d, 0, 0, d }, -- 75 2210 - { 1, d, 1, 0, 0, 0, 0, d }, -- 76 2211 - { 1, d, 1, 0, d, 0 }, -- 77 2212 - { d, 0, 0, d }, -- 78 2220 - { 0, d, 0, 0, d, 0 }, -- 79 2221 -} - -local sadles = { - false, false, false, false, false, false, false, false, false, - { { d, 1, 1, 1, 1, d }, { d, 0, 0, 0, 0, d }, { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, false, false, false }, -- 10 0101 - { { d, 1, 1, 1, 1, d }, { d, 0, 0, d }, { d, 1, 1, 1, 1, d, d, 0, 0, d }, false, false, false }, -- 11 0102 - false, false, false, false, false, false, false, - { { d, 1, 1, d }, { d, 0, 0, 0, 0, d }, { d, 1, 1, d, d, 0, 0, 0, 0, d }, false, false, false }, -- 19 0201 - { { d, 1, 1, d }, { d, 0, 0, d }, { d, 1, 1, d, d, 0, 0, d }, false, { d, 1, 0, d }, { 1, d, d, 0 } }, -- 20 0202 - false, false, - { false, false, { d, 1, 1, d, 1, 0, d, 0, 0, d }, false, { d, 1, 0,d, }, { 1, d, 1, 0,d, 0 } }, -- 23 0212 - false, false, false, false, false, false, - { { 0, 1, d, 1, 0, d }, { 1, d, 1, 0, d, 0 }, { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, false, false, false }, -- 30 1010 - false, false, - { { 1, 0, d, 0, 0, d, }, { 1, d, d, 0 }, { 0, 1, d, 1, 1, d, d, 0, 0, d }, false, false, false }, -- 33 1020 - false, false, false, false, false, false, false, false, false, false, false, false, false, - { false, false, { 0,1, d, 1, 1, d, d, 0, 0, d }, false, { 0,1, d, 1, 0, d }, {1, d, d, 0 } }, -- 47 1202 - false, false, - { false, false, { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, false, { 0, 1, d, 1, 0, d }, { 1, d, 1, 0, d, 0 } }, -- 50 1212 - false, false, false, false, false, false, - { { d, 1, 0, d }, { 1, d, 1, 0, 0, d }, { d, 1, 1, d, 1, 0, d, 0, 0, d }, false, false, false }, -- 57 2010 - false, false, - { { d, 1, 0,d }, { 1, d, d, 0 }, { d, 1, 1, d, d, 0, 0, d }, false, { d, 1, 1, d }, { d, 0, 0, d } }, -- 60 2020 - { false, false, { d, 1, 1, d, d, 0, 0, 0, 0, d }, false, { d, 1, 1, d }, { d, 0, 0, 0, 0, d } }, -- 61 2021 - false, false, false, false, false, false, false, - { false, false, { d, 1, 1, 1, 1, d, d, 0, 0, d }, false, { d, 1, 1, 1, 1, d }, { d, 0,0,d } }, -- 69 2120 - { false, false, { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, false, { d, 1, 1, 1, 1, d }, { d, 0, 0, 0, 0, d } }, -- 70 2121 -} - -local function whatever(data,nx,ny,threshold,background) - - if background then - - local llx = 1/2 - local lly = llx - local urx = ny + llx - local ury = nx + lly - - return { { llx, lly, urx, 0, urx, ury, 0, ury } } - - else - - local bands = { } - local b = 0 - - local function band(s,n,x,y) -- simple. no closure so fast - if n == 6 then - return { - x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], - } - elseif n == 8 then - return { - x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], - x - s[ 8], y + s[ 7], - } - elseif n == 10 then - return { - x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], - x - s[ 8], y + s[ 7], x - s[10], y + s[ 9], - } - elseif n == 4 then - return { - x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], - } - else -- 12 - return { - x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], - x - s[ 8], y + s[ 7], x - s[10], y + s[ 9], x - s[12], y + s[11], - } - end - end - - local pp = { } - - local d0 = data[1] - for j=1,ny-1 do - local d1 = data[j+1] - local k = j + 1 - local p = false - for i=1,nx-1 do - local v = 0 - local l = i + 1 - local c1 = d0[i] - if c1 == threshold then - v = v + 27 - elseif c1 > threshold then - v = v + 54 - end - local c2 = d0[l] - if c2 == threshold then - v = v + 9 - elseif c2 > threshold then - v = v + 18 - end - local c3 = d1[l] - if c3 == threshold then - v = v + 3 - elseif c3 > threshold then - v = v + 6 - end - local c4 = d1[i] - if c4 == threshold then - v = v + 1 - elseif c4 > threshold then - v = v + 2 - end - if v > 0 and v < 80 then - if v == 40 then - -- a little optimization: full areas appended horizontally - if p then - p[4] = l -- i + 1 - p[6] = l -- i + 1 - else - -- x-0 y+1 x-1 y+1 x-1 y+0 x-0 y+0 - p = { j, i, j, l, k, l, k, i } - b = b + 1 ; bands[b] = p - end - else - local s = singles[v] - if s then - b = b + 1 ; bands[b] = band(s,#s,k,i) - else - local s = sadles[v] - if s then - local m = (c1 + c2 + c3 + c4) / 4 - if m < threshold then - local s1 = s[1] if s1 then b = b + 1 ; bands[b] = band(s1,#s1,i,j) end - local s2 = s[2] if s2 then b = b + 1 ; bands[b] = band(s2,#s2,i,j) end - elseif m == threshold then - local s3 = s[3] if s3 then b = b + 1 ; bands[b] = band(s3,#s3,i,j) end - local s4 = s[4] if s4 then b = b + 1 ; bands[b] = band(s4,#s4,i,j) end - else - local s5 = s[5] if s5 then b = b + 1 ; bands[b] = band(s5,#s5,i,j) end - local s6 = s[6] if s6 then b = b + 1 ; bands[b] = band(s6,#s6,i,j) end - end - end - end - p = false - end - else - p = false - end - end - d0 = d1 - end - return bands - end -end - -function mp.lmt_contours_edge_set_by_band(value) - local p = getparameterset() - local result = p.result - - if result.cached then return end - - local values = result.values - local nofvalues = result.nofvalues - local data = result.data - local nx = result.nx - local ny = result.ny - local bands = { } - result.bands = bands - for value=1,nofvalues do - bands[value] = whatever(data,ny,nx,value,value == 1) - end -end - -function mp.lmt_contours_edge_get_band(value) - mpfill(getparameterset().result.bands[value],true) - mpflush() -end - --- Because we share some code surface plots also end up here. When working on the --- contour macros by concidence I ran into a 3D plot in --- --- https://staff.science.uva.nl/a.j.p.heck/Courses/mptut.pdf --- --- The code is pure MetaPost and works quite well. With a bit of optimization --- performance is also ok, but in the end a Lua solution is twice as fast and also --- permits some more tweaking at no cost. So, below is an adaptation of an example --- in the mentioned link. It's one of these cases where access to pseudo arrays --- is slowing down MP. - -local sqrt, sin, cos = math.sqrt, math.sin, math.cos - -local f_fill_rgb = formatters["F (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N) ;"] -local f_draw_rgb = formatters["D (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor %.3F ;"] -local f_mesh_rgb = formatters["U (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N) ;"] -local f_fill_cmy = formatters["F (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N,0) ;"] -local f_draw_cmy = formatters["D (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor %.3F ;"] -local f_mesh_cmy = formatters["U (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N,0) ;"] - -local f_function_n = formatters [ [[ - local math = math - local round = math.round - %s - return function(x,y) - return %s - end -]] ] - -local f_function_y = formatters [ [[ - local math = math - local round = math.round - local nan = NaN - local inf = math.huge - local er = 0 - %s - return function(x,y,dnan,dinf,report) - local n = %s - if n == nan then - er = er + 1 - if er < 10 then - report("nan at (%s,%s)",x,y) - end - n = dnan - elseif n == inf then - er = er + 1 - if er < 10 then - report("inf at (%s,%s)",x,y) - end - n = dinf - end - dx[my] = n - sy = sy + 1 - end - return n, er -end -]] ] - -local f_color = formatters [ [[ - local math = math - return function(f) - return %s - end -]] ] - -function mp.lmt_surface_do(specification) - -- - -- The projection and color brightness calculation have been inlined. We also store - -- differently. - -- - -- todo: ignore weird paths - -- - -- The prototype is now converted to use lmt parameter sets. - -- - local p = getparameterset("surface") - -- - local preamble = p.preamble or "" - local code = p.code or "return x + y" - local colorcode = p.color or "return f, f, f" - local linecolor = p.linecolor or 1 - local xmin = p.xmin or -1 - local xmax = p.xmax or 1 - local ymin = p.ymin or -1 - local ymax = p.ymax or 1 - local xstep = p.xstep or .1 - local ystep = p.ystep or .1 - local bf = p.brightness or 100 - local clip = p.clip or false - local lines = p.lines - local ha = p.snap or 0.01 - local hb = 2 * ha - -- - if lines == nil then lines = true end - -- - if xstep == 0 then xstep = (xmax - xmin)/100 end - if ystep == 0 then ystep = (ymax - ymin)/100 end - - local nxmin = round(xmin/xstep) - local nxmax = round(xmax/xstep) - local nymin = round(ymin/ystep) - local nymax = round(ymax/ystep) - local nx = nxmax - nxmin + 1 - local ny = nymax - nymin + 1 - -- - local xvector = p.xvector or { -0.7, -0.7 } - local yvector = p.yvector or { 1, 0 } - local zvector = p.zvector or { 0, 1 } - local light = p.light or { 3, 3, 10 } - -- - local xrx, xry = xvector[1], xvector[2] - local yrx, yry = yvector[1], yvector[2] - local zrx, zry = zvector[1], zvector[2] - local xp, yp, zp = light[1], light[2], light[3] - -- - local data = setmetatableindex("table") - local dx = (xmax - xmin) / nx - local dy = (ymax - ymin) / ny - local xt = xmin - -- - local minf, maxf - -- - -- similar as contours but no data loop here - -- - local fcode = load((p.check and f_function_y or f_function_n)(preamble,code)) - local func = type(fcode) == "function" and fcode() - if type(func) ~= "function" then - return false -- fatal error - end - -- - local ccode = load(f_color(colorcode)) - local color = type(ccode) == "function" and ccode() - if type(color) ~= "function" then - return false -- fatal error - end - -- - for i=0,nx do - local yt = ymin - for j=0,ny do - local zt = func(xt,yt) - -- projection from 3D to 2D coordinates - local x = xt * xrx + yt * yrx + zt * zrx - local y = xt * xry + yt * yry + zt * zry - local z = zt - -- numerical derivatives by central differences - local dfx = (func(xt+ha,yt) - func(xt-ha,yt)) / hb - local dfy = (func(xt,yt+ha) - func(xt,yt-ha)) / hb - -- compute brightness factor at a point - local ztp = zt - zp - local ytp = yt - yp - local xtp = xt - xp - local ztp = zt - zp - local ytp = yt - yp - local xtp = xt - xp - local ca = -ztp + dfy*ytp + dfx*xtp - local cb = sqrt(1+dfx*dfx+dfy*dfy) - local cc = sqrt(ztp*ztp + ytp*ytp + xtp*xtp) - local fac = bf*ca/(cb*cc*cc*cc) - -- addition: check range - if not minf then - minf = fac - maxf = fac - elseif fac < minf then - minf = fac - elseif fac > maxf then - maxf = fac - end - -- - data[i][j] = { x, y, fac } - -- - yt = yt + dy - end - xt = xt + dx - end - local result = { } - local r = 0 - local range = maxf - minf - local cl = linecolor or 1 - local enforce = attributes.colors.model == "cmyk" - for i=0,nx-1 do - for j=0,ny-1 do - -- points - local z1 = data[i] [j] - local z2 = data[i] [j+1] - local z3 = data[i+1][j+1] - local z4 = data[i+1][j] - -- color - local cf = z1[3] - if clip then - -- best clip here if needed - if cf < 0 then - cf = 0 - elseif cf > 1 then - cf = 1 - end - else - -- or remap when we want to - cf = (z1[3] - minf) / range - end - local z11 = z1[1] - local z12 = z1[2] - local z21 = z2[1] - local z22 = z2[2] - local z31 = z3[1] - local z32 = z3[2] - local z41 = z4[1] - local z42 = z4[2] - -- if lines then - -- -- fill first and draw then, previous shapes can be covered - -- else - -- -- fill and draw in one go to prevent artifacts - -- end - local cr, cg, cb = color(cf) - if not cr then cr = 0 end - if not cg then cg = 0 end - if not cb then cb = 0 end - if enforce then - cr, cg, cb = 1 - cr, 1 - cg, 1 - cb - r = r + 1 - if lines then - result[r] = f_fill_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) - r = r + 1 - result[r] = f_draw_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cl) - else - result[r] = f_mesh_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) - end - else - r = r + 1 - if lines then - result[r] = f_fill_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) - r = r + 1 - result[r] = f_draw_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cl) - else - result[r] = f_mesh_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) - end - end - end - end - mp.direct(concat(result)) -end diff --git a/tex/context/base/mkiv/mlib-ctx.mkxl b/tex/context/base/mkiv/mlib-ctx.mkxl deleted file mode 100644 index 88f26c9ac..000000000 --- a/tex/context/base/mkiv/mlib-ctx.mkxl +++ /dev/null @@ -1,32 +0,0 @@ -%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. - -\writestatus{loading}{MetaPost Library Graphics / Initializations} - -\registerctxluafile{mlib-fio}{autosuffix} -\registerctxluafile{mlib-run}{} -\registerctxluafile{mlib-ctx}{} -\registerctxluafile{mlib-lua}{autosuffix} -\registerctxluafile{mlib-mpf}{} -\registerctxluafile{mlib-scn}{autosuffix} -\registerctxluafile{mlib-mat}{autosuffix} -\registerctxluafile{mlib-ran}{autosuffix} -\registerctxluafile{mlib-lmp}{autosuffix} -\registerctxluafile{mlib-int}{autosuffix} -\registerctxluafile{mlib-lmt}{autosuffix} -\registerctxluafile{mlib-cnt}{autosuffix,optimize} -\registerctxluafile{mlib-svg}{autosuffix,optimize} - -\unprotect - -\protect \endinput diff --git a/tex/context/base/mkiv/mlib-fio.lmt b/tex/context/base/mkiv/mlib-fio.lmt deleted file mode 100644 index 4290537dd..000000000 --- a/tex/context/base/mkiv/mlib-fio.lmt +++ /dev/null @@ -1,191 +0,0 @@ -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", -} - -local type = type -local find = string.find -local concat = table.concat - -local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end) - -local report_metapost = logs.reporter("metapost") -local report_terminal = logs.reporter("metapost","terminal") -local report_logger = logs.reporter("metapost","log") -local report_error = logs.reporter("metapost","error") - -mplib.realtimelogging = false - -local l, nl, dl = { }, 0, false -local t, nt, dt = { }, 0, false -local e, ne, de = { }, 0, false - -local function logger(target,str) - if target == 1 then - -- log - elseif target == 2 or target == 3 then - -- term - if str == "\n" then - mplib.realtimelogging = true - if nl > 0 then - report_logger(concat(l,"",1,nl)) - nl, dl = 0, false - elseif not dl then - report_logger("") - dl = true - end - else - nl = nl + 1 - l[nl] = str - end - elseif target == 4 then - report_error(str) - end -end - -local finders = { } -mplib.finders = finders -- also used in meta-lua.lua - -local new_instance = mplib.new - -local function validftype(ftype) - if ftype == "mp" then - return "mp" - else - return nil - end -end - -finders.file = function(specification,name,mode,ftype) - return resolvers.findfile(name,validftype(ftype)) -end - -local findtexfile = resolvers.findtexfile -local opentexfile = resolvers.opentexfile -local splitlines = string.splitlines - -local function writetoterminal(terminaldata,maxterm,d) - local t = type(d) - local n = 0 - if t == "string" then - d = splitlines(d) - n = #d - for i=1,#d do - maxterm = maxterm + 1 - terminaldata[maxterm] = d[i] - end - elseif t == "table" then - for i=1,#d do - local l = d[i] - if find(l,"[\n\r]") then - local s = splitlines(l) - local m = #s - for i=1,m do - maxterm = maxterm + 1 - terminaldata[maxterm] = s[i] - end - n = n + m - else - maxterm = maxterm + 1 - terminaldata[maxterm] = d[i] - n = 1 - end - end - end - if trace_terminal then - report_metapost("writing %i lines, in cache %s",n,maxterm) - end - return maxterm -end - -local function readfromterminal(terminaldata,maxterm,nowterm) - if nowterm >= maxterm then - terminaldata[nowterm] = false - maxterm = 0 - nowterm = 0 - if trace_terminal then - report_metapost("resetting, maxcache %i",#terminaldata) - end - return maxterm, nowterm, nil - else - if nowterm > 0 then - terminaldata[nowterm] = false - end - nowterm = nowterm + 1 - local s = terminaldata[nowterm] - if trace_terminal then - report_metapost("reading line %i: %s",nowterm,s) - end - return maxterm, nowterm, s - end -end - -local function fileopener() - - -- these can go into the table itself - - local terminaldata = { } - local maxterm = 0 - local nowterm = 0 - - local terminal = { - name = "terminal", - close = function() - -- terminal = { } - -- maxterm = 0 - -- nowterm = 0 - end, - reader = function() - local line - maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm) - return line - end, - writer = function(d) - maxterm = writetoterminal(terminaldata,maxterm,d) - end, - } - - return function(name,mode,kind) - if name == "terminal" then - -- report_metapost("opening terminal") - return terminal - elseif mode == "w" then - local f = io.open(name,"wb") - if f then - -- report_metapost("opening file %a for writing",full) - return { - name = full, - writer = function(s) return f:write(s) end, -- io.write(f,s) - close = function() f:close() end, - } - end - else - local full = findtexfile(name,validftype(ftype)) - if full then - -- report_metapost("opening file %a for reading",full) - return opentexfile(full) - end - end - end - -end - -local function finder(name,mode,kind) - return findtexfile(name,kind) -end - -function mplib.new(specification) - local openfile = fileopener() - specification.find_file = finder - specification.run_logger = logger - specification.open_file = openfile - specification.interaction = "silent" - specification.halt_on_error = true - local instance = new_instance(specification) - return instance, openfile("terminal") -end - -mplib.finder = finder diff --git a/tex/context/base/mkiv/mlib-int.lmt b/tex/context/base/mkiv/mlib-int.lmt deleted file mode 100644 index 86e2e5732..000000000 --- a/tex/context/base/mkiv/mlib-int.lmt +++ /dev/null @@ -1,135 +0,0 @@ -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 mpstring = mp.string -local mpboolean = mp.boolean -local getdimen = tex.getdimen -local getcount = tex.getcount -local getmacro = tokens.getters.macro -local get = tex.get -local emwidths = fonts.hashes.emwidths -local exheights = fonts.hashes.exheights - -local registerscript = metapost.registerscript - -local on_right_page = structures.pages.on_right -local is_odd_page = structures.pages.is_odd -local in_body_page = structures.pages.in_body -local page_fraction = structures.pages.fraction - -local function defaultcolormodel() -- can be helper - local colormethod = getcount("MPcolormethod") - return (colormethod == 0 or colormethod == 1) and 1 or 3 -end - -local t = os.date("*t") -- maybe this should be a very early on global - -registerscript("year", function() return t.year end) -registerscript("month", function() return t.month end) -registerscript("day", function() return t.day end) -registerscript("hour", function() return t.hour end) -registerscript("minute", function() return t.min end) -registerscript("second", function() return t.sec end) - -registerscript("PaperHeight", function() return getdimen("paperheight") * factor end) -registerscript("PaperWidth", function() return getdimen("paperwidth") * factor end) -registerscript("PrintPaperHeight", function() return getdimen("printpaperheight") * factor end) -registerscript("PrintPaperWidth", function() return getdimen("printpaperwidth") * factor end) -registerscript("TopSpace", function() return getdimen("topspace") * factor end) -registerscript("BottomSpace", function() return getdimen("bottomspace") * factor end) -registerscript("BackSpace", function() return getdimen("backspace") * factor end) -registerscript("CutSpace", function() return getdimen("cutspace") * factor end) -registerscript("MakeupHeight", function() return getdimen("makeupheight") * factor end) -registerscript("MakeupWidth", function() return getdimen("makeupwidth") * factor end) -registerscript("TopHeight", function() return getdimen("topheight") * factor end) -registerscript("TopDistance", function() return getdimen("topdistance") * factor end) -registerscript("HeaderHeight", function() return getdimen("headerheight") * factor end) -registerscript("HeaderDistance", function() return getdimen("headerdistance") * factor end) -registerscript("TextHeight", function() return getdimen("textheight") * factor end) -registerscript("FooterDistance", function() return getdimen("footerdistance") * factor end) -registerscript("FooterHeight", function() return getdimen("footerheight") * factor end) -registerscript("BottomDistance", function() return getdimen("bottomdistance") * factor end) -registerscript("BottomHeight", function() return getdimen("bottomheight") * factor end) -registerscript("LeftEdgeWidth", function() return getdimen("leftedgewidth") * factor end) -registerscript("LeftEdgeDistance", function() return getdimen("leftedgedistance") * factor end) -registerscript("LeftMarginWidth", function() return getdimen("leftmarginwidth") * factor end) -registerscript("LeftMarginDistance", function() return getdimen("leftmargindistance") * factor end) -registerscript("TextWidth", function() return getdimen("textwidth") * factor end) -registerscript("RightMarginDistance", function() return getdimen("rightmargindistance") * factor end) -registerscript("RightMarginWidth", function() return getdimen("rightmarginwidth") * factor end) -registerscript("RightEdgeDistance", function() return getdimen("rightedgedistance") * factor end) -registerscript("RightEdgeWidth", function() return getdimen("rightedgewidth") * factor end) -registerscript("InnerMarginDistance", function() return getdimen("innermargindistance") * factor end) -registerscript("InnerMarginWidth", function() return getdimen("innermarginwidth") * factor end) -registerscript("OuterMarginDistance", function() return getdimen("outermargindistance") * factor end) -registerscript("OuterMarginWidth", function() return getdimen("outermarginwidth") * factor end) -registerscript("InnerEdgeDistance", function() return getdimen("inneredgedistance") * factor end) -registerscript("InnerEdgeWidth", function() return getdimen("inneredgewidth") * factor end) -registerscript("OuterEdgeDistance", function() return getdimen("outeredgedistance") * factor end) -registerscript("OuterEdgeWidth", function() return getdimen("outeredgewidth") * factor end) -registerscript("PageOffset", function() return getdimen("pagebackgroundoffset") * factor end) -registerscript("PageDepth", function() return getdimen("pagebackgrounddepth") * factor end) -registerscript("LayoutColumns", function() return getcount("layoutcolumns") end) -registerscript("LayoutColumnDistance", function() return getdimen("layoutcolumndistance") * factor end) -registerscript("LayoutColumnWidth", function() return getdimen("layoutcolumnwidth") * factor end) -registerscript("SpineWidth", function() return getdimen("spinewidth") * factor end) -registerscript("PaperBleed", function() return getdimen("paperbleed") * factor end) - -registerscript("RealPageNumber", function() return getcount("realpageno") end) -registerscript("LastPageNumber", function() return getcount("lastpageno") end) - -registerscript("PageNumber", function() return getcount("pageno") end) -registerscript("NOfPages", function() return getcount("lastpageno") end) - -registerscript("SubPageNumber", function() return getcount("subpageno") end) -registerscript("NOfSubPages", function() return getcount("lastsubpageno") end) - -registerscript("CurrentColumn", function() return getcount("mofcolumns") end) -registerscript("NOfColumns", function() return getcount("nofcolumns") end) - -registerscript("BaseLineSkip", function() return get ("baselineskip",true) * factor end) -registerscript("LineHeight", function() return getdimen("lineheight") * factor end) -registerscript("BodyFontSize", function() return getdimen("bodyfontsize") * factor end) - -registerscript("TopSkip", function() return get ("topskip",true) * factor end) -registerscript("StrutHeight", function() return getdimen("strutht") * factor end) -registerscript("StrutDepth", function() return getdimen("strutdp") * factor end) - -registerscript("PageNumber", function() return getcount("pageno") end) -registerscript("RealPageNumber", function() return getcount("realpageno") end) -registerscript("NOfPages", function() return getcount("lastpageno") end) - -registerscript("CurrentWidth", function() return get ("hsize") * factor end) -registerscript("CurrentHeight", function() return get ("vsize") * factor end) - -registerscript("EmWidth", function() return emwidths [false] * factor end) -registerscript("ExHeight", function() return exheights[false] * factor end) - -registerscript("HSize", function() return get ("hsize") * factor end) -registerscript("VSize", function() return get ("vsize") * factor end) -registerscript("LastPageNumber", function() return getcount("lastpageno") end) - -registerscript("OverlayWidth", function() return getdimen("d_overlay_width") * factor end) -registerscript("OverlayHeight", function() return getdimen("d_overlay_height") * factor end) -registerscript("OverlayDepth", function() return getdimen("d_overlay_depth") * factor end) -registerscript("OverlayLineWidth", function() return getdimen("d_overlay_linewidth") * factor end) -registerscript("OverlayOffset", function() return getdimen("d_overlay_offset") * factor end) -registerscript("OverlayRegion", function() mpstring(getmacro("m_overlay_region")) end) ---------------("CurrentLayout", function() mpstring(getmacro("currentlayout")) end) - --- should be direct --- --- registerscript("PageFraction", page_fraction) - -registerscript("PageFraction", function() return mpboolean(page_fraction()) end) -registerscript("OnRightPage", function() return mpboolean(on_right_page()) end) -registerscript("OnOddPage", function() return mpboolean(is_odd_page ()) end) -registerscript("InPageBody", function() return mpboolean(in_body_page ()) end) - -registerscript("defaultcolormodel", defaultcolormodel) diff --git a/tex/context/base/mkiv/mlib-lmp.lmt b/tex/context/base/mkiv/mlib-lmp.lmt deleted file mode 100644 index ff9682e87..000000000 --- a/tex/context/base/mkiv/mlib-lmp.lmt +++ /dev/null @@ -1,70 +0,0 @@ -if not modules then modules = { } end modules ['mlib-lmp'] = { - 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", -} - --- path relates stuff ... todo: use a stack (or numeric index to list) - -local type = type - -local aux = mp.aux -local mpnumeric = aux.numeric -local mppair = aux.pair - -local p = nil -local n = 0 - -local function mf_path_reset() - p = nil - n = 0 -end - -local scan = mp.scan -local scannumber = scan.number -local scanpath = scan.path - -local function mf_path_length() - p = scanpath() - n = p and #p or 1 - mpnumeric(n) -end - -local function mf_path_point() - local i = scannumber() - if i > 0 and i <= n then - local pi = p[i] - mppair(pi[1],pi[2]) - end -end - -local function mf_path_left() - local i = scannumber() - if i > 0 and i <= n then - local pi = p[i] - mppair(pi[5],pi[6]) - end -end - -local function mf_path_right() - local i = scannumber() - if i > 0 and i <= n then - local pn - if i == 1 then - pn = p[2] or p[1] - else - pn = p[i+1] or p[1] - end - mppair(pn[3],pn[4]) - end -end - -local registerscript = metapost.registerscript - -registerscript("pathreset", mf_path_reset) -registerscript("pathlengthof", mf_path_length) -registerscript("pathpointof", mf_path_point) -registerscript("pathleftof", mf_path_left) -registerscript("pathrightof", mf_path_right) diff --git a/tex/context/base/mkiv/mlib-lmt.lmt b/tex/context/base/mkiv/mlib-lmt.lmt deleted file mode 100644 index f0b59248a..000000000 --- a/tex/context/base/mkiv/mlib-lmt.lmt +++ /dev/null @@ -1,153 +0,0 @@ -if not modules then modules = { } end modules ['mlib-lmt'] = { - 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", -} - --- todo: check for possible inject usage - -local type = type - -local aux = mp.aux -local mpdirect = aux.direct -local mppath = mp.path - -local scan = mp.scan -local scannumeric = scan.numeric -local scanpath = scan.path - -local getparameter = metapost.getparameter - -function mp.lmt_function_x(xmin,xmax,xstep,code,shape) -- experimental - local code = "return function(x) return " .. code .. " end" - local action = load(code) - local points = { } - local nofpoints = 0 - if action then - action = action() - end - if shape == "steps" then - local halfx = xstep / 2 - local lastx = xmin - local lasty = action(xmin) - for xi = xmin, xmax, xstep do - local yi = action(xi) - local xx = lastx + halfx - nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty } - nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi } - lastx = xi - lasty = yi - end - if points[nofpoints][1] ~= xmax then - local yi = action(xmax) - local xx = lastx + halfx - nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty } - nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi } - lastx = xi - lasty = yi - end - else - for xi = xmin, xmax, xstep do - nofpoints = nofpoints + 1 ; points[nofpoints] = { xi, action(xi) } - end - if points[nofpoints][1] ~= xmax then - nofpoints = nofpoints + 1 ; points[nofpoints] = { xmax, action(xmax) } - end - end - mppath(points,shape == "curve" and ".." or "--",false) -end - -function mp.lmt_mesh_set() - local mesh = getparameter { "mesh", "paths" } - structures.references.currentset.mesh = mesh -end - -function mp.lmt_mesh_update() - local mesh = getparameter { "paths" } or getparameter { "mesh", "paths" } - mesh[scannumeric()] = scanpath(true) -end - --- moved here - -function mp.lmt_svg_include() - local labelfile = metapost.getparameter { "labelfile" } - if labelfile and labelfile ~= "" then - local labels = table.load(labelfile) -- todo: same path as svg file - if type(labels) == "table" then - for i=1,#labels do - metapost.remaptext(labels[i]) - end - end - end - local fontname = metapost.getparameter { "fontname" } - if fontname and fontname ~= "" then - local unicode = metapost.getparameter { "unicode" } - if unicode then - mpdirect ( - metapost.svgglyphtomp(fontname,math.round(unicode)) - ) - end - return - end - local colorfile = metapost.getparameter { "colormap" } - local colormap = false - if colorfile and colorfile ~= "" then - colormap = metapost.svgcolorremapper(colorfile) - end - local filename = metapost.getparameter { "filename" } - if filename and filename ~= "" then - mpdirect ( metapost.svgtomp { - data = io.loaddata(filename), - remap = true, - colormap = colormap, - id = filename, - } ) - else - local buffer = metapost.getparameter { "buffer" } - if buffer then - mpdirect ( metapost.svgtomp { - data = buffers.getcontent(buffer), - -- remap = true, - colormap = colormap, - id = buffer or "buffer", - } ) - else - local code = metapost.getparameter { "code" } - if code then - mpdirect ( metapost.svgtomp { - data = code, - colormap = colormap, - id = "code", - } ) - end - end - end -end - - -function mp.lmt_do_remaptext() - local parameters = metapost.scanparameters() - if parameters and parameters.label then - metapost.remaptext(parameters) - end -end - -do - - local dropins = fonts.dropins - local registerglyphs = dropins.registerglyphs - local registerglyph = dropins.registerglyph - - function mp.lmt_register_glyph() - registerglyph(metapost.getparameterset("mpsglyph")) - end - - function mp.lmt_register_glyphs() - registerglyphs(metapost.getparameterset("mpsglyphs")) - end - -end - -todecimal = xdecimal and xdecimal.new or tonumber -- bonus diff --git a/tex/context/base/mkiv/mlib-lua.lmt b/tex/context/base/mkiv/mlib-lua.lmt deleted file mode 100644 index 8721ed60c..000000000 --- a/tex/context/base/mkiv/mlib-lua.lmt +++ /dev/null @@ -1,168 +0,0 @@ -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", -} - -local type = type -local insert, remove = table.insert, table.remove - -local scan = mp.scan -local inject = mp.inject - -local currentmpx = nil -local stack = { } - -local scan_next = mplib.scan_next -local scan_expression = mplib.scan_expression -local scan_token = mplib.scan_token -local scan_symbol = mplib.scan_symbol -local scan_numeric = mplib.scan_numeric -local scan_integer = mplib.scan_integer -local scan_boolean = mplib.scan_boolean -local scan_string = mplib.scan_string -local scan_pair = mplib.scan_pair -local scan_color = mplib.scan_color -local scan_cmykcolor = mplib.scan_cmykcolor -local scan_transform = mplib.scan_transform -local scan_path = mplib.scan_path -local scan_pen = mplib.scan_pen - -scan.next = function(k) return scan_next (currentmpx,k) end -scan.expression = function(k) return scan_expression(currentmpx,k) end -scan.token = function(k) return scan_token (currentmpx,k) end -scan.symbol = function(k,e) return scan_symbol (currentmpx,k,e) end -scan.numeric = function() return scan_numeric (currentmpx) end -scan.integer = function() return scan_integer (currentmpx) end -scan.boolean = function() return scan_boolean (currentmpx) end -scan.string = function() return scan_string (currentmpx) end -scan.pair = function(t) return scan_pair (currentmpx,t) end -scan.color = function(t) return scan_color (currentmpx,t) end -scan.cmykcolor = function(t) return scan_cmykcolor (currentmpx,t) end -scan.transform = function(t) return scan_transform (currentmpx,t) end -scan.path = function(t) return scan_path (currentmpx,t) end -scan.pen = function(t) return scan_pen (currentmpx,t) end - -local solvepath = mplib.solvepath -local getstatus = mplib.getstatus - -mp.solve = function(...) - return solvepath(currentmpx,...) -end - -local inject_path = mplib.inject_path -local inject_numeric = mplib.inject_numeric -local inject_pair = mplib.inject_pair -local inject_boolean = mplib.inject_boolean -local inject_integer = mplib.inject_integer -local inject_string = mplib.inject_string -local inject_color = mplib.inject_color -local inject_cmykcolor = mplib.inject_cmykcolor -local inject_transform = mplib.inject_transform -local inject_whatever = mplib.inject_whatever - -------.path = function(t,cycle,curled) return inject_path (currentmpx,t,cycle,curled) end -inject.numeric = function(n) return inject_numeric (currentmpx,n) end -inject.pair = function(x,y) return inject_pair (currentmpx,x,y) end -inject.boolean = function(b) return inject_boolean (currentmpx,b) end -inject.integer = function(i) return inject_integer (currentmpx,i) end -inject.string = function(s) return inject_string (currentmpx,s) end -inject.color = function(r,g,b) return inject_color (currentmpx,r,g,b) end -inject.cmykcolor = function(c,m,y,k) return inject_cmykcolor(currentmpx,c,m,y,k) end -inject.transform = function(x,y,xx,xy,yx,yy) return inject_transform(currentmpx,x,y,xx,xy,yx,yy) end -inject.whatever = function(...) return inject_whatever (currentmpx,...) end - -local function same(p,n) - local f = p[1] - local l = p[n] - local nf = #f - local nl = #l - if nf == nl then - for i=1,nf do - if f[i] ~= l[i] then - return false - end - end - return true - end - return false -end - --- local p = mp.scan.path() --- mp.inject.path(p,true,true) - -function inject.path(p,close,connector) - local curled = false - local n = #p - if p.close or p.cycle then - close = true - end - if n > 1 then - -- [ ../true | --/false | nil/auto ] - if connector == nil or connector == "auto" then - connector = #p[1] > 2 - end - if connector == false or connector == "--" then - curled = true - elseif connector == true or connector == ".." then - if close and not same(p,n) then - p[n+1] = p[1] - end - end - end - return inject_path(currentmpx,p,close,curled) -end - --- bonus: - -scan .number = scan .numeric -inject.number = inject.numeric - -table.setmetatablecall(inject,function(t,...) - inject_whatever(currentmpx,...) -end) - --- experiment - -function mp.autoinject(m) - local t = type(m) - if t == "table" then - local n = #t - if n == 2 then - inject_pair(currentmpx,m) - elseif n == 3 then - inject_color(currentmpx,m) - elseif n == 4 then - inject_cmykcolor(currentmpx,m) - elseif n == 6 then - inject_transform(currentmpx,m) - end - elseif t == "number" then - inject_numeric(currentmpx,m) - elseif t == "string" then - inject_string(currentmpx,m) - elseif t == "boolean" then - inject_boolean(currentmpx,m) - end -end - -function metapost.pushscriptrunner(mpx) - insert(stack,mpx) - currentmpx = mpx -end - -function metapost.popscriptrunner() - currentmpx = remove(stack,mpx) -end - -function metapost.currentmpx() - return currentmpx -end - --- mplib.getstates(): zero is "normal" - -function metapost.currentmpxstatus() - return getstatus(currentmpx) or 0 -end diff --git a/tex/context/base/mkiv/mlib-mat.lmt b/tex/context/base/mkiv/mlib-mat.lmt deleted file mode 100644 index 3a63b32c7..000000000 --- a/tex/context/base/mkiv/mlib-mat.lmt +++ /dev/null @@ -1,139 +0,0 @@ -if not modules then modules = { } end modules ['mlib-mat'] = { - 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 scanners = mp.scan -local injectors = mp.inject - -local scannumeric = scanners.numeric -local scanpair = scanners.pair -local scancolor = scanners.color - -local mppair = injectors.pair or mp.pair - -local registerscript = metapost.registerscript - -local m = xmath -local c = xcomplex - -local m_acos = m.acos registerscript("m_acos", function() return m_acos (scannumeric()) end) -local m_acosh = m.acosh registerscript("m_acosh", function() return m_acosh (scannumeric()) end) -local m_asin = m.asin registerscript("m_asin", function() return m_asin (scannumeric()) end) -local m_asinh = m.asinh registerscript("m_asinh", function() return m_asinh (scannumeric()) end) -local m_atan = m.atan registerscript("m_atan", function() return m_atan (scannumeric()) end) -local m_atan2 = m.atan2 registerscript("m_atan2", function() return m_atan2 (scanpair ()) end) -local m_atanh = m.atanh registerscript("m_atanh", function() return m_atanh (scannumeric()) end) -local m_cbrt = m.cbrt registerscript("m_cbrt", function() return m_cbrt (scannumeric()) end) -local m_ceil = m.ceil registerscript("m_ceil", function() return m_ceil (scannumeric()) end) -local m_copysign = m.copysign registerscript("m_copysign", function() return m_copysign (scanpair ()) end) -local m_cos = m.cos registerscript("m_cos", function() return m_cos (scannumeric()) end) -local m_cosh = m.cosh registerscript("m_cosh", function() return m_cosh (scannumeric()) end) -local m_deg = m.deg registerscript("m_deg", function() return m_deg (scannumeric()) end) -local m_erf = m.erf registerscript("m_erf", function() return m_erf (scannumeric()) end) -local m_erfc = m.erfc registerscript("m_erfc", function() return m_erfc (scannumeric()) end) -local m_exp = m.exp registerscript("m_exp", function() return m_exp (scannumeric()) end) -local m_exp2 = m.exp2 registerscript("m_exp2", function() return m_exp2 (scannumeric()) end) -local m_expm1 = m.expm1 registerscript("m_expm1", function() return m_expm1 (scannumeric()) end) -local m_fabs = m.fabs registerscript("m_fabs", function() return m_fabs (scannumeric()) end) -local m_fdim = m.fdim registerscript("m_fdim", function() return m_fdim (scanpair ()) end) -local m_floor = m.floor registerscript("m_floor", function() return m_floor (scannumeric()) end) -local m_fma = m.fma registerscript("m_fma", function() return m_fma (scancolor ()) end) -local m_fmax = m.fmax registerscript("m_fmax", function() return m_fmax (scannumeric()) end) -local m_fmin = m.fmin registerscript("m_fmin", function() return m_fmin (scannumeric()) end) -local m_fmod = m.fmod registerscript("m_fmod", function() return m_fmod (scanpair ()) end) -local m_frexp = m.frexp registerscript("m_frexp", function() return m_frexp (scannumeric()) end) -local m_gamma = m.gamma registerscript("m_gamma", function() return m_gamma (scannumeric()) end) -local m_hypot = m.hypot registerscript("m_hypot", function() return m_hypot (scanpair ()) end) -local m_isfinite = m.isfinite registerscript("m_isfinite", function() return m_isfinite (scannumeric()) end) -local m_isinf = m.isinf registerscript("m_isinf", function() return m_isinf (scannumeric()) end) -local m_isnan = m.isnan registerscript("m_isnan", function() return m_isnan (scannumeric()) end) -local m_isnormal = m.isnormal registerscript("m_isnormal", function() return m_isnormal (scannumeric()) end) -local m_j0 = m.j0 registerscript("m_j0", function() return m_j0 (scannumeric()) end) -local m_j1 = m.j1 registerscript("m_j1", function() return m_j1 (scannumeric()) end) -local m_jn = m.jn registerscript("m_jn", function() return m_jn (scanpair ()) end) -local m_ldexp = m.ldexp registerscript("m_ldexp", function() return m_ldexp (scanpair ()) end) -local m_lgamma = m.lgamma registerscript("m_lgamma", function() return m_lgamma (scannumeric()) end) -local m_log = m.log registerscript("m_log", function() return m_log (scannumeric()) end) -local m_log10 = m.log10 registerscript("m_log10", function() return m_log10 (scannumeric()) end) -local m_log1p = m.log1p registerscript("m_log1p", function() return m_log1p (scannumeric()) end) -local m_log2 = m.log2 registerscript("m_log2", function() return m_log2 (scannumeric()) end) -local m_logb = m.logb registerscript("m_logb", function() return m_logb (scannumeric()) end) -local m_modf = m.modf registerscript("m_modf", function() return m_modf (scannumeric()) end) -local m_nearbyint = m.nearbyint registerscript("m_nearbyint", function() return m_nearbyint(scannumeric()) end) -local m_nextafter = m.nextafter registerscript("m_nextafter", function() return m_nextafter(scanpair ()) end) -local m_pow = m.pow registerscript("m_pow", function() return m_pow (scanpair ()) end) -local m_rad = m.rad registerscript("m_rad", function() return m_rad (scannumeric()) end) -local m_remainder = m.remainder registerscript("m_remainder", function() return m_remainder(scanpair ()) end) -local m_remquo = m.remquo registerscript("m_remquo", function() return m_remquo (scannumeric()) end) -local m_round = m.round registerscript("m_round", function() return m_round (scannumeric()) end) -local m_scalbn = m.scalbn registerscript("m_scalbn", function() return m_scalbn (scanpair ()) end) -local m_sin = m.sin registerscript("m_sin", function() return m_sin (scannumeric()) end) -local m_sinh = m.sinh registerscript("m_sinh", function() return m_sinh (scannumeric()) end) -local m_sqrt = m.sqrt registerscript("m_sqrt", function() return m_sqrt (scannumeric()) end) -local m_tan = m.tan registerscript("m_tan", function() return m_tan (scannumeric()) end) -local m_tanh = m.tanh registerscript("m_tanh", function() return m_tanh (scannumeric()) end) -local m_tgamma = m.tgamma registerscript("m_tgamma", function() return m_tgamma (scannumeric()) end) -local m_trunc = m.trunc registerscript("m_trunc", function() return m_trunc (scannumeric()) end) -local m_y0 = m.y0 registerscript("m_y0", function() return m_y0 (scannumeric()) end) -local m_y1 = m.y1 registerscript("m_y1", function() return m_y1 (scannumeric()) end) -local m_yn = m.yn registerscript("m_yn", function() return m_yn (scanpair ()) end) - -if not (c and c.sin) then - return -end - -local c_topair = c.topair -local c_new = c.new - -local c_sin = c.sin registerscript("c_sin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end) -local c_cos = c.cos registerscript("c_cos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end) -local c_tan = c.tan registerscript("c_tan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end) -local c_sinh = c.sinh registerscript("c_sinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end) -local c_cosh = c.cosh registerscript("c_cosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end) -local c_tanh = c.tanh registerscript("c_tanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end) - -local c_asin = c.asin registerscript("c_asin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end) -local c_acos = c.acos registerscript("c_acos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end) -local c_atan = c.atan registerscript("c_atan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end) -local c_asinh = c.asinh registerscript("c_asinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end) -local c_acosh = c.acosh registerscript("c_acosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end) -local c_atanh = c.atanh registerscript("c_atanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end) - -local c_sqrt = c.sqrt registerscript("c_sqrt", function() return mppair(c_topair(c_sqrt (c_new(scanpair())))) end) -local c_abs = c.abs registerscript("c_abs", function() return c_topair(c_abs (c_new(scanpair()))) end) -local c_arg = c.arg registerscript("c_arg", function() return c_topair(c_arg (c_new(scanpair()))) end) -local c_conj = c.conj registerscript("c_conj", function() return mppair(c_topair(c_conj (c_new(scanpair())))) end) -local c_exp = c.exp registerscript("c_exp", function() return mppair(c_topair(c_exp (c_new(scanpair())))) end) -local c_log = c.log registerscript("c_log", function() return mppair(c_topair(c_log (c_new(scanpair())))) end) -local c_proj = c.proj registerscript("c_proj", function() return mppair(c_topair(c_proj (c_new(scanpair())))) end) - -local c_erf = c.erf registerscript("c_erf", function() return mppair(c_topair(c_erf (c_new(scanpair())))) end) -local c_erfc = c.erfc registerscript("c_erfc", function() return mppair(c_topair(c_erfc (c_new(scanpair())))) end) -local c_erfcx = c.erfcx registerscript("c_erfcx", function() return mppair(c_topair(c_erfcx (c_new(scanpair())))) end) -local c_erfi = c.erfi registerscript("c_erfi", function() return mppair(c_topair(c_erfi (c_new(scanpair())))) end) -local c_dawson = c.dawson registerscript("c_dawson", function() return mppair(c_topair(c_dawson(c_new(scanpair())))) end) - -local c_voigt = c.voigt -local c_voigt_hwhm = c.voigt_hwhm - -registerscript("c_voigt", function() - return mppair(c_topair(c_voigt(c_new(scanpair()),c_new(scanpair()),c_new(scanpair())))) -end) - -registerscript("c_voigt_hwhm", function() - return mppair(c_topair(c_voigt_hwhm(c_new(scanpair()),c_new(scanpair())))) -end) - -local c_pow = c.pow registerscript("c_pow", function() return mppair(c_topair(c_pow(c_new(scanpair()),c_new(scanpair())))) end) -local c_add = c.add registerscript("c_add", function() return mppair(c_topair(c_add(c_new(scanpair()),c_new(scanpair())))) end) -local c_sub = c.sub registerscript("c_sub", function() return mppair(c_topair(c_sub(c_new(scanpair()),c_new(scanpair())))) end) -local c_mul = c.mul registerscript("c_mul", function() return mppair(c_topair(c_mul(c_new(scanpair()),c_new(scanpair())))) end) -local c_div = c.div registerscript("c_div", function() return mppair(c_topair(c_div(c_new(scanpair()),c_new(scanpair())))) end) - -local c_imag = c.imag registerscript("c_imag", function() return c_topair(c_imag(c_new(scanpair()))) end) -local c_real = c.real registerscript("c_real", function() return c_topair(c_real(c_new(scanpair()))) end) -local c_neg = c.neg registerscript("c_new", function() return c_topair(c_neg (c_new(scanpair()))) end) diff --git a/tex/context/base/mkiv/mlib-pdf.mkxl b/tex/context/base/mkiv/mlib-pdf.mkxl deleted file mode 100644 index 90a5b5a86..000000000 --- a/tex/context/base/mkiv/mlib-pdf.mkxl +++ /dev/null @@ -1,162 +0,0 @@ -%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 - -%D We use bit more code that needed because we want to limit the amount of boxing. - -\registerctxluafile{mlib-pdf}{} - -%D Some code is shared between MPLIB and MPS. The following variables are also -%D 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 - -\permanent\protected\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points - {\global\MPllx #1\onebasepoint - \global\MPlly #2\onebasepoint - \global\MPurx #3\onebasepoint - \global\MPury #4\onebasepoint - \global\MPwidth \dimexpr\MPurx-\MPllx\relax - \global\MPheight\dimexpr\MPury-\MPlly\relax} - -\permanent\protected\def\resetMPboundingbox - {\global\MPwidth \zeropoint - \global\MPheight\zeropoint - \global\MPllx \zeropoint - \global\MPlly \zeropoint - \global\MPurx \zeropoint - \global\MPury \zeropoint} - -\let\popMPboundingbox\relax - -\permanent\protected\def\pushMPboundingbox - {\enforced\permanent\protected\edef\popMPboundingbox - {\global\MPwidth \the\MPwidth - \global\MPheight\the\MPheight - \global\MPllx \the\MPllx - \global\MPlly \the\MPlly - \global\MPurx \the\MPurx - \global\MPury \the\MPury - \relax}} - -% we need to combine these - -\permanent\protected\def\repositionMPboxindeed - {\setbox\MPbox\hpack\bgroup - \kern-\MPllx - \raise-\MPlly - \box\MPbox - \egroup} - -\permanent\protected\def\repositionMPbox - {\ifzeropt\MPllx - \ifzeropt\MPlly - % okay - \else - \repositionMPboxindeed - \fi - \else - \repositionMPboxindeed - \fi} - -% combined - -\permanent\protected\def\finalizeMPbox - {\boxxoffset\MPbox-\MPllx\relax - \boxyoffset\MPbox\dimexpr\boxyoffset\MPbox-\MPheight-\MPlly\relax - \wd\MPbox\MPwidth - \ht\MPbox\MPheight} - -% MPLIB specific: - -\permanent\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded - -\permanent\protected\def\startMPLIBtoPDF#1#2#3#4% - {\meta_process_graphic_figure_start - \dostarttagged\t!mpgraphic\empty - \naturalhpack attr \imageattribute \plusone \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 - -\permanent\protected\def\stopMPLIBtoPDF - {\egroup - \finalizeMPbox - \box\MPbox - \egroup - \dostoptagged - \meta_process_graphic_figure_stop} - -\permanent\protected\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 - -\aliased\let\normalstartMPLIBtoPDF\startMPLIBtoPDF -\aliased\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF - -\permanent\protected\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF} -\permanent\protected\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage} - -% can become \permanent\protected\def\directMPgraphic#=#*#=% but best test first - -\permanent\protected\def\directMPgraphic - {\dodoublegroupempty\mlib_direct_graphic} - -\def\mlib_direct_graphic#1#2% makes pages (todo: make boxes) - {\meta_begin_graphic_group{#1}% - \enforced\let\startMPLIBtoPDF\directstartMPLIBtoPDF - \enforced\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/tex/context/base/mkiv/mlib-pps.mkxl b/tex/context/base/mkiv/mlib-pps.mkxl deleted file mode 100644 index 3830de762..000000000 --- a/tex/context/base/mkiv/mlib-pps.mkxl +++ /dev/null @@ -1,215 +0,0 @@ -%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. - -% todo: remove MPenvironment code - -\unprotect - -\registerctxluafile{mlib-pps}{} - -%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\mlib_flush_environment - {%\writestatus\m!metapost{flushing environment}% - \clf_mptexget - \enforced\let\MPLIBflushenvironment\relax}% MPenvironments are depricated} - -\aliased\let\MPLIBflushenvironment\mlib_flush_environment - -\permanent\protected\def\MPLIBsetNtext#1% #2% box text - {\MPLIBflushenvironment - \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text - \meta_set_current_color - \enforced\let\MPLIBflushenvironment\mlib_flush_environment - \let\next} % gobble open brace - -\permanent\protected\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 ! - \enforced\let\MPLIBflushenvironment\mlib_flush_environment - \let\next} % gobble open brace - -\aliased\let\MPLIBsettext\MPLIBsetNtext - -\permanent\protected\def\MPLIBsetNtextX#1% #2% box text - {\MPLIBflushenvironment - \hbox\bgroup % text - \meta_set_current_color - \enforced\let\MPLIBflushenvironment\mlib_flush_environment - \let\next} - -\permanent\protected\def\MPLIBsetCtextX#1#2% #3% box colorspec text - {\MPLIBflushenvironment - \hbox\bgroup % text - \directcolored[#2]% - \meta_set_current_color % so, textcolor wins ! - \enforced\let\MPLIBflushenvironment\mlib_flush_environment - \let\next} - -\aliased\let\MPLIBsettextX\MPLIBsetNtextX - -\permanent\permanent\protected\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}}} - -\permanent\protected\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{\fastsxsy{\mlib_sx}{\mlib_sy}{\box\scratchbox}\hss}}} - -% horrible (we could inline scale and matrix code): - -\permanent\protected\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} - -% \putnextboxincache{hans}{1}\hbox{foo} -% -% \startMPcode -% draw boundingbox rawtexbox("hans",1) ; -% draw rawtexbox("hans",1) ; -% \stopMPcode - -\permanent\protected\def\MPLIBgetboxscaledcm#1#2% - {\begingroup - \copyboxfromcache{#1}{#2}\MPtextbox % can be \clf_ - \mlib_get_box_scaled_cm_next} - -\protected\def\mlib_get_box_scaled_cm_next#1#2#3#4#5#6#7#8% 1-6: sx,rx,ry,sy,tx,ty - {\setbox\MPbox\hpack\bgroup - \dotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}% - \vpack to \zeropoint\bgroup - \vss - \hpack to \zeropoint \bgroup - \fastsxsy{#7}{#8}{\raise\dp\MPtextbox\box\MPtextbox}% - \hss - \egroup - \egroup - \egroup - \smashbox\MPbox - \box\MPbox - \endgroup} - -\permanent\protected\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 - -\permanent\protected\def\MPLIBpositionwhd#1#2#3#4#5% bp ! - {\dosavepositionwhd{#1}\zerocount{#2\onebasepoint}{#3\onebasepoint}{#4\onebasepoint}{#5\onebasepoint}\zeropoint} - -\def\mlib_stop_group#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 - \setbox\scratchbox\hpack\bgroup - \kern-#3\onebasepoint - \box\scratchbox - \egroup - \saveboxresource - attr {/Group << /S /Transparency /I \ifnum#1=1 true \else false \fi /K \ifnum#2=1 true \else false \fi >>} - resources {\pdfbackendcurrentresources} - \scratchbox - \setbox\scratchbox\hpack\bgroup - \kern#3\onebasepoint - \kern-\onebasepoint - \useboxresource\lastsavedboxresourceindex - \egroup - \wd\scratchbox\zeropoint - \ht\scratchbox\zeropoint - \dp\scratchbox\zeropoint - \box\scratchbox - \endgroup} - -\aliased\let\MPLIBstopgroup\relax - -\permanent\protected\def\MPLIBstartgroup#1#2#3#4#5#6% isolated 0/1, knockout 0/1 llx lly urx ury - {\begingroup - \setbox\scratchbox\hpack\bgroup - \enforced\permanent\protected\def\MPLIBstopgroup{\mlib_stop_group{#1}{#2}{#3}{#4}{#5}{#6}}} - -% For now here ... will be cleaned up: - -\newtoks\mptexttoks -\newbox \mptextbox -\newtoks\mpoutlinetoks -\newtoks\mpgraphictexttoks - -\mptexttoks {\global\setbox\mptextbox\hbox{\clf_mptexttoks}} -\mpoutlinetoks {\global\setbox\mptextbox\vbox{\clf_mpoutlinetoks}} -\mpgraphictexttoks{\global\setbox\mptextbox\vbox{\clf_mpgraphictexttoks}} - -\protect \endinput diff --git a/tex/context/base/mkiv/mlib-ran.lmt b/tex/context/base/mkiv/mlib-ran.lmt deleted file mode 100644 index cb8645e8d..000000000 --- a/tex/context/base/mkiv/mlib-ran.lmt +++ /dev/null @@ -1,237 +0,0 @@ -if not modules then modules = { } end modules ['mlib-ran'] = { - 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 next = next -local ceil, floor, random, sqrt, cos, sin, pi, max, min = math.ceil, math.floor, math.random, math.sqrt, math.cos, math.sin, math.pi, math.min, math.max -local remove = table.remove - --- Below is a bit of rainy saturday afternoon hobyism, while listening to Judith --- Owens redisCOVERed (came there via Leland Sklar who I have on a few live blurays; --- and who is also on YT). (Also nice: https://www.youtube.com/watch?v=GXqasIRaxlA) - --- When Aditya pointed me to an article on mazes I ended up at poison distributions --- which to me looks nicer than what I normally do, fill a grid and then randomize --- the resulting positions. With some hooks this can be used for interesting patterns --- too. A few links: --- --- https://bost.ocks.org/mike/algorithms/#maze-generation --- https://extremelearning.com.au/ --- https://www.jasondavies.com/maps/random-points/ --- http://devmag.org.za/2009/05/03/poisson-disk-sampling - --- The next function is quite close to what us discribed in the poisson-disk-sampling --- link mentioned before. One can either use a one dimensional grid array or a two --- dimensional one. The example code uses some classes dealing with points. In the --- process I added some more control. - --- we could do without the samplepoints list - -local function poisson(width, height, mindist, newpointscount, initialx, initialy) - local starttime = os.clock() - local cellsize = mindist / sqrt(2) - local nofwidth = ceil(width // cellsize) - local nofheight = ceil(height // cellsize) - local grid = lua.newtable(nofwidth,0) -- table.setmetatableindex("table") - local firstx = initialx or random() * width - local firsty = initialy or random() * height - local firstpoint = { firstx, firsty, 1 } - -- local samplepoints = { firstpoint } - local processlist = { firstpoint } - local nofprocesslist = 1 - local nofsamplepoints = 1 - local twopi = 2 * pi - - for i=1,nofwidth do - local g = lua.newindex(nofheight,false) - grid[i] = g - end - - local x = floor(firstx // cellsize) + 1 -- lua indices - local y = floor(firsty // cellsize) + 1 -- lua indices - - x = max(1, min(x, width - 1)) - y = max(1, min(y, height - 1)) - - grid[x][y] = firstpoint - - -- The website shows graphic for this 5*5 grid snippet, if we use a one dimentional - -- array then we could have one loop; a first version used a metatable trick so we - -- had grid[i+gx][j+gy] but we no we also return the grid, so ... we now just check. - - -- There is no need for the samplepoints list as we can get that from the grid but - -- instead we can store the index with the grid. - - while nofprocesslist > 0 do - local point = remove(processlist,random(1,nofprocesslist)) - nofprocesslist = nofprocesslist - 1 - for i=1,newpointscount do -- we start at 1 - local radius = mindist * (random() + 1) - local angle = twopi * random() - local nx = point[1] + radius * cos(angle) - local ny = point[2] + radius * sin(angle) - if nx > 1 and ny > 1 and nx <= width and ny <= height then -- lua indices - local gx = floor(nx // cellsize) - local gy = floor(ny // cellsize) - -- the 5x5 cells around the point - for i=-2,2 do - for j=-2,2 do - local cell = grid[i + gx] - if cell then - cell = cell[j + gy] - if cell and sqrt((cell[1] - nx)^2 + (cell[2] - ny)^2) < mindist then - goto next - end - end - end - end - -- local newpoint = { nx, ny } - nofprocesslist = nofprocesslist + 1 - nofsamplepoints = nofsamplepoints + 1 - local newpoint = { nx, ny, nofsamplepoints } - processlist [nofprocesslist] = newpoint - -- samplepoints[nofsamplepoints] = newpoint - grid[gx][gy] = newpoint - end - ::next:: - end - end - - return { - count = nofsamplepoints, - -- points = samplepoints, - grid = grid, - time = os.clock() - starttime, - } -end - --- For now: - -local randomizers = utilities.randomizers or { } -utilities.randomizers = randomizers -randomizers.poisson = poisson - --- The MetaFun interface: - -local formatters = string.formatters -local concat = table.concat - -local f_macro = formatters["%s(%N,%N);"] - -local f_macros = { - [2] = formatters["%s(%N,%N);"], - [3] = formatters["%s(%N,%N,%i);"], - [4] = formatters["%s(%N,%N,%i,%i);"], -} - -function grid_to_mp(t,f,n) - local grid = t.grid - local count = t.count - local result = { } - local r = 0 - local macro = f or "draw" - local runner = f_macros[n or 2] or f_macros[2] - for i=1,#grid do - local g = grid[i] - if g then - for j=1,#g do - local v = g[j] - if v then - r = r + 1 - result[r] = runner(macro,v[1],v[2],v[3],count) - end - end - end - end - return concat(result, " ") -end - -local getparameter = metapost.getparameter - -local function lmt_poisson() - local initialx = getparameter { "initialx" } - local initialy = getparameter { "initialy" } - local width = getparameter { "width" } - local height = getparameter { "height" } - local distance = getparameter { "distance" } - local count = getparameter { "count" } - - local result = poisson ( - width, height, distance, count, - initialx > 0 and initialx or false, - initialy > 0 and initialy or false - ) - - if result then - logs.report("poisson","w=%N, h=%N, d=%N, c=%N, n=%i, runtime %.3f", - width, height, distance, count, result.count, result.time - ) - end - - return result -end - -function mp.lmt_poisson_generate() - local result = lmt_poisson() - if result then - return grid_to_mp ( - result, - getparameter { "macro" }, - getparameter { "arguments" } - ) - end -end - --- -- some playing around showed no benefit --- --- function points_to_mp(t,f) --- local points = t.points --- local count = t.count --- local result = { } --- local r = 0 --- local macro = f or "draw" --- local runner = f_macros[n or 2] or f_macros[2] --- for i=1,count do --- local v = points[i] --- r = r + 1 --- result[r] = runner(macro,v[1],v[2],v[3],count) --- end --- return concat(result, " ") --- end --- --- local result = false --- local i, j, n = 0, 0, 0 --- --- function mp.lmt_poison_start() --- result = lmt_poisson() --- end --- --- function mp.lmt_poisson_stop() --- result = false --- end --- --- function mp.lmt_poisson_count() --- return result and result.count or 0 --- end --- --- function mp.lmt_poisson_get(i) --- if result then --- return mp.pair(result.points[i]) --- end --- end --- --- function mp.lmt_poisson_generate() --- mp.lmt_poisson_start() --- if result then --- return grid_to_mp ( --- result, --- getparameter { "macro" }, --- getparameter { "arguments" } --- ) --- end --- mp.lmt_poisson_stop() --- end diff --git a/tex/context/base/mkiv/mlib-scn.lmt b/tex/context/base/mkiv/mlib-scn.lmt deleted file mode 100644 index ff1cff0e3..000000000 --- a/tex/context/base/mkiv/mlib-scn.lmt +++ /dev/null @@ -1,780 +0,0 @@ -if not modules then modules = { } end modules ['mlib-scn'] = { - 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", -} - --- Very experimental, for Alan and me. - --- for i = 1 upto 32000 : % 0.062 --- ts := 5mm / 20; --- endfor ; --- --- for i = 1 upto 32000 : % 0.219 --- ts := (getparameter "axis" "sy") / 20; --- endfor ; --- --- for i = 1 upto 32000 : % 0.266 --- ts := (getparameterx "axis" "sy") / 20; --- endfor ; --- --- pushparameters "axis"; --- for i = 1 upto 32000 : % 0.250 --- ts := (getparameterx "sy") / 20; --- endfor ; --- popparameters; - -local type, next, rawget, getmetatable = type, next, rawget, getmetatable -local byte, gmatch = string.byte, string.gmatch -local insert, remove = table.insert, table.remove - -local mplib = mplib -local metapost = metapost - -local codes = mplib.getcodes() -local types = mplib.gettypes() - -table.hashed(codes) -table.hashed(types) - -metapost.codes = codes -metapost.types = types - -local setmetatableindex = table.setmetatableindex - -local scanners = mp.scan -local injectors = mp.inject - -local scannext = scanners.next -local scanexpression = scanners.expression -local scantoken = scanners.token -local scansymbol = scanners.symbol -local scannumeric = scanners.numeric -local scannumber = scanners.number -local scaninteger = scanners.integer -local scanboolean = scanners.boolean -local scanstring = scanners.string -local scanpair = scanners.pair -local scancolor = scanners.color -local scancmykcolor = scanners.cmykcolor -local scantransform = scanners.transform -local scanpath = scanners.path -local scanpen = scanners.pen - -local mpprint = mp.print -local injectnumeric = injectors.numeric -local injectstring = injectors.string -local injectboolean = injectors.boolean -local injectpair = injectors.pair -local injecttriplet = injectors.color -local injectquadruple = injectors.cmykcolor -local injecttransform = injectors.transform -local injectpath = injectors.path - -local report = logs.reporter("metapost") - -local semicolon_code = codes.semicolon -local equals_code = codes.equals -local comma_code = codes.comma -local colon_code = codes.colon -local leftbrace_code = codes.leftbrace -local rightbrace_code = codes.rightbrace -local leftbracket_code = codes.leftbracket -local rightbracket_code = codes.rightbracket -local leftdelimiter_code = codes.leftdelimiter -local rightdelimiter_code = codes.rightdelimiter -local numeric_code = codes.numeric -local string_code = codes.string -local capsule_code = codes.capsule -local nullary_code = codes.nullary -local tag_code = codes.tag -local definedmacro_code = codes.definedmacro - -local typescanners = nil -local tokenscanners = nil -local scanset = nil -local scanparameters = nil - -scanset = function() -- can be optimized, we now read twice - scantoken() - if scantoken(true) == rightbrace_code then - scantoken() - return { } - else - local l = { } - local i = 0 - while true do - i = i + 1 - local s = scansymbol(true) - if s == "{" then - l[i] = scanset() - elseif s == "[" then - local d = { } - scansymbol() - while true do - local s = scansymbol() - if s == "]" then - break; - elseif s == "," then - -- continue - else - local t = scantoken(true) - if t == equals_code or t == colon_code then - scantoken() - end - d[s] = tokenscanners[scantoken(true)]() - end - end - l[i] = d - else - local e = scanexpression(true) - l[i] = (typescanners[e] or scanexpression)() - end - if scantoken() == rightbrace_code then - break - else - -- whatever - end - end - return l - end -end - -local function scan_pair () return scanpair (true) end -local function scan_color () return scancolor (true) end -local function scan_cmykcolor() return scancmykcolor(true) end -local function scan_transform() return scantransform(true) end - -tokenscanners = { - [leftbrace_code] = scanset, - [numeric_code] = scannumeric, - [string_code] = scanstring, - [nullary_code] = scanboolean, -- todo -} - -typescanners = { - [types.known] = scannumeric, - [types.numeric] = scannumeric, - [types.string] = scanstring, - [types.boolean] = scanboolean, - [types.pair] = scan_pair, - [types.color] = scan_color, - [types.cmykcolor] = scan_cmykcolor, - [types.transform] = scan_transform, - [types.path] = scanpath, - [types.pen] = scanpen, -} - -table.setmetatableindex(tokenscanners,function() - local e = scanexpression(true) - return typescanners[e] or scanexpression -end) - --- a key like 'color' has code 'declare' - -local function scanparameters(fenced) - local data = { } - local close = "]" - if not fenced then - close = ";" - elseif scansymbol(true) == "[" then - scansymbol() - else - return data - end - while true do - -- local s = scansymbol() - local s = scansymbol(false,false) - if s == close then - break; - elseif s == "," then - -- continue - else - local t = scantoken(true) - if t == equals_code or t == colon_code then - -- optional equal or : - scantoken() - end - local kind = scantoken(true) - if kind == leftdelimiter_code or kind == tag_code or kind == capsule_code then - kind = scanexpression(true) - data[s] = (typescanners[kind] or scanexpression)() - elseif kind == leftbracket_code then - data[s] = get_parameters(true) - else - data[s] = tokenscanners[kind]() - end - end - end - return data -end - -local namespaces = { } -local presets = { } -local passed = { } - -local function get_parameters(nested) - local data = { } - if nested or scansymbol(true) == "[" then - scansymbol() - else - return data - end - while true do - local s = scansymbol(false,false) - if s == "]" then - break; - elseif s == "," then - -- continue - else - local t = scantoken(true) - if t == equals_code or t == colon_code then - -- optional equal or : - scantoken() - end - local kind = scantoken(true) - if kind == leftdelimiter_code or kind == tag_code or kind == capsule_code then - kind = scanexpression(true) - data[s] = (typescanners[kind] or scanexpression)() - elseif kind == leftbracket_code then - data[s] = get_parameters(true) - else - data[s] = tokenscanners[kind]() - end - end - end - return data -end - -local function getparameters() - local namespace = scanstring() - -- same as below - local parameters = get_parameters() - local presets = presets[namespace] - local passed = passed[namespace] - if passed then - if presets then - setmetatableindex(passed,presets) - end - setmetatableindex(parameters,passed) - elseif presets then - setmetatableindex(parameters,presets) - end - namespaces[namespace] = parameters - -- -end - -local function applyparameters() - local saved = namespaces - local namespace = scanstring() - local action = scanstring() -- before we scan the parameters - -- same as above - local parameters = get_parameters() - local presets = presets[namespace] - local passed = passed[namespace] - if passed then - if presets then - setmetatableindex(passed,presets) - end - setmetatableindex(parameters,passed) - elseif presets then - setmetatableindex(parameters,presets) - end - namespaces[namespace] = parameters - -- till here - mpprint(action) - namespaces = saved -end - -local function presetparameters() - local namespace = scanstring() - local parent = nil - local t = scantoken(true) - if t == string_code then - parent = presets[scanstring()] - end - local p = get_parameters() - if parent then - setmetatableindex(p,parent) - end - presets[namespace] = p -end - -local function collectnames() - local l = { } -- can be reused but then we can't nest - local n = 0 - while true do - local t = scantoken(true) - -- (1) not really needed - if t == numeric_code then - n = n + 1 l[n] = scaninteger(1) - elseif t == string_code then - n = n + 1 l[n] = scanstring(1) - elseif t == nullary_code then - n = n + 1 l[n] = scanboolean(1) - elseif t == leftbracket_code then - scantoken() -- leftbacket - n = n + 1 l[n] = scaninteger(1) - scantoken() -- rightbacket - elseif t == leftdelimiter_code or t == tag_code or t == capsule_code then - t = scanexpression(true) - n = n + 1 l[n] = (typescanners[t] or scanexpression)() - else - break - end - end - return l, n -end - -local function get(v) - local t = type(v) - if t == "number" then - return injectnumeric(v) - elseif t == "boolean" then - return injectboolean(v) - elseif t == "string" then - return injectstring(v) - elseif t == "table" then - local n = #v - if type(v[1]) == "table" then - return injectpath(v) - elseif n == 2 then - return injectpair(v) - elseif n == 3 then - return injecttriplet(v) - elseif n == 4 then - return injectquadruple(v) - elseif n == 6 then - return injecttransform(v) - end - end - return injectnumeric(0) -end - -local stack = { } - -local function pushparameters() - local l, n = collectnames() - insert(stack,namespaces) - for i=1,n do - local n = namespaces[l[i]] - if type(n) == "table" then - namespaces = n - else - break - end - end -end - -local function popparameters() - local n = remove(stack) - if n then - namespaces = n - else - report("stack error") - end -end - --- todo: - -local function getparameter() - local list, n = collectnames() - local v = namespaces - for i=1,n do - local l = list[i] - local vl = v[l] - if vl == nil then - if type(l) == "number" then - vl = v[1] - if vl == nil then - return injectnumeric(0) - end - else - return injectnumeric(0) - end - end - v = vl - end - if v == nil then - return injectnumeric(0) - else - return get(v) - end -end - -local function hasparameter() - local list, n = collectnames() - local v = namespaces - for i=1,n do - local l = list[i] - local vl = rawget(v,l) - if vl == nil then - if type(l) == "number" then - vl = rawget(v,1) - if vl == nil then - return injectboolean(false) - end - else - return injectboolean(false) - end - end - v = vl - end - if v == nil then - return injectboolean(false) - else - return injectboolean(true) - end -end - -local function hasoption() - local list, n = collectnames() - if n > 1 then - local v = namespaces - if n > 2 then - for i=1,n-1 do - local l = list[i] - local vl = v[l] - if vl == nil then - return injectboolean(false) - end - v = vl - end - else - v = v[list[1]] - end - if type(v) == "string" then - -- no caching .. slow anyway - local o = list[n] - if v == o then - return injectboolean(true) - end - for vv in gmatch(v,"[^%s,]+") do - for oo in gmatch(o,"[^%s,]+") do - if vv == oo then - return injectboolean(true) - end - end - end - end - end - return injectboolean(false) -end - -local function getparameterdefault() - local list, n = collectnames() - local v = namespaces - if n == 1 then - local l = list[1] - local vl = v[l] - if vl == nil then - -- maybe backtrack - local top = stack[#stack] - if top then - vl = top[l] - end - end - if vl == nil then - return injectnumeric(0) - else - return get(vl) - end - else - for i=1,n-1 do - local l = list[i] - local vl = v[l] - if vl == nil then - if type(l) == "number" then - vl = v[1] - if vl == nil then - return get(list[n]) - end - else - local last = list[n] - if last == "*" then - -- so, only when not pushed - local m = getmetatable(namespaces[list[1]]) - if n then - m = m.__index -- can also be a _m_ - end - if m then - local v = m - for i=2,n-1 do - local l = list[i] - local vl = v[l] - if vl == nil then - return injectnumeric(0) - end - v = vl - end - if v == nil then - return injectnumeric(0) - else - return get(v) - end - end - return injectnumeric(0) - else - return get(last) - end - end - end - v = vl - end - if v == nil then - return get(list[n]) - else - return get(v) - end - end -end - -local function getparametercount() - local list, n = collectnames() - local v = namespaces - for i=1,n do - v = v[list[i]] - if not v then - break - end - end - return injectnumeric(type(v) == "table" and #v or 0) -end - -local function getmaxparametercount() - local list, n = collectnames() - local v = namespaces - for i=1,n do - v = v[list[i]] - if not v then - break - end - end - local n = 0 - if type(v) == "table" then - local v1 = v[1] - if type(v1) == "table" then - n = #v1 - for i=2,#v do - local vi = v[i] - if type(vi) == "table" then - local vn = #vi - if vn > n then - n = vn - end - else - break; - end - end - end - - end - return injectnumeric(n) -end - -local validconnectors = { - [".."] = true, - ["..."] = true, - ["--"] = true, -} - -local function getparameterpath() - local list, n = collectnames() - local close = list[n] - if type(close) == "boolean" then - n = n - 1 - else - close = false - end - local connector = list[n] - if type(connector) == "string" and validconnectors[connector] then - n = n - 1 - else - connector = "--" - end - local v = namespaces - for i=1,n do - v = v[list[i]] - if not v then - break - end - end - if type(v) == "table" then - return injectpath(v,connector,close) - else - return injectpair(0,0) - end -end - -local function getparameterpen() - local list, n = collectnames() - local v = namespaces - for i=1,n do - v = v[list[i]] - if not v then - break - end - end - if type(v) == "table" then - return injectpath(v,"..",true) - else - return injectpair(0,0) - end -end - -local function getparametertext() - local list, n = collectnames() - local strut = list[n] - if type(strut) == "boolean" then - n = n - 1 - else - strut = false - end - local v = namespaces - for i=1,n do - v = v[list[i]] - if not v then - break - end - end - if type(v) == "string" then - return injectstring("\\strut " .. v) - else - return injectstring("") - end -end - --- local function getparameteroption() --- local list, n = collectnames() --- local last = list[n] --- if type(last) == "string" then --- n = n - 1 --- else --- return false --- end --- local v = namespaces --- for i=1,n do --- v = v[list[i]] --- if not v then --- break --- end --- end --- if type(v) == "string" and v ~= "" then --- for s in gmatch(v,"[^ ,]+") do --- if s == last then --- return true --- end --- end --- end --- return false --- end - -function metapost.scanparameters() --- scantoken() -- we scan the semicolon - return get_parameters() -end - -metapost.registerscript("getparameters", getparameters) -metapost.registerscript("applyparameters", applyparameters) -metapost.registerscript("presetparameters", presetparameters) -metapost.registerscript("hasparameter", hasparameter) -metapost.registerscript("hasoption", hasoption) -metapost.registerscript("getparameter", getparameter) -metapost.registerscript("getparameterdefault", getparameterdefault) -metapost.registerscript("getparametercount", getparametercount) -metapost.registerscript("getmaxparametercount",getmaxparametercount) -metapost.registerscript("getparameterpath", getparameterpath) -metapost.registerscript("getparameterpen", getparameterpen) -metapost.registerscript("getparametertext", getparametertext) ---------.registerscript("getparameteroption", getparameteroption) -metapost.registerscript("pushparameters", pushparameters) -metapost.registerscript("popparameters", popparameters) - -function metapost.getparameter(list) - local n = #list - local v = namespaces - for i=1,n do - local l = list[i] - local vl = v[l] - if vl == nil then - return - end - v = vl - end - return v -end - -function metapost.getparameterset(namespace) - return namespace and namespaces[namespace] or namespaces -end - -function metapost.setparameterset(namespace,t) - namespaces[namespace] = t -end - --- goodies - -metapost.registerscript("definecolor", function() - scantoken() -- we scan the semicolon - local s = get_parameters() - attributes.colors.defineprocesscolordirect(s) -end) - --- tex scanners - -local scanners = tokens.scanners -local scanhash = scanners.hash -local scanstring = scanners.string -local scanvalue = scanners.value -local scaninteger = scanners.integer -local scanboolean = scanners.boolean -local scanfloat = scanners.float -local scandimension = scanners.dimension - -local definitions = { } - -local bpfactor = number.dimenfactors.bp -local comma = byte(",") -local close = byte("]") - -local scanrest = function() return scanvalue(comma,close) or "" end -local scandimension = function() return scandimension() * bpfactor end - -local scanners = { - ["integer"] = scaninteger, - ["number"] = scanfloat, - ["numeric"] = scanfloat, - ["boolean"] = scanboolean, - ["string"] = scanrest, - ["dimension"] = scandimension, -} - -interfaces.implement { - name = "lmt_parameters_define", - arguments = "string", - actions = function(namespace) - local d = scanhash() - for k, v in next, d do - d[k] = scanners[v] or scanrest - end - definitions[namespace] = d - end, -} - -interfaces.implement { - name = "lmt_parameters_preset", - arguments = "string", - actions = function(namespace) - passed[namespace] = scanhash(definitions[namespace]) - end, -} - -interfaces.implement { - name = "lmt_parameters_reset", - arguments = "string", - actions = function(namespace) - passed[namespace] = nil - end, -} diff --git a/tex/context/base/mkiv/mlib-svg.lmt b/tex/context/base/mkiv/mlib-svg.lmt deleted file mode 100644 index 4c4122476..000000000 --- a/tex/context/base/mkiv/mlib-svg.lmt +++ /dev/null @@ -1,3277 +0,0 @@ -if not modules then modules = { } end modules ['mlib-svg'] = { - version = 1.001, - optimize = true, - 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", -} - --- Just a few notes: --- --- There is no real need to boost performance here .. we can always make a fast --- variant when really needed. I will also do some of the todo's when I run into --- proper fonts. I need to optimize this a bit but will do that once I'm satisfied --- with the outcome and don't need more hooks and plugs. At some point I will --- optimize the MetaPost part because now we probably have more image wrapping --- than needed. --- --- As usual with these standards, things like a path can be very compact while the --- rest is very verbose which defeats the point. This is a first attempt. There will --- be a converter to MP as well as directly to PDF. This module was made for one of --- the dangerous curves talks at the 2019 CTX meeting. I will do the font when I --- need it (not that hard). --- --- The fact that in the more recent versions of SVG the older text related elements --- are depricated and not even supposed to be supported, combined with the fact that --- the text element assumes css styling, demonstrates that there is not so much as a --- standard. It basically means that whatever technology dominates at some point --- (probably combined with some libraries that at that point exist) determine what --- is standard. Anyway, it probably also means that these formats are not that --- suitable for long term archival purposes. So don't take the next implementation --- too serious. So in the end we now have (1) attributes for properties (which is --- nice and clean and what attributes are for, (2) a style attribute that needs to --- be parsed, (3) classes that map to styles and (4) element related styles, plus a --- kind of inheritance (given the limited number of elements sticking to only as --- wrapper would have made much sense. Anyway, we need to deal with it. With all --- these style things going on, one can wonder where it will end. Basically svg --- became just a html element that way and less clean too. The same is true for --- tspan, which means that text itself is nested xml. --- --- We can do a direct conversion to PDF but then we also loose the abstraction which --- in the future will be used, and for fonts we need to spawn out to TeX anyway, so --- the little overhead of calling MetaPost is okay I guess. Also, we want to --- overload labels, share fonts with the main document, etc. and are not aiming at a --- general purpose SVG converter. For going to PDF one can just use InkScape. --- --- Written with Anne Clark on speakers as distraction. --- --- Todo when I run into an example (but ony when needed and reasonable): --- --- var(color,color) --- --color --- currentColor : when i run into an example --- a bit more shading --- clip = [ auto | rect(llx,lly,urx,ury) ] (in svg) --- xlink url ... whatever --- masks --- opacity per group (i need to add that to metafun first, inefficient pdf but --- maybe filldraw can help here) --- --- Maybe in metafun: --- --- penciled n -> withpen pencircle scaled n --- applied (...) -> transformed bymatrix (...) --- withopacity n -> withtransparency (1,n) - --- When testing mbo files: --- --- empty paths --- missing control points --- funny fontnames like abcdefverdana etc --- paths representing glyphs but also with style specs --- all kind of attributes --- very weird and inefficient shading - --- One can run into pretty crazy images, like lines that are fills being clipped --- to some width. That's the danger of hiding yourself behind an interface I guess. - -local rawget, rawset, type, tonumber, tostring, next, setmetatable = rawget, rawset, type, tonumber, tostring, next, setmetatable - -local P, S, R, C, Ct, Cs, Cc, Cp, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cg, lpeg.Cf, lpeg.Carg - -local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local sqrt, abs = math.sqrt, math.abs -local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash -local gmatch, gsub, find, match, rep = string.gmatch, string.gsub, string.find, string.match, string.rep -local formatters, fullstrip = string.formatters, string.fullstrip -local utfsplit, utfbyte = utf.split, utf.byte - -local xmlconvert, xmlcollected, xmlcount, xmlfirst, xmlroot = xml.convert, xml.collected, xml.count, xml.first, xml.root -local xmltext, xmltextonly = xml.text, xml.textonly -local css = xml.css or { } -- testing - -local function xmlinheritattributes(c,pa) - local at = c.at - local dt = c.dt - if at and dt then - if pa then - setmetatableindex(at,pa) - end - for i=1,#dt do - local dti = dt[i] - if type(dti) == "table" then - xmlinheritattributes(dti,at) - end - end - else - -- comment of so - end -end - -xml.inheritattributes = xmlinheritattributes - --- Maybe some day helpers will move to the metapost.svg namespace! - -metapost = metapost or { } -local metapost = metapost -local context = context - -local report = logs.reporter("metapost","svg") - -local trace = false trackers.register("metapost.svg", function(v) trace = v end) -local trace_text = false trackers.register("metapost.svg.text", function(v) trace_text = v end) -local trace_path = false trackers.register("metapost.svg.path", function(v) trace_path = v end) -local trace_result = false trackers.register("metapost.svg.result", function(v) trace_result = v end) -local trace_colors = false trackers.register("metapost.svg.colors", function(v) trace_colors = v end) - -local pathtracer = { - ["stroke"] = "darkred", - ["stroke-opacity"] = ".5", - ["stroke-width"] = ".5", - ["fill"] = "darkgray", - ["fill-opacity"] = ".75", -} - --- This is just an experiment. Todo: reset hash etc. Also implement --- an option handler. - -local svghash = false do - - local svglast = 0 - local svglist = false - - local function checkhash(t,k) - local n = svglast + 1 - svglast = n - svglist[n] = k - t[k] = n - return n - end - - function metapost.startsvghashing() - svglast = 0 - svglist = { } - svghash = setmetatableindex(checkhash) - end - - function metapost.stopsvghashing() - svglast = 0 - svglist = false - svghash = false - end - - interfaces.implement { - name = "svghashed", - arguments = "integer", - actions = function(n) - local t = svglist and svglist[n] - if t then - context(t) - end - end - } - -end - --- We have quite some closures because otherwise we run into the local variable --- limitations. It doesn't always look pretty now, sorry. I'll clean up this mess --- some day (the usual nth iteration of code). --- --- Most of the conversion is rather trivial code till I ran into a file with arcs. A --- bit of searching lead to the a2c javascript function but it has some puzzling --- thingies (like sin and cos definitions that look like leftovers and possible --- division by zero). Anyway, we can if needed optimize it a bit more. Here does it --- come from: - --- http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes --- https://github.com/adobe-webplatform/Snap.svg/blob/b242f49e6798ac297a3dad0dfb03c0893e394464/src/path.js - -local a2c do - - local pi, sin, cos, tan, asin, abs = math.pi, math.sin, math.cos, math.tan, math.asin, math.abs - - local d120 = (pi * 120) / 180 - local pi2 = 2 * pi - - a2c = function(x1, y1, rx, ry, angle, large, sweep, x2, y2, f1, f2, cx, cy) - - if (rx == 0 or ry == 0 ) or (x1 == x2 and y1 == y2) then - return { x1, y1, x2, y2, x2, y2 } - end - - local recursive = f1 - local rad = pi / 180 * angle - local res = nil - local cosrad = cos(-rad) -- local cosrad = cosd(angle) - local sinrad = sin(-rad) -- local sinrad = sind(angle) - - if not recursive then - - x1, y1 = x1 * cosrad - y1 * sinrad, x1 * sinrad + y1 * cosrad - x2, y2 = x2 * cosrad - y2 * sinrad, x2 * sinrad + y2 * cosrad - - local x = (x1 - x2) / 2 - local y = (y1 - y2) / 2 - local xx = x * x - local yy = y * y - local h = xx / (rx * rx) + yy / (ry * ry) - - if h > 1 then - h = sqrt(h) - rx = h * rx - ry = h * ry - end - - local rx2 = rx * rx - local ry2 = ry * ry - local ry2xx = ry2 * xx - local rx2yy = rx2 * yy - local total = rx2yy + ry2xx -- otherwise overflow - - local k = total == 0 and 0 or sqrt(abs((rx2 * ry2 - rx2yy - ry2xx) / total)) - - if large == sweep then - k = -k - end - - cx = k * rx * y / ry + (x1 + x2) / 2 - cy = k * -ry * x / rx + (y1 + y2) / 2 - - f1 = (y1 - cy) / ry -- otherwise crash on a tiny eps - f2 = (y2 - cy) / ry -- otherwise crash on a tiny eps - - f1 = asin((f1 < -1.0 and -1.0) or (f1 > 1.0 and 1.0) or f1) - f2 = asin((f2 < -1.0 and -1.0) or (f2 > 1.0 and 1.0) or f2) - - if x1 < cx then f1 = pi - f1 end - if x2 < cx then f2 = pi - f2 end - - if f1 < 0 then f1 = pi2 + f1 end - if f2 < 0 then f2 = pi2 + f2 end - - if sweep ~= 0 and f1 > f2 then f1 = f1 - pi2 end - if sweep == 0 and f2 > f1 then f2 = f2 - pi2 end - - end - - if abs(f2 - f1) > d120 then - local f2old = f2 - local x2old = x2 - local y2old = y2 - f2 = f1 + d120 * ((sweep ~= 0 and f2 > f1) and 1 or -1) - x2 = cx + rx * cos(f2) - y2 = cy + ry * sin(f2) - res = a2c(x2, y2, rx, ry, angle, 0, sweep, x2old, y2old, f2, f2old, cx, cy) - end - - local c1 = cos(f1) - local s1 = sin(f1) - local c2 = cos(f2) - local s2 = sin(f2) - - local t = tan((f2 - f1) / 4) - local hx = 4 * rx * t / 3 - local hy = 4 * ry * t / 3 - - local r = { x1 - hx * s1, y1 + hy * c1, x2 + hx * s2, y2 - hy * c2, x2, y2, unpack(res or { }) } - - if not recursive then -- we can also check for sin/cos being 0/1 - cosrad = cos(rad) - sinrad = sin(rad) - -- cosrad = cosd(angle) - -- sinrad = sind(angle) - for i0=1,#r,2 do - local i1 = i0 + 1 - local x = r[i0] - local y = r[i1] - r[i0] = x * cosrad - y * sinrad - r[i1] = x * sinrad + y * cosrad - end - end - - return r - end - -end - --- We share some patterns. - -local p_digit = lpegpatterns.digit -local p_hexdigit = lpegpatterns.hexdigit -local p_space = lpegpatterns.whitespace - -local factors = { - ["pt"] = 1.25, - ["mm"] = 3.543307, - ["cm"] = 35.43307, - ["px"] = 1, - ["pc"] = 15, - ["in"] = 90, - ["em"] = 12 * 1.25, - ["ex"] = 8 * 1.25, -} - -local percentage_r = 1/100 -local percentage_x = percentage_r -local percentage_y = percentage_r - --- incredible: we can find .123.456 => 0.123 0.456 ... - -local p_command_x = C(S("Hh")) -local p_command_y = C(S("Vv")) -local p_command_xy = C(S("CcLlMmQqSsTt")) -local p_command_a = C(S("Aa")) -local p_command = C(S("Zz")) - -local p_optseparator = S("\t\n\r ,")^0 -local p_separator = S("\t\n\r ,")^1 -local p_number = (S("+-")^0 * (p_digit^0 * P(".") * p_digit^1 + p_digit^1 * P(".") + p_digit^1)) - * (P("e") * S("+-")^0 * p_digit^1)^-1 - -local function convert (n) n = tonumber(n) return n end -local function convert_r (n,u) n = tonumber(n) if u == true then return percentage_r * n elseif u then return u * n else return n end end -local function convert_x (n,u) n = tonumber(n) if u == true then return percentage_x * n elseif u then return u * n else return n end end -local function convert_y (n,u) n = tonumber(n) if u == true then return percentage_y * n elseif u then return u * n else return n end end -local function convert_vx(n,u) n = tonumber(n) if u == true then return percentage_x * n elseif u then return u * n else return n end end -local function convert_vy(n,u) n = - tonumber(n) if u == true then return percentage_y * n elseif u then return u * n else return n end end - -local p_unit = (P("p") * S("txc") + P("e") * S("xm") + S("mc") * P("m") + P("in")) / factors -local p_percent = P("%") * Cc(true) - -local c_number_n = C(p_number) -local c_number_u = C(p_number) * (p_unit + p_percent)^-1 - -local p_number_n = c_number_n / convert -local p_number_x = c_number_u / convert_x -local p_number_vx = c_number_u / convert_vx -local p_number_y = c_number_u / convert_y -local p_number_vy = c_number_u / convert_vy -local p_number_r = c_number_u / convert_r - -local function asnumber (s) return s and lpegmatch(p_number, s) or 0 end -local function asnumber_r (s) return s and lpegmatch(p_number_r, s) or 0 end -local function asnumber_x (s) return s and lpegmatch(p_number_x, s) or 0 end -local function asnumber_y (s) return s and lpegmatch(p_number_y, s) or 0 end -local function asnumber_vx(s) return s and lpegmatch(p_number_vx,s) or 0 end -local function asnumber_vy(s) return s and lpegmatch(p_number_vy,s) or 0 end - -local p_number_vx_t = Ct { (p_number_vx + p_separator)^1 } -local p_number_vy_t = Ct { (p_number_vy + p_separator)^1 } - -local zerotable = { 0 } - -local function asnumber_vx_t(s) return s and lpegmatch(p_number_vx_t,s) or zerotable end -local function asnumber_vy_t(s) return s and lpegmatch(p_number_vy_t,s) or zerotable end - -local p_numbersep = p_number_n + p_separator -local p_numbers = p_optseparator * P("(") * p_numbersep^0 * p_optseparator * P(")") -local p_fournumbers = p_numbersep^4 -local p_path = Ct ( ( - p_command_xy * (p_optseparator * p_number_vx * - p_optseparator * p_number_vy )^1 - + p_command_x * (p_optseparator * p_number_vx )^1 - + p_command_y * (p_optseparator * p_number_vy )^1 - + p_command_a * (p_optseparator * p_number_vx * - p_optseparator * p_number_vy * - p_optseparator * p_number_r * - p_optseparator * p_number_n * -- flags - p_optseparator * p_number_n * -- flags - p_optseparator * p_number_vx * - p_optseparator * p_number_vy )^1 - + p_command - + p_separator -)^1 ) - --- We can actually use the svg color definitions from the tex end but maybe a user --- doesn't want those replace the normal definitions. --- --- local hexhash = setmetatableindex(function(t,k) local v = lpegmatch(p_hexcolor, k) t[k] = v return v end) -- per file --- local hexhash3 = setmetatableindex(function(t,k) local v = lpegmatch(p_hexcolor3,k) t[k] = v return v end) -- per file --- --- local function hexcolor (c) return hexhash [c] end -- directly do hexhash [c] --- local function hexcolor3(c) return hexhash3[c] end -- directly do hexhash3[c] - -local colormap = false - -local function prepared(t) - if type(t) == "table" then - local mapping = t.mapping or { } - local mapper = t.mapper - local colormap = setmetatableindex(mapping) - if mapper then - setmetatableindex(colormap,function(t,k) - local v = mapper(k) - t[k] = v or k - return v - end) - end - return colormap - else - return false - end -end - -local colormaps = setmetatableindex(function(t,k) - local v = false - if type(k) == "string" then - v = prepared(table.load(k)) -- todo: same path as svg file - elseif type(k) == "table" then - v = prepared(k) - k = k.name or k - end - t[k] = v - return v -end) - -function metapost.svgcolorremapper(colormap) - return colormaps[colormap] -end - --- todo: cache colors per image / remapper - -local colorcomponents, withcolor, thecolor, usedcolors do - - local svgcolors = { - aliceblue = 0xF0F8FF, antiquewhite = 0xFAEBD7, aqua = 0x00FFFF, aquamarine = 0x7FFFD4, - azure = 0xF0FFFF, beige = 0xF5F5DC, bisque = 0xFFE4C4, black = 0x000000, - blanchedalmond = 0xFFEBCD, blue = 0x0000FF, blueviolet = 0x8A2BE2, brown = 0xA52A2A, - burlywood = 0xDEB887, cadetblue = 0x5F9EA0, hartreuse = 0x7FFF00, chocolate = 0xD2691E, - coral = 0xFF7F50, cornflowerblue = 0x6495ED, cornsilk = 0xFFF8DC, crimson = 0xDC143C, - cyan = 0x00FFFF, darkblue = 0x00008B, darkcyan = 0x008B8B, darkgoldenrod = 0xB8860B, - darkgray = 0xA9A9A9, darkgreen = 0x006400, darkgrey = 0xA9A9A9, darkkhaki = 0xBDB76B, - darkmagenta = 0x8B008B, darkolivegreen = 0x556B2F, darkorange = 0xFF8C00, darkorchid = 0x9932CC, - darkred = 0x8B0000, darksalmon = 0xE9967A, darkseagreen = 0x8FBC8F, darkslateblue = 0x483D8B, - darkslategray = 0x2F4F4F, darkslategrey = 0x2F4F4F, darkturquoise = 0x00CED1, darkviolet = 0x9400D3, - deeppink = 0xFF1493, deepskyblue = 0x00BFFF, dimgray = 0x696969, dimgrey = 0x696969, - dodgerblue = 0x1E90FF, firebrick = 0xB22222, floralwhite = 0xFFFAF0, forestgreen = 0x228B22, - fuchsia = 0xFF00FF, gainsboro = 0xDCDCDC, ghostwhite = 0xF8F8FF, gold = 0xFFD700, - goldenrod = 0xDAA520, gray = 0x808080, green = 0x008000, greenyellow = 0xADFF2F, - grey = 0x808080, honeydew = 0xF0FFF0, hotpink = 0xFF69B4, indianred = 0xCD5C5C, - indigo = 0x4B0082, ivory = 0xFFFFF0, khaki = 0xF0E68C, lavender = 0xE6E6FA, - lavenderblush = 0xFFF0F5, lawngreen = 0x7CFC00, lemonchiffon = 0xFFFACD, lightblue = 0xADD8E6, - lightcoral = 0xF08080, lightcyan = 0xE0FFFF, lightgoldenrodyellow = 0xFAFAD2, lightgray = 0xD3D3D3, - lightgreen = 0x90EE90, lightgrey = 0xD3D3D3, lightpink = 0xFFB6C1, lightsalmon = 0xFFA07A, - lightseagreen = 0x20B2AA, lightskyblue = 0x87CEFA, lightslategray = 0x778899, lightslategrey = 0x778899, - lightsteelblue = 0xB0C4DE, lightyellow = 0xFFFFE0, lime = 0x00FF00, limegreen = 0x32CD32, - linen = 0xFAF0E6, magenta = 0xFF00FF, maroon = 0x800000, mediumaquamarine = 0x66CDAA, - mediumblue = 0x0000CD, mediumorchid = 0xBA55D3, mediumpurple = 0x9370DB, mediumseagreen = 0x3CB371, - mediumslateblue = 0x7B68EE, mediumspringgreen = 0x00FA9A, mediumturquoise = 0x48D1CC, mediumvioletred = 0xC71585, - midnightblue = 0x191970, mintcream = 0xF5FFFA, mistyrose = 0xFFE4E1, moccasin = 0xFFE4B5, - navajowhite = 0xFFDEAD, navy = 0x000080, oldlace = 0xFDF5E6, olive = 0x808000, - olivedrab = 0x6B8E23, orange = 0xFFA500, orangered = 0xFF4500, orchid = 0xDA70D6, - palegoldenrod = 0xEEE8AA, palegreen = 0x98FB98, paleturquoise = 0xAFEEEE, palevioletred = 0xDB7093, - papayawhip = 0xFFEFD5, peachpuff = 0xFFDAB9, peru = 0xCD853F, pink = 0xFFC0CB, - plum = 0xDDA0DD, powderblue = 0xB0E0E6, purple = 0x800080, red = 0xFF0000, - rosybrown = 0xBC8F8F, royalblue = 0x4169E1, saddlebrown = 0x8B4513, salmon = 0xFA8072, - sandybrown = 0xF4A460, seagreen = 0x2E8B57, seashell = 0xFFF5EE, sienna = 0xA0522D, - silver = 0xC0C0C0, skyblue = 0x87CEEB, slateblue = 0x6A5ACD, slategray = 0x708090, - slategrey = 0x708090, snow = 0xFFFAFA, springgreen = 0x00FF7F, steelblue = 0x4682B4, - tan = 0xD2B48C, teal = 0x008080, thistle = 0xD8BFD8, tomato = 0xFF6347, - turquoise = 0x40E0D0, violet = 0xEE82EE, wheat = 0xF5DEB3, white = 0xFFFFFF, - whitesmoke = 0xF5F5F5, yellow = 0xFFFF00, yellowgreen = 0x9ACD32, - } - - local f_rgb = formatters['withcolor svgcolor(%.3N,%.3N,%.3N)'] - local f_cmyk = formatters['withcolor svgcmyk(%.3N,%.3N,%.3N,%.3N)'] - local f_gray = formatters['withcolor svggray(%.3N)'] - local f_rgba = formatters['withcolor svgcolor(%.3N,%.3N,%.3N) withtransparency (1,%.3N)'] - local f_graya = formatters['withcolor svggray(%.3N) withtransparency (1,%.3N)'] - local f_name = formatters['withcolor "%s"'] - local f_svgrgb = formatters['svgcolor(%.3N,%.3N,%.3N)'] - local f_svgcmyk = formatters['svgcmyk(%.3N,%.3N,%.3N,%.3N)'] - local f_svggray = formatters['svggray(%.3N)'] - local f_svgname = formatters['"%s"'] - - local extract = bit32.extract - - local triplets = setmetatableindex(function(t,k) - -- we delay building all these strings - local v = svgcolors[k] - if v then - v = { extract(v,16,8)/255, extract(v,8,8)/255, extract(v,0,8)/255 } - else - v = false - end - t[k] = v - return v - end) - - local p_fraction = C(p_number) * C("%")^-1 / function(a,b) return tonumber(a) / (b and 100 or 255) end - local p_angle = C(p_number) * P("deg")^0 / function(a) return tonumber(a) end - local p_percent = C(p_number) * P("%") / function(a) return tonumber(a) / 100 end - local p_absolute = C(p_number) / tonumber - - local p_left = P("(") - local p_right = P(")") - local p_a = P("a")^-1 - local p_h_a_color = p_left - * p_angle - * p_separator * p_percent - * p_separator * p_percent - * p_separator^0 * p_absolute^0 - * p_right - - local colors = attributes.colors - local colorvalues = colors.values - local colorindex = attributes.list[attributes.private('color')] - local hsvtorgb = colors.hsvtorgb - local hwbtorgb = colors.hwbtorgb - local forcedmodel = colors.forcedmodel - - local p_splitcolor = - P("#") * C(p_hexdigit*p_hexdigit)^1 / function(r,g,b) - if not r then - return "gray", 0 - elseif not (g and b) then - return "gray", tonumber(r or "0", 16) / 255 or 0 - else - return "rgb", - tonumber(r or "0", 16) / 255 or 0, - tonumber(g or "0", 16) / 255 or 0, - tonumber(b or "0", 16) / 255 or 0 - end - end - + P("rgb") * p_a - * p_left * (p_fraction + p_separator)^-3 * (p_absolute + p_separator)^0 * p_right / function(r,g,b,a) - return "rgb", r or 0, g or 0, b or 0, a or false - end - + P("cmyk") - * p_left * (p_absolute + p_separator)^0 * p_right / function(c,m,y,k) - return "cmyk", c or 0, m or 0, y or 0, k or 0 - end - + P("hsl") * p_a - * p_h_a_color / function(h,s,l,a) - local r, g, b = hsvtorgb(h,s,l,a) - return "rgb", r or 0, g or 0, b or 0, a or false - end - + P("hwb") * p_a - * p_h_a_color / function(h,w,b,a) - local r, g, b = hwbtorgb(h,w,b) - return "rgb", r or 0, g or 0, b or 0, a or false - end - - function metapost.svgsplitcolor(color) - if type(color) == "string" then - local what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) - if not what then - local t = triplets[color] - if t then - what, s1, s2, s3 = "rgb", t[1], t[2], t[3] - end - end - return what, s1, s2, s3, s4 - else - return "gray", 0, false - end - end - - local function registeredcolor(name) - local color = colorindex[name] - if color then - local v = colorvalues[color] - local t = forcedmodel(v[1]) - if t == 2 then - return "gray", v[2] - elseif t == 3 then - return "rgb", v[3], v[4], v[5] - elseif t == 4 then - return "cmyk", v[6], v[7], v[8], v[9] - else - -- - end - end - end - - -- we can have a fast check for #000000 - - local function validcolor(color) - if usedcolors then - usedcolors[color] = usedcolors[color] + 1 - end - if colormap then - local c = colormap[color] - local t = type(c) - if t == "table" then - local what = t[1] - if what == "rgb" then - return - what, - tonumber(t[2]) or 0, - tonumber(t[3]) or 0, - tonumber(t[4]) or 0, - tonumber(t[4]) or false - elseif what == "cmyk" then - return - what, - tonumber(t[2]) or 0, - tonumber(t[3]) or 0, - tonumber(t[4]) or 0, - tonumber(t[5]) or 0 - elseif what == "gray" then - return - what, - tonumber(t[2]) or 0, - tonumber(t[3]) or false - end - elseif t == "string" then - color = c - end - end - local what, s1, s2, s3, s4 = registeredcolor(color) - if what then - return what, s1, s2, s3, s4 - end - what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) - if not what then - local t = triplets[color] - if t then - s1, s3, s3 = t[1], t[2], t[3] - what = "rgb" - end - end - return what, s1, s2, s3, s4 - end - - colorcomponents = function(color) - local what, s1, s2, s3, s4 = validcolor(color) - return s1, s2, s3, s4 -- so 4 means cmyk - end - - withcolor = function(color) - local what, s1, s2, s3, s4 = validcolor(color) - -- print(color,what, s1, s2, s3, s4) - if what == "rgb" then - if s4 then - if s1 == s2 and s1 == s3 then - return f_graya(s1,s4) - else - return f_rgba(s1,s2,s3,s4) - end - else - if s1 == s2 and s1 == s3 then - return f_gray(s1) - else - return f_rgb(s1,s2,s3) - end - end - elseif what == "cmyk" then - return f_cmyk(s1,s2,s3,s4) - elseif what == "gray" then - if s2 then - return f_graya(s1,s2) - else - return f_gray(s1) - end - end - return f_name(color) - end - - thecolor = function(color) - local what, s1, s2, s3, s4 = validcolor(color) - if what == "rgb" then - if s4 then - if s1 == s2 and s1 == s3 then - return f_svggraya(s1,s4) - else - return f_svgrgba(s1,s2,s3,s4) - end - else - if s1 == s2 and s1 == s3 then - return f_svggray(s1) - else - return f_svgrgb(s1,s2,s3) - end - end - elseif what == "cmyk" then - return f_cmyk(s1,s2,s3,s4) - elseif what == "gray" then - if s2 then - return f_svggraya(s1,s2) - else - return f_svggray(s1) - end - end - return f_svgname(color) - end - -end - --- actually we can loop faster because we can go to the last one - -local grabpath, grablist do - - local f_moveto = formatters['(%N,%N)'] - local f_curveto_z = formatters['controls(%N,%N)and(%N,%N)..(%N,%N)'] - local f_curveto_n = formatters['..controls(%N,%N)and(%N,%N)..(%N,%N)'] - local f_lineto_z = formatters['(%N,%N)'] - local f_lineto_n = formatters['--(%N,%N)'] - - local m = { __index = function() return 0 end } - - grabpath = function(str) - local p = lpegmatch(p_path,str) or { } - local np = #p - local all = { entries = np, closed = false, curve = false } - if np == 0 then - return all - end - setmetatable(p,m) - local t = { } -- no real saving here if we share - local n = 0 - local a = 0 - local i = 0 - local last = "M" - local prev = last - local kind = "L" - local x, y = 0, 0 - local x1, y1 = 0, 0 - local x2, y2 = 0, 0 - local rx, ry = 0, 0 - local ar, al = 0, 0 - local as, ac = 0, nil - local mx, my = 0, 0 - while i < np do - i = i + 1 - local pi = p[i] - if type(pi) ~= "number" then - last = pi - i = i + 1 - pi = p[i] - end - -- most often - if last == "c" then - x1 = x + pi - i = i + 1 ; y1 = y + p[i] - i = i + 1 ; x2 = x + p[i] - i = i + 1 ; y2 = y + p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto curveto - elseif last == "l" then - x = x + pi - i = i + 1 ; y = y + p[i] - goto lineto - elseif last == "h" then - x = x + pi - goto lineto - elseif last == "v" then - y = y + pi - goto lineto - elseif last == "a" then - x1 = x - y1 = y - rx = pi - i = i + 1 ; ry = p[i] - i = i + 1 ; ar = p[i] - i = i + 1 ; al = p[i] - i = i + 1 ; as = p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto arc - elseif last == "s" then - if prev == "C" then - x1 = 2 * x - x2 - y1 = 2 * y - y2 - else - x1 = x - y1 = y - end - x2 = x + pi - i = i + 1 ; y2 = y + p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto curveto - elseif last == "m" then - if n > 0 then - a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 - end - x = x + pi - i = i + 1 ; y = y + p[i] - goto moveto - elseif last == "z" then - goto close - -- less frequent - elseif last == "C" then - x1 = pi - i = i + 1 ; y1 = p[i] - i = i + 1 ; x2 = p[i] - i = i + 1 ; y2 = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto curveto - elseif last == "L" then - x = pi - i = i + 1 ; y = p[i] - goto lineto - elseif last == "H" then - x = pi - goto lineto - elseif last == "V" then - y = pi - goto lineto - elseif last == "A" then - x1 = x - y1 = y - rx = pi - i = i + 1 ; ry = p[i] - i = i + 1 ; ar = p[i] - i = i + 1 ; al = p[i] - i = i + 1 ; as = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto arc - elseif last == "S" then - if prev == "C" then - x1 = 2 * x - x2 - y1 = 2 * y - y2 - else - x1 = x - y1 = y - end - x2 = pi - i = i + 1 ; y2 = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto curveto - elseif last == "M" then - if n > 0 then - a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 - end - x = pi ; - i = i + 1 ; y = p[i] - goto moveto - elseif last == "Z" then - goto close - -- very seldom - elseif last == "q" then - x1 = x + pi - i = i + 1 ; y1 = y + p[i] - i = i + 1 ; x2 = x + p[i] - i = i + 1 ; y2 = y + p[i] - goto quadratic - elseif last == "t" then - if prev == "C" then - x1 = 2 * x - x1 - y1 = 2 * y - y1 - else - x1 = x - y1 = y - end - x2 = x + pi - i = i + 1 ; y2 = y + p[i] - goto quadratic - elseif last == "Q" then - x1 = pi - i = i + 1 ; y1 = p[i] - i = i + 1 ; x2 = p[i] - i = i + 1 ; y2 = p[i] - goto quadratic - elseif last == "T" then - if prev == "C" then - x1 = 2 * x - x1 - y1 = 2 * y - y1 - else - x1 = x - y1 = y - end - x2 = pi - i = i + 1 ; y2 = p[i] - goto quadratic - else - goto continue - end - ::moveto:: - n = n + 1 ; t[n] = f_moveto(x,y) - last = last == "M" and "L" or "l" - prev = "M" - mx = x - my = y - goto continue - ::lineto:: - n = n + 1 ; t[n] = (n > 0 and f_lineto_n or f_lineto_z)(x,y) - prev = "L" - goto continue - ::curveto:: - n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)(x1,y1,x2,y2,x,y) - prev = "C" - goto continue - ::arc:: - ac = a2c(x1,y1,rx,ry,ar,al,as,x,y) - for i=1,#ac,6 do - n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)( - ac[i],ac[i+1],ac[i+2],ac[i+3],ac[i+4],ac[i+5] - ) - end - prev = "A" - goto continue - ::quadratic:: - n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)( - x + 2/3 * (x1-x ), y + 2/3 * (y1-y ), - x2 + 2/3 * (x1-x2), y2 + 2/3 * (y1-y2), - x2, y2 - ) - x = x2 - y = y2 - prev = "C" - goto continue - ::close:: - -- n = n + 1 ; t[n] = prev == "C" and "..cycle" or "--cycle" - n = n + 1 ; t[n] = "--cycle" - if n > 0 then - a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 - end - if i == np then - break - else - i = i - 1 - end - kind = prev - prev = "Z" - -- this is kind of undocumented: a close also moves back - x = mx - y = my - ::continue:: - end - if n > 0 then - a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 - end - if prev == "Z" then - all.closed = true - end - all.curve = (kind == "C" or kind == "A") - return all, p - end - - -- this is a bit tricky as what are points for a mark ... the next can be simplified - -- a lot - - grablist = function(p) - local np = #p - if np == 0 then - return nil - end - local t = { } - local n = 0 - local a = 0 - local i = 0 - local last = "M" - local prev = last - local kind = "L" - local x, y = 0, 0 - local x1, y1 = 0, 0 - local x2, y2 = 0, 0 - local rx, ry = 0, 0 - local ar, al = 0, 0 - local as, ac = 0, nil - local mx, my = 0, 0 - while i < np do - i = i + 1 - local pi = p[i] - if type(pi) ~= "number" then - last = pi - i = i + 1 - pi = p[i] - end - -- most often - if last == "c" then - x1 = x + pi - i = i + 1 ; y1 = y + p[i] - i = i + 1 ; x2 = x + p[i] - i = i + 1 ; y2 = y + p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto curveto - elseif last == "l" then - x = x + pi - i = i + 1 ; y = y + p[i] - goto lineto - elseif last == "h" then - x = x + pi - goto lineto - elseif last == "v" then - y = y + pi - goto lineto - elseif last == "a" then - x1 = x - y1 = y - rx = pi - i = i + 1 ; ry = p[i] - i = i + 1 ; ar = p[i] - i = i + 1 ; al = p[i] - i = i + 1 ; as = p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto arc - elseif last == "s" then - if prev == "C" then - x1 = 2 * x - x2 - y1 = 2 * y - y2 - else - x1 = x - y1 = y - end - x2 = x + pi - i = i + 1 ; y2 = y + p[i] - i = i + 1 ; x = x + p[i] - i = i + 1 ; y = y + p[i] - goto curveto - elseif last == "m" then - x = x + pi - i = i + 1 ; y = y + p[i] - goto moveto - elseif last == "z" then - goto close - -- less frequent - elseif last == "C" then - x1 = pi - i = i + 1 ; y1 = p[i] - i = i + 1 ; x2 = p[i] - i = i + 1 ; y2 = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto curveto - elseif last == "L" then - x = pi - i = i + 1 ; y = p[i] - goto lineto - elseif last == "H" then - x = pi - goto lineto - elseif last == "V" then - y = pi - goto lineto - elseif last == "A" then - x1 = x - y1 = y - rx = pi - i = i + 1 ; ry = p[i] - i = i + 1 ; ar = p[i] - i = i + 1 ; al = p[i] - i = i + 1 ; as = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto arc - elseif last == "S" then - if prev == "C" then - x1 = 2 * x - x2 - y1 = 2 * y - y2 - else - x1 = x - y1 = y - end - x2 = pi - i = i + 1 ; y2 = p[i] - i = i + 1 ; x = p[i] - i = i + 1 ; y = p[i] - goto curveto - elseif last == "M" then - x = pi ; - i = i + 1 ; y = p[i] - goto moveto - elseif last == "Z" then - goto close - -- very seldom - elseif last == "q" then - x1 = x + pi - i = i + 1 ; y1 = y + p[i] - i = i + 1 ; x2 = x + p[i] - i = i + 1 ; y2 = y + p[i] - goto quadratic - elseif last == "t" then - if prev == "C" then - x1 = 2 * x - x1 - y1 = 2 * y - y1 - else - x1 = x - y1 = y - end - x2 = x + pi - i = i + 1 ; y2 = y + p[i] - goto quadratic - elseif last == "Q" then - x1 = pi - i = i + 1 ; y1 = p[i] - i = i + 1 ; x2 = p[i] - i = i + 1 ; y2 = p[i] - goto quadratic - elseif last == "T" then - if prev == "C" then - x1 = 2 * x - x1 - y1 = 2 * y - y1 - else - x1 = x - y1 = y - end - x2 = pi - i = i + 1 ; y2 = p[i] - goto quadratic - else - goto continue - end - ::moveto:: - n = n + 1 ; t[n] = x - n = n + 1 ; t[n] = y - last = last == "M" and "L" or "l" - prev = "M" - mx = x - my = y - goto continue - ::lineto:: - n = n + 1 ; t[n] = x - n = n + 1 ; t[n] = y - prev = "L" - goto continue - ::curveto:: - n = n + 1 ; t[n] = x - n = n + 1 ; t[n] = y - prev = "C" - goto continue - ::arc:: - ac = a2c(x1,y1,rx,ry,ar,al,as,x,y) - for i=1,#ac,6 do - n = n + 1 ; t[n] = ac[i+4] - n = n + 1 ; t[n] = ac[i+5] - end - prev = "A" - goto continue - ::quadratic:: - n = n + 1 ; t[n] = x2 - n = n + 1 ; t[n] = y2 - x = x2 - y = y2 - prev = "C" - goto continue - ::close:: - n = n + 1 ; t[n] = mx - n = n + 1 ; t[n] = my - if i == np then - break - end - kind = prev - prev = "Z" - x = mx - y = my - ::continue:: - end - return t - end - -end - --- todo: viewbox helper - -local s_wrapped_start = "draw image (" -local f_wrapped_stop = formatters[") shifted (0,%N) scaled %N ;"] - -local handletransform, handleviewbox do - - local sind = math.sind - - --todo: better lpeg - - local f_rotatedaround = formatters[" rotatedaround((%N,%N),%N)"] - local f_rotated = formatters[" rotated(%N)"] - local f_shifted = formatters[" shifted(%N,%N)"] - local f_slanted_x = formatters[" xslanted(%N)"] - local f_slanted_y = formatters[" yslanted(%N)"] - local f_scaled = formatters[" scaled(%N)"] - local f_xyscaled = formatters[" xyscaled(%N,%N)"] - local f_matrix = formatters[" transformed bymatrix(%N,%N,%N,%N,%N,%N)"] - - local s_transform_start = "draw image ( " - local f_transform_stop = formatters[")%s ;"] - - local function rotate(r,x,y) - if x then - return r and f_rotatedaround(x,-(y or x),-r) - elseif r then - return f_rotated(-r) - else - return "" - end - end - - local function translate(x,y) - if y then - return f_shifted(x,-y) - elseif x then - return f_shifted(x,0) - else - return "" - end - end - - local function scale(x,y) - if y then - return f_xyscaled(x,y) - elseif x then - return f_scaled(x) - else - return "" - end - end - - local function skewx(x) - if x then - return f_slanted_x(sind(-x)) - else - return "" - end - end - - local function skewy(y) - if y then - return f_slanted_y(sind(-y)) - else - return "" - end - end - - local function matrix(rx,sx,sy,ry,tx,ty) - return f_matrix(rx or 1, sx or 0, sy or 0, ry or 1, tx or 0, - (ty or 0)) - end - - -- How to deal with units here? Anyway, order seems to matter. - - local p_transform = Cf ( Ct("") * ( - lpegpatterns.whitespace^0 * Cg( - C("translate") * (p_numbers / translate) -- maybe xy - + C("scale") * (p_numbers / scale) - + C("rotate") * (p_numbers / rotate) - + C("matrix") * (p_numbers / matrix) - + C("skewX") * (p_numbers / skewx) - + C("skewY") * (p_numbers / skewy) - ) - )^1, rawset) - - handletransform = function(at) - local t = at.transform - if t then - local e = lpegmatch(p_transform,t) - if e then - e = concat({ - e.rotate or "", - e.skewX or "", - e.skewY or "", - e.scale or "", - e.translate or "", - e.matrix or "", - }, " ") - return s_transform_start, f_transform_stop(e), t - end - end - end - - handleviewbox = function(v) - if v then - local x, y, w, h = lpegmatch(p_fournumbers,v) - if h then - return x, y, w, h - end - end - end - -end - -local dashed do - - -- actually commas are mandate but we're tolerant - - local f_dashed_n = formatters[" dashed dashpattern (%s ) "] - local f_dashed_y = formatters[" dashed dashpattern (%s ) shifted (%N,0) "] - - local p_number = p_optseparator/"" * p_number_r - local p_on = Cc(" on ") * p_number - local p_off = Cc(" off ") * p_number - local p_dashed = Cs((p_on * p_off^-1)^1) - - dashed = function(s,o) - if not find(s,",") then - -- a bit of a hack: - s = s .. " " .. s - end - return (o and f_dashed_y or f_dashed_n)(lpegmatch(p_dashed,s),o) - end - -end - -do - - local handlers = { } - local process = false - local root = false - local result = false - local r = false - local definitions = false - local classstyles = false - local tagstyles = false - - local tags = { - ["a"] = true, - -- ["altgGlyph"] = true, - -- ["altgGlyphDef"] = true, - -- ["altgGlyphItem"] = true, - -- ["animate"] = true, - -- ["animateColor"] = true, - -- ["animateMotion"] = true, - -- ["animateTransform"] = true, - ["circle"] = true, - ["clipPath"] = true, - -- ["color-profile"] = true, - -- ["cursor"] = true, - ["defs"] = true, - -- ["desc"] = true, - ["ellipse"] = true, - -- ["filter"] = true, - -- ["font"] = true, - -- ["font-face"] = true, - -- ["font-face-format"] = true, - -- ["font-face-name"] = true, - -- ["font-face-src"] = true, - -- ["font-face-uri"] = true, - -- ["foreignObject"] = true, - ["g"] = true, - -- ["glyph"] = true, - -- ["glyphRef"] = true, - -- ["hkern"] = true, - ["image"] = true, - ["line"] = true, - ["linearGradient"] = true, - ["marker"] = true, - -- ["mask"] = true, - -- ["metadata"] = true, - -- ["missing-glyph"] = true, - -- ["mpath"] = true, - ["path"] = true, - -- ["pattern"] = true, - ["polygon"] = true, - ["polyline"] = true, - ["radialGradient"] = true, - ["rect"] = true, - -- ["script"] = true, - -- ["set"] = true, - ["stop"] = true, - ["style"] = true, - ["svg"] = true, - -- ["switch"] = true, - ["symbol"] = true, - ["text"] = true, - -- ["textPath"] = true, - -- ["title"] = true, - ["tspan"] = true, - ["use"] = true, - -- ["view"] = true, - -- ["vkern"] = true, - } - - local function handlechains(c) - if tags[c.tg] then - local at = c.at - local dt = c.dt - if at and dt then - -- at["inkscape:connector-curvature"] = nil -- cleare entry and might prevent table growth - local estyle = rawget(at,"style") - if estyle and estyle ~= "" then - for k, v in gmatch(estyle,"%s*([^:]+):%s*([^;]+);?") do - at[k] = v - end - end - local eclass = rawget(at,"class") - if eclass and eclass ~= "" then - for c in gmatch(eclass,"[^ ]+") do - local s = classstyles[c] - if s then - for k, v in next, s do - at[k] = v - end - end - end - end - local tstyle = tagstyles[tag] - if tstyle then - for k, v in next, tstyle do - at[k] = v - end - end - if trace_path and pathtracer then - for k, v in next, pathtracer do - at[k] = v - end - end - for i=1,#dt do - local dti = dt[i] - if type(dti) == "table" then - handlechains(dti) - end - end - end - end - end - - local handlestyle do - - -- It can also be CDATA but that is probably dealt with because we only - -- check for style entries and ignore the rest. But maybe we also need - -- to check a style at the outer level? - - local p_key = C((R("az","AZ","09","__","--")^1)) - local p_spec = P("{") * C((1-P("}"))^1) * P("}") - local p_valid = Carg(1) * P(".") * p_key + Carg(2) * p_key - local p_grab = ((p_valid * p_space^0 * p_spec / rawset) + p_space^1 + P(1))^1 - - local fontspecification = css.fontspecification - - handlestyle = function(c) - local s = xmltext(c) - lpegmatch(p_grab,s,1,classstyles,tagstyles) - for k, v in next, classstyles do - local t = { } - for k, v in gmatch(v,"%s*([^:]+):%s*([^;]+);?") do - if k == "font" then - local s = fontspecification(v) - for k, v in next, s do - t["font-"..k] = v - end - else - t[k] = v - end - end - classstyles[k] = t - end - for k, v in next, tagstyles do - local t = { } - for k, v in gmatch(v,"%s*([^:]+):%s*([^;]+);?") do - if k == "font" then - local s = fontspecification(v) - for k, v in next, s do - t["font-"..k] = v - end - else - t[k] = v - end - end - tagstyles[k] = t - end - end - - function handlers.style() - -- ignore - end - - end - - -- We can have root in definitions and then do a metatable lookup but use - -- is not used that often I guess. - - local function locate(id) - local res = definitions[id] - if res then - return res - end - local ref = gsub(id,"^url%(#(.-)%)$","%1") - local ref = gsub(ref,"^#","") - -- we can make a fast id lookup - local res = xmlfirst(root,"**[@id='"..ref.."']") - if res then - definitions[id] = res - end - return res - end - - -- also locate - - local function handleclippath(at) - local clippath = at["clip-path"] - - if not clippath then - return - end - - local spec = definitions[clippath] or locate(clippath) - - -- do we really need thsi crap - if not spec then - local index = match(clippath,"(%d+)") - if index then - spec = xmlfirst(root,"clipPath["..tostring(tonumber(index) or 0).."]") - end - end - -- so far for the crap - - if not spec then - report("unknown clip %a",clippath) - return - elseif spec.tg ~= "clipPath" then - report("bad clip %a",clippath) - return - end - - ::again:: - for c in xmlcollected(spec,"/(path|use|g)") do - local tg = c.tg - if tg == "use" then - local ca = c.at - local id = ca["xlink:href"] - if id then - spec = locate(id) - if spec then - local sa = spec.at - setmetatableindex(sa,ca) - if spec.tg == "path" then - local d = sa.d - if d then - local p = grabpath(d) - p.evenodd = sa["clip-rule"] == "evenodd" - p.close = true - return p, clippath - else - return - end - else - goto again - end - end - end - -- break - elseif tg == "path" then - local ca = c.at - local d = ca.d - if d then - local p = grabpath(d) - p.evenodd = ca["clip-rule"] == "evenodd" - p.close = true - return p, clippath - else - return - end - else - -- inherit? - end - end - end - - local s_shade_linear = ' withshademethod "linear" ' - local s_shade_circular = ' withshademethod "circular" ' - local f_shade_step = formatters['withshadestep ( withshadefraction %N withshadecolors(%s,%s) )'] - local f_shade_one = formatters['withprescript "sh_center_a=%N %N"'] - local f_shade_two = formatters['withprescript "sh_center_b=%N %N"'] - - local f_color = formatters['withcolor "%s"'] - local f_opacity = formatters['withtransparency (1,%N)'] - local f_pen = formatters['withpen pencircle scaled %N'] - - -- todo: gradient unfinished - -- todo: opacity but first we need groups in mp - - local function gradient(id) - local spec = definitions[id] -- no locate ! - if spec then - local kind = spec.tg - local shade = nil - local n = 1 - local a = spec.at - if kind == "linearGradient" then - shade = { s_shade_linear } - -- - local x1 = rawget(a,"x1") - local y1 = rawget(a,"y1") - local x2 = rawget(a,"x2") - local y2 = rawget(a,"y2") - if x1 and y1 then - n = n + 1 ; shade[n] = f_shade_one(asnumber_vx(x1),asnumber_vy(y1)) - end - if x2 and y2 then - n = n + 1 ; shade[n] = f_shade_one(asnumber_vx(x2),asnumber_vy(y2)) - end - -- - elseif kind == "radialGradient" then - shade = { s_shade_circular } - -- - local cx = rawget(a,"cx") -- x center - local cy = rawget(a,"cy") -- y center - local r = rawget(a,"r" ) -- radius - local fx = rawget(a,"fx") -- focal points - local fy = rawget(a,"fy") -- focal points - -- - if cx and cy then - -- todo - end - if r then - -- todo - end - if fx and fy then - -- todo - end - else - report("unknown gradient %a",id) - return - end - -- local gu = a.gradientUnits - -- local gt = a.gradientTransform - -- local sm = a.spreadMethod - local colora, colorb - -- startcolor ? - for c in xmlcollected(spec,"/stop") do - local a = c.at - local offset = rawget(a,"offset") - local colorb = rawget(a,"stop-color") - local opacity = rawget(a,"stop-opacity") - if colorb then - colorb = thecolor(colorb) - end - if not colora then - colora = colorb - end - -- what if no percentage - - local fraction = offset and asnumber_r(offset) - if not fraction then - -- offset = tonumber(offset) - -- for now - fraction = xmlcount(spec,"/stop")/100 - end - - if colora and colorb and color_a ~= "" and color_b ~= "" then - n = n + 1 ; shade[n] = f_shade_step(fraction,colora,colorb) - end - - colora = colorb - end - return concat(shade," ") - end - end - - local function drawproperties(stroke,at,opacity) - local p = at["stroke-width"] - if p then - p = f_pen(asnumber_r(p)) - end - local d = at["stroke-dasharray"] - if d == "none" then - d = nil - elseif d then - local o = at["stroke-dashoffset"] - if o and o ~= "none" then - o = asnumber_r(o) - else - o = false - end - d = dashed(d,o) - end - local c = withcolor(stroke) - local o = at["stroke-opacity"] or (opacity and at["opacity"]) - if o == "none" then - o = nil - elseif o then - o = asnumber_r(o) - if o and o ~= 1 then - o = f_opacity(o) - else - o = nil - end - end - return p, d, c, o - end - - local s_opacity_start = "draw image (" - local f_opacity_stop = formatters["setgroup currentpicture to boundingbox currentpicture withtransparency (1,%N)) ;"] - - local function sharedopacity(at) - local o = at["opacity"] - if o and o ~= "none" then - o = asnumber_r(o) - if o and o ~= 1 then - return s_opacity_start, f_opacity_stop(o) - end - end - end - - local function fillproperties(fill,at,opacity) - local c = c ~= "none" and (gradient(fill) or withcolor(fill)) or nil - local o = at["fill-opacity"] or (opacity and at["opacity"]) - if o and o ~= "none" then - o = asnumber_r(o) - if o == 1 then - return c - elseif o then - return c, f_opacity(o), o == 0 - end - end - return c - end - - -- todo: clip = [ auto | rect(llx,lly,urx,ury) ] - - local s_offset_start = "draw image ( " - local f_offset_stop = formatters[") shifted (%N,%N) ;"] - local s_rotation_start = "draw image ( " - local f_rotation_stop = formatters[") rotatedaround((0,0),-angle((%N,%N))) ;"] - local f_rotation_angle = formatters[") rotatedaround((0,0),-%N) ;"] - - local function offset(at) - local x = asnumber_vx(rawget(at,"x")) - local y = asnumber_vy(rawget(at,"y")) - if x ~= 0 or y ~= 0 then - return s_offset_start, f_offset_stop(x,y) - end - end - - local s_viewport_start = "draw image (" - local s_viewport_stop = ") ;" - local f_viewport_shift = formatters["currentpicture := currentpicture shifted (%03N,%03N);"] - local f_viewport_scale = formatters["currentpicture := currentpicture xysized (%03N,%03N);"] - local f_viewport_clip = formatters["clip currentpicture to (unitsquare xyscaled (%03N,%03N));"] - - local function viewport(x,y,w,h,noclip,scale) - r = r + 1 ; result[r] = s_viewport_start - return function() - local okay = w ~= 0 and h ~= 0 - if okay and scale then - r = r + 1 ; result[r] = f_viewport_scale(w,h) - end - if x ~= 0 or y ~= 0 then - r = r + 1 ; result[r] = f_viewport_shift(-x,y) - end - if okay and not noclip then - r = r + 1 ; result[r] = f_viewport_clip(w,-h) - end - - r = r + 1 ; result[r] = s_viewport_stop - end - end - - -- maybe forget about defs and just always locate (and then backtrack - -- over if needed) - - function handlers.defs(c) - for c in xmlcollected(c,"/*") do - local a = c.at - if a then - local id = rawget(a,"id") - if id then - definitions["#" .. id ] = c - definitions["url(#" .. id .. ")"] = c - end - end - end - end - - function handlers.symbol(c) - if uselevel == 0 then - local id = rawget(c.at,"id") - if id then - definitions["#" .. id ] = c - definitions["url(#" .. id .. ")"] = c - end - else - handlers.g(c) - end - end - - local uselevel = 0 - - function handlers.use(c) - local at = c.at - local id = rawget(at,"href") or rawget(at,"xlink:href") -- better a rawget - local res = locate(id) - if res then - -- width height ? - uselevel = uselevel + 1 - local boffset, eoffset = offset(at) - local btransform, etransform, transform = handletransform(at) - - if boffset then - r = r + 1 result[r] = boffset - end - - -- local clippath = at.clippath - - if btransform then - r = r + 1 result[r] = btransform - end - - local _transform = transform - local _clippath = clippath - at["transform"] = false - -- at["clip-path"] = false - - process(res,"/*") - - at["transform"] = _transform - -- at["clip-path"] = _clippath - - if etransform then - r = r + 1 ; result[r] = etransform - end - - if eoffset then - r = r + 1 result[r] = eoffset - end - - uselevel = uselevel - 1 - else - report("use: unknown definition %a",id) - end - end - - local f_no_draw = formatters['nodraw (%s)'] - local f_do_draw = formatters['draw (%s)'] - local f_no_fill_c = formatters['nofill (%s..cycle)'] - local f_do_fill_c = formatters['fill (%s..cycle)'] - local f_eo_fill_c = formatters['eofill (%s..cycle)'] - local f_no_fill_l = formatters['nofill (%s--cycle)'] - local f_do_fill_l = formatters['fill (%s--cycle)'] - local f_eo_fill_l = formatters['eofill (%s--cycle)'] - local f_do_fill = f_do_fill_c - local f_eo_fill = f_eo_fill_c - local f_no_fill = f_no_fill_c - local s_clip_start = 'draw image (' - local f_clip_stop_c = formatters[') ; clip currentpicture to (%s..cycle) ;'] - local f_clip_stop_l = formatters[') ; clip currentpicture to (%s--cycle) ;'] - local f_clip_stop = f_clip_stop_c - local f_eoclip_stop_c = formatters[') ; eoclip currentpicture to (%s..cycle) ;'] - local f_eoclip_stop_l = formatters[') ; eoclip currentpicture to (%s--cycle) ;'] - local f_eoclip_stop = f_eoclip_stop_c - - -- could be shared and then beginobject | endobject - - local function flushobject(object,at,c,o) - local btransform, etransform = handletransform(at) - local cpath = handleclippath(at) - - if cpath then - r = r + 1 ; result[r] = s_clip_start - end - - if btransform then - r = r + 1 ; result[r] = btransform - end - - r = r + 1 ; result[r] = f_do_draw(object) - - if c then - r = r + 1 ; result[r] = c - end - - if o then - r = r + 1 ; result[r] = o - end - - if etransform then - r = r + 1 ; result[r] = etransform - end - - r = r + 1 ; result[r] = ";" - - if cpath then - local f_done = cpath.evenodd - if cpath.curve then - f_done = f_done and f_eoclip_stop_c or f_clip_stop_c - else - f_done = f_done and f_eoclip_stop_l or f_clip_stop_l - end - r = r + 1 ; result[r] = f_done(cpath[1]) - end - end - - do - - local flush - - local f_linecap = formatters["interim linecap := %s ;"] - local f_linejoin = formatters["interim linejoin := %s ;"] - local f_miterlimit = formatters["interim miterlimit := %s ;"] - - local s_begingroup = "begingroup;" - local s_endgroup = "endgroup;" - - local linecaps = { butt = "butt", square = "squared", round = "rounded" } - local linejoins = { miter = "mitered", bevel = "beveled", round = "rounded" } - - local function startlineproperties(at) - local cap = at["stroke-linecap"] - local join = at["stroke-linejoin"] - local limit = at["stroke-miterlimit"] - cap = cap and linecaps [cap] - join = join and linejoins[join] - limit = limit and asnumber_r(limit) - if cap or join or limit then - r = r + 1 ; result[r] = s_begingroup - if cap then - r = r + 1 ; result[r] = f_linecap(cap) - end - if join then - r = r + 1 ; result[r] = f_linejoin(join) - end - if limit then - r = r + 1 ; result[r] = f_miterlimit(limit) - end - return function() - at["stroke-linecap"] = false - at["stroke-linejoin"] = false - at["stroke-miterlimit"] = false - r = r + 1 ; result[r] = s_endgroup - at["stroke-linecap"] = cap - at["stroke-linejoin"] = join - at["stroke-miterlimit"] = limit - end - end - end - - -- markers are a quite rediculous thing .. let's assume simple usage for now - - function handlers.marker() - -- todo: is just a def too - end - - -- kind of local svg ... so make a generic one - -- - -- todo: combine more (offset+scale+rotation) - - local function makemarker(where,c,x1,y1,x2,y2,x3,y3,parentat) - local at = c.at - local refx = rawget(at,"refX") - local refy = rawget(at,"refY") - local width = rawget(at,"markerWidth") - local height = rawget(at,"markerHeight") - local view = rawget(at,"viewBox") - local orient = rawget(at,"orient") - -- local ratio = rawget(at,"preserveAspectRatio") - local units = asnumber(at["markerUnits"] or parentat["stroke-width"]) or 1 - - local angx = 0 - local angy = 0 - local angle = 0 - - if where == "beg" then - if orient == "auto" then -- unchecked - -- no angle - angx = abs(x2 - x3) - angy = abs(y2 - y3) - elseif orient == "auto-start-reverse" then -- checked - -- points to start - angx = -abs(x2 - x3) - angy = -abs(y2 - y3) - elseif orient then -- unchecked - angle = asnumber_r(orient) - end - elseif where == "end" then - -- funny standard .. bug turned feature? - if orient == "auto" or orient == "auto-start-reverse" then - angx = abs(x1 - x2) - angy = abs(y1 - y2) - elseif orient then -- unchecked - angle = asnumber_r(orient) - end - elseif orient then -- unchecked - angle = asnumber_r(orient) - end - -- what wins: viewbox or w/h - - refx = asnumber_x(refx) - refy = asnumber_y(refy) - - width = (width and asnumber_x(width) or 3) * units - height = (height and asnumber_y(height) or 3) * units - - local x = 0 - local y = 0 - local w = width - local h = height - - -- kind of like the main svg - - r = r + 1 ; result[r] = s_offset_start - - local wrapupviewport --- todo : better viewbox code - local xpct, ypct, rpct - if view then - x, y, w, h = handleviewbox(view) - end - - if width ~= 0 then - w = width - end - if height ~= 0 then - h = height - end - - if h then - xpct = percentage_x - ypct = percentage_y - rpct = percentage_r - percentage_x = w / 100 - percentage_y = h / 100 - percentage_r = (sqrt(w^2 + h^2) / sqrt(2)) / 100 - wrapupviewport = viewport(x,y,w,h,true,true) -- no clip - end - - -- we can combine a lot here: - - local hasref = refx ~= 0 or refy ~= 0 - local hasrot = angx ~= 0 or angy ~= 0 or angle ~= 0 - - local btransform, etransform, transform = handletransform(at) - - if btransform then - r = r + 1 ; result[r] = btransform - end - - if hasrot then - r = r + 1 ; result[r] = s_rotation_start - end - - if hasref then - r = r + 1 ; result[r] = s_offset_start - end - - local _transform = transform - at["transform"] = false - - handlers.g(c) - - at["transform"] = _transform - - if hasref then - r = r + 1 ; result[r] = f_offset_stop(-refx,refy) - end - - if hasrot then - if angle ~= 0 then - r = r + 1 ; result[r] = f_rotation_angle(angle) - else - r = r + 1 ; result[r] = f_rotation_stop(angx,angy) - end - end - - if etransform then - r = r + 1 ; result[r] = etransform - end - - if h then - percentage_x = xpct - percentage_y = ypct - percentage_r = rpct - if wrapupviewport then - wrapupviewport() - end - end - r = r + 1 ; result[r] = f_offset_stop(x2,y2) - - end - - -- do we need to metatable the attributes here? - - local function addmarkers(list,begmarker,midmarker,endmarker,at) - local n = #list - if n > 3 then - if begmarker then - local m = locate(begmarker) - if m then - makemarker("beg",m,false,false,list[1],list[2],list[3],list[4],at) - end - end - if midmarker then - local m = locate(midmarker) - if m then - for i=3,n-2,2 do - makemarker("mid",m,list[i-2],list[i-1],list[i],list[i+1],list[i+2],list[i+3],at) - end - end - end - if endmarker then - local m = locate(endmarker) - if m then - makemarker("end",m,list[n-3],list[n-2],list[n-1],list[n],false,false,at) - end - end - else - -- no line - end - end - - local function flush(shape,dofill,at,list,begmarker,midmarker,endmarker) - - local fill = dofill and (at["fill"] or "black") - local stroke = at["stroke"] or "none" - - local btransform, etransform = handletransform(at) - local cpath = handleclippath(at) - - if cpath then - r = r + 1 ; result[r] = s_clip_start - end - - local has_stroke = stroke and stroke ~= "none" - local has_fill = fill and fill ~= "none" - - local bopacity, eopacity - if has_stroke and has_fill then - bopacity, eopacity = sharedopacity(at) - end - - if bopacity then - r = r + 1 ; result[r] = bopacity - end - - if has_fill then - local color, opacity = fillproperties(fill,at,not has_stroke) - local f_xx_fill = at["fill-rule"] == "evenodd" and f_eo_fill or f_do_fill - if btransform then - r = r + 1 ; result[r] = btransform - end - r = r + 1 result[r] = f_xx_fill(shape) - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - r = r + 1 ; result[r] = etransform or ";" - end - - if has_stroke then - local wrapup = startlineproperties(at) - local pen, dashing, color, opacity = drawproperties(stroke,at,not has_fill) - if btransform then - r = r + 1 ; result[r] = btransform - end - r = r + 1 ; result[r] = f_do_draw(shape) - if pen then - r = r + 1 ; result[r] = pen - end - if dashing then - r = r + 1 ; result[r] = dashing - end - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - r = r + 1 ; result[r] = etransform or ";" - -- - if list then - addmarkers(list,begmarker,midmarker,endmarker,at) - end - -- - if wrapup then - wrapup() - end - end - - if eopacity then - r = r + 1 ; result[r] = eopacity - end - - if cpath then - r = r + 1 ; result[r] = (cpath.evenodd and f_eoclip_stop or f_clip_stop)(cpath[1]) - end - - end - - local f_rectangle = formatters['unitsquare xyscaled (%N,%N) shifted (%N,%N)'] - local f_rounded = formatters['roundedsquarexy(%N,%N,%N,%N) shifted (%N,%N)'] - local f_line = formatters['((%N,%N)--(%N,%N))'] - local f_ellipse = formatters['(fullcircle xyscaled (%N,%N) shifted (%N,%N))'] - local f_circle = formatters['(fullcircle scaled %N shifted (%N,%N))'] - - function handlers.line(c) - local at = c.at - local x1 = rawget(at,"x1") - local y1 = rawget(at,"y1") - local x2 = rawget(at,"x2") - local y2 = rawget(at,"y2") - - x1 = x1 and asnumber_vx(x1) or 0 - y1 = y1 and asnumber_vy(y1) or 0 - x2 = x2 and asnumber_vx(x2) or 0 - y2 = y2 and asnumber_vy(y2) or 0 - - flush(f_line(x1,y1,x2,y2),false,at) - end - - function handlers.rect(c) - local at = c.at - local width = rawget(at,"width") - local height = rawget(at,"height") - local x = rawget(at,"x") - local y = rawget(at,"y") - local rx = rawget(at,"rx") - local ry = rawget(at,"ry") - - width = width and asnumber_x(width) or 0 - height = height and asnumber_y(height) or 0 - x = x and asnumber_vx(x) or 0 - y = y and asnumber_vy(y) or 0 - - y = y - height - - if rx then rx = asnumber(rx) end - if ry then ry = asnumber(ry) end - - if rx or ry then - if not rx then rx = ry end - if not ry then ry = rx end - flush(f_rounded(width,height,rx,ry,x,y),true,at) - else - flush(f_rectangle(width,height,x,y),true,at) - end - end - - function handlers.ellipse(c) - local at = c.at - local cx = rawget(at,"cx") - local cy = rawget(at,"cy") - local rx = rawget(at,"rx") - local ry = rawget(at,"ry") - - cx = cx and asnumber_vx(cx) or 0 - cy = cy and asnumber_vy(cy) or 0 - rx = rx and asnumber_r (rx) or 0 - ry = ry and asnumber_r (ry) or 0 - - flush(f_ellipse(2*rx,2*ry,cx,cy),true,at) - end - - function handlers.circle(c) - local at = c.at - local cx = rawget(at,"cx") - local cy = rawget(at,"cy") - local r = rawget(at,"r") - - cx = cx and asnumber_vx(cx) or 0 - cy = cy and asnumber_vy(cy) or 0 - r = r and asnumber_r (r) or 0 - - flush(f_circle(2*r,cx,cy),true,at) - end - - local f_lineto_z = formatters['(%N,%N)'] - local f_lineto_n = formatters['--(%N,%N)'] - - local p_pair = p_optseparator * p_number_vx * p_optseparator * p_number_vy - local p_open = Cc("(") - local p_close = Carg(1) * P(true) / function(s) return s end - local p_polyline = Cs(p_open * (p_pair / f_lineto_z) * (p_pair / f_lineto_n)^0 * p_close) - local p_polypair = Ct(p_pair^0) - - local function poly(c,final) - local at = c.at - local points = rawget(at,"points") - if points then - local path = lpegmatch(p_polyline,points,1,final) - local list = nil - local begmarker = rawget(at,"marker-start") - local midmarker = rawget(at,"marker-mid") - local endmarker = rawget(at,"marker-end") - if begmarker or midmarker or endmarker then - list = lpegmatch(p_polypair,points) - end - flush(path,true,at,list,begmarker,midmarker,endmarker) - end - end - - function handlers.polyline(c) poly(c, ")") end - function handlers.polygon (c) poly(c,"--cycle)") end - - local s_image_start = "draw image (" - local s_image_stop = ") ;" - - function handlers.path(c) - local at = c.at - local d = rawget(at,"d") - if d then - local shape, l = grabpath(d) - local fill = at["fill"] or "black" - local stroke = at["stroke"] or "none" - local n = #shape - - local btransform, etransform = handletransform(at) - local cpath = handleclippath(at) - if cpath then - r = r + 1 ; result[r] = s_clip_start - end - - -- todo: image (nicer for transform too) - - if fill and fill ~= "none" then - local color, opacity = fillproperties(fill,at) - local f_xx_fill = at["fill-rule"] == "evenodd" - if shape.closed then - f_xx_fill = f_xx_fill and f_eo_fill or f_do_fill - elseif shape.curve then - f_xx_fill = f_xx_fill and f_eo_fill_c or f_do_fill_c - else - f_xx_fill = f_xx_fill and f_eo_fill_l or f_do_fill_l - end - if n == 1 then - if btransform then - r = r + 1 ; result[r] = btransform - end - r = r + 1 result[r] = f_xx_fill(shape[1]) - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - r = r + 1 ; result[r] = etransform or ";" - else - r = r + 1 ; result[r] = btransform or s_image_start - for i=1,n do - if i == n then - r = r + 1 ; result[r] = f_xx_fill(shape[i]) - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - else - r = r + 1 ; result[r] = f_no_fill(shape[i]) - end - r = r + 1 ; result[r] = ";" - end - r = r + 1 ; result[r] = etransform or s_image_stop - end - end - - if stroke and stroke ~= "none" then - local begmarker = rawget(at,"marker-start") - local midmarker = rawget(at,"marker-mid") - local endmarker = rawget(at,"marker-end") - if begmarker or midmarker or endmarker then - list = grablist(l) - end - local wrapup = startlineproperties(at) - local pen, dashing, color, opacity = drawproperties(stroke,at) - if n == 1 and not list then - if btransform then - r = r + 1 ; result[r] = btransform - end - r = r + 1 result[r] = f_do_draw(shape[1]) - if pen then - r = r + 1 ; result[r] = pen - end - if dashing then - r = r + 1 ; result[r] = dashing - end - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - r = r + 1 result[r] = etransform or ";" - else - r = r + 1 result[r] = btransform or "draw image (" - for i=1,n do - r = r + 1 result[r] = f_do_draw(shape[i]) - if pen then - r = r + 1 ; result[r] = pen - end - if dashing then - r = r + 1 ; result[r] = dashing - end - if color then - r = r + 1 ; result[r] = color - end - if opacity then - r = r + 1 ; result[r] = opacity - end - r = r + 1 ; result[r] = ";" - end - if list then - addmarkers(list,begmarker,midmarker,endmarker,at) - end - r = r + 1 ; result[r] = etransform or ") ;" - end - if wrapup then - wrapup() - end - end - - if cpath then - r = r + 1 ; result[r] = f_clip_stop(cpath[1]) - end - - end - end - - end - - -- kind of special - - do - - -- some day: - -- - -- specification = identifiers.jpg(data."string") - -- specification.data = data - -- inclusion takes from data - -- specification.data = false - - local f_image = formatters[ [[figure("%s") xysized (%N,%N) shifted (%N,%N)]] ] - - local nofimages = 0 - - function handlers.image(c) - local at = c.at - local im = rawget(at,"xlink:href") - if im then - local kind, data = match(im,"^data:image/([a-z]+);base64,(.*)$") - if kind == "png" then - -- ok - elseif kind == "jpeg" then - kind = "jpg" - else - kind = false - end - if kind and data then - local w = rawget(at,"width") - local h = rawget(at,"height") - local x = rawget(at,"x") - local y = rawget(at,"y") - w = w and asnumber_x(w) - h = h and asnumber_y(h) - x = x and asnumber_vx(x) or 0 - y = y and asnumber_vy(y) or 0 - nofimages = nofimages + 1 - local name = "temp-svg-image-" .. nofimages .. "." .. kind - local data = mime.decode("base64")(data) - io.savedata(name,data) - if not w or not h then - local info = graphics.identifiers[kind](data,"string") - if info then - -- todo: keep aspect ratio attribute - local xsize = info.xsize - local ysize = info.ysize - if not w then - if not h then - w = xsize - h = ysize - else - w = (h / ysize) * xsize - end - else - h = (w / xsize) * ysize - end - end - end - -- safeguard: - if not w then w = h or 1 end - if not h then h = w or 1 end - luatex.registertempfile(name) - -- done: - flushobject(f_image(name,w,h,x,y - h),at) - else - -- nothing done - end - end - end - - end - - -- these transform: g a text svg symbol - - do - - function handlers.a(c) - process(c,"/*") - end - - function handlers.g(c) -- much like flushobject so better split and share - local at = c.at - - local btransform, etransform, transform = handletransform(at) - local cpath, clippath = handleclippath(at) - - if cpath then - r = r + 1 ; result[r] = s_clip_start - end - - if btransform then - r= r + 1 result[r] = btransform - end - - local _transform = transform - local _clippath = clippath - at["transform"] = false - at["clip-path"] = false - - process(c,"/*") - - at["transform"] = _transform - at["clip-path"] = _clippath - - if etransform then - r = r + 1 ; result[r] = etransform - end - - if cpath then - local f_done = cpath.evenodd - if cpath.curve then - f_done = f_done and f_eoclip_stop_c or f_clip_stop_c - else - f_done = f_done and f_eoclip_stop_l or f_clip_stop_l - end - r = r + 1 ; result[r] = f_done(cpath[1]) - end - end - - -- this will never really work out - -- - -- todo: register text in lua in mapping with id, then draw mapping unless overloaded - -- using lmt_svglabel with family,style,weight,size,id passed - - -- nested tspans are messy: they can have displacements but in inkscape we also - -- see x and y (inner and outer element) - - -- The size is a bit of an issue. I assume that the specified size relates to the - -- designsize but we want to be able to use other fonts. - - do - - local f_styled = formatters["\\svgstyled{%s}{%s}{%s}{%s}"] - local f_colored = formatters["\\svgcolored{%.3N}{%.3N}{%.3N}{"] - local f_placed = formatters["\\svgplaced{%.3N}{%.3N}{}{"] - local f_poschar = formatters["\\svgposchar{%.3N}{%.3N}{%s}"] - local f_char = formatters["\\svgchar{%s}"] - - local f_scaled = formatters["\\svgscaled{%N}{%s}{%s}{%s}"] - local f_normal = formatters["\\svgnormal{%s}{%s}{%s}"] - local f_hashed = formatters["\\svghashed{%s}"] - - -- We move to the outer (x,y) and when we have an inner offset we - -- (need to) compensate for that outer offset. - - -- local f_text_scaled_svg = formatters['(svgtext("%s") scaled %N shifted (%N,%N))'] - -- local f_text_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] - -- local f_text_simple_svg = formatters['svgtext("%s")'] - - local anchors = { - ["start"] = "drt", - ["end"] = "dflt", - ["middle"] = "d", - } - - local f_text_normal_svg = formatters['(textext.%s("%s") shifted (%N,%N))'] - local f_text_simple_svg = formatters['textext.%s("%s")'] - - -- or just maptext - - local f_mapped_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] - local f_mapped_simple_svg = formatters['svgtext("%s")'] - - local cssfamily = css.family - local cssstyle = css.style - local cssweight = css.weight - local csssize = css.size - - local usedfonts = setmetatableindex(function(t,k) - local v = setmetatableindex("table") - t[k] = v - return v - end) - - local p_texescape = lpegpatterns.texescape - - -- For now as I need it for my (some 1500) test files. - - local function checkedfamily(name) - if find(name,"^.-verdana.-$") then - name = "verdana" - end - return name - end - - -- todo: only escape some chars and handle space - - local defaultsize = 10 - - local function collect(t,c,x,y,size,scale,family,tx,ty) - local at = c.at - local ax = rawget(at,"x") - local ay = rawget(at,"y") - local dx = rawget(at,"dx") - local dy = rawget(at,"dy") - local v_fill = at["fill"] - local v_family = at["font-family"] - local v_style = at["font-style"] - local v_weight = at["font-weight"] - local v_size = at["font-size"] - -- - ax = ax and asnumber_vx(ax) or x - ay = ay and asnumber_vy(ay) or y - dx = dx and asnumber_vx(dx) or 0 - dy = dy and asnumber_vy(dy) or 0 - -- - if v_family then v_family = cssfamily(v_family) end - if v_style then v_style = cssstyle (v_style) end - if v_weight then v_weight = cssweight(v_weight) end - if v_size then v_size = csssize (v_size,factors) end - -- - ax = ax - x - ay = ay - y - -- - local elayered = ax ~= 0 or ay ~= 0 or false - local eplaced = dx ~= 0 or dy ~= 0 or false - - local usedsize, usedscaled - - if elayered then - -- we're now at the outer level again so we need to scale - -- back to the outer level values - t[#t+1] = formatters["\\svgsetlayer{%0N}{%0N}{"](ax,-ay) - usedsize = v_size or defaultsize - usedscale = usedsize / defaultsize - else - -- we're nested so we can be scaled - usedsize = v_size or size - usedscale = (usedsize / defaultsize) / scale - end - -- - -- print("element ",c.tg) - -- print(" layered ",elayered) - -- print(" font size ",v_size) - -- print(" parent size ",size) - -- print(" parent scale",scale) - -- print(" used size ",usedsize) - -- print(" used scale ",usedscale) - -- - if eplaced then - t[#t+1] = f_placed(dx,dy) - end - -- - if not v_family then v_family = family end - if not v_weight then v_weight = "normal" end - if not v_style then v_style = "normal" end - -- - if v_family then - v_family = fonts.names.cleanname(v_family) - v_family = checkedfamily(v_family) - end - -- - usedfonts[v_family][v_weight][v_style] = true - -- --- if usedscale == 1 then --- t[#t+1] = f_normal( v_family,v_weight,v_style) --- else - t[#t+1] = f_scaled(usedscale,v_family,v_weight,v_style) --- end - t[#t+1] = "{" - -- - local ecolored = v_fill and v_fill ~= "" or false - if ecolored then - -- todo cmyk - local r, g, b = colorcomponents(v_fill) - if r and g and b then - t[#t+1] = f_colored(r,g,b) - else - ecolored = false - end - end - -- - local dt = c.dt - local nt = #dt - for i=1,nt do - local di = dt[i] - if type(di) == "table" then - -- can be a tspan (should we pass dx too) - collect(t,di,x,y,usedsize,usedscale,v_family) - else - if i == 1 then - di = gsub(di,"^%s+","") - end - if i == nt then - di = gsub(di,"%s+$","") - end - local chars = utfsplit(di) - if svghash then - di = f_hashed(svghash[di]) - elseif tx then - for i=1,#chars do - chars[i] = f_poschar( - (tx[i] or 0) - x, - (ty[i] or 0) - y, - utfbyte(chars[i]) - ) - end - di = "{" .. concat(chars) .. "}" - else - -- this needs to be texescaped ! and even quotes and newlines - -- or we could register it but that's a bit tricky as we nest - -- and don't know what we can expect here - -- di = lpegmatch(p_texescape,di) or di - for i=1,#chars do - chars[i] = f_char(utfbyte(chars[i])) - end - di = concat(chars) - end - t[#t+1] = di - end - end - -- - if ecolored then - t[#t+1] = "}" - end - -- - t[#t+1] = "}" - -- - if eplaced then - t[#t+1] = "}" - end - if elayered then - t[#t+1] = "}" - end - -- - return t - end - - local s_startlayer = "\\svgstartlayer " - local s_stoplayer = "\\svgstoplayer " - - function handlers.text(c) - local only = fullstrip(xmltextonly(c)) - -- if metapost.processing() then - local at = c.at - local x = rawget(at,"x") - local y = rawget(at,"y") - - local tx = asnumber_vx_t(x) - local ty = asnumber_vy_t(y) - - x = tx[1] or 0 -- catch bad x/y spec - y = ty[1] or 0 -- catch bad x/y spec - - local v_fill = at["fill"] - if not v_fill or v_fill == "none" then - v_fill = "black" - end - local color, opacity, invisible = fillproperties(v_fill,at) - local anchor = anchors[at["text-anchor"] or "start"] or "drt" - local r = metapost.remappedtext(only) - if r then - if x == 0 and y == 0 then - only = f_mapped_simple_svg(r.index) - else - only = f_mapped_normal_svg(r.index,x,y) - end - flushobject(only,at,color,opacity) - if trace_text then - report("text: %s",only) - end - elseif not invisible then -- can be an option - local scale = 1 - local textid = 0 - local result = { } - local nx = #tx - local ny = #ty - -- - result[#result+1] = s_startlayer - if nx > 1 or ny > 1 then - concat(collect(result,c,x,y,defaultsize,1,"serif",tx,ty)) - else - concat(collect(result,c,x,y,defaultsize,1,"serif")) - end - result[#result+1] = s_stoplayer - result = concat(result) - if x == 0 and y == 0 then - result = f_text_simple_svg(anchor,result) - else - result = f_text_normal_svg(anchor,result,x,y) - end - flushobject(result,at,color,opacity) - if trace_text then - report("text: %s",result) - end - elseif trace_text then - report("invisible text: %s",only) - end - -- elseif trace_text then - -- report("ignored text: %s",only) - -- end - end - - function metapost.reportsvgfonts() - for family, weights in sortedhash(usedfonts) do - for weight, styles in sortedhash(weights) do - for style in sortedhash(styles) do - report("used font: %s-%s-%s",family,weight,style) - end - end - end - end - - statistics.register("used svg fonts",function() - if next(usedfonts) then - -- also in log file - logs.startfilelogging(report,"used svg fonts") - local t = { } - for family, weights in sortedhash(usedfonts) do - for weight, styles in sortedhash(weights) do - for style in sortedhash(styles) do - report("%s-%s-%s",family,weight,style) - t[#t+1] = formatters["%s-%s-%s"](family,weight,style) - end - end - end - logs.stopfilelogging() - return concat(t," ") - end - end) - - end - - function handlers.svg(c,x,y,w,h,noclip,notransform,normalize) - local at = c.at - - local wrapupviewport - local bhacked - local ehacked - local wd = w - -- local ex, em - local xpct, ypct, rpct - - local btransform, etransform, transform = handletransform(at) - - if trace then - report("view: %s, xpct %N, ypct %N","before",percentage_x,percentage_y) - end - - local viewbox = at.viewBox - - if viewbox then - x, y, w, h = handleviewbox(viewbox) - if trace then - report("viewbox: x %N, y %N, width %N, height %N",x,y,w,h) - end - end - if not w or not h or w == 0 or h == 0 then - noclip = true - end - if h then - -- - -- em = factors["em"] - -- ex = factors["ex"] - -- factors["em"] = em - -- factors["ex"] = ex - -- - xpct = percentage_x - ypct = percentage_y - rpct = percentage_r - percentage_x = w / 100 - percentage_y = h / 100 - percentage_r = (sqrt(w^2 + h^2) / sqrt(2)) / 100 - if trace then - report("view: %s, xpct %N, ypct %N","inside",percentage_x,percentage_y) - end - wrapupviewport = viewport(x,y,w,h,noclip) - end - -- todo: combine transform and offset here - - -- some fonts need this (bad transforms + viewbox) - if v and normalize and w and wd and w ~= wd and w > 0 and wd > 0 then - bhacked = s_wrapped_start - ehacked = f_wrapped_stop(y or 0,wd/w) - end - if btransform then - r = r + 1 ; result[r] = btransform - end - if bhacked then - r = r + 1 ; result[r] = bhacked - end - local boffset, eoffset = offset(at) - if boffset then - r = r + 1 result[r] = boffset - end - - at["transform"] = false - at["viewBox"] = false - - process(c,"/*") - - at["transform"] = transform - at["viewBox"] = viewbox - - if eoffset then - r = r + 1 result[r] = eoffset - end - if ehacked then - r = r + 1 ; result[r] = ehacked - end - if etransform then - r = r + 1 ; result[r] = etransform - end - if h then - -- - -- factors["em"] = em - -- factors["ex"] = ex - -- - percentage_x = xpct - percentage_y = ypct - percentage_r = rpct - if wrapupviewport then - wrapupviewport() - end - end - if trace then - report("view: %s, xpct %N, ypct %N","after",percentage_x,percentage_y) - end - end - - end - - process = function(x,p) - for c in xmlcollected(x,p) do - local tg = c.tg - local h = handlers[c.tg] - if h then - h(c) - end - end - end - - -- For huge inefficient files there can be lots of garbage to collect so - -- maybe we should run the collector when a file is larger than say 50K. - - function metapost.svgtomp(specification,pattern,notransform,normalize) - local mps = "" - local svg = specification.data - if type(svg) == "string" then - svg = xmlconvert(svg) - end - if svg then - local c = xmlfirst(svg,pattern or "/svg") - if c then - root = svg - result = { } - r = 0 - definitions = { } - tagstyles = { } - classstyles = { } - colormap = specification.colormap - usedcolors = trace_colors and setmetatableindex("number") or false - for s in xmlcollected(c,"style") do -- can also be in a def, so let's play safe - handlestyle(c) - end - handlechains(c) - xmlinheritattributes(c) -- put this in handlechains - handlers.svg ( - c, - specification.x, - specification.y, - specification.width, - specification.height, - specification.noclip, - notransform, - normalize, - specification.remap - ) - if trace_result then - report("result graphic:\n %\n t",result) - end - if usedcolors and next(usedcolors) then - report("graphic %a uses colors: %s",specification.id or "unknown",table.sequenced(usedcolors)) - end - mps = concat(result," ") - root = false - result = false - r = false - definitions = false - tagstyles = false - classstyles = false - colormap = false - else - report("missing svg root element") - end - else - report("bad svg blob") - end - return mps - end - -end - --- These helpers might move to their own module .. some day ... also they will become --- a bit more efficient, because we now go to mp and back which is kind of redundant, --- but for now it will do. - -do - - local bpfactor = number.dimenfactors.bp - - function metapost.includesvgfile(filename,offset) -- offset in sp - if lfs.isfile(filename) then - context.startMPcode("doublefun") - context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) - context.stopMPcode() - end - end - - function metapost.includesvgbuffer(name,offset) -- offset in sp - context.startMPcode("doublefun") - context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) - context.stopMPcode() - end - - interfaces.implement { - name = "includesvgfile", - actions = metapost.includesvgfile, - arguments = { "string", "dimension" }, - } - - interfaces.implement { - name = "includesvgbuffer", - actions = metapost.includesvgbuffer, - arguments = { "string", "dimension" }, - } - - function metapost.showsvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local comment = data.comment - local offset = data.pageoffset - local index = data.index - local first = math.max(index or 1,1) - local last = math.min(index or #dd,#dd) - for i=first,last do - local d = setmetatableindex( { - data = dd[i], - comment = comment and i or false, - pageoffset = offset or nil, - }, data) - metapost.showsvgpage(d) - end - elseif data.method == "code" then - context.startMPcode(doublefun) - context(metapost.svgtomp(data)) - context.stopMPcode() - else - context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } - context(metapost.svgtomp(data)) - local comment = data.comment - if comment then - context("draw boundingbox currentpicture withcolor .6red ;") - context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) - end - context.stopMPpage() - end - end - - function metapost.typesvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local index = data.index - if index and index > 0 and index <= #dd then - data = dd[index] - else - data = nil - end - end - if type(data) == "string" and data ~= "" then - buffers.assign("svgpage",data) - context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) - end - end - - function metapost.svgtopdf(data,...) - local mps = metapost.svgtomp(data,...) - if mps then - -- todo: special instance, only basics needed - local pdf = metapost.simple("metafun",mps,true,false,"svg") - if pdf then - return pdf - else - -- message - end - else - -- message - end - end - -end - -do - - local runner = sandbox.registerrunner { - name = "otfsvg2pdf", - program = "context", - template = "--batchmode --purgeall --runs=2 %filename%", - reporter = report_svg, - } - - -- By using an independent pdf file instead of pdf streams we can use resources and still - -- cache. This is the old method updated. Maybe a future version will just do this runtime - -- but for now this is the most efficient method. - - local decompress = gzip.decompress - local compress = gzip.compress - - function metapost.svgshapestopdf(svgshapes,pdftarget,report_svg) - local texname = "temp-otf-svg-to-pdf.tex" - local pdfname = "temp-otf-svg-to-pdf.pdf" - local tucname = "temp-otf-svg-to-pdf.tuc" - local nofshapes = #svgshapes - local pdfpages = { filename = pdftarget } - local pdfpage = 0 - local t = { } - local n = 0 - -- - os.remove(texname) - os.remove(pdfname) - os.remove(tucname) - -- - if report_svg then - report_svg("processing %i svg containers",nofshapes) - statistics.starttiming(pdfpages) - end - -- - -- can be option: - -- - -- n = n + 1 ; t[n] = "\\nopdfcompression" - -- - n = n + 1 ; t[n] = "\\starttext" - n = n + 1 ; t[n] = "\\setupMPpage[alternative=offset,instance=doublefun]" - -- - for i=1,nofshapes do - local entry = svgshapes[i] - local data = entry.data - if decompress then - data = decompress(data) or data - end - local specification = { - data = xmlconvert(data), - x = 0, - y = 1000, - width = 1000, - height = 1000, - noclip = true, - } - for index=entry.first,entry.last do - if not pdfpages[index] then - pdfpage = pdfpage + 1 - pdfpages[index] = pdfpage - local pattern = "/svg[@id='glyph" .. index .. "']" - n = n + 1 ; t[n] = "\\startMPpage" - n = n + 1 ; t[n] = metapost.svgtomp(specification,pattern,true,true) or "" - n = n + 1 ; t[n] = "\\stopMPpage" - end - end - end - n = n + 1 ; t[n] = "\\stoptext" - io.savedata(texname,concat(t,"\n")) - runner { filename = texname } - os.remove(pdftarget) - file.copy(pdfname,pdftarget) - if report_svg then - statistics.stoptiming(pdfpages) - report_svg("svg conversion time %s",statistics.elapsedseconds(pdfpages)) - end - os.remove(texname) - os.remove(pdfname) - os.remove(tucname) - return pdfpages - end - - function metapost.svgshapestomp(svgshapes,report_svg) - local nofshapes = #svgshapes - local mpshapes = { } - if report_svg then - report_svg("processing %i svg containers",nofshapes) - statistics.starttiming(mpshapes) - end - for i=1,nofshapes do - local entry = svgshapes[i] - local data = entry.data - if decompress then - data = decompress(data) or data - end - local specification = { - data = xmlconvert(data), - x = 0, - y = 1000, - width = 1000, - height = 1000, - noclip = true, - } - for index=entry.first,entry.last do - if not mpshapes[index] then - local pattern = "/svg[@id='glyph" .. index .. "']" - local mpcode = metapost.svgtomp(specification,pattern,true,true) or "" - if mpcode ~= "" and compress then - mpcode = compress(mpcode) or mpcode - end - mpshapes[index] = mpcode - end - end - end - if report_svg then - statistics.stoptiming(mpshapes) - report_svg("svg conversion time %s",statistics.elapsedseconds(mpshapes)) - end - return mpshapes - end - - function metapost.svgglyphtomp(fontname,unicode) - if fontname and unicode then - local id = fonts.definers.internal { name = fontname } - if id then - local tfmdata = fonts.hashes.identifiers[id] - if tfmdata then - local properties = tfmdata.properties - local svg = properties.svg - local hash = svg and svg.hash - local timestamp = svg and svg.timestamp - if hash then - local svgfile = containers.read(fonts.handlers.otf.svgcache,hash) - local svgshapes = svgfile and svgfile.svgshapes - if svgshapes then - if type(unicode) == "string" then - unicode = utfbyte(unicode) - end - local chardata = tfmdata.characters[unicode] - local index = chardata and chardata.index - if index then - for i=1,#svgshapes do - local entry = svgshapes[i] - if index >= entry.first and index <= entry.last then - local data = entry.data - if data then - local root = xml.convert(gzip.decompress(data) or data) - return metapost.svgtomp ( - { - data = root, - x = 0, - y = 1000, - width = 1000, - height = 1000, - noclip = true, - }, - "/svg[@id='glyph" .. index .. "']", - true, - true - ) - end - end - end - end - end - end - end - end - end - end - -end diff --git a/tex/context/base/mkiv/mult-aux.mkxl b/tex/context/base/mkiv/mult-aux.mkxl deleted file mode 100644 index 97ae12be1..000000000 --- a/tex/context/base/mkiv/mult-aux.mkxl +++ /dev/null @@ -1,1177 +0,0 @@ -%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. - -%D A generalization of \MKIV-like inheritance. Just something to play with -%D (interface might change). The code here evolved in an email exchange between me -%D and Wolgang Schuster. - -\writestatus{loading}{ConTeXt Multilingual Macros / Helpers} - -\registerctxluafile{mult-aux}{} - -\unprotect - -\immutable\edef\??empty{\Uchar25} \immutable\letvalue{\Uchar25}\empty % hex 19 - -% \edef\s!parent{\Uchar29} % inlining  is ugly, a tiny bit faster, but neglectable on a run - -%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 - -%D Start of experimental code: especially tables can have many assignments and -%D although most time is spent in the typesetting anyway, we can squeeze out a -%D little bit. Of course having 500 rows of 50 columns each with some setting does -%D not happen that often. One should keep in mind that in the average document -%D having some 500 assignments is no exception but there we're talking of -%D neglectable runtime for them. Of course in the definitions below there is no real -%D gain, only in the generated \setup* commands. Another situation with many -%D assignments is \XML\ where we can pass attributes and normally don't do testing -%D 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 - -% KEEP THIS: -% -% \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,],^^^^0004} -% -% \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 -% \orelse\if]#1% -% \expandafter\gobbleoneargument -% \else -% \mult_interfaces_get_parameters_assign#1==\empty^^^^0004% -% % \expandafter\mult_interfaces_get_parameters_item % saves skipping when at end -% \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#0^^^^0004% -% {\ifx\empty#1\empty -% \expandafter\mult_interfaces_get_parameters_error -% \orelse\ifx#3\empty -% \expandafter\mult_interfaces_get_parameters_error -% \else -% \expandafter\mult_interfaces_adef % assignment def -% \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#0\csname#2#3\endcsname#0% -% {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue} -% -% \def\mult_interfaces_get_parameters_error_two#0\csname#2#3\endcsname#0% -% {\mult_interfaces_get_parameters_error_indeed{#2}{#3}} -% -% \def\mult_interfaces_get_parameters_assign#1=#2=#3#0^^^^0004% -% {\ifx\empty#1\empty -% \mult_interfaces_get_parameters_error_one -% \orelse\ifx#3\empty -% \mult_interfaces_get_parameters_error_two -% \else -% \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}% -% \fi -% \doubleexpandafter\mult_interfaces_get_parameters_item} -% -% \stopinterface -% -% \newif\ifassignment -% -% \def\mult_check_for_assignment_indeed#0=#2#0^^^^0004% -% {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi} -% -% \def\mult_check_for_assignment_indeed_begin_#0=#2#0^^^^0004% -% {\if#2^^^^0003} -% -% \def\mult_check_for_assignment#1% -% {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004} -% -% % End of experimental code. - -%D We keep the above as reference, btu from now on experiment with the following -%D implementation. In principle this one is faster, but because normally we don't -%D have that many assignments it doesn't get noticed. For instance, the \LUAMETATEX\ -%D manual does less than 6000 assignments and the payoff starts around a tenfold of -%D that. But \unknown\ it's less tracing, so that's another benefit. - -%D Watch out: we accept that a \[k=v,,k=v] will generate a case where a key can become -%D a comma and trigger a warning but we intercept that elsewhere. The alternative is -%D to skip to the comma first which takes more time. - -\let\m_mult_interfaces_namespace\empty - -\def\mult_interfaces_get_parameters#1[% - {\def\m_mult_interfaces_namespace{#1}% - \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed} - -\def\mult_interfaces_get_parameters_indeed#1]% - {\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments} - -\def\mult_interfaces_get_parameters_item#*#1,% - {\ifarguments \else - \mult_interfaces_get_parameters_item_okay#1,\ignorearguments - \expandafter\mult_interfaces_get_parameters_item - \fi} - -\def\mult_interfaces_get_parameters_item_okay#1=#2,% - {\ifarguments - % done - \or - \mult_interfaces_get_parameters_item_error - \else - \mult_interfaces_adef\m_mult_interfaces_namespace{#1}{#2}% - \fi} - -% \def\mult_interfaces_get_parameters_item_error#0#0#0#4#5% -% {\if,#5\else\mult_interfaces_get_parameters_error_indeed{#4}{#5}\fi} - -\def\mult_interfaces_get_parameters_item_error#-#-#-#1#2% - {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi} - -\startinterface english - - \def\mult_interfaces_get_parameters_item_okay#1=#2,% - {\ifarguments - % done - \or - \mult_interfaces_get_parameters_item_error - \else - \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}% - \fi} - - \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-% - {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi} - -\stopinterface - -%D Used? - -\def\mult_check_for_assignment_indeed#-=#1#-^^^^0004% - {\if#1^^^^0003\assignmentfalse\else\assignmenttrue\fi} - -\def\mult_check_for_assignment_indeed_begin_#-=#1#-^^^^0004% - {\if#1^^^^0003} - -\def\mult_check_for_assignment#1% - {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004} - -%D Beware, zero arguments is an assignment! - -\def\mult_aux_no_assignment_indeed#1=#2]{\ifcase\ifarguments\plusone\or\zerocount\else\plusone\fi} -\def\mult_aux_no_assignment#1]{\mult_aux_no_assignment_indeed#1\ignorearguments\relax} - -%D This can give wrong results when we pass e.g. \type{\c!format}, so either we need -%D to use the \type {\k!} ones, but these are not defined in the english interface -%D so from now on we assume that the low level ones are used with the symbolic names -%D and that only the high level setup commands are used with language specific -%D interfaces. - -% \startinterface english - \protected\def\mult_interfaces_let #1#2{\letcsname#1#2\endcsname} - \protected\def\mult_interfaces_lete#1#2{\letcsname#1#2\endcsname\empty} - \protected\def\mult_interfaces_def #1#2{\defcsname#1#2\endcsname} - \protected\def\mult_interfaces_edef#1#2{\edefcsname#1#2\endcsname} - \protected\def\mult_interfaces_gdef#1#2{\globaldef\csname#1#2\endcsname} - \protected\def\mult_interfaces_xdef#1#2{\globaledef\csname#1#2\endcsname} -% \stopinterface - -%D Do, we only interface the assignment definition: - -\protected\def\mult_interfaces_adef#1#2{\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} - -\startinterface english - \protected\def\mult_interfaces_adef#1#2{\defcsname#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 -% -% slower: \def#3##1{\csname\ifcsname#1#2:##1\endcsname\expandafter\csstring\lastnamedcs\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% - -%D pre-expansion can be a bit faster but handly any effect on a normal run so let's -%D go for saving some memory - -\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter} - -\protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% - {\frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% - \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - \frozen\edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ? - \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% - \frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack - \frozen\def#8##1{\begincsname#1#2:##1\endcsname}% - % TODO - \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}} - -\permanent\protected\def\installparameterhandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \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 direct#2parameter\endcsname - \expandafter\noexpand\csname letfrom#2parameter\endcsname}} % strict#2parameter is gone - -\protected\def\mult_interfaces_install_root_parameter_handler#1#2#3% - {\frozen\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root - \frozen\def#3##1{\begincsname#1:##1\endcsname}} - -\permanent\protected\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}} - -\protected\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9% - {\frozen\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? - \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - \frozen\def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}% - \frozen\def#6{#1#2:}% - \frozen\def#7##1{#1##1:}% - \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname#1#2:\s!parent\endcsname#1\fi}% - \frozen\protected\def#9##1{\edefcsname#1##1:\s!parent\endcsname{#1#2}}} - -\permanent\protected\def\installparameterhashhandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \immutable\letcsname#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}} - -%D In \MKIV\ we can probably use the english variant for all other languages too. - -% todo: inline the def/let - -% \startinterface english - \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% - {\frozen\protected\def#3##1{\defcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) - \frozen\protected\def#4##1{\edefcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) - \frozen\protected\def#5##1{\letcsname#1#2:##1\endcsname}% ##1 ##2 - \frozen\protected\def#6##1{\letcsname#1#2:##1\endcsname\empty}}% ##1 -% \stopinterface - -\permanent\protected\def\installparametersethandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \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 - -\protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4% - {\frozen\protected\def#2##1##2% style color - {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline) - \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi - \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch) - \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}% - \frozen\protected\def#3##1% style - {\edef\currentstyleparameter{#1{##1}}% this name is public - \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}% - \frozen\protected\def#4##1% color - {\edef\currentcolorparameter{#1{##1}}% this name is public - \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}} - -\permanent\protected\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\orelse\ifx#4\empty\else - \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}% - \edefcsname#1#4:\s!parent\endcsname{#2}% - \fi} - - \def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi} -\permanent\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname} -\permanent\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname} - -% we could have a \setcurrent... macro and then always make them a frozen -% but it might have a little impact on performance ... something to leave -% to when we're done with the transition (it's kind of massive) - -\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8% why is \expanded still needed in clones - {\newtoks#5% - \newtoks#6% - \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] - {\let#8#4% - % watch out: no \edef#4{##1} before the ifarguments because #1 can have macros - \ifarguments - \let#4\empty - \the#5% predefine - \let#7\empty - \letcsname#1#4:\s!chain\endcsname\empty - \edefcsname#1#4:\s!parent\endcsname{#3}% - \or - \edef#4{##1}% - \the#5% predefine - \let#7\empty - \edefcsname#1#4:\s!chain\endcsname{##1}% - \edefcsname#1#4:\s!parent\endcsname{#3}% - \or - \edef#4{##1}% - \the#5% predefine - \relax - \ifhastok={##2}% - \let#7\empty - \edefcsname#1#4:\s!chain\endcsname{##1}% - \edefcsname#1#4:\s!parent\endcsname{#3}% - \mult_interfaces_get_parameters{#1#4:}[##2]% - \else - \edef#7{##2}% - \ifempty#7% - \edefcsname#1#4:\s!chain\endcsname{##1}% - \edefcsname#1#4:\s!parent\endcsname{#3}% - \else - \mult_check_for_parent{#1}{#3}#4#7% - \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% - \edefcsname#1#4:\s!parent\endcsname{#1##2}% - \fi - \fi - \or - \edef#4{##1}% - \the#5% predefine - \edef#7{##2}% - \mult_check_for_parent{#1}{#3}#4#7% - \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% - \edefcsname#1#4:\s!parent\endcsname{#1##2}% - \mult_interfaces_get_parameters{#1#4:}[##3]% - \fi - \the#6% - \let#4#8}} - -\permanent\protected\def\installdefinehandler#1#2#3% - {\mutable\letcsname current#2\endcsname\empty - \mutable\letcsname current#2parent\endcsname\empty - \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 everypreset#2\endcsname - \expandafter\noexpand\csname everydefine#2\endcsname - \expandafter\noexpand\csname current#2parent\endcsname - \expandafter\noexpand\csname saved_defined_#2\endcsname}} - -\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% - {\newtoks#4% - \newtoks#7% - \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it - \frozen\tolerant\protected\def#2[##1]##*[##2]% maybe helper - {\let#6#3% - \ifnum\lastarguments=\plustwo - \def#8####1% we will have a simple one as well - {\edef#3{####1}% - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#4}% - \processcommalist[##1]#8% - \else - \let#3\empty - \mult_interfaces_get_parameters{#1:}[##1]% - \the#4% - \fi - \let#3#6% - \the#7}} - -\permanent\protected\def\installsetuphandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \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}} - -\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value] -\let\doingrootsetuproot \plustwo % \setuplayout [key=value] -\let\doingrootsetnamed \plusthree % \setuplayout[name] -\let\doingrootsetroot \plusfour % \setuplayout - -\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3% - {\frozen\protected\def#3{\mult_interfaces_get_parameters{#1#2:}}} - -\protected\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% - {\newtoks#5% - \newconstant#2% - \newtoks#8% - \newtoks#9% - \frozen\tolerant\protected\def#4[##1]##*[##2]% maybe helper - {\ifarguments - % \setuplayout - \let#6#3% % previous becomes current - \let#3\empty % current becomes empty - #2\doingrootsetroot - \the#5% - \the#8% switchsetups - \or - \ifhastok={##1}% - % \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 - \ifempty#3% - \let#7#6% - #2\doingrootsetuproot - \the#5% - \the#8% switchsetups - \let#3#7% - \else - #2\doingrootsetnamed - \the#5% % we can check for previous vs current - \the#8% switchsetups - \fi - \fi - \or - % \setuplayout[whatever][key=value] - \let#7#3% - \let#6#3% - \edef#3{##1}% - #2\doingrootsetupnamed - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#5% - \ifx#3#6\the#8\fi % only switchsetups if previous == current - \let#3#7% - \fi - #2\zerocount % mode is always zero at the end - \the#9}} - -\permanent\protected\def\installswitchsetuphandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \mutable\letcsname previous#2\endcsname\empty - \normalexpanded - {\mult_interfaces_install_switch_setup_handler_a - {\noexpand#1}% \??aa - \expandafter\noexpand\csname current#2\endcsname - \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 - \expandafter\noexpand\csname everysetup#2\endcsname - \expandafter\noexpand\csname previous#2\endcsname - \expandafter\noexpand\csname saved_setup_current#2\endcsname - \expandafter\noexpand\csname everyswitch#2\endcsname - \expandafter\noexpand\csname everysetup#2root\endcsname}} - -\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% - {\newtoks#4% - \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% - \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% - {\let#7#3% - \ifarguments - \let#3\empty - \the#5% - \or - \let#3\empty - \mult_interfaces_get_parameters{#1:}[##1]% - \the#4% - \or - \def#8####1% - {\edef#3{####1}% - #6% checks parent and sets if needed - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#4}% - \processcommalist[##1]#8% - \or - \def#8####1% - {\edef#3{####1}% - \defcsname#1#3:\s!parent\endcsname{#1##2}% - \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent - \the#4}% - \processcommalist[##1]#8% - \fi - \let#3#7}} - -\permanent\protected\def\installautosetuphandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \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}} - -\permanent\protected\def\installbasicparameterhandler#1#2% - {\installparameterhandler {#1}{#2}% - \installparameterhashhandler{#1}{#2}% - \installparametersethandler {#1}{#2}% - \installrootparameterhandler{#1}{#2}} - -\permanent\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self) - {\installbasicparameterhandler{#1}{#2}% - \installautosetuphandler {#1}{#2}} - -\permanent\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self) - {\installbasicparameterhandler{#1}{#2}% - \installautosetuphandler {#1}{#2}% - \installstyleandcolorhandler {#1}{#2}} - -\permanent\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) - {\installbasicparameterhandler{#1}{#2}% - \installdefinehandler {#1}{#2}{#3}% - \installsetuphandler {#1}{#2}% - \installstyleandcolorhandler {#1}{#2}} - -\permanent\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self) - {\installbasicparameterhandler{#1}{#2}% - \installdefinehandler {#1}{#2}{#3}% - \installswitchsetuphandler {#1}{#2}% - \installstyleandcolorhandler {#1}{#2}} - -\permanent\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups - {\installbasicparameterhandler{#1}{#2}% - \installdefinehandler {#1}{#2}{#3}% - \installautosetuphandler {#1}{#2}% - \installstyleandcolorhandler {#1}{#2}} - -\permanent\protected\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 the -%D speed||critical ones. Therefore there is no reason to stick to \type {\@@xxkey} -%D for the sake of performance. For this reason we also provide a direct variant. -%D This permits a more consistent treatment of namespaces. A \type -%D {\whateverparameter} call is three times slower and a \type -%D {\directwhateverparameter} call two times but for some 100K expansions we only -%D loose some .1 second which is neglectable given the small amount of expansions in -%D real runs. - -%D We don't need colons for such simple cases. - -\protected\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5% - {\frozen\def#3##1{\begincsname#1##1\endcsname}% - \frozen\def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% - \frozen\def#5##1{\begincsname#1##1\endcsname}} - -\permanent\protected\def\installdirectparameterhandler#1#2% - {\mutable\letcsname current#2\endcsname\empty - \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}} - -\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4% - {\newtoks#4% - \frozen\protected\def#2[##1]{\ifarguments\or\mult_interfaces_get_parameters#1[##1]\fi\the#4}% - \frozen\def#3{\mult_interfaces_get_parameters#1}} - -\permanent\protected\def\installdirectsetuphandler#1#2% - {\normalexpanded - {\mult_interfaces_install_direct_setup_handler - {\noexpand#1}% \??aa - \expandafter\noexpand\csname setup#2\endcsname - \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency) - \expandafter\noexpand\csname everysetup#2\endcsname}} - -% \startinterface english - \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% - {\frozen\protected\def#2##1{\defcsname#1##1\endcsname}% - \frozen\protected\def#3##1{\edefcsname#1##1\endcsname}% - \frozen\protected\def#4##1{\letcsname#1##1\endcsname}% - \frozen\protected\def#5##1{\letcsname#1##1\endcsname\empty}}% -% \stopinterface - -\permanent\protected\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}} - -\aliased\let\installdirectstyleandcolorhandler\installstyleandcolorhandler - -\permanent\protected\def\installdirectcommandhandler#1#2% - {\installdirectparameterhandler {#1}{#2}% - \installdirectsetuphandler {#1}{#2}% - \installdirectparametersethandler {#1}{#2}% - \installdirectstyleandcolorhandler{#1}{#2}} - -\permanent\protected\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 - -\permanent\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} - {\immutable\edefcsname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} - -\permanent\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance} - {\edefcsname#1#2:\s!parent\endcsname{#3#4}} - -%D Here is another experiment: - -\protected\def\mult_interfaces_install_action_handler#1#2#3% - {\frozen\tolerant\protected\defcsname#1\endcsname[##1]##*[##2]% - {\begingroup - \ifarguments - \let#2\empty - \or - %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004% - % \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments - % \edef#2{##1}% - % \else - % \let#2\empty - % #3[##1]% - % \fi - \ifhastok={##1}% - \let#2\empty - #3[##1]% - \else - \edef#2{##1}% - \fi - \or - \edef#2{##1}% - #3[##2]% - \fi - \directsetup{handler:action:#1}% - \endgroup}} - -\permanent\protected\def\installactionhandler#1% - {\mutable\letcsname current#1\endcsname\empty - \normalexpanded - {\mult_interfaces_install_action_handler - {#1}% - \expandafter\noexpand\csname current#1\endcsname - \expandafter\noexpand\csname setupcurrent#1\endcsname}} - -% First we had, in tune with the regular system variables: -% -% \starttyping -% \protected\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>} - -\permanent\protected\def\installnamespace#1% for modules and users - {\ifcsname ????#1\endcsname - \writestatus\m!system{duplicate user namespace '#1'}\wait - \else - \global\advance\c_mult_interfaces_n_of_namespaces\plusone - \immutable\edefcsname ????#1\endcsname{\v_interfaces_prefix_template}% - \fi} - -\permanent\protected\def\installcorenamespace#1% - {\ifcsname ??#1\endcsname - \writestatus\m!system{duplicate core namespace '#1'}\wait - \else - \global\advance\c_mult_interfaces_n_of_namespaces\plusone - \immutable\edefcsname ??#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} - -% 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 - -\permanent \def\dummyparameter #1{\begincsname\??dummy#1\endcsname} -\permanent \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname} -\permanent\protected\def\setdummyparameter #1{\defcsname\??dummy#1\endcsname} -\permanent\protected\def\setexpandeddummyparameter#1{\edefcsname\??dummy#1\endcsname} -\permanent\protected\def\letdummyparameter #1{\letcsname\??dummy#1\endcsname} - -\edef\mult_interfaces_dummy{\??dummy} % nor immutable - -\permanent\protected\def\getdummyparameters[#1% - {\if\noexpand#1]% - \expandafter\gobbleoneargument - \else - \let\m_mult_interfaces_namespace\mult_interfaces_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: - -\permanent\tolerant\protected\def\definenamespace[#1]#*[#2]% namespace settings - {\clf_definenamespace{#1}{#2}} - -\permanent\protected\def\listnamespaces - {\clf_listnamespaces} - -%D Helper: -%D -%D \starttyping -%D \showparentchain{@@am}{left} -%D \stoptyping - -\permanent\protected\def\showparentchain#1#2% - {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}} - -\def\mult_interfaces_show_parent_chain#1% - {#1 => % - \ifcsname#1:\s!parent\endcsname - \expandafter\mult_interfaces_show_parent_chain\lastnamedcs - \fi} - -%D Another helper (needs to be applied): - -\permanent\protected\def\doifelsecommandhandler#1#2% namespace name - {\ifcsname#1#2:\s!parent\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifcommandhandlerelse\doifelsecommandhandler - -\permanent\protected\def\doifcommandhandler#1#2% namespace name - {\ifcsname#1#2:\s!parent\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotcommandhandler#1#2% namespace name - {\ifcsname#1#2:\s!parent\endcsname - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -% another set of (fast) helpers (grep for usage): - -\permanent\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy - {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3} - -\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy - {#1\endcsname#1\else#2\fi\endcsname} - -\permanent\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy - {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} - -\permanent\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname - {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}} - -\def\syst_helpers_expand_checked_value#1#2% - {#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 - -\let\c_mult_set\relax - -\protected\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7% - {\newcount#3% - \let#6\empty - \protected\def#2% - {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname - \ifx\c_mult_set\relax - \expandafter\newtoks\c_mult_set - \letcsname#1_t_#6\endcsname\c_mult_set - \fi} - \frozen\protected\def#4##1% - {\pushmacro#6% - \advance#3\plusone - \edef#6{##1}% - \unprotect}% - \frozen\protected\def#5% - {\protect - \advance#3\minusone - \popmacro#6}% - \frozen\protected\def#7##1% - {\edef#6{##1}% - #2% - \the\c_mult_set\relax}} - -\permanent\protected\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}} - -\protected\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc - {\let#5#2% - \frozen\protected\def#2% - {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}% - \tolerant\protected\def#6[##1]##*[##2]% - {\ifarguments\or - #3\toksapp\c_mult_set{#7[##1]}% - \or - #3\toksapp\c_mult_set{#8[##1][##2]}% - \fi}} - -\permanent\protected\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 setup#4_\s!single\endcsname - \expandafter\noexpand\csname setup#4_\s!double\endcsname}} - -%D Another experiment: - -\protected\def\mult_interfaces_install_parent_injector#1#2#3#4% - {\frozen\protected\def#4##1% - {\ifempty#3% - \defcsname#1#2:\s!parent\endcsname{#1##1}% - \fi}} - -\permanent\protected\def\installparentinjector#1#2% - {\normalexpanded{\mult_interfaces_install_parent_injector - {\noexpand#1}% - \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname current#2parent\endcsname - \expandafter\noexpand\csname inject#2parent\endcsname}} - -% The \LUA\ based variant is twice as fast as the above but as said, we don't use -% this one that often. It's more about less tracing than speed here. - -\permanent\protected\def\installmacrostack#1% - {\ifdefined#1\else\mutable\let#1\empty\fi - \global\protected\defcsname push_macro_\csstring#1\endcsname{\localpushmacro#1}% - \global\protected\defcsname pop_macro_\csstring#1\endcsname{\localpopmacro #1}} - -\permanent\protected\def\installglobalmacrostack#1% - {\ifdefined#1\else\mutable\glet#1\empty\fi - \global\protected\defcsname push_macro_\csstring#1\endcsname{\globalpushmacro#1}% - \global\protected\defcsname pop_macro_\csstring#1\endcsname{\globalpopmacro #1}} - -% \showmacrostack can be used to see if there are different entries - -% \unprotect -% -% \installcorenamespace {test} \installcommandhandler \??test {test} \??test -% \protected\def\TestMeA[#1]% -% {\edef\currenttest{#1} -% \edef\p_before{\testparameter\c!before}% -% \ifx\p_before\empty \relax \else \relax \fi} -% \protected\def\TestMeB[#1]% -% {\edef\currenttest{#1} -% \doifelsenothing{\testparameter\c!before}\relax\relax} -% \protected\def\TestMeC[#1]% -% {\edef\currenttest{#1} -% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi} -% \protected\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] -% \testfeatureonce{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502 -% \testfeatureonce{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530 -% \testfeatureonce{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487 -% \testfeatureonce{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493 -% \stoptext - -% There is no real demand for this ... even if this is two to three times as fast we -% only gain a few milliseconds: -% -% \starttyping -% \protected\def\foo#1{[foo:#1]} -% -% \installcommalistprocessor {foo} \foo -% \installcommalistprocessorcommand \processfoolist \foo -% -% \infofont -% -% \commalistprocessor{foo}[a,b,c,{x,y,z},d]\par -% \processfoolist[a, b, c, {x,y,z}, d]\par -% \processcommalist[{x,y,z}]\foo\blank -% -% \commalistprocessor{foo}[{x,y,z},a]\par -% \commalistprocessor{foo}[{x,y,z}]\par -% \processfoolist[{x,y,z},a]\par -% \processfoolist[{x,y,z}]\par -% \processcommalist[{x,y,z}]\foo\blank -% -% \protected\def\foo#1{} -% -% \testfeatureonce{400000}{\processfoolist [fixed,middle,bar]} \elapsedtime\quad -%%\testfeatureonce{400000}{\commalistprocessor{foo}[fixed,middle,bar]} \elapsedtime\quad -% \testfeatureonce{400000}{\processcommalist [fixed,middle,bar]\foo} \elapsedtime\quad -% \stoptyping -% -% For instance the luatex manual only has some 3000 calls. But I keep this around as one -% never knows when we might need it. - -\installcorenamespace{commalistprocessor} -\installcorenamespace{commalistprocessorwrap} -\installcorenamespace{commalistprocessorfirst} -\installcorenamespace{commalistprocessornext} -\installcorenamespace{commalistprocessoraction} - -\permanent\protected\def\installcommalistprocessor#1#2% 5 macro names overhead - {\protected\edefcsname\??commalistprocessor#1\endcsname[% - {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {} - \protected\edefcsname\??commalistprocessorwrap#1\endcsname##1]% - {\csname\??commalistprocessorfirst#1\endcsname##1,]} - \protected\edefcsname\??commalistprocessorfirst#1\endcsname\relax - {\csname\??commalistprocessornext#1\endcsname}% - \protected\edefcsname\??commalistprocessornext#1\endcsname - {\noexpand\futureexpandis]% - \noexpand\gobbleoneargument - \csname\??commalistprocessoraction#1\endcsname} - \protected\edefcsname\??commalistprocessoraction#1\endcsname##1,% - {\noexpand#2{##1}% - \csname\??commalistprocessornext#1\endcsname}} - -\permanent\protected\def\installcommalistprocessorcommand#1#2% \processor \action - {\edef\p_name{\csstring#2}% - \installcommalistprocessor\p_name{#2}% - \expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname} - -\permanent\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname} - -\protect \endinput diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index 6d6813fde..661a444de 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -5996,7 +5996,7 @@ return { ["pe"]="شروع‌پوشش", ["ro"]="startoverlay", }, - ["startoverzicht"]={ + ["startoverview"]={ ["cs"]="startprehled", ["de"]="startueberblick", ["en"]="startoverview", @@ -6410,7 +6410,7 @@ return { ["pe"]="پایان‌پوشش", ["ro"]="stopoverlay", }, - ["stopoverzicht"]={ + ["stopoverview"]={ ["cs"]="stopprehled", ["de"]="stopueberblick", ["en"]="stopoverview", @@ -8354,6 +8354,10 @@ return { ["pe"]="فرمان‌متن‌عمیق", ["ro"]="deeptextcommand", }, + ["define"]={ + ["en"]="define", + ["nl"]="definieer", + }, ["default"]={ ["cs"]="implicitni", ["de"]="default", diff --git a/tex/context/base/mkiv/mult-def.mkxl b/tex/context/base/mkiv/mult-def.mkxl deleted file mode 100644 index 13e22dade..000000000 --- a/tex/context/base/mkiv/mult-def.mkxl +++ /dev/null @@ -1,32 +0,0 @@ -%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} - -\immutable\setvalue{\??multilingual czech}{cs} -\immutable\setvalue{\??multilingual german}{de} -\immutable\setvalue{\??multilingual english}{en} -\immutable\setvalue{\??multilingual french}{fr} -\immutable\setvalue{\??multilingual italian}{it} -\immutable\setvalue{\??multilingual dutch}{nl} -\immutable\setvalue{\??multilingual persian}{pe} -\immutable\setvalue{\??multilingual romanian}{ro} - -\permanent\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\lastnamedcs\else en\fi} -\permanent\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\lastnamedcs\else en\fi} - -\clf_setuserinterface{\userinterfacetag}{\userresponsestag} - -\protect \endinput diff --git a/tex/context/base/mkiv/mult-dim.mklx b/tex/context/base/mkiv/mult-dim.mklx deleted file mode 100644 index 0526b3775..000000000 --- a/tex/context/base/mkiv/mult-dim.mklx +++ /dev/null @@ -1,156 +0,0 @@ -%D \module -%D [ file=core-gen, -%D version=1995.10.10, -%D title=\CONTEXT\ Core Macros, -%D subtitle=General, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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 dimension setters. -%D -%D \starttyping -%D \assigndimension -%D {|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} - -\immutable\setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint} -\immutable\setvalue{\??dimensionnormal \empty }#value#dimension#small#medium#big{#dimension\zeropoint} -\immutable\setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax} -\immutable\setvalue{\??dimensionnormal \v!medium}#value#dimension#small#medium#big{#dimension=#medium\relax} -\immutable\setvalue{\??dimensionnormal \v!big }#value#dimension#small#medium#big{#dimension=#big\relax} -\immutable\setvalue{\??dimensionnormal-\v!small }#value#dimension#small#medium#big{#dimension=-#small\relax} -\immutable\setvalue{\??dimensionnormal-\v!medium}#value#dimension#small#medium#big{#dimension=-#medium\relax} -\immutable\setvalue{\??dimensionnormal-\v!big }#value#dimension#small#medium#big{#dimension=-#big\relax} -\immutable\letvalue{\??dimensionnormal\s!unknown}\assign_dimension_direct - -\permanent\protected\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 {|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}} - -\immutable\setvalue{\??dimensionalfa\v!none }#value#macro#small#medium#big{\let #macro\!!zerocount} -\immutable\setvalue{\??dimensionalfa\v!small }#value#macro#small#medium#big{\edef#macro{#small}} -\immutable\setvalue{\??dimensionalfa\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}} -\immutable\setvalue{\??dimensionalfa\v!big }#value#macro#small#medium#big{\edef#macro{#big}} -\immutable\letvalue{\??dimensionalfa\s!unknown}\assign_alpha_dimension_direct - -\permanent\protected\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 {|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}} - -\immutable\setvalue{\??dimensionvalue\v!small }#value#macro#small#medium#big{\edef#macro{#small}} -\immutable\setvalue{\??dimensionvalue\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}} -\immutable\setvalue{\??dimensionvalue\v!big }#value#macro#small#medium#big{\edef#macro{#big}} -\immutable\letvalue{\??dimensionvalue\s!unknown}\assign_value_direct - -\permanent\protected\def\assignvalue#value% - {\ifcsname\??dimensionvalue#value\endcsname - \expandafter\lastnamedcs - \else - \expandafter\assign_value_direct - \fi{#value}} - -%D \macros -%D {assignwidth} -%D -%D This one is used a few times. -%D -%D \starttyping -%D \assignwidth -%D {|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 ... - -\immutable\setvalue{\??dimensionwidth }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width - \setbox\b_assign_width\emptybox} -\immutable\setvalue{\??dimensionwidth\v!fit }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width - \setbox\b_assign_width\emptybox} -\immutable\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} -\immutable\setvalue{\??dimensionwidth\v!line }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width - \setbox\b_assign_width\emptybox} -\immutable\letvalue{\??dimensionwidth\s!unknown}\assign_width_direct - -\permanent\protected\def\assignwidth#value% - {\ifcsname\??dimensionwidth#value\endcsname - \expandafter\lastnamedcs - \else - \expandafter\assign_width_direct - \fi{#value}} - -\protect \endinput diff --git a/tex/context/base/mkiv/mult-ini.mkxl b/tex/context/base/mkiv/mult-ini.mkxl deleted file mode 100644 index 709e7142f..000000000 --- a/tex/context/base/mkiv/mult-ini.mkxl +++ /dev/null @@ -1,805 +0,0 @@ -%D \module -%D [ file=mult-ini, -%D version=2008.10.22, % 1996.06.01, -%D title=\CONTEXT\ Multilingual Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This module is a stripped down version of \type {mult-ini.tex}, which we keep -%D around as \type {mult-kep.tex} for sentimental reasons. There you will find some -%D more historic information. - -\writestatus{loading}{ConTeXt Multilingual Macros / Initialization} - -\unprotect - -\registerctxluafile{mult-ini}{} -\registerctxluafile{mult-fmt}{initexonly} - -%D \macros -%D [constanten,variabelen,commands] -%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!} -%D -%D In the system modules we introduced some prefixed constants, variables (both -%D macros) and registers. Apart from a tremendous saving in terms of memory and a -%D gain in speed we use from now on prefixes when possible for just another reason: -%D consistency and multi||linguality. Systematically using prefixed macros enables -%D us to implement a multi||lingual user interface. Redefining these next set of -%D prefixes therefore can have desastrous results. -%D -%D \startlinecorrection -%D \starttable[|c|c|c|] -%D \HL -%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR -%D \HL -%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR -%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\FR -%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR -%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR -%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR -%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR -%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR -%D \HL -%D \stoptable -%D \stoplinecorrection -%D -%D In the single||lingual version we used \type {!}, \type {!!}, \type {!!!} and -%D \type {!!!!}. In the meantime some of these are obsolete (we had some 12 -%D originally). - -\immutable\def\c!prefix!{c!} -\immutable\def\k!prefix!{k!} -\immutable\def\e!prefix!{e!} -\immutable\def\f!prefix!{f!} % for the moment we keep this one -\immutable\def\m!prefix!{m!} -\immutable\def\s!prefix!{s!} -\immutable\def\v!prefix!{v!} -\immutable\def\t!prefix!{t!} - -%D \macros -%D [constants,variables,commands] -%D {@@,??} -%D -%D Variables generated by the system can be recognized on their prefix \type {@@}. -%D They are composed of a command (class) specific tag, which can be recognized on -%D \type {??}, and a system constant, which has the prefix \type {c!}. We'll se some -%D more of this. - -\immutable\def\??prefix {??} -\immutable\def\@@prefix {@@} - -%D Just to be complete we repeat some of the already defined system constants here. -%D Maybe their prefix \type {\s!} now falls into place. - -\def\s!next {next} \def\s!default {default} -\def\s!dummy {dummy} \def\s!unknown {unknown} - -\def\s!do {do} \def\s!dodo {dodo} - -\def\s!complex {complex} \def\s!start {start} -\def\s!simple {simple} \def\s!stop {stop} - -\def\s!true {true} -\def\s!false {false} - -%D The word \type {height} takes 6~token memory cells. The control sequence \type -%D {\height} on the other hand uses only one. Knowing this, we can improve the -%D performance of \TEX, both is terms of speed and memory usage, by using control -%D sequences instead of the words written in full. -%D -%D Where in the \ASCII\ file the second lines takes nine extra characters, \TEX\ -%D saves us 13~tokens. -%D -%D \starttyping -%D \hrule width 10pt height 2pt depth 1pt -%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt -%D \stoptyping -%D -%D One condition is that we have defined \type {\s!height}, \type {\s!width} and -%D \type {\s!depth} as respectively \type {height}, \type {width} and \type {depth}. -%D Using this scheme therefore only makes sense when a token sequence is used more -%D than once. Savings like this should of course be implemented in english, just -%D because \TEX\ is english. - -\def\s!width {width} -\def\s!height {height} -\def\s!depth {depth} -\def\s!spread {spread} -\def\s!plus {plus} -\def\s!minus {minus} -\def\s!to {to} - -\def\s!fil {fil} -\def\s!fill {fill} -\def\s!filll {filll} - -\def\s!attr {attr} -\def\s!axis {axis} -\def\s!both {both} -\def\s!bottom {bottom} -\def\s!left {left} -\def\s!options {options} -\def\s!orientation{orientation} -\def\s!reverse {reverse} -\def\s!right {right} -\def\s!top {top} -\def\s!xmove {xmove} -\def\s!xoffset {xoffset} -\def\s!ymove {ymove} -\def\s!yoffset {yoffset} - -%D \macros - -%D {defineinterfaceconstant, -%D defineinterfacevariable, -%D defineinterfaceelement, -%D definesystemvariable, -%D definesystemconstant, -%D definemessageconstant, -%D definefileconstant} -%D -%D The first part of this module is dedicated to dealing with multi||lingual -%D constants and variables. When \CONTEXT\ grew bigger and bigger in terms of bytes -%D and used string space, we switched to predefined constants. At the cost of more -%D hash table entries, the macros not only becase more compact, they became much -%D faster too. Maybe an even bigger advantage was that mispelling could no longer -%D lead to problems. Even a multi||lingual interface became possible. -%D -%D Constants |<|we'll introduce the concept of variables later on|>| are preceded by -%D a type specific prefix, followed by a \type {!}. To force consistency, we provide -%D a few commands for defining such constants. -%D -%D \starttyping -%D \defineinterfaceconstant {name} {meaning} -%D \defineinterfacevariable {name} {meaning} -%D \defineinterfaceelement {name} {meaning} -%D \stoptyping -%D -%D Which is the same as: -%D -%D \starttyping -%D \def\c!name{meaning} -%D \def\v!name{meaning} -%D \def\e!name{meaning} -%D \stoptyping - -%permanent\protected\def\defineinterfaceconstant#1#2{\immutable\defcsname\c!prefix!#1\endcsname{#2}} -\permanent\protected\def\defineinterfacevariable#1#2{\immutable\defcsname\v!prefix!#1\endcsname{#2}} -\permanent\protected\def\defineinterfaceelement #1#2{\immutable\defcsname\e!prefix!#1\endcsname{#2}} - -%D Next come some interface independant constants: -%D -%D \starttyping -%D \definefileconstant {name} {meaning} -%D \stoptyping - -\permanent\protected\def\definefileconstant#1#2{\immutable\defcsname\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 - -\permanent\protected\def\definesystemconstant #1{\immutable\defcsname\s!prefix!#1\endcsname{#1}} -\permanent\protected\def\definemessageconstant#1{\immutable\defcsname\m!prefix!#1\endcsname{#1}} - -%D For now here: - -\permanent\protected\def\definetagconstant #1{\immutable\defcsname\t!prefix!#1\endcsname{#1}} -\permanent\protected\def\aliastagconstant #1#2{\aliased \letcsname\t!prefix!#1\expandafter\endcsname\csname\t!prefix!#2\endcsname} - -%D In a parameter driven system, some parameters are shared by more system -%D components. In \CONTEXT\ we can distinguish parameters by a unique prefix. Such a -%D prefix is defined with: -%D -%D \starttyping -%D \definesystemvariable {name} -%D \stoptyping - -\permanent\protected\def\definesystemvariable#1{\immutable\edefcsname\??prefix#1\endcsname{\@@prefix#1}} - -\definesystemvariable{ms} - -%D \macros -%D {selectinterface, -%D defaultinterface, currentinterface, currentresponses} -%D -%D With \type {\selectinterface} we specify the language we are going to use. The -%D system asks for the language wanted, and defaults to \type {\currentinterface} -%D when we just give \type {enter}. By default the message system uses the current -%D interface language, but \type {\currentresponses} can specify another language -%D too. -%D -%D Because we want to generate formats directly too, we do not ask for interface -%D specifications when these are already defined (like in cont-nl.tex and alike). - -\ifdefined\defaultinterface - - \permanent\protected\def\selectinterface - {\writestatus{interface}{defining \currentinterface\space interface}% - %writeline - \writestatus{interface}{using \currentresponses\space messages}% - %\writeline - \enforced\permanent\let\selectinterface\relax} - -\else - - \def\defaultinterface{english} - - \permanent\overloaded\protected\def\selectinterface - {\enforced\permanent\protected\def\selectinterface##1##2% - {\bgroup - \endlinechar\minusone - \global\read16 to ##1 - \egroup - \doifnothing\currentinterface{\let##1=##2}% - \doifundefined{\s!prefix!##1}{\let##1=##2}}% - \selectinterface\currentinterface\defaultinterface - \writestatus{interface}{defining \currentinterface\space interface}% - %\writeline - \selectinterface\currentresponses\currentinterface - \writestatus{interface}{using \currentresponses\space messages}% - %\writeline - \enforced\permanent\let\selectinterface\relax} - -\fi - -\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi -\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi - -%D \macros -%D {startinterface} -%D -%D Sometimes we want to define things only for specific interface languages. This -%D can be done by means of the selector: -%D -%D \starttyping -%D \startinterface language -%D -%D language specific definitions & commands -%D -%D \stopinterface -%D \stoptyping - -\permanent\protected\def\startinterface #1 - {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}} - -\aliased\let\stopinterface\relax - -%D \macros -%D {startmessages, -%D getmessage, -%D showmessage, -%D makemessage} -%D -%D A package as large as \CONTEXT\ can hardly function without a decent message -%D mechanism. Due to its multi||lingual interface, the message subsystem has to be -%D multi||lingual too. A major drawback of this feature is that we have to code -%D messages. As a result, the source becomes less self documented. On the other -%D hand, consistency will improve. -%D -%D Because the overhead in terms of entries in the (already exhausted) hash table -%D has to be minimal, messages are packed in libraries. We can extract a message -%D from such a library in three ways: -%D -%D \starttyping -%D \getmessage {library} {tag} -%D \showmessage {library} {tag} {data} -%D \makemessage {library} {tag} {data} -%D \stoptyping -%D -%D The first command gets the message \type {tag} from the \type {library} -%D specified. The other commands take an extra argument: a list of items to be -%D inserted in the message text. While \type {\showmessage} shows the message at the -%D terminal, the other commands generate the message as text. Before we explain the -%D \type {data} argument, we give an example of a library. -%D -%D \starttyping -%D \startmessages english library: alfa -%D title: something -%D 1: first message -%D 2: second (--) message -- -%D \stopmessages -%D \stoptyping -%D -%D The first message is a simple one and can be shown with: -%D -%D \starttyping -%D \showmessage {alfa} {1} {} -%D \stoptyping -%D -%D The second message on the other hand needs some extra data: -%D -%D \starttyping -%D \showmessage {alfa} {2} {and last,to you} -%D \stoptyping -%D -%D This message is shown as: -%D -%D \starttyping -%D something : second (and last) message to you -%D \stoptyping -%D -%D As we can see, the title entry is shown with the message. The data fields are -%D comma separated and are specified in the message text by \type {--}. -%D -%D It is not required to define all messages in a library at once. We can add -%D messages to a library in the following way: -%D -%D \starttyping -%D \startmessages english library: alfa -%D 10: tenth message -%D \stopmessages -%D \stoptyping -%D -%D Because such definitions can take place in different modules, the system gives a -%D warning when a tag occurs more than once. The first occurrence takes preference -%D over later ones, so we had better use a save offset, as shown in the example. As -%D we can see, the title field is specified only the first time! -%D -%D Because we want to check for duplicate tags, the macros are a bit more -%D complicated than neccessary. The \NEWLINE\ token is used as message separator. -%D -%D For internal purposes one can use \type {\setmessagetext}, which puts the message -%D text asked for in \type {\currentmessagetext}. -%D -%D These will become obsolete: - -\permanent\protected\def\startmessages #1 library: #2 % - {\begingroup - \ifcsname\m!prefix!#2\endcsname\else\immutable\setgvalue{\m!prefix!#2}{#2}\fi - \catcode\endoflineasciicode\othercatcode - \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} - -\def\mult_messages_start_yes#1#2\stopmessages - {\clf_setinterfacemessages{#1}{#2}% - \endgroup} - -\def\mult_messages_start_nop#1#2\stopmessages - {\endgroup} - -\let\stopmessages\relax - -\permanent\protected\def\setinterfacemessage#1#2#3% - {\ifcsname\m!prefix!#1\endcsname\else\immutable\setgvalue{\m!prefix!#1}{#1}\fi - \clf_setinterfacemessage{#1}{#2}{#3}} - -\pushoverloadmode - -\permanent\protected\def\setmessagetext #1#2{\relax\edef\currentmessagetext{\clf_getmessage{#1}{#2}}} -\permanent\protected\def\getmessage #1#2{\relax\clf_getmessage{#1}{#2}} -\permanent\protected\def\doifelsemessage #1#2{\relax\clf_doifelsemessage{#1}{#2}} -\permanent\protected\def\showmessage #1#2#3{\relax\clf_showmessage{#1}{#2}{#3}} -\permanent\protected\def\writestatus #1#2{\relax\clf_writestatus{#1}{#2}} -\permanent\protected\def\message {\relax\clf_message} - -\popoverloadmode - -\aliased\let\doifmessageelse\doifelsemessage - -\permanent\protected\def\inlinemessage #1{\dontleavehmode{\tttf#1}} -\permanent\protected\def\displaymessage#1{\blank\inlinemessage{#1}\blank} - -\permanent\let\getsetupstring\clf_getsetupstring -\permanent\let\rawsetupstring\clf_rawsetupstring - -%D For old times sake: - -\let\showwarning\showmessage - -%D \macros -%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue -%D -%D We already defined these auxiliary macros in the system modules. Starting with -%D this module however, we have to take multi||linguality a bit more serious. -%D -%D In due time, when we exclusively use the parameter handler code, we can drop the -%D backmapping (\type{\c!k...}) and make \type {\c!c...} similar to \type {\v!...}. -%D In that case we can simply the following setters. - -\pushoverloadmode - -\permanent\protected\def\doletvalue #1#2{\letcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -\permanent\protected\def\dosetvalue #1#2{\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -\permanent\protected\def\dosetevalue #1#2{\edefcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -\permanent\protected\def\dosetgvalue #1#2{\global\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -\permanent\protected\def\dosetxvalue #1#2{\global\edefcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -\permanent\protected\def\doresetvalue #1#2{\letcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} -\permanent\protected\def\doignorevalue#1#2#3{\letcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} - -\permanent\protected\def\docopyvalue#1#2#3% - {\ifcsname\k!prefix!#3\endcsname - \defcsname#1\csname\k!prefix!#3\endcsname\expandafter\endcsname\expandafter - {\csname#2\csname\k!prefix!#3\endcsname\endcsname}% - \else - \defcsname#1#3\expandafter\endcsname\expandafter - {\csname#2#3\endcsname}% - \fi} - -\startinterface english - - \permanent\protected\def\doletvalue #1#2{\letcsname#1#2\endcsname} - \permanent\protected\def\dosetvalue #1#2{\defcsname#1#2\endcsname} - \permanent\protected\def\dosetevalue #1#2{\edefcsname#1#2\endcsname} - \permanent\protected\def\dosetgvalue #1#2{\global\defcsname#1#2\endcsname} - \permanent\protected\def\dosetxvalue #1#2{\global\edefcsname#1#2\endcsname} - \permanent\protected\def\doresetvalue #1#2{\letcsname#1#2\endcsname\empty} - \permanent\protected\def\doignorevalue#1#2#3{\letcsname#1#2\endcsname\empty} - - \permanent\protected\def\docopyvalue#1#2#3% - {\defcsname#1#3\expandafter\endcsname\expandafter - {\csname#2#3\endcsname}} - -\stopinterface - -\popoverloadmode - -%D We can now redefine some messages that will be introduced in the multi||lingual -%D system module. - -\permanent\protected\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}} -\permanent\protected\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}} -\permanent\protected\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}} - -%D \CONTEXT\ is a parameter driven package. This means that users instruct the -%D system by means of variables, values and keywords. These instructions take the -%D form: -%D -%D \starttyping -%D \setupsomething[some variable=some value, another one=a keyword] -%D \stoptyping -%D -%D or by keyword only: -%D -%D \starttyping -%D \dosomething[this way,that way,no way] -%D \stoptyping -%D -%D Because the same variables can occur in more than one setup command, we have to -%D be able to distinguish them. This is achieved by assigning them a unique prefix. -%D -%D Imagine a setup command for boxed text, that enables us to specify the height and -%D width of the box. Behide the scenes the command -%D -%D \starttyping -%D \setupbox [width=12cm, height=3cm] -%D \stoptyping -%D -%D results in something like -%D -%D \starttyping -%D \ {12cm} -%D \ {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 \ {21.0cm} -%D \ {27.9cm} -%D \stoptyping -%D -%D The prefixes \type {} and \type {} are hidden from users and can -%D therefore be language independant. Variables on the other hand, differ for each -%D language: -%D -%D \starttyping -%D \ {} -%D \ {} -%D \ {} -%D \stoptyping -%D -%D In this example we can see that the assigned values or keywords are language -%D dependant too. This will be a complication when defining multi||lingual setup -%D files. -%D -%D A third phenomena is that variables and values can have a similar meaning. -%D -%D \starttyping -%D \ {} -%D \ {12cm} -%D \stoptyping -%D -%D A (minor) complication is that where in english we use \type {}, in dutch -%D we find both \type {} and \type {}. This means that when we use -%D some sort of translation table, we have to distinguish between the variables at -%D the left side and the fixed values at the right. -%D -%D The same goes for commands that are composed of different user supplied and/or -%D language specific elements. In english we can use: -%D -%D \starttyping -%D \
-%D \ -%D \stoptyping -%D -%D But in dutch we have the following: -%D -%D \starttyping -%D \ -%D \ -%D \stoptyping -%D -%D These subtle differences automatically lead to a solution where variables, -%D values, elements and other components have a similar logical name (used in -%D macro's) but a different meaning (supplied by the user). -%D -%D Our solution is one in which the whole system is programmed in terms of -%D identifiers with language specific meanings. In such an implementation, each -%D fixed variable is available as: -%D -%D \starttyping -%D \ -%D \stoptyping -%D -%D This means that for instance: -%D -%D \starttyping -%D \setupbox[width=12cm] -%D \stoptyping -%D -%D expands to something like: -%D -%D \starttyping -%D \def\boxwidth{12cm} -%D \stoptyping -%D -%D because we don't want to recode the source, a setup command in another language -%D has to expand to this variable, so: -%D -%D \starttyping -%D \setupblock[width=12cm] -%D \stoptyping -%D -%D has to result in the definition of \type {\boxwidth} too. This method enables us -%D to build compact, fast and readable code. -%D -%D An alternative method, which we considered using, uses a more indirect way. In -%D this case, both calls generate a different variable: -%D -%D \starttyping -%D \def\boxwidth {12cm} -%D \def\boxbreedte {12cm} -%D \stoptyping -%D -%D And because we don't want to recode those megabytes of already developed code, -%D this variable has to be called with something like: -%D -%D \starttyping -%D \valueof\box\width -%D \stoptyping -%D -%D where \type {\valueof} takes care of the translation of \type {width} or \type -%D {breedte} to \type {width} and combining this with \type {box} to \type -%D {\boxwidth}. -%D -%D One advantage of this other scheme is that, within certain limits, we can -%D implement an interface that can be switched to another language at will, while -%D the current approach fixes the interface at startup. There are, by the way, other -%D reasons too for not choosing this scheme. Switching user generated commands is -%D for instance impossible and a dual interface would therefore give a strange mix -%D of languages. -%D -%D Now let's work out the first scheme. Although the left hand of the assignment is -%D a variable from the users point of view, it is a constant in terms of the system. -%D Both \type {width} and \type {breedte} expand to \type {width} because in the -%D source we only encounter \type {width}. Such system constants are presented as -%D -%D \starttyping -%D \c!width -%D \stoptyping -%D -%D This constant is always equivalent to \type {width}. As we can see, we use \type -%D {c!} to mark this one as constant. Its dutch counterpart is: -%D -%D \starttyping -%D breedte -%D \stoptyping -%D -%D When we interpret a setup command each variable is translated to it's \type{c!} -%D counterpart. This means that \type {breedte} and \type{width} expand to \type -%D {breedte} and \type {\c!width} which both expand to \type {width}. That way user -%D variables become system constants. -%D -%D The interpretation is done by means of a general setup command \type -%D {\getparameters} that we introduced in the system module. Let us define some -%D simple setup command: -%D -%D \starttyping -%D \protected\def\setupbox[#1]% -%D {\getparameters[\??bx][#1]} -%D \stoptyping -%D -%D This command can be used as: -%D -%D \starttyping -%D \setupbox [width=3cm, height=1cm] -%D \stoptyping -%D -%D Afterwards we have two variables \type {\@@bxwidth} and \type {\@@bxheight} which -%D have the values \type {3cm} and \type {1cm} assigned. These variables are a -%D combinatiom of the setup prefix \type {\??bx}, which expands to \type {@@bx} and -%D the translated user supplied variables \type {width} and \type {height} or \type -%D {breedte} and \type {hoogte}, depending on the actual language. In dutch we just -%D say: -%D -%D \starttyping -%D \stelblokin [breedte=3cm,hoogte=1cm] -%D \stoptyping -%D -%D and get ourselves \type {\@@bxwidth} and \type {\@@bxheight} too. In the source -%D of \CONTEXT, we can recognize constants and variables on their leading \type -%D {c!}, \type {v!} etc., prefixes on \type {??} and composed variables on \type -%D {@@}. -%D -%D We already saw that user supplied keywords need some special treatment too. This -%D time we don't translate the keyword, but instead use in the source a variable -%D which meaning depends on the interface language. -%D -%D \starttyping -%D \v!left -%D \stoptyping -%D -%D Which can be used in macro's like: -%D -%D \starttyping -%D \processaction -%D [\@@bxlocation] -%D [ \v!left=>\dosomethingontheleft, -%D \v!middle=>\dosomthinginthemiddle, -%D \v!right=>\dosomethingontheright] -%D \stoptyping -%D -%D Because variables like \type {\@@bxlocation} can have a lot of meanings, -%D including tricky expandable tokens, we cannot translate this meaning when we -%D compare. This means that \type {\@@bxlocation} can be \type {left} of \type -%D {links} of whatever meaning suits the language. But because \type {\v!left} also -%D has a meaning that suits the language, we are able to compare. -%D -%D Although we know it sounds confusing we want to state two important -%D characteristics of the interface as described: -%D -%D \startnarrower \em -%D user variables become system constants -%D \stopnarrower -%D -%D and -%D -%D \startnarrower \em -%D user constants (keywords) become system variables -%D \stopnarrower -%D -%D The \type {\c!internal} is a left over from the time that the user interface -%D documents were not using a specification alongside a keyword specification but -%D used a shared file in which case we need to go in both directions. - -% temporary mkiv hack (we can best just store the whole table in memory) - -\permanent\overloaded\protected\def\setinterfaceconstant#1#2% - {\clf_setinterfaceconstant{#1}{#2}% - \immutable\defcsname\c!prefix!#1\endcsname{#1}} - -\permanent\overloaded\protected\def\setinterfacevariable#1#2% - {\clf_setinterfacevariable{#1}{#2}% - \immutable\defcsname\v!prefix!#1\endcsname{#2}} - -%D \macros -%D {defineinterfaceconstant} -%D -%D Next we redefine a previously defined macro to take care of interface translation -%D too. It's a bit redundant, because in these situations we could use the -%D c||version, but for documentation purposes the x||alternative comes in handy. - -\permanent\overloaded\protected\def\defineinterfaceconstant#1#2% - {\immutable\defcsname\c!prefix!#1\endcsname{#2}} - -%D \macros -%D {startelements} -%D -%D Due to the object oriented nature of \CONTEXT, we also need to define the -%D elements that are used to build commands. -%D -%D Such elements sometimes are the same in different languages, but mostly they -%D differ. Things can get even confusing when we look at for instance the setup -%D commands. In english we say \type{\setup}, but in dutch we have: \type -%D {\stelin}. Such split elements are no problem, because we just define two -%D elements. When no second part is needed, we use a \type {-}: - -\permanent\overloaded\protected\def\setinterfaceelement#1#2% - {\clf_setinterfaceelement{#1}{#2}% - \ifcsname\e!prefix!#1\endcsname - \doifnotvalue{\e!prefix!#1}{#2}{\enforced\immutable\setvalue{\e!prefix!#1}{#2}}% - \else - \enforced\immutable\setvalue{\e!prefix!#1}{#2}% - \fi} - -\permanent\protected\def\setinterfacecommand#1#2% \frozen ? \permanent ? - {\doifnot{#1}{#2}% todo: let when already defined - {\defcsname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}} - -%D We just ignore these: - -\permanent\protected\def\startvariables{\gobbleuntil\stopvariables} \aliased\let\stopvariables\relax -\permanent\protected\def\startconstants{\gobbleuntil\stopconstants} \aliased\let\stopconstants\relax -\permanent\protected\def\startelements {\gobbleuntil\stopelements } \aliased\let\stopelements \relax -\permanent\protected\def\startcommands {\gobbleuntil\stopcommands } \aliased\let\stopcommands \relax - -%D For at the \LUA\ end (experiment): - -\def\ui_c#1#2{\immutable\global\defcsname\c!prefix!#1\endcsname{#1}% - \immutable\global\defcsname\k!prefix!#2\endcsname{#1}} % backmapping from non english -\def\ui_s #1{\immutable\global\defcsname\c!prefix!#1\endcsname{#1}% - \immutable\global\defcsname\k!prefix!#1\endcsname{#1}} % backmapping from non english -\def\ui_v#1#2{\immutable\global\defcsname\v!prefix!#1\endcsname{#2}} -\def\ui_e#1#2{\immutable\global\defcsname\e!prefix!#1\endcsname{#2}} -\def\ui_a#1#2{\frozen\protected\def#2{#1}} % will go away - -\startinterface english - - \def\ui_c#1#2{\immutable\global\defcsname\c!prefix!#1\endcsname{#1}} - \def\ui_s #1{\immutable\global\defcsname\c!prefix!#1\endcsname{#1}} - -\stopinterface - -%D So much for the basic multi||lingual interface commands. The macro's can be -%D enhanced with more testing facilities, but for the moment they suffice. - -\ifdefined\zwnj \else \immutable\edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv -\ifdefined\zwj \else \immutable\edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv - -%D \macros -%D {contextversion, contextversionnumber, contextversionno, -%D contextbanner, showcontextbanner, formatversion} -%D -%D Out of convenience we define the banners here. This might move to the \LUA\ end. - -\pushoverloadmode - -\permanent\overloaded\def\contextbanner - {ConTeXt \space - ver: \contextversion \space \contextmark \space \space - fmt: \formatversion \space \space - int: \currentinterface/\currentresponses} - -\permanent\overloaded\protected\def\showcontextbanner - {\writestatus\m!system\empty - \writestatus\m!system\contextbanner - \writestatus\m!system\empty} - -\immutable\overloaded\edef\formatversion - {\the\normalyear.\the\normalmonth.\the\normalday} - -\newcount\contextversionno - -\ifx\contextversion\undefined - \immutable\edef\contextversion{\the\normalyear.\the\normalmonth.\the\normalday\space 00:00} -\fi - -\permanent\overloaded\protected\def \contextversionnumber #1.#2.#3 #4:#5\relax{#1#2#3} - \contextversionno \expandafter\contextversionnumber\contextversion\relax -\immutable\overloaded \edef\contextversionnumber {\the\contextversionno\space\contextmark} - -\popoverloadmode - -%D \macros -%D {everydump} -%D -%D This one is only used when we generate the format. - -% \ifx\undefined\everydump -% \newtoks\everydump -% \def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump} -% \fi - -% \appendtoks \showcontextbanner \to \everydump - -\protect \endinput diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 3d0f65dba..c60ed1640 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -291,8 +291,10 @@ return { "futureexpand", "futureexpandis", "futureexpandisap", + "gdefcsname", "gleaders", "glet", + "gletcsname", "glyphdatafield", "glyphdimensionsmode", "glyphoptions", @@ -425,11 +427,13 @@ return { "tpack", "tracingfonts", "tracingmath", + "undent", "unletfrozen", "unletprotected", "vpack", "wordboundary", "wrapuppar", + "xdefcsname", "xtoksapp", "xtokspre", }, diff --git a/tex/context/base/mkiv/mult-prm.mkxl b/tex/context/base/mkiv/mult-prm.mkxl deleted file mode 100644 index 2ec763c39..000000000 --- a/tex/context/base/mkiv/mult-prm.mkxl +++ /dev/null @@ -1,117 +0,0 @@ -%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. - -% local all = table.load("mult-prm.lua") -% local tex = table.tohash(all.tex) -% for k, v in next, all do -% if k ~= "tex" then -% local h = table.tohash(v) -% for k, v in next, h do -% tex[k] = nil -% end -% all[k] = table.sortedkeys(h) -% end -% end -% all.tex = table.sortedkeys(tex) -% print((string.gsub(table.serialize(all,true),' "','\n "'))) - -\startluacode - - context.starttext() - - local missing = { - tex = { - -- todo: differenced between luatex and luametatex - }, - etex = { - -- todo: differenced between luatex and luametatex - }, - luatex = { - -- todo: differenced between luatex and luametatex - }, - pdftex = { -- maybe not complete - "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "pdfadjustspacing", - "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", - "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", - "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", - "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", - "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", - "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", - "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", - "pdfignoreddimen", "pdfignoreunknownimages", "pdfimageaddfilename", - "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", - "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", - "pdfinclusionerrorlevel", "pdfinfo", "pdfinfoomitdate", - "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", - "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages", - "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", - "pdfmapfile", "pdfmapline", "pdfmajorversion", "pdfminorversion", "pdfnames", - "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfrecompress", - "pdfobjcompresslevel", "pdfoutline", "pdfoutput", "pdfpageattr", - "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", - "pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode", - "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", - "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", - "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", - "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", - "pdfsuppressoptionalinfo", "pdfsuppressptexinfo", "pdftexbanner", - "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", - "pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate", - "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", - "pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage", - "pdfomitcidset", "pdfomitcharset", - }, - aleph = { -- we don't bother - "Alephminorversion", "Alephrevision", "Alephversion", - }, - omega = { -- we don't bother - "Omegaminorversion", "Omegarevision", "Omegaversion", - }, - xetex = { -- we don't bother - "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 , tex.extraprimitives("core","tex") ) ), - etex = table.sorted( table.merged( missing.etex , tex.extraprimitives("etex") ) ), - pdftex = table.sorted( table.merged( missing.pdftex, { } ) ), - luatex = table.sorted( table.merged( missing.luatex, tex.extraprimitives("luatex") ) ), - aleph = table.sorted( table.merged( missing.aleph , { } ) ), - omega = table.sorted( table.merged( missing.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/tex/context/base/mkiv/mult-sys.mkxl b/tex/context/base/mkiv/mult-sys.mkxl deleted file mode 100644 index b782e9db4..000000000 --- a/tex/context/base/mkiv/mult-sys.mkxl +++ /dev/null @@ -1,602 +0,0 @@ -%D \module -%D [ file=mult-sys, -%D version=1996.06.01, -%D title=\CONTEXT\ Multilingual Macros, -%D subtitle=System, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D In boring module we define a lot of obscure but useful system constants. -%D By doing so we save lots of memory while at the same time we prevent -%D ourself making typing errors. - -\writestatus{loading}{ConTeXt Multilingual Macros / System} - -\unprotect - -%D This file is mostly the same as the \MKII\ variant but we keep extending -%D \MKIV, so it was bout time to have a dedicated variant. -%D -%D The constants are grouped in such a way that there is a minimal change of -%D conflicts. -%D -%D \starttyping -%D \definesystemconstants {word} -%D \definemessageconstant {word} -%D \stoptyping -%D -%D This commands generate \type{\s!word} and \type{\m!word}. - -\definesystemconstant {hans} -\definesystemconstant {taco} -\definesystemconstant {wolfgang} - -%D First we define some system constants used for both the multi||lingual -%D interface and multi||linguag typesetting. - -% definesystemconstant {slovene} -% definesystemconstant {cz} -% definesystemconstant {vn} - -\definesystemconstant {afrikaans} \definesystemconstant {af} -\definesystemconstant {ancientgreek} \definesystemconstant {agr} -\definesystemconstant {ancientlatin} \definesystemconstant {ala} -\definesystemconstant {arabic} \definesystemconstant {ar} -\definesystemconstant {bokmal} \definesystemconstant {nb} -\definesystemconstant {catalan} \definesystemconstant {ca} -\definesystemconstant {chinese} \definesystemconstant {cn} -\definesystemconstant {croatian} \definesystemconstant {hr} -\definesystemconstant {czech} \definesystemconstant {cs} -\definesystemconstant {danish} \definesystemconstant {da} -\definesystemconstant {dutch} \definesystemconstant {nl} -\definesystemconstant {english} \definesystemconstant {en} -\definesystemconstant {estonian} \definesystemconstant {et} -\definesystemconstant {esperanto} % \definesystemconstant {eo} -\definesystemconstant {farsi} \definesystemconstant {fa} % just persian -\definesystemconstant {finnish} \definesystemconstant {fi} -\definesystemconstant {french} \definesystemconstant {fr} -\definesystemconstant {gbenglish} \definesystemconstant {gb} -\definesystemconstant {german} \definesystemconstant {de} -\definesystemconstant {greek} \definesystemconstant {gr} -\definesystemconstant {hebrew} \definesystemconstant {he} -\definesystemconstant {yiddish} \definesystemconstant {yi} -\definesystemconstant {hungarian} \definesystemconstant {hu} -\definesystemconstant {italian} \definesystemconstant {it} -\definesystemconstant {japanese} \definesystemconstant {ja} -\definesystemconstant {korean} \definesystemconstant {kr} -\definesystemconstant {latin} \definesystemconstant {la} -\definesystemconstant {lithuanian} \definesystemconstant {lt} -\definesystemconstant {malayalam} \definesystemconstant {ml} -\definesystemconstant {norwegian} \definesystemconstant {no} -\definesystemconstant {nynorsk} \definesystemconstant {nn} -\definesystemconstant {persian} \definesystemconstant {pe} -\definesystemconstant {polish} \definesystemconstant {pl} -\definesystemconstant {portuguese} \definesystemconstant {pt} -\definesystemconstant {romanian} \definesystemconstant {ro} -\definesystemconstant {russian} \definesystemconstant {ru} -\definesystemconstant {slovak} \definesystemconstant {sk} -\definesystemconstant {slovenian} \definesystemconstant {sl} -\definesystemconstant {spanish} \definesystemconstant {es} -\definesystemconstant {swedish} \definesystemconstant {sv} -\definesystemconstant {thai} \definesystemconstant {th} % mojca mentioned it at BT2013 but we need more info -\definesystemconstant {turkish} \definesystemconstant {tr} -\definesystemconstant {turkmen} \definesystemconstant {tk} -\definesystemconstant {ukenglish} \definesystemconstant {uk} -\definesystemconstant {ukrainian} \definesystemconstant {ua} -\definesystemconstant {usenglish} \definesystemconstant {us} -\definesystemconstant {vietnamese} \definesystemconstant {vi} - -%D Left|-|overs: - -\defineinterfaceconstant {HL} {HL} -\defineinterfaceconstant {VL} {VL} -\defineinterfaceconstant {NL} {NL} - -%D For proper \UNICODE\ support we need a few font related constants. - -\definesystemconstant {action} -\definesystemconstant {all} -\definesystemconstant {ampersand} -\definesystemconstant {ascii} -\definesystemconstant {attribute} -\definesystemconstant {attr} -\definesystemconstant {author} -\definesystemconstant {auto} -\definesystemconstant {axis} -\definesystemconstant {a} -\definesystemconstant {bf} -\definesystemconstant {big} -\definesystemconstant {binary} -\definesystemconstant {bi} -\definesystemconstant {blackboard} -\definesystemconstant {black} -\definesystemconstant {BoldItalic} -\definesystemconstant {BoldSlanted} -\definesystemconstant {Bold} -\definesystemconstant {bold} -\definesystemconstant {both} -\definesystemconstant {bottomfloat} -\definesystemconstant {bottom} -\definesystemconstant {box} -\definesystemconstant {bp} -\definesystemconstant {bs} -\definesystemconstant {b} -\definesystemconstant {calligraphy} -\definesystemconstant {Calligraphy} -\definesystemconstant {Caps} -\definesystemconstant {casual} -\definesystemconstant {Casual} -\definesystemconstant {catcodes} -\definesystemconstant {catcodetable} -\definesystemconstant {cc} -\definesystemconstant {cg} -\definesystemconstant {chain} -\definesystemconstant {check} -\definesystemconstant {child} -\definesystemconstant {cite} -\definesystemconstant {class} -\definesystemconstant {clone} -\definesystemconstant {cmyk} -\definesystemconstant {cm} -\definesystemconstant {code} -\definesystemconstant {collapsing} -\definesystemconstant {command} -\definesystemconstant {compare} -\definesystemconstant {complex} -\definesystemconstant {counter} -\definesystemconstant {cramped} -\definesystemconstant {current} -\definesystemconstant {c} -\definesystemconstant {data} -\definesystemconstant {dd} -\definesystemconstant {decimal} -\definesystemconstant {DefaultFont} -\definesystemconstant {default} -\definesystemconstant {depth} -\definesystemconstant {designsize} -\definesystemconstant {direction} -\definesystemconstant {display} -\definesystemconstant {document} -\definesystemconstant {dodo} -\definesystemconstant {done} -\definesystemconstant {double} -\definesystemconstant {do} -\definesystemconstant {dtp} -\definesystemconstant {dummy} -\definesystemconstant {d} -\definesystemconstant {edge} -\definesystemconstant {effect} -\definesystemconstant {empty} -\definesystemconstant {em} -\definesystemconstant {environment} -\definesystemconstant {extensions} -\definesystemconstant {external} -\definesystemconstant {ex} -\definesystemconstant {e} -\definesystemconstant {fallbacks} -\definesystemconstant {fallback} -\definesystemconstant {false} -\definesystemconstant {fax} -\definesystemconstant {features} -\definesystemconstant {file} -\definesystemconstant {filll} -\definesystemconstant {fill} -\definesystemconstant {fil} -\definesystemconstant {first} -\definesystemconstant {float} -\definesystemconstant {font} -\definesystemconstant {forget} -\definesystemconstant {format} -\definesystemconstant {fraktur} -\definesystemconstant {full} -\definesystemconstant {f} -\definesystemconstant {global} -\definesystemconstant {goodies} -\definesystemconstant {gray} -\definesystemconstant {handler} -\definesystemconstant {handwriting} -\definesystemconstant {Handwriting} -\definesystemconstant {hascaption} -\definesystemconstant {haslevel} -\definesystemconstant {hasnumber} -\definesystemconstant {hasparent} -\definesystemconstant {hassuffix} -\definesystemconstant {hastitle} -\definesystemconstant {head} -\definesystemconstant {height} -\definesystemconstant {hw} -\definesystemconstant {hyphenmin} -\definesystemconstant {indeed} -\definesystemconstant {initializations} -\definesystemconstant {insert} % maybe insertclass -\definesystemconstant {integral} -\definesystemconstant {internal} -\definesystemconstant {in} -\definesystemconstant {italics} -\definesystemconstant {Italic} -\definesystemconstant {italic} -%definesystemconstant {it} -\definesystemconstant {itemgroupcolumns} -\definesystemconstant {kernpairs} -\definesystemconstant {language} -\definesystemconstant {lcgreek} -\definesystemconstant {lefthyphenchar} -\definesystemconstant {lefthyphenmin} -\definesystemconstant {leftpage} -\definesystemconstant {left} -\definesystemconstant {level} -\definesystemconstant {ligatures} -\definesystemconstant {line} -\definesystemconstant {link} -\definesystemconstant {list} -\definesystemconstant {local} -\definesystemconstant {lua} -\definesystemconstant {mapping} -\definesystemconstant {map} -\definesystemconstant {margintext} -\definesystemconstant {margin} -\definesystemconstant {marker} -\definesystemconstant {MathBold} % not used -\definesystemconstant {MathRomanBold} -\definesystemconstant {MathRoman} -\definesystemconstant {math} -\definesystemconstant {Math} % not used -\definesystemconstant {mblr} -\definesystemconstant {mbrl} -\definesystemconstant {mb} -\definesystemconstant {middle} -\definesystemconstant {minus} -\definesystemconstant {mixedcolumn} -\definesystemconstant {mi} % maybe some day a special default vector -\definesystemconstant {mkii} -\definesystemconstant {mkiv} -\definesystemconstant {mm} -\definesystemconstant {mnem} % kind of generic short tag -\definesystemconstant {mode} -\definesystemconstant {MonoBoldItalic} -\definesystemconstant {MonoBoldSlanted} -\definesystemconstant {MonoBold} -\definesystemconstant {MonoCaps} -\definesystemconstant {MonoItalic} -\definesystemconstant {MonoSlanted} -\definesystemconstant {Mono} -\definesystemconstant {mono} -\definesystemconstant {mrlr} -\definesystemconstant {mrrl} -\definesystemconstant {mr} -\definesystemconstant {multi} -\definesystemconstant {name} -\definesystemconstant {next} -\definesystemconstant {nocite} -\definesystemconstant {nodepth} -\definesystemconstant {noheight} -\definesystemconstant {nomath} -\definesystemconstant {none} -\definesystemconstant {normal} -\definesystemconstant {Normal} -\definesystemconstant {nowidth} -\definesystemconstant {numbering} -\definesystemconstant {number} -\definesystemconstant {options} -\definesystemconstant {ord} -\definesystemconstant {orientation} -\definesystemconstant {otr} -\definesystemconstant {pagefloat} -\definesystemconstant {page} -\definesystemconstant {paragraph} -\definesystemconstant {parent} -\definesystemconstant {patterns} -\definesystemconstant {pc} -\definesystemconstant {pickup} -\definesystemconstant {plural} -\definesystemconstant {plus} -%definesystemconstant {pt} -\definesystemconstant {realpage} -\definesystemconstant {register} -\definesystemconstant {Regular} -\definesystemconstant {regular} -\definesystemconstant {rel} -\definesystemconstant {reset} -\definesystemconstant {reverse} -\definesystemconstant {rgb} -\definesystemconstant {righthyphenchar} -\definesystemconstant {righthyphenmin} -\definesystemconstant {rightpage} -\definesystemconstant {right} -\definesystemconstant {rm} -\definesystemconstant {rname} -\definesystemconstant {rscale} -\definesystemconstant {SansBoldItalic} -\definesystemconstant {SansBoldSlanted} -\definesystemconstant {SansBold} -\definesystemconstant {SansCaps} -\definesystemconstant {SansItalic} -\definesystemconstant {SansSlanted} -\definesystemconstant {Sans} -\definesystemconstant {sans} -\definesystemconstant {scriptscript} -\definesystemconstant {script} -\definesystemconstant {sc} -\definesystemconstant {second} -\definesystemconstant {section} -\definesystemconstant {SerifBoldItalic} -\definesystemconstant {SerifBoldSlanted} -\definesystemconstant {SerifBold} -\definesystemconstant {SerifCaps} -\definesystemconstant {SerifItalic} -\definesystemconstant {SerifSlanted} -\definesystemconstant {Serif} -\definesystemconstant {serif} -\definesystemconstant {setups} -\definesystemconstant {setup} -\definesystemconstant {set} -\definesystemconstant {themaintextcolor} -\definesystemconstant {simple} -\definesystemconstant {Simple} -\definesystemconstant {single} -\definesystemconstant {singular} -\definesystemconstant {size} -\definesystemconstant {slanted} -\definesystemconstant {Slanted} -%definesystemconstant {sl} -\definesystemconstant {smallcaps} -\definesystemconstant {small} -\definesystemconstant {somewhere} -\definesystemconstant {special} -\definesystemconstant {spec} -\definesystemconstant {spot} -\definesystemconstant {spread} -\definesystemconstant {sp} -\definesystemconstant {ss} -\definesystemconstant {start} -\definesystemconstant {stop} -\definesystemconstant {subpage} -\definesystemconstant {subtype} -\definesystemconstant {sub} -\definesystemconstant {Support} -\definesystemconstant {sygreek} -\definesystemconstant {symbol} -\definesystemconstant {system} % not yet interfaces messages -\definesystemconstant {text} -\definesystemconstant {tex} -\definesystemconstant {tf} -\definesystemconstant {third} -\definesystemconstant {topfloat} -\definesystemconstant {top} -\definesystemconstant {to} -\definesystemconstant {traditional} -\definesystemconstant {triple} -\definesystemconstant {true} -\definesystemconstant {tt} -\definesystemconstant {Type} -\definesystemconstant {ucgreek} -\definesystemconstant {uncramped} -\definesystemconstant {unexpanded} -\definesystemconstant {Unicode} -\definesystemconstant {unknown} -\definesystemconstant {userdata} -\definesystemconstant {userpage} -\definesystemconstant {user} -\definesystemconstant {vfrac} -\definesystemconstant {white} -\definesystemconstant {width} -\definesystemconstant {xml} -\definesystemconstant {xmove} -\definesystemconstant {xoffset} -\definesystemconstant {xx} -\definesystemconstant {x} -\definesystemconstant {ymove} -\definesystemconstant {yoffset} - -%D As the name of their define command states, the next set of constants is used in -%D the message macro's. - -\definemessageconstant {backend} -\definemessageconstant {check} -\definemessageconstant {chemicals} -\definemessageconstant {colors} -\definemessageconstant {columns} -\definemessageconstant {fields} -\definemessageconstant {figures} -\definemessageconstant {files} -\definemessageconstant {floatblocks} -\definemessageconstant {fonts} -\definemessageconstant {handlings} -\definemessageconstant {interactions} -\definemessageconstant {javascripts} -\definemessageconstant {languages} -\definemessageconstant {layouts} -\definemessageconstant {lua} -\definemessageconstant {metapost} -\definemessageconstant {publications} -\definemessageconstant {references} -\definemessageconstant {regimes} -\definemessageconstant {structures} -\definemessageconstant {symbols} -\definemessageconstant {system} -\definemessageconstant {textblocks} -\definemessageconstant {verbatims} -\definemessageconstant {versions} - -%D When we use numbers and dimensions the same applies as with the keywords like -%D \type {width} and \type {plus} mentioned earlier. - -\immutable\def\!!ten {10} -\immutable\def\!!twelve {12} -\immutable\def\!!hundred {100} -\immutable\def\!!thousand {1000} -\immutable\def\!!tenthousand {10000} -\immutable\def\!!maxcard {65536} -\immutable\def\!!medcard {32768} - -\immutable\def\!!zeropoint {0pt} -\immutable\def\!!onepoint {1pt} -\immutable\def\!!twopoint {2pt} -\immutable\def\!!threepoint {3pt} -\immutable\def\!!fourpoint {4pt} -\immutable\def\!!fivepoint {5pt} -\immutable\def\!!sixpoint {6pt} -\immutable\def\!!sevenpoint {7pt} -\immutable\def\!!eightpoint {8pt} -\immutable\def\!!ninepoint {9pt} -\immutable\def\!!tenpoint {10pt} -\immutable\def\!!elevenpoint {11pt} -\immutable\def\!!twelvepoint {12pt} -\immutable\def\!!fourteenpointfour {14.4pt} - -\immutable\def\!!plustoken {+} % todo: \??plustoken -\immutable\def\!!minustoken {-} % todo: \??minustoken - -\immutable\def\__unknown__ {\string\\//} % unlikely value - -%D Variables are composed of a command specific tag and a user supplied variable -%D (system constant). The tag \type {du} for instance is available as \type {\??du} -%D and expands to \type {@@du} in composed variables. - -\definesystemvariable {du} % dummy, will stay - -% bibl: - -\definesystemvariable {pv} % PublicationVariable -\definesystemvariable {pb} % PuBlication - -% needs checking (namespaces now) - -\definesystemvariable {fw} % simpleFonts by Wolfgang - -% old pragma - -\definesystemvariable {kt} % KonTakten -\definesystemvariable {kw} % KontaktWaarde -\definesystemvariable {st} % STickers -\definesystemvariable {km} % KenMerk - -% mkii - -\definesystemvariable {xf} % XML File (xtag) -\definesystemvariable {xp} % XML Processing (xtag, so still needed) -\definesystemvariable {fo} % xml FO (xtag) -\definesystemvariable {fx} % FoXet - -% mkiv - -%D Next we define some language independant one letter variables and keywords. We can -%D actually make these system variables. - -\defineinterfaceconstant {x} {x} -\defineinterfaceconstant {y} {y} -\defineinterfaceconstant {w} {w} -\defineinterfaceconstant {h} {h} -\defineinterfaceconstant {s} {s} -\defineinterfaceconstant {t} {t} - -\defineinterfaceconstant {a} {a} % can go -\defineinterfaceconstant {b} {b} % can go -\defineinterfaceconstant {c} {c} % can go -\defineinterfaceconstant {d} {d} % can go -\defineinterfaceconstant {e} {e} % can go -\defineinterfaceconstant {f} {f} % can go - -%defineinterfaceconstant {s} {s} -\defineinterfaceconstant {r} {r} -\defineinterfaceconstant {g} {g} -%defineinterfaceconstant {b} {b} -%defineinterfaceconstant {c} {c} -\defineinterfaceconstant {m} {m} -%defineinterfaceconstant {y} {y} -\defineinterfaceconstant {k} {k} -%defineinterfaceconstant {a} {a} % alternative -%defineinterfaceconstant {t} {t} % transparency -\defineinterfaceconstant {p} {p} % percentage -%defineinterfaceconstant {h} {h} -%defineinterfaceconstant {s} {s} -\defineinterfaceconstant {v} {v} - -\defineinterfaceconstant {rgb} {rgb} -\defineinterfaceconstant {cmyk} {cmyk} -\defineinterfaceconstant {mp} {mp} - -\defineinterfacevariable {rgb} {rgb} -\defineinterfacevariable {cmyk} {cmyk} -\defineinterfacevariable {mp} {mp} - -\defineinterfacevariable {s} {s} - -\defineinterfacevariable {a} {a} -\defineinterfacevariable {b} {b} -\defineinterfacevariable {c} {c} -\defineinterfacevariable {d} {d} - -%D Special purpose variables: - -\immutable\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi} - -%D The names of files and their extensions are fixed. \CONTEXT\ uses as less -%D files as possible. Utility files can be recognized by the first two -%D characters of the extension: \type {tu}. - -%definefileconstant {utilityfilename} {texutil} -%definefileconstant {blockextension} {tub} -%definefileconstant {figureextension} {tuf} -%definefileconstant {inputextension} {tui} -%definefileconstant {outputextension} {tuo} % tup for previous run -%definefileconstant {optionextension} {top} -%definefileconstant {temporaryextension} {tmp} -%definefileconstant {patternsextension} {pat} -%definefileconstant {hyphensextension} {hyp} -%definefileconstant {fontmapextension} {map} -\definefileconstant {bibextension} {bbl} - -%D These files are loaded at start||up. They may contain system specific setups (or -%D calls to other files), old macro's, to garantee compatibility and new macro's noy -%D yet present in the format. - -\definefileconstant {sysfilename} {cont-sys.mkiv} -\definefileconstant {newfilename} {cont-new.mkiv} -\definefileconstant {locfilename} {cont-loc.mkiv} -\definefileconstant {expfilename} {cont-exp.mkiv} -\definefileconstant {fntfilename} {cont-fnt.mkiv} % not yet used -\definefileconstant {gdsfilename} {cont-fnt.lfg} % not yet used - -%D The setup files for the language, font, color and special subsystems have a common -%D prefix. This means that we have at most three characters for unique filenames. - -\definefileconstant {colo_run} {colo-run} -\definefileconstant {font_run} {font-run} -\definefileconstant {page_run} {page-run} -\definefileconstant {symb_run} {symb-run} -\definefileconstant {publ_tra} {publ-tra} - -%D For figure inclusion we need(ed): - -%defineinterfaceconstant {tif} {tif} -%defineinterfaceconstant {eps} {eps} -%defineinterfaceconstant {mps} {mps} -%defineinterfaceconstant {jpg} {jpg} -%defineinterfaceconstant {pdf} {pdf} -%defineinterfaceconstant {png} {png} -%defineinterfaceconstant {avi} {avi} -%defineinterfaceconstant {mov} {mov} -%defineinterfaceconstant {svg} {svg} -\defineinterfaceconstant {tex} {tex} % Also gone? -%defineinterfaceconstant {tmp} {tmp} -%defineinterfaceconstant {cld} {cld} - -%D A careful reader will have noticed that in the module \type {mult-ini} we defined -%D \type {\selectinterface}. We were not yet able to actually select an interface, -%D because we still had to define the constants and variables. Now we've done so, -%D selection is permitted. - -\selectinterface - -%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT. - -\definemessageconstant {addresses} -\definemessageconstant {documents} - -\protect \endinput diff --git a/tex/context/base/mkiv/node-aux.lmt b/tex/context/base/mkiv/node-aux.lmt deleted file mode 100644 index d952ec41b..000000000 --- a/tex/context/base/mkiv/node-aux.lmt +++ /dev/null @@ -1,396 +0,0 @@ -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 = nodes -local context = context - -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 par_code = nodecodes.par - -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 getattr = nuts.getattr -local getboth = nuts.getboth -local getprev = nuts.getprev -local getwidth = nuts.getwidth -local setwidth = nuts.setwidth -local getboxglue = nuts.getboxglue -local setboxglue = nuts.setboxglue - -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 setattrlist = nuts.setattrlist - -local traversers = nuts.traversers -local nextnode = traversers.node -local nextglyph = traversers.glyph - -local flush_node = nuts.flush -local flush_list = nuts.flush_list -local hpack_nodes = nuts.hpack -local unset_attribute = nuts.unset_attribute -local first_glyph = nuts.first_glyph -local copy_node = nuts.copy -local find_tail = nuts.tail -local getbox = nuts.getbox -local count = nuts.count -local isglyph = nuts.isglyph - -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") - -local function takebox(id) - local box = getbox(id) - if box then - local list = getlist(box) - setlist(box,nil) - local copy = copy_node(box) - if list then - setlist(copy,list) - end - texsetbox(id,false) - 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) - flush_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) - flush_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, id in nextnode, head do - setattr(n,attr,value) - 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, id in nextnode, head do - if not getattr(n,attr) then - setattr(n,attr,value) - end - 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, id in nextnode, head do - setattr(n,attr,unsetvalue) - 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) - -function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 - if untagged then - return first_glyph(n) - else - for g in nextglyph ,n do - return g - end - end -end - -local function firstcharinbox(n) - local l = getlist(getbox(n)) - if l then - for g, c in nextglyph, l do - return c - 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 - setattrlist(n,attr) - end - if head then - setlink(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) -- 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, id, subtype in nextnode, start do - if id == wantedid then - if not wantedsubtype or subtype == 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 - -local function rehpack(n,width) - local head = getlist(n) - local size = width or getwidth(n) - local temp = hpack_nodes(head,size,"exactly") - setwidth(n,size) - local set, order, sign = getboxglue(temp) - setboxglue(n,set,order,sign) - setlist(temp) - flush_node(temp) - return n -end - -nuts.rehpack = rehpack - -function nodes.rehpack(n,...) - rehpack(tonut(n),...) -end - -do - - local parcodes = nodes.parcodes - local hmodepar_code = parcodes.hmode_par - local vmodepar_code = parcodes.vmode_par - - local getnest = tex.getnest - local getsubtype = nuts.getsubtype - - function nuts.setparproperty(action,...) - local tail = tonut(getnest().tail) - while tail do - if getid(tail) == par_code then - local s = getsubtype(tail) - if s == hmodepar_code or s == vmodepar_code then - return action(tail,...) - else - -- something is wrong here - end - end - tail = getprev(tail) - end - end - - local getsubtype = nodes.getsubtype - - function nodes.start_of_par(n) - local s = getsubtype(n) - return s == hmodepar_code or s == vmodepar_code - end - -end diff --git a/tex/context/base/mkiv/node-bck.mkxl b/tex/context/base/mkiv/node-bck.mkxl deleted file mode 100644 index e37d65b1c..000000000 --- a/tex/context/base/mkiv/node-bck.mkxl +++ /dev/null @@ -1,92 +0,0 @@ -%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. - -\unprotect - -\registerctxluafile{node-bck}{optimize} - -% \backgroundvbox[green] {\input tufte } \par -% \backgroundvbox[blue] {\input ward } \par -% \backgroundvbox[red] {\input knuth } \par -% \backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par - -\permanent\def\colorattr#1% - {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname - \node_backgrounds_thecolorattr{\currentcolorprefix#1}% - \orelse\ifcsname\??colorattribute#1\endcsname - \node_backgrounds_thecolorattr{#1}% - \fi} - -\def\node_backgrounds_thecolorattr#1% - {attr \colormodelattribute \c_attr_colormodel - attr \colorattribute \lastnamedcs - attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized - -\permanent\def\thecolorattr#1% - {attr \colormodelattribute \c_attr_colormodel - attr \colorattribute \csname\??colorattribute#1\endcsname - attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized - -\permanent\def\backgroundcolorattr#1% - {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname - \node_backgrounds_thebackgroundcolorattr{\currentcolorprefix#1}% - \orelse\ifcsname\??colorattribute#1\endcsname - \node_backgrounds_thebackgroundcolorattr{#1}% - \fi} - -\permanent\def\thebackgroundcolorattr#1% - {attr \backgroundattribute \plusone - attr \colormodelattribute \c_attr_colormodel - attr \colorattribute \csname\??colorattribute#1\endcsname - attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized - -\def\node_backgrounds_thebackgroundcolorattr#1% - {attr \backgroundattribute \plusone - attr \colormodelattribute \c_attr_colormodel - attr \colorattribute \lastnamedcs - attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized - -\permanent\def\thealignbackgroundcolorattr#1% - {attr \alignbackgroundattribute \plusone - attr \colormodelattribute \c_attr_colormodel - attr \colorattribute \csname\??colorattribute#1\endcsname - attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized - -\permanent\protected\def\backgroundhbox{\node_backgrounds_boxes_add\hbox} -\permanent\protected\def\backgroundvbox{\node_backgrounds_boxes_add\vbox} -\permanent\protected\def\backgroundvtop{\node_backgrounds_boxes_add\vtop} -\permanent\protected\def\backgroundline{\dontleavehmode\node_backgrounds_boxes_add\hbox} - -% \def\node_backgrounds_boxes_add#1[#2]% -% {\begingroup -% \clf_enablebackgroundboxes -% \dousecolorparameter{#2}% -% \normalexpanded{\endgroup#1 -% attr \backgroundattribute \plusone -% attr \colormodelattribute \the\c_attr_colormodel -% attr \colorattribute \the\c_attr_color -% attr \transparencyattribute \the\c_attr_transparency}} -% -% more efficient: - -\def\node_backgrounds_boxes_add#1[#2]% - {\clf_enablebackgroundboxes - #1\backgroundcolorattr{#2}} - -\protect \endinput diff --git a/tex/context/base/mkiv/node-cmp.lmt b/tex/context/base/mkiv/node-cmp.lmt deleted file mode 100644 index 21fd700f0..000000000 --- a/tex/context/base/mkiv/node-cmp.lmt +++ /dev/null @@ -1,237 +0,0 @@ -if not modules then modules = { } end modules ['node-cmp'] = { - 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 a LuaTeX compatibility module. The code below is no longer --- present in node-met or node-aux. These functions are rarely used. - -if node.count then - return -end - -local type = type - -local node = node -local direct = node.direct -local todirect = direct.tovaliddirect -local tonode = direct.tonode - -local count = direct.count -local length = direct.length -local slide = direct.slide - -function node.count(id,first,last) - return count(id,first and todirect(first), last and todirect(last) or nil) -end - -function node.length(first,last) - return length(first and todirect(first), last and todirect(last) or nil) -end - -function node.slide(n) - if n then - n = slide(todirect(n)) - if n then - return tonode(n) - end - end - return nil -end - -local hyphenating = direct.hyphenating -local ligaturing = direct.ligaturing -local kerning = direct.kerning - --- kind of inconsistent - -function node.hyphenating(first,last) - if first then - local h, t = hyphenating(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end -end - -function node.ligaturing(first,last) - if first then - local h, t = ligaturing(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end -end - -function node.kerning(first,last) - if first then - local h, t = kerning(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end - end - -local protect_glyph = direct.protect_glyph -local unprotect_glyph = direct.unprotect_glyph -local protect_glyphs = direct.protect_glyphs -local unprotect_glyphs = direct.unprotect_glyphs - -function node.protect_glyphs(first,last) - protect_glyphs(todirect(first), last and todirect(last) or nil) -end - -function node.unprotect_glyphs(first,last) - unprotect_glyphs(todirect(first), last and todirect(last) or nil) -end - -function node.protect_glyph(first) - protect_glyph(todirect(first)) -end - -function node.unprotect_glyph(first) - unprotect_glyph(todirect(first)) -end - -local flatten_discretionaries = direct.flatten_discretionaries -local check_discretionaries = direct.check_discretionaries -local check_discretionary = direct.check_discretionary - -function node.flatten_discretionaries(first) - local h, count = flatten_discretionaries(todirect(first)) - return tonode(h), count -end - -function node.check_discretionaries(n) - check_discretionaries(todirect(n)) -end - -function node.check_discretionary(n) - check_discretionary(todirect(n)) -end - -local hpack = direct.hpack -local vpack = direct.vpack -local list_to_hlist = direct.mlist_to_hlist - -function node.hpack(head,...) - local h, badness = hpack(head and todirect(head) or nil,...) - return tonode(h), badness -end - -function node.vpack(head,...) - local h, badness = vpack(head and todirect(head) or nil,...) - return tonode(h), badness -end - -function node.mlist_to_hlist(head,...) - return tonode(mlist_to_hlist(head and todirect(head) or nil,...)) -end - -local end_of_math = direct.end_of_math -local find_attribute = direct.find_attribute -local first_glyph = direct.first_glyph - -function node.end_of_math(n) - if n then - n = end_of_math(todirect(n)) - if n then - return tonode(n) - end - end - return nil -end - -function node.find_attribute(n,a) - if n then - local v, n = find_attribute(todirect(n),a) - if n then - return v, tonode(n) - end - end - return nil -end - -function node.first_glyph(first,last) - local n = first_glyph(todirect(first), last and todirect(last) or nil) - return n and tonode(n) or nil -end - -local dimensions = direct.dimensions -local rangedimensions = direct.rangedimensions -local effective_glue = direct.effective_glue - -function node.dimensions(a,b,c,d,e) - if type(a) == "userdata" then - a = todirect(a) - if type(b) == "userdata" then - b = todirect(b) - end - return dimensions(a,b) - else - d = todirect(d) - if type(e) == "userdata" then - e = todirect(e) - end - return dimensions(a,b,c,d,e) - end - return 0, 0, 0 -end - -function node.rangedimensions(parent,first,last) - return rangedimenensions(todirect(parent),todirect(first),last and todirect(last)) -end - -function node.effective_glue(list,parent) - return effective_glue(list and todirect(list) or nil,parent and todirect(parent) or nil) -end - -local uses_font = direct.uses_font -local has_glyph = direct.has_glyph -local protrusion_skippable = direct.protrusion_skippable -local make_extensible = direct.make_extensible - -function node.uses_font(n,f) - return uses_font(todirect(n),f) -end - -function node.has_glyph(n) - return has_glyph(todirect(n)) -end - -function node.protrusion_skippable(n) - return protrusion_skippable(todirect(n)) -end - -function node.make_extensible(...) - local n = make_extensible(...) - return n and tonode(n) or nil -end - -local last_node = direct.last_node - -function node.last_node() - local n = last_node() - return n and tonode(n) or nil -end - -local is_zero_glue = direct.is_zero_glue -local getglue = direct.getglue -local setglue = direct.setglue - -function node.is_zero_glue(n) - return is_zero_glue(todirect(n)) -end - -function node.get_glue(n) - return get_glue(todirect(n)) -end - -function node.set_glue(n) - return set_glue(todirect(n)) -end - -node.family_font = tex.getfontoffamily diff --git a/tex/context/base/mkiv/node-fin.mkxl b/tex/context/base/mkiv/node-fin.mkxl deleted file mode 100644 index 183e02429..000000000 --- a/tex/context/base/mkiv/node-fin.mkxl +++ /dev/null @@ -1,78 +0,0 @@ -%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} - -\unprotect - -\registerctxluafile{node-shp}{optimize} -% \registerctxluafile{node-fin}{autosuffix,optimize} % we might generalize this one -\registerctxluafile{node-fin}{optimize} % we might generalize this one - -\permanent\protected\def\finalizeobjectbox #1{\clf_finalizebox#1\relax} -\permanent\protected\def\finalizeshipoutbox#1{\clf_finalizebox#1\relax} - -% Experimental (for Aditya): - -\permanent\protected\def\cleanupbox#1{\clf_cleanupbox#1\relax} - -% Tricky stuff: this might become obsolete. It is about time to check this out -% now (after more than a decade)! The few times that we need this we can better -% copy some of the sensitive attributes (mostly color). - -\definesystemattribute[trigger][public] - -\newcount\c_syst_attr_trigger - -\permanent\edef\startinheritattributes{\c_attr_trigger\plusone} -\permanent\edef\stopinheritattributes {\c_attr_trigger\attributeunsetvalue} - -\permanent\def\syst_attr_trigger_copy_yes{\afterassignment\syst_attr_trigger_copy_indeed\c_syst_attr_trigger} -\permanent\def\syst_attr_trigger_dump_yes{\afterassignment\syst_attr_trigger_dump_indeed\c_syst_attr_trigger} - -\def\syst_attr_trigger_copy_indeed - {\ifvbox\c_syst_attr_trigger - \vpack attr \triggerattribute \plusone {\unvcopy\c_syst_attr_trigger}% - \else - \hpack attr \triggerattribute \plusone {\unhcopy\c_syst_attr_trigger}% - \fi} - -\def\syst_attr_trigger_dump_indeed - {\ifvbox\c_syst_attr_trigger - \vpack attr \triggerattribute \plusone {\unvbox\c_syst_attr_trigger}% - \else - \hpack attr \triggerattribute \plusone {\unhbox\c_syst_attr_trigger}% - \fi} - -\permanent\protected\def\enableattributeinheritance - {\clf_enablestatetriggering - \enforced\let\attributedcopy\syst_attr_trigger_copy_yes - \enforced\let\attributedbox \syst_attr_trigger_dump_yes} - -\permanent\protected\def\disableattributeinheritance - {\clf_disablestatetriggering - \enforced\let\attributedcopy\copy - \enforced\let\attributedbox \box} - -\disableattributeinheritance - -\installtexdirective - {attributes.inheritance} - {\enableattributeinheritance} - {\disableattributeinheritance} - -% \appendtoks -% \enableattributeinheritance % might become default -% \to\everyjob - -\protect \endinput diff --git a/tex/context/base/mkiv/node-gcm.lmt b/tex/context/base/mkiv/node-gcm.lmt deleted file mode 100644 index 8b09fb82b..000000000 --- a/tex/context/base/mkiv/node-gcm.lmt +++ /dev/null @@ -1,112 +0,0 @@ -if not modules then modules = { } end modules ['node-gmc'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, tostring = type, tostring - -local nodes = nodes -local ligature_code = nodes.glyphcodes.ligature -local nuts = nodes.nuts - -local getnext = nuts.getnext -local getsubtype = nuts.getsubtype -local copy_node = nuts.copy -local flush_list = nuts.flush_list -local count = nuts.count -local isglyph = nuts.isglyph -local getprop = nuts.getprop -local setprop = nuts.setprop - -local fastcopy = table.fastcopy - -local report_error = logs.reporter("node-aux:error") - -local function set_components(base,list) - local t = { } - local n = 0 - local l = list - while list do - local char = isglyph(list) - if char then - n = n + 1 - t[n] = char - end - list = getnext(list) - end - -- was forgotten: - flush_list(l) - -- - setprop(base,"components",n > 0 and t or false) -end - -local function get_components(base) - return getprop(base,"components") -end - -local function copy_no_components(base) - local copy = copy_node(base) - setprop(copy,"components",false) -- no metatable lookup! - return copy -end - -local function copy_only_glyphs(base) - local t = getprop(base,"components") -- also metatable - if t then - return fastcopy(t) - end -end - -local function do_count(t,marks) - local n = 0 - if t then - for i=1,#t do - local c = t[i] - if type(c) == "table" then - n = n + do_count(t,marks) - elseif not marks[c] then - n = n + 1 - else - --marks don't count - end - end - end - return n -end - --- start is a mark and we need to keep that one - -local done = false - -local function count_components(base,marks) - local char = isglyph(base) - if char then - if getsubtype(base) == ligature_code then - if not done then - logs.report("fonts","!") - logs.report("fonts","! check count_components with mkiv !") - logs.report("fonts","!") - done = true - end - local t = getprop(base,"components") - if t then - return do_count(t,marks) - end - elseif not marks[char] then - return 1 - end - end - return 0 -end - -nuts.set_components = set_components -nuts.get_components = get_components -nuts.copy_only_glyphs = copy_only_glyphs -nuts.copy_no_components = copy_no_components -nuts.count_components = count_components - -nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end -nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end diff --git a/tex/context/base/mkiv/node-ini.lmt b/tex/context/base/mkiv/node-ini.lmt deleted file mode 100644 index 5cce9030d..000000000 --- a/tex/context/base/mkiv/node-ini.lmt +++ /dev/null @@ -1,280 +0,0 @@ -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-- -

Most of the code that had accumulated here is now separated in modules.

---ldx]]-- - -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-- -

Access to nodes is what gives its power. Here we implement a -few helper functions. These functions are rather optimized.

---ldx]]-- - -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 getvalues = node.values - -tex.magicconstants = { -- we use tex.constants for something else - running = -1073741824, -- null_flag - maxdimen = 1073741823, -- max_dimen - trueinch = 4736286, -} - -local listcodes = mark(getsubtypes("list")) -local rulecodes = mark(getsubtypes("rule")) -local dircodes = mark(getsubtypes("dir")) -local glyphcodes = mark(getsubtypes("glyph")) -local disccodes = mark(getsubtypes("disc")) -local gluecodes = mark(getsubtypes("glue")) -local boundarycodes = mark(getsubtypes("boundary")) -local penaltycodes = mark(getsubtypes("penalty")) -local kerncodes = mark(getsubtypes("kern")) -local mathcodes = mark(getsubtypes("math")) -local noadcodes = mark(getsubtypes("noad")) -local radicalcodes = mark(getsubtypes("radical")) -local accentcodes = mark(getsubtypes("accent")) -local fencecodes = mark(getsubtypes("fence")) ------ fractioncodes = mark(getsubtypes("fraction")) -local parcodes = mark(getsubtypes("par")) - -local fillvalues = mark(getvalues("fill")) -local dirvalues = mark(getvalues("dir")) - -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 = allocate { - literal = 0x1, [0x1] = "literal", - latelua = 0x2, [0x2] = "latelua", - userdefined = 0x3, [0x3] = "userdefined", - savepos = 0x4, [0x4] = "savepos", - save = 0x5, [0x5] = "save", - restore = 0x6, [0x6] = "restore", - setmatrix = 0x7, [0x7] = "setmatrix", - open = 0x8, [0x8] = "open", - close = 0x9, [0x9] = "close", - write = 0xA, [0xA] = "write", -} - -local usercodes = allocate { - [ 97] = "attribute", -- a - [100] = "number", -- d - [102] = "float", -- f - [108] = "lua", -- l - [110] = "node", -- n - [115] = "string", -- s - [116] = "token" -- t -} - -local noadoptions = allocate { - set = 0x08, - unused_1 = 0x00 + 0x08, - unused_2 = 0x01 + 0x08, - axis = 0x02 + 0x08, - no_axis = 0x04 + 0x08, - exact = 0x10 + 0x08, - left = 0x11 + 0x08, - middle = 0x12 + 0x08, - right = 0x14 + 0x08, -} - -local literalvalues = allocate { - [0] = "origin", - [1] = "page", - [2] = "always", - [3] = "raw", - [4] = "text", - [5] = "font", - [6] = "special", -} - -gluecodes = allocate(swapped(gluecodes,gluecodes)) -dircodes = allocate(swapped(dircodes,dircodes)) -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)) -disccodes = allocate(swapped(disccodes,disccodes)) -accentcodes = allocate(swapped(accentcodes,accentcodes)) -fencecodes = allocate(swapped(fencecodes,fencecodes)) -parcodes = allocate(swapped(parcodes,parcodes)) -rulecodes = allocate(swapped(rulecodes,rulecodes)) -usercodes = allocate(swapped(usercodes,usercodes)) -noadoptions = allocate(swapped(noadoptions,noadoptions)) - -dirvalues = allocate(swapped(dirvalues,dirvalues)) -literalvalues = allocate(swapped(literalvalues,literalvalues)) -fillvalues = allocate(swapped(fillvalues,fillvalues)) - -nodes.gluecodes = gluecodes -nodes.dircodes = dircodes -nodes.boundarycodes = boundarycodes -nodes.noadcodes = noadcodes -nodes.whatcodes = whatcodes -nodes.listcodes = listcodes -nodes.glyphcodes = glyphcodes -nodes.kerncodes = kerncodes -nodes.penaltycodes = penaltycodes -nodes.mathcodes = mathcodes -nodes.disccodes = disccodes -nodes.accentcodes = accentcodes -nodes.radicalcodes = radicalcodes -nodes.fencecodes = fencecodes -nodes.parcodes = parcodes -nodes.rulecodes = rulecodes -nodes.usercodes = usercodes - -nodes.noadoptions = noadoptions -nodes.fillvalues = fillvalues -nodes.fillcodes = fillvalues -- for now -nodes.dirvalues = dirvalues -nodes.literalvalues = literalvalues - -nodes.nodecodes = nodecodes - --- local subtypes = allocate { --- [nodecodes.glue] = gluecodes, --- [nodecodes.dir] = dircodes, --- [nodecodes.boundary] = boundarycodes, --- [nodecodes.noad] = noadcodes, --- [nodecodes.whatsit] = whatcodes, --- [nodecodes.glyph] = glyphcodes, --- [nodecodes.kern] = kerncodes, --- [nodecodes.penalty] = penaltycodes, --- [nodecodes.math] = mathcodes, --- [nodecodes.disc] = disccodes, --- [nodecodes.accent] = accentcodes, --- [nodecodes.radical] = radicalcodes, --- [nodecodes.fence] = fencecodes, --- [nodecodes.par] = parcodes, --- [nodecodes.rule] = rulecodes, - --- [nodecodes.vlist] = listcodes, --- [nodecodes.hlist] = listcodes, - --- -- [nodecodes.list] = listcodes, - --- -- [nodecodes.parameter] = parametercodes, --- -- [nodecodes.user] = usercodes, --- } - --- for k in next, table.sortedkeys(subtypes) do --- local v = nodecodes[k] --- print(k,v) --- if k and subtypes[k] then --- subtypes[v] = subtypes[k] --- end --- end - -local subtypes = allocate { - glue = gluecodes, - dir = dircodes, - boundary = boundarycodes, - noad = noadcodes, - whatsit = whatcodes, - glyph = glyphcodes, - kern = kerncodes, - penalty = penaltycodes, - math = mathcodes, - disc = disccodes, - accent = accentcodes, - radical = radicalcodes, - fence = fencecodes, - par = parcodes, - rule = rulecodes, - - vlist = listcodes, - hlist = listcodes, - - -- list = listcodes, - - -- parameter = parametercodes, - -- user = usercodes, -} - -for k, v in table.sortedhash(subtypes) do - local i = nodecodes[k] - if i and not subtypes[i] then - subtypes[i] = v - end -end - -nodes.subtypes = subtypes - --- a few more friendly aliases: - -nodes.skipcodes = gluecodes -nodes.directioncodes = dircodes -nodes.whatsitcodes = whatcodes -nodes.discretionarycodes = disccodes - -nodes.directionvalues = dirvalues -nodes.literalvalues = literalvalues - -glyphcodes.glyph = glyphcodes.character - -gluecodes.parfillrightskip = gluecodes.parfillrightskip or gluecodes.parfillskip -gluecodes.parfillskip = gluecodes.parfillskip or gluecodes.parfillrightskip - -listcodes.row = listcodes.alignment -listcodes.column = listcodes.alignment - -kerncodes.kerning = kerncodes.fontkern -kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new - -literalvalues.direct = literalvalues.always - -nodes.noadoptions = { - set = 0x08, - unused_1 = 0x00 + 0x08, - unused_2 = 0x01 + 0x08, - axis = 0x02 + 0x08, - no_axis = 0x04 + 0x08, - exact = 0x10 + 0x08, - left = 0x11 + 0x08, - middle = 0x12 + 0x08, - right = 0x14 + 0x08, -} - --- We use the real node code numbers. - -local texsetintegervalue = tex.setintegervalue - -for i=0,nodecodes.glyph do - texsetintegervalue(nodecodes[i] .. "nodecode",i,"immutable") -end -for i=0,#gluecodes do - texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable") -end - --- tex.set("internalcodesmode",1) -- obsolete diff --git a/tex/context/base/mkiv/node-ini.mkxl b/tex/context/base/mkiv/node-ini.mkxl deleted file mode 100644 index 4cb322448..000000000 --- a/tex/context/base/mkiv/node-ini.mkxl +++ /dev/null @@ -1,56 +0,0 @@ -%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-cmp}{autosuffix} -\registerctxluafile{node-ini}{autosuffix} -\registerctxluafile{node-met}{} -\registerctxluafile{node-nut}{autosuffix} -\registerctxluafile{node-res}{} -%registerctxluafile{node-ppt}{} % experimental, not used so probably useless -\registerctxluafile{node-aux}{autosuffix} -\registerctxluafile{node-gcm}{autosuffix} -\registerctxluafile{node-tst}{} -\registerctxluafile{node-tra}{} % we might split it off (module) -\registerctxluafile{node-snp}{autosuffix} -\registerctxluafile{node-tsk}{} -\registerctxluafile{node-tex}{autosuffix} -\registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used -\registerctxluafile{node-pro}{} -\registerctxluafile{node-ser}{autosuffix} -\registerctxluafile{node-ext}{} -\registerctxluafile{node-acc}{} % experimental -%registerctxluafile{node-prp}{} % makes no sense (yet) -\registerctxluafile{node-scn}{} -\registerctxluafile{node-syn}{} -\registerctxluafile{node-par}{autosuffix} - -%D This might go away (needs checking anyway, very old code): - -\newcount\c_node_tracers_show_box % box number - -\permanent\protected\def\shownextnodes{\afterassignment\node_tracers_show_next\c_node_tracers_show_box} -\permanent\protected\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))}} - -\permanent\protected\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}} -\permanent\protected\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/node-mig.lmt b/tex/context/base/mkiv/node-mig.lmt deleted file mode 100644 index c19913509..000000000 --- a/tex/context/base/mkiv/node-mig.lmt +++ /dev/null @@ -1,134 +0,0 @@ -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 nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getlist = nuts.getlist -local getpost = nuts.getpost -local getprop = nuts.getprop - -local setprop = nuts.setprop -local setlink = nuts.setlink -local setlist = nuts.setlist -local setpost = nuts.setpost - -local count = nuts.count -local migrate = nuts.migrate - -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 = false -local migrate_marks = false -local t_inserts = 0 -local t_marks = 0 -local t_sweeps = 0 - -local trialtypesetting = context.trialtypesetting - -function nodes.handlers.migrate(head,where) - if head and not trialtypesetting() and where == "alignment" then - if trace_migrations then - report_nodes("migration sweep %a",where) - end - local current = head - while current do - local id = getid(current) - if (id == vlist_code or id == hlist_code or id == insert_code) and not getprop(current,"migrated") then - setprop(current,"migrated",true) - local list = getlist(current) - if list then - t_sweeps = t_sweeps + 1 - local h, first, last = migrate(list,migrate_inserts,migrate_marks) - if first then - if trace_migrations then - local ni = count(insert_code,first) - local nm = count(mark_code,first) - t_inserts = t_inserts + ni - t_marks = t_marks + nm - report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a", - t_sweeps,nodecodes[id],ni,nm,where) - - end - local p, t = getpost(current) - if p then - setlink(t,first) - else - setpost(current,first) - end - end - end - end - current = getnext(current) - end - end - return head -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) - --- Since we started with mkiv we had it as experiment but it is about time --- to have a more formal interface .. it's still optional due to possible --- side effects. - -local enableaction = nodes.tasks.enableaction -local disableaction = nodes.tasks.disableaction -local texsetcount = tex.setcount - -local migrations = { } -nodes.migrations = migrations -local enabled = false - -local function check() - if migrate_marks or migrate_inserts then - if not enabled then - enableaction("mvlbuilders", "nodes.handlers.migrate") - enabled = true - texsetcount("automigrationmode",3) - end - else - if enabled then - disableaction("mvlbuilders", "nodes.handlers.migrate") - enabled = false - texsetcount("automigrationmode",0) - end - end -end - -function migrations.setmarks(v) - migrate_marks = v - check() -end - -function migrations.setinserts(v) - migrate_inserts = v - check() -end diff --git a/tex/context/base/mkiv/node-mig.mkxl b/tex/context/base/mkiv/node-mig.mkxl deleted file mode 100644 index 420140e6f..000000000 --- a/tex/context/base/mkiv/node-mig.mkxl +++ /dev/null @@ -1,44 +0,0 @@ -%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 \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}{autosuffix} - -\aliased\let\automigrateinserts\donothing -\aliased\let\automigratemarks \donothing - -\protect diff --git a/tex/context/base/mkiv/node-nut.lmt b/tex/context/base/mkiv/node-nut.lmt deleted file mode 100644 index 6b9dd803e..000000000 --- a/tex/context/base/mkiv/node-nut.lmt +++ /dev/null @@ -1,579 +0,0 @@ -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" -} - --- Some comments anbout going nuts can be found in the mkiv file with the --- suffix "lua", including some timing and musings. We copy the direct table --- (1) because that's what we did while things evolved and (2) because we --- also add some more helpers. - -local type, rawget = type, rawget - -local nodes = nodes -local direct = node.direct - -local fastcopy = table.fastcopy - -local nodecodes = nodes.nodecodes -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph - -local tonode = direct.tonode -local tonut = direct.todirect - -local is_node = direct.is_node -local is_nut = direct.is_direct - -local d_remove_node = direct.remove -local d_flush_node = direct.flush_node -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 -local d_traverse = direct.traverse -local d_setlink = direct.setlink -local d_getboth = direct.getboth - -local nuts = { - check_discretionaries = direct.check_discretionaries, - copy = direct.copy, - copy_list = direct.copy_list, - copy_node = direct.copy, - copy_only = direct.copy_only or direct.copy, - count = direct.count, - current_attributes = direct.current_attributes, - delete = direct.delete, - dimensions = direct.dimensions, - effective_glue = direct.effective_glue, - end_of_math = direct.end_of_math, - exchange = direct.exchange, - find_attribute = direct.find_attribute, - first_glyph = direct.first_glyph, - flatten_discretionaries = direct.flatten_discretionaries, - flush = d_flush_node, - flush_components = direct.flush_components, - flush_list = direct.flush_list, - flush_node = direct.flush_node, - free = direct.free, - getsynctexfields = direct.get_synctex_fields, - getattr = direct.get_attribute, - getattrs = direct.get_attributes, - getattributelist = direct.getattributelist, - getattrlist = direct.getattributelist, - getboth = d_getboth, - getbox = direct.getbox, - getboxglue = direct.getglue, - getchar = direct.getchar, - getcomponents = direct.getcomponents, - getdata = direct.getdata, - getdepth = direct.getdepth, - getdir = direct.getdir, - getdirection = direct.getdirection, - getdisc = direct.getdisc, - getdiscretionary = direct.getdisc, - getexpansion = direct.getexpansion, - getfam = direct.getfam, - getfield = direct.getfield, - getfont = direct.getfont, - getglue = direct.getglue, - getglyphdata = direct.getglyphdata, - getheight = direct.getheight, - getid = d_getid, - getkern = direct.getkern, - getlang = direct.getlanguage,-- will become obsolete - getlanguage = direct.getlanguage, - getleader = direct.getleader, - getlist = d_getlist, - getnext = d_getnext, - getnormalizedline = direct.getnormalizedline, - getnucleus = direct.getnucleus, - getoffsets = direct.getoffsets, - getorientation = direct.getorientation, - getoptions = direct.getoptions, - getpenalty = direct.getpenalty, - getpost = direct.getpost, - getpre = direct.getpre, - getprev = d_getprev, - getreplace = direct.getreplace, - getruledata = direct.getdata, -- obsolete when we have the split - getscript = direct.setscript, - getshift = direct.getshift, - getstate = direct.getstate, - getsub = direct.getsub, - getsubpre = direct.getsubpre, - getsubtype = direct.getsubtype, - getsup = direct.getsup, - getsuppre = direct.getsuppre, - getsurround = direct.getkern, - gettotal = direct.gettotal, - getvalue = direct.getdata, -- obsolete - getwhd = direct.getwhd, - getwidth = direct.getwidth, - has_attribute = direct.has_attribute, - has_dimensions = direct.has_dimensions, - has_field = direct.has_field, - has_glyph = direct.has_glyph or direct.first_glyph, - hpack = direct.hpack, - hyphenating = direct.hyphenating, - insert_after = d_insert_after, - insert_before = d_insert_before, - is_direct = is_direct, - is_node = is_node, - is_nut = direct.is_direct, - is_zero_glue = direct.is_zero_glue, - ischar = direct.is_char, - isglyph = direct.is_glyph, - kerning = direct.kerning, - last_node = direct.last_node, - length = direct.length, - ligaturing = direct.ligaturing, - migrate = direct.migrate, - mlist_to_hlist = direct.mlist_to_hlist, - new = direct.new, - protect_glyph = direct.protect_glyph, - protect_glyphs = direct.protect_glyphs, - protrusion_skippable = direct.protrusion_skippable, - rangedimensions = direct.rangedimensions, - getglyphdimensions = direct.getglyphdimensions, - getkerndimension = direct.getkerndimension, - remove = d_remove_node, - reverse = direct.reverse, - set_attribute = direct.set_attribute, - setattr = direct.set_attribute, - setattrs = direct.set_attributes, - setattributelist = direct.setattributelist, - setattrlist = direct.setattributelist, - setboth = direct.setboth, - setbox = direct.setbox, - setboxglue = direct.setglue, - setchar = direct.setchar, - setcomponents = direct.setcomponents, - setdata = direct.setdata, - setdepth = direct.setdepth, - setdir = direct.setdir, - setdirection = direct.setdirection, - setdisc = direct.setdisc, - setdiscretionary = direct.setdisc, - setexpansion = direct.setexpansion, - setfam = direct.setfam, - setfield = direct.setfield, - setfont = direct.setfont, - setglue = direct.setglue, - setglyphdata = direct.setglyphdata, - setheight = direct.setheight, - setkern = direct.setkern, - setlang = direct.setlanguage, - setlanguage = direct.setlanguage, - setleader = direct.setleader, - setlink = d_setlink, - setlist = direct.setlist, - setnext = direct.setnext, - setnucleus = direct.setnucleus, - setoffsets = direct.setoffsets, - setorientation = direct.setorientation, - setoptions = direct.setoptions, - setpenalty = direct.setpenalty, - setpost = direct.setpost, - setpre = direct.setpre, - setprev = direct.setprev, - setreplace = direct.setreplace, - setruledata = direct.setdata, -- obsolete when we have the split - setscript = direct.getscript, - setshift = direct.setshift, - setsplit = direct.setsplit, - setstate = direct.setstate, - setsub = direct.setsub, - setsubpre = direct.setsubpre, - setsubtype = direct.setsubtype, - setsup = direct.setsup, - setsuppre = direct.setsuppre, - setsurround = direct.setkern, - setsynctexfields = direct.set_synctex_fields, - setvalue = direct.setdata, -- obsolete - setwhd = direct.setwhd, - setwidth = direct.setwidth, - slide = d_slide, - start_of_par = direct.start_of_par, - tail = d_find_tail, - takeattr = direct.unset_attribute, -- ? - tonode = tonode, - tonut = tonut, - tostring = direct.tostring, - traverse = d_traverse, - traverse_char = direct.traverse_char, - traverse_glyph = direct.traverse_glyph, - traverse_id = direct.traverse_id, - traverse_list = direct.traverse_list, - traverse_content = direct.traverse_content, - unprotect_glyph = direct.unprotect_glyph, - unprotect_glyphs = direct.unprotect_glyphs, - unset_attribute = direct.unset_attribute, - usedlist = direct.usedlist, - uses_font = direct.uses_font, - vpack = direct.vpack, - writable_spec = direct.writable_spec, - write = direct.write, - append = direct.append, -} - -nodes.nuts = nuts - -nodes.is_node = is_node -nodes.is_direct = is_nut -nodes.is_nut = is_nut - -nodes.tonode = tonode -nodes.tonut = tonut - -function nuts.delete(head,current) - return d_remove_node(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 prev or next then - d_setlink(prev,new,next) - end - if head then - if head == current then - head = new - end - d_flush_node(current) - return head, new - else - d_flush_node(current) - return new - end -end - -local function countall(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 + countall(list) -- self counts too - else - n = n + 1 - end - else - n = n + 1 - end - stack = d_getnext(stack) - end - return n -end - -nuts.countall = countall - -function nodes.countall(stack,flat) - return countall(tonut(stack),flat) -end - -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(...) -- slides ! - 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 "" -end - -function nuts.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end -function nuts.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end - -nodes.vianuts = nuts.vianuts -nodes.vianodes = nuts.vianodes - -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_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 - --- this might move - -local propertydata = direct.get_properties_table(true) - -local getattr = nuts.getattr -local setattr = nuts.setattr - -nodes.properties = { - data = propertydata, -} - --- experimental code with respect to copying attributes has been removed --- as it doesn't pay of (most attributes are only accessed once anyway) - -function nuts.getprop(n,k) - local p = propertydata[n] - if p then - if k then - return p[k] - else - return p - end - end -end - -function nuts.rawprop(n,k) - local p = rawget(propertydata,n) - if p then - if k then - return p[k] - else - return p - end - end -end - -function nuts.setprop(n,k,v) - local p = propertydata[n] - if p then - p[k] = v - else - propertydata[n] = { [k] = v } - end -end - -function nuts.theprop(n) - local p = propertydata[n] - if not p then - p = { } - propertydata[n] = p - end - return p -end - - -function nuts.isdone(n,k) - local p = propertydata[n] - if not p then - propertydata[n] = { [k] = true } - return false - end - local v = p[k] - if v == nil then - propertydata[n] = { [k] = true } - return false - end - return v -end - -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 diff --git a/tex/context/base/mkiv/node-par.lmt b/tex/context/base/mkiv/node-par.lmt deleted file mode 100644 index af3125d23..000000000 --- a/tex/context/base/mkiv/node-par.lmt +++ /dev/null @@ -1,48 +0,0 @@ -if not modules then modules = { } end modules ['node-par'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local sequencers = utilities.sequencers - --- This are called a lot! - -local actions = nodes.tasks.actions("everypar") - -local function everypar(head) - starttiming(builders) - head = actions(head) - stoptiming(builders) - return head -end - -callbacks.register("insert_par",everypar,"after paragraph start") - -local actions = sequencers.new { - name = "paragraph", - arguments = "mode,indented", - returnvalues = "indented", - results = "indented", -} - -sequencers.appendgroup(actions,"before") -- user -sequencers.appendgroup(actions,"system") -- private -sequencers.appendgroup(actions,"after" ) -- user - -local function paragraph(mode,indented) - local runner = actions.runner - if runner then - starttiming(builders) - indented = runner(mode,indented) - stoptiming(builders) - end - return indented -end - -callbacks.register("begin_paragraph",paragraph,"before paragraph start") diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua index e0bd35f6b..098ed50c2 100644 --- a/tex/context/base/mkiv/node-ref.lua +++ b/tex/context/base/mkiv/node-ref.lua @@ -429,9 +429,14 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx else if id == glue_code then local subtype = getsubtype(current) + -- todo in lmtx: lefthangskip and righthangskip if subtype == leftskip_code or subtype == parfillleftskip_code then goto NEXT elseif subtype == rightskip_code or subtype == parfillskip_code then + if reference and (done[reference] or 0) == 0 then + head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) + reference, first, last, firstdir = nil, nil, nil, nil + end goto NEXT end end diff --git a/tex/context/base/mkiv/node-rul.mkxl b/tex/context/base/mkiv/node-rul.mkxl deleted file mode 100644 index 3697e92ef..000000000 --- a/tex/context/base/mkiv/node-rul.mkxl +++ /dev/null @@ -1,618 +0,0 @@ -%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 formal definitions are: -%D -%D \showsetup{underbar} -%D \showsetup{underbars} -%D \showsetup{overbar} -%D \showsetup{overbars} -%D \showsetup{overstrike} -%D \showsetup{overstrikes} -%D -%D \showsetup{setupbars} -%D -%D Units can be any normal \TEX\ unit: -%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}{optimize} - -\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 - -\aliased\let\setupbars\setupbar - -\appendtoks - \ifsecondargument - \node_rules_define - \else - \the\t_node_rules_checklist - \fi -\to \everysetupbar - -\appendtoks - \ifcsname\??barindex\currentbar\endcsname - \lastnamedcs\zerocount - \else - \expandafter\newcount\csname\??barindex\currentbar\endcsname - \fi - % \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}% - \normalexpanded{\t_node_rules_checklist{\the\t_node_rules_checklist\relax\node_rules_redefine{\currentbar}}}% - % \etoksapp\t_node_rules_checklist{\node_rules_redefine{\currentbar}}% - \node_rules_define - \frozen\instance\setuevalue\currentbar{\node_rules_direct{\currentbar}}% -\to \everydefinebar - -\newbox\b_node_rules - -\protected\def\node_rules_define - {\edef\p_node_rules_color{\barparameter\c!color}% - \edef\p_node_text{\barparameter\c!text}% - \ifx\p_node_text\empty\else - \setbox\b_node_rules\hbox{\p_node_text}% - \fi - \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 - empty {\barparameter\c!empty}% - \ifx\p_node_text\empty\else - % not that useful and efficient, more for testing something - text \b_node_rules - repeat {\barparameter\c!repeat}% - \fi - \relax}} - -\protected\def\node_rules_redefine#1% - {\def\currentbar{#1}\node_rules_define} - -\protected\def\node_rules_direct#1% - {\groupedcommand - {\node_rules_set{#1}\barparameter\c!left}% - {\relax\barparameter\c!right}} - -\permanent\protected\def\inlinebar[#1]% - {\node_rules_direct{#1}} - -% \protected\def\inlinecurrentbar -% {\node_rules_direct{\currentbar}} - -% store in properties - -\permanent\protected\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 - % maybe: \usebarstyleandcolor\c!textgroundstyle\c!textcolor - % 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 - \c_attr_ruled\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} - -\permanent\protected\def\resetbar - {\c_attr_ruled\attributeunsetvalue} - -\permanent\protected\def\nobar - {\groupedcommand - {\resetbar\barparameter\c!left}% - {\relax\barparameter\c!right}} - -\permanent\protected\def\startbar[#1]% - {\begingroup - \node_rules_set{#1}% - \ignorespaces - \barparameter\c!left} - -\permanent\protected\def\stopbar - {\removeunwantedspaces - \barparameter\c!right - \endgroup} - -\permanent\protected\def\setbar[#1]% - {\node_rules_set{#1}} - -\aliased\let\directsetbar\node_rules_set - -% ungrouped - -\newcount\c_node_rules_nesting % todo: same as colors - -\permanent\protected\def\pushbar[#1]% - {\global\advance\c_node_rules_nesting\plusone - \expandafter\edef\csname\??barstack\number\c_node_rules_nesting\endcsname{\c_attr_ruled\the\c_attr_ruled}% - \node_rules_set{#1}} - -\permanent\protected\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!empty=, % new: yes = hide text - \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] - -\pushoverloadmode - -\aliased\let\normalmathoverbar \overbar -\aliased\let\normalmathunderbar \underbar -\aliased\let\normalmathoverstrike \overstrike -\aliased\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] - -\definebar - [\v!hiddenbar] - [\v!underbar] - [\c!continue=\v!yes, - \c!empty=\v!yes, - \c!left=\zwj, - \c!right=\zwj] - -% \setupbar[\v!overstrike][continue=all] - -% we want these always so ... - -\ifdefined\normalmathunderbar - \enforced\permanent\expandafter\let\expandafter\normaltextunderbar\csname\v!underbar\endcsname - \enforced\permanent\protected\def\underbar{\mathortext\normalmathunderbar\normaltextunderbar} -\else - \enforced\permanent\expandafter\let\expandafter\underbar\csname\v!underbar\endcsname -\fi - -\ifdefined\normalmathoverbar - \enforced\permanent\expandafter\let\expandafter\normaltextoverbar\csname\v!overbar\endcsname - \enforced\permanent\protected\def\overbar{\mathortext\normalmathoverbar\normaltextoverbar} -\else - \enforced\permanent\expandafter\let\expandafter\overbar\csname\v!overbar\endcsname -\fi - -\ifdefined\normalmathunderstrike - \enforced\permanent\expandafter\let\expandafter\normaltextunderstrike\csname\v!understrike\endcsname - \enforced\permanent\protected\def\understrike{\mathortext\normalmathunderstrike\normaltextunderstrike} -\else - \enforced\permanent\expandafter\let\expandafter\understrike\csname\v!understrike\endcsname -\fi - -\ifdefined\normalmathoverstrike - \enforced\permanent\expandafter\let\expandafter\normaltextoverstrike\csname\v!overstrike\endcsname - \enforced\permanent\protected\def\overstrike{\mathortext\normalmathoverstrike \normaltextoverstrike} -\else - \enforced\permanent\expandafter\let\expandafter\overstrike\csname\v!overstrike\endcsname -\fi - -\enforced\permanent\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname -\enforced\permanent\expandafter\let\expandafter\underbars \csname\v!underbars \endcsname -\enforced\permanent\expandafter\let\expandafter\overbars \csname\v!overbars \endcsname - -\enforced\permanent\protected\def\setupunderbar[#1]% too incompatible for the moment - {} - -\popoverloadmode - -%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} - path p ; p := (0,RuleDepth) -- (RuleWidth,RuleDepth) ; - numeric l ; l := arclength(p); - l := l mod RuleThickness/4; - draw - p - shifted (l,RuleFactor*RuleOffset) - dashed dashpattern(off 2RuleThickness+l on 0 off 2RuleThickness) - 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{\the\t_node_shifts_checklist\node_shifts_redefine{\currentshift}}}% order ? - \node_shifts_define - \setuevalue\currentshift{\node_shifts_direct{\currentshift}}% -\to \everydefineshift - -\protected\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}} - -\protected\def\node_shifts_redefine#1% - {\def\currentshift{#1}\node_shifts_define} - -% \protected\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 ! - -\protected\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 - \clf_enableshifts % will be relaxed - \c_attr_shifted\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}} % weird feature that i probably needed once - -\protected\def\startshift[#1]% - {\begingroup - \node_shifts_set{#1}% - \ignorespaces} - -\protected\def\stopshift - {\removeunwantedspaces - \endgroup} - -% \protected\def\node_shifts_direct#1% -% {\doisolatedgroupedalign{\node_shifts_set{#1}}\donothing} - -\protected\def\node_shifts_direct#1% - {\groupedcommand - {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}\ignorespaces} - {\removeunwantedspaces\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: - -\protected\def\dostartisolation{\signalcharacter} -\protected\def\dostopisolation {\signalcharacter} -\protected\def\doisolator {\signalcharacter} - -\protected\def\dosetupisolatedalign#1% - {\doisolator - \setupalign[#1]\relax} - -\protected\def\doisolatedgroupedalign#1#2% - {\groupedcommand - {\begingroup\dostartisolation\begingroup#1} - {#2\endgroup\dostopisolation\endgroup}} - -%D More rules. - -% The following code rocks and was written with the Toto Live in Poland bluray -% in loop mode on my 5.1 surround development setup (the Toto lineup with Simon -% Phillips on drums). The Amsterdam concert is equally energizing. - -\installcorenamespace{linefiller} -\installcorenamespace{linefillerindex} -\installcorenamespace{linefillerattribute} - -\installcommandhandler \??linefiller {linefiller} \??linefiller - -\definesystemattribute[linefiller][public] - -\newtoks\t_node_linefiller_checklist - -\let\c_node_linefiller_index\relax % temporary synonym - -\aliased\let\setuplinefillers\setuplinefiller - -\appendtoks - \ifsecondargument - \node_linefiller_define - \else - \the\t_node_linefiller_checklist - \fi -\to \everysetuplinefiller - -\appendtoks - \ifcsname\??linefillerindex\currentlinefiller\endcsname - \lastnamedcs\zerocount - \else - \expandafter\newcount\csname\??linefillerindex\currentlinefiller\endcsname - \fi - \etoksapp\t_node_linefiller_checklist{\t_node_linefiller_checklist\node_linefiller_redefine{\currentlinefiller}}% - \node_linefiller_define -\to \everydefinelinefiller - -\protected\def\node_linefiller_define - {\edef\p_node_rules_color{\linefillerparameter\c!color}% - \setevalue{\??linefillerattribute\currentlinefiller}{\number - \clf_definelinefiller - %method \linefillerparameter\c!method - location {\linefillerparameter\c!location}% - scope {\linefillerparameter\c!scope}% - mp {\includeMPgraphic{\linefillerparameter\c!mp}}% - ma \thecolormodelattribute - ca \thecolorattribute\p_node_rules_color - ta \thetransparencyattribute\p_node_rules_color - height \dimexpr\linefillerparameter\c!height\relax - depth \dimexpr\linefillerparameter\c!depth\relax - distance \dimexpr\linefillerparameter\c!distance\relax - threshold \dimexpr\linefillerparameter\c!threshold\relax - rulethickness \dimexpr\linefillerparameter\c!rulethickness\relax - \relax}} - -\protected\def\node_linefiller_redefine#1% - {\def\currentlinefiller{#1}\node_linefiller_define} - -\protected\def\node_linefiller_set#1% todo: check parent ! todo: move attr etc to lua - {\def\currentlinefiller{#1}% - \expandafter\let\expandafter\c_node_linefiller_index\csname\??linefillerindex#1\endcsname - \advance\c_node_linefiller_index\plusone - \clf_enablelinefillers - \c_attr_linefiller\numexpr - \plusthousand*\c_node_linefiller_index - +\csname\??linefillerattribute#1\ifcsname\??linefiller#1:\number\c_node_linefiller_index\s!parent\endcsname:\number\c_node_linefiller_index\fi\endcsname - \relax} - -\permanent\tolerant\protected\def\startlinefiller[#1]#*[#2]% - {\begingroup - \par - \def\currentlinefiller{#1}% - \ifargument#1\or - % we need to update settings - \setuplinefiller[#1][#2]% no \setupcurrentlinefiller as we need to update settings - \fi - \node_linefiller_set{#1}% - \linefillerparameter\c!before - \usealignparameter\linefillerparameter - \uselinefillerstyleandcolor\c!textstyle\c!textcolor} % bars have foregroundcolor - -\permanent\protected\def\stoplinefiller - {\par - \linefillerparameter\c!after - \endgroup} - -\permanent\protected\def\setlinefiller[#1]% - {\node_linefiller_set{#1}} - -\setuplinefillers - [%c!method=0, - %c!mp=, - \c!location=\v!both, - \c!scope=\v!local, - \c!distance=\zeropoint, - \c!threshold=\zeropoint, - \c!rulethickness=\linewidth, - \c!height=\linewidth, - \c!depth=\zeropoint, - %\c!textcolor=, - %\c!textstyle=, - %\c!align=, - %\c!before=, - %\c!after=, - \c!color=] - -\definelinefiller - [filler] - [\c!height=.75\exheight, - %\c!mp=rules:filler:demo, - %\c!threshold=.25\emwidth, - \c!distance=.25\emwidth, - \c!rulethickness=.25\exheight] - -%D Bonus: -%D -%D \starttyping -%D \startuseMPgraphic{foo} -%D fill unitsquare -%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) -%D shifted (-ExHeight/8,ExHeight/16) -%D withcolor RuleColor ; -%D \stopuseMPgraphic -%D -%D \definelinefiller[foo][mp=foo,color=darkred] -%D -%D \linefillerhbox[foo]{OEPS} -%D \stoptyping - -\protected\def\node_backgrounds_filler_box#1#2[#3]% - {\bgroup - \clf_enablebackgroundboxes - \dowithnextbox{% - \node_linefiller_set{#3}% already sets the attribute - #1% - attr \backgroundattribute \plusone - % attr \linefillerattribute \the\c_attr_linefiller - {\box\nextbox}% - \egroup}% - #2} - -\permanent\protected\def\linefillerhbox{\node_backgrounds_filler_box\hpack\hbox} -\permanent\protected\def\linefillervbox{\node_backgrounds_filler_box\vpack\vbox} -\permanent\protected\def\linefillervtop{\node_backgrounds_filler_box\tpack\vtop} - -%D Bonus: - -\permanent\protected\def\autorule{\clf_autorule} % todo: public implementor - -\protect \endinput diff --git a/tex/context/base/mkiv/node-ser.lmt b/tex/context/base/mkiv/node-ser.lmt deleted file mode 100644 index 0d7f3ccad..000000000 --- a/tex/context/base/mkiv/node-ser.lmt +++ /dev/null @@ -1,285 +0,0 @@ -if not modules then modules = { } end modules ['node-ser'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, tostring = type, tostring -local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize -local formatters, format, rep = string.formatters, string.format, string.rep - -local allocate = utilities.storage.allocate - -local context = context -local nodes = nodes -local node = node - -local getfields = node.fields - -local traverse = nodes.traverse -local is_node = nodes.is_node - -local nodecodes = nodes.nodecodes -local subtypes = nodes.subtypes - -local tonode = nodes.tonode -local tonut = nodes.tonut - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist - -local f_char = formatters["%U"] -local f_attr = formatters[""] -local f_recurse = formatters[""] - --- flat : don't use next, but indexes --- verbose : also add type - -local canbezero = { - integer = true, - dimension = true, - number = true, -} - -local canbelist = { - attribute = "", - node = "", - token = "", - attribute_list = "", - node_list = "", - token_list = "", -} - -local canbeignored = { - prev = "" -} - -local canbechar = { - char = true, - small_char = true, - large_char = true, -} - -local fieldtypes = table.setmetatableindex(function(t,k) - local v = getfields(k,true) or false - t[k] = v - return v -end) - -nodes.fieldtypes = fieldtypes - -local function astable(n) - n = tonode(n) - if n then - local fields = fieldtypes[n.id] - if fields then - local result = { } - for field, fieldtype in sortedhash(fields) do - local value = n[field] - if value then - if canbeignored[field] then - value = nil - elseif canbezero[fieldtype] and value == 0 then - value = nil - elseif canbelist[fieldtype] then - value = canbelist[fieldtype] - end - if value then - result[field] = value - end - end - end - local id = n.id - if id then - id = nodecodes[id] - result.id = id - local subtype = n.subtype - if subtype then - local subtypes = subtypes[id] - if subtypes then - result.subtype = subtypes[subtype] - end - end - end - return result - end - end -end - -nodes.astable = astable - -setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end) - -local function to_table(n,flat,verbose,noattributes,done) - local d = tonut(n) - if done[d] then - return f_recurse(d) - else - done[d] = true - local fields = fieldtypes[n.id] - if fields then - local result = { } - for field, fieldtype in sortedhash(fields) do - local value = n[field] - if value then - if fieldtype == "attribute_list" or fieldtype == "attribute" then - if noattributes then - result[value] = canbeignored[value] - else - result[value] = to_table(value,flat,verbose,noattributes,done) - end - elseif canbeignored[field] then - result[value] = canbeignored[value] - elseif not verbose and canbezero[fieldtype] and value == 0 then - value = nil - elseif canbelist[fieldtype] then - if flat then - result[value] = canbelist[value] - else - result[value] = to_table(value,flat,verbose,noattributes,done) - end - end - if value then - result[field] = value - end - end - end - if verbose then - local id = result.id - if id then - id = nodecodes[id] - result.id = id - local subtype = result.subtype - if subtype then - local subtypes = subtypes[id] - if subtypes then - result.subtype = subtypes[subtype] - end - end - end - for k, v in next, canbechar do - local v = result[k] - if v then - result[k] = f_char(v) - end - end - end - return result - end - end -end - -local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true - if n then - local d = { } - if flat then - local t, tn = { }, 0 - while n do - tn = tn + 1 - local nt = to_table(n,flat,verbose,noattributes,d) - t[tn] = nt - nt.next = nil - nt.prev = nil - n = n.next - end - done = nil - return t - else - local t = to_table(n,flat,verbose,noattributes,d) - local n = n.next - if n then - t.next = totable(n,flat,verbose,noattributes,d) - end - return t - end - else - return { } - end -end - -nodes.totable = function(n,...) return totable(tonode(n),...) end -nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list - -local function key(k) - return ((type(k) == "number") and "["..k.."]") or k -end - -function nodes.serialize(root,flat,verbose,noattributes,name) - return serialize(totable(tonode(root),flat,verbose,noattributes),name) -end - -function nodes.serializebox(n,flat,verbose,noattributes,name) - return serialize(totable(tex.box[n],flat,verbose,noattributes),name) -end - -function nodes.visualizebox(n,flat,verbose,noattributes,name) - context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name) -end - -function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway - head = tonode(head) - if not n then - context.starttyping(true) - end - while head do - local id = head.id - context(rep(" ",n or 0) .. tostring(head) .. "\n") - if id == hlist_code or id == vlist_code then - nodes.list(head.list,(n or 0)+1) - end - head = head.next - end - if not n then - context.stoptyping(true) - end -end - -function nodes.print(head,n) - head = tonode(head) - while head do - local id = head.id - logs.writer(string.formatters["%w%S"],n or 0,head) - if id == hlist_code or id == vlist_code then - nodes.print(head.list,(n or 0)+1) - end - head = head.next - end -end - --- quick hack, nicer is to have a proper expand per node type already prepared - -local function apply(n,action) - while n do - action(n) - local id = n.id - if id == hlist_code or id == vlist_code then - apply(n.list,action) - end - n = n.next - end -end - -nodes.apply = apply - -local nuts = nodes.nuts -local getid = nuts.getid -local getlist = nuts.getlist -local getnext = nuts.getnext - -local function apply(n,action) - while n do - action(n) - local id = getid(n) - if id == hlist_code or id == vlist_code then - local list = getlist(n,action) - if list then - apply(list,action) - end - end - n = getnext(n) - end -end - -nuts.apply = apply diff --git a/tex/context/base/mkiv/node-snp.lmt b/tex/context/base/mkiv/node-snp.lmt deleted file mode 100644 index 8c0237a5c..000000000 --- a/tex/context/base/mkiv/node-snp.lmt +++ /dev/null @@ -1,69 +0,0 @@ -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 status = status - -local nodeusage = nodes.pool and nodes.pool.usage -local nodestock = nodes.pool and nodes.pool.stock -local clock = os.gettimeofday or os.clock -- should go in environment -local lasttime = clock() -local samples = { } - -function snapshots.takesample(comment) - if nodeusage then - local c = clock() - samples[#samples+1] = { - nodes = nodeusage(), - stock = nodestock(), - texcallbacks = status.getcallbackstate(), - mpcallbacks = mplib.getcallbackstate(), - backendcallbacks = backends.getcallbackstate(), - luavariables = status.getluastate(), - texvariables = status.gettexstate(), - comment = comment, - variables = { - lasttime = c, - elapsed = c - lasttime, - }, - memories = { - pool = status.getpoolstate(), - hash = status.gethashstate(), - lookup = status.getlookupstate(), - node = status.getnodestate(), - token = status.gettokenstate(), - buffer = status.getbufferstate(), - input = status.getinputstate(), - file = status.getfilestate(), - nest = status.getneststate(), - parameter = status.getparameterstate(), - save = status.getsavestate(), - expand = status.getexpandstate(), - read = status.getreadstate(), - font = status.getfontstate(), - language = status.getlanguagestate(), - mark = status.getmarkstate(), - sparse = status.getsparsestate(), - }, - } - end -end - -function snapshots.getsamples() - return samples -- one return value ! -end - -function snapshots.resetsamples() - samples = { } -end diff --git a/tex/context/base/mkiv/node-tex.lmt b/tex/context/base/mkiv/node-tex.lmt deleted file mode 100644 index aae084740..000000000 --- a/tex/context/base/mkiv/node-tex.lmt +++ /dev/null @@ -1,39 +0,0 @@ -if not modules then modules = { } end modules ['node-tex'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -builders = builders or { } -local kernel = builders.kernel or { } -builders.kernel = kernel - -local nuts = nodes.nuts - -local hyphenate = language.hyphenate - -local hyphenating = nuts.hyphenating -local ligaturing = nuts.ligaturing -local kerning = nuts.kerning - -function kernel.hyphenation(head) - return (hyphenate(head)) -- nodes ! -end - -function kernel.hyphenating(head) - return (hyphenating(head)) -end - -function kernel.ligaturing(head) - return (ligaturing(head)) -end - -function kernel.kerning(head) - return (kerning(head)) -end - -callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") -callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere") -callbacks.register('kerning' , false, "normal kerning routine, called elsewhere") diff --git a/tex/context/base/mkiv/norm-ctx.mkxl b/tex/context/base/mkiv/norm-ctx.mkxl deleted file mode 100644 index 5cee04935..000000000 --- a/tex/context/base/mkiv/norm-ctx.mkxl +++ /dev/null @@ -1,87 +0,0 @@ -%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: - -\aliased\let\ordordspacing \Umathordordspacing -\aliased\let\ordopspacing \Umathordopspacing -\aliased\let\ordbinspacing \Umathordbinspacing -\aliased\let\ordrelspacing \Umathordrelspacing -\aliased\let\ordopenspacing \Umathordopenspacing -\aliased\let\ordclosespacing \Umathordclosespacing -\aliased\let\ordpunctspacing \Umathordpunctspacing -\aliased\let\ordinnerspacing \Umathordinnerspacing -\aliased\let\opordspacing \Umathopordspacing -\aliased\let\opopspacing \Umathopopspacing -\aliased\let\opbinspacing \Umathopbinspacing -\aliased\let\oprelspacing \Umathoprelspacing -\aliased\let\opopenspacing \Umathopopenspacing -\aliased\let\opclosespacing \Umathopclosespacing -\aliased\let\oppunctspacing \Umathoppunctspacing -\aliased\let\opinnerspacing \Umathopinnerspacing -\aliased\let\binordspacing \Umathbinordspacing -\aliased\let\binopspacing \Umathbinopspacing -\aliased\let\binbinspacing \Umathbinbinspacing -\aliased\let\binrelspacing \Umathbinrelspacing -\aliased\let\binopenspacing \Umathbinopenspacing -\aliased\let\binclosespacing \Umathbinclosespacing -\aliased\let\binpunctspacing \Umathbinpunctspacing -\aliased\let\bininnerspacing \Umathbininnerspacing -\aliased\let\relordspacing \Umathrelordspacing -\aliased\let\relopspacing \Umathrelopspacing -\aliased\let\relbinspacing \Umathrelbinspacing -\aliased\let\relrelspacing \Umathrelrelspacing -\aliased\let\relopenspacing \Umathrelopenspacing -\aliased\let\relclosespacing \Umathrelclosespacing -\aliased\let\relpunctspacing \Umathrelpunctspacing -\aliased\let\relinnerspacing \Umathrelinnerspacing -\aliased\let\openordspacing \Umathopenordspacing -\aliased\let\openopspacing \Umathopenopspacing -\aliased\let\openbinspacing \Umathopenbinspacing -\aliased\let\openrelspacing \Umathopenrelspacing -\aliased\let\openopenspacing \Umathopenopenspacing -\aliased\let\openclosespacing \Umathopenclosespacing -\aliased\let\openpunctspacing \Umathopenpunctspacing -\aliased\let\openinnerspacing \Umathopeninnerspacing -\aliased\let\closeordspacing \Umathcloseordspacing -\aliased\let\closeopspacing \Umathcloseopspacing -\aliased\let\closebinspacing \Umathclosebinspacing -\aliased\let\closerelspacing \Umathcloserelspacing -\aliased\let\closeopenspacing \Umathcloseopenspacing -\aliased\let\closeclosespacing\Umathcloseclosespacing -\aliased\let\closepunctspacing\Umathclosepunctspacing -\aliased\let\closeinnerspacing\Umathcloseinnerspacing -\aliased\let\punctordspacing \Umathpunctordspacing -\aliased\let\punctopspacing \Umathpunctopspacing -\aliased\let\punctbinspacing \Umathpunctbinspacing -\aliased\let\punctrelspacing \Umathpunctrelspacing -\aliased\let\punctopenspacing \Umathpunctopenspacing -\aliased\let\punctclosespacing\Umathpunctclosespacing -\aliased\let\punctpunctspacing\Umathpunctpunctspacing -\aliased\let\punctinnerspacing\Umathpunctinnerspacing -\aliased\let\innerordspacing \Umathinnerordspacing -\aliased\let\inneropspacing \Umathinneropspacing -\aliased\let\innerbinspacing \Umathinnerbinspacing -\aliased\let\innerrelspacing \Umathinnerrelspacing -\aliased\let\inneropenspacing \Umathinneropenspacing -\aliased\let\innerclosespacing\Umathinnerclosespacing -\aliased\let\innerpunctspacing\Umathinnerpunctspacing -\aliased\let\innerinnerspacing\Umathinnerinnerspacing - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-bar.mkxl b/tex/context/base/mkiv/pack-bar.mkxl deleted file mode 100644 index c6a111531..000000000 --- a/tex/context/base/mkiv/pack-bar.mkxl +++ /dev/null @@ -1,94 +0,0 @@ -%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 experimental code). -%D It could be in scrn-bar but it's static. In the meantime the interface has been -%D 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} \??positionbar - -\setuppositionbar - [\c!min=\plusone, - \c!max=\plusone, - \c!n=\plusone - \c!text=?, - \c!width=\emwidth, - \c!height=\strutheight, - \c!depth=\strutdepth] - -\permanent\protected\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}} - -\permanent\protected\def\verticalpositionbar[#1]% - {\vbox to \vsize - {\hsize\positionbarparameter\c!width - \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}} - -\permanent\protected\def\horizontalgrowingbar[#1]% - {\hpack to \hsize - {\setuppositionbar[#1]% - \usepositionbarstyleandcolor\c!style\c!color - \vrule\s!width\zeropoint\s!height\positionbarparameter\c!height\s!depth\positionbarparameter\c!depth - \leaders\vrule\hskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill - \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill - \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} - -\permanent\protected\def\verticalgrowingbar[#1]% - {\vpack to \vsize - {\hsize\positionbarparameter\c!width - \setuppositionbar[#1]% - \usepositionbarstyleandcolor\c!style\c!color - \hrule\s!width\positionbarparameter\c!width\s!height\zeropoint\s!depth\zeropoint - \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill - \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill - \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-bck.mklx b/tex/context/base/mkiv/pack-bck.mklx deleted file mode 100644 index 3c15beb5f..000000000 --- a/tex/context/base/mkiv/pack-bck.mklx +++ /dev/null @@ -1,245 +0,0 @@ -%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 backgrounds. As it is -%D still used WS adapted the code to the new command handler methods so that it gets -%D a second life. So 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 means that texts is -%D to be collected and split over pages. To show what can be done, we provide this -%D part of the documentation with some gray background and a red frame. Both the -%D background and frame can have all characteristics 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. The main problem with -%D this kind of functionality is to get 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 be used -%D 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 - \frozen\setuevalue{\e!start\currentbackground}{\pack_backgrounds_start [\currentbackground]}% - \frozen\setuevalue{\e!stop \currentbackground}{\pack_backgrounds_stop }% - \frozen\setuevalue {\currentbackground}{\pack_backgrounds_direct[\currentbackground]}% -\to \everydefinebackground - -\protected\def\pack_backgrounds_start[#tag]% - {\endgraf - \begingroup - \def\currentbackground{#tag}% - \doifelse{\backgroundparameter\c!state}\v!start - \pack_backgrounds_start_indeed - \pack_backgrounds_start_ignore} - -\tolerant\def\pack_backgrounds_start_indeed[#settings]% - {\setupcurrentbackground[#settings,\c!state=\v!start,\c!offset=\v!overlay]% - \let\pack_backgrounds_stop\pack_backgrounds_stop_indeed - \setbox\scratchboxone\vbox\bgroup - \strut - \vskip-2\lineheight - \strut - \blank[\v!disable] - \leftskip \backgroundparameter\c!leftoffset - \rightskip\backgroundparameter\c!rightoffset} - -\tolerant\def\pack_backgrounds_start_ignore[#settings]% - {\let\pack_backgrounds_stop\pack_backgrounds_stop_ignore} - -\let\pack_backgrounds_stop\relax - -\protected\def\pack_backgrounds_stop_indeed % we shoul duse the fast background variant of framed - {\endgraf - \removelastskip - \strut - \vskip-2\lineheight - \strut - % safeguard added - \ifdim\dimexpr\pagetotal+2\lineheight\relax>\pagegoal - \page - \fi - % till here - \egroup - \scratchdistance\leftskip % new ** - \forgetall - \ifinsidefloat - \backgroundsplitmode\zerocount - \fi - \ifcase\backgroundsplitmode - \inheritedbackgroundframed{\box\scratchboxone}% - \or - \hskip\scratchdistance - \inheritedbackgroundframed{\box\scratchboxone}% - \else - \splitmaxdepth\boxmaxdepth - \splittopskip\topskip - \doloop - {\ifzeropt\pagetotal % empty page - \scratchdimen\textheight - \backgroundsplitmode\plusone % split to max height - \else - \setbox\scratchdimentwo\vbox{\backgroundparameter\c!before}% - \scratchdimen\dimexpr\pagegoal-\ht\scratchdimentwo-\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\ht\scratchboxone>\scratchdimen % larger than page - \setbox\scratchdimentwo\vsplit\scratchboxone to \scratchdimen - \else - \setbox\scratchdimentwo\box\scratchboxone - \backgroundsplitmode\zerocount % no split - \fi - \setbox\scratchdimentwo\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split - {\vskip\backgroundparameter\c!topoffset - \unvcopy\scratchdimentwo - \prevdepth\dp\scratchdimentwo - \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\scratchdistance % new ** - \fi - \inheritedbackgroundframed{\box\scratchdimentwo}% - \stoplinecorrection - \ifcase\backgroundsplitmode % no split - \backgroundparameter\c!after - \else % some split - \page_otr_fill_and_eject_page % no \page ! - \fi - \else - \page - \fi - \ifdim\ht\scratchboxone>\zeropoint \else - \exitloop - \fi}% - \fi - \endgroup - \endgraf} - -\protected\def\pack_backgrounds_stop_ignore - {\endgroup - \endgraf} - -\protected\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 - \permanent\expandafter\let\expandafter\startbackground\csname\e!start\v!background\endcsname - \permanent\expandafter\let\expandafter\stopbackground \csname\e!stop \v!background\endcsname - \permanent\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 - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-box.mkxl b/tex/context/base/mkiv/pack-box.mkxl deleted file mode 100644 index b638dda3b..000000000 --- a/tex/context/base/mkiv/pack-box.mkxl +++ /dev/null @@ -1,1114 +0,0 @@ -%D \module -%D [ file=pack-box, -%D version=2002.04.12, -%D title=\CONTEXT\ Packaging Macros, -%D subtitle=Boxes, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Packaging Macros / Boxes} - -%D This module contains all kind of macros for moving content around. Many -%D macros here come from other modules, but depencies made it more clear -%D to isolate them. We invite users to document the macros. They can be -%D handy shortcuts for otherwise complex tasks. - -\unprotect - -%D We need to set the size, else we get dimensions depending on the content, -%D which in itself is ok, but can lead to loops due to rounding errors (happened -%D in demo-obv). - -% \definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] -% \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] -% \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] -% \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] - -\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] -\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] -\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] -\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] - -\permanent\protected\def\internaltextoverlay#1% will become more generic and installable - {\startoverlay % i.e. probably an overlay by itself - {\positionregionoverlay\textanchor{\v!text#1}}% see later - {\composedlayer {\v!text#1}}% - \stopoverlay} - -\defineoverlay[\v!text-2][\internaltextoverlay{-2}] -\defineoverlay[\v!text-1][\internaltextoverlay{-1}] -\defineoverlay[\v!text+1][\internaltextoverlay{+1}] -\defineoverlay[\v!text+2][\internaltextoverlay{+2}] - -\installcorenamespace {anchor} - -% produces a box too -% -% \anchor[text-1][preset=lefttop][framed settings]{HELLO WORLD} - -\permanent\tolerant\protected\def\defineanchor[#1]#*[#2]#*[#3]#*[#4]% name targetlayer layersetting framedsetting - {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}} - -\def\pack_anchors_process_defined#1#2#3% - {\tolerant\def\pack_anchors_process_defined_indeed[##1]##*[##2]% - {\ifarguments - \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}% - \or - \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}% - \or - \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}% - \fi - \next}% picks up a box - \pack_anchors_process_defined_indeed} - -\protected\def\anchor[#1]% - {\begingroup - \edef\currentanchor{#1}% - \ifcsname\??anchor\currentanchor\endcsname - \expandafter\lastnamedcs - \else - \expandafter\pack_anchor_notdefined - \fi} - -\tolerant\def\pack_anchor_notdefined[#1]#*[#2]% - {\ifarguments - \expandafter\gobbletwoarguments - \or - \expandafter\pack_anchor_notdefined_one - \else - \expandafter\pack_anchor_notdefined_two - \fi{#1}{#2}} - -\def\pack_anchor_notdefined_one #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#1}}\vbox} -\def\pack_anchor_notdefined_two #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#2}}\vbox} -\def\pack_anchors_process_indeed#1#2#3{\dowithnextbox{\pack_anchors_process_finish {#1}{#2}{#3}}\vbox} - -\newbox \b_pack_anchors -\newdimen\d_pack_anchors_width -\newdimen\d_pack_anchors_height -\newdimen\d_pack_anchors_depth - -% \definelayer[anchor] - -\newcount\c_pack_anchors_n -\newtoks \t_pack_anchors_flush - -\protected\def\pack_anchors_register#1#2% - {\global\advance\c_pack_anchors_n\plusone - \pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]% - \putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors -% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}% - \doglobal\appendetoks - \pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}% - \to \t_pack_anchors_flush - \glet\pack_anchors_flush_all\pack_anchors_flush_all_indeed} - -\protected\def\pack_anchors_flush#1#2#3% - {\doifelseboxincache\v!anchor{#1} - {\doifelsereferencefound{\v!layer:\v!anchor:#1} - {\ifnum\currentreferencerealpage=\realpageno\relax - \setlayer[#2][#3,\c!position=\v!no]{\directboxfromcache\v!anchor{#1}}% - \else - \donetrue - \fi - }\donetrue}% - \donetrue}% - -\protected\def\pack_anchors_flush_all_indeed - {\donefalse - \the\t_pack_anchors_flush - \ifdone\else - \global\t_pack_anchors_flush\emptytoks - \glet\pack_anchors_flush_all\relax - \fi} - -\let\pack_anchors_flush_all\relax - -\appendtoks - \pack_anchors_flush_all -\to \everybeforepagebody - -\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy - {\checkpositionoverlays - \setbox\b_pack_anchors\box\nextbox - \framed % could be a predefined framed but used seldom - [\c!offset=\v!overlay,\c!frame=\v!off,#3] - {\pack_anchors_register{#1}{#2}% - \novrule % hm, not needed as we frame the size (but kind of default) - \s!width \wd\b_pack_anchors - \s!height\ht\b_pack_anchors - \s!depth \dp\b_pack_anchors}% - \endgroup} - -% \setlayeranchored[text-1][preset=lefttop]{HELLO WORLD} produces a simple (empty) hbox -% synchronizes per page - -\permanent\tolerant\protected\def\setlayeranchored[#1]#*[#2]% - {\begingroup - \ifarguments - \dowithnextbox - {\endgroup}% - \else - \dowithnextbox - {\checkpositionoverlays - \setbox\b_pack_anchors\box\nextbox - \dontleavehmode\hpack{\pack_anchors_register{#1}{#2}}% - \endgroup}% - \fi - \hbox} - -% collectors - -\installcorenamespace{collectorbox} -\installcorenamespace{collector} - -\installcommandhandler \??collector {collector} \??collector - -\setupcollector - [\c!state=\v!start, - \c!x=\zeropoint, - \c!y=\zeropoint, - \c!offset=\zeropoint, - \c!rotation=, % geen 0 ! - \c!hoffset=\zeropoint, - \c!voffset=\zeropoint, - \c!location=rb, - \c!corner=] - -\appendtoks - \ifcsname\??collectorbox\currentcollector\endcsname \else - \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname - \fi -\to \everydefinecollector - -\permanent\protected\def\resetcollector[#1]% - {\ifcsname\??collectorbox#1\endcsname - \global\setbox\lastnamedcs\emptybox - \fi} - -\newconditional\c_pack_boxes_collector_valid_box - -\let\b_pack_boxes_collector\scratchbox - -\def\pack_boxes_collector_check_box#1% - {\edef\currentcollector{#1}% - \ifcsname\??collectorbox\currentcollector\endcsname - \settrue\c_pack_boxes_collector_valid_box - \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs - \else - \setfalse\c_pack_boxes_collector_valid_box - \writestatus{collector}{unknown collector \currentcollector}% - \fi} - -\permanent\tolerant\protected\def\setcollector[#1]#*[#2]% todo: keep reference point - {\bgroup - \pack_boxes_collector_check_box{#1}% - \ifconditional\c_pack_boxes_collector_valid_box - \setupcurrentcollector[#2]% - \expandafter\pack_boxes_collector_yes - \else - \expandafter\pack_boxes_collector_nop - \fi} - -\def\pack_boxes_collector_yes - {\forgetall - \dontcomplain - \dowithnextboxcs\pack_boxes_collector_finish\hbox} - -\let\pack_boxes_collector_nop\egroup - -\installcorenamespace{collectorcorners} - -\setvalue{\??collectorcorners\v!middle}% - {\ifdim\d_pack_layers_x_size>\zeropoint - \advance\d_pack_layers_x_position.5\d_pack_layers_x_size - \fi - \ifdim\d_pack_layers_y_size>\zeropoint - \advance\d_pack_layers_y_position.5\d_pack_layers_y_size - \fi} - -\setvalue{\??collectorcorners\v!bottom}% - {\ifdim\d_pack_layers_y_size>\zeropoint - \advance\d_pack_layers_y_position-\d_pack_layers_y_size - \d_pack_layers_y_position-\d_pack_layers_y_position - \fi} - -\setvalue{\??collectorcorners\v!right}% - {\ifdim\d_pack_layers_x_size>\zeropoint - \advance\d_pack_layers_x_position-\d_pack_layers_x_size - \d_pack_layers_x_position-\d_pack_layers_x_position - \fi} - -\def\pack_boxes_collector_check_corner#1% - {\ifcsname\??collectorcorners#1\endcsname - \lastnamedcs - \fi} - -\def\pack_boxes_collector_finish - {\edef\p_collector_rotation{\collectorparameter\c!rotation}% - \edef\p_collector_corner {\collectorparameter\c!corner}% - \ifempty\p_collector_rotation \else - \setbox\nextbox\hpack - {\rotate - [\c!location=\v!high, - \c!rotation=\p_collector_rotation] - {\box\nextbox}}% - \fi - \d_pack_layers_x_size\wd\b_pack_boxes_collector - \d_pack_layers_y_size\htdp\b_pack_boxes_collector - \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax - \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax - \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner - \setbox\nextbox\hpack - {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}% - \boxmaxdepth\zeropoint % really needed, nice example - \global\advance\boxhdisplacement\d_pack_layers_x_position - \ifdim\boxhdisplacement<\zeropoint - \global\setbox\b_pack_boxes_collector\hpack - {\kern-\boxhdisplacement - \box\b_pack_boxes_collector}% - \fi - \global\advance\boxvdisplacement\d_pack_layers_y_position - \ifdim\boxvdisplacement<\zeropoint - \global\setbox\b_pack_boxes_collector\hpack - {\lower-\boxvdisplacement - \box\b_pack_boxes_collector}% - \fi - \d_pack_layers_x_size\wd\b_pack_boxes_collector - \d_pack_layers_y_size\htdp\b_pack_boxes_collector - \global\setbox\b_pack_boxes_collector\hpack - {\box\b_pack_boxes_collector - \kern\dimexpr - -\d_pack_layers_x_size - +\d_pack_layers_x_position - \ifdim\boxhdisplacement<\zeropoint - -\boxhdisplacement - \fi - \relax - \lower\d_pack_layers_y_position\hpack - {\ifdim\boxvdisplacement<\zeropoint - \lower-\boxvdisplacement - \fi - \box\nextbox}}% - % combine height and depth into depth only (later flushed as height) - \global\setbox\b_pack_boxes_collector\hpack - {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}% - % just to be sure - \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size - \wd\b_pack_boxes_collector\d_pack_layers_x_size - \fi - \egroup} - -\permanent\protected\def\flushcollector[#1]% - {\bgroup - \pack_boxes_collector_check_box{#1}% - \ifconditional\c_pack_boxes_collector_valid_box - \edef\p_collector_state{\collectorparameter\c!state}% - \ifx\p_collector_state\v!stop \else - \vpack{\hpack{\raise - \dp\b_pack_boxes_collector - \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}% - \fi - \fi - \egroup} - -\permanent\protected\def\composedcollector#1% no [], handy as argument - {\flushcollector[#1]} - -\permanent\tolerant\protected\def\adaptcollector[#1]#*[#2]% % a typical case where \global\wd looks better in the code - {\begingroup - \pack_boxes_collector_check_box{#1}% - \ifconditional\c_pack_boxes_collector_valid_box - \letcollectorparameter\c!voffset\zeropoint - \letcollectorparameter\h!voffset\zeropoint - \setupcurrentcollector[#2]% - \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax - \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax - \fi - \endgroup} - -%\definecollector[test] -%\setcollector[test] -% [location=rb] -% {\externalfigure[koe][frame=on,width=3cm]} -%\setcollector[test] -% [corner={right,bottom},location={left,top}] -% {\framed{gans}} -%\composedcollector{test} - -\definecollector - [caption] - -\permanent\tolerant\protected\def\collectedtext[#1]#*[#2]% for captions - {\pack_boxes_collector_text[#1][#2]} - -\def\pack_boxes_collector_text[#1][#2]#3% #3 is mandate so no tolerant here, so still two step - {\bgroup - \dowithnextbox - {\setcollector - [caption] - {\box\nextbox}% - \setcollector - [caption][#1]% - {\letdummyparameter\c!style\empty - \letdummyparameter\c!color\empty - \getdummyparameters[#2]% - \dousestyleparameter{\directdummyparameter\c!style}% - \setupinterlinespace - \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}% - \composedcollector{caption}% - \egroup}% - \hbox} - -% \collectedtext -% [corner={right,bottom},location={left,top}] -% [background=color,backgroundcolor=white,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} -% -% \collectedtext -% [rotation=90,corner={right,bottom},location={right,top}] -% [frame=on,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} -% -% \collectedtext -% [rotation=90,corner={left,bottom},location={left,top}] -% [frame=on,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} - -\installcorenamespace {layeredtext} -\installcorenamespace {layeredtextlayer} -\installcorenamespace {layeredtextframed} - -\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext - -\newdimen\d_pack_layeredtexts_width -\newdimen\d_pack_layeredtexts_height - -\definelayer % private - [\??layeredtextlayer] - -\setuplayer % private - [\??layeredtextlayer] - [\c!width=\d_pack_layeredtexts_width, - \c!height=\d_pack_layeredtexts_height] - -\defineframed % private - [\??layeredtextframed] - [\c!offset=\v!overlay, - \c!frame=\v!off, - \c!background={\v!foreground,\??layeredtextlayer}, - \c!width=\d_pack_layeredtexts_width, - \c!height=\d_pack_layeredtexts_height] - -\setuplayeredtext % public (the attached data, usually small stuff, not the main thing) - [\c!frame=\v!overlay, - \c!color=, - \c!style=, - \c!foregroundcolor=\layeredtextparameter\c!color, - \c!foregroundstyle=\layeredtextparameter\c!style] - -\permanent\tolerant\protected\def\placelayeredtext[#1]#*[#2]#*[#3]#4% tag layersettings content(framed)settings content - {\bgroup - \edef\currentlayeredtext{#1}% - \checklayeredtextparent % bonus - \setupcurrentlayeredtext[#3]% - \dowithnextbox - {\d_pack_layeredtexts_width \wd\nextbox - \d_pack_layeredtexts_height\ht\nextbox - \begingroup % preserve \nextbox - \setlayer - [\??layeredtextlayer]% - [#2]% - {\setfalse\fontattributeisset - \uselayeredtextstyleparameter\c!style - \ifconditional\fontattributeisset - \setupinterlinespace - \fi - \inheritedlayeredtextframed{#4}}% - \endgroup - \placeframed[\??layeredtextframed]{\flushnextbox}% - \egroup}% - \hbox} - -\permanent\protected\def\layeredtext - {\placelayeredtext[]} - -% \layeredtext -% [corner={right,bottom},location={left,top}] -% [background=color,backgroundcolor=white,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} -% -% \layeredtext -% [rotation=90,corner={right,bottom},location={right,top}] -% [frame=on,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} -% -% \layeredtext -% [rotation=90,corner={left,bottom},location={left,top}] -% [frame=on,offset=0pt] -% {gans} -% {\externalfigure[koe][width=3cm]} - -\permanent\tolerant\protected\def\ornamenttext[#1]#*[#2]% takes another argument - {\bgroup - \doifelseassignment{#1} - {\letdummyparameter\c!alternative\v!a - \getdummyparameters[#1]% - \doifelse{\directdummyparameter\c!alternative}\v!a - {\egroup\collectedtext}% - {\egroup\layeredtext }% - [#1][#2]}% - {\egroup\getvalue{#1}}} - -\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]% - {\setuvalue{#1}{\pack_ornament_text[#2][#3]}} - -% \defineornament -% [affiliation] -% [rotation=90,corner={right,bottom},location={right,top}, -% hoffset=-.25ex] -% [frame=on,background=color,backgroundcolor=red,offset=0pt] -% -% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} -% -% \defineornament -% [affiliation] -% [rotation=90,corner={right,bottom},location={right,top}, -% hoffset=-.25ex,alternative=b] -% [frame=on,background=color,backgroundcolor=red,offset=0pt] -% -% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} -% -% \defineornament -% [affiliation] -% [rotation=90,corner={right,bottom},location={left,top}, -% hoffset=.25ex,voffset=.25ex,alternative=a] -% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] -% -% \affiliation{photo}{\externalfigure[molen][width=3cm]} -% -% \defineornament -% [affiliation] -% [rotation=90,corner={right,bottom},location={left,top}, -% hoffset=.25ex,voffset=.25ex,alternative=b] -% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] -% -% \affiliation{drawing}{\externalfigure[hakker][width=3cm]} - -\newcount\c_pack_boxes_bleeds - -\installcorenamespace {bleeding} - -\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding - -\setupbleeding - [\c!location=l, - \c!stretch=\v!yes, - \c!width=3cm, - \c!height=3cm, - \c!offset=2mm, - \c!page=\v!no, - \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset - \c!hoffset=\scratchoffset] % which often saves one resolve - -\def\bleedwidth {\the\hsize} % these are global ! -\def\bleedheight{\the\vsize} % these are global ! - -\newconditional\c_pack_boxes_l -\newconditional\c_pack_boxes_r -\newconditional\c_pack_boxes_t -\newconditional\c_pack_boxes_b - -\installcorenamespace{bleedinglocation} - -\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint} -\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint} -\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint} -\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint} -\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} -\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} -\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} -\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} -\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} -\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} -\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} -\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} - -\permanent\tolerant\protected\def\bleed[#1]% - {\hbox\bgroup - \global\advance\c_pack_boxes_bleeds\plusone - % - \xdef\bleedwidth {\the\hsize}% - \xdef\bleedheight{\the\vsize}% - % - \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}% - \edef\currentpageposition{page:0}% todo: per page - % - \setupcurrentbleeding[#1]% - % - \scratchwidth \bleedingparameter\c!width - \scratchheight \bleedingparameter\c!height - \scratchoffset \bleedingparameter\c!offset - \scratchhoffset\bleedingparameter\c!hoffset - \scratchvoffset\bleedingparameter\c!voffset - % - \setfalse\c_pack_boxes_l % left - \setfalse\c_pack_boxes_r % right - \setfalse\c_pack_boxes_t % top - \setfalse\c_pack_boxes_b % bottom - % - \csname\??bleedinglocation\bleedingparameter\c!location\endcsname - % - \doifelse{\bleedingparameter\c!stretch}\v!yes\donetrue\donefalse - % - \xdef\bleedwidth{\the\dimexpr - \ifdone - \ifconditional\c_pack_boxes_l - \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition - \orelse\ifconditional\c_pack_boxes_r - \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked - \else - \scratchwidth - \fi - \else - \scratchwidth - \fi+\scratchhoffset - \relax}% - \xdef\bleedheight{\the\dimexpr - \ifdone - \ifconditional\c_pack_boxes_t - \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked - \orelse\ifconditional\c_pack_boxes_b - \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition + \MPh\currentbgposition % not checked (\MPh added) - \else - \scratchheight - \fi - \else - \scratchheight - \fi+\scratchvoffset - \relax}% - \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox} - -\def\pack_boxes_bleed_settings - {\hsize\bleedwidth - \vsize\bleedheight} - -\def\pack_boxes_bleed_finish - {\doif{\bleedingparameter\c!page}\v!yes - {\setbox\nextbox\topskippedbox{\box\nextbox}}% - \setbox\nextbox\hpack to \scratchwidth - {\ifconditional\c_pack_boxes_l\hss\fi - \box\nextbox - \ifconditional\c_pack_boxes_r\hss\fi}% - \ifconditional\c_pack_boxes_b - \setbox\nextbox\hpack - {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}% - \fi - \wd\nextbox\scratchwidth - \ht\nextbox\scratchheight - \dp\nextbox\zeropoint - \ifdone - \hpos\currentbgposition{\box\nextbox}% - \else - \box\nextbox - \fi - \egroup} - -\defineexternalfigure - [bleed] % should be \v!bleed - [\c!width=\bleedwidth, - \c!height=\bleedheight] - -% \placefigure[left]{none} -% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}} -% -% \input tufte -% -% \placefigure[left]{none} -% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}} -% -% \input tufte -% -% \placefigure[right]{none} -% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}} -% -% \input tufte -% -% \placefigure -% [top,none] -% {} % no caption -% {\bleed -% [hoffset=-\backspace, -% voffset=3mm, -% width=0cm, -% height=6\lineheight, -% page=yes, % correct for topskip -% location=lt] -% {\externalfigure[koe][bleed][frame=on]}} - -% \setlayerframed[layer id][layer settings][framed setting]{data} -% \setlayerframed[layer id][combined settings]{data} - -% tricky: offsets apply to both the layer and the framed; it makes sense to -% only apply the offset to ... - -\permanent\tolerant\protected\def\setlayerframed[#1]#*[#2]#*[#3] - {\ifarguments - % error - \or - \expandafter\pack_layers_set_framed_s - \or - \expandafter\pack_layers_set_framed_d - \or - \expandafter\pack_layers_set_framed_t - \fi[#1][#2][#3]} - -\def\pack_layers_set_framed_s[#1][#2][#3]% - {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]% - \normalframedwithsettings[\c!location=\v!normal]} % different kind of location - -\def\pack_layers_set_framed_d[#1][#2][#3]% - {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]% - \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location - -\def\pack_layers_set_framed_t[#1][#2][#3]% - {\setlayer[#1][#2]% - \normalframedwithsettings[#3]} - -\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#3]% - {\bgroup - \letdummyparameter\c!align\empty - \letdummyparameter\c!width\hsize - \letdummyparameter\c!color\empty - \letdummyparameter\c!style\empty - \getdummyparameters[#3]% - \dowithnextboxcontent - {\forgetall - \hsize\directdummyparameter\c!width - \usealignparameter\directdummyparameter - \dousestyleparameter{\directdummyparameter\c!style}} - {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color - \egroup}% - \vtop} - -% \setupbackgrounds -% [page] -% [background=pagefigures] -% -% \definelayer -% [pagefigures] -% [x=-2mm, -% y=-2mm, -% width=\paperwidth, -% height=\paperheight] -% -% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}] -% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}] -% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}] -% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}] -% \definelayerpreset [middle] [corner=middle,location=middle] -% -% \setlayer[pagefigures][preset=lefttop] -% \setlayer[pagefigures][preset=righttop] -% \setlayer[pagefigures][preset=leftbottom] -% \setlayer[pagefigures][preset=rightbottom] - -\definelayerpreset - [\v!left\v!top] - [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}] - -\definelayerpreset - [\v!right\v!top] - [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}] - -\definelayerpreset - [\v!left\v!bottom] - [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}] - -\definelayerpreset - [\v!right\v!bottom] - [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}] - -\definelayerpreset - [\v!middle] - [\c!corner=\v!middle,\c!location=\v!middle] - -\definelayerpreset - [\v!middle\v!top] - [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth] - -\definelayerpreset - [\v!middle\v!bottom] - [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth] - -\definelayerpreset - [\v!middle\v!left] - [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight] - -\definelayerpreset - [\v!middle\v!right] - [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight] - -% left and right hanging: - -\definelayerpreset - [\v!left\v!top\v!left] - [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}] - -\definelayerpreset - [\v!right\v!top\v!right] - [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}] - -\installcorenamespace{alignedboxes} - -\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish} -\permanent\tolerant\protected\def\aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox} - -\def\pack_boxes_aligned_finish - {\ifcsname\??alignedboxes\serializedcommalist\endcsname - \expandafter\lastnamedcs - \else - \expandafter\middlebox - \fi{\flushnextbox}% - \egroup} - -\letvalue{\??alignedboxes }\middlebox -\letvalue{\??alignedboxes\v!middle }\middlebox -\letvalue{\??alignedboxes\v!middle\v!middle}\middlebox -\letvalue{\??alignedboxes\v!left }\leftbox -\letvalue{\??alignedboxes\v!left \v!top }\lefttopbox -\letvalue{\??alignedboxes\v!left \v!bottom}\leftbottombox -\letvalue{\??alignedboxes\v!right }\rightbox -\letvalue{\??alignedboxes\v!right \v!top }\righttopbox -\letvalue{\??alignedboxes\v!right \v!bottom}\rightbottombox -\letvalue{\??alignedboxes\v!bottom }\bottombox -\letvalue{\??alignedboxes\v!bottom\v!left }\bottomleftbox -\letvalue{\??alignedboxes\v!bottom\v!right }\bottomrightbox -\letvalue{\??alignedboxes\v!top }\topbox -\letvalue{\??alignedboxes\v!top \v!left }\topleftbox -\letvalue{\??alignedboxes\v!top \v!right }\toprightbox -\letvalue{\??alignedboxes\v!line }\baselinemiddlebox % \v!grid is taken -\letvalue{\??alignedboxes\v!line \v!left }\baselineleftbox -\letvalue{\??alignedboxes\v!line \v!middle}\baselinemiddlebox -\letvalue{\??alignedboxes\v!line \v!right }\baselinerightbox -\letvalue{\??alignedboxes c}\middlebox -\letvalue{\??alignedboxes l}\leftbox -\letvalue{\??alignedboxes r}\rightbox -\letvalue{\??alignedboxes b}\bottombox -\letvalue{\??alignedboxes t}\topbox -\letvalue{\??alignedboxes lt}\lefttopbox -\letvalue{\??alignedboxes lb}\leftbottombox -\letvalue{\??alignedboxes rt}\righttopbox -\letvalue{\??alignedboxes rb}\rightbottombox -\letvalue{\??alignedboxes tl}\topleftbox -\letvalue{\??alignedboxes bl}\bottomleftbox -\letvalue{\??alignedboxes tr}\toprightbox -\letvalue{\??alignedboxes br}\bottomrightbox -\letvalue{\??alignedboxes m}\middlebox -\letvalue{\??alignedboxes g}\baselinemiddlebox -\letvalue{\??alignedboxes gl}\baselineleftbox -\letvalue{\??alignedboxes gc}\baselinemiddlebox -\letvalue{\??alignedboxes gr}\baselinerightbox - -% left/right/top/bottomoffset -> dimensions change -% x/y | method=fixed -> dimensions don't change - -\installcorenamespace{offsetbox} - -\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox - -\setupoffsetbox - [\c!x=\zeropoint, - \c!y=\zeropoint, - \c!width=\wd\nextbox, - \c!height=\ht\nextbox, - \c!depth=\dp\nextbox, - \c!location=, - \c!leftoffset=\zeropoint, - \c!rightoffset=\zeropoint, - \c!topoffset=\zeropoint, - \c!bottomoffset=\zeropoint, - \c!method=] - -\aliased\let\setupoffset\setupoffsetbox - -\permanent\tolerant\protected\def\offsetbox[#1]% - {\bgroup - \pack_boxes_offset_check[#1]% - \dowithnextboxcs\pack_boxes_offsetfinish} - -\permanent\tolerant\protected\def\offset[#1]% - {\bgroup - \pack_boxes_offset_check[#1]% - \dowithnextboxcs\pack_boxes_offsetfinish\hbox} - -\newcount\c_pack_boxes_offset_level - -\def\pack_boxes_offset_check - {\advance\c_pack_boxes_offset_level\plusone - \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}% - \checkoffsetboxparent - \setupcurrentoffsetbox} - -\def\pack_boxes_offsetfinish - {\donefalse - \scratchxposition \offsetboxparameter\c!x - \scratchyposition \offsetboxparameter\c!y - \scratchleftoffset \offsetboxparameter\c!leftoffset - \scratchrightoffset \offsetboxparameter\c!rightoffset - \scratchtopoffset \offsetboxparameter\c!topoffset - \scratchbottomoffset\offsetboxparameter\c!bottomoffset - \relax % really needed - \ifzeropt\scratchleftoffset \else\donetrue\fi - \ifzeropt\scratchrightoffset \else\donetrue\fi - \ifzeropt\scratchtopoffset \else\donetrue\fi - \ifzeropt\scratchbottomoffset\else\donetrue\fi - \ifdone - \edef\p_method{\offsetboxparameter\c!method}% - \ifx\p_method\v!fixed % new - \ifzeropt\scratchleftoffset - \ifzeropt\scratchrightoffset \else - \scratchxposition-\scratchrightoffset - \scratchrightoffset\zeropoint - \fi - \else - \scratchxposition\scratchleftoffset - \scratchleftoffset\zeropoint - \fi - \ifzeropt\scratchtopoffset - \ifzeropt\scratchbottomoffset \else - \scratchyposition-\scratchbottomoffset - \scratchbottomoffset\zeropoint - \fi - \else - \scratchyposition\scratchtopoffset - \scratchtopoffset\zeropoint - \fi - \donefalse - \fi - \fi - \ifdone - \setbox\nextbox\vpack - {\forgetall % already done - \offinterlineskip - \kern\scratchtopoffset - \hpack - {\kern\scratchleftoffset - \box\nextbox - \kern\scratchrightoffset}% - \kern\scratchbottomoffset}% - \ht\nextbox\htdp\nextbox - \dp\nextbox\zeropoint - \fi - \scratchwidth \offsetboxparameter\c!width - \scratchheight\offsetboxparameter\c!height - \scratchdepth \offsetboxparameter\c!depth - \edef\p_location{\offsetboxparameter\c!location}% - \setbox\nextbox\hpack - {\kern\scratchxposition - \lower\scratchyposition\hpack - {\ifempty\p_location - \box\nextbox - \else - \alignedbox[\p_location]\hpack{\box\nextbox}% - \fi}}% - \wd\nextbox\scratchwidth - \ht\nextbox\scratchheight - \dp\nextbox\scratchdepth - \box\nextbox - \egroup} - -%D \starttyping -%D \framed[offset=overlay]{\offset[leftoffset=1cm] -%D {\framed[offset=overlay]{\offset[rightoffset=1cm] -%D {\externalfigure[koe][width=1cm]}}}} -%D -%D \blank -%D -%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank -%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank -%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank -%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank -%D \stoptyping - -% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid] -% -% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte -% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte -% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte -% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte - -% Some old code: -% -% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf -% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf -% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf -% -% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf -% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf -% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf -% -% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf -% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf -% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf - -\def\pack_boxes_tabbed#1#2#3#4% - {\dontleavehmode - \begingroup - \setbox\scratchbox\hpack{#3}% - \hpack to \wd\scratchbox{#1#4#2}% - \endgroup} - -\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss} -\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss \relax} -\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss \hss} - -\let\mtabbed\ctabbed - -% to be documented - -\permanent\protected\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{} - {\hpack\bgroup - \letdummyparameter\c!width \zeropoint - \letdummyparameter\c!height\zeropoint - \letdummyparameter\c!depth \zeropoint - \getdummyparameters[#1]% - \setbox\scratchbox\emptyhbox - \wd\scratchbox\directdummyparameter\c!width - \ht\scratchbox\directdummyparameter\c!height - \dp\scratchbox\directdummyparameter\c!depth - \box\scratchbox - \egroup} - -% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]} - -% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} - -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} -% -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} -% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} -% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} - -\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize - {\bgroup - \forgetall - \scratchcounter#1\relax - \scratchwidth #2\relax - \scratchheight #3\relax - \dowithnextboxcs\pack_boxes_background_image\hbox} - -\def\pack_boxes_background_image - {\offinterlineskip - \ifcase\scratchcounter - % just one - \else - \scratchdimen\scratchwidth \divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax - \scratchdimen\scratchheight\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax - % to be considered: methods - \ifcase\scratchcounter - \or % x and y - \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% - \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% - \or % x - \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% - \or % y - \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% - \fi - \fi - \ifdim\wd\nextbox>\scratchwidth - \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}% - \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% - \fi - \ifdim\ht\nextbox>\scratchheight - \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}% - \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% - \fi - \box\nextbox - \egroup} - -\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize - {\bgroup - \forgetall - \scratchcounter#1\relax - \scratchwidth #2\relax - \scratchheight #3\relax - \dowithnextboxcs\pack_boxes_background_image_fill\hbox} - -\def\pack_boxes_background_image_fill - {\offinterlineskip - \setbox\nextbox\hpack\bgroup - \ifdim\scratchwidth>\scratchheight - \scale[\c!width=\the\scratchwidth]{\box\nextbox}% - \else - \scale[\c!height=\the\scratchheight]{\box\nextbox}% - \fi - \egroup - \ifdim\wd\nextbox>\scratchwidth - \setbox\nextbox\hpack to \scratchwidth - {\ifcase\scratchcounter - \hss\box\nextbox\hss - \or - \box\nextbox\hss - \or - \hss\box\nextbox - \else - \hss\box\nextbox\hss - \fi}% - \setbox\nextbox\hpack - {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% - \fi - \ifdim\ht\nextbox>\scratchheight - \setbox\nextbox\vpack to \scratchheight - {\ifcase\scratchcounter - \vss\box\nextbox\vss - \or - \box\nextbox\vss - \or - \vss\box\nextbox - \else - \vss\box\nextbox\vss - \fi}% - \setbox\nextbox\hpack - {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% - \fi - \box\nextbox - \egroup} - -\permanent\protected\def\overlayimage#1% - {\vpack to \overlayheight\bgroup - \vss - \hpack to \overlaywidth\bgroup - \hss - \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]% - \hss - \egroup - \vss - \egroup} - -\permanent\protected\def\clippedoverlayimage#1% - {\clip - [\c!width=\overlaywidth,\c!height=\overlayheight] - {\overlayimage{#1}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-com.mkxl b/tex/context/base/mkiv/pack-com.mkxl deleted file mode 100644 index 9392a68a6..000000000 --- a/tex/context/base/mkiv/pack-com.mkxl +++ /dev/null @@ -1,949 +0,0 @@ -%D \module -%D [ file=pack-com, % used to be in core-mis, -%D version=20120111, -%D title=\CONTEXT\ Packing Macros, -%D subtitle=Combinations, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Packaging Macros / Combinations} - -\unprotect - -% \startfloatcombination will be redone ... we can decouple the floatcontent -% and caption and pass them to combinations so that we get better fit when the -% caption is wider than the float, testcase: -% -% \startfloatcombination [2*2] -% \placefigure[local]{alpha}{\externalfigure[cow.pdf][width=1cm]}% -% \placefigure[local]{beta} {\externalfigure[cow.pdf][width=2cm]}% -% \placefigure[local]{gamma}{\externalfigure[cow.pdf][width=3cm]} -% \placefigure[local]{delta}{\externalfigure[cow.pdf][width=4cm]} -% \stopfloatcombination - -%D We could of course map combinations onto one of the table mechanisms but as it -%D has served us well for ages we keep this one. The code has been cleaned up a bit -%D and mkiv'd. -%D -%D Okay ... I might luafy this one eventually. - -% \startcombination {alpha} {a} {beta} {b} \stopcombination -% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination -% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination -% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination -% \startcombination[2] \combination {alpha} {a} \combination{beta} {b} \stopcombination - -%D We do support some structure but the order matters and currently it's only window -%D dressing: - -%D \starttyping -%D \let\startcontent\bgroup -%D \let\stopcontent \egroup -%D \let\startcaption\bgroup -%D \let\stopcaption \egroup -%D \stoptyping -%D -%D Of course we should have started with more structure as it would simply the code. -%D -%D \starttyping -%D \startcombination -%D \startcontent -%D \externalfigure[cow] -%D \stopcontent -%D \startcaption -%D Some cow. -%D \stopcaption -%D \startcontent -%D \externalfigure[cow] -%D \stopcontent -%D \startcaption -%D The same cow. -%D \stopcaption -%D \stopcombination -%D \stoptyping - -\ifdefined\dotagcombination \else \let\dotagcombination\relax \fi - -\newsystemmode{combination} - -\appendtoks - \globalresetsystemmode{combination}% -\to \everyinsidefloat - -\newcount\c_pack_combinations_nesting % local - -\newcount\c_pack_combinations_x % global -\newcount\c_pack_combinations_y % global -\newcount\c_pack_combinations_max % global - -\newdimen\d_pack_combinations_ht % global - -\newbox \b_pack_combinations_captions % global % can go -\newbox \b_pack_combinations_temp % global % can go -\newbox \b_pack_combinations_content % local -\newbox \b_pack_combinations_caption % local - -\installcorenamespace{combination} - -\installcommandhandler \??combination {combination} \??combination - -\initializeboxstack{\??combination captions} -\initializeboxstack{\??combination temp} - -\newcount\c_pack_combinations_x_saved -\newcount\c_pack_combinations_y_saved -\newcount\c_pack_combinations_max_saved - -\newdimen\d_pack_combinations_ht_saved - -\newbox \b_pack_combinations_captions_saved -\newbox \b_pack_combinations_temp_saved -\newbox \b_pack_combinations_content_saved -\newbox \b_pack_combinations_caption_saved - -\setfalse\c_strc_constructions_define_commands - -\def\pack_combinations_push - {\advance\c_pack_combinations_nesting\plusone - \ifnum\c_pack_combinations_nesting>\plusone - \c_pack_combinations_x_saved \c_pack_combinations_x - \c_pack_combinations_y_saved \c_pack_combinations_y - \c_pack_combinations_max_saved\c_pack_combinations_max - \d_pack_combinations_ht_saved \d_pack_combinations_ht - \setbox\b_pack_combinations_captions_saved\box\b_pack_combinations_captions - \setbox\b_pack_combinations_temp_saved \box\b_pack_combinations_temp - \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content - \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption - \else - \globalsetsystemmode{combination}% why global - \fi} - -\def\pack_combinations_pop - {\ifnum\c_pack_combinations_nesting>\plusone - \global\c_pack_combinations_x \c_pack_combinations_x_saved - \global\c_pack_combinations_y \c_pack_combinations_y_saved - \global\c_pack_combinations_max\c_pack_combinations_max_saved - \global\d_pack_combinations_ht \d_pack_combinations_ht_saved - \global\setbox\b_pack_combinations_captions\box\b_pack_combinations_captions_saved - \global\setbox\b_pack_combinations_temp \box\b_pack_combinations_temp_saved - \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved - \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved - \else - \globalresetsystemmode{combination}% why global - \fi - \advance\c_pack_combinations_nesting\minusone} - -\definelabel - [\v!combination] % handy for configuring - [\c!numberconversion=\v!character, - \c!text=] - -\settrue\c_strc_constructions_define_commands - -\setupcombination - [\c!width=\v!fit, - \c!height=\v!fit, - \c!distance=\emwidth, - \c!location=\v!bottom, % can be something {top,left} - \c!before=\blank, - \c!after=, - \c!inbetween={\blank[\v!medium]}, - %\c!style=, - %\c!color=, - \c!nx=2, % new - \c!ny=1, % new - \c!align=\v!middle] - -\let\setupcombinations\setupcombination % for the moment (we might distinguish) - -\installcorenamespace{combinationlocation} -\installcorenamespace{combinationalternative} - -\appendtoks - \setfalse\c_strc_constructions_define_commands - \normalexpanded - {\definelabel - [\v!combination:\currentcombination]% - [\v!combination\ifempty\currentcombinationparent\else:\currentcombinationparent\fi]}% - [\s!counter=\currentcombination,\c!levels=1]% - \settrue\c_strc_constructions_define_commands -\to \everydefinecombination - -\setvalue{\??combinationlocation\v!left }{\let\m_pack_combinations_leftfiller\relax} -\setvalue{\??combinationlocation\v!right }{\let\m_pack_combinations_rightfiller\relax} -\setvalue{\??combinationlocation\v!top }{\let\m_pack_combinations_valigner\depthonlybox} -\setvalue{\??combinationlocation\v!middle}{\let\m_pack_combinations_valigner\halfwaybox} - -\def\pack_combinations_location_reset - {\let\m_pack_combinations_rightfiller\hfil - \let\m_pack_combinations_leftfiller \hfil - \let\m_pack_combinations_valigner \firstofoneargument} - -\pack_combinations_location_reset - -\def\pack_combinations_location_step#1% - {\csname\??combinationlocation#1\endcsname} - -% formally ok: -% -% \protected\def\stopcombination -% {\egroup -% \egroup} -% -% more robust: -% -% \protected\def\stopcombination -% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries -% \egroup -% \egroup} -% -% even better: -% -% \protected\def\stopcombination -% {\bgroup -% \scratchtoks{{}}% -% \dorecurse\c_pack_combinations_y -% {\toksapp{{}{}}}% -% \expandafter\egroup\the\scratchtoks -% \egroup -% \dostoptagged -% \egroup} -% -% faster - -\protected\def\pack_common_content_start{\bgroup\ignorespaces} -\protected\def\pack_common_content_stop {\removeunwantedspaces\egroup} -\protected\def\pack_common_caption_start{\bgroup\ignorespaces} -\protected\def\pack_common_caption_stop {\removeunwantedspaces\egroup} - -\newtoks\everycombination - -\protected\def\stopcombination - {\bgroup\normalexpanded{\egroup{}\ntimes{{}{}}\c_pack_combinations_y}% brr - \dostoptagged - \egroup - \pack_combinations_pop - \egroup} - -\permanent\tolerant\protected\def\startcombination[#1]#*[#2]% can be simplified - {\bgroup % so we can grab a group - \pack_combinations_push - \edef\currentcombination{#1}% - \edef\currentcombinationspec{#2}% - \ifempty\currentcombinationspec - \ifcondition\validassignment{#1}% - \let\currentcombination\empty - \setupcurrentcombination[#1]% - \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% - \else - \doifelseinstring{*}\currentcombination - {\edef\currentcombinationspec{\currentcombination*\plusone*}% - \let\currentcombination\empty} - {\doifelsenumber\currentcombination - {\edef\currentcombinationspec{\currentcombination*\plusone*}% - \let\currentcombination\empty} - {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}% - \fi - \else - \ifcondition\validassignment{#2}% - \setupcurrentcombination[#2]% - \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% - \else - \edef\currentcombinationspec{\currentcombinationspec*\plusone*}% - \fi - \fi - % - \forgetall - % - \the\everycombination - % - \let\startcontent\pack_common_content_start - \let\stopcontent \pack_common_content_stop - \let\startcaption\pack_common_caption_start - \let\stopcaption \pack_common_caption_stop - % - \edef\p_height {\combinationparameter\c!height}% - \edef\p_width {\combinationparameter\c!width}% - \edef\p_location{\combinationparameter\c!location}% - \edef\p_distance{\combinationparameter\c!distance}% - % - \pack_combinations_location_reset - \rawprocesscommacommand[\p_location]\pack_combinations_location_step - % - \dostarttaggedchained\t!combination\currentcombination\??combination - \vbox \ifx\p_height\v!fit\else to \p_height \fi \bgroup - \let\combination\empty % permits \combination{}{} handy for cld - \normalexpanded{\pack_combinations_start_indeed[\currentcombinationspec]}} - -\let\pack_combinations_check_x_y\relax - -\protected\def\pack_combinations_start_indeed[#1*#2*#3]% - {\global\c_pack_combinations_x#1\relax - \global\c_pack_combinations_y#2\relax - \setexpandedcombinationparameter\c!nx{\the\c_pack_combinations_x}% in case we access it - \setexpandedcombinationparameter\c!ny{\the\c_pack_combinations_y}% in case we access it - \pack_combinations_check_x_y - \dotagcombination - \global\setbox\b_pack_combinations_captions\emptybox - \global\c_pack_combinations_max\c_pack_combinations_x - \multiply\c_pack_combinations_y\c_pack_combinations_x - \tabskip\zeropoint - \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup % repetitive preamble - \aligntab - \m_pack_combinations_leftfiller - \alignmark\alignmark - \m_pack_combinations_rightfiller - \aligntab - \tabskip\zeropoint \s!plus 1fill % \fillskip - \alignmark\alignmark - \cr - \pack_combinations_pickup} - -%D I've first considered using a constructor directly but it's more overhead and -%D some settings conflict with already used combination settings so instead we plug -%D in labels. This also permits extensions later on. - -\appendtoks - \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}% -\to \everydefinecombination - -\def\pack_combinations_pickup - {\dostarttagged\t!combinationpair\empty % better make this text - \dostarttagged\t!combinationcontent\empty - \assumelongusagecs\pack_combinations_pickup_content_indeed} - -\def\pack_combinations_pickup_content_indeed - {\dowithnextboxcs\pack_combinations_pickup_content\hbox} - -\def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box - {\dostoptagged - \setbox\b_pack_combinations_content\box\nextbox - \dostarttagged\t!combinationcaption\empty - \expandnamespacemacro\??combinationalternative\p_pack_combinations_alternative\v!text} - -\setvalue{\??combinationalternative\v!text}% - {\assumelongusagecs\pack_combinations_alternative_text_indeed} - -\setvalue{\??combinationalternative\v!label}% - {\assumelongusagecs\pack_combinations_alternative_label_indeed} - -\def\pack_combinations_alternative_text_indeed - {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup - \afterassignment\pack_combinations_caption_first - \let\nexttoken=} - -\def\pack_combinations_alternative_label_indeed - {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup - \hsize\wd\b_pack_combinations_content - \usealignparameter\combinationparameter - \usecombinationstyleandcolor\c!style\c!color - \begstrut - \normalexpanded{\strc_labels_command[\v!combination\ifempty\currentcombination\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\ifempty\currentcombination\else:\currentcombination\fi}{1}}% - \fi - \fi -\to \everycombination - -\def\pack_combinations_pickup_caption - {\dostoptagged - \dostoptagged - \setbox\b_pack_combinations_caption\box\nextbox - \pack_combinations_pickup_package_pair} - -\def\pack_combinations_caption_first - {\futurelet\nexttoken\pack_combinations_caption_second} - -\def\pack_combinations_caption_second - {\ifx\nexttoken\egroup - % the caption is empty - \orelse\ifx\nexttoken\stopcaption - % the caption is empty (new per 2014-05-24) - \else - % todo: \p_pack_combinations_alternative\v!none: no style, strut etc - \hsize\wd\b_pack_combinations_content - \usealignparameter\combinationparameter - \usecombinationstyleandcolor\c!style\c!color - \bgroup - \aftergroup\endstrut - \aftergroup\egroup - \begstrut - \fi} - -\def\pack_combinations_pickup_package_pair % we need to store the caption row - {\vbox - {\forgetall - \m_pack_combinations_valigner{\box\b_pack_combinations_content}% - % we need to save the caption for a next alignment line - \pack_combinations_save_caption}% - \ifnum\c_pack_combinations_y>\plusone - \global\advance\c_pack_combinations_y\minusone - \global\advance\c_pack_combinations_x\minusone - \ifcase\c_pack_combinations_x - \doubleexpandafter\pack_combinations_pickup_package_pair_a - \else - \doubleexpandafter\pack_combinations_pickup_package_pair_b - \fi - \else - \singleexpandafter\pack_combinations_pickup_package_pair_c - \fi} - -\def\pack_combinations_pickup_package_pair_a - {\cr - \pack_combinations_flush_captions - \noalign - {\forgetall - \global\setbox\b_pack_combinations_captions\emptybox - \nointerlineskip - \combinationparameter\c!after - \combinationparameter\c!before - \vss - \nointerlineskip}% - \global\c_pack_combinations_x\c_pack_combinations_max - \pack_combinations_pickup} - -\def\pack_combinations_pickup_package_pair_b - {\aligntab - \aligntab - \aligntab - \kern\p_distance - \aligntab - \pack_combinations_pickup} - -\def\pack_combinations_pickup_package_pair_c - {\cr - \pack_combinations_flush_captions - \egroup} - -\installcorenamespace{combinationcaption} - -\def\pack_combinations_save_caption - {\ifdim\htdp\b_pack_combinations_caption>\d_pack_combinations_ht - \global\d_pack_combinations_ht\htdp\b_pack_combinations_caption - \fi - \savebox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}{\box\b_pack_combinations_caption}} - -\def\pack_combinations_flush_captions - {\noalign - {\ifdim\d_pack_combinations_ht>\zeropoint - \nointerlineskip % indeed - \combinationparameter\c!inbetween - \global\c_pack_combinations_x\c_pack_combinations_max - \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes - \else - \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop - \fi}% - \pack_combinations_flush_captions_indeed - \crcr} - -\def\pack_combinations_flush_captions_yes - {\vpack to \d_pack_combinations_ht\bgroup - \foundbox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}% - \vss - \egroup - \global\advance\c_pack_combinations_x\minusone - \ifnum\c_pack_combinations_x>\zerocount % \c_pack_combinations_max - \expandafter\pack_combinations_flush_captions_yes_followup - \else - \global\d_pack_combinations_ht\zeropoint - \initializeboxstack{\??combinationcaption:\number-\c_pack_combinations_nesting}% - \fi} - -\let\pack_combinations_flush_captions_nop\donothing - -\def\pack_combinations_flush_captions_yes_followup - {\aligntab - \aligntab - \aligntab - \aligntab - \pack_combinations_flush_captions_indeed} - -%D \macros -%D {startfloatcombination} -%D -%D \setupexternalfigures[directory={../sample}] -%D \startbuffer -%D \placefigure -%D [left,none] -%D {} -%D {\startfloatcombination[2*2] -%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]} -%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]} -%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]} -%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]} -%D \stopfloatcombination} -%D -%D \input tufte -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\protected\def\pack_combinations_float_hack_a#1% - {\strc_floats_build_box_separate_split{#1}% - \box\b_strc_floats_separate_content} - -\protected\def\pack_combinations_float_hack_b#1% - {\box\b_strc_floats_separate_caption} - -\permanent\tolerant\protected\def\startfloatcombination[#1]#*[#2]% - {\ifinsidefloat\else\dontleavehmode\fi % tricky, floatcombinations fail to align well otherwise - \vbox\bgroup - \strc_floats_build_box_separate_set - %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature - \postcenterfloatmethod\zerocount - \forcelocalfloats - \protected\def\stopfloatcombination{\pack_combinations_stop_float{#1}}} - -\let\stopfloatcombination\relax - -\def\pack_combinations_float_check_x_y - {\ifnum\numexpr\c_pack_combinations_x*\c_pack_combinations_y\relax<\noflocalfloats\relax - \global\c_pack_combinations_x\noflocalfloats - \global\c_pack_combinations_y\plusone - \fi - \let\pack_combinations_check_x_y\relax}% - -\def\pack_combinations_stop_float#1% - {\scratchtoks\emptytoks - \dorecurse\noflocalfloats - {\appendetoks - {\pack_combinations_float_hack_a{\recurselevel}}% - {\pack_combinations_float_hack_b{\recurselevel}}% - \to\scratchtoks}% brrr - \let\pack_combinations_check_x_y\pack_combinations_float_check_x_y - \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination - \resetlocalfloats - \egroup} - -%D \macros -%D {definepairedbox, setuppairedbox, placepairedbox} -%D -%D Paired boxes, formally called legends, but from now on a legend is just an -%D instance, are primarily meant for typesetting some text alongside an -%D illustration. Although there is quite some variation possible, the functionality -%D is kept simple, if only because in most cases such pairs are typeset sober. -%D -%D The location specification accepts a pair, where the first keyword specifies the -%D arrangement, and the second one the alignment. The first key of the location pair -%D is one of \type {left}, \type {right}, \type {top} or \type {bottom}, while the -%D second key can also be \type {middle}. -%D -%D The first box is just collected in an horizontal box, but the second one is a -%D vertical box that gets passed the bodyfont and alignment settings. -%D -%D In many cases the table builders can be used instead, but as this mechanism is a -%D traditional \CONTEXT\ one we keep it around. - -%D \macros -%D {setuplegend, placelegend} -%D -%D It makes sense to typeset a legend to a figure in \TEX\ and not in a drawing -%D package. The macro \type {\placelegend} combines a figure (or something else) and -%D its legend. This command is just a paired box. -%D -%D The legend is placed according to \type {location}, being \type {bottom} or \type -%D {right}. The macro macro is used as follows. -%D -%D \starttyping -%D \placefigure -%D {whow} -%D {\placelegend -%D {\externalfigure[cow]} -%D {\starttabulate -%D \NC 1 \NC head \NC \NR -%D \NC 2 \NC legs \NC \NR -%D \NC 3 \NC tail \NC \NR -%D \stoptabulate}} -%D -%D \placefigure -%D {whow} -%D {\placelegend -%D {\externalfigure[cow]} -%D {\starttabulate[|l|l|l|l|] -%D \NC 1 \NC head \NC 3 \NC tail \NC \NR -%D \NC 2 \NC legs \NC \NC \NC \NR -%D \stoptabulate}} -%D -%D \placefigure -%D {whow} -%D {\placelegend[n=2] -%D {\externalfigure[cow]} -%D {\starttabulate -%D \NC 1 \NC head \NC \NR -%D \NC 2 \NC legs \NC \NR -%D \NC 3 \NC tail \NC \NR -%D \stoptabulate}} -%D -%D \placefigure -%D {whow} -%D {\placelegend[n=2] -%D {\externalfigure[cow]} -%D {head \par legs \par tail}} -%D -%D \placefigure -%D {whow} -%D {\placelegend[n=2] -%D {\externalfigure[cow]} -%D {\startitemize[packed] -%D \item head \item legs \item tail \item belly \item horns -%D \stopitemize}} -%D -%D \placefigure -%D {whow} -%D {\placelegend[n=2,width=.8\hsize] -%D {\externalfigure[cow]} -%D {\startitemize[packed] -%D \item head \item legs \item tail \item belly \item horns -%D \stopitemize}} -%D -%D \def\MytTestTwo#1#2% -%D {\placefigure -%D {whow} -%D {\placelegend[location={#1,#2}] -%D {\externalfigure[cow]} -%D {\starttabulate -%D \NC 1 \NC head \NC \NR -%D \NC 2 \NC legs \NC \NR -%D \NC 3 \NC tail \NC \NR -%D \stoptabulate}}} -%D -%D \def\MytTestOne#1{\processcommalist[left,right,top,bottom]{\MytTestTwo{#1}}} -%D -%D \processcommalist[left,right,top,bottom,middle]\MytTestOne -%D \stoptyping -%D -%D More structure is also possible (the order matters!): -%D -%D \starttyping -%D \startplacefigure[title=whow] -%D \startplacelegend[location={bottom,middle},color=red] -%D \startcontent -%D \externalfigure[cow] -%D \stopcontent -%D \startcaption -%D \starttabulate[|l|l|] -%D \NC 1 \NC head \NC \NR -%D \NC 2 \NC legs \NC \NR -%D \NC 3 \NC tail \NC \NR -%D \stoptabulate -%D \stopcaption -%D \stopplacelegend -%D \stopplacefigure -%D \stoptyping - -% todo: natural size - -\newsystemmode{pairedbox} - -\appendtoks - \globalresetsystemmode{pairedbox}% -\to \everyinsidefloat - -\installcorenamespace {pairedbox} - -\installcommandhandler \??pairedbox {pairedbox} \??pairedbox - -\setuppairedbox - [\c!n=1, - \c!distance=\bodyfontsize, - %\c!before=, - %\c!after=, - %\c!color=, - %\c!style=, - \c!inbetween={\blank[\v!medium]}, - \c!width=\hsize, - \c!height=\vsize, - \c!maxwidth=\textwidth, % \makeupwidth, - \c!maxheight=\textheight, % \makeupheight, - %\c!bodyfont=, - %\c!align=, - \c!location=\v!bottom] - -% watch the hsize/vsize tricks - -\newbox \b_pack_pairedboxes_first -\newbox \b_pack_pairedboxes_second -\newdimen\s_pack_pairedboxes_size - -\appendtoks - \setuevalue{\e!setup\currentpairedbox\e!endsetup}{\setuppairedbox [\currentpairedbox]}% - \setuevalue{\e!place\currentpairedbox }{\placepairedbox [\currentpairedbox]}% one argument is mandate anyway - \setuevalue{\e!start\e!place\currentpairedbox }{\startplacepairedbox[\currentpairedbox]}% one argument is mandate anyway - \setuevalue{\e!stop\e!place \currentpairedbox }{\stopplacepairedbox }% -\to \everydefinepairedbox - -\permanent\tolerant\protected\def\startplacepairedbox[#1]#*[#2]% - {\bgroup - \edef\currentpairedbox{#1}% - \setupcurrentpairedbox[#2]% - \pairedboxparameter\c!before - \bgroup - \edef\p_location{\pairedboxparameter\c!location}% - \edef\p_n {\pairedboxparameter\c!n}% - % - \let\startcontent\pack_common_content_start - \let\stopcontent \pack_common_content_stop - \let\startcaption\pack_common_caption_start - \let\stopcaption \pack_common_caption_stop - % - \globalsetsystemmode{pairedbox}% - \pack_pairedboxes_before - \assumelongusagecs\pack_pairedboxes_first_pickup} - -\permanent\protected\def\stopplacepairedbox{} % we just pick up two boxes - -\let\placepairedbox\startplacepairedbox % we just pick up two boxes - -\def\pack_pairedboxes_first_pickup - {\dowithnextboxcs\pack_pairedboxes_first\hbox - \bgroup - \let\next=} - -\def\pack_pairedboxes_first - {\pack_pairedboxes_between - \assumelongusagecs\pack_pairedboxes_second_pickup} - -\def\pack_pairedboxes_second_pickup - {\dowithnextboxcs\pack_pairedboxes_second\vbox - \bgroup - \pack_pairedboxes_inside_second - \let\next=} - -\def\pack_pairedboxes_second - {\pack_pairedboxes_after - \egroup - \pairedboxparameter\c!after - \egroup} - -\newconditional\c_pack_pairedboxes_horizontal \settrue\c_pack_pairedboxes_horizontal - -\installcorenamespace{pairedboxnature} -\installcorenamespace{pairedboxalign} - -\let\pack_pairedboxes_fill_top \relax -\let\pack_pairedboxes_fill_bottom\relax - -\setvalue{\??pairedboxnature\v!left}% - {\settrue\c_pack_pairedboxes_horizontal - \let\pack_pairedboxes_flush\pack_pairedboxes_flush_left} - -\setvalue{\??pairedboxnature\v!right}% - {\settrue\c_pack_pairedboxes_horizontal - \let\pack_pairedboxes_flush\pack_pairedboxes_flush_right} - -\setvalue{\??pairedboxnature\v!top}% - {\setfalse\c_pack_pairedboxes_horizontal - \let\pack_pairedboxes_fill_top\relax - \let\pack_pairedboxes_fill_bottom\vss - \let\pack_pairedboxes_flush\pack_pairedboxes_flush_top} - -\setvalue{\??pairedboxnature\v!bottom}% - {\setfalse\c_pack_pairedboxes_horizontal - \let\pack_pairedboxes_fill_top\vss - \let\pack_pairedboxes_fill_bottom\relax - \let\pack_pairedboxes_flush\pack_pairedboxes_flush_bottom} - -\def\pack_pairedboxes_flush_left - {\box\b_pack_pairedboxes_second - \kern\pairedboxparameter\c!distance - \box\b_pack_pairedboxes_first} - -\def\pack_pairedboxes_flush_right - {\box\b_pack_pairedboxes_first - \kern\pairedboxparameter\c!distance - \box\b_pack_pairedboxes_second} - -\def\pack_pairedboxes_flush_top - {\box\b_pack_pairedboxes_second - \endgraf - \nointerlineskip - \pairedboxparameter\c!inbetween - \box\b_pack_pairedboxes_first} - -\def\pack_pairedboxes_flush_bottom - {\box\b_pack_pairedboxes_first - \endgraf - \nointerlineskip - \pairedboxparameter\c!inbetween - \box\b_pack_pairedboxes_second} - -\setvalue{\??pairedboxalign\v!left}% 0 - {\let\pack_pairedboxes_align_l\relax - \let\pack_pairedboxes_align_r\hss - \let\pack_pairedboxes_align_t\relax - \let\pack_pairedboxes_align_b\relax} - -\setvalue{\??pairedboxalign\v!right}% 1 - {\let\pack_pairedboxes_align_l\hss - \let\pack_pairedboxes_align_r\relax - \let\pack_pairedboxes_align_t\relax - \let\pack_pairedboxes_align_b\relax} - -\setvalue{\??pairedboxalign\v!high}% 2 - {\let\pack_pairedboxes_align_l\relax - \let\pack_pairedboxes_align_r\relax - \let\pack_pairedboxes_align_t\relax - \let\pack_pairedboxes_align_b\vss} - -\setvalue{\??pairedboxalign\v!low}% 3 - {\let\pack_pairedboxes_align_l\relax - \let\pack_pairedboxes_align_r\relax - \let\pack_pairedboxes_align_t\vss - \let\pack_pairedboxes_align_b\relax} - -\setvalue{\??pairedboxalign\v!middle}% 4 - {\let\pack_pairedboxes_align_l\hss - \let\pack_pairedboxes_align_r\hss - \let\pack_pairedboxes_align_t\vss - \let\pack_pairedboxes_align_b\vss} - -\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }} -\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}} - -\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}} -\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}} - -\def\pack_pairedboxes_before - {\ifempty\p_location - \csname\??pairedboxnature\v!left \endcsname - \csname\??pairedboxalign \v!middle\endcsname - \else - \getfromcommacommand[\p_location][1]% - \csname\??pairedboxnature - \ifcsname\??pairedboxnature\commalistelement\endcsname\commalistelement\else\v!left\fi - \endcsname - \getfromcommacommand[\p_location][2]% - \csname\??pairedboxalign - \ifcsname\??pairedboxalign\commalistelement\endcsname\commalistelement\else\v!middle\fi - \endcsname - \fi} - -\def\pack_pairedboxes_between - {\usebodyfontparameter\pairedboxparameter - \setbox\b_pack_pairedboxes_first\box\nextbox - \ifconditional\c_pack_pairedboxes_horizontal - \pack_pairedboxes_between_horizontal - \else - \pack_pairedboxes_between_vertical - \fi - \ifnum\p_n>\plusone - \setrigidcolumnhsize\hsize{\pairedboxparameter\c!distance}\p_n - \fi} - -\def\pack_pairedboxes_between_horizontal - {\scratchdistance\pairedboxparameter\c!distance - \scratchwidth\pairedboxparameter\c!maxwidth\relax - \setlocalhsize - \hsize\dimexpr\availablehsize-\wd\b_pack_pairedboxes_first-\scratchdistance\relax - \hsize\pairedboxparameter\c!width\relax % can be \hsize - \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\scratchdistance\relax - \ifdim\dimexpr\hsize+\scratchdimen\relax>\scratchwidth - \hsize\dimexpr\scratchwidth-\scratchdimen\relax - \fi} - -\def\pack_pairedboxes_between_vertical - {\scratchwidth\pairedboxparameter\c!maxwidth\relax - \hsize\wd\b_pack_pairedboxes_first - \hsize\pairedboxparameter\c!width\relax % can be \hsize - \ifdim\hsize>\scratchwidth\relax - \hsize\scratchwidth - \fi} - -\def\pack_pairedboxes_after - {\setbox\b_pack_pairedboxes_second\vpack - {\ifnum\p_n>\plusone - \rigidcolumnbalance\nextbox - \else - \box\nextbox - \fi}% - \ifconditional\c_pack_pairedboxes_horizontal - \pack_pairedboxes_pack_horizontal - \else - \pack_pairedboxes_pack_vertical - \fi} - -\def\pack_pairedboxes_pack_horizontal - {\dontleavehmode\hbox\bgroup - \forgetall - \s_pack_pairedboxes_size\ht - \ifdim\ht\b_pack_pairedboxes_first>\ht\b_pack_pairedboxes_second - \b_pack_pairedboxes_first - \else - \b_pack_pairedboxes_second - \fi - \vsize\s_pack_pairedboxes_size - \ifdim\s_pack_pairedboxes_size<\pairedboxparameter\c!height\relax % can be \vsize - \s_pack_pairedboxes_size\pairedboxparameter\c!height - \fi - \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax - \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight - \fi - \pack_pairedbox_valign\b_pack_pairedboxes_first - \pack_pairedbox_valign\b_pack_pairedboxes_second - \pack_pairedboxes_flush - \egroup} - -\def\pack_pairedboxes_pack_vertical - {\dontleavehmode\vpack\bgroup - \forgetall - \s_pack_pairedboxes_size\wd - \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second - \b_pack_pairedboxes_first - \else - \b_pack_pairedboxes_second - \fi - \pack_pairedbox_halign\b_pack_pairedboxes_first - \pack_pairedbox_halign\b_pack_pairedboxes_second - \s_pack_pairedboxes_size\ht\b_pack_pairedboxes_second - \vsize\s_pack_pairedboxes_size - \ifdim\ht\b_pack_pairedboxes_second<\pairedboxparameter\c!height\relax % can be \vsize - \s_pack_pairedboxes_size\pairedboxparameter\c!height\relax % \relax needed - \fi - \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax % todo: totale hoogte - \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed - \fi - \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second - \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size - {\pack_pairedboxes_fill_top - \box\b_pack_pairedboxes_second - \pack_pairedboxes_fill_bottom}% \kern\zeropoint - \fi - \pack_pairedboxes_flush - \egroup} - -\def\pack_pairedboxes_inside_second - {\forgetall - \setupalign[\pairedboxparameter\c!align]% - \usepairedboxstyleandcolor\c!style\c!color - \tolerantTABLEbreaktrue % hm. - \blank[\v!disable]% use fast one - \everypar{\begstrut}} % also flushers here (see bTABLE) - -\definepairedbox[\v!legend] - -\permanent\protected\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox} -\permanent\protected\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox} - -\def\pack_topofeachother_one{\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox} -\def\pack_sidebyside_one {\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox} - -\def\pack_topofeachother_two{\setbox\scratchboxtwo\box\nextbox - \halign{\hss\alignmark\alignmark\hss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% - \egroup\egroup} -\def\pack_sidebyside_two {\setbox\scratchboxtwo\box\nextbox - \valign{\vss\alignmark\alignmark\vss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% - \egroup\egroup} - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-lyr.mkxl b/tex/context/base/mkiv/pack-lyr.mkxl deleted file mode 100644 index 366eeff75..000000000 --- a/tex/context/base/mkiv/pack-lyr.mkxl +++ /dev/null @@ -1,772 +0,0 @@ -%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 the output routine, but -%D future extensions may depend on a more close cooperation. -%D -%D First we overload a macro from \type {pack-rul}. From now on we accept a -%D (optional) argument: the specific layer it will go in. This means that we can -%D move an overlay from one background to the other using the dimensions of the -%D parent. - -\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi - -\pushoverloadmode - -\permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#2]#*[#3]% overlay [layer] content - {\ifnum\lastarguments=\plusthree - %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp - \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}% - \else - \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% - \fi - \processcommalist[#1]\pack_framed_define_overlay_indeed} - -\popoverloadmode - -%D We use the command handler code. The previous, more direct parameter handling was -%D 25\% faster when no parameters were passed when adding content to a layer. -%D However, when we pass for instance a preset, the new methos is some 10\% faster -%D and it happens that in most cases we do pass some parameters. It would be -%D interesting to see if we can push the preset in between the regular chain but it -%D could also lead to 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 the data that goes -%D into a layer, is typeset immediately. Each layer automatically gets an associated -%D overlay, which can be used in any background assignment. -%D -%D After a layer is defined, you can change its 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 \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode - -\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 needed anyway). - -\def\pack_layers_reset_box#1% - {\ifcsname\??layerbox#1\endcsname - %\global\setbox\csname\??layerbox#1\endcsname\emptybox - \global\setbox\lastnamedcs\emptybox - \fi} - -\permanent\protected\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 \type {position} is -%D set, relative positioning is used, with the current point as reference point. -%D Otherwise the topleft corner is used as reference point. -%D -%D \starttyping -%D \setlayer [identifier] [optional parameters] {data} -%D \stoptyping - -\permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right - {\edef\currentlayerwidth {\thelayerwidth {#2#1}}% - \edef\currentlayerheight{\thelayerheight{#2#1}}} - -\permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi} -\permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi} - -\permanent\tolerant\protected\def\setlayer[#1]#*[#2]#*[#3]% #4 == box do \fi is ok - {\bgroup - \nofarguments\lastarguments - \checkpositionoverlays % otherwise funny regions - \edef\currentlayer{#1}% - \edef\p_pack_layers_state{\layerparameter\c!state}% - \ifx\p_pack_layers_state\v!stop - \dowithnextboxcs\egroup\hbox % no pack ? - \orelse\ifnum\nofarguments=\plusthree - \edef\m_pack_layers_target{#2}% - \pack_layers_set_indeed{#3}% - \orelse\ifhastok={#2}% - \let\m_pack_layers_target\empty - \pack_layers_set_indeed{#2}% - \else - \edef\m_pack_layers_target{#2}% - \pack_layers_set_indeed\empty - \fi} - -\def\pack_layers_set_indeed#1% - {\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 - \dowithnextbox{\pack_layers_set_finish{#1}}\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 - \orelse\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 - \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}% wrong one - \edef\m_pack_layers_region{\layerparameter\c!region}% - \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{layering}{region: \m_pack_layers_region=>\MPxywhd\m_pack_layers_region}% - % \writestatus {}{anchor: \m_pack_layers_anchor=>\MPxywhd\m_pack_layers_anchor}% - % \writestatus {}{offset: \c!dx,\c!dy =>\lastlayerxpos,\lastlayerypos}% - \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 - \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 - \glet\lastlayerxpos\!!zeropoint - \glet\lastlayerypos\!!zeropoint - \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions - \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions - \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions - \edef\m_pack_layers_page{\layerparameter\c!page}} - -\permanent\tolerant\protected\def\definelayerpreset[#1]#*[#2]% - {\ifarguments - \or - \letvalue{\??layerpreset#1}\empty - \orelse\ifhastok={#2}% - \setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}% - \else - \setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}% - \fi} - -\def\pack_layers_set_content#1% - {\layerwidth \layerparameter\c!width % global (local later) - \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 - \ifempty\p_pack_layers_rotation \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 - \ifx\p_pack_layers_position\v!yes - \pack_layers_set_last_position_yes - \else - \pack_layers_set_last_position_nop - \fi - % - \ifempty\m_pack_layers_page \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 - % or maybe instead of the \vskip - % \raise-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_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 not even that -%D complicated. It mainly comes down to skipping to the right place and placing a -%D box on top of or below the existing content. In the case of position tracking, -%D another reference point is chosen. - -%D \macros -%D {doifelselayerdata} - -\permanent\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 page dependent one -%D (when defined). This feature is more efficient in \ETEX\ since there testing for -%D an undefined macro does not takes hash space. - -% todo: setups before flush, handy hook - -\permanent\protected\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 - \orelse\ifx\p_pack_layers_state\v!next - \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up - \orelse\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 - \endgroup} - -% optimized - -\def\pack_layers_flush_single - {\ifcsname\??layerbox\currentlayer\endcsname - \ifvoid\lastnamedcs - \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname - \ifvoid\lastnamedcs\else - \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two - \fi - \fi - \else - \chardef\b_layer_one\lastnamedcs - \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname - \ifvoid\lastnamedcs\else - \chardef\b_layer_two\lastnamedcs - \startoverlay - {\pack_layers_flush_indeed\plusone \currentlayer \b_layer_one}% - {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}% - \stopoverlay - \fi - \else - \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one - \fi - \fi - \orelse\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname - \ifvoid\lastnamedcs - % nothing - \else - \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two - \fi - \fi} - -% less optimized: - -\def\pack_layers_flush_double#1% - {\startoverlay - {\ifcsname\??layerbox\currentlayer\endcsname - \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two - \fi - \fi}% - {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname - \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two - \fi - \fi}% - {\ifcsname\??layerbox#1\currentlayer\endcsname - \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two - \fi - \fi}% - {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname - \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs - \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two - \fi - \fi}% - \stopoverlay} - -\let\pack_layers_top_fill \relax -\let\pack_layers_bottom_fill\vss - -\def\pack_layers_flush_indeed#1#2#3% - {\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 - \orelse\ifx\p_pack_layers_state\v!repeat - \settrue\c_pack_layers_repeated - \else - \setfalse\c_pack_layers_repeated - \fi - \fi - \fi - %chardef\b_layers\csname\??layerbox#2\endcsname % trick - \let\b_layers#3% - % we need to copy in order to retain the negative offsets for a next - % stage of additions, i.e. llx/lly accumulate in repeat mode and the - % compensation may differ each flush depending on added content - \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 - % and maybe 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}% -% - \ifx\p_pack_layers_method\v!overlay \wd\nextbox\d_overlay_width\fi - \box\nextbox -% - \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}% - \ifempty\p_pack_layers_region\else - \anch_mark_tagged_box\nextbox\p_pack_layers_region % was \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 when we use it as -%D parameter. This name also suits better to other layering commands. - -\permanent\protected\def\composedlayer#1{\flushlayer[#1]} - -\permanent\protected\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 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 - -\def\MPlayerwidth {\hsize} -\def\MPlayerheight{\vsize} - -\permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[#3]% - {\edef\MPlayerwidth {\MPw{#2}}% - \edef\MPlayerheight{\MPh{#2}}% - \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]} - -\permanent\tolerant\protected\def\getMPlayer[#1]#*[#2]% - {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument - -%D Watch out, a redefinition: - -\ifdefined\settextpagecontent \else - \writestatus\m!system{error in page-lyr.tex} \wait -\fi - -\definelayer - [OTRTEXT] - -\setuplayer - [OTRTEXT] - [\c!width=\innermakeupwidth, - \c!height=\textheight] - -\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr - -\overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr - -\permanent\overloaded\protected\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/tex/context/base/mkiv/pack-mrl.mkxl b/tex/context/base/mkiv/pack-mrl.mkxl deleted file mode 100644 index edc581953..000000000 --- a/tex/context/base/mkiv/pack-mrl.mkxl +++ /dev/null @@ -1,850 +0,0 @@ -%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} \??blackrules - -\permanent\protected\def\blackrule - {\hpack\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 - \orelse\ifx\p_depth\v!max - \setstrut - \fi - \useblackrulesstyleandcolor\c!style\c!color - \ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname - \lastnamedcs - \else - \vrule - \fi - \ifx\p_width \v!max\s!width \emwidth\orelse\ifempty\p_width \else\s!width \p_width \fi - \ifx\p_height\v!max\s!height\strutht\orelse\ifempty\p_height\else\s!height\p_height\fi - \ifx\p_depth \v!max\s!depth \strutdp\orelse\ifempty\p_depth \else\s!depth \p_depth \fi - \egroup} - -\setupblackrules - [\c!width=\emwidth, - \c!height=\exheight, - \c!depth=\zeropoint, - \c!color=] - -%D \macros -%D {blackrules} -%D -%D One can call for a sequence of black rules, if needed 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. - -\permanent\tolerant\protected\def\blackrules[#1]% probably never used - {\hpack\bgroup - \ifarguments\or\setupcurrentblackrules[#1]\fi - \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 % why not just check distance - \ifnum\scratchcounter=\plusone - \scratchdistance\zeropoint - \else - \scratchwidth\dimexpr(\scratchwidth-\scratchcounter\scratchdistance+\scratchdistance)/\scratchcounter\relax - \fi - \fi - \useblackrulesstyleandcolor\c!style\c!color - % a typical case of where we can use a simple loop or even a leaders - \dorecurse\scratchcounter\pack_black_rules_step - \unskip - \egroup} - -\def\pack_black_rules_step - {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname - \lastnamedcs - \else - \vrule - \fi - \s!width \scratchwidth - \s!height\scratchheight - \s!depth \scratchdepth - \relax - \ifzeropt\scratchdistance\else - \hskip\scratchdistance - \fi} - -\installcorenamespace{blackruletype} - -\setvalue{\??blackruletype mp}% - {\frule - type {mp}% - data {\includeMPgraphic{\directblackrulesparameter\c!mp}} - line \dimexpr\directblackrulesparameter\c!rulethickness\relax - } - -\letvalue{\??blackruletype\s!no }\novrule -%letvalue{\??blackruletype\s!yes}\vrule - -\setupblackrules - [\c!n=3, - \c!rulethickness=\linewidth, - \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} - -\protected\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} - -\permanent\tolerant\protected\def\vl[#1]% - {\pack_rule_vl_indeed{#1}{#1}{#1}} - -\permanent\tolerant\protected\def\hl[#1]% - {\dontleavehmode - \hbox - {\vrule - \s!width #1\emwidth - \s!height\linewidth - \s!depth \zeropoint}} - -\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 - -\permanent\protected\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 - \ifzeropt\linewidth - \c_pack_thinrules_type\zerocount - \orelse\ifx\p_frame\v!on - \c_pack_thinrules_type\expandnamespaceparameter\??thinrulealternatives\directthinrulesparameter\c!alternative\v!b\relax - \else - \c_pack_thinrules_type\zerocount - \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} - -\permanent\protected\def\hairline % can be overloaded - {\endgraf - \thinrule - \endgraf} - -\permanent\tolerant\protected\def\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 - \ifempty\p_inbetween - \softbreak % \ifhmode \hskip \parfillskip \break \fi - \else - \endgraf - \nowhitespace - \p_inbetween - \fi - \fi}% - \fi - \fi - \ifempty\p_after - \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] - -% can be done nicer with futureexpandis - -\permanent\protected\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_yes{#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_yes#1% - {\noindent % this will force side floats to be calculated - \bgroup - \setbox\scratchbox\hpack to \availablehsize - {\scratchwidth \directtextrulesparameter\c!rulethickness\relax - \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax - \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax - \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 - \box\scratchbox - %\carryoverpar - \egroup} - -\def\pack_textrule_with_text_nop#1% - {\ifhmode - \endgraf - \fi - \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on - \pack_textrule_correct_depth_yes - \pack_textrule_correct_depth_nop - \nointerlineskip - \noindent\naturalvpack % was \dontleavehmode - {\color[\directtextrulesparameter\c!rulecolor] - {\hrule - \s!depth \directtextrulesparameter\c!rulethickness - \s!height\zeropoint - \s!width \availablehsize}}} - -\def\pack_textrule_correct_depth_yes - {\vskip\dimexpr - \strutdp +.5\exheight - \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} - \pack_textrule_with_text_nop - \pack_textrule_with_text_yes - {#1}% - \ifvmode - \prevdepth\zeropoint - \fi} - -%D The grouped commands also supports bodyfont switching: - -\permanent\protected\def\starttextrule#1% - {\bgroup - \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}% - \csname\??textrulealternatives\v!top\endcsname{#1}% - \bgroup - \usebodyfontparameter\directtextrulesparameter} - -\permanent\protected\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=] - -\permanent\tolerant\protected\def\fillinrules[#1]#:#=#*#=% - {\endgraf - \begingroup - \setupcurrentfillinrules[#1]% - \let\pack_fillinrules_rule\thinrules - \directfillinrulesparameter\c!before - \setupcurrentthinrules - [\c!n=\directfillinrulesparameter\c!n, - \c!interlinespace=\directfillinrulesparameter\c!interlinespace, - \c!before=, - \c!after=]% - \scratchdistance\directfillinrulesparameter\c!distance\relax - \noindent - \iftok{#2}\emptytoks\else - \edef\p_width{\directfillinrulesparameter\c!width}% - \ifx\p_width\v!fit - \scratchdistance\zeropoint - \hbox - \orelse\ifx\p_width\v!broad - \hbox - \else - \hbox to \directfillinrulesparameter\c!width - \fi - \bgroup - \usefillinrulesstyleandcolor\c!style\c!color - \strut - #2% - \hfill\directfillinrulesparameter\c!separator - \hskip\scratchdistance - \egroup - \fi - \setupwhitespace[\v!big]% - \ignorespaces - \pack_fillinrules_rule - \iftok{#3}\emptytoks\else - \kern\scratchdistance - \usefillinrulesstyleandcolor\c!style\c!color - #3% - \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} - -\permanent\tolerant\protected\def\fillintext[#1]#:#=#*#=% - {\endgraf - \begingroup - \setupcurrentfillinrules[#1]% - \def\pack_fillinrules_rule{\unhbox\nextbox\unskip}% - \dowithnextbox{\pack_fillinrules_indeed{#2}{\hfill#3}}% - \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 \fillinline \input reich \par -%D \fillinline[margin=0cm] \input reich \par -%D \stopbuffer -%D -%D \startexample -%D \getbuffer -%D \stopexample -%D -%D which was typeset by saying: -%D -%D \typebuffer -%D -%D The two commands that take care of this are: -%D -%D \showsetup{fillinline} -%D \showsetup{setupfillinlines} -%D -%D Contrary to older implementations we now use the wrapper. - -\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] - -\protected\def\pack_fillinline_before#1% - {} - -\protected\def\pack_fillinline_after#1% - {\begingroup - \setupcurrentfillinlines[#1]% - \ifhmode\unskip\hfill\fi - \scratchdistance\directfillinlinesparameter\c!distance - \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax - \scratchwidth \dimexpr\directfillinlinesparameter\c!width-\scratchdistance\relax - \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else - \expandafter\rlap - \fi - {\kern\scratchdistance - \blackrule - [\c!color=\directfillinlinesparameter\c!color, - \c!width=\scratchwidth, - \c!height=\scratchheight, - \c!depth=\scratchheight]}% - \frozen\advance\rightskip \directfillinlinesparameter\c!margin\relax - \frozen\parfillskip\zeropoint\relax - \endgroup} - -\permanent\tolerant\protected\def\fillinline[#1]% - {\registerparwrapper - {fillinline}% - {\pack_fillinline_before{#1}}% - {\pack_fillinline_after {#1}% - \unregisterparwrapper{fillinline}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-ori.lmt b/tex/context/base/mkiv/pack-ori.lmt deleted file mode 100644 index a786b19ef..000000000 --- a/tex/context/base/mkiv/pack-ori.lmt +++ /dev/null @@ -1,70 +0,0 @@ -if not modules then modules = { } end modules ['pack-ori'] = { - 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" -} - -local context = context -local implement = interfaces.implement -local variables = interfaces.variables - -local settings_to_array = utilities.parsers.settings_to_array - -local orientation = { - [variables.up] = 0x000, - [variables.left] = 0x001, - [variables.down] = 0x002, - [variables.right] = 0x003, - [variables.top] = 0x004, - [variables.bottom] = 0x005, -} -local vertical = { - [variables.line] = 0x000, - [variables.top] = 0x010, - [variables.bottom] = 0x020, - [variables.middle] = 0x030, -} -local horizontal = { - [variables.middle] = 0x000, - [variables.flushleft] = 0x100, - [variables.flushright] = 0x200, - [variables.left] = 0x300, - [variables.right] = 0x400, -} - -implement { - name = "toorientation", - public = true, - arguments = { - { - { "horizontal", "string" }, - { "vertical", "string" }, - { "orientation", "string" }, - } - }, - actions = function(t) - local n = 0 - local m = t.horizontal if m then n = n | (horizontal [m] or 0) end - local m = t.vertical if m then n = n | (vertical [m] or 0) end - local m = t.orientation if m then n = n | (orientation[m] or 0) end - -- logs.report("orientation","0x%03X : %s",n,table.sequenced(t)) - context(n) - end, -} - -implement { - name = "stringtoorientation", - public = true, - arguments = "string", - actions = function(s) - local n = 0 - local t = settings_to_array(s) - local m = t[1] if m then n = n | (horizontal [m] or 0) end - local m = t[2] if m then n = n | (vertical [m] or 0) end - local m = t[3] if m then n = n | (orientation[m] or 0) end - -- logs.report("orientation","0x%03X : %s",n,s) - context(n) - end, -} diff --git a/tex/context/base/mkiv/pack-ori.mkxl b/tex/context/base/mkiv/pack-ori.mkxl deleted file mode 100644 index 4365db3ac..000000000 --- a/tex/context/base/mkiv/pack-ori.mkxl +++ /dev/null @@ -1,97 +0,0 @@ -%D \module -%D [ file=pack-ori, % was experimental -%D version=2019.07.30, -%D title=\CONTEXT\ Packaging Macros, -%D subtitle=Anchoring, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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 / Anchoring} - -\registerctxluafile{pack-ori}{autosuffix} - -\unprotect - -%D Possible options are: -%D -%D \starttabulate[|T|T|] -%D \NC orientation \NC up left down right top bottom -%D \NC vertical \NC line top bottom middle -%D \NC horizontal \NC middle flushleft flushright left right -%D \stoptabulate - -\installcorenamespace{orientation} -\installcorenamespace{orientations} - -\installcommandhandler \??orientation {orientation} \??orientation - -\setuporientation - [\c!orientation=\v!normal, - \c!horizontal=\v!normal, - \c!vertical=\v!normal] - -\appendtoks - \expandafter\chardef\csname\??orientations\currentorientation\endcsname\toorientation - orientation {\orientationparameter\c!orientation} - horizontal {\orientationparameter\c!horizontal} - vertical {\orientationparameter\c!vertical} - \relax\relax -\to \everydefineorientation - -\defineorientation[\v!normal] - -\defineorientation[\v!up] [\c!orientation=\v!up] -\defineorientation[\v!down] [\c!orientation=\v!down] -\defineorientation[\v!left] [\c!orientation=\v!left] -\defineorientation[\v!right] [\c!orientation=\v!right] -\defineorientation[\v!top] [\c!orientation=\v!top] -\defineorientation[\v!bottom][\c!orientation=\v!bottom] - -%D There will be some more helpers here. - -\permanent\def\theorientation#1% - {\numexpr - \ifcsname\??orientations#1\endcsname - \lastnamedcs - \else - \zerocount - \fi - \relax} - -\permanent\def\autoorientation#1% - {\numexpr - \ifcsname\??orientations#1\endcsname - \lastnamedcs - \else - \auto_orientation{#1}% - \fi - \relax} - -%D The \type {\immediateassignment} and \type {\immediateassigned} primitives are -%D kind of obsolete and might be dropped (if not already) from \LUAMETATEX. Local -%D scanning is, although it is a bit slower, more general. We didn't really need and -%D use these primitives in \CONTEXT\ anyway, apart from some playing around with -%D some full expansion, which made no sense in the end so it was dropped. When -%D things get that hairy it's often a good reason to look into \LUA\ variants. - -\def\auto_orientation#1% - %{\immediateassignment\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}% % quite fast - {\beginlocalcontrol\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}\endlocalcontrol % good enough - %{\localcontrolled{\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}}% % a bit slower - \csname\??orientations#1\endcsname} - -\permanent\protected\def\doifelseorientation#1% - {\ifcsname\??orientations#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -% \def\iforientationcsname#1{\ifcsname\??orientations} - -\protect \endinput diff --git a/tex/context/base/mkiv/pack-rul.mkxl b/tex/context/base/mkiv/pack-rul.mkxl deleted file mode 100644 index c9383dff0..000000000 --- a/tex/context/base/mkiv/pack-rul.mkxl +++ /dev/null @@ -1,3014 +0,0 @@ -%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}{optimize} - -\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 - -\permanent\tolerant\protected\def\setuplinewidth[#1]% - {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}} - -%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 - {\enforced\let\framedparameter \pack_framed_framedparameter - \enforced\let\framedparameterhash\pack_framed_framedparameterhash - \enforced\let\setupcurrentframed \pack_framed_setupcurrentframed - \inframedtrue} - -%D A helper: - -\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax} - -%D Inheritance: - -\permanent\protected\def\installinheritedframed#1% - {\normalexpanded{\mult_interfaces_install_inherited_framed - \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 - -\protected\def\mult_interfaces_install_inherited_framed#1#2#3#4#5#6#7#8#9% - {\enforced\frozen\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% - \enforced\frozen\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root - \frozen\instance\protected\def#8% - {\bgroup - \bgroup - \inframedtrue - \enforced\let\currentframed #1% - \enforced\let\framedparameter #2% - \enforced\let\framedparameterhash#3% - \enforced\let\setupcurrentframed #7% - \pack_framed_process_indeed}% - \frozen\instance\protected\def#9% - {\bgroup - \inframedtrue - \enforced\let\currentframed #1% - \enforced\let\framedparameter #2% - \enforced\let\framedparameterhash#3% - \enforced\let\setupcurrentframed #7% - \pack_framed_process_box_indeed}} - -\permanent\protected\def\installframedcommandhandler#1#2#3% - {\installcommandhandler{#1}{#2}{#3}% - \installinheritedframed{#2}} - -\permanent\protected\def\installframedautocommandhandler#1#2#3% - {\installautocommandhandler{#1}{#2}{#3}% - \installinheritedframed{#2}} - -\permanent\protected\def\installsimpleframedcommandhandler#1#2#3% - {\installsimplecommandhandler{#1}{#2}{#3}% - \installinheritedframed{#2}} - -% for regular framed - -\setupframed - [\c!width=\v!fit, - \c!height=\v!broad, - %\c!minheight=\zeropoint, - %\c!lines=, - \c!offset=.25\exheight, % \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!anchoring=, - \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] - -\permanent\protected\def\definesimplifiedframed[#1]% no settings - {\defineframed[#1][\??simplifiedframed]% - \enforced\letcsname#1\endcsname\undefined} - -\letcsname\??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_anchoring \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_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 - {\raise\d_framed_target_dp\hpack{\frule - type fill - width \d_framed_target_wd - height \d_framed_target_ht - depth \d_framed_target_dp - line \d_framed_linewidth - radius \p_framed_backgroundradius\space - corner {\p_framed_backgroundcorner} - \relax}} - -\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 - \orelse\ifx\p_framed_frame\v!on - \pack_framed_stroked_box_round - \fi} - -% \pack_framed_stroked_box_normal % later - -\def\pack_framed_stroked_box_round - {\raise\d_framed_target_dp\hpack{\frule - width \d_framed_target_wd - height \d_framed_target_ht - depth \d_framed_target_dp - line \d_framed_linewidth - radius \p_framed_frameradius\space - corner {\p_framed_framecorner} - \relax}} - -% 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 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}% - \ifempty\p_framed_backgroundcolor \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 - -\permanent\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 - -\let\m_overlay_region\empty - -% expandable ... in a future version the space will go (in mp one can use Overlay*) - -\permanent\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables -\permanent\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default -\permanent\def\overlaydepth {\the\d_overlay_depth \space} % values. -\permanent\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) -\permanent\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. -\permanent\def\overlayregion {\m_overlay_region} - -% public but kind of protected - -\permanent\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} -\permanent\def\usedoverlayheight {\dimexpr\d_overlay_height \relax} -\permanent\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} -\permanent\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} -\permanent\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax} - -%D The next register is used to initialize overlays. - -\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 - -\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded - {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% - \processcommalist[#1]\pack_framed_define_overlay_indeed} - -\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions - {\bgroup % redundant grouping - \setlayoutcomponentattribute{\v!overlay:#1}% - \setbox\scratchbox\hbox \layoutcomponentboxattribute{\the\everyoverlay#2}% - \boxxoffset\scratchbox-.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width - \boxyoffset\scratchbox-.5\dimexpr\ht\scratchbox-\d_framed_target_ht+\d_framed_target_dp\relax % not \d_overlay_height ! - \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} - -\permanent\protected\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: - -\permanent\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 - \orelse\ifcsname\??overlay\m_framed_background\endcsname - \expandafter\pack_framed_process_background_indeed_external\lastnamedcs - \fi} - -\def\pack_framed_process_background_indeed_internal#1% % : in name - {\bgroup - \setbox\b_framed_extra\hpack\bgroup - \ifzeropt\framedbackgroundoffset\else - \kern-\framedbackgroundoffset - \fi - \hbox\bgroup#1\egroup - \egroup - \wd\b_framed_extra\zeropoint - \ht\b_framed_extra\framedbackgroundheight - \dp\b_framed_extra\framedbackgrounddepth - \box\b_framed_extra - \egroup} - -\def\pack_framed_process_background_indeed_external - {\pack_framed_overlay_initialize - \pack_framed_process_background_indeed_internal} - -\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground) - {\edef\m_framed_background{#1}% - \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_set_region % experiment - {\ifx\m_overlay_region\v!yes - \edef\m_overlay_region{\reservedautoregiontag}% - \fi} - -\def\pack_framed_add_region % experiment - {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} - -\def\pack_framed_add_background - {\setbox\b_framed_normal\hpack % 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 - \ifempty\p_framed_component - \resetlayoutcomponentattribute - \else - \setlayoutcomponentattribute{\v!background:\p_framed_component}% - \fi - \let\foregroundbox\pack_framed_background_box_content - \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay - \the\everybackgroundbox % moved - \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it - \box\b_framed_normal - \hss - \egroup}} - -\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\hpack - {\kern-\d_framed_frameoffset - \raise\scratchdimen - \hpack{\ifempty\overlaylinecolor\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_opened - {\setbox\scratchbox\vpack \bgroup - \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname - \nointerlineskip % new (needed for fences) - \hpack \bgroup - \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname - \novrule - \s!width \d_framed_target_wd - \s!height\d_framed_target_ht - \s!depth \d_framed_target_dp - \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname - \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_closed - {\hpack\bgroup - \scratchdimen.5\d_framed_linewidth - \hskip\scratchdimen - \clf_framedoutline - \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax - \dimexpr\d_framed_target_ht-\scratchdimen\relax - \dimexpr\d_framed_target_dp-\scratchdimen\relax - \d_framed_linewidth - \relax - \egroup} - -\def\pack_framed_stroked_box_normal - {\ifx\p_framed_frame\v!closed - \pack_framed_stroked_box_normal_closed - \else - \pack_framed_stroked_box_normal_opened - \fi} - -\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} -\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} -\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} -\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_is_overlaid -\newconditional\c_framed_has_frame -\newconditional\c_framed_has_extra_offset -\newconditional\c_framed_text_location_none - -\newconstant \c_framed_has_strut % 0=relaxes 1=pseudostruts 2=realstruts - -%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{.25\exheight} - -\installcorenamespace{regularframedlevel} - -\permanent\protected\def\installregularframed#1% - {\defineframed[#1]} - -\permanent\protected\def\presetlocalframed[#1]% - {\defineframed[#1]} - -% \presetlocalframed[\??framed] - -\newcount\c_pack_framed_nesting - -\permanent\tolerant\protected\def\framed[#1]% - {\bgroup - \advance\c_pack_framed_nesting\plusone - \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed - \edef\currentframed{>\the\c_pack_framed_nesting}% - \pack_framed_initialize - \bgroup - \setupcurrentframed[#1]% here !, seldom no argument so no need to optimize - \pack_framed_process_indeed} - -\permanent\tolerant\protected\def\startframed[#1]#*[#2]% - {\bgroup - \ifarguments - \pack_framed_initialize - \bgroup - \or - \ifhastok={#1}% - \advance\c_pack_framed_nesting\plusone - \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed - \edef\currentframed{>\the\c_pack_framed_nesting}% - \pack_framed_initialize - \bgroup - \setupcurrentframed[#1]% here ! - \else - \edef\currentframed{#1}% - \pack_framed_initialize - \bgroup - \fi - \else - \edef\currentframed{#1}% - \pack_framed_initialize - \bgroup - \setupcurrentframed[#2]% here ! - \fi - \pack_framed_process_indeed - \bgroup - \ignorespaces} - -% till here - -\permanent\protected\def\stopframed - {\removeunwantedspaces - \egroup} - -\protected\def\normalframedwithsettings[#1]% - {\bgroup - \advance\c_pack_framed_nesting\plusone - \letcsname\??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 dimensions can be -%D set, only frames and backgrounds. - -%% \protected\def\fastlocalframed[#1]#2[#3]#4% 3-4 - -\permanent\protected\def\fastlocalframed[#1]#*[#2]#3% - {\bgroup - \edef\currentframed{#1}% - \pack_framed_initialize - \setbox\b_framed_normal\hbox{#3}% - \iftrialtypesetting \else - \edef\m_overlay_region{\framedparameter\c!region}% - \ifempty\m_overlay_region\else - \pack_framed_set_region - \fi - \fi - \setupcurrentframed[#2]% - \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds - \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds - \edef\p_framed_frame{\framedparameter\c!frame}% - \edef\p_framed_background{\framedparameter\c!background}% - % not here, in calling macro: setups - \pack_framed_remove_depth - \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else - \ifempty\p_framed_rulethickness\else - \d_framed_linewidth\p_framed_rulethickness\relax - \fi - \pack_framed_add_outline % real or invisible frame - \fi - \ifempty\p_framed_background \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 - \iftrialtypesetting\orelse\ifempty\m_overlay_region\else - \pack_framed_add_region - \fi - \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. - -\protected\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) - {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2 - \edef\m_overlay_region{\framedparameter\c!region}% - \ifempty\m_overlay_region\else - \pack_framed_set_region - \fi - \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds - \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds - \edef\p_framed_frame{\framedparameter\c!frame}% - \edef\p_framed_background{\framedparameter\c!background}% - \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else - \ifempty\p_framed_rulethickness \else - \d_framed_linewidth\p_framed_rulethickness\relax - \fi - \pack_framed_add_outline % real or invisible frame - \fi - \ifempty\p_framed_background \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 - \ifempty\m_overlay_region\else - \pack_framed_add_region - \fi - \box\b_framed_normal - \egroup} - -\protected\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 - -\permanent\tolerant\protected\def\localframed[#1]#*[#2]% - {\bgroup - \bgroup - \edef\currentframed{#1}% - \pack_framed_initialize - \setupcurrentframed[#2]% here ! - \pack_framed_process_indeed} - -\permanent\protected\def\directlocalframed[#1]% no optional - {\bgroup - \bgroup - \edef\currentframed{#1}% - \pack_framed_initialize - \pack_framed_process_indeed} - -\aliased\let\localframedwithsettings\localframed - -% done - -\defineinterfaceconstant {fr!analyze} {fr:analyze} % private option - -\let\delayedbegstrut\relax -\let\delayedendstrut\relax -\let\delayedstrut \relax - -\let\localoffset\empty -\let\localwidth \empty -\let\localheight\empty -\let\localformat\empty -\let\localstrut \empty - -\protected\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}% - \ifempty\p_framed_foregroundstyle\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\p_strut {\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_anchoring {\framedparameter\c!anchoring}% - % - \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 - \orelse\ifx\p_framed_frame\v!none % no frame, no framewidth - \setfalse\c_framed_has_frame - \else - \settrue\c_framed_has_frame - \fi - \ifconditional\c_framed_has_frame - \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% - \ifempty\p_framed_rulethickness\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 - % - \ifempty\localformat - \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}% - \ifempty\p_framed_lines - \orelse\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 - % 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\p_strut\endcsname - \lastnamedcs - \else - \framed_offset_alternative_unknown - \fi - % the next check could move to strutalternative - \ifcase\c_framed_has_strut % none (not even noindent) - \enforced\let\localbegstrut\relax - \enforced\let\localendstrut\relax - \enforced\let\localstrut \relax - \or % no / overlay - \enforced\let\localbegstrut\pseudobegstrut - \enforced\let\localendstrut\pseudoendstrut - \enforced\let\localstrut \pseudostrut - \else - \enforced\let\localbegstrut\begstrut - \enforced\let\localendstrut\endstrut - \enforced\let\localstrut \strut - \fi - \ifx\p_framed_autostrut\v!yes - \enforced\let\delayedbegstrut\relax - \enforced\let\delayedendstrut\relax - \enforced\let\delayedstrut \relax - \else - \enforced\let\delayedbegstrut\localbegstrut - \enforced\let\delayedendstrut\localendstrut - \enforced\let\delayedstrut \localstrut - \enforced\let\localbegstrut \relax - \enforced\let\localendstrut \relax - \enforced\let\localstrut \relax - \fi - \ifconditional\c_framed_has_height - \enforced\let\\\pack_framed_vboxed_newline - \ifconditional\c_framed_has_width - \enforced\let\hairline\pack_framed_vboxed_hairline - \ifconditional\c_framed_has_format - \let\next\pack_framed_format_format_yes - \else - \let\next\pack_framed_format_format_nop - \fi - \else - \enforced\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 - \orelse\ifconditional\c_framed_has_width - \ifconditional\c_framed_has_format - \enforced\let\\\pack_framed_vboxed_newline - \enforced\let\hairline\pack_framed_vboxed_hairline - \let\next\pack_framed_format_format_width - \else - \enforced\let\\\pack_framed_hboxed_newline - \enforced\let\hairline\pack_framed_hboxed_hairline - \let\next\pack_framed_format_format_hsize - \fi - \else - \enforced\let\\\pack_framed_hboxed_newline - \enforced\let\hairline\pack_framed_hboxed_hairline - \let\next\pack_framed_format_format_no_size - \fi - \pack_framed_check_extra_offsets - \edef\p_framed_background{\framedparameter\c!background}% -% \ifempty\p_framed_background -% \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 - \ifempty\p_framed_orientation - \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}% - {\c_framed_has_strut\plusone} - -\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} - -\setvalue{\??framedstrutalternative\v!none}% not even pseudo struts - {\c_framed_has_strut\zerocount} - -% offsets - -\setvalue{\??framedoffsetalternative\v!none}% - {\setfalse\c_framed_has_offset - \c_framed_has_strut\plusone - \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 - \c_framed_has_strut\plusone - \settrue\c_framed_is_overlaid - \d_framed_local_offset\zeropoint} - -% \setvalue{\??framedoffsetalternative\v!strut}% -% {\setfalse\c_framed_has_offset -% \c_framed_has_strut\plustwo -% \settrue\c_framed_is_overlaid -% \d_framed_local_offset\zeropoint} - -\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000 - {\settrue \c_framed_has_offset - \c_framed_has_strut\plustwo - \setfalse\c_framed_is_overlaid - \let\localoffset\defaultframeoffset - \letframedparameter\c!offset\defaultframeoffset % brrr - \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} - -\def\framed_offset_alternative_unknown - {\settrue \c_framed_has_offset - \c_framed_has_strut\plustwo - \setfalse\c_framed_is_overlaid - \let\defaultframeoffset\localoffset - \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} - -\letvalue{\??framedoffsetalternative\s!unknown}\framed_offset_alternative_unknown - -% 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% - \ifempty\checkedframeoffset \zeropoint\orelse - \ifx\checkedframeoffset\v!overlay\zeropoint\orelse - \ifx\checkedframeoffset\v!none \zeropoint\orelse - \ifx\checkedframeoffset\v!frame \zeropoint\orelse - \ifx\checkedframeoffset\v!default\zeropoint\else - #2% - \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 - \orelse\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_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}} - -\def\pack_framed_reverse_box - {\ifvbox\b_framed_normal - \edef\p_linedirection{\framedparameter\c!linedirection}% - \ifx\p_linedirection\v!reverse - \reversevboxcontent\b_framed_normal - \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}% - \fi - \fi} - -\protected\def\pack_framed_finish - {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down - \pack_framed_locator_before\p_framed_location - \ifconditional\c_framed_has_format - %\ifconditional\c_framed_has_height \else - % \edef\p_profile{\framedparameter\c!profile}% - % \ifempty\p_profile\else - % \pack_framed_profile_box - % \fi - %\fi - \ifempty\p_framed_anchoring\else - \pack_framed_reverse_box - \fi - \ifx\p_framed_autowidth\v!force - \pack_framed_finish_a - \orelse\ifx\localwidth\v!fit - \ifx\p_framed_autowidth\v!yes - \pack_framed_finish_a - \else - \pack_framed_finish_b - \fi - \orelse\ifx\localwidth\v!fixed - \pack_framed_finish_b - \else - \pack_framed_finish_c - \fi - \ifconditional\c_framed_has_height \else - \edef\p_profile{\framedparameter\c!profile}% - \ifempty\p_profile\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 - \else - \edef\p_framed_minheight{\framedparameter\c!minheight}% - \ifempty\p_framed_minheight \else - \ifdim\ht\b_framed_normal<\p_framed_minheight - \ht\b_framed_normal\p_framed_minheight - \fi - \fi - \fi - \edef\p_framed_empty{\framedparameter\c!empty}% - \ifx\p_framed_empty\v!yes - \pack_framed_fake_box - \fi - \ifempty\p_framed_anchoring\else - \pack_framed_handle_anchoring - \fi - \pack_framed_stop_orientation % moved here at 2014-05-25 - \iftrialtypesetting \else - \edef\m_overlay_region{\framedparameter\c!region}% - \ifempty\m_overlay_region\else - \pack_framed_set_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\relax - \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 - % better: \pushmacro\\postprocessframebox etc - \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 - \ifempty\p_framed_background \else - \edef\p_framed_component{\framedparameter\c!component}% - \pack_framed_add_background - \fi - \fi - \pack_framed_locator_after\p_framed_location - \iftrialtypesetting \else - \ifempty\m_overlay_region\else - \pack_framed_add_region - \fi - \fi - \box\b_framed_normal - \global\frameddimensionstate % global so to be used directly afterwards ! - \ifconditional\c_framed_has_width - \ifconditional\c_framed_has_height \plusthree \else \plusone \fi - \else - \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi - \fi - \egroup - \egroup} - -%D Anchoring is experimental and was prototyped around the ctx meeting in 2018 but -%D never mede it into the core yet. It operates independent of the orientation -%D mechanism already present. It's a rather efficient feature. Best is to use -%D predefined orientations, like: -%D -%D \starttyping -%D \defineorientation[leftflushleft] [orientation=left,horizontal=flushleft] -%D -%D \framed [anchoring={leftflushleft}] {anchoring} -%D \stoptyping -%D -%D But this also works: -%D -%D \starttyping -%D \framed [anchoring={flushleft,top,up}] {anchoring} -%D \stoptyping -%D -%D When an anchoring is given (use \type {normal} for the default) you can also -%D use the \type {xanchor} and \type {yanchor} offsets. - -% because we mess with the width later on, we need double wrapping: - -\def\pack_framed_handle_anchoring - {\scratchcounter\autoorientation\p_framed_anchoring\relax - \edef\p_xanchor{\framedparameter\c!xanchor}% - \edef\p_yanchor{\framedparameter\c!yanchor}% - \setbox\b_framed_normal\hpack{\hpack % here - % using the keyword approachs works ok, don't mess with orientation - % directly here using \boxorientation ... it doesn't work that well - \s!orientation\scratchcounter - \ifempty\p_xanchor\else \s!xoffset \p_xanchor\fi - \ifempty\p_yanchor\else \s!yoffset \p_yanchor\fi - {\box\b_framed_normal}}} - -\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{\begincsname\??framedlocatorbefore#1\endcsname} -\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname} - -\newdimen\d_framed_locator_ht -\newdimen\d_framed_locator_dp -\newdimen\d_framed_locator_lo -\newdimen\d_framed_locator_ro - -\def\pack_framed_locator_set#1% - {\d_framed_locator_ht\dimexpr - #1+\d_framed_linewidth - \ifconditional\c_framed_has_offset - +\framedparameter\c!offset - \fi - +\framedparameter\c!toffset - \relax - \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax} - -\def\pack_framed_locator_set_lo - {\global\d_framed_locator_lo\dimexpr - \d_framed_linewidth - \ifconditional\c_framed_has_offset - +\framedparameter\c!offset - \fi - +\framedparameter\c!loffset - \relax} - -\def\pack_framed_locator_set_ro - {\global\d_framed_locator_ro\dimexpr - \d_framed_linewidth - \ifconditional\c_framed_has_offset - +\framedparameter\c!offset - \fi - +\framedparameter\c!roffset - \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_locator_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}} % why do we pack .. dange of loosing? - -\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}} % why do we pack .. dange of loosing? - -\installframedlocator \v!low - {} - {\pack_framed_locator_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_locator_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}} % why do we pack .. dange of loosing? - -\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}} % why do we pack .. dange of loosing? - -\installframedlocator \v!lohi % maybe also \v!center - {\pack_framed_locator_before\v!middle} - {\pack_framed_locator_after \v!middle} - -\installframedlocator \v!bottom - {} - {\pack_framed_locator_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}} % why do we pack .. dange of loosing? - -\installframedlocator \v!keep % retains height/depth - {\pack_framed_remove_depth} - {\pack_framed_restore_depth} - -\newdimen\d_framed_formula - -\installframedlocator \v!formula % private, will become a more generic name - {} - {\pack_framed_locator_set\d_framed_formula - \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}} % why do we pack .. danger of loosing? - -% 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 - \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. - -\permanent\tolerant\protected\def\inframed[#1]{\framed[\c!location=\v!low,#1]} - -%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background, -%D but no content, so actually we have a sort of phantom framed box. - -%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 - -\protected\def\pack_framed_math_strut - {\Ustartmath - \triggermathstyle\c_framed_mstyle - \vphantom{(}% - \Ustopmath} - -\installcorenamespace{mathframed} - -\installframedcommandhandler \??mathframed {mathframed} \??mathframed - -\newcount\c_pack_framed_mathframed -\newtoks \t_pack_framed_mathframed - -\appendtoks - \frozen\instance\setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}% -\to \everydefinemathframed - -\protected\def\pack_framed_mathframed#1% - {\begingroup - \edef\currentmathframed{#1}% - \dosingleempty\pack_framed_mathframed_indeed} - -\def\pack_framed_math_pos - {\global\advance\c_pack_framed_mathframed\plusone - \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}% - \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}% - \xypos\pack_framed_mc_two} - -\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here - {\iffirstargument - \setupcurrentmathframed[#1]% - \fi - \c_framed_mstyle\normalmathstyle - \edef\m_framed_location{\mathframedparameter\c!location}% - \ifx\m_framed_location\v!mathematics - \enforced\let\normalstrut\pack_framed_math_pos - \orelse\ifx\m_framed_location\v!low\else - \enforced\let\normalstrut\pack_framed_math_strut - \fi - \inheritedmathframedframed\bgroup - \Ustartmath - \triggermathstyle\c_framed_mstyle - \the\t_pack_framed_mathframed - #2% - \Ustopmath - \egroup - \endgroup} - -\appendtoks - \mathraggedstatus\plustwo % makes \startalign work - \eqalignmode \zerocount % makes \startalign fit -\to \t_pack_framed_mathframed - -\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 - -\permanent\protected\def\doformatonelinerbox % beware: assumes explicit preceding bgroup - {\ifconditional\raggedonelinerstate - \expandafter\dodoformatonelinerbox - \else - \expandafter\nodoformatonelinerbox - \fi} - -\permanent\protected\def\dodoformatonelinerbox - {\afterassignment\redoformatonelinerbox - \setbox\nextbox\hbox} % maybe \hpack - -\permanent\protected\def\redoformatonelinerbox - {\aftergroup\dododoformatonelinerbox - \ignorespaces} - -\permanent\protected\def\dododoformatonelinerbox - {\hpack to \hsize % was \hbox - {\ifcase\raggedstatus\or\hss\or\hss \fi - \unhbox\nextbox \removeunwantedspaces - \ifcase\raggedstatus\or \or\hss\or\hss\fi}% - \egroup} - -\permanent\protected\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}% - \ifempty\p_framed_foregroundcolor\else\dousecolorparameter\p_framed_foregroundcolor\fi} - -\def\pack_framed_do_setups - {\ifempty\p_framed_setups \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 - \synchronizeinlinedirection - \localbegstrut - \atendofgroup\localendstrut - \atendofgroup\pack_framed_do_bottom - \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 - \synchronizeinlinedirection - \localbegstrut - \atendofgroup\localendstrut - \atendofgroup\vss - \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 - \synchronizeinlinedirection - \localbegstrut - \atendofgroup\localendstrut - \atendofgroup\vss - \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 - \synchronizeinlinedirection - \localbegstrut - \atendofgroup\localendstrut - \atendofgroup\pack_framed_do_bottom - \doformatonelinerbox} - -\def\pack_framed_format_format_vsize - {\vbox to \d_framed_height % no vpack .. maybe grid - \bgroup - \let\postprocessframebox\relax - % \pack_framed_forgetall - \iftrialtypesetting \else - \pack_framed_set_foregroundcolor - \fi - \vsize\d_framed_height - \pack_framed_do_setups - \vss - \atendofgroup\vss - \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 - \atendofgroup\hss - \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 \unprotect -%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 \protect -%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. - -\protected\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth - {\begingroup - \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi - \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax - \par - \nointerlineskip - \kern\scratchoffset - \dontleavehmode - \hrule\s!height\d_framed_linewidth\s!depth\zeropoint - \par - \kern-\d_framed_linewidth - \dontleavehmode - \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% - \hfill - \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}% - \par - \nointerlineskip - \kern\scratchoffset - \nointerlineskip - \endgraf - \nointerlineskip - \localbegstrut - \endgroup} - -\protected\def\pack_framed_hboxed_hairline % use framed dimen - {\bgroup - \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi - \ifconditional\c_framed_has_height - \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. - -\protected\def\pack_framed_vboxed_newline - {\endgraf\ignorespaces} - -\protected\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<>} -%D \showsetup{<>} -%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 - \frozen\instance\setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}% - \frozen\instance\setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }% - \frozen\instance\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} - -\protected\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}}} - -% todo: sort out first/lastline ht/dp - -\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 % \vpack - \startboxedcontent - \hsize\localhsize - % \insidefloattrue % ? better - \usebodyfontparameter\framedtextparameter - % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used - \letframedtextparameter\c!strut\v!no - \inheritedframedtextframed\bgroup - \enforced\let\\\endgraf - \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 - \framedtextparameter\c!inner - \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] - -\protected\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 - \orelse\ifinsidefloat - \egroup - \box\b_framed_normal - \else - \egroup - \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}% - \fi - \egroup} - -%D We define the general (and original) case by just saying: - -\def\pack_framed_text_check % messy dependency - {\localhsize\hsize - \ifinsidefloat \orelse \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} - -\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. - -\protected\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 - \iffirstargument - \setupcurrentframedtext[#1]% - \fi - \edef\p_framed_text_strut{\framedtextparameter\c!strut}% - \letframedtextparameter\c!strut\v!no - \inheritedframedtextframed\bgroup - \blank[\v!disable]% - \enforced\let\\\endgraf - \useframedtextstyleandcolor\c!style\c!color - \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 - \framedtextparameter\c!inner - \ifx\p_framed_text_strut\v!no - \let\pack_framed_strut\relax - \else - \let\pack_framed_strut\strut - \fi - \bgroup - \aftergroup\pack_framed_text_stop_direct - \afterassignment\ignorespaces - \afterassignment\pack_framed_strut - \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 - \frozen\instance\setuevalue{\currentframed}{\pack_framed_defined_process[\currentframed]}% -\to \everydefineframed - -\newcount\c_temp_framed_crap - -\permanent\tolerant\protected\def\pack_framed_defined_process[#1]#*[#2]% official (not much checking, todo: parent) - {\bgroup - \ifcsname\??regularframedlevel#1\endcsname - %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname - \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 - \defcsname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed - \bgroup - \edef\currentframed{#1>\the\c_pack_framed_temp}% - \pack_framed_initialize - \setupcurrentframed[#2]% here ! - \pack_framed_process_indeed} - -\aliased\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] - -\permanent\let\stopframedcontent\relax - -\permanent\tolerant\protected\def\startframedcontent[#1]% - {\bgroup - \edef\currentframedcontent{#1}% - \ifx\currentframedcontent\v!off - \enforced\let\stopframedcontent\egroup - \else - \checkframedcontentparent - \enforced\let\stopframedcontent\pack_framed_stop_content_indeed - \expandafter\pack_framed_start_content_indeed - \fi} - -\def\pack_framed_start_content_indeed - {\setbox\b_framed_normal\hpack\bgroup - \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 - \vpack\bgroup - \vskip\scratchtopoffset - \vbox\bgroup - \forgetall - \blank[\v!disable]} - -\protected\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: - -\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 - -%D Fast enough for most cases (we could do a massive \type {\ifhastok} instead): - -\protected\def\doifelseframed#1% - {\iftok{#1\c!frame }{\v!on}\expandafter\firstoftwoarguments - \orelse\iftok{#1\c!topframe }{\v!on}\expandafter\firstoftwoarguments - \orelse\iftok{#1\c!bottomframe}{\v!on}\expandafter\firstoftwoarguments - \orelse\iftok{#1\c!leftframe }{\v!on}\expandafter\firstoftwoarguments - \orelse\iftok{#1\c!rightframe }{\v!on}\expandafter\firstoftwoarguments - \orelse\iftok{#1\c!background } {}\expandafter\secondoftwoarguments - \else \expandafter\firstoftwoarguments\fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/page-bck.mkxl b/tex/context/base/mkiv/page-bck.mkxl deleted file mode 100644 index 94e4f4a95..000000000 --- a/tex/context/base/mkiv/page-bck.mkxl +++ /dev/null @@ -1,715 +0,0 @@ -%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 - -\permanent\protected\def\initializepagebackgrounds - {\setfalse\c_page_backgrounds_new - \setfalse\c_page_backgrounds_new_right - \setfalse\c_page_backgrounds_new_left - \setfalse\c_page_backgrounds_some} - -%D We keep calculations and checks to a minimum and also try to minimize -%D the amount of tracing due to expansion. - -\let\currentotrbackground\empty - -%D This is the only spot where we have a low level dependency on the way -%D parent chains are defined but we want the speed. - -\protected\def\page_backgrounds_check_background - {\ifcsname\??framed\currentotrbackground:\c!background\endcsname - %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}% - \edef\page_background_temp{\lastnamedcs}% - \ifempty\page_background_temp - \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{\letcsname\currentotrbackground\endcsname\relax } -\def\page_backgrounds_set_nop{\letcsname\currentotrbackground\endcsname\undefined} - -\protected\def\page_backgrounds_check#1% - {\edef\currentotrbackground{\??layoutbackgrounds#1}% - \page_backgrounds_check_background} - -\permanent\def\doifelsesomebackground#1% - {\ifcsname\??layoutbackgrounds#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifsomebackgroundelse\doifelsesomebackground - -\permanent\def\doifsomebackground#1% - {\ifcsname\??layoutbackgrounds#1\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -%D The background mechanism falls back on the \type {\framed} macro. This means -%D that all normal frame and overlay features can be used. - -\def\page_backgrounds_add_to_box#1% area - {\ifcsname\??layoutbackgrounds#1\endcsname - \expandafter\page_backgrounds_add_to_box_indeed - \else - \expandafter\gobblefourarguments - \fi#1} - -%D We don't need the dimensions here as this is a real framed but the question is: -%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only -%D for hidden). - -\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero - {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}% - \ifempty\p_page_backgrounds_setups \else - \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! - \fi - % #2 has the right dimensions already - \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground) - - -%D There are quite some backgrounds. At the bottom layer, there is the {\em paper} -%D background. This one is only used for special purposes, like annotations to -%D documents. - -\def\page_backgrounds_add_to_print#1% - {\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight} - -%D The page backgrounds can be put behind the {\em left page}, the {\em right page} -%D or {\em each page}. As with the paper background, these are calculated on each -%D page. - -\def\page_backgrounds_add_to_paper#1% - {\doifbothsidesoverruled - {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% - {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% - {\page_backgrounds_add_to_box\v!leftpage #1\paperwidth\paperheight}% - \page_backgrounds_add_to_box\v!page#1\paperwidth\paperheight} - -%D Then there are the 25 areas that make up the layout: {\em top, header, text, -%D footer, bottom} times {\em left edge, left margin, text, right margin, right -%D edge}. These are only recalculated when they change or when the \type {status} -%D is set to \type {repeat}. - -\newbox\leftbackground % todo: rename -\newbox\rightbackground % todo: rename - -%D Finaly there is an aditional {\em text} background, again useful for special -%D purposes only. This one is calculated each time. The hidden backgrounds are not -%D meant for users! - -\newconditional\c_page_backgrounds_hidden_enabled - -\def\page_backgrounds_add_to_text#1% - {\ifconditional\c_page_backgrounds_hidden_enabled - \page_backgrounds_add_to_box\v!hidden#1\makeupwidth\textheight % mine ! - \fi - \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight} - -%D The next couple of macros implement the area backgrounds. As said, these are -%D cached in dedicated boxes. The offsets and depth of the page are used for -%D alignment purposes. - -%newdimen\pageoffset % bleed -%newdimen\pagedepth % built-in - -%D We need a bit more clever mechanism in order to handle layers well. This means -%D that we cannot calculate both background at the same time since something may -%D have changed halfway a page. - -%D Margin swapping has been simplified: see mkii code in case of regression. -%D Calculation is delayed till the page anyway so the state is known. - -\def\page_backgrounds_recalculate - {\global\settrue\c_page_backgrounds_new} - -\def\page_backgrounds_set_boxes - {\ifconditional\c_page_backgrounds_new - \page_backgrounds_set_boxes_r - \fi - \doifbothsides - \page_backgrounds_set_boxes_a - \page_backgrounds_set_boxes_b - \page_backgrounds_set_boxes_c - \ifx\p_page_backgrounds_state\v!repeat\else - \global\setfalse\c_page_backgrounds_new - \fi} - -\def\page_backgrounds_set_boxes_r - {\global\settrue\c_page_backgrounds_new_right - \global\settrue\c_page_backgrounds_new_left - \global\setbox\leftbackground\emptybox - \global\setbox\rightbackground\emptybox} - -\def\page_backgrounds_set_boxes_a - {\ifconditional\c_page_backgrounds_new_left - % \showmessage\m!layouts8\empty - \page_backgrounds_set_box\leftbackground % \conditionalfalse - \global\setfalse\c_page_backgrounds_new_left - \global\setfalse\c_page_backgrounds_new_right - \fi} - -\def\page_backgrounds_set_boxes_b - {\ifconditional\c_page_backgrounds_new_left - % \showmessage\m!layouts8\empty - \page_backgrounds_set_box\leftbackground - \global\setfalse\c_page_backgrounds_new_left - \fi} - -\def\page_backgrounds_set_boxes_c - {\ifconditional\c_page_backgrounds_new_right - % \showmessage\m!layouts8\empty - \page_backgrounds_set_box\rightbackground - \global\setfalse\c_page_backgrounds_new_right - \fi} - -\def\page_backgrounds_add_to_main#1% todo: dimension spec - {\ifconditional\c_page_backgrounds_some - \page_backgrounds_set_boxes - \setbox#1\vpack - {\offinterlineskip - \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}% - \box#1}% - \fi} - -\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE -\newdimen\pagebackgroundvoffset -\newdimen\pagebackgroundoffset % used elsewhere -\newdimen\pagebackgrounddepth -\newdimen\pagebackgroundcompensation - -\def\page_backgrounds_set_offsets % used in menus (we can use ifcsname's here) - {\ifconditional\c_page_backgrounds_some \ifconditional\c_page_backgrounds_new - \page_backgrounds_set_offsets_indeed % indirect, less tracing - \fi \fi} - -\def\page_backgrounds_set_offsets_indeed - {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname - \page_backgrounds_set_offsets_yes - \orelse\ifcsname\??layoutbackgrounds\v!text\endcsname - \page_backgrounds_set_offsets_yes - \else - \page_backgrounds_set_offsets_nop - \fi} - -\def\page_backgrounds_set_offsets_nop - {\global\pagebackgroundhoffset \zeropoint - \global\pagebackgroundvoffset \zeropoint - \global\pagebackgrounddepth \zeropoint - \global\pagebackgroundcompensation\zeropoint} - -\def\page_backgrounds_set_offsets_yes - {\global\pagebackgroundoffset \d_page_backgrounds_depth - \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax - \ifzeropt\pagebackgroundcompensation - \page_backgrounds_set_offsets_nop - \else - \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname - \global\pagebackgroundhoffset\zeropoint - \orelse\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname - \global\pagebackgroundhoffset\zeropoint - \else - \global\pagebackgroundhoffset\pagebackgroundcompensation - \fi - \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname - \global\pagebackgroundvoffset\zeropoint - \global\pagebackgrounddepth \zeropoint - \orelse\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname - \global\pagebackgroundvoffset\zeropoint - \global\pagebackgrounddepth \zeropoint - \else - \global\pagebackgroundvoffset\pagebackgroundcompensation - \global\pagebackgrounddepth \d_page_backgrounds_depth - \fi - \fi} - -\appendtoks - \page_backgrounds_set_offsets -\to \everybeforepagebody - -\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins - -%D The swapping here is pretty nasty! Maybe we should find another way some day but -%D for now we tweak. - -\def\page_backgrounds_set_box#1% #2% - {\global\setbox#1\vpack - {\dontcomplain - \swapmargins - \ifconditional\swapbackgroundmargins - \doifelsemarginswap \donothing - {\enforced\swapcsvalues\v!rightmargin\v!leftmargin - \enforced\swapcsvalues\v!rightedge \v!leftedge}% - \fi - \calculatereducedvsizes - \offinterlineskip - % \ifconditional#2\relax - % \doswapmargins % hm, this one gets nilled in \swapmargins anyway - % \fi - \ifdim\topheight>\zeropoint - \kern\dimexpr-\topheight-\topdistance\relax - \page_backgrounds_set_box_row\v!top\topheight - \kern\topdistance - \fi - \ifdim\headerheight>\zeropoint - \page_backgrounds_set_box_row\v!header\headerheight - \kern\headerdistance - \fi - \ifdim\textheight>\zeropoint - \page_backgrounds_set_box_row\v!text\textheight - \fi - \ifdim\footerheight>\zeropoint - \kern\footerdistance - \page_backgrounds_set_box_row\v!footer\footerheight - \fi - \ifdim\bottomheight>\zeropoint - \kern\bottomdistance - \page_backgrounds_set_box_row\v!bottom\bottomheight - \fi - \vfilll}% - \smashbox#1} - -\def\page_backgrounds_set_box_row#1#2% maybe helper - {\setbox\scratchbox\vpack to #2 - \bgroup\hpack\bgroup - \goleftonpage - \ifdim\leftedgewidth>\zeropoint - \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname - \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2% - \else - \kern\leftedgewidth - \fi - \kern\leftedgedistance - \fi - \ifdim\leftmarginwidth>\zeropoint - \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname - \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2% - \else - \kern\leftmarginwidth - \fi - \kern\leftmargindistance - \fi - \ifcsname\??layoutbackgrounds#1\v!text\endcsname - \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2% - \else - \kern\makeupwidth - \fi - \ifdim\rightmarginwidth>\zeropoint - \kern\rightmargindistance - \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname - \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2% - \else - \kern\rightmarginwidth - \fi - \fi - \ifdim\rightedgewidth>\zeropoint - \kern\rightedgedistance - \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname - \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2% - \else - \kern\rightedgewidth - \fi - \fi - \egroup\egroup - \wd\scratchbox\zeropoint - \box\scratchbox\relax} - -% these are fake framed .. maybe it's nicer to honor foreground here as well -% but it's probably a slow downer - -\def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height - {\begingroup - \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}% - \ifempty\p_page_backgrounds_setups \else - \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! - \fi - \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}% - \ifempty\p_page_backgrounds_command - \expandafter\page_backgrounds_set_box_cell_nop - \else - \expandafter\page_backgrounds_set_box_cell_yes - \fi#3#4% - \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox - \endgroup} - -\def\page_backgrounds_set_box_cell_nop#1#2% - {\setbox\scratchbox\emptyvbox - \wd\scratchbox#1% - \ht\scratchbox#2} - -\def\page_backgrounds_set_box_cell_yes#1#2% - {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}% - \dp\scratchbox\zeropoint} - -%D The background mechanism is quite demanding in terms or resources. We used to -%D delay these definitions till runtime usage, but since today's \TEX's are large, -%D we now do the work on forehand. -%D -%D \starttyping -%D \setupbackgrounds [settings] -%D \setupbackgrounds [paper,page,text,..] [settings] -%D \setupbackgrounds [top,...] [leftedge,...] [settings] -%D \stoptyping -%D -%D \showsetup{setupbackgrounds} -%D -%D Because the number of arguments runs from one to three, we need to check -%D for it. - -\newtoks\everybackgroundssetup - -% \permanent\protected\def\setupbackgrounds -% {\dotripleempty\page_backgrounds_setup} -% -% \def\page_backgrounds_setup -% {\ifthirdargument -% \expandafter\page_backgrounds_setup_double -% \orelse\ifsecondargument -% \expandafter\page_backgrounds_setup_single -% \orelse\iffirstargument -% \expandafter\page_backgrounds_setup_basics -% \fi} - -\permanent\tolerant\protected\def\setupbackgrounds[#1]#*[#2]#*[#3]% - {\ifarguments - \expandafter\gobblethreeoptionals - \or - \expandafter\page_backgrounds_setup_basics - \or - \expandafter\page_backgrounds_setup_single - \or - \expandafter\page_backgrounds_setup_double - \fi[#1][#2][#3]} - -\newdimen\d_page_backgrounds_offset -\newdimen\d_page_backgrounds_depth - -\appendtoks - \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}% - \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }% - \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }% - \global\d_page_backgrounds_offset\ifempty\p_offset\zeropoint\else\p_page_backgrounds_offset\fi - \global\d_page_backgrounds_depth \ifempty\p_depth \zeropoint\else\p_page_backgrounds_depth \fi - \global\pagebackgroundoffset\d_page_backgrounds_offset\relax - \global\pagebackgrounddepth \d_page_backgrounds_depth \relax - \ifx\p_page_backgrounds_state\v!stop - \global\setfalse\c_page_backgrounds_new - \else - \global\settrue \c_page_backgrounds_new - \fi -\to \everybackgroundssetup - -\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage} -\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage} -\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge} - -\protected\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up - {\global\settrue\c_page_backgrounds_some - \def\page_backgrounds_setup_step##1% - {\doifelseinset{##1}\v_page_backgrounds_double_set - {\page_backgrounds_setup_and_check{##1}{#3}} - {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}% - \processcommacommand[#2]\page_backgrounds_setup_step_nested}}% - \processcommacommand[#1]\page_backgrounds_setup_step - \the\everybackgroundssetup} - -\protected\def\page_backgrounds_setup_single[#1][#2][#3]% - {\global\settrue\c_page_backgrounds_some - \doifelsecommon{#1}\v_page_backgrounds_single_set - {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}% - \processcommacommand[#1]\page_backgrounds_setup_step - \the\everybackgroundssetup}% - {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}} - -\protected\def\page_backgrounds_setup_basics[#1][#2][#3]% - {\setupframed[\??layoutbackgrounds][#1]% - \the\everybackgroundssetup} - -\protected\def\page_backgrounds_setup_and_check#1#2% tag settings - {\edef\currentotrbackground{\??layoutbackgrounds#1}% - \setupframed[\currentotrbackground][#2]% - \page_backgrounds_check_background} - -%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level -%D framed object associated. - -\definesimplifiedframed[\??layoutbackgrounds\v!paper] -\definesimplifiedframed[\??layoutbackgrounds\v!page] -\definesimplifiedframed[\??layoutbackgrounds\v!leftpage] -\definesimplifiedframed[\??layoutbackgrounds\v!rightpage] - -\definesimplifiedframed[\??layoutbackgrounds\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!hidden] - -\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge] -\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge] - -\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge] -\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge] - -\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge] -\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge] - -\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge] -\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge] - -\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge] -\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text] -\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin] -\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge] - -\setupbackgrounds - [\v!page] - [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere - \c!depth=\zeropoint] - -%D General setup: - -\setupbackgrounds - [\c!state=\c!start] - -%D The hidden layer can be populated by extending the following comma separated -%D list. This only happens in core modules. - -% todo page-2 .. page+2 achter pagina -> bleed -% spread-2 .. spread+2 achter spread -> spread (repeat 2 times) - -\permanent\protected\def\enablehiddenbackground - {\global\settrue\c_page_backgrounds_hidden_enabled - \global\settrue\c_page_backgrounds_some - \page_backgrounds_recalculate} - -\permanent\protected\def\disablehiddenbackground - {\global\setfalse\c_page_backgrounds_hidden_enabled} - -\def\hiddenbackgroundlist - {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2} - -\defineoverlay[\v!text-2][\positionregionoverlay\textanchor{\v!text-2}] % no new anchor, we share text -\defineoverlay[\v!text-1][\positionregionoverlay\textanchor{\v!text-1}] -\defineoverlay[\v!text+1][\positionregionoverlay\textanchor{\v!text+1}] -\defineoverlay[\v!text+2][\positionregionoverlay\textanchor{\v!text+2}] - -\setupbackgrounds - [\v!hidden] - [\c!background=\hiddenbackgroundlist] - -%D Because we haven't really set up backgrounds yet, we set the main efficiency -%D switch to false. - -\setfalse\c_page_backgrounds_some - -%D Sometimes you have a document wide (page) background but need to overload it -%D locally. In such case (at least in my experience) the only values that get set -%D are the background and backgroundcolor (if set at all). A full inheritance chain -%D would complicate things because then we need to use named backgrounds which in -%D turn will make this mechanism slower. I considered independent local backgrounds -%D but that also complicates the code (not that much) but isolation means that we -%D need to set more parameters each time. The following simple approach proabbly -%D suits most usage. -%D -%D \starttyping -%D \starttext -%D \setupbackgrounds[page][background=color,backgroundcolor=red] -%D \input tufte \page -%D \setupbackgrounds[page][background=,backgroundcolor=] -%D \input tufte \page -%D \setupbackgrounds[page][background=color,backgroundcolor=red] -%D \input tufte \page -%D \pushbackground[page] -%D \setupbackgrounds[page][background=color,backgroundcolor=green] -%D \input tufte \page -%D \popbackground -%D \input tufte \page -%D \stoptext -%D \stoptyping - -\permanent\protected\def\pushbackground[#1]% - {\pushmacro\popbackground - \edef\currentotrbackground{\??layoutbackgrounds#1}% - \enforced\permanent\protected\edef\popbackground - {\setupframed - [\currentotrbackground] - [\c!background=\namedframedparameter{\currentotrbackground}\c!background, - \c!backgroundcolor=\namedframedparameter{\currentotrbackground}\c!backgroundcolor]% - \page_backgrounds_check_background - \popmacro\popbackground}% - \setupframed - [\currentotrbackground] - [\c!background=,\c!backgroundcolor=]% - \page_backgrounds_check_background} - -\permanent\let\popbackground\relax - -\protect \endinput - -% %D The next series is used in local (for instance floating) backgrounds. -% -% \installsimplifiedframed{\??layoutbackgrounds\v!local} -% -% \getparameters -% [\??layoutbackgrounds\v!local] -% [\c!component=local, -% \c!background=\localbackgroundlist] -% -% \def\localbackgroundlist -% {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2} -% -% \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] % todo share -% \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}] -% \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}] -% \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}] -% -% \def\page_backgrounds_add_local_to_box -% {\ifconditional\c_page_backgrounds_hidden_enabled -% \expandafter\page_backgrounds_add_local_to_box_indeed -% \else -% \expandafter\gobbleoneargument -% \fi} -% -% \def\page_backgrounds_add_local_to_box_indeed#1% -% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}% -% \global\advance\localpositionnumber\plusone} % afterwards ! -% -% \let\page_backgrounds_add_local_to_box\gobbleoneargument - -% Test how previous macro behaves with depth: -% -% \startcolumnset -% \input tufte -% \placefigure{none}{\framed[lines=5]{xxx}} -% \input tufte -% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate} -% \input tufte -% \stopcolumnset - diff --git a/tex/context/base/mkiv/page-imp.mkiv b/tex/context/base/mkiv/page-imp.mkiv index a83089986..829ed24f4 100644 --- a/tex/context/base/mkiv/page-imp.mkiv +++ b/tex/context/base/mkiv/page-imp.mkiv @@ -167,11 +167,7 @@ % \def\page_shipout_box#1{\normalshipout\box#1\relax} % takes a number -\ifcase\contextlmtxmode - \def\page_shipout_show_box{\scratchcounter} -\else - \def\page_shipout_show_box{\showbox diagnose} -\fi +\def\page_shipout_show_box{\scratchcounter} \unexpanded\def\page_shipout_box#1% {\ifcase\tracingoutput\else diff --git a/tex/context/base/mkiv/page-ini.mkxl b/tex/context/base/mkiv/page-ini.mkxl deleted file mode 100644 index 481e5abd5..000000000 --- a/tex/context/base/mkiv/page-ini.mkxl +++ /dev/null @@ -1,376 +0,0 @@ -%D \module -%D [ file=page-ini, -%D version=2000.10.20, -%D title=\CONTEXT\ Page Macros, -%D subtitle=Initializations, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Page Macros / Initializations} - -\registerctxluafile{page-ini}{} - -%D The \type {\processpage} command has become obsolete. It's original -%D purpose was to flush only parts of a document but nowadays we have -%D project structure and modes. This is just one of those very early -%D features that no longer makes sense. - -%D The \type {\couplepage} command has become obsolete. It's original -%D purpose was to provide hooks for printer directives (like choosing -%D different paper trays). - -\unprotect - -%D Shipout control. - -\newcount\nofshipouts - -\appendtoks - \global\advance\nofshipouts\plusone -\to \everyaftershipout - -\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled - -\protected\def\page_otr_shipout % not used at all - {\ifconditional\c_otr_shipout_enabled - \expandafter\page_otr_shipout_yes - \else - \expandafter\page_otr_shipout_nop - \fi} - -\aliased\let\page_otr_shipout_yes\normalshipout - -\protected\def\page_otr_shipout_nop - {\writestatus\m!system{ignoring shipout of real page \the\realpageno}% - \global\advance\realpageno\minusone % else no flush of resources - \dowithnextbox{\deadcycles\zerocount}} - -% We don't support direct user \shipouts (weird: this does not work, bug?) -% -% \let\shipout\page_otr_shipout_nop - -%D Building pages. - -\newbox\pagebox - -% \ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi -% \ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi -% \ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi - -\newtoks\t_page_postprocessors_box -\newtoks\t_page_postprocessors_page -\newtoks\t_page_postprocessors_column - -\newconstant\b_page_postprocessor - -\def\page_apply_postprocessors_box#1% - {\b_page_postprocessor#1\relax - \the\t_page_postprocessors_box} - -\def\page_apply_postprocessors_page#1% - {\b_page_postprocessor#1\relax - \the\t_page_postprocessors_page} - -\def\page_apply_postprocessors_column#1% - {\b_page_postprocessor#1\relax - \the\t_page_postprocessors_column} - -%D Floats. - -\def\page_otr_flush_all_floats - {%\flushnotes already done - \ifconditional\c_page_floats_some_waiting - \page_otr_command_flush_all_floats - \fi} - -\def\page_otr_insert_dummy_page - {\par - \ifvmode - \page_otr_flush_all_floats - \fixedspace - \vfill - \page_otr_command_next_page - \fi} - -\def\page_otr_flush_pending_content - {\vkern\zeropoint\relax - \ifvoid\normalpagebox \else - \unvbox\normalpagebox - \penalty\outputpenalty - \fi} - -\newconstant\c_page_postponed_mode % \c_page_postponed_mode\plusone -\newbox \b_page_otr_saved - -\installoutputroutine\savepagecontent - {\global\setbox\b_page_otr_saved\box\normalpagebox} - -\permanent\protected\def\flushpagecontent - {\ifvoid\b_page_otr_saved\else\unvbox\b_page_otr_saved\fi} - -% Test case: assumes one group level for output routine, todo: -% a toks. -% -% \starttext -% -% \startbuffer[makeup] -% \startpagemakeup[pagestate=start,page=no] -% \color[red]{ -% \vfill -% \dorecurse{3}{ -% \samplefile{klein} -% \vfill -% } -% } -% \stoppagemakeup -% \stopbuffer -% -% \startcolor[green] -% \dorecurse{10}{ -% \dontleavehmode{\bf 1:#1:} \samplefile{sapolsky}\par -% } -% \stopcolor -% -% \startpostponing % [+3] -% \getbuffer[makeup] -% \stoppostponing -% -% \startcolor[blue] -% \dorecurse{25}{ -% \dontleavehmode{\bf 2:#1:} \samplefile{sapolsky}\par -% } -% \stopcolor -% -% \stoptext - -\def\page_otr_construct_and_shipout#1#2#3% - {\forgetall - \page_boxes_shipout{\page_boxes_constructed_page#1#2}% \hbox removed - \page_otr_flush_pending_content - % not really needed, replaced by \flushsavedfloats - \page_otr_check_for_pending_inserts - % but does not hurt either (we're still in the otr!) - \inpagebodytrue % needed for enabling \blank ! brrr - \pagebodymode\plusone % todo: \plustwo when spread - \page_otr_command_flush_saved_floats - \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns - \strc_pagenumbers_increment_counters % should hook into an every - \page_adapts_synchronize - \page_otr_check_for_pending_inserts - \page_otr_command_flush_facing_floats - \page_floats_flush_page_floats % before postponed blocks - \page_spread_flush % defined later - \ifnum#3=\plusone - % this is tricky! we need to make sure we are in the output group - \ifnum\c_page_postponed_mode=\plusone - \aftergroup\page_postponed_blocks_flush - \else - \page_postponed_blocks_flush - \fi - \else - \page_postponed_blocks_flush - \fi} - -% Can't we get rid of this hackery? It's used in some widgets -% stuff so probably not. - -\newbox\b_page_otr_special - -\def\page_otr_flush_special_content - {\ifvoid\b_page_otr_special \else - \box\b_page_otr_special - \fi} - -\def\page_otr_add_special_content - {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox} - -\def\page_otr_add_special_content_indeed - {\wd\nextbox\zeropoint - \ht\nextbox\zeropoint - \dp\nextbox\zeropoint - \global\setbox\b_page_otr_special\hbox - {%\hskip-\maxdimen % not here, fails in acrobat (clips) - \box\b_page_otr_special\box\nextbox}}% was \unhbox, is now box again - -\let\flushatshipout\page_otr_add_special_content - -\maxdeadcycles=1000 - -\newtoks\afterpage \newtoks\aftereverypage -\newtoks\beforepage \newtoks\beforeeverypage - -\newif\ifarrangingpages \arrangingpagesfalse - -\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off - -% \appendtoks -% \ifcase\pageornamentstate \or -% \pageornamentstate\zerocount -% \fi -% \to \everyaftershipout - -\appendtoks - \ifcase\pageornamentstate \or - \global\pageornamentstate\zerocount - \fi -\to \everyaftershipout - -% Mark synchronization - -\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages - -\def\page_marks_synchronize_page#1% box - {\strc_markings_synchronize\v!page{#1}{\ifconditional\c_page_marks_building_successive_pages\v!keep\fi}} - -\def\page_marks_synchronize_column#1#2#3#4% first last column box - {\ifnum#3=#1\relax - \strc_markings_synchronize{\number#3,\v!column:\number#3,\v!first,\v!column:\v!first}{#4}{}% - \orelse\ifnum#3=#2\relax - \strc_markings_synchronize{\number#3,\v!column:\number#3,\v!last, \v!column:\v!last }{#4}{}% - \else - \strc_markings_synchronize{\number#3,\v!column:\number#3 }{#4}{}% - \fi} - -% Page body building - -\newconditional\c_page_boxes_save_page_body -\newbox \b_page_boxes_saved_page_body - -\def\page_boxes_constructed_page_body#1#2% - {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup - \boxmaxdepth\maxdimen % new - \dontcomplain - \page_marks_synchronize_page {#2}% we could consider doing this for \pagebox (needs testing) - \page_boxes_construct_content \pagebox{#1}{#2}% - \page_backgrounds_add_to_main \pagebox - \page_boxes_apply_offsets \pagebox - \page_info_add_to_box \pagebox - \ifcase\pageornamentstate - \page_backgrounds_add_to_paper \pagebox - \fi - \anch_positions_register_page \pagebox - \ifarrangingpages - \page_boxes_apply_shift_paper \pagebox % \v!paper - \else - \page_boxes_apply_clip_paper \pagebox - \page_marks_add_page \pagebox - \page_boxes_apply_replicate \pagebox - \page_boxes_apply_scale \pagebox - \page_boxes_apply_mirror_paper \pagebox - \page_boxes_apply_orientate_paper \pagebox - \page_marks_add_more \pagebox - \page_boxes_apply_center \pagebox - \page_backgrounds_add_to_print \pagebox - \page_boxes_apply_mirror_print \pagebox - \page_boxes_apply_orientate_print \pagebox - \page_boxes_apply_shift_print \pagebox % \v!page - \page_boxes_apply_offset \pagebox - \page_boxes_apply_negate_print \pagebox - \fi - \box\pagebox - \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi} - -\appendtoks - \restoreglobalbodyfont - \pickupattributes -\to \everybeforepagebody - -% if we really need this ... we need to bypass \permanent - -% \ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed? -% -% \prependtoks -% \let\nextbox\nestednextbox -% \to \everybeforepagebody - -\def\page_boxes_constructed_page#1#2% - {\vpack\bgroup % intercept spurious spaces - \the\everybeforepagebody - \starttextproperties - \checkmarginblocks - \the\beforeeverypage - \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% - \inpagebodytrue - \pagebodymode\plusone % todo: \plustwo when spread - \page_boxes_constructed_page_body#1#2% - \normalexpanded{\global\afterpage \emptytoks\the\afterpage }% - \the\aftereverypage - \resetpagebreak - \resetlayouttextlines % will go to \aftereverypage - \stoptextproperties - \the\everyafterpagebody - \egroup} - -\permanent\def\doifelsetopofpage - {\ifdim\pagegoal=\maxdimen - \expandafter\firstoftwoarguments - \orelse\ifdim\pagegoal=\vsize - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiftopofpageelse\doifelsetopofpage - -% %D Idea: -% -% \newinsert\thispageinsert % <- installinsertion -% -% \def\flushatthispage -% {\bgroup -% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}% -% \hbox} -% -% \appendtoks -% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi -% \to \everyshipout - -% not yet in i-* file - -\installcorenamespace{markedpage} - -% todo: just define at the lua end ... less hassle - -\permanent\tolerant\protected\def\markpage [#1]#*[#2]{\clf_markpage {#1}{#2}} -\permanent \def\markedpages [#1]{\clf_markedpages {#1}} % expandable -\permanent\protected \def\doifelsemarkedpage#1{\clf_doifelsemarkedpage{#1}} -\permanent\protected \def\startmarkpages [#1]{\clf_startmarkpages {#1}} -\permanent\protected \def\stopmarkpages {\clf_stopmarkpages } - -%D Experimental: - -\newconstant\c_page_force_strut_depth_trace_mode - -\installtextracker - {otr.forcestrutdepth} - {\c_page_force_strut_depth_trace_mode\plusone} - {\c_page_force_strut_depth_trace_mode\zerocount} - -\installoutputroutine\forcestrutdepth - {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode - \unvbox\normalpagebox} - -\installoutputroutine\forcestrutdepthplus % experimental - {\clf_forcestrutdepthplus\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode - \unvbox\normalpagebox} - -% maybe better: -% -% \installoutputroutine\doforcestrutdepth -% {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode -% \unvbox\normalpagebox} -% -% \protected\def\forcestrutdepth -% {\par\ifvmode\ifinner\else\doforcestrutdepth\fi\fi} - -% Also experimental: - -\permanent\protected\def\doifelsependingpagecontent{\clf_doifelsependingpagecontent} -% \permanent\protected\let\doifelsependingpagecontent\clf_doifelsependingpagecontent - -\protect \endinput diff --git a/tex/context/base/mkiv/page-ins.mkiv b/tex/context/base/mkiv/page-ins.mkiv index 96088b79e..6f2b56f82 100644 --- a/tex/context/base/mkiv/page-ins.mkiv +++ b/tex/context/base/mkiv/page-ins.mkiv @@ -51,13 +51,8 @@ \fi \to \everysetupinsertion -\ifcase\contextlmtxmode - \setupinsertion - [\c!anchoring=\v!none] -\else - \setupinsertion - [\c!anchoring=\v!auto] -\fi +\setupinsertion + [\c!anchoring=\v!none] \appendtoks \page_inserts_check_anchoring diff --git a/tex/context/base/mkiv/page-lay.mkxl b/tex/context/base/mkiv/page-lay.mkxl deleted file mode 100644 index 063268527..000000000 --- a/tex/context/base/mkiv/page-lay.mkxl +++ /dev/null @@ -1,1623 +0,0 @@ -%D \module -%D [ file=page-lay, -%D version=2000.10.20, % copied from main-001 -%D title=\CONTEXT\ Page Macros, -%D subtitle=Layout Specification, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Page Macros / Layout Specification} - -%D Before you start wondering why some of the page related modules skip upward or -%D left in order to place elements, you must realize that the reference point is the -%D top left corner of the main typesetting area. One reason for this choice is that -%D it suited some viewers that displayed page areas. Another reason is that margins, -%D edges and top and bottom areas are kind of virtual, while the header, text and -%D footer areas normally determine the text flow. - -\unprotect - -%D The dimensions related to layout areas are represented by real dimensions. - -\newdimen\paperheight \paperheight = 297mm -\newdimen\paperwidth \paperwidth = 210mm -\newdimen\paperoffset \paperoffset = \zeropoint -\newdimen\paperbleed \paperbleed = \zeropoint -\newdimen\spinewidth \spinewidth = \zeropoint - -\newdimen\printpaperheight \printpaperheight = \paperheight -\newdimen\printpaperwidth \printpaperwidth = \paperwidth - -\newdimen\makeupheight % calculated -\newdimen\makeupwidth % calculated - -\newdimen\textheight % calculated -\newdimen\textwidth % calculated - -\newdimen\topspace \topspace = 2cm -\newdimen\backspace \backspace = \topspace -\newdimen\cutspace \cutspace = \zeropoint -\newdimen\bottomspace \bottomspace = \zeropoint - -\newdimen\headerheight \headerheight = 2cm -\newdimen\footerheight \footerheight = \headerheight - -\newdimen\topoffset \topoffset = \zeropoint -\newdimen\backoffset \backoffset = \topoffset - -\newdimen\leftmarginwidth \leftmarginwidth = 3cm -\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth - -\newdimen\leftedgewidth \leftedgewidth = 3cm -\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth - -\newdimen\topheight \topheight = \zeropoint -\newdimen\bottomheight \bottomheight = \topheight - -\newcount\layoutlines \layoutlines = \zerocount -\newcount\layoutcolumns \layoutcolumns = \zerocount -\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint -\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint - -\newdimen\totaltextwidth - -%D The next series of dimensions are complemented by left and rights ones. - -\newdimen\margindistance -\newdimen\edgedistance -\newdimen\marginwidth -\newdimen\edgewidth - -%D Because a distance does not really makes sense when there is no area, we use a -%D zero distance in case there is no area. - -%D The horizontal distances are: - -\newdimen\leftedgedistance -\newdimen\rightedgedistance -\newdimen\leftmargindistance -\newdimen\rightmargindistance - -%D The vertical distances are: - -\newdimen\topdistance -\newdimen\headerdistance -\newdimen\textdistance -\newdimen\footerdistance -\newdimen\bottomdistance - -\newdimen\textovershoot % available in pagebuilder - -%D We need to calculate the extra distances: - -\newdimen\naturalmarginwidth -\newdimen\naturaledgewidth -\newdimen\naturalmargindistance -\newdimen\naturaledgedistance -\newdimen\naturalleftedgedistance -\newdimen\naturalrightedgedistance -\newdimen\naturalleftmargindistance -\newdimen\naturalrightmargindistance -\newdimen\naturaltopdistance -\newdimen\naturalheaderdistance -\newdimen\naturaltextdistance -\newdimen\naturalfooterdistance -\newdimen\naturalbottomdistance - -%D Now we've come to the setup and definition commands. - -\installcorenamespace{layout} -\installcorenamespace{layoutlocation} -\installcorenamespace{layoutalternative} -\installcorenamespace{layoutcolumn} -\installcorenamespace{layoutmethod} - -\installswitchcommandhandler \??layout {layout} \??layout - -\appendtoks - \doifnothing{\directlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}% -\to \everydefinelayout - -\appendtoks - \ifcase\layoutsetupmode - % can't happen - \or % \setuplayout[name][key=value] - \ifx\previouslayout\currentlayout - \letlayoutparameter\c!state\v!normal % global ? still needed ? - \let\currentlayout\currentlayout - \page_layouts_synchronize - \page_layouts_check_next - \fi - \or % \setuplayout[key=value] - % we can inherit so we always synchronize - \letlayoutparameter\c!state\v!normal % global ? still needed ? - \let\currentlayout\previouslayout - \page_layouts_synchronize - \page_layouts_check_next - \or % \setuplayout[name] - \ifx\currentlayout\v!reset - \let\currentlayout\empty - \fi - \letlayoutparameter\c!state\v!normal % global ? still needed ? - \glet\currentlayout\currentlayout % global - \page_layouts_synchronize - \page_layouts_check_next - \or % \setuplayout (reverts to main layout) - \letlayoutparameter\c!state\v!normal % global ? still needed ? - \glet\currentlayout\empty % global - \page_layouts_synchronize - \page_layouts_check_next - \fi -\to \everysetuplayout - -\permanent\def\doifelselayoutdefined#1% - {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiflayoutdefinedelse\doifelselayoutdefined - -\permanent\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi} - -% \newconditional\reverselayout - -\def\page_layouts_set_dimensions - {\global\naturalmarginwidth \layoutparameter\c!margin - \global\naturaledgewidth \layoutparameter\c!edge - \global\naturalmargindistance \layoutparameter\c!margindistance - \global\naturaledgedistance \layoutparameter\c!edgedistance - \global\naturalleftedgedistance \layoutparameter\c!leftedgedistance - \global\naturalrightedgedistance \layoutparameter\c!rightedgedistance - \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance - \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance - \global\naturaltopdistance \layoutparameter\c!topdistance - \global\naturalheaderdistance \layoutparameter\c!headerdistance - \global\naturaltextdistance \layoutparameter\c!textdistance - \global\naturalfooterdistance \layoutparameter\c!footerdistance - \global\naturalbottomdistance \layoutparameter\c!bottomdistance - % - \global\marginwidth \naturalmarginwidth - \global\edgewidth \naturaledgewidth - \global\margindistance \naturalmargindistance - \global\edgedistance \naturaledgedistance - % - \global\leftedgedistance \layoutdistance\leftedgewidth \naturalleftedgedistance - \global\rightedgedistance \layoutdistance\rightedgewidth \naturalrightedgedistance - \global\leftmargindistance \layoutdistance\leftmarginwidth \naturalleftmargindistance - \global\rightmargindistance \layoutdistance\rightmarginwidth\naturalrightmargindistance - \global\topdistance \layoutdistance\topheight \naturaltopdistance - \global\headerdistance \layoutdistance\headerheight \naturalheaderdistance - \global\textdistance \naturaltextdistance - \global\footerdistance \layoutdistance\footerheight \naturalfooterdistance - \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance} - -\def\page_layouts_set_distances % local in \setreducedvsize - {\headerdistance\layoutdistance\headerheight\naturalheaderdistance - \footerdistance\layoutdistance\footerheight\naturalfooterdistance} - -% these are wrong in the running text, assumes some swapping, needs a cleanup - -\newtoks\extralayoutcalculations - -\def\page_layouts_calculate_extras - {\the\extralayoutcalculations} - -\newtoks\everyswapmargins % watch the order ! - -\appendtoks - \enforced\swapcsvalues\leftmargindistance\rightmargindistance - \enforced\swapcsvalues\leftedgedistance \rightedgedistance - \enforced\swapcsvalues\leftmarginwidth \rightmarginwidth - \enforced\swapcsvalues\leftedgewidth \rightedgewidth - % - \enforced\swapcsvalues\leftmargintotal \rightmargintotal - \enforced\swapcsvalues\leftedgetotal \rightedgetotal - \enforced\swapcsvalues\leftsidetotal \rightsidetotal - \enforced\swapcsvalues\leftcombitotal \rightcombitotal - \enforced\swapcsvalues\innermargintotal \outermargintotal - \enforced\swapcsvalues\inneredgetotal \outeredgetotal - \enforced\swapcsvalues\innercombitotal \outercombitotal - \enforced\swapcsvalues\innersidetotal \outersidetotal -\to \everyswapmargins - -%D The papersize macros have a long history and we don't want to change the commands -%D so they keep looking a bit complex. - -%D \macros -%D {definepapersize} -%D -%D Before we start calculating layout dimensions, we will first take care of paper -%D sizes. The first argument can be either an assignment (for defaults) or an -%D identifier, in which case the second argument is an assignment. -%D -%D \showsetup{definepapersize} -%D -%D Yet undocumented, let's see if it gets noticed. -%D -%D \starttyping -%D \definepapersize[main] [A4] [A4] -%D \definepapersize[extra][A4,landscape][A4,landscape] -%D -%D \starttext -%D \setuppapersize[main] -%D Page 1. \page -%D Page 2. \page -%D \setuppapersize[extra] -%D Page 2 \page -%D \setuppapersize[main] -%D Page 3. \page -%D Page 4. \page -%D \adaptpapersize[extra] -%D Page 5. \page -%D Page 6. \page -%D \stoptext -%D \stoptyping -%D -%D \macros -%D {setuppaper,setuppapersize} -%D -%D When setting up the papersize on which to typeset and print, we can also -%D determine some more characteristics. -%D -%D \showsetup{setuppapersize} -%D -%D We keep track of these features with the following -%D variables. - -\installcorenamespace{layouttarget} -\installcorenamespace{layoutpaper} -\installcorenamespace{layoutprint} -\installcorenamespace{layoutcurrent} - -\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler - -\newconditional\c_page_target_paper_mirror -\newconstant \c_page_target_paper_orientation -\newconstant \c_page_target_paper_reverse -\newconditional\c_page_target_paper_landscape -\newconditional\c_page_target_paper_negate - -\newconditional\c_page_target_print_mirror -\newconstant \c_page_target_print_orientation -\newconstant \c_page_target_print_reverse -\newconditional\c_page_target_print_landscape -\newconditional\c_page_target_print_negate -\newconditional\c_page_target_print_doublesided - -\let\v_page_target_left_fill \relax -\let\v_page_target_right_fill \relax -\let\v_page_target_top_fill \relax -\let\v_page_target_bottom_fill\relax - -\let\papersize \empty -\let\printpapersize\empty - -\def\v_page_target_top {\namedlayouttargetparameter\papersize\c!top } -\def\v_page_target_bottom {\namedlayouttargetparameter\papersize\c!bottom} -\def\v_page_target_left {\namedlayouttargetparameter\papersize\c!left } -\def\v_page_target_right {\namedlayouttargetparameter\papersize\c!right } -\def\v_page_target_method {\rootlayouttargetparameter \c!method} -\def\v_page_target_scale {\rootlayouttargetparameter \c!scale } -\def\v_page_target_nx {\numexpr\rootlayouttargetparameter \c!nx \relax} -\def\v_page_target_ny {\numexpr\rootlayouttargetparameter \c!ny \relax} -\def\v_page_target_dx {\dimexpr\rootlayouttargetparameter \c!dx \relax} -\def\v_page_target_dy {\dimexpr\rootlayouttargetparameter \c!dy \relax} -\def\v_page_target_width {\dimexpr\rootlayouttargetparameter \c!width \relax} -\def\v_page_target_height {\dimexpr\rootlayouttargetparameter \c!height \relax} -\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter \c!topspace \relax} -\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter \c!backspace\relax} -\def\v_page_target_offset {\dimexpr\rootlayouttargetparameter \c!offset \relax} - -\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax} - -%D Normally we will not use this command directly but for now it works out okay. In -%D the future we might use more of the related commands. - -\setuplayouttarget - [% these are rather special - \c!nx=1, - \c!ny=1, - \c!dx=\zeropoint, - \c!dy=\zeropoint, - \c!topspace=\zeropoint, - \c!backspace=\zeropoint, - \c!width=\zeropoint, - \c!height=\zeropoint, - % - \c!method=\v!normal, - \c!option=\v!max, - \c!alternative=\v!normal, - % - \c!scale=1, - \c!offset=\zeropoint, - % - \c!top=, - \c!bottom=, - \c!left=, - \c!right=, - % - \c!location=] - -% \definepapersize[name][A4][A3] -% \definepapersize[name][settings] - -\permanent\tolerant\protected\def\definepapersize[#1]#*[#2]#*[#3]% - {\edef\currentlayouttarget{#1}% - \ifempty\currentlayouttarget - % invalid target - \orelse\ifhastok={#2}% - \definelayouttarget[#1][#2]% - \else - \setevalue{\??layoutpaper#1}{#2}% - \ifparameter#3\or - \setevalue{\??layoutprint#1}{#3}% - \else - \setevalue{\??layoutprint#1}{#2}% - \fi - \fi} - -\appendtoks - \letvalue{\??layoutcurrent\currentlayouttarget}\relax -\to \everydefinelayouttarget - -%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi} -%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi} - -\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi} -\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi} - -% \setuppaper [page=A4,paper=A3] % the k/v variant, changes the current page mapping -% \setuppapersize[A4][a=b,c=d] % the k/v variant, changes nothing, just settings -% \setuppapersize[A4][A3] % changes the current page mapping - -\let\page_paper_reinstate\relax -\let\page_paper_restore \relax - -\permanent\tolerant\protected\def\setuppapersize[#1]#*[#2]% - {\ifarguments - \page_paper_restore - \orelse\ifhastok={#1}% - \page_paper_setup_size_settings[#1]% - \orelse\ifhastok={#2}% - \page_paper_setup_size_settings_by_name[#1][#2]% - \else - \page_paper_setup_size_change_size[#1][#2]% - \fi} - -\protected\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size - {\let\currentlayouttarget\empty - \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% - \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% - \setupcurrentlayouttarget[#1]% - \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% - \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% - \ifx\m_layouttarget_paper_saved\m_layouttarget_paper - \ifx\m_layouttarget_print_saved\m_layouttarget_print - % we didn't change the size, maybe only sx or sy or so - \else - \page_paper_setup_size_settings_recalibrate - \fi - \else - \page_paper_setup_size_settings_recalibrate - \fi} - -\def\page_paper_setup_size_settings_recalibrate - {\ifempty\m_layouttarget_paper - % forget about it - \else - \ifempty\m_layouttarget_print - \let\m_layouttarget_print\m_layouttarget_paper - \fi - \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]% - \fi - \letlayouttargetparameter\c!page \papersize - \letlayouttargetparameter\c!paper\printpapersize} - -\protected\def\page_paper_setup_size_settings_by_name[#1][#2]% - {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}% - \setuplayouttarget[#2]} - -\protected\def\page_paper_setup_size_change_size[#1][#2]% - {\doifelsenothing{#2} - {\page_paper_set_current[#1][#1]} - {\page_paper_set_current[#1][#2]}} - -\permanent\let\setuppaper\page_paper_setup_size_settings - -\permanent\protected\def\adaptpapersize - {\glet\page_paper_reinstate\page_paper_restore - \setuppapersize} - -\appendtoks - \page_paper_reinstate - \glet\page_paper_reinstate\relax -\to \everyaftershipout - -\protected\def\page_paper_set_restore#1#2% - {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}} - -\protected\def\page_paper_set_current[#1][#2]% - {\normalexpanded{\page_paper_set_current_indeed - [\page_paper_the_paper_size{#1}]% - [\page_paper_the_print_size{#2}]}} - -\protected\def\page_paper_reset_paper - {\global\setfalse\c_page_target_paper_landscape - \global\setfalse\c_page_target_paper_mirror - \global\setfalse\c_page_target_paper_negate - \global\c_page_target_paper_orientation\uprotationangle - \global\c_page_target_paper_reverse \uprotationangle} - -\protected\def\page_paper_reset_print - {\global\setfalse\c_page_target_print_landscape - \global\setfalse\c_page_target_print_mirror - \global\setfalse\c_page_target_print_negate - \global\c_page_target_print_orientation\uprotationangle - \global\c_page_target_print_reverse \uprotationangle} - -\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper -\letvalue{\??layoutprint\v!reset}\page_paper_reset_print - -\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape} -\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror} -\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate} -\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle - \global\c_page_target_paper_reverse \leftrotationangle} -\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle - \global\c_page_target_paper_reverse \leftrotationangle} -\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle - \global\c_page_target_paper_reverse \zerocount} -\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle - \global\c_page_target_paper_reverse \rightrotationangle} - -\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape} -\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror} -\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate} -\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle - \global\c_page_target_print_reverse \leftrotationangle} -\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle - \global\c_page_target_print_reverse \leftrotationangle} -\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle - \global\c_page_target_print_reverse \zerocount} -\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle - \global\c_page_target_print_reverse \rightrotationangle} - -%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi} -%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi} - -\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname} -\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname} - -\protected\def\page_paper_identify_target#1% - {\ifcsname\??layoutcurrent#1\endcsname - \edef\currentlayouttarget{#1}% - \fi} - -\newdimen\d_page_minimum_paper_size \d_page_minimum_paper_size\luaexpr{math.pi}\onebasepoint - -\protected\def\page_paper_set_current_indeed[#1][#2]% - {\edef\m_page_asked_paper{#1}% can be the restores - \edef\m_page_asked_print{#2}% - % - \page_paper_set_restore\m_page_asked_paper\m_page_asked_print - % - % locate page target - \let\currentlayouttarget\empty - \page_paper_reset_paper - \processcommacommand[\m_page_asked_paper]\page_paper_identify_target - \ifempty\currentlayouttarget - \let\currentlayouttarget\currentpage - \fi - \glet\papersize\currentlayouttarget - \page_paper_reset_paper - \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option - \global\paperwidth \layouttargetparameter\c!width \relax - \global\paperheight\layouttargetparameter\c!height\relax - \ifdim\paperwidth<\d_page_minimum_paper_size - \global\paperwidth\d_page_minimum_paper_size - \fi - \ifdim\paperheight<\d_page_minimum_paper_size - \global\paperheight\d_page_minimum_paper_size - \fi - \ifconditional\c_page_target_paper_landscape - \enforced\global\swapcsvalues\paperwidth\paperheight - \fi - \ifinpagebody % local freeze - \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}% - \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}% - \fi - % - \page_paper_set_offsets - % locate paper target - \page_paper_reset_print - \processcommacommand[\m_page_asked_print]\page_paper_identify_target - \glet\printpapersize\currentlayouttarget - \page_paper_reset_print - \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option - \global\printpaperwidth \layouttargetparameter\c!width \relax - \global\printpaperheight\layouttargetparameter\c!height\relax - \ifdim\printpaperwidth<\onepoint - \global\printpaperwidth\paperwidth - \fi - \ifdim\printpaperheight<\onepoint - \global\printpaperheight\paperheight - \fi - \ifconditional\c_page_target_print_landscape - \enforced\global\swapcsvalues\printpaperwidth\printpaperheight - \fi - % this check can be confusing, so we've added the possibility - % to bypass this test: \setuppapersize[option=fit] - \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}% - \ifx\m_page_asked_option\v!max % \v!fit is - \begingroup - % we need to pre-swap else we get the wrong paper size - \ifnum\c_page_target_paper_orientation=\rightrotationangle - \enforced\swapcsvalues\paperwidth\paperheight - \orelse\ifnum\c_page_target_paper_orientation=\leftrotationangle - \enforced\swapcsvalues\paperwidth\paperheight - \fi - \ifnum\c_page_target_print_orientation=\rightrotationangle - \enforced\swapcsvalues\printpaperwidth\printpaperheight - \orelse\ifnum\c_page_target_print_orientation=\leftrotationangle - \enforced\swapcsvalues\printpaperwidth\printpaperheight - \fi - \ifdim\paperheight>\printpaperheight - \global\printpaperheight\paperheight - \writestatus\m!system{print height forced to paper height}% - \fi - \ifdim\paperwidth>\printpaperwidth - \global\printpaperwidth\paperwidth - \writestatus\m!system{print width forced to paper width}% - \fi - \endgroup - \fi - %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}% - \page_layouts_synchronize - % new but we assume \setuplayout - \scrn_canvas_synchronize_only} - -\ifdefined\scrn_canvas_synchronize_only \else - \let\scrn_canvas_synchronize_only\relax -\fi - -\ifdefined\page_paper_set_offsets \else - - \def\page_paper_set_offsets % will move - {\global\paperoffset\v_page_target_offset - \global\advance\paperwidth -2\paperoffset - \global\advance\paperheight-2\paperoffset} - -\fi - -\ifdefined\synchronizegridsnapping \else - \let\synchronizegridsnapping\relax -\fi - -\let\p_page_layouts_width \empty -\let\p_page_layouts_height\empty - -\def\page_layouts_synchronize - {\setups[\layoutparameter\c!preset]\relax - \global\leftmarginwidth \layoutparameter\c!leftmargin - \global\rightmarginwidth\layoutparameter\c!rightmargin - \global\leftedgewidth \layoutparameter\c!leftedge - \global\rightedgewidth \layoutparameter\c!rightedge - \global\headerheight \layoutparameter\c!header - \global\footerheight \layoutparameter\c!footer - \global\bottomheight \layoutparameter\c!bottom - \global\topheight \layoutparameter\c!top - \global\backspace \layoutparameter\c!backspace - \global\topspace \layoutparameter\c!topspace - \page_layouts_set_dimensions - \synchronizegridsnapping - \usesetupsparameter\layoutparameter % depends on gridsnapping ! - \synchronizewhitespace - \synchronizeblank - \setupinterlinespace[\v!reset]% \synchronizegloballinespecs - \global\cutspace\layoutparameter\c!cutspace\relax - \edef\p_page_layouts_width{\layoutparameter\c!width}% - \ifx\p_page_layouts_width\v!middle - \ifzeropt\cutspace - \global\cutspace\backspace - \fi - \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax - \orelse\ifx\p_page_layouts_width\v!fit - \ifzeropt\cutspace - \global\cutspace\backspace - \fi - \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax - \scratchdimen\dimexpr\backspace - -\leftedgewidth -\leftedgedistance - -\leftmarginwidth-\leftmargindistance\relax - \ifdim\scratchdimen<\zeropoint - \scratchdimen\zeropoint - \fi - \global\advance\makeupwidth\dimexpr - -\rightmargindistance-\rightmarginwidth - -\rightedgedistance -\rightedgewidth - -\scratchdimen\relax - \else - \global\makeupwidth\p_page_layouts_width\relax - \ifzeropt\cutspace - \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax - % \else - % A kind of inconsistent specification, but used - % in for instance s-pre-19.tex; the cutspace is - % used only for determining some kind of right - % margin; don't use this in doublesided mode - \fi - \fi - \scratchdimen\layoutparameter\c!bottomspace\relax - %\ifzeropt\scratchdimen - % \scratchdimen\topspace - %\fi - \global\bottomspace\layoutparameter\c!bottomspace\relax - \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty - \ifcase\layoutlines - \edef\p_page_layouts_height{\layoutparameter\c!height}% - \ifx\p_page_layouts_height\v!middle - \ifzeropt\bottomspace - \global\bottomspace\topspace - \fi - \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax - \orelse\ifx\p_page_layouts_height\v!fit - \ifzeropt\bottomspace - \global\bottomspace\topspace - \fi - \global\makeupheight\dimexpr\paperheight-\bottomspace\relax - \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax - \ifdim\scratchdimen<\zeropoint - \scratchdimen\zeropoint - \fi - \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax - \else - \global\makeupheight\layoutparameter\c!height\relax - \ifzeropt\bottomspace - \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax - % \else - % inconsistent specification - \fi - \fi - \else - % beware, when the bodyfont changes (switched) this will change as well; implementing - % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set - % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we - % stick to the current method (after a night of experimenting ...2003/10/13) - \global\makeupheight\dimexpr - \layoutparameter\c!lines\lineheight-\strutheight+\topskip+ - \headerdistance+\headerheight+\footerdistance+\footerheight\relax - \fi - \backoffset\layoutparameter\c!horoffset\relax - \topoffset \layoutparameter\c!veroffset\relax - \ifdim\makeupwidth<\onepoint - \global\makeupwidth\onepoint - \fi - \ifdim\makeupheight<\onepoint - \global\makeupheight\onepoint - \fi - % handy in page builder - \global\totaltextwidth\dimexpr - \leftedgetotal - +\leftmargintotal - +\makeupwidth - +\rightmargintotal - +\rightedgetotal - \relax - % \page_layouts_check_next % here ? - \page_layouts_check_direction - \page_layouts_calculate_extras - \page_target_check_centering - \calculatehsizes - \calculatevsizes - \page_layouts_check_pseudo_columns - \page_backgrounds_recalculate} - -\def\page_layouts_check_direction - {\edef\p_direction{\layoutparameter\c!direction}% - \ifx\p_direction\v!reverse - \enforced\global\swapcsvalues\naturalleftedgedistance \naturalrightedgedistance - \enforced\global\swapcsvalues\naturalleftmargindistance\naturalrightmargindistance - \enforced\global\swapcsvalues\leftedgedistance \rightedgedistance - \enforced\global\swapcsvalues\leftmargindistance \rightmargindistance - \enforced\global\swapcsvalues\leftmarginwidth \rightmarginwidth - \enforced\global\swapcsvalues\leftedgewidth \rightedgewidth - \enforced\global\swapcsvalues\backspace \cutspace - \expandafter\setsystemmode - \else - \expandafter\resetsystemmode - \fi{reverselayout}} - -\def\page_layouts_check_pseudo_columns - {\global\layoutcolumns\layoutparameter\c!columns - \global\layoutcolumndistance\layoutparameter\c!columndistance - \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax - \ifnum\layoutcolumns>\plusone - \global\divide\layoutcolumnwidth\layoutcolumns - \dorecurse\layoutcolumns\page_layouts_check_pseudo_column - \fi} - -\def\page_layouts_check_pseudo_column - {\setxvalue{\??layoutcolumn\recurselevel}% - {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}} - -\letvalue{\??layoutcolumn0}\zeropoint - -\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs - {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname} - -\def\page_layouts_synchronize_at_start - {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check - \page_layouts_synchronize - \fi} - -\appendtoks - \page_layouts_synchronize_at_start % still needed? -\to \everystarttext - -% document: -% -% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page] -% -% \startstandardmakeup[page=blank] ... \stopstandardmakeup - -\ifdefined\lastpage \else \let\lastpage\!!plusone \fi - -\def\page_layouts_change#1% - {%\writestatus\m!layouts{changing to layout #1}% - \xdef\currentlayout{#1}% - \page_layouts_synchronize} - -\let\changetolayout\page_layouts_change % also public - -\def\v_real_page_normal {\the\realpageno} -\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax} - -\def\v_real_page_odd_or_even - {\ifodd\pagenoshift - \ifodd\realpageno\v!even\else\v!odd \fi - \else - \ifodd\realpageno\v!odd \else\v!even\fi - \fi} - -\let\v_real_page_current\v!current - -\def\v_real_page_named - {\ifnum\lastpage=\realpageno - \v!last - \orelse\ifnum\plusone=\realpageno - \v!first - \else - \__unknown__ - \fi} - -\let\v_page_layouts_pre_check\relax - -\def\page_layouts_check_default_indeed#1% - {\edef\m_page_check{#1} - \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}% - \ifx\m_page_state\v!start - \glet\v_page_layouts_pre_check\currentlayout - \glet\currentlayout\m_page_check - \page_layouts_synchronize - \orelse\ifx\m_page_state\v!repeat - \glet\v_page_layouts_pre_check\relax - \glet\currentlayout\m_page_check - \page_layouts_synchronize - \fi} - -\def\page_layouts_check_revert - {\glet\currentlayout\v_page_layouts_pre_check - \glet\v_page_layouts_pre_check\relax - \page_layouts_synchronize} - -\def\page_layouts_check_default - {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname - \page_layouts_check_default_indeed\v_real_page_normal - \orelse\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname - \page_layouts_check_default_indeed\v_real_page_reverse - \orelse\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname - \page_layouts_check_default_indeed\v_real_page_named - \orelse\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname - \page_layouts_check_default_indeed\v_real_page_current - \orelse\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname - \page_layouts_check_default_indeed\v_real_page_odd_or_even - \orelse\ifx\v_page_layouts_pre_check\relax - % okay - \else - \page_layouts_check_revert - \fi} - -\permanent\protected\def\installlayoutmethod#1#2% - {\setgvalue{\??layoutmethod#1}{#2}} - -\installlayoutmethod\v!default{\page_layouts_check_default} -\installlayoutmethod\v!normal {\page_layouts_check_default} - -% \def\page_layouts_check_next -% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname -% \layoutparameter\c!method -% \else -% \v!normal -% \fi\endcsname} - -\def\page_layouts_check_next - {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname - \lastnamedcs - \else - \page_layouts_check_default - \fi} - -\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay - -% inheritance -% -% \definelayout -% [test] -% [width=12cm, -% height=10cm] -% -% \definelayout -% [more] -% [test] -% [height=12cm] -% -% testcase -% -% \setuppagenumbering[alternative=doublesided] -% -% \setuplayout [width=11cm] -% \definelayout [odd] [backspace=1cm] -% \definelayout [even] [backspace=4cm] -% \definelayout [5] [backspace=5cm] -% \definelayout [6] [backspace=5cm] -% \definelayout [-2] [backspace=0cm,cutspace=0cm] -% \definelayout [last] [backspace=0cm,cutspace=0cm] -% -% \checkcurrentlayout \showframe -% -% \starttext -% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf} -% \stoptext - -% Because we want to keep the set parameters as they are we use some -% helpers to communicate between the several page building related -% mechanism. - -\appendtoks \page_layouts_check_next \to \everystarttext -\appendtoks \page_layouts_check_next \to \everyaftershipout - -\newconditional\c_page_layouts_location_is_set -\newconditional\c_page_layouts_location_is_middle - -\def\page_layouts_location_reset % we start in the left top and mirror right pages - {\setfalse\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \relax - \let\v_page_target_right_fill \hss % ? \relax - \let\v_page_target_top_fill \relax - \let\v_page_target_bottom_fill\vss} % \relax} - -\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \hss - \let\v_page_target_right_fill \relax} -\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \relax - \let\v_page_target_right_fill \hss} -\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_top_fill \vss - \let\v_page_target_bottom_fill\relax} -\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_top_fill \relax - \let\v_page_target_bottom_fill\vss} -\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set - \settrue\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \hss - \let\v_page_target_right_fill \hss - \let\v_page_target_top_fill \vss - \let\v_page_target_bottom_fill\vss} -\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_ - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_right_fill \hss - \let\v_page_target_bottom_fill\hss} -\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided} -\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided} - -\def\page_target_check_centering_indeed#1% - % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi} - {\begincsname\??layoutlocation#1\endcsname} - -\protected\def\page_target_check_centering - {\setfalse\c_page_target_print_doublesided - \page_layouts_location_reset - \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed} - -% installers - -\permanent\protected\def\installlayoutalternative#1#2% - {\setgvalue{\??layoutalternative#1}{#2}} - -\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box - {\setbox#1\vpack % was \vbox - {\offinterlineskip - \begingroup % needed ? - \uselayoutstyleandcolor\c!style\c!color - \offinterlineskip - \page_layouts_insert_elements % zero size - \endgroup - \page_insert_body#2#3}}% including footnotes - -\installlayoutalternative\v!default{\page_boxes_construct_content_default} -\installlayoutalternative\v!normal {\page_boxes_construct_content_default} - -% \def\page_boxes_construct_content % targetbox flusher box -% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname -% \layoutparameter\c!alternative -% \else -% \v!normal -% \fi\endcsname} - -\def\page_boxes_construct_content % targetbox flusher box - {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname - \expandafter\lastnamedcs - \else - \expandafter\page_boxes_construct_content_default - \fi} - -%D \macros -%D {adaptlayout} - -\installcorenamespace{adaptlayout} -\installcorenamespace{pageadaptations} - -\installsetuponlycommandhandler \??adaptlayout {adaptlayout} - -\newdimen\d_page_adepts_pushed_text_height -\newdimen\d_page_adepts_pushed_footer_height -\newdimen\d_page_adepts_height -\newdimen\d_page_adapts_delta - -\permanent\protected\tolerant\def\adaptlayout[#1]#*[#2]% - {\ifparameter#2\or - \processcommalist[#1]{\page_adapts_layout_register{#2}}% - \page_adapts_check - \else - \page_adapts_layout_indeed{#1}% - \fi} - -\def\page_adapts_layout_register#1#2% - {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}} - -\let\p_adapts_height\zeropoint -\let\p_adapts_lines \zerocount - -\def\page_adapts_layout_indeed#1% - {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]% - \page_adepts_push - \edef\p_adapts_height{\adaptlayoutparameter\c!height}% - \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}% - \ifx\p_adapts_height\v!max - \global\d_page_adepts_height\footerheight - \else - \global\d_page_adepts_height\dimexpr - \ifnum\p_adapts_lines=\zerocount - \p_adapts_height - \else - \p_adapts_lines\openlineheight - \fi - \relax - \ifdim\d_page_adepts_height>\footerheight - \global\d_page_adepts_height\footerheight - \fi - \fi - \global\advance\textheight \d_page_adepts_height - \global\advance\footerheight-\d_page_adepts_height - \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}% - % this will become a better one (do we need insert correction?) - \page_otr_command_set_vsize - % - \page_backgrounds_recalculate - \glet\page_adepts_push\relax - \glet\page_adepts_pop\page_adepts_pop_indeed} - -% \def\page_adapts_check -% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname} -% -% \def\page_adapts_reset -% {\ifcsname\??pageadaptations\the\realpageno\endcsname -% \global\undefinevalue{\??pageadaptations\the\realpageno}% -% \fi} - -\def\page_adapts_check - {\begincsname\??pageadaptations\the\realpageno\endcsname} - -\def\page_adapts_reset - {\ifcsname\??pageadaptations\the\realpageno\endcsname - \global\letcsname\??pageadaptations\the\realpageno\endcsname\relax - \fi} - -\def\page_adepts_push_indeed - {\global\d_page_adepts_pushed_text_height \textheight - \global\d_page_adepts_pushed_footer_height\footerheight} - -\def\page_adepts_pop_indeed - {\global\textheight \d_page_adepts_pushed_text_height - \global\footerheight\d_page_adepts_pushed_footer_height - \page_layouts_synchronize - \glet\page_adepts_push\page_adepts_push_indeed - \glet\page_adepts_pop\relax} - -\appendtoks \page_adapts_check \to \everystarttext -\appendtoks \page_adapts_reset \to \everyshipout - -\let\page_adepts_pop \relax -\let\page_adepts_push\page_adepts_push_indeed - -\protected\def\page_adapts_synchronize % used elsewhere - {\page_adepts_pop - \page_adapts_check} - -\def\page_adapts_status_info % used elsewhere - {\ifx\page_adepts_pop\relax \else - \space(adept: \the\d_page_adepts_height)\space - \fi - \the\realpageno} - -%D \macros -%D {startlayout,stoplayout} - -\permanent\protected\def\startlayout[#1]% - {\page - \globalpushmacro\currentlayout - \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}} - -\permanent\protected\def\stoplayout - {\page - \globalpopmacro\currentlayout - \setuplayout[\currentlayout]} - -% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET - -\ifx\doifelselayoutsomeline\undefined % eventually defined in page-txt - \let\doifelselayoutsomeline\secondofthreearguments -\fi - -\permanent\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} -\permanent\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} -\permanent\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} -\permanent\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} - -\permanent\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances} -\permanent\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances} - -\def\page_layouts_set_modes - {\ifzeropt\headerheight - \resetsystemmode\v!header - \else - \setsystemmode\v!header - \fi - \ifzeropt\footerheight - \resetsystemmode\v!footer - \else - \setsystemmode\v!footer - \fi} - -\permanent\protected\def\calculatevsizes % name will change - {\textheight\makeupheight - \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing - \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing - \page_layouts_set_modes - \resetglobal - \page_otr_command_set_vsize} - -\permanent\protected\def\calculateglobalvsizes % name will change - {\global\textheight\makeupheight - \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing - \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing - \page_layouts_set_modes - \page_otr_command_set_vsize} - -\permanent\protected\def\calculatereducedvsizes % name will change - {\textheight\makeupheight - \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero - \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero} - -\newdimen\innermakeupwidth % special purpose -\newdimen\innermakeupmargin % special purpose - -\newconditional\innermakeupcompensation \settrue\innermakeupcompensation - -\permanent\def\compensatedinnermakeupmargin - {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax} - -\permanent\protected\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth - {\textwidth\makeupwidth % which is a tricky but valid value - \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }% - \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}% - \ifempty\m_currentlayout_text_width \else - \textwidth\m_currentlayout_text_width % local - \fi - \global\innermakeupwidth\textwidth - \ifempty\m_currentlayout_text_margin - \global\innermakeupmargin\zeropoint - \else - \global\innermakeupmargin\m_currentlayout_text_margin\relax - \fi - \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax - \global\advance\innermakeupwidth-\scratchdimen - \advance\textwidth-\scratchdimen} % local - -\permanent\protected\def\calculatehsizes % name will change - {\freezetextwidth - \page_otr_command_set_hsize} - -%D When we start at an even page, we need to swap the layout differently. We cannot -%D adapt the real page number, since it is used in cross referencing. The next -%D switch is set when we start at an even page. - -% #single #left #right - -\permanent\def\doifelseoddpage - {\ifodd\pagenoshift - \expandafter\page_layouts_if_odd_else_yes - \else - \expandafter\page_layouts_if_odd_else_nop - \fi} - -\aliased\let\doifoddpageelse\doifelseoddpage - -\def\page_layouts_if_odd_else_yes - {\ifodd\realpageno - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\def\page_layouts_if_odd_else_nop - {\ifodd\realpageno - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\def\page_layouts_if_odd_else_again#1{\doifelseoddpage} - -\def\doifbothsidesoverruled - {\ifdoublesided - \expandafter\page_layouts_if_odd_else_again - \else - \expandafter\firstofthreearguments - \fi} - -\def\doifbothsides% #1 #2 #3 - {\ifdoublesided - \expandafter\page_layouts_if_both_sides - \else - \expandafter\firstofthreearguments - \fi} - -\def\page_layouts_if_both_sides - {\ifsinglesided - \expandafter\firstofthreearguments - \else - \expandafter\page_layouts_if_odd_else_again - \fi} - -\newdimen\texthoffset - -\permanent\protected\def\settexthoffset % name will change - {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}} - -\permanent\protected\def\goleftonpage % name will change (we could cache) - {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax} - -\permanent\def\doifelsemarginswap#1#2% protected? - {\doifbothsides{#1}{#1}{#2}} - -\aliased\let\doifmarginswapelse\doifelsemarginswap - -\def\swapmargins % name will change, frozen? - {\doifelsemarginswap\relax\doswapmargins} - -\def\doswapmargins % name will change, frozen? - {\let\swapmargins \relax % to prevent local swapping - \let\doswapmargins\relax % to prevent local swapping - \the\everyswapmargins} - -\permanent\def\rightorleftpageaction - {\ifdoublesided - \expandafter\page_layouts_right_or_left_page_action - \else - \expandafter\firstoftwoarguments - \fi} - -\def\page_layouts_right_or_left_page_action - {\ifsinglesided - \expandafter\firstoftwoarguments - \else - \expandafter\doifelseoddpage - \fi} - -% swapping needs frozen - -\permanent\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth } -\permanent\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth} -\permanent\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance } -\permanent\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance} - -\permanent\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth } -\permanent\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth} -\permanent\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance } -\permanent\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance} - -\permanent\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace} -\permanent\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace } - -\permanent\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax} -\permanent\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax} -\permanent\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax} -\permanent\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax} - -\permanent\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax} -\permanent\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax} -\permanent\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax} -\permanent\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax} - -\permanent\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax} -\permanent\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax} -\permanent\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax} -\permanent\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax} - -\permanent\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax} -\permanent\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax} -\permanent\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax} -\permanent\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax} - -%D \macros -%D {startlocallayout} -%D -%D These macros should be used with care. They permit local layouts (as used in -%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we -%D have \type {\definelayout}, so this hack will disappear in future versions. - -\permanent\protected\def\startlocallayout - {\globalpushmacro\page_paper_restore - \globalpushmacro\currentlayout} - -\permanent\protected\def\stoplocallayout - {\globalpopmacro\currentlayout - \globalpopmacro\page_paper_restore - \page_paper_restore - \setuplayout[\currentlayout]\relax} % explicit ! - -%D \macros -%D {showprint, showframe, showlayout, showsetups} -%D -%D We predefine a couple of tracing macros. -%D -%D \showsetup{showprint} -%D \showsetup{showframe} -%D \showsetup{showlayout} -%D \showsetup{showsetups} -%D %showsetup{showmargins} -%D %showsetup{showgrid} -%D %showsetup{showusage} - -\fetchruntimecommand \showprint \f!page_run -\fetchruntimecommand \showframe \f!page_run -\fetchruntimecommand \showlayout \f!page_run -\fetchruntimecommand \showsetups \f!page_run -\fetchruntimecommand \showmargins \f!page_run -\fetchruntimecommand \showgrid \f!page_run - -\glet\page_grids_add_to_box\gobbleoneargument -\glet\page_grids_add_to_one\gobbleoneargument -\glet\page_grids_add_to_mix\gobbleoneargument - -%D The default dimensions are quite old and will not change. The funny fractions -%D were introduced when we went from fixed dimensions to relative ones. Since -%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The -%D asymmetrical layout is kind of handy for short quick||and||dirty stapled -%D documents. -%D -%D Although valid, it is not a real good idea to use dimensions based on the \type -%D {em} unit. First of all, since there are no fonts loaded yet, this dimension -%D makes no sense, and second, you would loose track of values, since they could -%D change while going to a new page, depending on the current font setting. - -\setuplayout - [ \c!topspace=.08417508418\paperheight, % 2.5cm - \c!top=\zeropoint, - \c!topdistance=\zeropoint, - \c!header=.06734006734\paperheight, % 2.0cm - \c!headerdistance=\zeropoint, - \c!height=.84175084175\paperheight, % 25.0cm - \c!footerdistance=\layoutparameter\c!headerdistance, - \c!footer=.06734006734\paperheight, % 2.0cm - \c!bottomdistance=\layoutparameter\c!topdistance, - \c!bottom=\zeropoint, - \c!backspace=.11904761905\paperwidth, % 2.5cm - \c!edge=\zeropoint, - \c!edgedistance=\layoutparameter\c!margindistance, - \c!margin=.12649983170\paperwidth, % snijwit-2*afstand - \c!margindistance=.02008341748\paperwidth, % 12.0pt - \c!leftedge=\layoutparameter\c!edge, - \c!leftedgedistance=\layoutparameter\c!edgedistance, - \c!leftmargin=\layoutparameter\c!margin, - \c!leftmargindistance=\layoutparameter\c!margindistance, - \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\ - \c!rightmargindistance=\layoutparameter\c!margindistance, - \c!rightmargin=\layoutparameter\c!margin, - \c!rightedgedistance=\layoutparameter\c!edgedistance, - \c!rightedge=\layoutparameter\c!edge, - \c!veroffset=\zeropoint, - \c!bottomspace=\zeropoint, - \c!horoffset=\zeropoint, - \c!cutspace=\zeropoint, - \c!textwidth=, % dangerous option -> centered / local - \c!textmargin=, % dangerous option -> both sides - \c!textdistance=\zeropoint, % shift down on grid - \c!style=, - \c!color=, - \c!marking=\v!off, - \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange) - \c!state=\v!start, - \c!scale=1, - \c!sx=1, - \c!sy=1, - \c!nx=1, - \c!ny=1, - \c!dx=\zeropoint, - \c!dy=\zeropoint, - \c!grid=\v!no, - \c!direction=\v!normal, - \c!preset=, - \c!setups=\systemsetupsprefix\s!default, - \c!clipoffset=\zeropoint, - \c!lines=0, - \c!paper=, % for foxet - \c!page=, % for foxet - \c!columns=\plusone, - \c!columndistance=\zeropoint] - -%D First we define a whole range of (DIN) papersizes, of which the A-series makes -%D most sense. We enable checking. - -\definepapersize [A0] [\c!width=841mm,\c!height=1189mm] -\definepapersize [A1] [\c!width=594mm,\c!height=841mm] -\definepapersize [A2] [\c!width=420mm,\c!height=594mm] -\definepapersize [A3] [\c!width=297mm,\c!height=420mm] -\definepapersize [A4] [\c!width=210mm,\c!height=297mm] -\definepapersize [A5] [\c!width=148mm,\c!height=210mm] -\definepapersize [A6] [\c!width=105mm,\c!height=148mm] -\definepapersize [A7] [\c!width=74mm,\c!height=105mm] -\definepapersize [A8] [\c!width=52mm,\c!height=74mm] -\definepapersize [A9] [\c!width=37mm,\c!height=52mm] -\definepapersize [A10] [\c!width=26mm,\c!height=37mm] - -\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm -%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide - -\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm] -\definepapersize [B1] [\c!width=707mm,\c!height=1000mm] -\definepapersize [B2] [\c!width=500mm,\c!height=707mm] -\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm] -\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm] -\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm] -\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm] -\definepapersize [B7] [\c!width=88mm,\c!height=125mm] -\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm] -\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm] -\definepapersize [B10] [\c!width=31mm,\c!height=44mm] - -\definepapersize [C0] [\c!width=917mm,\c!height=1297mm] -\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm] -\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm] -\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm] -\definepapersize [C4] [\c!width=229mm,\c!height=324mm] -\definepapersize [C5] [\c!width=162mm,\c!height=229mm] -\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm] -\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm] -\definepapersize [C8] [\c!width=57mm,\c!height=81mm] -\definepapersize [C9] [\c!width=40mm,\c!height=57mm] -\definepapersize [C10] [\c!width=28mm,\c!height=40mm] - -%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the -%D latest DIN specifications. Peter Rolf came up with these and a few more missing -%D sizes. Watch out: spaces and slashes! - -\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm] -\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm] -\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm] - -%D Because there are no standardized screen sizes, we define a bunch of sizes with -%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4} -%D paper. - -\definepapersize [S3] [\c!width=300pt,\c!height=225pt] -\definepapersize [S4] [\c!width=400pt,\c!height=300pt] -\definepapersize [S5] [\c!width=500pt,\c!height=375pt] -\definepapersize [S6] [\c!width=600pt,\c!height=450pt] -\definepapersize [S8] [\c!width=800pt,\c!height=600pt] -\definepapersize [SL] [\c!width=640pt,\c!height=400pt] % low -\definepapersize [SM] [\c!width=720pt,\c!height=450pt] % medium -\definepapersize [SW] [\c!width=800pt,\c!height=450pt] % wide -\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt] -\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt] -\definepapersize [HD-] [\c!width=960pt,\c!height=540pt] - -%D These are handy too: - -\definepapersize [S33] [\c!width=300pt,\c!height=300pt] -\definepapersize [S44] [\c!width=400pt,\c!height=400pt] -\definepapersize [S55] [\c!width=500pt,\c!height=500pt] -\definepapersize [S66] [\c!width=600pt,\c!height=600pt] - -%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it -%D does not hurt to have the paper size ready. - -\definepapersize [CD] [\c!width=120mm,\c!height=120mm] - -%D The next series is for our English speaking friends who decided to stick to non -%D metric values. Thanks to Nelson Beebe for completing the inch based list. - -\definepapersize [letter] [\c!width=8.5in,\c!height=11in] -\definepapersize [ledger] [\c!width=11in,\c!height=17in] -\definepapersize [tabloid] [\c!width=17in,\c!height=11in] - -\definepapersize [legal] [\c!width=8.5in,\c!height=14in] -\definepapersize [folio] [\c!width=8.5in,\c!height=13in] -\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in] - -\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet -\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets -\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets - -%D The next set is for Tobias Burnus, who gave me the sizes. - -\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in] -\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in] -\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in] -\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in] -\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in] -\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in] -\definepapersize [check] [\c!width=8.58in,\c!height=3.88in] -\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm] -\definepapersize [E4] [\c!width=280mm,\c!height=400mm] - -%D The next three sets are supplied by Taco: - -\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm] -\definepapersize [RA1] [\c!width=610mm,\c!height=860mm] -\definepapersize [RA2] [\c!width=430mm,\c!height=610mm] -\definepapersize [RA3] [\c!width=305mm,\c!height=430mm] -\definepapersize [RA4] [\c!width=215mm,\c!height=305mm] - -%D ISO SRA (supplementary raw A) sizes: - -\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm] -\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm] -\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm] -\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm] -\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm] - -%D Swedish thesis formats: - -\definepapersize [G5] [\c!width=169mm,\c!height=239mm] -\definepapersize [E5] [\c!width=155mm,\c!height=220mm] - -%D Industry invention: - -\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm] - -%D For Alan: - -\definepapersize [business] [\c!width=85mm,\c!height=55mm] -\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in] - -%D We can now default to a reasonable size. We match the print paper size with the -%D typeset paper size. This setting should come after the first layout specification -%D (already done). - -% \definepapersize -% [\v!default] -% [ \c!width=\paperwidth, -% \c!height=\paperheight] - -% \definepapersize -% [samesized] -% [ \c!width=\paperwidth, -% \c!height=\paperheight] - -\setuppapersize - [\c!distance=1.5cm] % offset is already taken - -\definepapersize - [oversized] - [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax, - \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax] - -\definepapersize - [undersized] - [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax, - \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax] - -\definepapersize - [doublesized] - [ \c!width=\dimexpr \paperwidth \relax, - \c!height=\dimexpr2\paperheight\relax] - -\definepapersize - [doubleoversized] - [ \c!width=\dimexpr \paperwidth +\layouttargetparameter\c!distance\relax, - \c!height=\dimexpr2\paperheight+\layouttargetparameter\c!distance\relax] - -\definepapersize - [doublewide] - [ \c!width=\dimexpr2\paperwidth \relax, - \c!height=\dimexpr \paperheight\relax] - -% \setuppapersize -% [A4][A4] - -\setuppapersize - [A4] % [samesized] - -%D A few goodies, first a full page layout: - -\definelayout - [\v!page] - -\setuplayout - [\v!page] - [\c!backspace=\zeropoint, - \c!cutspace=\zeropoint, - \c!topspace=\zeropoint, - \c!bottomspace=\zeropoint, - \c!margin=\zeropoint, - \c!edge=\zeropoint, - \c!header=\zeropoint, - \c!footer=\zeropoint, - \c!top=\zeropoint, - \c!bottom=\zeropoint, - \c!leftmargin=\zeropoint, - \c!rightmargin=\zeropoint, - \c!leftedge=\zeropoint, - \c!rightedge=\zeropoint, - \c!textdistance=\zeropoint, - \c!width=\v!middle, - \c!height=\v!middle, - \c!lines=0, - \c!grid=\v!no] - -%D A quick and dirty one: - -\definelayout - [\v!middle] - [\c!width=\v!middle, - \c!height=\v!middle] - -%D One for testing examples (5mm is often the non printable area): - -\definelayout - [\v!tight] - -\definelayout - [\v!tight] - [\v!page] - [\c!backspace=5mm, - \c!cutspace=5mm, - \c!topspace=5mm, - \c!bottomspace=5mm] - -\protect \endinput diff --git a/tex/context/base/mkiv/page-mcl.mkxl b/tex/context/base/mkiv/page-mcl.mkxl deleted file mode 100644 index 112d9931d..000000000 --- a/tex/context/base/mkiv/page-mcl.mkxl +++ /dev/null @@ -1,543 +0,0 @@ -%D \module -%D [ file=page-mcl, -%D version=2020.07.26, % stripped down redone page-mul -%D title=\CONTEXT\ Page Macros, -%D subtitle=Multicolumns Limited, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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 / Multicolumns Limited} - -\unprotect - -%D Columns are kind of hairy in \TEX\ and we would be better if no one needed them. -%D Anyway, we do need some support and no mechanism can serve all. The original -%D multicolumn mechanism of \MKII\ was never fully adapted to \MKIV, where mixed -%D columns and page columns showed up instead. However, for some cases a dumb -%D mechanism makes sense, so again we introduce multi columns, but without float -%D hacks. This one will be optimized for mixed usage as for instance itemize needs. -%D Their main advantage is that they can better deal with notes, which are hairy in -%D themselves. This will (for now) only happen in \LMTX. -%D -%D The code is stripped down ancient \MKII\ code and might become cleaner as it -%D evolves. Macros keep similar names but take a different namespace. The code is -%D not yet perfect wrt spacing! - -% \enableexperiments[itemize.columns] -% -% \starttext -% -% \startmulticolumns -% \dorecurse{10}{\samplefile{ward}\footnote{note #1}\par} -% \stopmulticolumns -% -% \dorecurse{4}{\samplefile{ward}\par} -% -% \startitemize[packed,columns,two] -% \dorecurse{100}{\startitem test #1 \footnote{this is a footnote #1}\stopitem} -% \stopitemize -% -% \stoptext - -\ifdefined \startmulticolumns - - % we're testing and don't want to remake the format - -\else - -\installcorenamespace {multicolumns} - -\installframedcommandhandler \??multicolumns {multicolumns} \??multicolumns - -\newdimen \d_page_mcl_available_width -\newdimen \d_page_mcl_distance -\newdimen \d_page_mcl_leftskip -\newdimen \d_page_mcl_rightskip -\newdimen \d_page_mcl_used_width -\newdimen \d_page_mcl_temp -\newdimen \d_page_mcl_saved_pagetotal % brrr, still needed ? - -\newcount \c_page_mcl_balance_minimum -\newcount \c_page_mcl_n_of_lines - -\newbox \b_page_mcl_preceding -\newdimen \d_page_mcl_preceding_height -\newconditional\c_page_mcl_preceding_present - -\newbox \b_page_mcl_rest_of_page -\newbox \b_page_mcl_page - -\newconditional\c_page_mcl_reverse -\newconditional\c_page_mcl_balance - -\newconstant \c_page_mcl_routine - -\setnewconstant\c_page_mcl_routine_regular \zerocount -\setnewconstant\c_page_mcl_routine_intercept \plusone -\setnewconstant\c_page_mcl_routine_continue \plustwo -\setnewconstant\c_page_mcl_routine_balance \plusthree -\setnewconstant\c_page_mcl_routine_error \plusfour - -\newbox \b_page_mcl_balance_content -\newconstant \c_page_mcl_balance_tries_max -\newcount \c_page_mcl_balance_tries -\newdimen \d_page_mcl_balance_target -\newdimen \d_page_mcl_balance_natural_height -\newdimen \d_page_mcl_balance_step -\newconditional\c_page_mcl_balance_possible - -\c_page_mcl_balance_tries_max 250 % 100 is too small when floats are involved - -%def\m_page_mcl_overshoot_ratio{\ifgridsnapping0\else.5\fi} -\def\m_page_mcl_overshoot_ratio{.5} - -\fi - -\protected\def\page_mcl_command_set_hsize - {\d_page_mcl_available_width\dimexpr - \makeupwidth - -\d_page_mcl_leftskip - -\d_page_mcl_rightskip - -\nofcolumns\d_page_mcl_distance - +\d_page_mcl_distance - \relax - \d_page_mcl_used_width\dimexpr - \d_page_mcl_available_width/\nofcolumns - \relax - \textwidth\d_page_mcl_used_width - \hsize\d_page_mcl_used_width} - -\protected\def\page_mcl_set_n_of_lines#1% - {\d_page_mcl_temp\dimexpr - +\textheight - \ifdim\d_page_mcl_preceding_height>\zeropoint -\d_page_mcl_preceding_height \fi -% \ifdim\ht\b_page_mcl_preceding>\zeropoint -\ht\b_page_mcl_preceding \fi - -#1% - \relax - \getnoflines\d_page_mcl_temp - \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines - \noflines\layoutlines - \fi \fi - \c_page_mcl_n_of_lines\noflines} - -% \protected\def\page_mcl_command_set_vsize -% {%%\page_one_command_set_vsize % indeed? -% \page_mcl_set_n_of_lines\zeropoint -% \d_page_mcl_temp\nofcolumns\dimexpr -% \c_page_mcl_n_of_lines\openlineheight -% % +\m_page_mcl_overshoot_ratio\openlineheight % collect enough data -% \relax -% \global\vsize \d_page_mcl_temp -% \global\pagegoal\d_page_mcl_temp} % let's do it only here, reports maxdimen anyway - -\protected\def\page_mcl_command_set_vsize - {\global\vsize\dimexpr\nofcolumns\textheight+\nofcolumns\lineheight\relax - \pagegoal\dimexpr - \vsize -% -\d_page_floats_inserted_top % needs checking -% -\d_page_floats_inserted_bottom % needs checking - -\c_page_mix_n_of_columns\insertheights - \relax} - -\protected\def\page_mcl_command_routine - {\ifcase\c_page_mcl_routine - \page_one_command_routine - \or - \page_mcl_routine_intercept - \or - \page_mcl_routine_continue - \or - \page_mcl_routine_balance - \or - \page_mcl_routine_error - \fi} - -\let\page_mcl_command_package_contents\page_one_command_package_contents - -\def\page_mcl_routine_intercept - {\global\setbox\b_page_mcl_preceding\vbox - {\page_otr_command_flush_top_insertions - \unvbox\normalpagebox}} - -\def\page_mcl_routine_error - {\showmessage\m!columns3\empty - \page_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments - -\protected\def\page_mcl_initialize_variables - {\reseteverypar % maybe still freeze .... - \dontcomplain - \settopskip - \setmaxdepth - \topskip 1\topskip - \splittopskip \topskip - \splitmaxdepth \maxdepth - \boxmaxdepth \maxdepth % dangerous - \emergencystretch\zeropoint - \relax} - -\def\page_mcl_flush_preceding_normal - {\unvbox\b_page_mcl_preceding} - -\def\page_mcl_flush_preceding_ongrid - {\scratchdimen\dimexpr - \d_page_mcl_saved_pagetotal - -\d_page_mcl_preceding_height - -\topskip - \relax - \box\b_page_mcl_preceding - \kern\scratchdimen} - -\def\page_mcl_flush_packaged_columns_continued - {\page_mcl_flush_packaged_columns_indeed - \box\b_page_mcl_page} - -\def\page_mcl_flush_packaged_columns_balanced - {\bgroup - \page_mcl_flush_packaged_columns_indeed - \getnoflines{\htdp\b_page_mcl_page}% - \ht\b_page_mcl_page\dimexpr - \noflines\openlineheight - -\openstrutdepth - \ifgridsnapping - % quick hack (at least it works with itemize) - \else - -\openlineheight - +\topskip - \fi - \relax - \dp\b_page_mcl_page\openstrutdepth - \box\b_page_mcl_page - \egroup} - -\def\page_mcl_synchronize_marks - {\dohandleallcolumns{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}} - -\def\page_mcl_flush_packaged_columns_indeed - {\ifvoid\b_page_mcl_preceding - \setfalse\c_page_mcl_preceding_present % will be set elsewhere - \else - \settrue\c_page_mcl_preceding_present - \page_apply_postprocessors_box\b_page_mcl_preceding - \fi - \forgetall - \page_mcl_initialize_variables - \page_mcl_synchronize_marks - \setbox\b_page_mcl_page\vpack - {\ifconditional\c_page_mcl_reverse\reversehpack\else\naturalhpack\fi to \makeupwidth - {\hskip\ifconditional\c_page_mcl_reverse\d_page_mcl_rightskip\else\d_page_mcl_leftskip\fi\relax - \dohandleallcolumns - {\wd\currentcolumnbox\d_page_mcl_used_width - \setbox\scratchbox\hpack{\strut\box\currentcolumnbox}% hm, why strut - \anch_mark_column_box\scratchbox\currentcolumn - \box\scratchbox - \hfil}% - \unskip - \hskip\ifconditional\c_page_mcl_reverse\d_page_mcl_leftskip\else\d_page_mcl_rightskip\fi}}% - \ifconditional\c_page_mcl_preceding_present - \settrue\c_page_mcl_preceding_present - \ifgridsnapping - \page_mcl_flush_preceding_ongrid % obey grid settings, force on grid - \else - \page_mcl_flush_preceding_normal % ignore grid settings, not on grid - \fi - \fi - \global\d_page_mcl_preceding_height\zeropoint - \page_otr_command_set_vsize - \dosomebreak\nobreak % hm, only needed when topstuff - \ifgridsnapping \else - \ifconditional\c_page_mcl_preceding_present - \nointerlineskip - \vskip\dimexpr\openstrutheight-\topskip\relax - \fi - \fi - \prevdepth\openstrutdepth - \nointerlineskip - \dp\b_page_mcl_page\zeropoint} - -\def\page_mcl_split_column#1#2% copy or box - {\global\setbox\currentcolumnbox\vsplit#1 upto #2} - -\def\page_mcl_routine_continue - {\bgroup - \forgetall - \page_mcl_initialize_variables - \settotalinsertionheight - \page_mcl_set_n_of_lines\totalinsertionheight - \d_page_mcl_balance_target\c_page_mcl_n_of_lines\openlineheight - \dohandleallcolumns{\page_mcl_split_column\normalpagebox\d_page_mcl_balance_target}% - \setbox\b_page_mcl_rest_of_page\vpack{\unvbox\normalpagebox}% - \dohandleallcolumns - {\global\setbox\currentcolumnbox\vpack to \d_page_mcl_balance_target - {\unvbox\currentcolumnbox % wel of niet \unvbox ? - \vfill}}% - \setbox\b_page_mcl_preceding\vpack{\page_mcl_flush_packaged_columns_continued}% - \page_otr_construct_and_shipout\box\b_page_mcl_preceding\zerocount % three arguments - \page_otr_command_set_hsize - \page_otr_command_set_vsize - \unvbox\b_page_mcl_rest_of_page - \egroup} - -\def\page_mcl_routine_balance - {\bgroup - % why no \forgetall here - \page_mcl_initialize_variables - \widowpenalty\zerocount - \setbox\b_page_mcl_balance_content\vpack{\unvbox\normalpagebox}% - \ifdim\ht\b_page_mcl_balance_content>\openlineheight % at least one line - \ifnum\c_page_mcl_balance_minimum<\plustwo % balance anyway - \settrue\c_page_mcl_balance_possible - \else % check criterium to available lines - \getnoflines{\ht\b_page_mcl_balance_content}% - \divide\noflines \nofcolumns \relax - \ifnum\noflines<\c_page_mcl_balance_minimum \relax - \ifdim\dimexpr\ht\b_page_mcl_balance_content+\openlineheight\relax>\makeupheight - \settrue\c_page_mcl_balance_possible % column exceeding text height - \else - \setfalse\c_page_mcl_balance_possible % it seems to fit - \fi - \else - \settrue\c_page_mcl_balance_possible % balance indeed - \fi - \fi - \else - \setfalse\c_page_mcl_balance_possible % balancing does not make sense - \fi - \ifconditional\c_page_mcl_balance_possible % start balancing, was: \ifdim\ht\b_page_mcl_balance_content>\openlineheight - \page_mcl_balance_try_one - \page_mcl_balance_try_two - \else - % a one liner is not properly handled here, so best rewrite the text then - \showmessage\m!columns{10}\empty - \global\setbox\firstcolumnbox\vpack{\unvbox\b_page_mcl_balance_content}% - \fi - \c_page_mcl_routine\c_page_mcl_routine_error - %\baselinebottom % forces depth in separation rule - \page_mcl_flush_packaged_columns_balanced - %\allowbreak - \egroup} - -% \showmakeup - -\def\page_mcl_balance_try_one - {\d_page_mcl_balance_target\dimexpr\ht\b_page_mcl_balance_content+\topskip-\baselineskip\relax - \divide\d_page_mcl_balance_target \nofcolumns - \vbadness\plustenthousand - \c_page_mcl_balance_tries\zerocount - \bgroup - \ifgridsnapping - \d_page_mcl_balance_step\lineheight - \else - \d_page_mcl_balance_step\spacingfactor\onepoint % rubish - \fi - \doloop\page_mcl_balance_try_one_attempt - \global\setbox\b_page_mcl_rest_of_page\box\voidbox - \ifnum\c_page_mcl_balance_tries>\c_page_mcl_balance_tries_max\relax - \showmessage\m!columns7\empty - \else - \showmessage\m!columns8{\the\c_page_mcl_balance_tries}% - \fi - \egroup} - -\def\page_mcl_balance_try_one_attempt - {\advance\c_page_mcl_balance_tries \plusone - \global\setbox\b_page_mcl_rest_of_page\copy\b_page_mcl_balance_content\relax - \dohandleallcolumns{\page_mcl_split_column\b_page_mcl_rest_of_page\d_page_mcl_balance_target}% - \d_page_mcl_balance_natural_height\zeropoint - \dohandleallcolumns\page_mcl_balance_try_one_attempt_step -\advance\d_page_mcl_balance_natural_height-33\scaledpoint % some slack - \ifnum\c_page_mcl_balance_tries>\c_page_mcl_balance_tries_max\relax - \exitloop - \orelse\ifdim\ht\b_page_mcl_rest_of_page>\zeropoint - \advance\d_page_mcl_balance_target\d_page_mcl_balance_step\relax - \orelse\ifdim\d_page_mcl_balance_natural_height>\ht\firstcolumnbox\relax - \advance\d_page_mcl_balance_target\d_page_mcl_balance_step\relax - \else - \exitloop - \fi} - -\def\page_mcl_balance_try_one_attempt_step - {\ifcase\currentcolumn\or\else - \ifdim\ht\currentcolumnbox>\d_page_mcl_balance_natural_height\relax - \d_page_mcl_balance_natural_height\ht\currentcolumnbox - \fi - \fi} - -\def\page_mcl_balance_try_two % hm ... can probably go - {\dohandleallcolumnscs\page_mcl_balance_try_two_step} - -% \def\page_mcl_balance_try_two_step -% {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox -% {\box\currentcolumnbox -% \vfill}} - -\def\page_mcl_balance_try_two_step - {%\global\setbox\currentcolumnbox\box\currentcolumnbox - \ht\currentcolumnbox\ht\firstcolumnbox} - -\tolerant\protected\def\startmulticolumns[#1]% - {\bgroup - \ifinsidecolumns - \page_mcl_start_nop - \else - \setupmulticolumns[#1]% - \nofcolumns\multicolumnsparameter\c!n\relax - \ifnum\nofcolumns>\plusone - \page_mcl_start_yes - \nofmulticolumns\nofcolumns - \else - \page_mcl_start_nop - \fi - \fi} - -\def\page_mcl_start_nop - {\enforced\let\stopmulticolumns\page_mcl_stop_nop} - -\permanent\protected\def\page_mcl_stop_nop - {\egroup} - -\protected\def\page_mcl_start_yes - {\whitespace - \begingroup - \enforced\let\stopmulticolumns\page_mcl_stop_indeed - \global\insidecolumnstrue - \global\insidemulticolumnstrue - % - \d_page_mcl_distance\multicolumnsparameter\c!distance\relax - % - \edef\p_direction{\multicolumnsparameter\c!direction}% - \ifx\p_direction\v!right - \setfalse\c_page_mcl_reverse - \else - \settrue\c_page_mcl_reverse - \fi - % - \edef\p_balance{\multicolumnsparameter\c!balance}% - \ifx\p_balance\v!yes - \settrue\c_page_mcl_balance - \else - \setfalse\c_page_mcl_balance - \fi - % - \usealignparameter\multicolumnsparameter - % - \edef\p_blank{\multicolumnsparameter\c!blank}% - \ifx\p_blank\empty \else - \setupblank[\p_blank]% - \fi - % - \ifdim\s_spac_whitespace_parskip>\zeropoint\relax - \setupwhitespace[\p_blank]% - \fi - \c_page_mcl_balance_minimum\multicolumnsparameter\c!ntop\relax - % - \begingroup - % - \d_page_mcl_leftskip \leftskip - \d_page_mcl_rightskip\rightskip - \leftskip \zeropoint - \rightskip \zeropoint - \hangafter \zerocount - \hangindent \zeropoint - % - \widowpenalty \zerocount % will become option - \clubpenalty \zerocount % will become option - % - \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 - % - \reseteverypar % todo - % - \ifdim\pagetotal=\zeropoint \else - \verticalstrut - \vskip-\struttotal - \fi - \global\d_page_mcl_saved_pagetotal\pagetotal - \setupoutputroutine[\s!multicolumn]% - \c_page_mcl_routine\c_page_mcl_routine_intercept - \page_otr_trigger_output_routine - \global\d_page_mcl_preceding_height\ht\b_page_mcl_preceding - \c_page_mcl_routine\c_page_mcl_routine_continue - \page_otr_command_set_hsize - \page_otr_command_set_vsize} - -\permanent\protected\def\page_mcl_stop_indeed - {\relax - \synchronizeoutput - \par - \ifconditional\c_page_mcl_balance - \c_page_mcl_routine\c_page_mcl_routine_continue - \goodbreak - \c_page_mcl_routine\c_page_mcl_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_mcl_routine\c_page_mcl_routine_regular - % - \ifvoid\b_page_mcl_preceding\else - \unvbox\b_page_mcl_preceding - \fi - \global\d_page_mcl_preceding_height\zeropoint - \endgroup % here - \nofcolumns\plusone - \nofmulticolumns\plusone - \page_otr_command_set_vsize - \dosomebreak\allowbreak - \page_floats_column_pop_saved - % - \global\insidemulticolumnsfalse - \global\insidecolumnsfalse - \endgroup - \egroup}% - -\setupmulticolumns - [\c!n=2, - \c!ntop=1, - \c!direction=\v!right, - \c!distance=1.5\bodyfontsize, % influenced by switching - \c!balance=\v!yes, - \c!align={\v!text,\v!tolerant}, - \c!blank={\v!line,\v!fixed}] - -\defineoutputroutine - [\s!multicolumn] - [\s!page_otr_command_routine =\page_mcl_command_routine, - \s!page_otr_command_package_contents=\page_mcl_command_package_contents, - \s!page_otr_command_set_vsize =\page_mcl_command_set_vsize, - \s!page_otr_command_set_hsize =\page_mcl_command_set_hsize] - -\let\strc_itemgroups_start_columns_old\strc_itemgroups_start_columns -\let\strc_itemgroups_stop_columns_old \strc_itemgroups_stop_columns - -\def\strc_itemgroups_start_columns_new - {\startmulticolumns[\c!n=\itemgroupparameter\c!n]} - -\def\strc_itemgroups_stop_columns_new - {\stopmulticolumns} - -\installtexexperiment - {itemize.columns} - {\let\strc_itemgroups_start_columns\strc_itemgroups_start_columns_new - \let\strc_itemgroups_stop_columns \strc_itemgroups_stop_columns_new} - {\let\strc_itemgroups_start_columns\strc_itemgroups_start_columns_old - \let\strc_itemgroups_stop_columns \strc_itemgroups_stop_columns_old} - -\protect \endinput diff --git a/tex/context/base/mkiv/page-mix.mkxl b/tex/context/base/mkiv/page-mix.mkxl deleted file mode 100644 index 20f4ff3ca..000000000 --- a/tex/context/base/mkiv/page-mix.mkxl +++ /dev/null @@ -1,1092 +0,0 @@ -%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}{} - -\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 - -% old multicolumns mechanism -% -% \c!ntop=1, -% \c!rule=\v!off, : now separator=rule -% \c!height=, -% \c!blank={\v!line,\v!fixed}, -% \c!rulethickness=\linewidth, -% \c!offset=.5\bodyfontsize, - -\setupmixedcolumns - [\c!distance=1.5\bodyfontsize, - \c!n=\plustwo, - %\c!align=, % inherit (also replaces tolerance) - %\c!before=, - %\c!after=, - %\c!separator=\v!none, - %\c!setups=, - %\c!balance=\v!no, - %\c!blank={\v!line,\v!fixed}, yes or no - \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!notes=\v!yes, - \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 - -\newconditional\c_page_mix_process_notes -\newconditional\c_page_mix_grid_snapping - -%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] -% -% \protected\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, - \c!notes=\v!no] % kind of hidden - -% better - -\setupmixedcolumns - [\s!itemgroupcolumns] - [\c!splitmethod=\v!fixed, - \c!grid=\v!yes, - \c!internalgrid=\v!line] - -% even better: - -\setupitemgroup - [\c!grid=\v!tolerant:10] % 10 pct tolerance in columns snapping - -\setupmixedcolumns - [\s!itemgroupcolumns] - [\c!grid=\itemgroupparameter\c!grid] - -% the fast hooks: - -\protected\def\strc_itemgroups_start_columns - {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one - -\protected\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. - -\protected\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 ? - {\forgetall - \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_construct_and_shipout#1#2#3% - {\ifconditional\c_page_mix_grid_snapping\else\gridsnappingfalse\fi % maybe only for notes (bottom alignment) - \page_otr_construct_and_shipout#1#2#3% - \ifconditional\c_page_mix_grid_snapping \gridsnappingtrue \fi} - - -\def\page_mix_routine_error - {\showmessage\m!columns3\empty - \page_mix_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments - -%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. - -\protected\def\page_mix_command_set_hsize - {\hsize\d_page_mix_column_width - \columnwidth\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. - -\protected\def\page_mix_command_set_vsize - {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax - \pagegoal\dimexpr - \vsize -% -\d_page_floats_inserted_top % needs checking -% -\d_page_floats_inserted_bottom % needs checking - -\c_page_mix_n_of_columns\insertheights - \relax} - -%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}% - \setfalse\c_page_mix_grid_snapping - \ifempty\p_grid - % just follow the default grid settings - \else - \ifgridsnapping\settrue\c_page_mix_grid_snapping\fi - \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} - -\protected\def\installmixedcolumnseparator#1#2% - {\setvalue{\??mixedcolumnsseparator#1}{#2}} - -\installmixedcolumnseparator\v!rule - {\vrule - \s!width \mixedcolumnsparameter\c!rulethickness - \s!height\mixedcolumnseparatorheight - \s!depth \mixedcolumnseparatordepth - \relax} - -\protected\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 - -\installmacrostack\currentmixedcolumns -\installmacrostack\currentmixedcolumnsmethod - -\protected\def\startmixedcolumns - {\dodoubleempty\page_mix_start_columns} - -\def\page_mix_start_columns_checked#1#2% - {\edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% - \ifx\currentmixedcolumnsmethod\v!box - \singleexpandafter#1% - \orelse\ifinsidecolumns - \doubleexpandafter#2% - \else - \doubleexpandafter#1% - \fi} - -\protected\def\page_mix_start_columns - {\push_macro_currentmixedcolumns - \push_macro_currentmixedcolumnsmethod - \ifsecondargument - \singleexpandafter\page_mix_start_columns_a - \orelse\iffirstargument - \doubleexpandafter\page_mix_start_columns_b - \else - \doubleexpandafter\page_mix_start_columns_c - \fi} - -\def\page_mix_start_columns_a[#1]% [#2]% - {\edef\currentmixedcolumns{#1}% - \page_mix_start_columns_checked - \page_mix_start_columns_a_yes - \page_mix_start_columns_a_nop} - -\def\page_mix_start_columns_a_yes[#1]% - {\mixedcolumnsparameter\c!before\relax - \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax - \begingroup - \setupcurrentmixedcolumns[#1]% - \page_mix_initialize_columns - \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname - \let\stopmixedcolumns\page_mix_columns_stop_yes} - -\def\page_mix_start_columns_a_nop[#1]% - {\begingroup - \let\stopmixedcolumns\page_mix_columns_stop_nop} - -\def\page_mix_start_columns_b[#1][#2]% - {\doifelseassignment{#1}% - {\let\currentmixedcolumns\empty - \page_mix_error_b} - {\edef\currentmixedcolumns{#1}% - \firstargumentfalse}% - \page_mix_start_columns_checked - \page_mix_start_columns_b_yes - \page_mix_start_columns_b_nop - [#1]} - -\def\page_mix_start_columns_b_yes[#1]% - {\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 - \let\stopmixedcolumns\page_mix_columns_stop_yes} - -\def\page_mix_start_columns_b_nop[#1]% - {\begingroup - \let\stopmixedcolumns\page_mix_columns_stop_nop} - -\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 - \page_mix_start_columns_checked - \page_mix_start_columns_c_yes - \page_mix_start_columns_c_nop} - -\def\page_mix_start_columns_c_yes - {\mixedcolumnsparameter\c!before\relax - \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax - \begingroup - \page_mix_initialize_columns - \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname - \let\stopmixedcolumns\page_mix_columns_stop_yes} - -\def\page_mix_start_columns_c_nop - {\begingroup - \let\stopmixedcolumns\page_mix_columns_stop_nop} - -\protected\def\page_mix_fast_columns_start#1% - {\push_macro_currentmixedcolumns - \push_macro_currentmixedcolumnsmethod - \edef\currentmixedcolumns{#1}% - \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% - \mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings ! - \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax - \begingroup - \page_mix_initialize_columns - \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname % no \relax - \let\page_mix_fast_columns_stop\page_mix_columns_stop_yes} - -%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. - -\let\page_mix_fast_columns_stop\relax - -\newtoks\t_page_mix_at_the_end - -\def\page_mix_finalize_columns - {\ifconditional\c_page_mix_process_notes \else - \global\t_page_mix_at_the_end{\stoppostponingnotes}% - \fi} - -\protected\def\page_mix_columns_stop_yes - {\begincsname\??mixedcolumnsstop\currentmixedcolumnsmethod\endcsname % no \relax - \page_mix_finalize_columns - \endgroup - \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax - \mixedcolumnsparameter\c!after\relax - \pop_macro_currentmixedcolumnsmethod - \pop_macro_currentmixedcolumns - \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} - -\protected\def\page_mix_columns_stop_nop - {\page_mix_finalize_columns - \endgroup - \pop_macro_currentmixedcolumnsmethod - \pop_macro_currentmixedcolumns - \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} - -% \protected\def\page_mix_columns_stop_yes -% {\begincsname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax -% \endgroup -% \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax -% \mixedcolumnsparameter\c!after\relax -% \ifx\currentmixedcolumnsmethod\s!otr -% \pop_macro_currentmixedcolumnsmethod -% \pop_macro_currentmixedcolumns -% \synchronizeoutput % brrr, otherwise sometimes issues in itemize -% \else -% \pop_macro_currentmixedcolumnsmethod -% \pop_macro_currentmixedcolumns -% \fi -% } - -%D This is how the fast one is used: - -\protected\def\strc_itemgroups_start_columns - {\page_mix_fast_columns_start\s!itemgroupcolumns} - -\protected\def\strc_itemgroups_stop_columns - {\page_mix_fast_columns_stop} % set by start - -% not used nor documented so commented: -% -% \setupmixedcolumns -% [\s!itemgroupcolumns] -% [\c!grid=\itemgroupparameter\c!grid] -% -% \setupitemgroup -% [\c!grid=\v!yes] % we need a value - -% 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 - % - \doifelse{\mixedcolumnsparameter\c!notes}\v!yes\settrue\setfalse\c_page_mix_process_notes - \ifconditional\c_page_mix_process_notes \else - \startpostponingnotes - \fi - % - \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 - % - \columnwidth \d_page_mix_column_width - \columndistance\d_page_mix_distance - \nofcolumns \c_page_mix_n_of_columns - \textwidth \d_page_mix_column_width % kind of redundant but we had it so ... - % - \usemixedcolumnscolorparameter\c!color - % - \insidecolumnstrue % new - % - \usealignparameter \mixedcolumnsparameter - \useblankparameter \mixedcolumnsparameter - \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. - -\protected\def\page_mix_routine_construct#1% - {\d_page_mix_max_height\mixedcolumnsparameter\c!maxheight % can have changed due to header=high - \ifconditional\c_page_mix_process_notes - \totalnoteheight\zeropoint - \else - \settotalinsertionheight - \fi - \clf_mixsetsplit - box \b_page_mix_collected - nofcolumns \c_page_mix_n_of_columns - maxheight \d_page_mix_max_height - noteheight \totalnoteheight - 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 tru\else fals\fi e % - notes \ifconditional\c_page_mix_process_notes tru\else fals\fi e % - \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\recurselevel - % 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} - -\protected\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 - \hskip\d_page_mix_rightskip - \egroup - \wd\b_page_mix_collected\dimexpr - \d_page_mix_max_width - +\d_page_mix_rightskip - +\d_page_mix_leftskip - \relax } - -\protected\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 - \vbox \bgroup - \hsize\d_page_mix_column_width - \ifconditional\c_page_mix_process_notes - \placenoteinserts - \fi - \egroup - \hss - \egroup} - -% \protected\def\page_mix_command_package_column -% {\page_mix_hbox to \d_page_mix_column_width \bgroup -% % maybe intercept empty -% \ruledhpack\bgroup -% \clf_mixgetsplit\recurselevel\relax -% \egroup -% \hskip-\d_page_mix_column_width -% \ruledhpack \bgroup -% \hsize\d_page_mix_column_width -% \ifconditional\c_page_mix_process_notes -% \placenoteinserts -% \fi -% \egroup -% \hss -% \egroup} - -\protected\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_mix_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments - \clf_mixflushrest - \clf_mixcleanup - \egroup} - -\protected\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_mix_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments - \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 - \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}% - \ifempty\p_profile \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: - -\protected\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 - -\protected\def\page_mix_command_check_if_float_fits - {\ifpostponecolumnfloats - \global\setfalse\c_page_floats_room - \orelse\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} - -\protected\def\page_mix_command_flush_floats - {\page_one_command_flush_floats} - -\protected\def\page_mix_command_flush_saved_floats - {\page_one_command_flush_saved_floats} - -% \protected\def\page_mix_command_flush_top_insertions -% {\page_one_command_flush_top_insertions} - -\protected\def\page_mix_place_float_top - {\showmessage\m!columns4\empty\page_one_place_float_here} - -\protected\def\page_mix_place_float_bottom - {\showmessage\m!columns5\empty\page_one_place_float_here} - -\protected\def\page_mix_place_float_here - {\page_one_place_float_here} - -\protected\def\page_mix_place_float_force - {\page_one_place_float_force} - -\protected\def\page_mix_command_side_float_output - {\page_mix_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments - -\protected\def\page_mix_command_synchronize_side_floats - {\page_sides_forget_floats} - -\protected\def\page_mix_command_flush_side_floats - {\page_sides_forget_floats} - -\protected\def\page_mix_command_next_page - {\page_otr_eject_page} - -\protected\def\page_mix_command_next_page_and_inserts - {\page_otr_eject_page_and_flush_inserts} - -%D Moved here and dedicated: - -\protected\def\page_mix_command_test_column - {\dodoubleempty\page_mix_command_test_column_indeed} - -\protected\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 - \c_attr_checkedbreak\number\scratchdimen % why \number - \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: - -\let\page_mix_command_flush_all_floats\page_one_command_flush_all_floats - -\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_synchronize_hsize =\page_mix_command_synchronize_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_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_check_if_float_fits =\page_mix_command_check_if_float_fits, - % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize, - \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box, - \s!page_otr_command_side_float_output =\page_mix_command_side_float_output, - \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats, - \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_all_floats =\page_mix_command_flush_all_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/tex/context/base/mkiv/page-not.mkxl b/tex/context/base/mkiv/page-not.mkxl deleted file mode 100644 index 2d1c3fea6..000000000 --- a/tex/context/base/mkiv/page-not.mkxl +++ /dev/null @@ -1,32 +0,0 @@ -%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 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 - -\newdimen\totalinsertionheight - -\protected\def\settotalinsertionheight - {\calculatetotalnoteheight - \totalinsertionheight\dimexpr - \totalnoteheight - +\page_insert_insertion_height\s!topfloat - +\page_insert_insertion_height\s!bottomfloat - \relax} - -\protect \endinput diff --git a/tex/context/base/mkiv/page-one.mkxl b/tex/context/base/mkiv/page-one.mkxl deleted file mode 100644 index 3e7d3e2a8..000000000 --- a/tex/context/base/mkiv/page-one.mkxl +++ /dev/null @@ -1,709 +0,0 @@ -%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 - -\protected\def\page_one_command_next_page - {\page_otr_eject_page} - -\protected\def\page_one_command_next_page_and_inserts - {\page_otr_eject_page_and_flush_inserts} - -\protected\def\page_one_command_set_hsize - {\global\hsize\textwidth - \columnwidth\textwidth} % bonus so that it's not zero - -\protected\def\page_one_command_set_float_hsize - {\global\hsize\textwidth} - -\protected\def\page_one_command_set_vsize - {\ifgridsnapping - \ifcase\layoutlines - \getrawnoflines\textheight - \else - \noflines\layoutlines - \fi - \global\vsize\noflines\openlineheight - \else - \global\vsize\textheight - \fi - \global\advance\vsize\d_page_adapts_delta - % alternatively we could set it in builders.buildpage_filter - % \ifdim\pagegoal<\maxdimen .. \fi - \pagegoal\dimexpr - \vsize - -\d_page_floats_inserted_top - -\d_page_floats_inserted_bottom - -\insertheights - \relax} - -% 1 = partial page, 2 = whole page, 3 = partial page - -% We really need a setting! Todo, what key to use? - -\pushoverloadmode - \setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day - \overloaded\let\kindofpagetextareas\kindofpagetextareas -\popoverloadmode - -\def\page_one_registered_text_area_a % two arguments: (un)vbox n - {\ifconditional\c_page_areas_enabled - \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 - -\protected\def\page_one_command_package_contents#1#2% \box \unvbox % 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) -% \parfillskip\zeropoint - \page_one_registered_text_area_a#1#2% \unvbox - % - \ifgridsnapping - \unskip % new per 2019-06-18, otherwise weird bottom floats - \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax - \prevdepth\openstrutdepth - \page_otr_command_flush_bottom_insertions - \vfil - \orelse\ifcase\bottomraggednessmode - % ragged (default) - \unskip % new per 2019-06-18, otherwise weird bottom floats - \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax - \prevdepth\openstrutdepth - % these have whitespace before but we can have some more options - % like a \vfill or so - \page_otr_command_flush_bottom_insertions - \vfil - \or - % align (normal) - \page_otr_command_flush_bottom_insertions - \or - % baseline - \unskip % new per 2019-06-18, otherwise weird bottom floats - \vkern\dimexpr\maxdepth-\d_page_one_natural_depth\relax - \page_otr_command_flush_bottom_insertions - \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 - {\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} - -\protected\def\page_one_command_side_float_output - {\page_otr_construct_and_shipout\unvbox\normalpagebox\plusone} % three arguments, we need to be in the output group - -\protected\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 - {\floatingpenalty\zerocount - \insert\namedinsertionnumber\s!topfloat\bgroup - \forgetall - \ifconditional\c_page_one_top_of_insert - \ifconditional\c_page_one_correct_top_insert - \topskipcorrection % [xx] new: see icare topbleed - \kern-\lineskip - \par - \prevdepth\maxdimen - \fi - \fi - \page_otr_command_flush_float_box - \vskip\s_page_one_between_top_insert - \egroup} - -\let\totaltopinserted\!!zeropoint -\let\totalbotinserted\!!zeropoint - -\protected\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} - -\protected\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 - \floatingpenalty\zerocount - \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} - -\protected\def\page_one_command_flush_top_insertions - {\ifvoid\namedinsertionnumber\s!topfloat\else - \page_one_command_flush_top_insertions_indeed % less tracing - \fi - \global\d_page_floats_inserted_top\zeropoint} - -\def\page_one_command_flush_top_insertions_indeed - {\ifgridsnapping - \box\namedinsertionnumber\s!topfloat - \vkern-\topskip - \vkern\strutheight % [xx] new: see icare topbleed - \else - \ifcase\c_page_floats_insertions_topskip_mode - % 0: default, do nothing - \or - % 1: no topskip (crossed fingers) - \vskip-\topskip % skip ! - \vkern\strutheight - \fi - \unvbox\namedinsertionnumber\s!topfloat - \fi} - -\protected\def\page_one_command_flush_bottom_insertions - {\ifvoid\namedinsertionnumber\s!bottomfloat\else - \page_one_command_flush_bottom_insertions_indeed - \fi - \global\d_page_floats_inserted_bottom\zeropoint - \global\setfalse\c_page_floats_not_permitted} - -\def\page_one_command_flush_bottom_insertions_indeed - {\ifgridsnapping - % \floatparameter\c!bottombefore - \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% - % \floatparameter\c!bottomafter - \else - \floatparameter\c!bottombefore - \unvbox\namedinsertionnumber\s!bottomfloat - \floatparameter\c!bottomafter - \fi} - -\protected\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} - -\protected\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_floats_get_compressed - {\setfalse\c_page_floats_center_box % not needed as we do call directly - %% 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 - \hpack to \ifdim\naturalfloatwd>\makeupwidth\makeupwidth\else\naturalfloatwd\fi - {\hss\box\floatbox\hss}% - \ifnum\recurselevel<\nofcollectedfloats - \hfil - \fi}% - \hfil}} - -\def\page_one_command_flush_floats_indeed - {\ifconditional\c_page_floats_some_waiting - \ifconditional\c_page_floats_pack_flushed - \page_floats_collect\s!text\hsize\d_page_floats_compress_distance - \ifcase\nofcollectedfloats - \page_floats_get - \or - \page_floats_get - \else - \page_one_command_floats_get_compressed - \fi - \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} - -\protected\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} - -\protected\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 - \scratchdimenone\dimexpr - \pagetotal - +\floatheight - +\d_strc_floats_top - +\d_strc_floats_overflow - -\pageshrink - \relax - \scratchdimentwo\pagegoal - \relax % needed - \ifcase\c_page_one_float_method - % method 0 : raw - \or - % method 1 : safe - % too fuzzy as it can change and for a high page it's a lot : \scratchdimentwo .99\pagegoal - \advance\scratchdimentwo -\strutdp - \or - % method 2 : tight - \advance\scratchdimenone -\onepoint - \fi - \relax % really needed ! ! ! ! - \ifdim\scratchdimenone>\scratchdimentwo - \global\setfalse\c_page_floats_room - \else - \global\settrue\c_page_floats_room - \fi - \fi} - -\protected\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_ - \orelse\ifconditional\c_page_margin_blocks_present - \page_one_command_flush_floats - \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_here_indeed - {\ifgridsnapping - % otherwise real bad outcome - \else - % this was not really applied (delayed) - % \baselinecorrection % this has to be done better (and definitely not in column mode) - % so we now use this: - \checkprevdepth - \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_margin - {\page_margin_blocks_process_float - \nonoindentation} % new, due to popular request - -\def\page_one_place_float_leftmargin - {\page_one_place_float_side_indeed - \page_sides_process_float_leftmargin - \nonoindentation} % new, due to popular request - -\def\page_one_place_float_rightmargin - {\page_one_place_float_side_indeed - \page_sides_process_float_rightmargin - \nonoindentation} % new, due to popular request - -\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_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 - \nonoindentation} % new, due to popular request - -\def\page_one_place_float_top - {\page_one_place_float_otherwise - \nonoindentation} - -\def\page_one_place_float_bottom - {\page_one_place_float_otherwise - \nonoindentation} % new, due to popular request - -\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 - \orelse\ifx\floatmethod\v!bottom - \page_one_place_float_bottom_indeed - \else - \page_one_place_float_here_indeed - \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 - \floatingpenalty\zerocount - \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} - -\protected\def\page_one_command_flush_side_floats - {\page_sides_flush_floats} - -\protected\def\page_one_command_synchronize_side_floats - {\page_sides_synchronize_floats} - -\protected\def\page_one_command_test_page - {\testpage} - -\protected\def\page_one_command_flush_all_floats - {\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} - -\protected\def\page_one_command_flush_facing_floats - {\strc_floats_facing_flush} - -\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_synchronize_hsize =\page_one_command_synchronize_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_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_check_if_float_fits =\page_one_command_check_if_float_fits, - % \s!page_otr_command_set_float_hsize =\page_one_command_set_float_hsize, - \s!page_otr_command_flush_float_box =\page_one_command_flush_float_box, - \s!page_otr_command_side_float_output =\page_one_command_side_float_output, - \s!page_otr_command_synchronize_side_floats=\page_one_command_synchronize_side_floats, - \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_all_floats =\page_one_command_flush_all_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, - \s!page_otr_command_flush_facing_floats =\page_one_command_flush_facing_floats -] - -% \setupoutputroutine -% [\s!singlecolumn] - -\protect \endinput diff --git a/tex/context/base/mkiv/page-otr.mklx b/tex/context/base/mkiv/page-otr.mklx deleted file mode 100644 index 797e31274..000000000 --- a/tex/context/base/mkiv/page-otr.mklx +++ /dev/null @@ -1,335 +0,0 @@ -%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 same time we -%D 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}{} - -\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 - -\protected\def\defineoutputroutinecommand[#name]% doing multiple on one go saves syncing - {\processcommalist[#name]\page_otr_commands_define} - -\protected\def\page_otr_commands_define#name% - {\ifcsname#name\endcsname \else - \letcsname#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 - -\protected\def\page_otr_specifics_preset#name% - {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands - \ifempty\page_otr_specifics_command - \writestatus{\currentoutputroutine}{- \expandafter\strippedcsname\csname#name\endcsname}% - \letcsname#name\endcsname\relax - \else - \writestatus{\currentoutputroutine}{+ \expandafter\strippedcsname\csname#name\endcsname}% - \letcsname#name\expandafter\endcsname\page_otr_specifics_command - \fi} - -\protected\def\page_otr_specifics_preset_normal#name% - {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands - \ifempty\page_otr_specifics_command - \letcsname#name\endcsname\relax - \else - \letcsname#name\expandafter\endcsname\page_otr_specifics_command - \fi} - -\protected\def\page_otr_specifics_preset_traced#name% - {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands - \ifempty\page_otr_specifics_command - \writestatus{\currentoutputroutine}{preset: - \expandafter\strippedcsname\csname#name\endcsname}% - \letcsname#name\endcsname\relax - \else - \writestatus{\currentoutputroutine}{preset: + \expandafter\strippedcsname\csname#name\endcsname}% - \letcsname#name\expandafter\endcsname\page_otr_specifics_command - \fi} - -\let\page_otr_specifics_preset\page_otr_specifics_preset_normal - -\protected\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_otr_trigger_penalty \c_page_otr_trigger_penalty -100010 - -\newcount \c_page_otr_columns % we will share this one - -\newif \ifinotr % we keep this (name) for old times sake - -% \def\page_otr_update_page_goal#1#2% -% {\global\c_page_otr_columns#2\relax -% \pagegoal\dimexpr\vsize-\c_page_otr_columns\insertheights\relax} - -\appendtoks - \insertheights\zeropoint -\to \everyaftershipout - -\protected\def\page_otr_message_b{\page_otr_message_s+} -\protected\def\page_otr_message_e{\page_otr_message_s-} - -\protected\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 - i:\the\insertheights - \ifdim\pagetotal>\pagegoal - ,\space - d:\the\dimexpr\pagetotal-\pagegoal\relax - \fi}} - -\protected\def\page_otr_trigger#penalty% - {\begingroup - \par - \penalty#penalty% - \endgroup} - -\protected\def\installoutputroutine#invoke#action% \invoke \action - {\global\advance\c_page_otr_trigger_penalty\minusone - \frozen\protected\edef#invoke{\page_otr_trigger{\number\c_page_otr_trigger_penalty}}% - \setvalue{\??otrtriggers\number\c_page_otr_trigger_penalty}{#action}} - -\protected\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} - -\protected\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_otr_set_engine_output_routine#content% - {\global\output - {\inotrtrue - \the\everybeforeoutput - #content\relax - \the\everyafteroutput}} - -% Just as fuzzy (and in 'one' we are okay with \aftergroup anyway): -% -% \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi -% \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi -% -% \def\page_otr_set_engine_output_routine#content% -% {\the\everybeforeoutputgroup -% \global\output -% {\inotrtrue -% \the\everybeforeoutput -% #content\relax -% \the\everyafteroutput -% \aftergroup\the\aftergroup\everyafteroutputgroup}} -% -% \appendtoks -% \ifnum\c_page_postponed_mode=\plusone -% \page_postponed_blocks_flush % and then not in \page_otr_construct_and_shipout -% \fi -% \to \everyafteroutputgroup - -\page_otr_set_engine_output_routine\page_otr_triggered_output_routine - -\installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead - {\ifvoid\normalpagebox\else - \unvbox\normalpagebox - % not \pagediscards as it does more harm than good - \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: - -\protected\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). Most -%D routines will use ard codes names but sometimes we want to adapt, -%D which is why we have these: - -\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_all_floats} -\definesystemconstant{page_otr_command_flush_margin_blocks} -\definesystemconstant{page_otr_command_test_column} -\definesystemconstant{page_otr_command_flush_facing_floats} - -\definesystemconstant{singlecolumn} -\definesystemconstant{multicolumn} % will move -\definesystemconstant{columnset} % will move -\definesystemconstant{pagecolumn} % 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_all_floats, - \s!page_otr_command_flush_margin_blocks, - \s!page_otr_command_test_column, - \s!page_otr_command_flush_facing_floats] - -\appendtoks - \setupoutputroutine[\s!singlecolumn]% -\to \everydump - -\protect \endinput diff --git a/tex/context/base/mkiv/page-spr.mkxl b/tex/context/base/mkiv/page-spr.mkxl deleted file mode 100644 index 3a835a61c..000000000 --- a/tex/context/base/mkiv/page-spr.mkxl +++ /dev/null @@ -1,131 +0,0 @@ -%D \module -%D [ file=page-spr, -%D version=2002.11.11, -%D title=\CONTEXT\ Page Macros, -%D subtitle=Spreading, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Page Macros / Spreading} - -% This module is experimental and not yet official! - -\unprotect - -\newbox \b_page_spread_content -\newconditional\c_page_spread_busy -\newconditional\c_page_spread_once % when true only one flush (writes etc) - -\permanent\overloaded\protected\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear - {\setbox#1\hpack - {\setlayoutcomponentattribute{\v!page:\v!text}% - \vpack \layoutcomponentboxattribute to \textheight - {\offinterlineskip - \freezetextwidth - \hsize\textwidth % local variant of \sethsize - \boxmaxdepth\maxdepth - \noindent % content can be < \hsize - \page_otr_command_package_contents#2#3}}% - \dp#1\zeropoint - \ifconditional\c_page_spread_busy - \normalsettextpagecontent_spread{#1}% - \else - \normalsettextpagecontent_normal{#1}% - \fi} - -\def\normalsettextpagecontent_normal#1% - {\ifdim\wd#1=\makeupwidth\else - \setbox#1\hpack to \makeupwidth - {\hss\box#1\hss}% never change the \hss's - \fi} - -\def\normalsettextpagecontent_spread#1% - {\setbox#1\hpack to \makeupwidth - {\ifvoid\b_page_spread_content - \ifconditional\c_page_spread_once - \box#1% - \else - \global\setbox\b_page_spread_content\box#1% - \copy\b_page_spread_content - \fi - \hss % left page - \else - \hss % right page - \ifarrangingpages - % writes don't matter anyway - \orelse\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 - \box\b_page_spread_content - \fi}} - -\protected\def\page_spread_flush - {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else - % this page will be discarded later - \emptyhbox \page - \fi \fi } - -\permanent\protected\def\startspread - {\ifdoublesided - \ifconditional\c_page_spread_busy - \doubleexpandafter\page_spread_start_nop - \else - \doubleexpandafter\page_spread_start_yes - \fi - \else - \expandafter\page_spread_start_nop - \fi} - -\let\stopspread\relax - -\protected\def\page_spread_start_yes - {\bgroup - \page[\v!left]% - %\setsystemmode{spread}% - \settrue\c_page_spread_busy - \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}% - \let\stopspread\page_spread_stop_yes} - -\protected\def\page_spread_stop_yes - {\kern\zeropoint - \page - \setuplayout[\c!textwidth=\textwidth]% - \page[\v!left]% - \egroup} - -\protected\def\page_spread_start_nop - {\bgroup - \let\stopspread\page_spread_stop_nop} - -\protected\def\page_spread_stop_nop - {\egroup} - -\protect \endinput - -% texexec --arr --pdf test -% -% \setuplayout[width=middle] -% \setuppapersize[A4][A3,landscape] -% \setuppagenumbering[alternative=doublesided] -% \setuparranging[2UP] -% -% \starttext -% -% \dorecurse{3}{\input tufte } -% -% \startspread -% \dorecurse{10}{\input tufte } -% \stopspread -% -% \dorecurse{3}{\input tufte } -% -% \stoptext diff --git a/tex/context/base/mkiv/page-txt.mklx b/tex/context/base/mkiv/page-txt.mklx deleted file mode 100644 index 9058f893d..000000000 --- a/tex/context/base/mkiv/page-txt.mklx +++ /dev/null @@ -1,950 +0,0 @@ -% 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,setupfooter, setupbottom} -%D -%D The macros in this module sometimes look a bit more complicated than needed, -%D which is a direct result of the fact that their ancestors are quite old and -%D 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=] - -\permanent\tolerant\protected\def\setuplayouttext[#vertical]#spacer[#horizontal]#spacer[#settings]% - {\ifnum\lastarguments>\plustwo - \setuplayoutelement[#vertical:#horizontal][#settings]% - \else - \setuplayoutelement[#vertical][#horizontal]% - \fi} - -\appendtoks - \ifempty\currentlayoutelement\else - \page_layouts_synchronize_element\currentlayoutelement % brr, can be vertical:horizontal - \fi -\to \everysetuplayoutelement - -\def\page_layouts_reset_element_status#vertical% - {\global\defcsname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}} - -\def\page_layouts_set_element_status_normal#vertical% - {\global\letcsname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal - \global\letcsname\??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 \orelse - \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \orelse - \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \orelse - \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi - \letgvalue{\??layouttextssynchronize#vertical}\currenttextstate} - -\permanent\protected\def\setuptop {\setuplayouttext[\v!top ]} -\permanent\protected\def\setupheader{\setuplayouttext[\v!header]} -\permanent\protected\def\setuptext {\setuplayouttext[\v!text ]} -\permanent\protected\def\setupfooter{\setuplayouttext[\v!footer]} -\permanent\protected\def\setupbottom{\setuplayouttext[\v!bottom]} - -%D We inherit some settings: - -\setuplayoutelement - [ \c!leftstyle=\layoutelementparameter\c!style, - \c!middlestyle=\layoutelementparameter\c!style, - \c!rightstyle=\layoutelementparameter\c!style, - \c!leftcolor=\layoutelementparameter\c!color, - \c!middlecolor=\layoutelementparameter\c!color, - \c!rightcolor=\layoutelementparameter\c!color, - \c!leftwidth=\layoutelementparameter\c!width, - \c!middlewidth=\layoutelementparameter\c!width, - \c!rightwidth=\layoutelementparameter\c!width] - -%D \macros -%D {noheaderandfooterlines,notopandbottomlines} -%D -%D Although not really needed, the following shortcuts sometimes come in handy. -%D -%D \showsetup{noheaderandfooterlines} -%D \showsetup{notopandbottomlines} - -\permanent\protected\def\noheaderandfooterlines - {\setuplayoutelement[\v!header][\c!state=\v!empty]% - \setuplayoutelement[\v!footer][\c!state=\v!empty]} - -\permanent\protected\def\notopandbottomlines - {\setuplayoutelement[\v!top ][\c!state=\v!empty]% - \setuplayoutelement[\v!bottom][\c!state=\v!empty]} - -%D \macros -%D {setuptoptexts,setupheadertexts,setuptexttexts,setupfootertexts,setupbottomtexts} -%D -%D The next macros take one or more arguments. The exact setup depends on the number -%D of arguments. Although not that intuitive, the current scheme evolved out of the -%D original. When margin and edge texts as well as middle texts showed up, the -%D current odd|/|even scheme surfaced. -%D -%D \showsetup{setuptoptexts} -%D \showsetup{setupheadertexts} -%D \showsetup{setuptexttexts} -%D \showsetup{setupfootertexts} -%D \showsetup{setupbottomtexts} -%D -%D Only the following have checking for pagenumber, date and mark built in, so when -%D someone uses the key|/|value interface these things have to be set explicitly as -%D part of the text. - -\permanent\protected\def\setuptoptexts {\setuptexts[\v!top ]} -\permanent\protected\def\setupheadertexts{\setuptexts[\v!header]} -\permanent\protected\def\setuptexttexts {\setuptexts[\v!text ]} -\permanent\protected\def\setupfootertexts{\setuptexts[\v!footer]} -\permanent\protected\def\setupbottomtexts{\setuptexts[\v!bottom]} - -\permanent\tolerant\protected\def\setuptexts[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% - {\ifarguments - % there is always one - \or - \edef\currentlayoutelement{#vertical:\v!text}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext - \edef\currentlayoutelement{#vertical:\v!margin}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext - \edef\currentlayoutelement{#vertical:\v!edge}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext - \or - \edef\currentlayoutelement{#vertical:\v!text}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}% - \or - \edef\currentlayoutelement{#vertical:\v!text}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}% - \or - \edef\currentlayoutelement{#vertical:#horizontal}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}% - \or - \edef\currentlayoutelement{#vertical:\v!text}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}% - \or - \edef\currentlayoutelement{#vertical:#horizontal}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}% - \fi} - -%D Left and right texts are swapped on odd and even pages, but only when double -%D sided typesetting is enabled. - -\setvalue{\??layouttextstrut\v!yes}{\setstrut\strut} % maybe more variants - -\let\m_page_layouts_element_content\empty - -\protected\def\page_layouts_process_element_single#content% - {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx - \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname - \lastnamedcs - \else - \doifelsemarking\m_page_layouts_element_content - {\getmarking[\m_page_layouts_element_content][\v!first]}% - {#content}% - \fi} - -\protected\def\page_layouts_process_element_double#first#second% - {\doifelseoddpage - {\page_layouts_process_element_single{#first}} - {\page_layouts_process_element_single{#second}}} - -\protected\def\page_layouts_process_element_indeed#style#color#width% - {\begingroup - \uselayoutelementstyleandcolor#style#color% - \begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname - \ignorecrlf - \edef\currentlayoutelementwidth{\layoutelementparameter#width}% - \ifempty\currentlayoutelementwidth\else - \expandafter\page_layouts_process_element_limited - \fi\p_text - \endgroup} - -\def\page_layouts_process_element_limited#content% are the {}{}{} still needed? - {\limitated - left \currentlayoutelementwidth - text {#content} - sentinel {\unknown} - \relax} - -\setvalue{\??layouttextspecial\v!pagenumber}{\page_layouts_place_page_number} -\setvalue{\??layouttextspecial\v!date }{\currentdate} - -%D When specified, the texts are automatically limited in length. - -\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 the \type {status} -%D variable. This is handled by the next 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 - -\protected\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} - -\permanent\protected\def\doifelselayouttextline#vertical% shown or not - {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% - \ifx\currentlayoutelementstate\v!normal - \expandafter\firstoftwoarguments - \orelse\ifx\currentlayoutelementstate\v!start - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifelselayoutsomeline#vertical% present or not - {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% - \ifx\currentlayoutelementstate\v!none - \expandafter\secondoftwoarguments - \orelse\ifx\currentlayoutelementstate\v!high - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \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} - -% \setupheadertexts [11] -% \definetext [title] [header] [aa] -% \setupheadertexts [11] [22] -% \definetext [title] [header] [aa] [bb] -% \setupheadertexts [text] [11] [22] -% \definetext [title] [header] [text] [aa] [bb] -% \setupheadertexts [11] [22] [33] [44] -% \definetext [title] [header] [aa] [bb] [cc] [dd] -% \setupheadertexts [text] [11] [22] [33] [44] -% \definetext [title] [header] [text] [aa] [bb] [cc] [dd] - -\def\page_layouts_place_text_line_unknown#vertical#height% - {\global\settrue\resyncaftertextline - \begingroup % new - \page_layouts_reset_element_status#vertical% - \begincsname\namedlayoutelementhash{#vertical}\textlinestatus\endcsname - \begincsname\namedlayoutelementhash{#vertical:\v!text}\textlinestatus\endcsname - \begincsname\namedlayoutelementhash{#vertical:\v!margin}\textlinestatus\endcsname - \begincsname\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 is flushed. - -\permanent\protected\def\resetlayouttextlines % public - {\begincsname\??layouttextsreset\v!top \endcsname - \begincsname\??layouttextsreset\v!header\endcsname - \begincsname\??layouttextsreset\v!text \endcsname - \begincsname\??layouttextsreset\v!footer\endcsname - \begincsname\??layouttextsreset\v!bottom\endcsname - \ifconditional\resyncaftertextline - \calculateglobalvsizes - \page_backgrounds_recalculate - \global\setfalse\resyncaftertextline - \fi} - -\permanent\def\getspecificlayouttext#vertical#horizontal#what% - {\begincsname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname} - -% \settext[header][text][middle][xxx][yyy] - -\permanent\tolerant\protected\def\settextcontent[#vertical]#spacer[#horizontal]#spacer[#one]#spacer[#two]#spacer[#three]% header text middle text/text - {\ifarguments\or\or\or % 3 - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}% - {\page_layouts_process_element_double{#one}{#one}}% - \or % 4 - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% - {\page_layouts_process_element_double{#two}{#two}}% - \or % 5 - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% - {\page_layouts_process_element_double{#two}{#three}}% - \fi} - -\let\currentlayoutelement\relax - -%D This will be redefined, so no \type {\frozen} here! - -\permanent\tolerant\protected\def\resettextcontent[#vertical]#spacer[#horizontal]#spacer[#tag]% header text middle - {\ifarguments\or\or % 2 - \edef\currentlayoutelement{#vertical:#horizontal}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!middletext - \resetlayoutelementparameter\c!righttext - \or % 3 - \edef\currentlayoutelement{#vertical:#horizontal}% - \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}% - \fi} - -\letvalue{\??layouttextcontent\v!text:\c!middle}\c!middletext -\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 macros. These are hooked -%D into the general purpose token list registers mentioned before. - -\let\currentlayouttextline\relax - -\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 - \enforced\let\\\ignoredlinebreak - \enforced\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 - \vkern\zeropoint}% keep the \dp, beware of \vtops, never change this! - \dp\b_page_layouts_element\zeropoint - \box\b_page_layouts_element - \vkern-#height\relax} - -\let\page_layouts_place_extra_text_left \empty % historic -\let\page_layouts_place_extra_text_right\empty % historic - -\def\page_layouts_place_text_line_right - {\hpack - {\ifdim\leftedgewidth>\zeropoint - \page_layouts_left_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth - \fi - \ifdim\leftmarginwidth>\zeropoint - \page_layouts_left_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\zerocount - \fi - \ifdim\makeupwidth>\zeropoint - \page_layouts_text_body_element_l_m_r_e - \fi - \ifdim\rightmarginwidth>\zeropoint - \page_layouts_right_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\plusone - \fi - \ifdim\rightedgewidth>\zeropoint - \page_layouts_right_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth - \fi}} - -\def\page_layouts_place_text_line_left - {\hpack - {\ifdim\leftedgewidth>\zeropoint - \page_layouts_left_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth - \fi - \ifdim\leftmarginwidth>\zeropoint - \page_layouts_left_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\zerocount - \fi - \ifdim\makeupwidth>\zeropoint - \page_layouts_text_body_element_e_r_m_l - \fi - \ifdim\rightmarginwidth>\zeropoint - \page_layouts_right_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\plusone - \fi - \ifdim\rightedgewidth>\zeropoint - \page_layouts_right_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth - \fi}} - -\def\page_layouts_left_edge_element_indeed#text#style#color#width% - {\letfromlayoutelementparameter\p_text#text% - \ifempty\p_text - \kern\leftedgewidth - \else - \hbox to \leftedgewidth\bgroup - \hss - \page_layouts_process_element_indeed#style#color#width% - \egroup - \fi} - -\def\page_layouts_left_edge_element#text#style#color#width% - {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}% - \page_layouts_place_element_indeed\leftedgewidth - {\page_layouts_left_edge_element_indeed#text#style#color#width}% - \kern\leftedgedistance} - -\def\page_layouts_right_edge_element_indeed#text#style#color#width% - {\letfromlayoutelementparameter\p_text#text% - \ifempty\p_text - \kern\rightedgewidth - \else - \hbox to \rightedgewidth\bgroup - \page_layouts_process_element_indeed#style#color#width% - \hss - \egroup - \fi} - -\def\page_layouts_right_edge_element#text#style#color#width% - {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}% - \kern\rightedgedistance - \page_layouts_place_element_indeed\rightedgewidth - {\page_layouts_right_edge_element_indeed#text#style#color#width}} - -% margin needs checking! - -\def\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo% - {\letfromlayoutelementparameter\p_text#text% - \ifempty\p_text - \kern\leftmarginwidth - \else - \hbox to \leftmarginwidth\bgroup - \hss - \page_layouts_process_element_indeed#style#color#width% - \egroup - \fi - \ifcase#margintoo\or - \letfromlayoutelementparameter\p_text\c!margintext - \ifempty\p_text\else - \kern-\leftmarginwidth - \hbox to \leftmarginwidth\bgroup - \hss - \p_text % styling ? - \egroup - \fi - \fi} - -\def\page_layouts_left_margin_element#text#style#color#width#margintoo% - {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}% - \page_layouts_place_element_indeed\leftmarginwidth - {\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo}% - \kern\leftmargindistance} - -\def\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo% - {\letfromlayoutelementparameter\p_text#text% - \ifempty\p_text - \kern\rightmarginwidth - \else - \hbox to \rightmarginwidth\bgroup - \page_layouts_process_element_indeed#style#color#width% - \hss - \egroup - \fi - \ifcase#margintoo\or - \letfromlayoutelementparameter\p_text\c!margintext - \ifempty\p_text\else - \kern-\rightmarginwidth - \hbox to \rightmarginwidth\bgroup - \p_text % ? styling - \hss - \egroup - \fi - \fi} - -\def\page_layouts_right_margin_element#text#style#color#width#margintoo% - {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}% - \kern\rightmargindistance - \page_layouts_place_element_indeed\rightmarginwidth - {\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo}} - -\def\page_layouts_text_body_element_indeed_l_m_r_e - {\letfromlayoutelementparameter\p_text\c!lefttext - \ifempty\p_text - \ifempty\page_layouts_place_extra_text_left\else - \hbox to \makeupwidth\bgroup - \page_layouts_place_extra_text_left - \hss - \egroup - \kern-\makeupwidth - \fi - \else - \hbox to \makeupwidth\bgroup - \page_layouts_place_extra_text_left - \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth - \hss - \egroup - \kern-\makeupwidth - \fi - \letfromlayoutelementparameter\p_text\c!middletext - \ifempty\p_text\else - \hbox to \makeupwidth\bgroup - \hss - \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth - \hss - \egroup - \kern-\makeupwidth - \fi - \letfromlayoutelementparameter\p_text\c!righttext - \ifempty\p_text - \kern\makeupwidth - \else - \hbox to \makeupwidth\bgroup - \hss - \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth - \egroup - \fi} - -\def\page_layouts_text_body_element_indeed_e_r_m_l - {\letfromlayoutelementparameter\p_text\c!righttext - \ifempty\p_text\else - \hbox to \makeupwidth\bgroup - \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth - \hss - \egroup - \kern-\makeupwidth - \fi - \letfromlayoutelementparameter\p_text\c!middletext - \ifempty\p_text\else - \hbox to \makeupwidth\bgroup - \hss - \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth - \hss - \egroup - \kern-\makeupwidth - \fi - \letfromlayoutelementparameter\p_text\c!lefttext - \ifempty\p_text - \ifempty\page_layouts_place_extra_text_right - \kern\makeupwidth - \else - \hbox to \makeupwidth\bgroup - \hss - \page_layouts_place_extra_text_right - \egroup - \fi - \else - \hbox to \makeupwidth\bgroup - \hss - \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth - \page_layouts_place_extra_text_right - \egroup - \fi} - -\def\page_layouts_text_body_element_l_m_r_e - {\edef\currentlayoutelement{\currentlayouttextline:\v!text}% - \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_l_m_r_e} - -\def\page_layouts_text_body_element_e_r_m_l - {\edef\currentlayoutelement{\currentlayouttextline:\v!text}% - \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_e_r_m_l} - -\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 purpose, one can add a rule -%D in the following way. This method makes the rules disappear in case of an empty -%D text 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 \type {unknown}. This -%D one is used to take care of symbolic texts handlers. -%D -%D \showsetup{definetext} -%D -%D The next example demonstrates how we can use this mechanism to provide page -%D (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 - -\permanent\tolerant\protected\def\definetext[#tag]#spacer[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% - {\ifnum\lastarguments<\plusfour - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal]\relax}% 1, 2, 3 - \orelse\ifarguments\or\or\or\or - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a]\relax}% 4 - \or - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b]\relax}% 5 - \or - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c]\relax}% 6 - \or - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c][#d]\relax}% 7 - \fi} - -%D A few more page breakers: - -\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 main text, the top and -%D 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: -%D -%D We reset a previous location but only when it has a pagenumber associated. This -%D is a rather messy test but better than the MkII way where we use states and keep -%D 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 \protected 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 \empty - \let\page_layouts_place_extra_text_right\empty - \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]} - -\protected\def\strc_pagenumbers_set_location - {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}% - \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location - % unchanged - \else - \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location - \page_layouts_reset_page_number_location - \ifempty\p_strc_pagenumbers_location - % set otherwise - \orelse\ifx\p_strc_pagenumbers_location\v!none - % set otherwise - \else - \page_layouts_identify_page_number_location - \page_layouts_set_page_number_location - \fi - \fi} - -\def\page_layouts_place_page_number_left % historic - {\begingroup - \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}% - \ifzeropt\wd\scratchbox\else - \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}% - \ifempty\p_strc_pagenumbers_width - \box\scratchbox\tfskip - \else - \hpack 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}% - \ifempty\p_strc_pagenumbers_width - \tfskip\box\scratchbox - \else - \hpack to \p_strc_pagenumbers_width{\hss\box\scratchbox}% - \fi - \fi - \endgroup} - -\strc_pagenumbers_set_location % initializes - -\newbox\b_page_layouts_element - -\def\page_layouts_insert_elements - {\ifcase\pageornamentstate - \page_layouts_place_elements_indeed % we could have a special flag for always ignored - \fi} - -\def\page_layouts_place_elements_indeed - {\setbox\b_page_layouts_element\vpack - {\dontcomplain - \calculatereducedvsizes - \swapmargins - \offinterlineskip - \vkern\dimexpr-\topheight-\topdistance\relax - \the\toptextcontent - \vkern\dimexpr\topheight+\topdistance\relax - \the\headertextcontent - \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax - \anch_positions_place_anchors - \vkern\dimexpr-\textdistance-\textheight\relax - \the\texttextcontent - \vkern\textheight - \the\everyendoftextbody - \vkern\footerdistance - \the\footertextcontent - \vkern\dimexpr\footerheight+\bottomdistance\relax - \the\bottomtextcontent - \vkern\bottomheight - \vfilll}% - \smashbox\b_page_layouts_element - \box\b_page_layouts_element} - -% \ifdefined\page_prepare_backgrounds\else -% \let\page_prepare_backgrounds\gobbleoneargument -% \fi - -% only for very special controlled cases or experiments: - -\let\page_scale_text_box\gobbleoneargument - -\def\page_insert_body#1#2% - {\setbox\b_page_layouts_element\vpack - {\offinterlineskip - \calculatereducedvsizes - \calculatehsizes - \swapmargins - \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax - \dontleavehmode - %\page_prepare_backgrounds{#2}% - \hpack 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_apply_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 - \page_scale_text_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 (tracing) information. -%D -%D This will be stored as normal and overloaded in page-lyr and later in page-spr we -%D overload the the stored version .. eventually i will clear up the experimental -%D mess. - -\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded - {\setbox#1\hpack to \makeupwidth - {\hss % so don't change this - \setlayoutcomponentattribute{\v!page:\v!text}% - \vpack \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}% this will vbox - \hss}% - \dp#1\zeropoint} - -\protect \endinput diff --git a/tex/context/base/mkiv/phys-dim.mkxl b/tex/context/base/mkiv/phys-dim.mkxl deleted file mode 100644 index 3102650bf..000000000 --- a/tex/context/base/mkiv/phys-dim.mkxl +++ /dev/null @@ -1,808 +0,0 @@ -%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, space delimited mode is -%D now resticted! -%D -%D Depending on the digit mode the command \type {\digits} normalizes number -%D 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 purposes. -%D 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 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 well as different -%D formats. We strongly suggest you to use the grouped call. -%D -%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 -%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) - -\permanent\protected\def\setdigitmethod#1{\c_phys_digits_method #1\relax} -\permanent\protected\def\setdigitsign #1{\c_phys_digits_sign #1\relax} -\permanent\protected\def\setdigitorder #1{\c_phys_digits_order #1\relax} - -\aliased\let\setdigitmode\setdigitmethod % compatibility - -\def\phys_digits_normalized % we could calculate once and remember - {\ifcase\c_phys_digits_sign - \expandafter\secondoftwoarguments - \orelse\ifmmode - \expandafter\phys_digits_normalized_math - \else - \expandafter\phys_digits_normalized_text - \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] - -\permanent\protected\def\digitstextbinop#1% assumes preceding - {\ifmmode#1\else\fourperemspace\nobreak#1\fourperemspace\fi} - -%frozen\def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi} -\frozen\def\digitstimessymbol{\digitstextbinop\times} - -\frozen\protected\def\digitszeropadding {\hphantom{0}} -%frozen\protected\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}} -%frozen\protected\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}} -\frozen\protected\def\digitsnegative {\phys_digits_normalized{0}{\mathematics{\negative}}} -\frozen\protected\def\digitspositive {\phys_digits_normalized{0}{\mathematics{\positive}}} -%frozen\protected\def\digitsminus {\phys_digits_normalized{0}{\mathematics{-}}} -%frozen\protected\def\digitsplus {\phys_digits_normalized{0}{\mathematics{+}}} -\frozen\protected\def\digitsminus {\phys_digits_normalized{0}{\mathminus}} -\frozen\protected\def\digitsplus {\phys_digits_normalized{0}{\mathplus}} -\frozen\protected\def\digitsplusminus {\phys_digits_normalized{0}{\mathplusminus}} -\frozen\protected\def\digitsspace {\hphantom{0}} - \protected\def\digitsseparatorspace{\hphantom{.}} -\frozen\protected\def\digitssignspace {\hphantom{\digitsminus}} -\frozen\protected\def\digitshighspace {\hphantom{\digitspositive}} -\frozen\protected\def\digitspower #1{\digitstimessymbol10\phys_digits_raised{#1}} -\frozen\protected\def\digitspowerplus #1{\digitstimessymbol10\phys_digits_raised{\digitsplus#1}} -\frozen\protected\def\digitspowerminus #1{\digitstimessymbol10\phys_digits_raised{\digitsminus#1}} -\frozen\protected\def\digitsdigit #1{#1} - -\frozen\protected\def\normaldigitscommasymbol {,} -\frozen\protected\def\normaldigitsperiodsymbol{.} - -\aliased\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 - -\frozen\protected\def\digitscommasymbol {\csname\??digitscomma \number\c_phys_digits_method\endcsname} -\frozen\protected\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname} -\frozen\protected\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname} - -\frozen\protected\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing -\frozen\protected\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing -\frozen\protected\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing -\frozen\protected\def\digitsintermediateperiod{\digitscommasymbol } % more for tracing - -%D The user macro: - -\protected\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} - -\permanent\protected\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 now -%D but when we moved on to \LUATEX\ a variant was prototyped that permits a less -%D texie coding. I finally picked up that thread and cleaned up the code a bit so -%D users can now play with it. (The main reason was that I wanted to test -%D 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 extent we need -%D 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] - -\aliased\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 - -\frozen\protected\def\unitssmallspace {\thinspace} -\frozen\protected\def\unitsmediumspace{\medspace} -\frozen\protected\def\unitsbigspace {\thickspace} -\frozen\protected\def\unitsbackspace {\negthinspace} - -\permanent\protected\def\installunitsseparator#1#2% - {\setvalue{\??unitseparator#1}{#2}} - -\protected\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 {} - -\permanent\protected\def\installunitsspace#1#2% - {\setvalue{\??unitspace#1}{#2}} - -\protected\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 - \nocharacteralign -\to \everyunits - -\appendtoks - \frozen\instance\setuevalue\currentunit{\phys_units_direct{\currentunit}} -\to \everydefineunit - -\protected\def\phys_units_direct#1% - {\begingroup - \the\everyunits - \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}% - \enforced\edef\unitlanguage{\unitparameter\s!language}% - \enforced\let\prefixlanguage\unitlanguage - \enforced\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} - -\protected\def\phys_units_direct_text_in_math#1% - {\mathtext{% - \c_phys_units_mode\plustwo - \phys_units_indeed{#1}% - \phys_units_finish - }% - \endgroup} - -\protected\def\phys_units_direct_math#1% - {\c_phys_units_mode\plusone - \rm\tf % slow - \mathtf - \phys_units_indeed{#1}% - \phys_units_finish - \endgroup} - -\protected\def\phys_units_direct_text#1% - {\phys_units_indeed{#1}% - \phys_units_finish - \endgroup} - -\protected\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} - -\protected\def\phys_units_direct_nested#1#2% - {\phys_units_indeed{#2}} - -\appendtoks - \let\phys_units_direct\phys_units_direct_nested -\to \everyunits - -\protected\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}}} - -\permanent\protected\def\digitstextbinnop#1% - {\ifmmode#1\else#1\fourperemspace\fi} - -\permanent\protected\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix -\permanent\protected\def\unitsPU #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree} % unit -\permanent\protected\def\unitsPS #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix -\permanent\protected\def\unitsUS #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix -\permanent\protected\def\unitsP #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour} % prefix -\permanent\protected\def\unitsU #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree} % unit -\permanent\protected\def\unitsS #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone} % suffix -\permanent\protected\def\unitsO #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo} % operator -%permanent\protected\def\unitsN #1{\phys_units_start#1\c_phys_units_state\plusfive} % number -\permanent\protected\def\unitsC #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix} % connected -\permanent\protected\def\unitsQ #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount} -\permanent\protected\def\unitsR #1#2{% todo: tagging - \ifmmode - #2% - \orelse\ifnum#1=\plusone - \digitstextbinop{#2}% before and after - \else - \digitstextbinnop{#2}% after - \fi - \c_phys_units_state\zerocount - \setfalse\c_phys_units_dospace - \setfalse\c_phys_units_number - \setfalse\c_phys_units_quantity} -\permanent\protected\def\unitsRPM {\unitsR\plusone {±}} % todo: symbols -\permanent\protected\def\unitsRTO {\unitsR\plusone {–}} % todo: symbols -\permanent\protected\def\unitsRabout {\unitsR\zerocount{±}} % todo: symbols -\permanent\protected\def\unitsPopen {(} -\permanent\protected\def\unitsPclose {)} -\permanent\protected\def\unitrange #1{} - -% 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. - -\permanent\protected\def\phys_units_text_prime {\textacute} -\permanent\protected\def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute} -\permanent\protected\def\phys_units_text_celsius {°C} -\permanent\protected\def\phys_units_text_fahrenheit {°F} - -\permanent\protected\def\checkedtextprime - {\iffontchar\font"2032\relax\iffontchar\font"2033\relax - ′\else\phys_units_text_prime\fi\else\phys_units_text_prime - \fi} - -\permanent\protected\def\checkedtextdoubleprime - {\iffontchar\font"2033\relax\iffontchar\font"2032\relax - ″\else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime - \fi} - -% \permanent\protected\def\checkedtextcelsius -% {\ifmmode -% \phys_units_text_celsius -% \orelse\iffontchar\font"2103\relax -% ℃\else\phys_units_text_celsius -% \fi} -% -% \permanent\protected\def\checkedtextfahrenheit -% {\ifmmode -% \phys_units_text_fahrenheit -% \orelse\iffontchar\font"2109\relax -% ℉\else\phys_units_text_fahrenheit -% \fi} -% -% % but, as users don't like this ... - -\aliased\let\checkedtextcelsius \phys_units_text_celsius -\aliased\let\checkedtextfahrenheit\phys_units_text_fahrenheit - -\setelementnature[unit] [mixed] -\setelementnature[quantity][mixed] - -\let\phys_units_finish\relax - -\permanent\protected\def\unitsNstartindeed - {\ifmmode \else - \settrue\c_phys_units_quantity - \dostarttagged\t!quantity\empty - \settrue\c_phys_units_number - \dostarttagged\t!number\empty - \fi} - -\permanent\protected\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 - -% \aliased\let\unitsNstartindeed\unitsNstart - -\permanent\protected\def\unitsNstart - {\doifelsenextchar\unitsNstop\gobbleoneargument\unitsNstartindeed} - -% End of hack. - -\permanent\protected\def\unitsNspace - {\space} - -\permanent\protected\def\unitsN#1% - {\unitsNstart#1\unitsNstop} - -\def\phys_units_start - {\ifmmode - \dostarttagged\t!maction\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} - -\permanent\def\unitsraise - {\ifcase\c_phys_units_mode - \expandafter\unitshigh - \or - \expandafter\normalsuperscript - \or - \expandafter\unitshigh - \or - \expandafter\normalsuperscript - \fi} - -\permanent\def\unitslower - {\ifcase\c_phys_units_mode - \expandafter\unitslow - \or - \expandafter\normalsubscript - \or - \expandafter\unitslow - \or - \expandafter\normalsubscript - \fi} - -\protected\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} - -\permanent\protected\def\unitsTIMES - {\ifnum\c_phys_units_state=\plusone % suffix - \else - \unitssmallspace - \fi - \cdot} % or \times - -\permanent\protected\def\unitsOUTOF - {\ifnum\c_phys_units_state=\plusone % suffix - \else - \unitssmallspace - \fi - :} - -\permanent\protected\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}, \type -%D {suffix}, \type {symbol},\type {packaged}. You also need to define labels: -%D -%D \starttyping -%D \setupunittext -%D [point=pt, -%D basepoint=bp, -%D scaledpoint=sp, -%D didot=dd, -%D cicero=cc] -%D \stoptyping - -\permanent\tolerant\protected\def\registerunit[#1]#*[#2]% todo: public implementer - {\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/tex/context/base/mkiv/prop-ini.mkiv b/tex/context/base/mkiv/prop-ini.mkiv deleted file mode 100644 index 3b1c59b24..000000000 --- a/tex/context/base/mkiv/prop-ini.mkiv +++ /dev/null @@ -1,64 +0,0 @@ -%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/tex/context/base/mkiv/publ-inc.mkxl b/tex/context/base/mkiv/publ-inc.mkxl deleted file mode 100644 index 8e6cd2bdf..000000000 --- a/tex/context/base/mkiv/publ-inc.mkxl +++ /dev/null @@ -1,63 +0,0 @@ -%D \module -%D [ file=publ-inc, -%D version=2018.06.23, -%D title=\CONTEXT\ Publication Macros, -%D subtitle=XML inclusion, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Publication Macros / XML inclusion} - -\registerctxluafile{publ-inc}{} - -%D A teaser for Alan. - -\unprotect - -\definesymbol[btxattachment][{\infofont\darkred btx}] -\definesymbol[btxcomment] [{\infofont\darkblue btx}] - -\protected\def\btx_add_blob#1#2% - {\relax - \clf_btxentrytobuffer{\currentbtxdataset}{\currentbtxtag}{temp-btx-export}% - #2% - [\c!symbol=#1,% - \c!space=\v!yes, - \c!buffer=temp-btx-export,% - \c!name={\currentbtxtag.bib}]% - \relax} - -\permanent\protected\def\btxattach - {\iftrialtypesetting \else \ifexporting \iflocation - \dostarttagged\t!ignore\empty - \btx_add_blob{btxattachment}\attachment - \dostoptagged - \fi \fi \fi} - -\permanent\protected\def\btxcomment - {\iftrialtypesetting \else \ifexporting \iflocation - \dostarttagged\t!ignore\empty - \btx_add_blob{btxcomment}\comment - \dostoptagged - \fi \fi \fi} - -%D This kind of feature creep is not yet configurable, nor documented. - -\permanent\protected\def\btxaddsource - {\iftrialtypesetting \else \ifexporting \iflocation - \dostarttagged\t!ignore\empty - \llap{% - \btx_add_blob{btxattachment}\attachment - \quad - \btx_add_blob{btxcomment}\comment - \hskip\leftmargindistance - }% - \dostoptagged - \fi \fi \fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/publ-ini.mkxl b/tex/context/base/mkiv/publ-ini.mkxl deleted file mode 100644 index 7c1671528..000000000 --- a/tex/context/base/mkiv/publ-ini.mkxl +++ /dev/null @@ -1,2029 +0,0 @@ -%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: some clf_ can be public implementers instead - -% TODO: s! vs v! for default and neutral key/values -% todo: too many refs in list - -% TODO A.-B. Foo (dash as connector, see JMH) - -% 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}{} -\registerctxluafile{publ-ini}{} -\registerctxluafile{publ-sor}{} -\registerctxluafile{publ-aut}{} -\registerctxluafile{publ-usr}{} -\registerctxluafile{publ-oth}{} % this could become an option -\registerctxluafile{publ-fnd}{} % new method (for the moment only local) -\registerctxluafile{publ-jrn}{} -\registerctxluafile{publ-reg}{} - -\unprotect - -\startcontextdefinitioncode - -%D These are currently not interfaced. - -\definesystemconstant {btx} - -\definesystemconstant {btxset} -\definesystemconstant {btxref} -\definesystemconstant {btxint} -\definesystemconstant {btxltx} -\definesystemconstant {btxrtx} -\definesystemconstant {btxatx} -\definesystemconstant {btxbtx} -\definesystemconstant {btxspc} -\definesystemconstant {btxlst} -\definesystemconstant {btxcom} - -\defineinterfacevariable {btxcite} {btxcite} -\defineinterfacevariable {btxlist} {btxlist} -\defineinterfacevariable {btxrendering} {btxrendering} - -\definelabelclass[btxlabel][2] - -\clf_definelabels{btxlabel}{btx}\s!false\relax - -% 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. - -\mutable\let\currentbtxspecification \empty -\mutable\let\currentbtxspecificationfallback\empty - -\installmacrostack\currentbtxspecification -\installmacrostack\currentbtxspecificationfallback - -\permanent\protected\def\startbtxrenderingdefinitions[#1]% - {\unprotect - \push_macro_currentbtxspecification - \edef\currentbtxspecification{#1}} - -\permanent\protected\def\stopbtxrenderingdefinitions - {\pop_macro_currentbtxspecification - \protect} - -\permanent\protected\def\loadfoundpublicationfile#1#2% name foundname / not a user command - {\input{#2}} - -\permanent\protected\def\loadbtxdefinitionfile [#1]{\clf_btxloaddefinitionfile {#1}} % can be public implementer -\permanent\protected\def\loadbtxreplacementfile[#1]{\clf_btxloadreplacementfile{#1}} % can be public implementer - -\protected\def\publ_specification_push#1% - {\push_macro_currentbtxspecification - \push_macro_currentbtxspecificationfallback - \edef\currentbtxspecification{#1}% - \edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}% - \ifx\currentbtxspecificationfallback\currentbtxspecification - \let\currentbtxspecificationfallback\empty - \fi - \clf_btxsetspecification{\currentbtxspecification}} - -\protected\def\publ_specification_pop - {\pop_macro_currentbtxspecificationfallback - \pop_macro_currentbtxspecification - \clf_btxsetspecification{\currentbtxspecification}} - -\protected\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]% - \ifempty\currentbtxspecification - % 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 - -\protected\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]}} - -% \protected\def\btxcheckdefine#1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain{define}{#1}{#2}}} -% \protected\def\btxchecksetup #1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain {setup}{#1}{#2}}} - -\permanent\protected\def\btxcheckdefine#1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain{define}{#1}}} % {#2} -\permanent\protected\def\btxchecksetup #1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain {setup}{#1}}} % {#2} - -% for the moment experimental: - -\permanent\protected\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}% - \orelse\ifnum\btxsetupmode=\doingrootsetupnamed - \doifelsecommandhandler\??btx\currentbtx - {\publ_specification_set{\btxparameter\c!specification}}% - {}% maybe a warning - \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 - -\protected\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 - -\permanent\protected\def\setbtxparameterset#1#2% - {\edef\currentbtx - {\ifcsname\??btx\currentbtxspecification:#1:#2:\s!parent\endcsname - \currentbtxspecification:% - \orelse\ifempty\currentbtxspecificationfallback - \orelse\ifcsname\??btx\currentbtxspecificationfallback:#1:#2:\s!parent\endcsname - \currentbtxspecificationfallback:% - \fi#1:#2}} - -\permanent\protected\def\setbtxparametersetroot#1% - {\edef\currentbtx - {\ifcsname\??btx\currentbtxspecification:#1:\s!parent\endcsname - \currentbtxspecification:#1% - \orelse\ifempty\currentbtxspecificationfallback - \orelse\ifcsname\??btx\currentbtxspecificationfallback:#1:\s!parent\endcsname - \currentbtxspecificationfallback:#1% - \fi}} - -\permanent\protected\def\setbtxrendering - {\edef\currentbtxrendering - {\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname - \currentbtxspecification - \orelse\ifempty\currentbtxspecificationfallback - \orelse\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname - \currentbtxspecificationfallback - \fi}} - -\permanent\protected\def\setbtxlist % maybe simplify this one, always list=rendering? - {\edef\currentbtxlist - {\ifcsname\??btx\currentbtxrendering:\s!parent\endcsname - \currentbtxrendering - \orelse\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname - \currentbtxspecification - \orelse\ifempty\currentbtxspecificationfallback - \orelse\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname - \currentbtxspecificationfallback - \fi}% - \edef\currentlist{\s!btx:\currentbtxlist}} - -\permanent\protected\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 - \orelse\iffirstargument - \clf_btxusedataset - specification {\dummyparameter\c!specification}% - dataset {\v!default}% - filename {#1}% - \relax - \fi - \endgroup} - -\definebtxdataset - [\v!default] -% [\c!language=] % nothing set so use current - -% \usebtxdataset -% [default] -% [mybibs.bib] - -%D These can be overloaded in the traditional module so we go \type {\frozen} -%D instead of \type {\permanent}. - -\frozen\let\stoppublication\relax - -\frozen\tolerant\protected\def\startpublication[#1]#*[#2]% - {\begingroup - \catcode\commentasciicode\othercatcode - \ifparameters - \expandafter\publ_set_publication_default - \or - \expandafter\publ_set_publication_checked - \or - \expandafter\publ_set_publication_indeed - \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 - -\permanent\protected\def\btxcommand#1% - {\ifcsname\??btxcommand#1\endcsname - \expandafter\publ_command_yes - \else - \expandafter\publ_command_nop - \fi{#1}} - -\newtoks\t_btx_cmd -\newbox \b_btx_cmd - -\t_btx_cmd{\global\setbox\b_btx_cmd\hpack{\clf_btxcmdstring}} - -\aliased\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\letcsname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname - \orelse\ifcsname\utfupper{#1}\endcsname - \showmessage\m!publications{10}{#1}{\utfupper{#1}}% - \global\letcsname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname - \else - \showmessage\m!publications{11}{#1}% - \setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}% - \fi - \publ_command_yes{#1}} - -\permanent\protected\def\definebtxcommand#1% {body} #1..#n{body} - {\setuvalue{\??btxcommand\csstring#1}}% - -% access - -\let\currentbtxtag \empty -\let\currentbtxdataset\v!default - -\permanent\protected\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 - -% todo we can pick up the current's at the lua end (implementers) - -%permanent\def\btxfield #1{\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}} -%permanent\def\btxdetail #1{\clf_btxdetail {\currentbtxdataset}{\currentbtxtag}{#1}} -%permanent\def\btxflush #1{\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}} -%permanent\def\btxdirect #1{\clf_btxdirect {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxfieldname #1{\clf_btxfieldname {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxfieldtype #1{\clf_btxfieldtype {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxfoundname #1{\clf_btxfoundname {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxfoundtype #1{\clf_btxfoundtype {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxauthorfield#1{\clf_btxauthorfield \currentbtxauthorindex{#1}} -\permanent\def\btxdoifelse #1{\clf_btxdoifelse {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxdoif #1{\clf_btxdoif {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\def\btxdoifnot #1{\clf_btxdoifnot {\currentbtxdataset}{\currentbtxtag}{#1}} - -\aliased\let\btxsetup\fastsetup - -\permanent\def\btxfield #1{\dostarttagged\t!pubfld{#1}\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} -\permanent\def\btxdetail #1{\dostarttagged\t!pubfld{#1}\clf_btxdetail{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} -\permanent\def\btxflush #1{\dostarttagged\t!pubfld{#1}\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} -\permanent\def\btxdirect #1{\dostarttagged\t!pubfld{#1}\clf_btxdirect{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} -%permanent\def\btxauthorfield#1{\dostarttagged\t!pubfld{#1}\clf_btxauthorfield \currentbtxauthorindex{#1}\dostoptagged} - -%D How complex will we go? Can we assume that e.g. an apa style will not be mixed -%D with another one? I think this assumption is okay. For manuals we might want to -%D mix but we can work around it. - -%D Rendering. - -\permanent\protected\def\btxspace {\removeunwantedspaces\space} -\permanent\protected\def\btxnobreakspace {\removeunwantedspaces\nobreakspace} % these two are -\permanent\protected\def\btxnbsp {\removeunwantedspaces\nbsp} % the same anyway -\permanent\protected\def\btxperiod {\removeunwantedspaces.\space} -\permanent\protected\def\btxcomma {\removeunwantedspaces,\space} -\permanent\protected\def\btxcommabreak {\removeunwantedspaces,\hskip\zeropoint plus .5\emwidth\relax} -\permanent\protected\def\btxcolon {\removeunwantedspaces:\space} -\permanent\protected\def\btxsemicolon {\removeunwantedspaces;\space} -\permanent\protected\def\btxlparent {\removeunwantedspaces\space(} % obsolete -\permanent\protected\def\btxrparent {\removeunwantedspaces)\space} % obsolete -\permanent\protected\def\btxleftparenthesis {\removeunwantedspaces\space(} -\permanent\protected\def\btxrightparenthesis {\removeunwantedspaces)\space} -\permanent\protected\def\btxrightparenthesisperiod{\removeunwantedspaces).\space} -\permanent\protected\def\btxrightparenthesiscomma {\removeunwantedspaces),\space} -\permanent\protected\def\btxleftbracket {\removeunwantedspaces\space[} -\permanent\protected\def\btxrightbracket {\removeunwantedspaces]\space} -\permanent\protected\def\btxrightbracketperiod {\removeunwantedspaces].\space} -\permanent\protected\def\btxrightbracketcomma {\removeunwantedspaces],\space} - -%D Variables: - -\mutable\let\currentbtxbacklink \empty \permanent\protected\def\btxsetbacklink {\def\currentbtxbacklink} -\mutable\let\currentbtxcategory \empty \permanent\protected\def\btxsetcategory {\def\currentbtxcategory} -\mutable\let\currentbtxcombis \empty \permanent\protected\def\btxsetcombis {\def\currentbtxcombis} -\mutable\let\currentbtxdataset \empty \permanent\protected\def\btxsetdataset {\def\currentbtxdataset} -\mutable\let\currentbtxfirst \empty \permanent\protected\def\btxsetfirst {\def\currentbtxfirst} -\mutable\let\currentbtxsecond \empty \permanent\protected\def\btxsetsecond {\def\currentbtxsecond} -\mutable\let\currentbtxsuffix \empty \permanent\protected\def\btxsetsuffix {\def\currentbtxsuffix} -\mutable\let\currentbtxinternal \empty \permanent\protected\def\btxsetinternal {\def\currentbtxinternal} -\mutable\let\currentbtxlefttext \empty \permanent\protected\def\btxsetlefttext {\def\currentbtxlefttext} -\mutable\let\currentbtxrighttext \empty \permanent\protected\def\btxsetrighttext {\def\currentbtxrighttext} -\mutable\let\currentbtxbefore \empty \permanent\protected\def\btxsetbefore {\def\currentbtxbefore} -\mutable\let\currentbtxafter \empty \permanent\protected\def\btxsetafter {\def\currentbtxafter} -\mutable\let\currentbtxlanguage \empty \permanent\protected\def\btxsetlanguage {\def\currentbtxlanguage} -\mutable\let\currentbtxtag \empty \permanent\protected\def\btxsettag {\def\currentbtxtag} -\mutable\let\currentbtxnumber \empty \permanent\protected\def\btxsetnumber {\def\currentbtxnumber} -\mutable\let\currentbtxfirstinternal\empty \permanent\protected\def\btxsetfirstinternal{\def\currentbtxfirstinternal} -\mutable\let\currentbtxlastinternal \empty \permanent\protected\def\btxsetlastinternal {\def\currentbtxlastinternal} - -\mutable\let\currentbtxauthorvariant\v!normal \permanent\protected\def\btxsetauthorvariant{\def\currentbtxauthorvariant} -\mutable\let\currentbtxfirstnames \empty \permanent\protected\def\btxsetfirstnames {\let\currentbtxfirstnames\currentbtxfirstnames_indeed} -\mutable\let\currentbtxinitials \empty \permanent\protected\def\btxsetinitials {\let\currentbtxinitials \currentbtxinitials_indeed } -\mutable\let\currentbtxjuniors \empty \permanent\protected\def\btxsetjuniors {\let\currentbtxjuniors \currentbtxjuniors_indeed } -\mutable\let\currentbtxsurnames \empty \permanent\protected\def\btxsetsurnames {\let\currentbtxsurnames \currentbtxsurnames_indeed } -\mutable\let\currentbtxvons \empty \permanent\protected\def\btxsetvons {\let\currentbtxvons \currentbtxvons_indeed } - -\newconstant\currentbtxoverflow \permanent\protected\def\btxsetoverflow #1{\currentbtxoverflow #1\relax} -\newconstant\currentbtxconcat \permanent\protected\def\btxsetconcat #1{\currentbtxconcat #1\relax} -\newconstant\currentbtxcount \permanent\protected\def\btxsetcount #1{\currentbtxcount #1\relax} -\newconstant\currentbtxauthorindex %permanent\protected\def\btxsetauthorindex#1{\currentbtxauthorindex#1\relax} % passed directly -\newconstant\currentbtxauthorcount %permanent\protected\def\btxsetauthorcount#1{\currentbtxauthorcount#1\relax} % passed directly -\newconstant\currentbtxauthorstate \permanent\protected\def\btxsetauthorstate#1{\currentbtxauthorstate#1\relax} - -\protected\def\currentbtxfirstnames_indeed{\clf_btxcurrentfirstnames\numexpr\currentbtxauthorindex\relax} -\protected\def\currentbtxinitials_indeed {\clf_btxcurrentinitials \numexpr\currentbtxauthorindex\relax} -\protected\def\currentbtxjuniors_indeed {\clf_btxcurrentjuniors \numexpr\currentbtxauthorindex\relax} -\protected\def\currentbtxsurnames_indeed {\clf_btxcurrentsurnames \numexpr\currentbtxauthorindex\relax} -\protected\def\currentbtxvons_indeed {\clf_btxcurrentvons \numexpr\currentbtxauthorindex\relax} - -\mutable\let\currentbtxfirstpage \empty \permanent\protected\def\btxsetfirstpage#1{\def\currentbtxfirstpage{\btx_page_number{#1}}} -\mutable\let\currentbtxlastpage \empty \permanent\protected\def\btxsetlastpage #1{\def\currentbtxlastpage {\btx_page_number{#1}}} - -\mutable\let\currentbtxfield \empty -\mutable\let\currentbtxfielddoi \empty -\mutable\let\currentbtxfieldmonth \empty -\mutable\let\currentbtxfieldyear \empty -\mutable\let\currentbtxfieldurl \empty -\mutable\let\currentbtxcriterium \empty -\mutable\let\currentbtxlist \empty -\mutable\let\currentbtxlistentry \empty -\mutable\let\currentbtxlistindex \empty -\mutable\let\currentbtxreference \empty -\mutable\let\currentbtxrenderingtitle \empty -\mutable\let\currentbtxcitetag \empty - -\mutable\def\currentbtxauthorvariant{normal} - -\protected\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\currentbtxlanguage \empty - \let\currentbtxsuffix \empty - %\let\currentbtxdataset \empty % will always be set - %\let\currentbtxtag \empty % will always be set - \let\currentbtxnumber \empty} - -\protected\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 \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} - -\protected\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} - -\protected\def\btx_reset_numbering % probably not needed - {\let \currentbtxfirst \empty - \let \currentbtxsecond\empty - \let \currentbtxsuffix\empty - \setconstant\currentbtxconcat\zerocount} - -%D Pages: - -\protected\def\btx_page_number#1% - {\def\currentlistindex{#1}% - \structurelistpagenumber} - -%D Language: - -\mutable\def\mainbtxlanguage{\currentmainlanguage} - -\protected\def\btx_check_language - {\let\mainbtxlanguage\currentlanguage - \ifempty\currentbtxlanguage - \let\currentbtxlanguage\currentlanguage - \else - \btx_check_language_indeed - \fi} - -\protected\def\btx_check_language_indeed - {\edef\currentbtxlanguage{\reallanguagetag\currentbtxlanguage}% - \ifempty\currentbtxlanguage - \let\currentbtxlanguage\currentlanguage - \orelse\ifx\currentbtxlanguage\currentlanguage\else - \setcurrentlanguage\currentmainlanguage\currentbtxlanguage - \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. - -\permanent\protected\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!interaction=\v!none, - %\c!alternative=\v!paragraph, - %\c!width=\v!auto, - %\c!distance=\emwidth, - \c!before=\blank, - \c!after=\blank] - -\permanent\tolerant\protected\def\setupbtxlist[#1]#*[#2]% - {\ifarguments\or - \setuplist[\s!btx][#1]% - \or - \setuplist[\s!btx:#1][#2]% - \fi} - -\appendtoks - \ifempty\currentbtxrenderingparent - \definelist - [\s!btx:\currentbtxrendering]% - [\s!btx]% - \orelse\ifx\currentbtxrenderingparent\s!btx - \definelist - [\s!btx:\currentbtxrendering]% - [\s!btx]% - \else - \definelist - [\s!btx:\currentbtxrendering]% - [\s!btx:\currentbtxrenderingparent]% - \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 - -\protected\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} - -\permanent\protected\def\btxpagesetup#1% there will be no left|right|command|style at this inner level - {\begingroup - \publ_fast_setup\plusfive\s!list\s!page - \endgroup - \btx_reset_page} % probably not needed - -\permanent\protected\def\btxnumberingsetup#1% - {\begingroup - \dostarttagged\t!listtag\empty - \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering % brrrr \setbtxlist - \btxparameter\c!left - \publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}% - \btxparameter\c!right - \dostoptagged - \endgroup - \btx_reset_numbering} % probably not needed - -% end of page stuff - -\permanent\protected\def\btxflushlisttext - {\begingroup - \usebtxstyleandcolor\c!style\c!color - \ignorespaces - \publ_fast_setup\plusfour\s!list\currentbtxcategory - \removeunwantedspaces - \endgroup} - -\permanent\protected\def\btxflushlistcombis - {\begingroup - \processcommacommand[\currentbtxcombis]\btx_entry_inject_combi % maybe in lua - \endgroup} - -\def\btx_entry_inject_list_text - {\publ_fast_setup\plusfour\s!list\s!text} - -\ifdefined\dotagpublication \else \aliased\let\dotagpublication\gobbletwoarguments \fi - -\protected\def\btx_entry_inject - {\begingroup - \dostarttagged\t!publication\empty - \dotagpublication\currentbtxdataset\currentbtxtag - \redoconvertfont % see (**) in strc-lst, this will become an configuration option - \edef\currentbtxcategory{\btxfield{category}}% - \ignorespaces - \ifconditional\c_btx_list_texts - \dostarttagged\t!listtext\s!left - \currentbtxbefore - \dostoptagged - \fi - %\dostarttagged\t!listcontent\empty - \btx_entry_inject_list_text - %\dostoptagged - \ifconditional\c_btx_list_pages - \dostarttagged\t!listpage\empty - \btx_entry_inject_pages - \dostoptagged - \fi - \ifconditional\c_btx_list_texts - \dostarttagged\t!listtext\s!right - \currentbtxafter - \dostoptagged - \fi - \dostoptagged - \endgroup} - -\permanent\protected\def\btxshowentryinline[#1]#*[#2]% - {\ifarguments - \ctxcommand{showbtxentry("\currentbtxdataset","\currentbtxtag")} - \or - \ctxcommand{showbtxentry("\currentbtxdataset","#1")} - \or - \ctxcommand{showbtxentry("#1","#2")} - \fi} - -\permanent\protected\def\btxstartcombientry - {\begingroup} - -\permanent\protected\def\btxstopcombientry - {\endgroup} - -\permanent\protected\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} - -\newtoks\everybtxlistrendering - -\appendtoks - \setbtxlist - % - \edef\currentbtxcriterium{\btxrenderingparameter\c!criterium}% \v!cite will become \s!cite - \ifempty\currentbtxcriterium - \let\currentbtxcriterium\v!previous - \orelse\ifx\currentbtxcriterium\v!cite - \let\currentbtxcriterium\v!here - \fi - % - \iflocation - \letinteractionparameter\c!style\empty -% \letinteractionparameter\c!color\empty -% \letinteractionparameter\c!contrastcolor\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 - -\permanent\protected\def\btxsetnoflistentries #1{\edef\nofbtxlistentries {#1}} -\permanent\protected\def\btxsetcurrentlistentry#1{\edef\currentbtxlistentry{#1}} -\permanent\protected\def\btxsetcurrentlistindex#1{\edef\currentbtxlistindex{#1}} - -\permanent\protected\def\btxdoifelsesameaspreviouschecked#1#2% #1 == always | doublesided - {\clf_btxdoifelsesameasprevious - {\currentbtxdataset}% - \currentbtxlistentry% - {#2}% - \c_btx_list_reference - {#1}} - -\permanent\protected\def\btxdoifelsesameasprevious - {\btxdoifelsesameaspreviouschecked\v!doublesided} - -\permanent\protected\def\btxdoifelsecombiinlist#1#2% - {\clf_btxdoifelsecombiinlist{#1}{#2}} - -\aliased\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked -\aliased\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious -\aliased\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist - -\tolerant\def\publ_place_list_indeed#1#2[#3]#*[#4]% - {\begingroup - \ifparameters - \let\currentbtxrendering\currentbtxspecification - \or - \ifhastok={#3}% - % [settings] - \let\currentbtxrendering\currentbtxspecification - \setupcurrentbtxrendering[#3]% - \edef\p_specification{\btxrenderingparameter\c!specification}% - \ifempty\p_specification\else - \let\currentbtxspecification\p_specification - \let\currentbtxrendering\currentbtxspecification % tricky - \fi - \else - \edef\currentbtxrendering{#3}% - \edef\p_specification{\btxrenderingparameter\c!specification}% - \ifempty\p_specification\else - \let\currentbtxspecification\p_specification - \fi - \fi - \or - % [rendering] [settings] - \edef\currentbtxrendering{#3}% - \setupcurrentbtxrendering[#4]% - \edef\p_specification{\btxrenderingparameter\c!specification}% - \ifempty\p_specification\else - \let\currentbtxspecification\p_specification - \fi - \fi - \setbtxparameterset\currentbtxspecification\s!list - \the\everybtxlistrendering - \ifconditional#1\relax - \edef\currentbtxrenderingtitle{\btxrenderingparameter\c!title}% - \ifempty\currentbtxrenderingtitle - \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\headtext{\currentbtxrendering}}]}% - \else - \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\currentbtxrenderingtitle}]}% - \fi - \fi - \ifempty\currentbtxrendering - \setbtxrendering % hm - \fi - \edef\currentbtxdataset{\btxrenderingparameter\c!dataset}% - \uselanguageparameter\btxdatasetparameter % new - \setbtxlist - \the\everystructurelist - \the\everysetupbtxlistplacement - % 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}% - filter {\btxrenderingparameter\c!filter}% - \relax - \ifnum\nofbtxlistentries>\zerocount - \forgetall - \btxrenderingparameter\c!before - \ifconditional#2\relax - \edef\p_command{\btxrenderingparameter\c!command}% - \ifempty\p_command - \edef\p_setups{\btxrenderingparameter\c!setups}% - \ifempty\p_setups - \else - \directsetup{\p_setups}% - \fi - \else - \expandafter\p_command\expandafter{\number\nofbtxlistentries}\relax - \fi - \else - \dostarttagged\t!publications\currentbtxrendering - \dostarttagged\t!list{btx}% - \startpacked[\v!blank]% - % sorting and so - \clf_btxpreparelistentries{\currentbtxdataset}% could be put in collect - % next we analyze the width - \ifempty\currentbtxnumbering \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 - \dostoptagged - \dostoptagged - \fi - \btxrenderingparameter\c!after - \fi - \ifconditional#1\relax - \stopnamedsection - \fi - \global\advance\btxblock\plusone - \endgroup} - -\permanent\protected\def\placebtxrendering {\publ_place_list_indeed\conditionalfalse\conditionalfalse} -\permanent\protected\def\completebtxrendering{\publ_place_list_indeed\conditionaltrue \conditionalfalse} -\permanent\protected\def\flushbtxrendering {\publ_place_list_indeed\conditionalfalse\conditionaltrue } - -\aliased\let\completelistofpublications\completebtxrendering % for old times sake -\aliased\let\placelistofpublications \placebtxrendering % for old times sake - -%D This is somewhat special (for Alan of course): -%D -%D \starttyping -%D % #1 is number of entries -%D -%D \starttexdefinition unexpanded btx:for:alan:wrapper #1 -%D \bTABLE -%D % we can have a command or setups -%D \flushbtxentries[command=\texdefinition{btx:for:alan:content}] -%D \eTABLE -%D \stoptexdefinition -%D -%D % #1 is tag -%D -%D \starttexdefinition unexpanded btx:for:alan:content #1 -%D \bTR -%D \bTD -%D \btxsettag{#1} -%D \btxfield{name} -%D \eTD -%D \eTR -%D \stoptexdefinition -%D -%D % we can have a command or setups -%D -%D \flushbtxrendering [method=dataset,command=\texdefinition{btx:for:alan:wrapper}] -%D \stoptyping -%D -%D Because we want to be ungrouped we use a special loop construct. - -\permanent\protected\def\btxsetlisttag#1% - {\clf_btxflushlisttag{\currentbtxdataset}#1\relax} - -\newcount\c_btx_list_index - -\let\m_btx_list_action\empty - -\def\publ_flush_list_step_command - {\btxsetlisttag{\c_btx_list_index} - \expandafter\m_btx_list_action\expandafter{\currentbtxtag}% - \ifnum\c_btx_list_index<\nofbtxlistentries - \advance\c_btx_list_index\plusone - \expandafter\publ_flush_list_step_command - \else - \glet\m_btx_list_action\relax - \fi} - -\def\publ_flush_list_step_setup - {\btxsetlisttag{\c_btx_list_index} - \directsetup{\m_btx_list_action}% - \ifnum\c_btx_list_index<\nofbtxlistentries - \advance\c_btx_list_index\plusone - \expandafter\publ_flush_list_step_setup - \else - \glet\m_btx_list_action\relax - \fi} - -\permanent\protected\def\flushbtxentries[#1]% - {\begingroup - \getdummyparameters[\c!command=,\c!setups=,#1]% - \xdef\m_btx_list_action{\dummyparameter\c!command}% - \ifempty\m_btx_list_action - \xdef\m_btx_list_action{\dummyparameter\c!setups}% - \ifempty\m_btx_list_action - \endgroup - \c_btx_list_index\zerocount - \else - \endgroup - \c_btx_list_index\plusone - \doubleexpandafter\publ_flush_list_step_command - \fi - \else - \endgroup - \c_btx_list_index\plusone - \expandafter\publ_flush_list_step_command - \fi} - -%D So far. - -\permanent\def\currentbtxblock{\number\btxblock} - -% called at the lua end, for determining the width - -\permanent\protected\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 - {\dostarttagged\t!listcontent\empty - \btx_list_reference_inject - \btx_entry_inject - \dostoptagged} - -\def\btx_page_indeed - {} - -\permanent\protected\def\btxhandlelistentry - {\strc_lists_entry_process} - -\permanent\protected\def\btxstartlistentry % maybe pass i - {\begingroup - \global\advance\c_btx_list_reference\plusone} - -\permanent\protected\def\btxstoplistentry - {\iftrialtypesetting - \global\advance\c_btx_list_reference\minusone - \fi - \endgroup} - -\newtoks\everybtxlistentry - -\permanent\protected\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 - -\protected\def\btx_reference_indeed - {\begingroup - % redundant will go away: - \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering - % - \ifempty\currentbtxnumbering - % nothing - \orelse\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 - \endgroup} - -\permanent\protected\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} - -\protected\def\btx_reference_checked - {\dontleavehmode\hbox\bgroup % \hpack - \btx_reference_indeed - \egroup} - -\newcount\c_btx_list_reference - -\protected\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 - {\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 - %\ifempty\currentbtxcombis \else\s!btxcom={\currentbtxcombis},\fi% - \ifempty\currentbtxbefore \else\s!btxbtx={\currentbtxbefore},\fi% - \ifempty\currentbtxafter \else\s!btxatx={\currentbtxafter },\fi% - \ifempty\currentbtxbacklink\else\s!btxint=\number\currentbtxbacklink\fi - }% - {\s!btx::\v!list::\number\c_btx_list_reference}% - {\currentbtxnumber}} - -\newconditional\c_btx_cite_reference_injected - -\permanent\protected\def\btx_cite_reference_inject - {\ifconditional\c_btx_cite_reference_injected \else - \dontleavehmode - \iftrialtypesetting \else - \ifempty\currentbtxbacklink - % can be made empty when combining author / year - \orelse\ifnum\currentbtxbacklink>\zerocount - \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 - {\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,% - %\ifempty\currentbtxcombis \else\s!btxcom={\currentbtxcombis},\fi% - \ifempty\currentbtxbefore \else\s!btxbtx={\currentbtxbefore},\fi% - \ifempty\currentbtxafter \else\s!btxatx={\currentbtxafter },\fi% - \ifempty\currentbtxbacklink\else\s!btxint=\number\currentbtxbacklink,\fi - \ifempty\currentbtxciteuservariables\else,\currentbtxciteuservariables\fi]} - -\permanent\def\currentbtxuservariable #1{\clf_btxuservariable {\currentbtxdataset}{#1}} -\permanent\def\btxdoifelseuservariable#1{\clf_btxdoifelseuservariable{\currentbtxdataset}{#1}} - -\aliased\let\btxdoifuservariableelse\btxdoifelseuservariable - -\aliased\let\btxcitereference\btx_cite_reference_inject - -\mutable\let\currentbtxnumbering \empty -\mutable\let\currentbtxcitealternative \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 - \orelse\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 - \let\currentlistmethod\s!btx -\to \everysetupbtxlistplacement - -\permanent\tolerant\protected\def\btxremapauthor[#1]#*[#2]% - {\clf_btxremapauthor{#1}{#2}} - -\permanent\protected\def\btxshowauthorremapping - {\clf_btxshowauthorremapping} - -\permanent\protected\def\btxflushauthor - {\doifelsenextoptionalcs\btx_flush_author_yes\btx_flush_author_nop} - -\permanent\protected\def\btxflushsuffix - {\ifempty\currentbtxsuffix - % 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}} - -\protected\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}}% - connector {\btxparameter{\c!connector:initials}}% - }% - \relax - \endgroup} - -% yes or no: maybe just \flushauthor{...}{...} - -\permanent\protected\def\btxflushauthorname {\btx_flush_author{name}} % #1 -\permanent\protected\def\btxflushauthornormal {\btx_flush_author{normal}} % #1 -\permanent\protected\def\btxflushauthornormalshort {\btx_flush_author{normalshort}} % #1 -\permanent\protected\def\btxflushauthorinverted {\btx_flush_author{inverted}} % #1 -\permanent\protected\def\btxflushauthorinvertedshort{\btx_flush_author{invertedshort}} % #1 - -\mutable\let\currentbtxauthorfield\s!author - -\permanent\protected\def\btxsetauthorfield#1{\edef\currentbtxauthorfield{#1}} - -\permanent\protected\def\currentbtxciteauthorbyfield - {\begingroup - %\setbtxparameterset\s!cite\s!author - % the alternatives inherit from cite:author - % and APA distinguishes authoryears from authoryear ("and" vs. "&") - \setbtxparameterset\s!cite\currentbtxcitealternative - \clf_btxauthor - {\currentbtxdataset}% - {\currentbtxtag}% - {\currentbtxauthorfield}% - {% - 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} - -\permanent\protected\def\currentbtxciteauthor - {\let\currentbtxauthorfield\s!author - \currentbtxciteauthorbyfield} % always author - -\permanent\protected\def\btxstartauthor#1#2#3% a state > 0 signals that some authors can clash - {\begingroup - \currentbtxauthorindex#1\relax - \currentbtxauthorcount#2\relax - \currentbtxauthorstate#3\relax} - -\permanent\protected\def\btxstopauthor - {\endgroup} - -\permanent\protected\def\btxciteauthorsetup#1{\fastsetup{\s!btx:\s!cite:\s!author:#1}} -\permanent\protected\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} - -% Interaction -% -% Because we have more complex entries in lists we don't use the normal list -% interaction features. - -\newconditional\btxinteractive -\newconditional\btxinteractivenumber -\newconditional\btxinteractivetext -\newconditional\btxinteractivepage - -\mutable\let\currentbtxinteraction\empty - -\installcorenamespace{btxinteraction} - -\setvalue{\??btxinteraction\v!number}{\settrue\btxinteractivenumber} -\setvalue{\??btxinteraction\v!text }{\settrue\btxinteractivetext} -\setvalue{\??btxinteraction\v!page }{\settrue\btxinteractivepage} -\setvalue{\??btxinteraction\v!all }{\settrue\btxinteractivenumber - \settrue\btxinteractivetext - \settrue\btxinteractivepage} - -% \setupbtx[interaction=page] % or text or number or all -% \setupbtxrendering[pagestate=start] - -\appendtoks - \iflocation - \edef\currentbtxinteraction{\btxparameter\c!interaction}% - \ifx\currentbtxinteraction\v!stop - \setfalse\btxinteractive - \else - \let\structurelistlocation\empty - \settrue\btxinteractive - \begincsname\??btxinteraction\currentbtxinteraction\endcsname - \fi - \else - \setfalse\btxinteractive - \fi -\to \everysetupbtxlistplacement - -\appendtoks - \iflocation - \edef\currentbtxinteraction{\btxparameter\c!interaction}% - \ifx\currentbtxinteraction\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 - -\mutable\let\currentbtxciteuservariables\empty -\mutable\let\currentbtxcitealternative \empty - -\permanent\protected\def\btxhybridcite % so one can alias the old - {\dontleavehmode - \begingroup - \strictdoifelsenextoptional\publ_cite_tags_options\publ_cite_tags_indeed} - -\protected\def\publ_cite_tags_options[#1]% - {\strictdoifelsenextoptional{\publ_cite_tags_options_indeed{#1}}{\publ_cite_tags_indeed{#1}}} - -\protected\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} - -\protected\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}% - \ifempty\p_reference - \edef\currentbtxcitetag{#2}% - \else - \let\currentbtxcitetag\p_reference - \edef\currentbtxciteuservariables{#2}% - \fi - \edef\p_specification{\dummyparameter\c!specification}% - \ifempty\p_specification - \else - \let\currentbtxspecification\p_specification - \fi - \edef\p_alternative{\dummyparameter\c!alternative}% - \ifempty\p_alternative - \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 - -\mutable\let\currentbtxcitemethod\v!hidden - -\def\publ_cite_variant - {\begingroup - \publ_cite_handle_variant_indeed[\currentbtxcitetag]} - -\protected\def\publ_cite_handle_variant#1% - {\begingroup - \edef\currentbtxcitealternative{#1}% - \setbtxparameterset\s!cite\currentbtxcitealternative - \the\everysetupbtxciteplacement - \publ_cite_handle_variant_indeed} - -\permanent\protected\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} - -\aliased\let\dobtxcitevariantblob\publ_cite_handle_variant_blob % command can use it via lua - -\tolerant\def\publ_cite_handle_variant_indeed[#1]% - {\letbtxparameter\c!alternative\currentbtxcitealternative - \edef\currentbtxreference{#1}% - \saverunningstyleandcolor - \usebtxstyleandcolor\c!style\c!color - \uselanguageparameter\btxdatasetparameter % new - \btxparameter\c!left - \btxparameter\c!command{\dobtxcitevariantblob}% {\publ_cite_handle_variant_blob}% - \btxparameter\c!right - \endgroup} - -\permanent\protected\def\btxlistcitation {\publ_citation\v!list} -\permanent\protected\def\btxtextcitation {\publ_citation\v!text} -\permanent\protected\def\btxalwayscitation{\publ_citation\v!always} - -\tolerant\def\publ_citation#1[#2]#*[#3]% could be made more efficient but not now - {\dontleavehmode - \begingroup - \let\currentbtxcitemethod#1% - \ifparameter#3\or - \publ_cite_tags_options_indeed{#2}[#3]% - \else - \publ_cite_tags_indeed{#2}% - \fi} - -\permanent\tolerant\protected\def\btxhiddencitation[#1]% - {\iftrialtypesetting \else - \begingroup - \let\currentbtxcitemethod\v!hidden - \edef\currentbtxreference{#1}% - \clf_btxhandlenocite - method {\currentbtxcitemethod}% - dataset {\currentbtxdataset}% - reference {\currentbtxreference}% - \relax - %\clf_btxflushmarked - \endgroup - \fi} - -\permanent\protected\def\btxmissing#1% - {\dontleavehmode{\tttf<#1>}} - -%D Compatibility: - -\aliased\let\hiddencitation\btxhiddencitation \aliased\let\hiddencite\hiddencitation -\aliased\let\listcitation \btxlistcitation \aliased\let\listcite \listcitation -\aliased\let\textcitation \btxtextcitation \aliased\let\textcite \textcitation -\aliased\let\alwayscitation\btxalwayscitation \aliased\let\alwayscite\alwayscitation - -\permanent\protected\def\citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite} -\permanent\protected\def\nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite} - -\aliased\let\cite \citation -\aliased\let\nocite \nocitation -\aliased\let\usecitation\nocitation - -\protected\def\publ_entry_citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite} -\protected\def\publ_entry_nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite} - -\appendtoks - \enforced\let\cite \publ_entry_citation - \enforced\let\nocite\publ_entry_nocitation -\to \everybtxlistrendering - -\permanent\protected\def\btxdirectlistcite #1{\btxlistcitation [#1]\relax} % no optional arguments -\permanent\protected\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% - \orelse\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:#2\endcsname - \currentbtxspecificationfallback:#1:#2% - \orelse\ifcsname\??setup:\s!btx:#1:#2\endcsname - #1:#2% - \orelse\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname - \currentbtxspecification:#1:\s!unknown - \orelse\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:\s!unknown\endcsname - \currentbtxspecificationfallback:#1:\s!unknown - \else - #1:\s!unknown - \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% - \orelse\ifcsname\??setup:\s!btx:#1:#2\endcsname - #1:#2% - \orelse\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname - \currentbtxspecification:#1:\s!unknown - \else - #1:\s!unknown - \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 - -\protected\def\publ_fast_btx_setup_chain_inbetween{\allowbreak->\allowbreak} -\protected\def\publ_fast_btx_setup_colon_inbetween{\allowbreak :\allowbreak} - -\protected\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} - -\protected\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} - -\protected\def\publ_fast_btx_setup_normal#1% - {\btxsetuptype#1\relax - \ifempty\currentbtxspecificationfallback - \expandafter\publ_fast_setup_nop - \else - \expandafter\publ_fast_setup_yes - \fi} - -\protected\def\publ_fast_btx_setup_visual#1#2#3% - {\btxsetuptype#1\relax - \ifempty\currentbtxspecificationfallback - \expandafter\publ_fast_btx_setup_chain_nop - \else - \expandafter\publ_fast_btx_setup_chain_yes - \fi{#2}{#3}% - \ifempty\currentbtxspecificationfallback - \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 - -\permanent\protected\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 - -\permanent\protected\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 - -\permanent\protected\def\btxstartsubcite#1% - {\begingroup - \btx_reset_cite % todo: limited set - % \saverunningstyleandcolor % let's see when Alan needs it - \def\currentbtxcitealternative{#1}% - \setbtxparameterset\s!cite\currentbtxcitealternative - \usebtxstyleandcolor\c!style\c!color - \btxparameter\c!left - \relax} - -\permanent\protected\def\btxstopsubcite - {\relax - \btxparameter\c!right - \endgroup} - -\permanent\protected\def\btxstartciterendering[#1]% - {\begingroup - \edef\currentbtxcitealternative{#1}% - \setbtxparameterset\s!cite\currentbtxcitealternative - \usebtxstyleandcolor\c!style\c!color - \btxparameter\c!left - \relax} - -\permanent\protected\def\btxstopciterendering - {\relax - \btxparameter\c!right - \endgroup} - -\aliased\let\btxstartciteauthor\begingroup -\aliased\let\btxstopciteauthor \endgroup - -\permanent\protected\def\btxstartcite{\begingroup\btx_reset_cite} -\aliased \let\btxstopcite \endgroup - -%D Whatever helpers: - -\permanent\protected\def\btxsingularplural#1{\clf_btxsingularorplural{\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\protected\def\btxoneorrange #1{\clf_btxoneorrange {\currentbtxdataset}{\currentbtxtag}{#1}} -\permanent\protected\def\btxfirstofrange #1{\clf_btxfirstofrange {\currentbtxdataset}{\currentbtxtag}{#1}} - -\aliased\let\btxsingularorplural\btxsingularplural - -\stopcontextdefinitioncode - -%D Journals - -\permanent\protected\def\btxloadjournallist [#1]{\clf_btxloadjournallist{#1}} -\permanent\protected\def\btxsavejournallist [#1]{\clf_btxsavejournallist{#1}} -\permanent\protected\def\btxaddjournal [#1][#2]{\clf_btxaddjournal{#1}{#2}} -\permanent \def\btxexpandedjournal #1{\clf_btxexpandedjournal{#1}} % \protected ? -\permanent \def\btxabbreviatedjournal#1{\clf_btxabbreviatedjournal{#1}} % \protected ? - -% \installcorenamespace{btxjournal} -% -% \letvalue{\s!btxjournal\v!long }\btxexpandedjournal -% \letvalue{\s!btxjournal\v!short }\btxabbreviatedjournal -% \letvalue{\s!btxjournal\v!normal}\firstofoneargument -% -% \protected\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: - -\tolerant\permanent\protected\def\savebtxdataset[#1]#*[#2]#*[#3] - {\ifarguments - % bad news - \or - \ifhastok={#1}% - \publ_save_dataset_indeed[\s!default][\jobname-saved.bib][#1]% - \else - \publ_save_dataset_indeed[\s!default][#1][]% - \fi - \or - \ifhastok={#2}% - \publ_save_dataset_indeed[\s!default][#1][#2]% - \else - \publ_save_dataset_indeed[#1][#2][]% - \fi - \or - \publ_save_dataset_indeed[#1][#2][#3]% - \fi} - -\protected\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: - -\protected\def\placecitation{\citation[entry]} % [#1] - -\permanent\protected\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] - -\protected\def\publ_registers_set - {\ifempty\currentbtxregister \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 - -\permanent\protected\def\btxindexedauthor#1#2#3#4#5#6% alternative von last initials first junior - {\begingroup - \def\currentbtxcitealternative{#1}% - \ifempty\currentbtxcitealternative - \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} - -\permanent\protected\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 - -\permanent\protected\def\btxstartstyle[#1]% - {\begingroup - \let\savedcurrentbtx\currentbtx - \def\currentbtx{#1}% - \usebtxstyle\c!style - \let\currentbtx\savedcurrentbtx} - -\permanent\protected\def\btxstartcolor[#1]% - {\begingroup - \let\savedcurrentbtx\currentbtx - \def\currentbtx{#1}% - \usebtxcolor\c!color - \let\currentbtx\savedcurrentbtx} - -\permanent\protected\def\btxstartstyleandcolor[#1]% - {\begingroup - \let\savedcurrentbtx\currentbtx - \def\currentbtx{#1}% - \usebtxstyleandcolor\c!style\c!color - \let\currentbtx\savedcurrentbtx} - -\aliased\let\btxstopstyle \endgroup -\aliased\let\btxstopcolor \endgroup -\aliased\let\btxstopstyleandcolor\endgroup - -\permanent\protected\def\btxusecommand[#1]#2% using #2 permits space after [] - {\namedbtxparameter{#1}\c!command{#2}} - -\permanent\protected\def\startbtxrunningstyleandcolor - {\dontleavehmode - \begingroup - \restorerunningstyleandcolor} - -\permanent\protected\def\stopbtxrunningstyleandcolor - {\endgroup} - -%D Maybe handy: - -\permanent\protected\def\btxdoifelsematches#1#2#3% - {\clf_btxdoifelsematches{#1}{#2}{#3}} - -%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={\removepunctuation;\space}, - \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!range=\directdiscretionary\endash, - \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 - -\permanent\protected\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] - -%D Delayed loading: - -\fetchruntimecommand \showbtxdatasetfields \f!publ_tra -\fetchruntimecommand \showbtxdatasetcompleteness \f!publ_tra -\fetchruntimecommand \showbtxdatasetauthors \f!publ_tra -\fetchruntimecommand \showbtxhashedauthors \f!publ_tra -\fetchruntimecommand \showbtxfields \f!publ_tra -\fetchruntimecommand \showbtxtables \f!publ_tra - -%D Some potential crap: -%D -%D Because I consider this bad data management and a weird mix of languages only one -%D accessor is provided. - -\permanent\tolerant\protected\def\btxshortcut[#1]#:#2% - {\clf_btxshortcut{\ifparameter#1\or#1\else\s!default\fi}{#2}} - -\protect diff --git a/tex/context/base/mkiv/publ-tra.mkxl b/tex/context/base/mkiv/publ-tra.mkxl deleted file mode 100644 index ccad4c22a..000000000 --- a/tex/context/base/mkiv/publ-tra.mkxl +++ /dev/null @@ -1,84 +0,0 @@ -%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}{} - -\unprotect - -\permanent\protected\gdef\showbtxdatasetfields {\publ_show_dataset_whatever{showbtxdatasetfields}} -\permanent\protected\gdef\showbtxdatasetcompleteness{\publ_show_dataset_whatever{showbtxdatasetcompleteness}} -\permanent\protected\gdef\showbtxdatasetauthors {\publ_show_dataset_whatever{showbtxdatasetauthors}} - -\tolerant\gdef\publ_show_dataset_whatever#1[#2]% - {\begingroup - \letdummyparameter\c!specification\currentbtxspecification - \setdummyparameter\c!dataset {\currentbtxdataset}% - \letdummyparameter\c!field \empty - \ifparameter#2\or - \ifhastok={#2}% - \getdummyparameters[#2]% - \else - \setdummyparameter\c!dataset{#2}% - \fi - \fi - \ctxcommand{#1{ - dataset = "\dummyparameter\c!dataset", - specification = "\dummyparameter\c!specification", - field = "\dummyparameter\c!field", - }}% - \endgroup} - -\permanent\tolerant\protected\gdef\showbtxfields[#1]% - {\begingroup - \setdummyparameter\c!rotation{90}% - \ifparameter#1\or - \ifhastok={#1}% - \letdummyparameter\c!specification\currentbtxspecification - \getdummyparameters[#1]% - \else - \setdummyparameter\c!specification{#1}% - \fi - \else - \letdummyparameter\c!specification\currentbtxspecification - \fi - \ctxcommand{showbtxfields{ - rotation = "\dummyparameter\c!rotation", - specification = "\dummyparameter\c!specification" - }}% - \endgroup} - -\permanent\tolerant\protected\gdef\showbtxtables[#1]% - {\begingroup - \ctxcommand{showbtxtables{}}% - \endgroup} - -\permanent\tolerant\protected\gdef\showbtxhashedauthors[#1]% - {\ctxcommand{showbtxhashedauthors{}}} - -\protect - -\continueifinputfile{publ-tra.mkiv} - -\starttext - - \showbtxfields[rotation=85] \page - \showbtxfields[rotation=90] \page - - \showbtxtables \page - -\stoptext diff --git a/tex/context/base/mkiv/publ-xml.mkxl b/tex/context/base/mkiv/publ-xml.mkxl deleted file mode 100644 index 925ccff1a..000000000 --- a/tex/context/base/mkiv/publ-xml.mkxl +++ /dev/null @@ -1,111 +0,0 @@ -%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 - -\permanent\tolerant\protected\def\convertbtxdatasettoxml[#1]% - {\clf_convertbtxdatasettoxml{\ifparameter\or#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/tex/context/base/mkiv/regi-ini.mkxl b/tex/context/base/mkiv/regi-ini.mkxl deleted file mode 100644 index 31e8b4717..000000000 --- a/tex/context/base/mkiv/regi-ini.mkxl +++ /dev/null @@ -1,37 +0,0 @@ -%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}{} - -\unprotect - -%D \macros -%D {enableregime,disableregime, -%D startregime,stopregime, -%D currentregime} -%D -%D Beware, the enable and disable commands are global switches, so best use the -%D start|/|stop commands. - -\let\currentregime\empty - -\permanent\protected\def\enableregime[#1]{\clf_enableregime{#1}} -\permanent\protected\def\disableregime {\clf_disableregime} -\permanent\protected\def\startregime [#1]{\clf_startregime{#1}} -\permanent\protected\def\stopregime {\clf_stopregime} - -% only for diagnostics: - -% \def\codepagename#1{\cldcontext{os.tocodepage("#1")}} - -\protect \endinput diff --git a/tex/context/base/mkiv/scrn-ini.mklx b/tex/context/base/mkiv/scrn-ini.mklx deleted file mode 100644 index 40b099cfc..000000000 --- a/tex/context/base/mkiv/scrn-ini.mklx +++ /dev/null @@ -1,254 +0,0 @@ -%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}{} - -%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 - \orelse\ifx\currentinteraction\previousinteraction - \checkinteractionstate - \fi -\to \everysetupinteraction - -\protected\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} - -\aliased\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 -% interactions so 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 -% -% \protected\def\scrn_interaction_direct#1% -% {\edef\currentinteraction{#1}} -% -% \protected\def\scrn_interaction_start#1% -% {\pushmacro\currentinteraction -% \edef\currentinteraction{#1}} -% -% \protected\def\scrn_interaction_stop -% {\popmacro\currentinteraction} -% -% \protected\def\setinteraction[#1]% -% {\def\currentinteraction{#1}} -% -% \defineinteraction[\v!interaction] - -\permanent\protected\def\startinteraction[#1]% - {\pushmacro\currentinteraction - \edef\currentinteraction{#1}} - -\permanent\protected\def\stopinteraction - {\popmacro\currentinteraction} - -\permanent\protected\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. - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\setlocationcolor {\setlocationcolorspecified \referencepagestate} -\permanent\protected\def\setlocationattributes{\setlocationattributesspecified\referencepagestate} -\permanent\protected\def\setlocationcolorspec {\setlocationcolorspecspecified \referencepagestate} - -\permanent\protected\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} - -\newconditional\c_scrn_identity_preroll - -\installtexdirective - {interaction.identity.preroll} - {\settrue \c_scrn_identity_preroll} - {\setfalse\c_scrn_identity_preroll} - -\def\scrn_identity_prerolled#1% - {\begingroup - \edef\tempstring{\interactionparameter#1}% - \ifx\tempstring\empty - \endgroup - \else - \the\everypreroll - \nodestostring\tempstring{\tempstring}% - \normalexpanded{\endgroup\setexpandedinteractionparameter{#1}{\tempstring}}% - \fi} - -\def\scrn_identity_synchronize - {\begingroup - \ifconditional\c_scrn_identity_preroll - \scrn_identity_prerolled\c!title - \scrn_identity_prerolled\c!subtitle - \scrn_identity_prerolled\c!author - \scrn_identity_prerolled\c!date - \scrn_identity_prerolled\c!keyword - \fi - \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 - \endgroup} - -\appendtoks - \scrn_identity_synchronize -\to \everysetupinteraction - -% this comes before starttext - -\def\scrn_identity_document#1#2% - {\doifdocumentvariable{metadata:#1}{\setupinteraction[#2=\documentvariable{metadata:#1}]}} - -\appendtoks % not interfaced i.e. english - \scrn_identity_document {title}\c!title - \scrn_identity_document {subject}\c!subtitle - \scrn_identity_document{subtitle}\c!subtitle - \scrn_identity_document {author}\c!author - \scrn_identity_document {authors}\c!author - \scrn_identity_document {keyword}\c!keyword - \scrn_identity_document{keywords}\c!keyword - \scrn_identity_document {date}\c!date -\to \everystartdocument % or stop - -\setupinteraction - [\c!title=, - \c!subtitle=, - \c!author=, - \c!keyword=, - \c!date=] - -\protect \endinput diff --git a/tex/context/base/mkiv/scrn-pag.mklx b/tex/context/base/mkiv/scrn-pag.mklx deleted file mode 100644 index ef3923f56..000000000 --- a/tex/context/base/mkiv/scrn-pag.mklx +++ /dev/null @@ -1,310 +0,0 @@ -%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}{} - -\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 - \orelse\ifx\currentinteractionscreenwidth\v!fit - \donefalse - \global\canvaswidth\dimexpr - \leftcombitotal - + \makeupwidth - + \rightcombitotal - + 2\dimexpr - \interactionscreenparameter\c!backspace - + \interactionscreenparameter\c!horoffset - \relax - \relax - \orelse\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 - \ifx\currentinteractionscreenheight\v!max - \global\canvasheight\printpaperheight - \orelse\ifx\currentinteractionscreenheight\v!fit - \donefalse - \global\canvasheight\dimexpr - \topheight - + \topdistance - + \makeupheight - + \bottomdistance - + \bottomheight - + 2\dimexpr - \interactionscreenparameter\c!topspace - + \interactionscreenparameter\c!veroffset - \relax - \relax - \orelse\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 - \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 - \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed -\to \everysetuplayout - -\appendtoks - \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed -\to \everysetuplayouttarget - -\def\scrn_canvas_synchronize_only - {\clf_setupcanvas - paperwidth \printpaperwidth - paperheight \printpaperheight - \relax} - -\def\scrn_canvas_synchronize_set#width#height% - {\clf_setupcanvas - paperwidth \dimexpr#width\relax - paperheight \dimexpr#height\relax - \relax} - -\let\scrn_canvas_synchronize_reset\scrn_canvas_synchronize_only - -\def\scrn_canvas_synchronize_simple_indeed - {\scrn_canvas_synchronize_only - %\glet\scrn_canvas_synchronize_simple \relax - \glet\scrn_canvas_synchronize_complex\relax} - -\def\scrn_canvas_synchronize_complex_indeed - {\scrn_canvas_calculate % otherwise we need to hook it into setuppage etc - \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 - copies \numexpr\interactionscreenparameter\c!copies\relax - print {\interactionscreenparameter\c!print}% - \relax - %\glet\scrn_canvas_synchronize_simple \relax - \glet\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 - \orelse\ifx\p_option\v!fit - \global\settrue \c_scrn_canvas_tight_page - \else - \global\setfalse\c_scrn_canvas_tight_page - \fi - \endgroup -\to \everysetupinteractionscreen - -\setupinteractionscreen - [\c!width=\printpaperwidth, - \c!height=\printpaperheight, - \c!horoffset=\zeropoint, - \c!veroffset=\zeropoint, - \c!backspace=\backspace, - \c!topspace=\topspace, - \c!copies=\plusone, % not the best place but backend anyway - \c!option=\v!auto] - -\appendtoks - \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed -\to \everysetupinteractionscreen - -%D Conditional page breaks: - -\permanent\tolerant\protected\def\screen[#list]% - {\iflocation - \page[#list]% - \fi} - -%D Page transitions: - -\let\scrn_transitions_list\empty - -\permanent\tolerant\protected\def\setuppagetransitions[#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/tex/context/base/mkiv/scrp-ini.mkiv b/tex/context/base/mkiv/scrp-ini.mkiv index ab934fe3b..4eb3f29e3 100644 --- a/tex/context/base/mkiv/scrp-ini.mkiv +++ b/tex/context/base/mkiv/scrp-ini.mkiv @@ -42,9 +42,7 @@ \registerctxluafile{scrp-tha}{} \registerctxluafile{scrp-tib}{} -\ifcase \contextlmtxmode - \definesystemattribute[script][public,pickup] -\fi +\definesystemattribute[script][public,pickup] %D Since scripts need specific \LUA\ code we use hard coded attribute values, but we %D might have more tricks at some time, so we use a proper define macro too. diff --git a/tex/context/base/mkiv/spac-ali.mkxl b/tex/context/base/mkiv/spac-ali.mkxl deleted file mode 100644 index 5cb494682..000000000 --- a/tex/context/base/mkiv/spac-ali.mkxl +++ /dev/null @@ -1,1243 +0,0 @@ -%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 {flush*} -%D variants. Starting at the last day of 2011 both methods are merged into one and -%D caching has been added, which makes switching twice as fast. - -\registerctxluafile{spac-ali}{optimize} - -\definesystemattribute[realign] [public] % might be combined with the next one -\definesystemattribute[alignstate][public] % will make a single attributes for several states - -\appendtoks - \c_attr_realign \attributeunsetvalue - \c_attr_alignstate\attributeunsetvalue -\to \everyforgetall - -\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue} -\permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo} -\permanent\protected\def\signalouterrealign{\clf_setrealign\plusone} - -\installcorenamespace{aligncommand} -\installcorenamespace{alignhorizontal} -\installcorenamespace{alignvertical} - -% \installcorenamespace{alignmentnormalcache} -% \installcorenamespace{alignmentraggedcache} - -% nasty hack: - -\installcorenamespace{alignmentnormalcacheodd} -\installcorenamespace{alignmentnormalcacheeven} - -\installcorenamespace{alignmentraggedcacheodd} -\installcorenamespace{alignmentraggedcacheeven} - -\immutable\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi} -\immutable\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi} - -\newtoks\everyresetalign % todo - -% This will become a more advanced layout controller soon: - -\newconditional\layoutlefttoright \settrue\layoutlefttoright -\newconditional\displaylefttoright \settrue\displaylefttoright -\newconditional\inlinelefttoright \settrue\inlinelefttoright - -\permanent\protected\def\lefttoright - {\ifvmode - \spac_directions_lefttoright_vmode - \else - \spac_directions_lefttoright_hmode - \fi} - -\permanent\protected\def\righttoleft - {\ifvmode - \spac_directions_righttoleft_vmode - \else - \spac_directions_righttoleft_hmode - \fi} - -\protected\def\spac_directions_lefttoright_vmode - {\settrue\displaylefttoright - \settrue\inlinelefttoright - \textdirection\directionlefttoright - \pardirection \directionlefttoright} - -\protected\def\spac_directions_righttoleft_vmode - {\setfalse\displaylefttoright - \setfalse\inlinelefttoright - \textdirection\directionrighttoleft - \pardirection \directionrighttoleft} - -\protected\def\spac_directions_lefttoright_hmode - {\linedirection\directionlefttoright % linedir keeps subtype of skip - \settrue\inlinelefttoright} - -\protected\def\spac_directions_righttoleft_hmode - {\linedirection\directionrighttoleft % linedir keeps subtype of skip - \setfalse\inlinelefttoright} - -\permanent\protected\def\synchronizelayoutdirection - {\ifconditional\layoutlefttoright - \spac_directions_synchronize_lr - \else - \spac_directions_synchronize_rl - \fi} - -\permanent\protected\def\synchronizedisplaydirection - {\ifconditional\displaylefttoright - \spac_directions_synchronize_lr - \else - \spac_directions_synchronize_rl - \fi} - -\def\spac_directions_synchronize_lr - {\settrue\inlinelefttoright - \textdirection\directionlefttoright - \pardirection \directionlefttoright} - -\def\spac_directions_synchronize_rl - {\setfalse\inlinelefttoright - \textdirection\directionrighttoleft - \pardirection \directionrighttoleft} - -\permanent\protected\def\synchronizeinlinedirection - {% why not \linedirection here - \textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi} - -\permanent\protected\def\checkedlefttoright - {\ifvmode - \spac_directions_lefttoright_vmode - \else - \spac_directions_lefttoright_hmode_checked - \fi} - -\permanent\protected\def\checkedrighttoleft - {\ifvmode - \spac_directions_righttoleft_vmode - \else - \spac_directions_righttoleft_hmode_checked - \fi} - -\protected\def\spac_directions_lefttoright_hmode_checked - {\ifconditional\inlinelefttoright\else - \lefttoright - \fi} - -\protected\def\spac_directions_righttoleft_hmode_checked - {\ifconditional\inlinelefttoright - \righttoleft - \fi} - -\installcorenamespace{bidi} - -\letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright -\letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft - -\permanent\protected\def\usebidiparameter#1% - {\begincsname\??bidi#1\c!bidi\endcsname} - -\permanent\protected\def\showdirections - {\dontleavehmode - \begingroup\infofont\textdirection\directionlefttoright[\space - layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space - display: \ifconditional\displaylefttoright l2r\else r2l\fi\space - inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space - ]\endgroup} - -\permanent\protected\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox -\permanent\protected\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox -\permanent\protected\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox -\permanent\protected\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox -\permanent\protected\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop -\permanent\protected\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop - -\permanent\protected\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next} -\permanent\protected\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox -\permanent\protected\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop - -\permanent\protected\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi} -\permanent\protected\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi} -\permanent\protected\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi} - -% Tolerance and hyphenation - -\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{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi} - -\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered - {\ifnum\tolerance<\c_spac_tolerance_minimum - \tolerance\c_spac_tolerance_minimum % small values have unwanted side effects - \else - % 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 - %\else - % no need to do something as we're in \nohyphens - \fi} - -\protected\def\spac_align_set_tolerant - {\tolerance\c_spac_tolerance_normal} - -\protected\def\spac_align_set_very_tolerant - {\tolerance\c_spac_tolerance_extreme} - -\protected\def\spac_align_set_stretch - {\emergencystretch\bodyfontsize} - -\protected\def\spac_align_set_extreme_stretch - {\emergencystretch10\bodyfontsize} - -% Vertical - -\newconstant\c_spac_align_state_vertical - -\protected\def\spac_align_set_vertical_none - {\enforced\let\raggedtopcommand \relax - \enforced\let\raggedbottomcommand\relax} - -\protected\def\spac_align_set_vertical_lohi - {\enforced\let\raggedtopcommand \vfilll - \enforced\let\raggedbottomcommand\vfilll} - -\protected\def\spac_align_set_vertical_low - {\enforced\let\raggedtopcommand \vfilll - \enforced\let\raggedbottomcommand\relax} - -\protected\def\spac_align_set_vertical_high - {\enforced\let\raggedtopcommand \relax - \enforced\let\raggedbottomcommand\vfilll} - -\def\spac_align_flush_vertical - {\ifcase\c_spac_align_state_vertical - \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_hard {\plusone fill} -\def\v_spac_align_fill_amount_extreme {\plustenthousand filll} -\def\v_spac_align_fill_amount_negative {\minusone fil} -\def\v_spac_align_fill_amount_double {\plustwo fil} -\def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key -\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 - -\permanent\protected\def\spac_align_set_horizontal_none % should also relax \updateraggedskips - {\raggedstatus \zerocount - \c_attr_alignstate\attributeunsetvalue - \leftskip \plusone\leftskip - \rightskip \plusone\rightskip - \spaceskip \zeropoint - \xspaceskip \zeropoint - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_one_fil % new - \setfalse \raggedonelinerstate % now here - \let\updateraggedskips\relax} % no need for adaption - -\permanent\protected\def\spac_align_set_horizontal_left - {\setraggedness \spac_align_set_raggedness_left - \raggedstatus \plusone - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_center - {\setraggedness \spac_align_set_raggedness_middle - \raggedstatus \plustwo - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_right - {\setraggedness \spac_align_set_raggedness_right - \raggedstatus \plusthree - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_one_fil - %\parindent \parindent - \relax} - -\permanent\protected\def\spac_align_set_horizontal_very_left - {\raggedstatus \plusone - \c_attr_alignstate\plusone - \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount - \rightskip \plusone\rightskip\s!plus\zeropoint - \spaceskip \v_spac_align_space_amount - \xspaceskip \v_spac_align_space_amount_x - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_very_center - {\raggedstatus \plustwo - \c_attr_alignstate\plustwo - \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount - \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount - \spaceskip \v_spac_align_space_amount - \xspaceskip \v_spac_align_space_amount_x - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_very_right - {\raggedstatus \plusthree - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - %\parindent \parindent - \relax} - -\permanent\protected\def\spac_align_set_horizontal_wide_center - {\setraggedness \spac_align_set_raggedness_middle - \raggedstatus \plustwo - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_centered_last_line - {\raggedstatus \zerocount - \c_attr_alignstate\attributeunsetvalue - \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax - \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax - \spaceskip \zeropoint\relax - \xspaceskip \zeropoint\relax - \parfillleftskip \zeropoint - \parfillskip \zeropoint\s!plus\v_spac_align_fill_amount_double\relax - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_flushedright_last_line - {\raggedstatus \zerocount - \c_attr_alignstate\attributeunsetvalue - \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax - \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax - \spaceskip \zeropoint\relax - \xspaceskip \zeropoint\relax - \parfillskip \zeropoint - \parfillleftskip \zeropoint\s!plus\v_spac_align_fill_amount_extreme\relax - \parindent \zeropoint - \relax} - -\permanent\protected\def\spac_align_set_horizontal_right_tt % a plain command - {\tttf % brrr - \raggedstatus \plusthree - \c_attr_alignstate\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 - \parfillleftskip \zeropoint - \parfillskip \s_zero_plus_zero - %\parindent \parindent - \relax} - -\permanent\protected\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 - % 8 right aligned last line - \spac_align_set_horizontal_flushedright_last_line - \or - % 9 paragraph - \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 - -\permanent\protected\def\raggedbottom - {\bottomraggednessmode\zerocount - \settopskip} - -\permanent\protected\def\alignbottom - {\bottomraggednessmode\plusone - \settopskip} - -\permanent\protected\def\baselinebottom - {\bottomraggednessmode\plustwo - \settopskip} - -\aliased\let\normalbottom\alignbottom % downward compatible - -\permanent\protected\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 - {\enforced\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\letcsname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand - \global\letcsname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips} - -\def\spac_align_collect#1% - {\csname\??aligncommand#1\endcsname} - -% The local (key driven) setter: - -\permanent\protected\def\spac_align_prepare#1% deferred - {\edef\m_spac_align_asked{#1}% - \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname - \ifx\raggedcommand\relax - \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: - -\permanent\tolerant\protected\def\setupalign[#1]% immediate - {\edef\m_spac_align_asked{#1}% - \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname - \ifx\raggedcommand\relax - \spac_align_add_to_cache - \else - \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align_asked\endcsname - \fi - \raggedcommand} - -\permanent\protected\def\usealignparameter#1% faster local variant - {\edef\m_spac_align_asked{#1\c!align}% - \ifx\m_spac_align_asked\empty\else - \spac_align_use_indeed - \fi} - -\permanent\protected\def\dousealignparameter#1% faster local variant - {\edef\m_spac_align_asked{#1}% - \ifx\m_spac_align_asked\empty\else - \spac_align_use_indeed - \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 - -\protected\def\spac_align_use_later#1% - {\begingroup - \edef\m_spac_align_asked{#1}% - \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname - \ifx\raggedcommand\relax - \spac_align_add_to_cache - \fi - \endgroup} - -\protected\def\spac_align_use_now#1% - {\csname\??alignmentnormalcache#1\endcsname} - -% Maybe we need something different in columns. - -\protected\def\installalign#1#2% beware: commands must be unexpandable! - {\ifcsname\??aligncommand#1\endcsname \else - \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}% - \fi} - -% 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 -% -% \protected\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\plusfour } -\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfive } -\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!end }{\c_spac_align_state_horizontal\pluseight} -\setvalue{\??aligncommand\v!paragraph }{\c_spac_align_state_horizontal\plusnine} - -\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!hangingboth }{\toksapp\t_spac_align_collected{\font_protruding_enable_b}} -\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{\??aligncommand1*\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} - -% a one shot (only usefull in e.g. framed, also needs tolerance and stretch) - -\setvalue{\??aligncommand \v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} -\setvalue{\??aligncommand1*\v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} -\setvalue{\??aligncommand2*\v!more}{\toksapp\t_spac_align_collected{\looseness\plustwo}} - -% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\nopenalties}} -% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\setdefaultpenalties}} - -\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} - -\protected\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 - -\permanent\protected\def\enablereversealignment - {\the\t_spac_every_swap_align - \t_spac_every_swap_align\emptytoks} - -% Visible commands: - -\aliased\let\notragged \spac_align_set_horizontal_none -\aliased\let\raggedleft \spac_align_set_horizontal_left -\aliased\let\raggedcenter \spac_align_set_horizontal_center -\aliased\let\raggedright \spac_align_set_horizontal_right -\aliased\let\veryraggedleft \spac_align_set_horizontal_very_left -\aliased\let\veryraggedcenter \spac_align_set_horizontal_very_center -\aliased\let\veryraggedright \spac_align_set_horizontal_very_right -\aliased\let\raggedwidecenter \spac_align_set_horizontal_wide_center -\aliased\let\centeredlastline \spac_align_set_horizontal_centered_last_line -\aliased\let\flushedrightlastline\spac_align_set_horizontal_flushedright_last_line -\aliased\let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command -\aliased\let\forgetragged \spac_align_set_horizontal_none - -\appendtoks - \spac_align_set_horizontal_none -\to \everyforgetall - -% Box commands. - -\permanent\protected\def\ibox - {\vbox\bgroup - \forgetall - \enforced\let\\\endgraf - \ifdoublesided\signalinnerrealign\fi - \doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left - \let\next} - -\permanent\protected\def\obox - {\vbox\bgroup - \forgetall - \enforced\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) - {\enforced\let\raggedbox\vbox - \processcommacommand[#1]\spac_align_set_ragged_vbox} - -\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used) - {\enforced\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} - -\permanent\protected\def\spac_align_vertical_left {\lbox} -\permanent\protected\def\spac_align_vertical_right {\rbox} -\permanent\protected\def\spac_align_vertical_middle {\cbox} -\permanent\protected\def\spac_align_vertical_inner {\ibox} -\permanent\protected\def\spac_align_vertical_outer {\obox} -\permanent\protected\def\spac_align_vertical_flushleft {\rbox} -\permanent\protected\def\spac_align_vertical_flushright{\lbox} -\permanent\protected\def\spac_align_vertical_center {\cbox} -\permanent\protected\def\spac_align_vertical_no {\vbox\bgroup\spac_align_set_horizontal_right\let\next=} - -\permanent\protected\def\spac_align_horizontal_left {\doalignedline\v!left} -\permanent\protected\def\spac_align_horizontal_right {\doalignedline\v!right} -\permanent\protected\def\spac_align_horizontal_middle {\doalignedline\v!middle} -\permanent\protected\def\spac_align_horizontal_inner {\doalignedline\v!inner} -\permanent\protected\def\spac_align_horizontal_outer {\doalignedline\v!outer} -\permanent\protected\def\spac_align_horizontal_flushleft {\doalignedline\v!right} -\permanent\protected\def\spac_align_horizontal_flushright{\doalignedline\v!left} -\permanent\protected\def\spac_align_horizontal_center {\doalignedline\v!middle} - -\setvalue{\??alignvertical \v!left }{\enforced\let\raggedbox\spac_align_vertical_left} -\setvalue{\??alignvertical \v!right }{\enforced\let\raggedbox\spac_align_vertical_right} -\setvalue{\??alignvertical \v!middle }{\enforced\let\raggedbox\spac_align_vertical_middle} -\setvalue{\??alignvertical \v!inner }{\enforced\let\raggedbox\spac_align_vertical_inner} -\setvalue{\??alignvertical \v!outer }{\enforced\let\raggedbox\spac_align_vertical_outer} -\setvalue{\??alignvertical \v!flushleft }{\enforced\let\raggedbox\spac_align_vertical_flushleft } -\setvalue{\??alignvertical \v!flushright}{\enforced\let\raggedbox\spac_align_vertical_flushright} -\setvalue{\??alignvertical \v!center }{\enforced\let\raggedbox\spac_align_vertical_center} -\setvalue{\??alignvertical \v!no }{\enforced\let\raggedbox\spac_align_vertical_no} - -\setvalue{\??alignhorizontal\v!left }{\enforced\let\raggedbox\spac_align_horizontal_left} -\setvalue{\??alignhorizontal\v!right }{\enforced\let\raggedbox\spac_align_horizontal_right} -\setvalue{\??alignhorizontal\v!middle }{\enforced\let\raggedbox\spac_align_horizontal_middle} -\setvalue{\??alignhorizontal\v!inner }{\enforced\let\raggedbox\spac_align_horizontal_inner} -\setvalue{\??alignhorizontal\v!outer }{\enforced\let\raggedbox\spac_align_horizontal_outer} -\setvalue{\??alignhorizontal\v!flushleft }{\enforced\let\raggedbox\spac_align_horizontal_flushleft} -\setvalue{\??alignhorizontal\v!flushright}{\enforced\let\raggedbox\spac_align_horizontal_flushright} -\setvalue{\??alignhorizontal\v!center }{\enforced\let\raggedbox\spac_align_horizontal_center} - -% The next one can be in use so we keep it around but oen should -% be aware of possible interference. - -\permanent\protected\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall) - {\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% - \updateraggedskips} - -\permanent\def\dosetraggedskips#1#2#3#4#5#6#7% - {\raggedstatus #1\relax - \leftskip 1\leftskip \s!plus#2\relax - \rightskip 1\rightskip\s!plus#3\relax - \spaceskip #4\relax - \xspaceskip #5\relax - \parfillskip \zeropoint\s!plus#6\relax - \parindent #7\relax - \c_attr_alignstate\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi} - -% older (context) names: - -\aliased\let\spaceamount \interwordspace -\aliased\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} - -\permanent\protected\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 \automatichyphenpenalty \explicithyphenpenalty - \displaywidowpenalty \widowpenalty \clubpenalty \brokenpenalty - \doublehyphendemerits \finalhyphendemerits \adjdemerits - \relax}% - \dontleavehmode - \begingroup - \inleftmargin{\vsmash{\infofont\framed[\c!align=\v!right]{\thepardata}}}% - \endgroup - \let\showpardata\relax} - -\permanent\protected\def\startshowpardata - {\begingroup - \showstruts - \tracingparagraphs\maxdimen - \appendtoksonce\showpardata\to\everypar} - -\permanent\protected\def\stopshowpardata - {\endgraf - \endgroup} - -% Structure: - -\protected\def\startalignment - {\par - \begingroup - \setupalign} - -\protected\def\stopalignment - {\par - \endgroup} - -\setnewconstant\alignstrutmode\plusone - -% see later for the real definition, which in the simple case is: - -\newtoks \everyleftofalignedline -\newtoks \everyrightofalignedline - -\permanent\protected\def\shiftalignedline#1#2#3#4% left, right, inner, outer - {\rightorleftpageaction - {\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}% - \everyrightofalignedline{\hskip\dimexpr#2+#4\relax}} - {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}% - \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}} - -\permanent\def\doalignline#1#2% \\ == newline - {\noindentation % was \noindent - \dontleavehmode % added in marrakesch at TUG 2006\begingroup - \begingroup - \setlocalhsize % new - \enforced\permanent\protected\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 \permanent\def\line {\hbox to\hsize} \fi -\ifdefined\leftline \else \permanent\def\leftline #1{\line{#1\hss}} \fi -\ifdefined\rightline \else \permanent\def\rightline #1{\line{\hss#1}} \fi -\ifdefined\centerline \else \permanent\def\centerline#1{\line{\hss#1\hss}} \fi - -% direct commands - -\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% - {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi} - -\permanent\tolerant\protected\def\startlinealignment[#1]% - {\spac_align_wrapper_handle{#1}% - \bgroup\ignorespaces} - -\protected\def\spac_align_wrapper_stop - {\removeunwantedspaces\egroup} - -\permanent\let\stoplinealignment\spac_align_wrapper_stop - -\permanent\protected\def\startleftaligned {\startlinealignment[\v!left ]} \permanent\let\stopleftaligned \spac_align_wrapper_stop -\permanent\protected\def\startmiddlealigned{\startlinealignment[\v!middle]} \permanent\let\stopmiddlealigned\spac_align_wrapper_stop -\permanent\protected\def\startrightaligned {\startlinealignment[\v!right ]} \permanent\let\stoprightaligned \spac_align_wrapper_stop -\permanent\protected\def\startmaxaligned {\startlinealignment[\v!max ]} \permanent\let\stopmaxaligned \spac_align_wrapper_stop - -\aliased\let\startmidaligned \startmiddlealigned \aliased\let\stopmidaligned \stopmiddlealigned -\aliased\let\startcenteraligned\startmiddlealigned \aliased\let\stopcenteraligned\stopmiddlealigned - -\permanent\protected\def\leftaligned {\spac_align_wrapper_handle\v!left } -\permanent\protected\def\middlealigned{\spac_align_wrapper_handle\v!middle} -\permanent\protected\def\rightaligned {\spac_align_wrapper_handle\v!right } -\permanent\protected\def\maxaligned {\spac_align_wrapper_handle\v!max } - -\aliased\let\midaligned \middlealigned -\aliased\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 - -% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname} - -%D Experimental (will be redone when floats are redone as it's real messy -%D now). It can also be made faster (if needed). - -\permanent\protected\def\doxalignline#1#2#3#4#5#6% - {\noindentation % was \noindent - \dontleavehmode % added in marrakesch at TUG 2006\begingroup - \begingroup - \setlocalhsize - \enforced\permanent\protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient - \dowithnextbox - {\hbox to \localhsize - {#1\hskip\ifdone#2\else#3\fi#4% - \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} - -\permanent\protected\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 } - -\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ? - -\permanent\protected\def\alignedline#1#2% setting default - {\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 - -%D We need to pick up a box (downward compatible in case \type {\bgroup} -%D is used (test suite index example). - -\permanent\tolerant\protected\def\wordright[#1]% - {\dowithnextbox - {\normalexpanded{\spac_word_right_indeed{#1}{\hpack{\thebox\nextbox}}}} - \hbox} - -\protected\def\spac_word_right_indeed#1#2% - {\registerparwrapper - {\v!word:\v!right} - {\begingroup - \frozen\parfillskip \zeropoint - \frozen\finalhyphendemerits\zerocount - \endgroup} - {\doifelseparwrapper{\v!word:\v!right}% - {\doifelse{#1}\v!right{\kern-\rightskip}{\doifsomething{#1}{\kern-#1}}% - \strut \removeunwantedspaces - \hfill - \allowbreak % changed back from \hskip\zeropoint - \quad}% - {\allowbreak % changed back from \hskip\zeropoint - \break}% - \unregisterparwrapper{\v!word:\v!right}% - \strut - \hfill - \nobreak - #2% - \allowbreak}} - -% \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. - -% v\protected\def\bottomword -% {\par -% \dowithnextbox -% {\leaders\box\nextbox\vfil\page} -% \vbox to \lineheight} -% -% \permanent\protected\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 - -\protected\def\spac_align_simple_left #1{{#1\hss}} -\protected\def\spac_align_simple_right #1{{\hss#1}} -\protected\def\spac_align_simple_middle#1{{\hss#1\hss}} - -\letvalue{\??alignsimple \v!right }\spac_align_simple_left -\letvalue{\??alignsimple \v!outer }\spac_align_simple_left % not managed! see linenumbers -\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 - -\permanent\protected\def\simplealignedbox#1#2% - {\hbox \ifdim#1>\zeropoint to #1 - \ifcsname\??alignsimple#2\endcsname - \doubleexpandafter\lastnamedcs - \else - \doubleexpandafter\spac_align_simple_left - \fi - \fi} - -\permanent\protected\def\simplealignedspreadbox#1#2% - {\hbox \ifdim#1>\zeropoint spread #1 - \ifcsname\??alignsimple#2\endcsname - \doubleexpandafter\lastnamedcs - \else - \doubleexpandafter\spac_align_simple_left - \fi - \fi} - -\permanent\protected\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 - -\permanent\protected\def\simplereversealignedbox#1#2% - {\hbox \ifdim#1>\zeropoint to #1 - \ifcsname\??alignsimplereverse#2\endcsname - \doubleexpandafter\lastnamedcs - \else - \doubleexpandafter\spac_align_simple_left - \fi - \fi} - -\permanent\protected\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} -% -% \protected\def\spac_align_set_ss#1% -% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname} - -% Some obsolete (old) helpers: - -\permanent\tolerant\protected\def\definehbox[#1][#2]% - {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi} - -%D Some direction related helpers: - -\installcorenamespace {reverse} - -\setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi} -\setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi} - -\permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname} - -%D Now official: - -\permanent\protected\def\spaceorpar - {\endgraf\ifhmode\space\fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua index 899d274b4..ac90926e1 100644 --- a/tex/context/base/mkiv/spac-chr.lua +++ b/tex/context/base/mkiv/spac-chr.lua @@ -129,7 +129,8 @@ end local function nbsp(head,current) local para = fontparameters[getfont(current)] - if getattr(current,a_alignstate) == 1 then -- flushright + local attr = getattr(current,a_alignstate) or 0 + if attr >= 1 or attr <= 3 then -- flushright head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0) else head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink) diff --git a/tex/context/base/mkiv/spac-chr.mkxl b/tex/context/base/mkiv/spac-chr.mkxl deleted file mode 100644 index 8d7bba42e..000000000 --- a/tex/context/base/mkiv/spac-chr.mkxl +++ /dev/null @@ -1,103 +0,0 @@ -%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}{optimize} - -\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\c_attr_characters#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. - -\pushoverloadmode - -%immutable\edef\nobreakspace {\begingroup\setalignstateattribute\normalUchar"00A0\endgroup} % 1 = left -\immutable\edef\nobreakspace {\normalUchar"00A0} % space -\immutable\edef\softhyphen {\normalUchar"00AD} % softhyohen -\immutable\edef\enquad {\normalUchar"2000} % quad/2 -\immutable\edef\emquad {\normalUchar"2001} % quad -\immutable\edef\twoperemspace {\normalUchar"2002} % quad/2 -% % "2003 % quad == \quad == \hskip\emwidth -\immutable\edef\threeperemspace {\normalUchar"2004} % quad/3 -\immutable\edef\fourperemspace {\normalUchar"2005} % quad/4 -%immutable\edef\fiveperemspace {\normalUchar"001E} % quad/5 (bonus) -\immutable\edef\sixperemspace {\normalUchar"2006} % quad/6 -\immutable\edef\figurespace {\normalUchar"2007} % width of zero -\immutable\edef\punctuationspace {\normalUchar"2008} % width of period -\immutable\edef\breakablethinspace {\normalUchar"2009} % quad/8 -\immutable\edef\hairspace {\normalUchar"200A} % quad/8 -\immutable\edef\zerowidthspace {\normalUchar"200B} % 0 -\immutable\edef\zerowidthnonjoiner {\normalUchar"200C} % 0 -\immutable\edef\zerowidthjoiner {\normalUchar"200D} % 0 -\immutable\edef\narrownobreakspace {\normalUchar"202F} % quad/8 -%immutable\edef\mediummathspace {\normalUchar"205F} % space/8 (math) -%immutable\edef\zerowidthnobreakspace{\normalUchar"FEFF} -%immutable\edef\fiveperemspace {\normalUchar"001E} - -\immutable\protected\def\zerowidthnobreakspace{\penalty\plustenthousand\kern\zeropoint} -\immutable\protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} - -\aliased\let\ideographicspace \enquad -\aliased\let\ideographichalffillspace \emquad - -\immutable\let\zwnj \zerowidthnonjoiner -\immutable\let\zwj \zerowidthjoiner -\immutable\let\nbsp \nobreakspace - -\popoverloadmode - -\immutable\chardef\optionalspace"1F % will be space unless before punctuation - -% Shortcuts: - -% unexpanded as otherwise we need to intercept / cleanup a lot - -\protected\def~{\nobreakspace} - -\protect \endinput - diff --git a/tex/context/base/mkiv/spac-grd.mkxl b/tex/context/base/mkiv/spac-grd.mkxl deleted file mode 100644 index fbb02f50c..000000000 --- a/tex/context/base/mkiv/spac-grd.mkxl +++ /dev/null @@ -1,375 +0,0 @@ -%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} - -\permanent\let\poplastnode\relax - -\permanent\protected\def\pushlastnode - {\csname\??lastnodepusher - \ifcsname\??lastnodepusher\the\lastnodetype\endcsname - \the\lastnodetype - \else - \s!unknown - \fi - \endcsname} - -\setvalue{\??lastnodepusher\number\kernnodecode}% - {\enforced\permanent\protected\edef\poplastnode{\kern\the\lastkern\relax}% - \kern-\lastkern} - -\setvalue{\??lastnodepusher\number\gluenodecode}% - {\enforced\permanent\protected\edef\poplastnode{\vskip\the\lastskip\relax}% - \vskip-\lastskip} - -\setvalue{\??lastnodepusher\number\penaltynodecode}% - {\enforced\permanent\protected\edef\poplastnode{\penalty\the\lastpenalty\relax}% - \nobreak} - -\setvalue{\??lastnodepusher\s!unknown}% - {\enforced\permanent\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\hpack{\setstrut\strut}% - \setbox\b_spac_lines_correction_after \hbox {(}% - \d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax - \d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax - \ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi - \ifdim\d_spac_lines_correction_after <\zeropoint\d_spac_lines_correction_after \zeropoint\fi} - -% 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: - -\permanent\protected\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]} -\permanent\protected\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]} - -\permanent\def\showbaselinecorrection - {\enforced\permanent\protected\def\dobaselinecorrection % visualization is not watertight! - {\bgroup - \ifdim\prevdepth>\zeropoint - \kern-\prevdepth - \fi - \setbox\scratchbox\emptyhbox - \wd\scratchbox\hsize - \dp\scratchbox\strutdp - \nointerlineskip - \forgetall - \ruledvpack{\box\scratchbox}% - \egroup - \prevdepth\strutdp}% - \enforced\permanent\protected\def\dotopbaselinecorrection{\hrule\s!height\d_spac_lines_correction_before}% - \enforced\permanent\protected\def\dobotbaselinecorrection{\hrule\s!height\d_spac_lines_correction_after }} - -% \def\dobaselinecorrection % beware, this one is redefined below -% {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi -% \kern\strutdp -% \prevdepth\strutdp} - -\permanent\protected\def\baselinecorrection - {\endgraf - \ifvmode - \ifdim\prevdepth<\maxdimen - \ifdim\prevdepth<\zeropoint \else - \ifdim\prevdepth<\strutdepth \relax - \pushlastnode - \dobaselinecorrection - \poplastnode - \fi - \fi - \fi - \fi} - -\permanent\protected\def\pagebaselinecorrection - {\ifdim\pagegoal<\maxdimen - \ifdim\pagetotal>\lineheight % or \topskip - \scratchdimen\pagetotal - \advance\scratchdimen\lineheight - \ifdim\scratchdimen<\pagegoal - \baselinecorrection - \fi - \fi - \fi} - -\permanent\protected\def\startbaselinecorrection - {\bgroup - \enforced\let\stopbaselinecorrection\egroup - \ifcase\baselinecorrectionmode - \or % normal - \baselinecorrection - \ifvmode - \setbox\scratchbox\vbox\bgroup\ignorespaces - \enforced\let\stopbaselinecorrection\donormalstopbaselinecorrection - \fi - \or % off - \or % force - \baselinecorrection - \ifvmode - \setbox\scratchbox\vbox\bgroup\ignorespaces - \enforced\let\stopbaselinecorrection\doforcedstopbaselinecorrection - \fi - \fi} - -\permanent\let\stopbaselinecorrection\relax - -\permanent\protected\def\donormalstopbaselinecorrection % I have to check columns yet. - {\egroup - \topbaselinecorrection - \box\scratchbox - \botbaselinecorrection - \egroup} - -\permanent\protected\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 - -\permanent\protected\def\onbaselinecorrection {\baselinecorrectionmode\plusone } -\permanent\protected\def\offbaselinecorrection {\baselinecorrectionmode\plustwo } -\permanent\protected\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree} - -%D \macros -%D {topbaselinecorrection,botbaselinecorrection} -%D -%D The actual top and bottom corrections are implemented as: - -\permanent\protected\def\topbaselinecorrection - {\ifvmode \ifdim\pagegoal<\maxdimen - \forcedtopbaselinecorrection - \fi \fi} - -% \permanent\protected\def\forcedtopbaselinecorrection -% {\ifvmode -% \bgroup -% \spac_lines_initialize_corrections -% \whitespace % no longer ok -% \nointerlineskip -% \dotopbaselinecorrection -% \egroup -% \fi} - -\permanent\protected\def\botbaselinecorrection - {\ifvmode - \bgroup - \spac_lines_initialize_corrections - \dobotbaselinecorrection - \allowbreak % new, otherwise problems when many in a row - \prevdepth\strutdp - \egroup - \fi} - -% nointerlineskip -% -% startpacked -% \startlinecorrection \framed{test} \stoplinecorrection -% \startlinecorrection \framed{test} \stoplinecorrection -% \stoppacked - -\permanent\protected\def\forcedtopbaselinecorrection - {\ifvmode - \bgroup - \spac_lines_initialize_corrections - \vspacing[\v!white] - %\nointerlineskip % - \dotopbaselinecorrection - \egroup - \fi} - -\permanent\protected\def\dobaselinecorrection - {\ifdim\prevdepth>\zeropoint - \vspacing[\the\dimexpr-\prevdepth+\strutdp\relax]% - \else - \vspacing[\the\dimexpr\strutdp\relax]% - \fi - \prevdepth\strutdp} - -% \permanent\protected\def\dobaselinecorrection -% {\scratchdimen\dimexpr\ifdim\prevdepth>\zeropoint-\prevdepth+\fi\strutdp\relax -% \vspacing[\the\scratchdimen]% -% \prevdepth\strutdp} -% -% some day: -% -% \permanent\protected\def\dobaselinecorrection -% {\clf_checkstrutdepth\strutdp} -% -% \permanent\protected\def\baselinecorrection -% {\endgraf -% \ifvmode -% \ifdim\prevdepth<\maxdimen -% \ifdim\prevdepth<\zeropoint \else -% \ifdim\prevdepth<\strutdepth \relax -% % works in mvl: -% % \forcestrutdepth -% % doesn't work immediately (unless enforced with penalty): -% % \pushlastnode -% % \dobaselinecorrection -% % \poplastnode -% % works ok: -% \clf_checkstrutdepth\strutdp -% \fi -% \fi -% \fi -% \fi} - -%D For the moment only with placefloats (should work in mvl and boxes): - -\permanent\protected\def\checkprevdepth - {\endgraf - \ifvmode - \ifdim\prevdepth<\maxdimen - \ifdim\prevdepth<\zeropoint \else - \ifdim\prevdepth<\strutdepth \relax - \clf_checkstrutdepth\strutdp - \fi - \fi - \fi - \fi} - -\let\normalstartbaselinecorrection\startbaselinecorrection - -\pushoverloadmode - -\permanent\protected\def\startbaselinecorrection - {\ifgridsnapping - \snaptogrid[\v!normal]\vbox\bgroup - \enforced\let\stopbaselinecorrection\egroup - \else - \normalstartbaselinecorrection - \fi} - -\popoverloadmode - -% This is new (and experimental) and might replace some of the above. beware it doesn't always work -% out well, e.g. when used grouped and such (e.g. before display math doesn't work out well). - -% \permanent\protected\def\fakenextstrutline -% {\par -% \begingroup -% \reseteverypar -% \dontleavehmode\hpack to \zeropoint{\page_sides_anchor\hss\strut}% just a tracer -% \vskip-\parskip -% \vskip-\struttotal -% \endgroup} - -% \permanent\protected\def\fakenextstrutline -% {\par -% \begingroup -% \reseteverypar -% \dontleavehmode\hpack{\strut}\par -% \clf_fakenextstrutline -% \ifdim\pagetotal>\lineheight -% \pagetotal\dimexpr\pagetotal-\lineheight\relax -% \fi -% \endgroup} - -% \permanent\protected\def\fakenextstrutline -% {\par -% \begingroup -% \reseteverypar -% \forgetall -% \dontleavehmode\hpack{\strut}\par -% \clf_removelastline -% \endgroup} - -\protect \endinput diff --git a/tex/context/base/mkiv/spac-hor.mkxl b/tex/context/base/mkiv/spac-hor.mkxl deleted file mode 100644 index b6f92947e..000000000 --- a/tex/context/base/mkiv/spac-hor.mkxl +++ /dev/null @@ -1,1259 +0,0 @@ -%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}{} - -\let\parfillrightskip\parfillskip - -\bitwiseflip \normalizelinemode \parindentskipcode -\bitwiseflip \normalizelinemode \normalizelinecode - -\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. - -\permanent\protected\def\presetindentation - {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}} - -\permanent\protected\def\setupindenting - {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size} - -\protected\def\spac_indentation_setup_size - {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}% - \ifzeropt\parindent\else - \parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand - \fi} - -\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 - \ifempty\m_spac_indentation_options \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 - \spac_indentation_variant_yes % better than: \let\checkindentation\relax - \else - \spac_indentation_variant_no - \fi - \spac_indentation_check_toggle} - -\def\spac_indentation_set_everypar - {\everypar{\checkindentation}} - -\permanent\protected\def\useindentingparameter#1% faster local variant - {\edef\m_spac_indentation_options{#1\c!indenting}% - \ifempty\m_spac_indentation_options \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} - -\permanent\tolerant\protected\def\defineindenting[#1]#*[#2]% todo: mixes - {\ifarguments\else\setevalue{\??indentingpreset#1}{#2}\fi} - -\def\spac_indentation_apply_step_one_nested - {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one} - -\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 - \orelse\ifcsname\??indentingmethod#1\endcsname - % case two - \else - \edef\v_spac_indentation_current{#1}% single entry in list - \let\normalindentation\v_spac_indentation_current - \spac_indentation_setup_size - \fi} - -\def\spac_indentation_apply_step_two#1% - {\ifcsname\??indentingpreset#1\endcsname - \spac_indentation_apply_step_two_nested - \orelse\ifcsname\??indentingmethod#1\endcsname - \lastnamedcs - \else - % case one - \fi} - -\permanent\protected\def\indenting % kind of obsolete - {\doifelsenextoptionalcs\spac_indentation_setup_options\relax} - -% use \noindentation to suppress next indentation - -\installcorenamespace{indentingmethod} - -\permanent\protected\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{\ifempty\normalindentation\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\ifzeropt\parindent - \d_spac_indentation_par - \else - \zeropoint - \fi\relax} - -\permanent\protected\def\noindenting{\indenting[\v!no, \v!next ]} -\permanent\protected\def\doindenting{\indenting[\v!yes,\v!first]} - -%D Here come the handlers (still rather messy ... we need states). - -%newif\ifindentation \indentationtrue % will become a mode - -\aliased\let\checkindentation\relax - -\installmacrostack\checkindentation - -\def\spac_indentation_remove - {\ifzeropt\parindent \else - \begingroup - \setbox\scratchbox\lastbox - \endgroup - \fi} - -\def\spac_indentation_kill_indeed - {%\global\indentationfalse - \spac_indentation_remove} - -\permanent\protected\def\spac_indentation_do_toggle_indeed - {%\global\indentationfalse - \enforced\glet\checkindentation\spac_indentation_no_toggle_indeed - \spac_indentation_remove} - -\permanent\protected\def\spac_indentation_no_toggle_indeed - {%\global\indentationtrue - \enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} - -\permanent\protected\def\spac_indentation_do_indeed - {}%\global\indentationtrue} - -\permanent\protected\def\spac_indentation_do_toggle - {\enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} - -\permanent\protected\def\spac_indentation_no_toggle - {\enforced\glet\checkindentation\spac_indentation_no_toggle_indeed} - -\permanent\protected\def\spac_indentation_check_toggle - {\ifcase\c_spac_indentation_toggle_state - % nothing - \or - \spac_indentation_no_toggle - \or - \spac_indentation_do_toggle - \fi} - -\permanent\protected\def\spac_indentation_variant_yes - {\enforced\glet\checkindentation\spac_indentation_do_indeed} - -\permanent\protected\def\spac_indentation_no_next_check - {\spac_indentation_remove - \enforced\glet\checkindentation\spac_indentation_do_indeed} - -\permanent\protected\def\spac_indentation_variant_no % made global - {\ifinpagebody \else - %\global\indentationfalse - \enforced\glet\checkindentation\spac_indentation_no_next_check - \fi} - -\permanent\protected\def\nonoindentation % bv bij floats - {\ifinpagebody \else - %\global\indentationtrue - \enforced\glet\checkindentation\spac_indentation_do_indeed - \fi} - -\permanent\protected\def\spac_indentation_variant_force - {\ifvmode \ifzeropt\parindent \else - % was : \hskip\parindent - % can be: \indent - % but we test: - \noindent\hskip\parindent - \fi \fi} - -% public: - -\aliased\let\indentation \spac_indentation_variant_force -\aliased\let\noindentation\spac_indentation_variant_no % public -\aliased\let\doindentation\spac_indentation_variant_yes % public - -\permanent\protected\def\dontrechecknextindentation % public (in macros) - {\global\enforced\let\dorechecknextindentation\relax} - -\aliased\let\dorechecknextindentation\relax % public (in macros) - -\permanent\protected\protected\def\spac_indentation_check_next_indentation - {\global\enforced\let\dorechecknextindentation\relax - \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par - -\def\spac_indentation_variant_auto - {\global\enforced\let\dorechecknextindentation\spac_indentation_check_next_indentation} - -%D This one sets up the local indentation behaviour (i.e. either or not -%D a next paragraph will be indented). - -\installcorenamespace{indentnext} - -\permanent\protected\def\checknextindentation[#1]% - {\begincsname\??indentnext#1\endcsname} - -\permanent\protected\def\useindentnextparameter#1% new, the more efficient variant - {\edef\p_indentnext{#1\c!indentnext}% - \ifempty\p_indentnext\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 - -\permanent\protected\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 - -\permanent\protected\def\forgethorizontalstretch - {\emergencystretch\zeropoint} - -\appendtoks - \forgethorizontalstretch -\to \everyforgetall % needed in pagebody - -%D Helper: - -\permanent\protected\def\softbreak - {\relax\ifhmode\hskip\parfillskip\break\fi} - -%D \macros -%D {frenchspacing,nonfrenchspacing} -%D -%D Somehow \type{\frenchspacing} can lead to hyphenation between dashes so we now -%D have \type {\newfrenchspacing} (moved from \type {syst-chr}). Maybe it's not -%D needed any more. - -%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 } - -\permanent\protected\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand} -\permanent\protected\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}} -\permanent\protected\def\nonfrenchspacing{\spac_spacecodes_set_stretch} - -\permanent\protected\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}} - -\installspacingmethod \empty {} % keep values -\installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere -\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation -\installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation - -%% \permanent\protected\def\setupspacing -%% {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop} -%% -%% \def\spac_spacecodes_setup_yes[#1]% -%% {\begincsname\??spacecodemethod#1\endcsname -%% \updateraggedskips} -%% -%% \def\spac_spacecodes_setup_nop -%% {\updateraggedskips} - -\permanent\tolerant\protected\def\setupspacing[#1]% - {\ifarguments\or - \begincsname\??spacecodemethod#1\endcsname - \fi - \updateraggedskips} - -%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: - -\permanent\protected\def\synchronizespacecodes{\updateraggedskips} - -% \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 \ 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. - -\permanent\protected\def\specialspaceprimitive - {\begingroup - % so, no fancy extra spacing after: foo i.e.\ bar - \nonfrenchspacing\normalspaceprimitive - \endgroup} - -\permanent\protected\def\normalnotobeyedspace - {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing) - -\pushoverloadmode - -\overloaded\let\ =\normalnotobeyedspace % so we redefine the primitive! - -\popoverloadmode - -% Because I strip spaces at the end of lines (in the editor) we need a bit of -% a trick to define slash+newline, so \space and \ 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} - -\permanent\protected\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math - -\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later - -% \def\space { } -\permanent\protected\def\removelastspace{\ifhmode\unskip\fi} -\permanent\protected\def\nospace {\removelastspace\ignorespaces} - -\ifdefined\nospaces - \permanent\protected\def\nospacing{\normalnospaces\plusone} - \permanent\protected\def\dospacing{\normalnospaces\zerocount} -\else - \permanent\protected\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint} - \permanent\protected\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what -\fi - -\ifdefined\softhyphen \else - \let\softhyphen\explicitdiscretionary -\fi - -% todo: - -\cldcontext{"\string\\protected\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: - -\permanent\protected\def\fixedspace - {\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox - \hskip\wd\scratchbox\relax} - -\permanent\protected\def\fixedspaces - {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace - \enforced\let~\fixedspace} % we need to renew it - -\appendtoks - \enforced\let~\space - \enforced\let\ \space -\to \everysimplifycommands - -\newsignal\d_spac_keep_unwanted_space_signal - -% \parindentmode\plusone - -\permanent\protected\def\keepunwantedspaces - {\ifhmode - \ifdim\lastskip=\d_spac_keep_unwanted_space_signal\else - \hskip\d_spac_keep_unwanted_space_signal\relax - \fi - \fi} - -\permanent\protected\def\removeunwantedspaces - {\ifhmode - \expandafter \spac_helpers_remove_unwantedspace - \fi} - -\def\spac_helpers_remove_unwantedspace - {\ifnum\lastnodetype=\gluenodecode\relax - \ifnum\lastnodesubtype=\indentskipsubtypecode\relax - % keep parindent - \orelse\ifdim\lastskip=\d_spac_keep_unwanted_space_signal\relax - \unskip - \else - \unskip - \doubleexpandafter\spac_helpers_remove_unwantedspace - \fi - \fi} - -\permanent\protected\def\onlynonbreakablespace - {\ifdim\lastskip=\interwordspace - \unskip - \nonbreakablespace - \fi - \ignorespaces} - -% \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\enspace \else \permanent\protected\def\enspace{\kern .5\emwidth} \fi -\ifdefined\quad \else \permanent\protected\def\quad {\hskip \emwidth\relax} \fi -\ifdefined\enskip \else \permanent\protected\def\enskip {\hskip.5\emwidth\relax} \fi -\ifdefined\qquad \else \permanent\protected\def\qquad {\hskip 2\emwidth\relax} \fi - -\permanent\protected\def\negenspace{\kern-.5\emwidth} -\permanent\protected\def\negemspace{\kern- \emwidth} - -\let\emspace\quad - -\permanent\protected\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) - -\permanent\tolerant\protected\def\quads[#1]% we do robust checking - {\dontleavehmode - \begingroup - %\scratchcounter\ifparameter#1\or#1\else\plusthree\fi - \scratchcounter\ifchknum#1\or#1\else\plusthree\fi - \zwj\dorecurse\scratchcounter{\hskip\emwidth\zwj}% - \endgroup} - -% Suggested by GB (not the name -): - -\def\rapfillskip{.5\hsize plus .092\hsize minus .5\hsize} % D.A.'s value - -% Bovendien definieren we enkele extra \fill's: - -\newskip\s_spac_fil \s_spac_fil = \zeropoint \s!plus 1\s!fil \relax -\newskip\s_spac_fill \s_spac_fill = \zeropoint \s!plus 1\s!fill \relax -\newskip\s_spac_filll \s_spac_filll = \zeropoint \s!plus 1\s!filll\relax - -\newskip\s_spac_neg_fil \s_spac_neg_fil = \zeropoint \s!plus-1\s!fil \relax -\newskip\s_spac_neg_fill \s_spac_neg_fill = \zeropoint \s!plus-1\s!fill \relax -\newskip\s_spac_neg_filll \s_spac_neg_filll = \zeropoint \s!plus-1\s!filll\relax - -\permanent\protected\def\hfilll {\hskip\s_spac_filll\relax} -\permanent\protected\def\vfilll {\vskip\s_spac_filll\relax} - -\permanent\protected\def\hfillneg {\hskip\s_spac_neg_fill \relax} -\permanent\protected\def\hfilllneg{\hskip\s_spac_neg_filll\relax} -\permanent\protected\def\vfillneg {\vskip\s_spac_neg_fill \relax} -\permanent\protected\def\vfilllneg{\vskip\s_spac_neg_filll\relax} - -\permanent\protected\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} -\permanent\protected\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere - -% maybe we should hash the analysis - -\installcorenamespace{narrower} -\installcorenamespace{narrowermethod} - -\newskip\s_spac_narrower_left -\newskip\s_spac_narrower_right -\newskip\s_spac_narrower_middle - -\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 - \frozen\instance\setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}% - \frozen\instance\setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}% -\to \everydefinenarrower - -\permanent\protected\def\installnarrowermethod#1#2% - {\setvalue{\??narrowermethod#1}{#2}} - -\protected\def\spac_narrower_method_analyze#1% - {\ifcsname\??narrowermethod#1\endcsname - \lastnamedcs - \else - \global\advance\s_spac_narrower_middle#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_middle \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_middle-\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_middle \zeropoint - \global \s_spac_narrower_right \zeropoint\relax} -\installnarrowermethod \v!none {} -\installnarrowermethod \v!reverse {} % never seen - -\permanent\overloaded\tolerant\protected\def\spac_narrower_start[#1]#*[#2]% - {\begingroup - \edef\currentnarrower{#1}% - \ifparameter#2\or - \spac_narrower_start_apply{#2}% - \else - \spac_narrower_start_apply{\narrowerparameter\v!default}% - \fi} - -\newskip \s_spac_narrower_left_last -\newskip \s_spac_narrower_right_last -\newconditional\s_spac_narrower_last_swap - -\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_middle\zeropoint - \edef\askednarrower{#1}% - \ifx\askednarrower\v!reverse - \ifconditional\s_spac_narrower_last_swap - \permanent\leftskip \s_spac_narrower_right_last - \permanent\rightskip\s_spac_narrower_left_last - \setfalse\s_spac_narrower_last_swap - \else - \permanent\leftskip \s_spac_narrower_left_last - \permanent\rightskip\s_spac_narrower_right_last - \settrue\s_spac_narrower_last_swap - \fi - \else - \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize - \permanent\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax - \permanent\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax - \fi - \seteffectivehsize} - -\permanent\protected\def\spac_narrower_stop - {\narrowerparameter\c!after - \normalexpanded{% - \endgroup - \s_spac_narrower_left_last \the\leftskip \relax - \s_spac_narrower_right_last\the\rightskip\relax - \ifconditional\s_spac_narrower_last_swap - \setfalse\s_spac_narrower_last_swap - \else - \settrue\s_spac_narrower_last_swap - \fi - }} - -%% \permanent\protected\def\startnarrower -%% {\dosingleempty\spac_narrower_start_basic} -%% -%% \protected\def\spac_narrower_start_basic[#1]% - -\permanent\tolerant\protected\def\startnarrower[#1]% - {\begingroup - \let\currentnarrower\empty - \ifparameter#1\or - \spac_narrower_start_apply{#1}% - \else - \spac_narrower_start_apply{\narrowerparameter\v!default}% - \fi} - -\let\stopnarrower\spac_narrower_stop - -%% \protected\def\startnarrow % current how -%% {\begingroup -%% \dodoubleempty\spac_narrower_start_named} -%% -%% \def\spac_narrower_start_named -%% {\ifsecondargument -%% \expandafter\spac_narrower_start_named_two -%% \else -%% \expandafter\spac_narrower_start_named_one -%% \fi} - -% can be cleaned up more ... todo - -\permanent\tolerant\protected\def\startnarrow[#1]#*[#2]% current how - {\begingroup - \ifnum\lastarguments=\plustwo - \expandafter\spac_narrower_start_named_two - \else - \expandafter\spac_narrower_start_named_one - \fi[#1][#2]} - -\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 {\dimexpr\leftskip \relax} -\newdimen\d_spac_effective_rightskip \def\effectiverightskip{\dimexpr\rightskip\relax} - -\permanent\protected\def\seteffectivehsize - {\setlocalhsize - \d_spac_effective_hsize \localhsize - \d_spac_effective_leftskip 1\leftskip - \d_spac_effective_rightskip1\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!yes }{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} -\letvalue{\??skipadaptionleft \v!no }\zeropoint -\letvalue{\??skipadaptionleft \empty }\zeropoint -\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right} -\letvalue{\??skipadaptionright\v!no }\zeropoint -\letvalue{\??skipadaptionright\empty }\zeropoint - -% \setvalue{\??skipadaptionleft \v!standard}{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} -% \setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right} - -\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname -\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname - -% \protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax} -% \protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax} - -\permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} -\permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} - -\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\permanent\advance\leftskip \leftskipadaption } -\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\permanent\advance\rightskip\rightskipadaption} - -\permanent\protected\def\forgetbothskips - {\leftskip\zeropoint - \rightskip\zeropoint - \relax} - -\appendtoks - \forgetbothskips -\to \everyforgetall - -% in spac-ver.mkiv -% -% \protected\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} - -\permanent\protected\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} - -%% \protected\def\setuptolerance -%% {\dosingleargument\spac_tolerances_setup} -%% -%% \def\spac_tolerances_setup[#1]% -%% {\doifelseinset\v!vertical{#1}% -%% {\processcommacommand[#1]\spac_tolerances_step_vertical } -%% {\processcommacommand[#1]\spac_tolerances_step_horizontal}} - -\permanent\tolerant\protected\def\setuptolerance[#1]% - {\ifarguments\or - \doifelseinset\v!vertical{#1}% - {\processcommacommand[#1]\spac_tolerances_step_vertical } - {\processcommacommand[#1]\spac_tolerances_step_horizontal}% - \fi} - -%D \macros -%D {pushindentation,popindentation} -%D -%D The pushing and popping is done by: - -\newbox\b_spac_indentations_a -\newbox\b_spac_indentations_b - -\permanent\protected\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} - -\permanent\protected\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 - -\permanent\protected\def\justonespace{\removeunwantedspaces\space} -%frozen\protected\def\justaperiod {\removeunwantedspaces.} -%frozen\protected\def\justacomma {\removeunwantedspaces,} - -\installcorenamespace{hspace} - -\permanent\protected\def\ignorecrlf - {\enforced\let\crlf\justonespace - \enforced\let\\\crlf} - -\permanent\protected\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} - -\permanent\tolerant\protected\def\hspace[#1]#*[#2]% - {\ifhmode - \removeunwantedspaces - \hskip % always a skip even when 0pt - \ifparameter#2\or - \hspaceamount{#1}{#2}% - \orelse\ifparameter#1\or - \hspaceamount\empty{#1}% - \else - \hspaceamount\empty\s!default - \fi - \relax - \expandafter\ignorespaces - \fi} - -\permanent\overloaded\def\hspaceamount #1#2{\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax} -\permanent\overloaded\def\directhspaceamount #1{\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} - -% no installhspace here (this is already an old command) - -\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}: - -\permanent\protected\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax} -\permanent\protected\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax} -\permanent\protected\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax} - -\newmuskip\hairmuskip \hairmuskip=.15mu - -\overloaded\permanent\protected \def\hairspace {\textormathspace+\hairmuskip{.5}} -\overloaded\permanent\protected \def\thinspace {\textormathspace+\thinmuskip 1} -%overloaded\permanent\protected \def\medspace {\textormathspace+\medmuskip 2} % 4/18 em -\overloaded\permanent\protected \def\thickspace {\textormathspace+\thickmuskip3} -\overloaded\permanent\protected \def\neghairspace {\textormathspace-\thinmuskip{.5}} -\overloaded\permanent\protected \def\negthinspace {\textormathspace-\thinmuskip 1} -\overloaded\permanent\protected \def\negmedspace {\textormathspace-\medmuskip 2} -\overloaded\permanent\protected \def\negthickspace{\textormathspace-\thickmuskip3} -\overloaded\permanent\protected\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}} - -% needed for unicode: - -%protected\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1} -%protected\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace -%protected\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax} -%protected\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax} -%protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie -%protected\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax} -%protected\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this -%protected\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup} -%protected\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax} -%protected\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax} -%protected\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace} -%protected\def\narrownobreakspace {\penalty\plustenthousand\thinspace} -%protected\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint} -%protected\def\zerowidthspace {\hskip\zeropoint} - -\definehspace[.5][.1250\emwidth] % hair -\definehspace[1] [.1667\emwidth] % thin -\definehspace[2] [.2222\emwidth] % med -\definehspace[3] [.2777\emwidth] % thick - -\aliased\let \, \thinspace -\aliased\let \: \medspace -\aliased\let \; \thickspace -\aliased\let \! \negthinspace - -% plain ... -% -% \ifdefined\> \else \protected\def\>{\mskip \medmuskip } \fi -% \ifdefined\* \else \protected\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi - -\permanent\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} - -\permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace - {\setvalue{\??spacemethods#1}{#2}} - -\permanent\def\activatespacehandler#1% - {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname} - -\permanent\protected\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}% -\permanent\protected\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% -\permanent\protected\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% - -% hm, order matters when we \let in \obeyspaces - -\installspacemethod \v!on - {\obeyspaces - \enforced\let\obeyedspace\spac_spaces_checked_control - \enforced\let\ =\obeyedspace} - -\installspacemethod \v!yes - {\obeyspaces - \enforced\let\obeyedspace\spac_spaces_checked_normal - \enforced\let\ =\obeyedspace} - -\installspacemethod \v!off % == default - {\normalspaces - \enforced\let\obeyedspace\normalspace - \enforced\let\ =\normalspaceprimitive} % was \normalspace - -\installspacemethod \v!fixed - {\obeyspaces - \enforced\let\obeyedspace\spac_spaces_checked_fixed - \enforced\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 - -\permanent\protected\def\autoinsertnextspace - {\futurelet\nexttoken\spac_spaces_auto_insert_next} - -\permanent\def\spac_spaces_auto_insert_next - {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end - -%D Moved from bib module: - -\permanent\protected\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): - -\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} - -\permanent\protected\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small} -\permanent\protected\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} -\permanent\protected\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} - -%D A rather unknown one: - -\permanent\protected\def\widened % moved from cont-new - {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop} - -\def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}} -\def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}} - -%D For the moment here (used in page-txt): - -\protected\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\d_spac_ignore_spaces_signal -\newcount \c_spac_ignore_spaces - -\protected\def\startignorespaces - {\advance\c_spac_ignore_spaces\plusone - \ifcase\c_spac_ignore_spaces\or \ifhmode - \hskip\d_spac_ignore_spaces_signal - \fi \fi - \ignorespaces} - -\protected\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 - {\ifzeropt\lastskip - \exitloop - \orelse\ifdim\lastskip=\d_spac_ignore_spaces_signal - \unskip - \exitloop - \else - \unskip - \fi} - -%D \macros -%D {obeyfollowingtoken} - -\def\obeyfollowingtoken{{}} % end \cs scanning - -%D Something new: - -\protected\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax} -\protected\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary} - -\protected\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore} -\protected\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter} -\protected\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter} - -\protect \endinput diff --git a/tex/context/base/mkiv/spac-par.lmt b/tex/context/base/mkiv/spac-par.lmt deleted file mode 100644 index 3af8ea415..000000000 --- a/tex/context/base/mkiv/spac-par.lmt +++ /dev/null @@ -1,80 +0,0 @@ -if not modules then modules = { } end modules ['spac-par'] = { - version = 1.001, - comment = "companion to spac-par.mkxl", - 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 collected = utilities.storage.allocate() -local tobesaved = utilities.storage.allocate() -local wrappers = { } - -local jobparwrappers = { - collected = collected, - tobesaved = tobesaved, -} - -job.parwrappers = jobparwrappers - -local function initializer() - tobesaved = jobparwrappers.tobesaved - collected = jobparwrappers.collected -end - -local function finalizer() - -- nothing yet -end - -job.register('job.parwrappers.collected', tobesaved, initializer, finalizer) - -implement { - name = "newparwrapper", - arguments = "string", - actions = function(id) - local t = tobesaved[id] - local n - if t then - n = #t + 1 - t[n] = 0 - else - n = 1 - tobesaved[id] = { 0 } - end - wrappers[id] = n - end -} - -implement { - name = "setparwrapper", - arguments = "string", - protected = true, - actions = function(id) - local t = tobesaved[id] - local n = #t - t[n] = t[n] + 1 - end -} - -implement { - name = "getparwrapper", - arguments = "string", - public = true, - actions = function(id) - local t = tobesaved[id] - context(t and t[#t] or 0) - end -} - -implement { - name = "lastparwrapper", - arguments = "string", - public = true, - actions = function(id) - local t = collected and collected[id] - context(t and t[wrappers[id]] or 0) - end -} diff --git a/tex/context/base/mkiv/spac-par.mkxl b/tex/context/base/mkiv/spac-par.mkxl deleted file mode 100644 index 524e31bc5..000000000 --- a/tex/context/base/mkiv/spac-par.mkxl +++ /dev/null @@ -1,446 +0,0 @@ -%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} - -\registerctxluafile{spac-par}{autosuffix} - -\unprotect - -% TODO: \appendtoks \strut \wrapuppar{\strut}\to \everypar - -%D New experimental stuff: - -% this might move to syst-ini.mkxl - -\setnewconstant\paragraphupdatecodes\numexpr - \frozentolerancecode - + \frozenloosenesscode - + \frozenlinepenaltycode - + \frozenwidowpenaltycode - + \frozenclubpenaltycode - + \frozenbrokenpenaltycode - + \frozendemeritscode -\relax - -\setnewconstant\paragraphpenaltycodes\numexpr - \frozenlinepenaltycode - + \frozenwidowpenaltycode - + \frozenclubpenaltycode - + \frozenbrokenpenaltycode -\relax - -\setnewconstant\paragraphdemeritcodes\numexpr - \frozendemeritscode -\relax - -\setnewconstant\paragraphshapecodes\numexpr - \frozenhangcode - + \frozenskipcode - + \frozenparfillcode - + \frozenshapecode -\relax - -\setnewconstant\frozenparagraphdefault\numexpr - \frozenhsizecode % \hsize - + \frozenskipcode % \leftskip \rightskip - + \frozenhangcode % \hangindent \hangafter - + \frozenindentcode % \parindent - + \frozenparfillcode % \parfillskip \parfillleftskip - + \frozenadjustcode % \adjustspacing - + \frozenprotrudecode % \protrudechars - + \frozentolerancecode % \tolerance \pretolerance - + \frozenstretchcode % \emergcystretch - + \frozenloosenesscode % \looseness - + \frozenlastlinecode % \lastlinefit - + \frozenlinepenaltycode % \linepenalty \interlinepenalty \interlinepenalties - + \frozenclubpenaltycode % \clubpenalty \clubpenalties - + \frozenwidowpenaltycode % \widowpenalty \widowpenalties - + \frozendisplaypenaltycode % \displaypenalty \displaypenalties - + \frozenbrokenpenaltycode % \brokenpenalty - + \frozendemeritscode % \doublehyphendemerits \finalhyphendemerits \adjdemerits - + \frozenshapecode % \parshape - % \frozenlinecode % \baselineskip \lineskip \lineskiplimit -\relax - -\setnewconstant\paragraphlinecodes\numexpr - \frozenlinecode -\relax - -\permanent\protected\def\freezeparagraphproperties {\snapshotpar\frozenparagraphdefault} -\permanent\protected\def\defrostparagraphproperties{\snapshotpar\zerocount} - -\permanent\protected\def\updateparagraphproperties{\ifhmode\snapshotpar\paragraphupdatecodes \fi} -\permanent\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi} -\permanent\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi} -\permanent\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi} -\permanent\protected\def\updateparagraphlines {\ifhmode\snapshotpar\paragraphlinecodes \fi} - -% so far - -\let\spac_paragraph_freeze\relax - -\permanent\protected\def\setparagraphfreezing {\enforced\let\spac_paragraph_freeze\freezeparagraphproperties} -\permanent\protected\def\forgetparagraphfreezing{\enforced\let\spac_paragraph_freeze\relax} - -\installcorenamespace {bparwrap} -\installcorenamespace {eparwrap} -\installcorenamespace {parwrapbefore} -\installcorenamespace {parwrapafter} -\installcorenamespace {parwrapcount} - -\let\spac_paragraph_wrap\relax - -\newcount\c_spac_paragraph_group_level - -\protected\def\spac_paragraph_update - {\c_spac_paragraph_group_level\currentgrouplevel\relax - \ifcsname\??bparwrap\the\c_spac_paragraph_group_level\endcsname - \the\lastnamedcs - \relax - \dontleavehmode % just in case - \wrapuppar{\the\csname\??eparwrap\the\c_spac_paragraph_group_level\endcsname\relax}% - \fi} - -\permanent\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre} -\permanent\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp} - -\protected\def\spac_paragraph_install - {\expandafter\newtoks\csname\??bparwrap\the\currentgrouplevel\endcsname - \expandafter\newtoks\csname\??eparwrap\the\currentgrouplevel\endcsname} - -\def\spac_paragraph_install_count#1% - {\expandafter\newcount\csname\??parwrapcount#1\endcsname} - -\def\spac_paragraph_install_pair#1#2#3% - {\expandafter\newtoks\csname\??parwrapbefore#3\endcsname - \expandafter\newtoks\csname\??parwrapafter #3\endcsname - #1\csname\??bparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapbefore#3\endcsname}% - #2\csname\??eparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapafter #3\endcsname}} - -\def\spac_register_par_wrapper_yes#1#2#3#4#5% - {\ifcsname\??bparwrap\the\currentgrouplevel\endcsname \else - \spac_paragraph_install - \fi - \ifcsname\??parwrapcount#3\endcsname \else - \spac_paragraph_install_count{#3}% - \fi - \ifcsname\??parwrapbefore#3\endcsname \else - \spac_paragraph_install_pair#1#2{#3}% - \fi - #1\csname\??parwrapbefore#3\endcsname{\advance\csname\??parwrapcount#3\endcsname\plusone\relax - \clf_setparwrapper{#3}#4}% - #2\csname\??parwrapafter #3\endcsname{#5}% - \clf_newparwrapper{#3}% - \enforced\let\spac_paragraph_wrap\spac_paragraph_update} - -\def\spac_register_par_wrapper_nop#1#2#3#4#5% - {\ifcsname\??parwrapcount#3\endcsname \else - \spac_paragraph_install_count{#3}% - \fi - \csname\??parwrapcount#3\endcsname\plusone - #4\wrapuppar{#5}} - -\protected\def\spac_register_par_wrapper - {\ifhmode - \expandafter\spac_register_par_wrapper_nop - \else - \expandafter\spac_register_par_wrapper_yes - \fi} - -\permanent\protected\def\forgetparwrapper - {\csname\??bparwrap\the\currentgrouplevel\endcsname\emptytoks - \csname\??eparwrap\the\currentgrouplevel\endcsname\emptytoks} - -\permanent\protected\def\unregisterparwrapper#1% - {\csname\??parwrapcount#1\endcsname\zerocount - \ifcsname\??parwrapbefore#1\endcsname - \lastnamedcs\emptytoks - \csname\??parwrapafter#1\endcsname\emptytoks - \fi} - -\permanent\def\directparwrapper#1#2% - {#1\wrapuppar{#2}} - -\permanent\protected\def\doifelseparwrapper#1% - {\unless\ifcsname\??parwrapcount#1\endcsname - \expandafter\secondoftwoarguments - \orelse\ifcase\lastnamedcs - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -% \getparwrapper % defined in lua -% \lastparwrapper % defined in lua - -\permanent\protected\def\showparwrapperstate#1% - {\begingroup - \infofont ¶#1\hilo - {\smallinfofont\getparwrapper {#1}}% - {\smallinfofont\lastparwrapper{#1}}% - \endgroup} - -%appendtoks\updateparwrapperindeed\to\everypar -%appendtoks\spac_paragraph_wrap \to\everypar -%appendtoks\spac_paragraph_freeze \to\everypar - -\setparagraphfreezing - -\appendtoks\enforced\let\spac_paragraph_wrap\relax\to\everyforgetall - -%D In due time, the code below will be upgraded using the above mechanisms. - -%D The dreadful sequence \type {\bgroup} \unknown\ \type {\carryoverpar} \unknown\ -%D \type {\egroup} is needed when for instance sidefloats are used in combination -%D with something that starts with a group. This is because otherwise the -%D indentation as set (by the output routine) inside the group are forgotten -%D afterwards. (I must not forget its existence). - -\permanent\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable ! - {\normalexpanded - {\noexpand#1% - \hangindent\the\hangindent - \hangafter \the\hangafter - \parskip \the\parskip - \leftskip \the\leftskip - \rightskip \the\rightskip - \relax}} - -\permanent\protected\def\pushparagraphproperties - {\edef\currentparagraphproperties{\carryoverpar\relax}% - \pushmacro\currentparagraphproperties} - -\permanent\protected\def\popparagraphproperties - {\popmacro\currentparagraphproperties - \currentparagraphproperties} - -\permanent\protected\def\flushparagraphproperties - {\popmacro\currentparagraphproperties} - -%D Beware, changing this will break some code (like pos/backgrounds) but it has been -%D 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 - -\permanent\protected\tolerant\def\setupparagraphintro[#1]#*[#2]% - {\def\spac_paragraphs_intro_step##1% - {\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}% - \processcommacommand[#1]\spac_paragraphs_intro_step} - -\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 - \gtoksapp\t_spac_paragraphs_intro_first{#1}% - \glet\insertparagraphintro\spac_paragraphs_flush_intro} - -\setvalue{\??paragraphintro\v!next}#1% - {\global\settrue\c_spac_paragraphs_intro_next - \gtoksapp\t_spac_paragraphs_intro_next{#1}% - \glet\insertparagraphintro\spac_paragraphs_flush_intro} - -\setvalue{\??paragraphintro\v!each}#1% - {\global\settrue\c_spac_paragraphs_intro_each - \gtoksapp\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 - -\permanent\protected\def\flushatparagraph#1% - {\global\c_spac_paragraphs_intro_first\plusone - \gtoksapp\t_spac_paragraphs_intro_first{#1}% - \glet\insertparagraphintro\spac_paragraphs_flush_intro} - -%D Here comes the flusher (we misuse the one level expansion of token registers to -%D feed a nice stream into the paragraph.) - -\protected\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly - {\normalexpanded{% % after another so the first code is there twice - \ifconditional\c_spac_paragraphs_intro_each - \ifconditional\c_spac_paragraphs_intro_next - \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}} - -\protected\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}} - -\protected\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. By using -%D 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 -% -% \protected\def\pushpostponednodedata -% {\global\advance\c_spac_postponed_data\plusone -% \savebox\??postponednodesstack{\the\c_spac_postponed_data}{\box\b_spac_postponed_data}} -% -% \protected\def\poppostponednodedata -% {\global\setbox\b_spac_postponed_data\hbox{\foundbox\??postponednodesstack{\the\c_spac_postponed_data}}% -% \global\advance\c_spac_postponed_data\minusone -% \ifvoid\b_spac_postponed_data\else -% \glet\flushpostponednodedata\spac_postponed_data_flush -% \fi} - -\newtoks\everyflushatnextpar - -\permanent\protected\def\pushpostponednodedata - {\globalpushbox\b_spac_postponed_data} - -\permanent\protected\def\poppostponednodedata - {\globalpopbox\b_spac_postponed_data - \ifvoid\b_spac_postponed_data\else - \glet\flushpostponednodedata\spac_postponed_data_flush - \fi} - -\permanent\protected\def\flushatnextpar - {\begingroup - \the\everyflushatnextpar - \glet\flushpostponednodedata\spac_postponed_data_flush - \dowithnextboxcs\spac_postponed_data_finish\hpack} - -% \def\spac_postponed_data_finish -% {\global\setbox\b_spac_postponed_data\hpack % to\zeropoint -% {\box\b_spac_postponed_data\box\nextbox}% -% \endgroup} -% -% This is better when used with protrusion which does not like too deeply nested -% boxes: -% -% \def\spac_postponed_data_finish -% {\dontcomplain -% \global\setbox\b_spac_postponed_data\hpack to \zeropoint -% {\unhbox\b_spac_postponed_data\unhbox\nextbox}% -% \endgroup} -% -% We could do this if there is content with widths ... not that is should be used -% that way, but this way we don't overflow: - -\def\spac_postponed_data_finish - {\dontcomplain - \global\setbox\b_spac_postponed_data\hpack % to \zeropoint - {\unhbox\b_spac_postponed_data - \scratchdimen\wd\nextbox - \unhbox\nextbox - \ifcase\scratchdimen\else\kern-\b_spac_postponed_data\fi}% - \endgroup} - -\def\spac_postponed_data_flush - {%\iftrialtypesetting \else - \ifvoid\b_spac_postponed_data\else - \hpack{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data - \fi - \glet\flushpostponednodedata\relax - }%\fi} - -\permanent\protected\def\doflushatpar % might be renamed - {\ifvmode - \expandafter\flushatnextpar - \else - \expandafter\firstofoneargument - \fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/spac-ver.lmt b/tex/context/base/mkiv/spac-ver.lmt deleted file mode 100644 index 90eeacf26..000000000 --- a/tex/context/base/mkiv/spac-ver.lmt +++ /dev/null @@ -1,2527 +0,0 @@ -if not modules then modules = { } end modules ['spac-ver'] = { - version = 1.001, - optimize = true, - comment = "companion to spac-ver.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- we also need to call the spacer for inserts! - --- somehow lists still don't always have proper prev nodes so i need to --- check all of the luatex code some day .. maybe i should replece the --- whole mvl handler by lua code .. why not - --- todo: use lua nodes with lua data (>0.79) --- see ** can go when 0.79 - --- needs to be redone, too many calls and tests now ... still within some --- luatex limitations - --- this code dates from the beginning and is kind of experimental; it --- will be optimized and improved soon .. it's way too complex now but --- dates from less possibilities --- --- the collapser will be redone with user nodes; also, we might get make --- parskip into an attribute and appy it explicitly thereby getting rid --- of automated injections; eventually i want to get rid of the currently --- still needed tex -> lua -> tex > lua chain (needed because we can have --- expandable settings at the tex end - --- todo: strip baselineskip around display math - -local next, type, tonumber = next, type, tonumber -local gmatch, concat = string.gmatch, table.concat -local ceil, floor, abs = math.ceil, math.floor, math.abs -local lpegmatch = lpeg.match -local unpack = unpack or table.unpack -local allocate = utilities.storage.allocate -local todimen = string.todimen -local formatters = string.formatters - -local nodes = nodes -local trackers = trackers -local attributes = attributes -local context = context -local tex = tex - -local texlists = tex.lists -local texget = tex.get -local texgetcount = tex.getcount -local texgetdimen = tex.getdimen -local texgetglue = tex.getglue -local texset = tex.set -local texsetdimen = tex.setdimen -local texsetcount = tex.setcount -local texnest = tex.nest -local texgetbox = tex.getbox - -local buildpage = tex.triggerbuildpage - -local variables = interfaces.variables -local implement = interfaces.implement - -local v_local = variables["local"] -local v_global = variables["global"] -local v_box = variables.box ------ v_page = variables.page -- reserved for future use -local v_split = variables.split -local v_min = variables.min -local v_max = variables.max -local v_none = variables.none -local v_line = variables.line -local v_noheight = variables.noheight -local v_nodepth = variables.nodepth -local v_line = variables.line -local v_halfline = variables.halfline -local v_line_m = "-" .. v_line -local v_halfline_m = "-" .. v_halfline -local v_first = variables.first -local v_last = variables.last -local v_top = variables.top -local v_bottom = variables.bottom -local v_minheight = variables.minheight -local v_maxheight = variables.maxheight -local v_mindepth = variables.mindepth -local v_maxdepth = variables.maxdepth -local v_offset = variables.offset -local v_strut = variables.strut - -local v_hfraction = variables.hfraction -local v_dfraction = variables.dfraction -local v_bfraction = variables.bfraction -local v_tlines = variables.tlines -local v_blines = variables.blines - --- vertical space handler - -local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end) -local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end) -local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) -local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) -local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) -local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) -local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end) - -local remove_math_skips = true directives.register("vspacing.removemathskips", function(v) remnove_math_skips = v end) - -local report_vspacing = logs.reporter("vspacing","spacing") -local report_collapser = logs.reporter("vspacing","collapsing") -local report_snapper = logs.reporter("vspacing","snapping") -local report_specials = logs.reporter("vspacing","specials") - -local a_skipcategory = attributes.private('skipcategory') -local a_skippenalty = attributes.private('skippenalty') -local a_skiporder = attributes.private('skiporder') -local a_snapmethod = attributes.private('snapmethod') -local a_snapvbox = attributes.private('snapvbox') - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local setlink = nuts.setlink -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local setlist = nuts.setlist -local getattr = nuts.getattr -local getattrs = nuts.getattrs -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox -local getwhd = nuts.getwhd -local setwhd = nuts.setwhd -local getprop = nuts.getprop -local setprop = nuts.setprop -local getglue = nuts.getglue -local setglue = nuts.setglue -local getkern = nuts.getkern -local getpenalty = nuts.getpenalty -local setshift = nuts.setshift -local setwidth = nuts.setwidth -local getwidth = nuts.getwidth -local setheight = nuts.setheight -local getheight = nuts.getheight -local setdepth = nuts.setdepth -local getdepth = nuts.getdepth -local setnext = nuts.setnext - -local find_node_tail = nuts.tail -local flush_node = nuts.flush_node -local remove_node = nuts.remove -local count_nodes = nuts.countall -local hpack_node = nuts.hpack -local vpack_node = nuts.vpack -local start_of_par = nuts.start_of_par - -local write_node = nuts.write - -local nextnode = nuts.traversers.node -local nexthlist = nuts.traversers.hlist - -local nodereference = nuts.reference - -local theprop = nuts.theprop - -local listtoutf = nodes.listtoutf -local nodeidstostring = nodes.idstostring - -local nodepool = nuts.pool - -local new_penalty = nodepool.penalty -local new_kern = nodepool.kern -local new_glue = nodepool.glue -local new_rule = nodepool.rule - -local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes ------ penaltycodes = nodes.penaltycodes ------ listcodes = nodes.listcodes - -local penalty_code = nodecodes.penalty -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local rule_code = nodecodes.rule -local par_code = nodecodes.par - -local userskip_code = gluecodes.userskip -local lineskip_code = gluecodes.lineskip -local baselineskip_code = gluecodes.baselineskip -local parskip_code = gluecodes.parskip -local topskip_code = gluecodes.topskip -local splittopskip_code = gluecodes.splittopskip - -local linelist_code = nodes.listcodes.line - -local properties = nodes.properties.data - -local vspacing = builders.vspacing or { } -builders.vspacing = vspacing - -local vspacingdata = vspacing.data or { } -vspacing.data = vspacingdata - -local snapmethods = vspacingdata.snapmethods or { } -vspacingdata.snapmethods = snapmethods - -storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") - -do - - local default = { - [v_maxheight] = true, - [v_maxdepth] = true, - [v_strut] = true, - [v_hfraction] = 1, - [v_dfraction] = 1, - [v_bfraction] = 0.25, - } - - local fractions = { - [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, - [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, - [v_box] = v_bfraction, - [v_top] = v_tlines, [v_bottom] = v_blines, - } - - local values = { - offset = "offset" - } - - local colonsplitter = lpeg.splitat(":") - - local function listtohash(str) - local t = { } - for s in gmatch(str,"[^, ]+") do - local key, detail = lpegmatch(colonsplitter,s) - local v = variables[key] - if v then - t[v] = true - if detail then - local k = fractions[key] - if k then - detail = tonumber("0" .. detail) - if detail then - t[k] = detail - end - else - k = values[key] - if k then - detail = todimen(detail) - if detail then - t[k] = detail - end - end - end - end - else - detail = tonumber("0" .. key) - if detail then - t[v_hfraction] = detail - t[v_dfraction] = detail - end - end - end - if next(t) then - t[v_hfraction] = t[v_hfraction] or 1 - t[v_dfraction] = t[v_dfraction] or 1 - return t - else - return default - end - end - - function vspacing.definesnapmethod(name,method) - local n = #snapmethods + 1 - local t = listtohash(method) - snapmethods[n] = t - t.name = name -- not interfaced - t.specification = method -- not interfaced - context(n) - end - -end - -local function validvbox(parentid,list) - if parentid == hlist_code then - local id = getid(list) - if id == par_code and start_of_par(list) then - list = getnext(list) - if not next then - return nil - end - end - local done = nil - for n, id in nextnode, list do - if id == vlist_code or id == hlist_code then - if done then - return nil - else - done = n - end - elseif id == glue_code or id == penalty_code then - -- go on - else - return nil -- whatever - end - end - if done then - local id = getid(done) - if id == hlist_code then - return validvbox(id,getlist(done)) - end - end - return done -- only one vbox - end -end - -local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped - -- problem: any snapped vbox ends up in a line - if list and parentid == hlist_code then - local id = getid(list) - if id == par_code and start_of_par(list) then - list = getnext(list) - if not list then - return false - end - end - for n, id in nextnode, list do - if id == hlist_code or id == vlist_code then - -- local a = getattr(n,a_snapmethod) - -- if not a then - -- -- return true -- not snapped at all - -- elseif a == 0 then - -- return true -- already snapped - -- end - local p = getprop(n,"snapper") - if p then - return p - end - elseif id == glue_code or id == penalty_code then -- or id == kern_code then - -- go on - else - return false -- whatever - end - end - end - return false -end - --- quite tricky: ceil(-something) => -0 - -local function ceiled(n) - if n < 0 or n < 0.01 then - return 0 - else - return ceil(n) - end -end - -local function floored(n) - if n < 0 or n < 0.01 then - return 0 - else - return floor(n) - end -end - --- check variables.none etc - -local function fixedprofile(current) - local profiling = builders.profiling - return profiling and profiling.fixedprofile(current) -end - -local function snap_hlist(where,current,method,height,depth) -- method[v_strut] is default - if fixedprofile(current) then - return - end - local list = getlist(current) - local t = trace_vsnapping and { } - if t then - t[#t+1] = formatters["list content: %s"](listtoutf(list)) - t[#t+1] = formatters["snap method: %s"](method.name) -- not interfaced - t[#t+1] = formatters["specification: %s"](method.specification) -- not interfaced - end - local snapht, snapdp - if method[v_local] then - -- snapping is done immediately here - snapht = texgetdimen("bodyfontstrutheight") - snapdp = texgetdimen("bodyfontstrutdepth") - if t then - t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp) - end - elseif method[v_global] then - snapht = texgetdimen("globalbodyfontstrutheight") - snapdp = texgetdimen("globalbodyfontstrutdepth") - if t then - t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp) - end - else - -- maybe autolocal - -- snapping might happen later in the otr - snapht = texgetdimen("globalbodyfontstrutheight") - snapdp = texgetdimen("globalbodyfontstrutdepth") - local lsnapht = texgetdimen("bodyfontstrutheight") - local lsnapdp = texgetdimen("bodyfontstrutdepth") - if snapht ~= lsnapht and snapdp ~= lsnapdp then - snapht, snapdp = lsnapht, lsnapdp - end - if t then - t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) - end - end - - local wd, ht, dp = getwhd(current) - - local h = (method[v_noheight] and 0) or height or ht - local d = (method[v_nodepth] and 0) or depth or dp - local hr = method[v_hfraction] or 1 - local dr = method[v_dfraction] or 1 - local br = method[v_bfraction] or 0 - local ch = h - local cd = d - local tlines = method[v_tlines] or 1 - local blines = method[v_blines] or 1 - local done = false - local plusht = snapht - local plusdp = snapdp - local snaphtdp = snapht + snapdp - local extra = 0 - - if t then - t[#t+1] = formatters["hlist: wd %p ht %p (used %p) dp %p (used %p)"](wd,ht,h,dp,d) - t[#t+1] = formatters["fractions: hfraction %s dfraction %s bfraction %s tlines %s blines %s"](hr,dr,br,tlines,blines) - end - - if method[v_box] then - local br = 1 - br - if br < 0 then - br = 0 - elseif br > 1 then - br = 1 - end - local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp) - local x = n * snaphtdp - h - d - plusht = h + x / 2 - plusdp = d + x / 2 - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_box,plusht,plusdp) - end - elseif method[v_max] then - local n = ceiled((h+d)/snaphtdp) - local x = n * snaphtdp - h - d - plusht = h + x / 2 - plusdp = d + x / 2 - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_max,plusht,plusdp) - end - elseif method[v_min] then - -- we catch a lone min - if method.specification ~= v_min then - local n = floored((h+d)/snaphtdp) - local x = n * snaphtdp - h - d - plusht = h + x / 2 - plusdp = d + x / 2 - if plusht < 0 then - plusht = 0 - end - if plusdp < 0 then - plusdp = 0 - end - end - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_min,plusht,plusdp) - end - elseif method[v_none] then - plusht, plusdp = 0, 0 - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_none,0,0) - end - end - -- for now, we actually need to tag a box and then check at several points if something ended up - -- at the top of a page - if method[v_halfline] then -- extra halfline - extra = snaphtdp/2 - plusht = plusht + extra - plusdp = plusdp + extra - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline,plusht,plusdp) - end - end - if method[v_line] then -- extra line - extra = snaphtdp - plusht = plusht + extra - plusdp = plusdp + extra - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line,plusht,plusdp) - end - end - if method[v_halfline_m] then -- extra halfline - extra = - snaphtdp/2 - plusht = plusht + extra - plusdp = plusdp + extra - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline_m,plusht,plusdp) - end - end - if method[v_line_m] then -- extra line - extra = - snaphtdp - plusht = plusht + extra - plusdp = plusdp + extra - if t then - t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line_m,plusht,plusdp) - end - end - if method[v_first] then - local thebox = current - local id = getid(thebox) - if id == hlist_code then - thebox = validvbox(id,getlist(thebox)) - id = thebox and getid(thebox) - end - if thebox and id == vlist_code then - local list = getlist(thebox) - local lw, lh, ld - for n in nexthlist, list do - lw, lh, ld = getwhd(n) - break - end - if lh then - local wd, ht, dp = getwhd(thebox) - if t then - t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) - t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) - end - local delta = h - lh - ch, cd = lh, delta + d - h, d = ch, cd - local shifted = hpack_node(getlist(current)) - setshift(shifted,delta) - setlist(current,shifted) - done = true - if t then - t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) - end - elseif t then - t[#t+1] = "first: not done, no content" - end - elseif t then - t[#t+1] = "first: not done, no vbox" - end - elseif method[v_last] then - local thebox = current - local id = getid(thebox) - if id == hlist_code then - thebox = validvbox(id,getlist(thebox)) - id = thebox and getid(thebox) - end - if thebox and id == vlist_code then - local list = getlist(thebox) - local lw, lh, ld - for n in nexthlist, list do - lw, lh, ld = getwhd(n) - end - if lh then - local wd, ht, dp = getwhd(thebox) - if t then - t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) - t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) - end - local delta = d - ld - cd, ch = ld, delta + h - h, d = ch, cd - local shifted = hpack_node(getlist(current)) - setshift(shifted,delta) - setlist(current,shifted) - done = true - if t then - t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) - end - elseif t then - t[#t+1] = "last: not done, no content" - end - elseif t then - t[#t+1] = "last: not done, no vbox" - end - end - if method[v_minheight] then - ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht - if t then - t[#t+1] = formatters["minheight: %p"](ch) - end - elseif method[v_maxheight] then - ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht - if t then - t[#t+1] = formatters["maxheight: %p"](ch) - end - else - ch = plusht - if t then - t[#t+1] = formatters["set height: %p"](ch) - end - end - if method[v_mindepth] then - cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp - if t then - t[#t+1] = formatters["mindepth: %p"](cd) - end - elseif method[v_maxdepth] then - cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp - if t then - t[#t+1] = formatters["maxdepth: %p"](cd) - end - else - cd = plusdp - if t then - t[#t+1] = formatters["set depth: %p"](cd) - end - end - if method[v_top] then - ch = ch + tlines * snaphtdp - if t then - t[#t+1] = formatters["top height: %p"](ch) - end - end - if method[v_bottom] then - cd = cd + blines * snaphtdp - if t then - t[#t+1] = formatters["bottom depth: %p"](cd) - end - end - local offset = method[v_offset] - if offset then - -- we need to set the attr - if t then - local wd, ht, dp = getwhd(current) - t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) - end - local shifted = hpack_node(getlist(current)) - setshift(shifted,offset) - setlist(current,shifted) - if t then - local wd, ht, dp = getwhd(current) - t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) - end - setattr(shifted,a_snapmethod,0) - setattr(current,a_snapmethod,0) - end - if not height then - setheight(current,ch) - if t then - t[#t+1] = formatters["forced height: %p"](ch) - end - end - if not depth then - setdepth(current,cd) - if t then - t[#t+1] = formatters["forced depth: %p"](cd) - end - end - local lines = (ch+cd)/snaphtdp - if t then - local original = (h+d)/snaphtdp - local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth")) - t[#t+1] = formatters["final lines : %p -> %p (%p)"](original,lines,whatever) - t[#t+1] = formatters["final height: %p -> %p"](h,ch) - t[#t+1] = formatters["final depth : %p -> %p"](d,cd) - end --- todo: --- --- if h < 0 or d < 0 then --- h = 0 --- d = 0 --- end - if t then - report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t) - end - if not method[v_split] then - -- so extra will not be compensated at the top of a page - extra = 0 - end - return h, d, ch, cd, lines, extra -end - -local categories = { - [0] = "discard", - [1] = "largest", - [2] = "force", - [3] = "penalty", - [4] = "add", - [5] = "disable", - [6] = "nowhite", - [7] = "goback", - [8] = "packed", - [9] = "overlay", - [10] = "enable", - [11] = "notopskip", -} - -categories = allocate(table.swapped(categories,categories)) -vspacing.categories = categories - -function vspacing.tocategories(str) - local t = { } - for s in gmatch(str,"[^, ]") do -- use lpeg instead - local n = tonumber(s) - if n then - t[categories[n]] = true - else - t[b] = true - end - end - return t -end - -function vspacing.tocategory(str) -- can be optimized - if type(str) == "string" then - return set.tonumber(vspacing.tocategories(str)) - else - return set.tonumber({ [categories[str]] = true }) - end -end - -vspacingdata.map = vspacingdata.map or { } -- allocate ? -vspacingdata.skip = vspacingdata.skip or { } -- allocate ? - -storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map") -storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip") - -do - - local P, C, R, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs - - vspacing.fixed = false - - local map = vspacingdata.map - local skip = vspacingdata.skip - - local sign = S("+-")^0 - local multiplier = C(sign * R("09")^1) * P("*") - local singlefier = Cs(sign * Cc(1)) - local separator = S(", ") - local category = P(":") * C((1-separator)^1) - local keyword = C((1-category-separator)^1) - local splitter = (multiplier + Cc(1)) * keyword * (category + Cc(false)) - - local k_fixed = variables.fixed - local k_flexible = variables.flexible - local k_category = "category" - local k_penalty = "penalty" - local k_order = "order" - - function vspacing.setmap(from,to) - map[from] = to - end - - function vspacing.setskip(key,value,grid) - if value ~= "" then - if grid == "" then grid = value end - skip[key] = { value, grid } - end - end - - local expandmacro = token.expand_macro - -- local runlocal = tex.runlocal - -- local setmacro = tokens.setters.macro - -- local settoks = tex.settoks - local toscaled = tex.toscaled - - local setattrs = nuts.setattrs - - local b_done = false - local b_packed = false - - local b_amount = 0 - local b_stretch = 0 - local b_shrink = 0 - local b_category = false - local b_penalty = false - local b_order = false - local b_fixed = false - local b_grid = false - - local pattern = nil - - local packed = categories.packed - - local gluefactor = .25 - - local ctx_ignoreparskip = context.core.ignoreparskip - - local function before() - b_amount = 0 - b_stretch = 0 - b_shrink = 0 - b_category = 1 - b_penalty = false - b_order = false - b_fixed = b_grid - end - - local function after() - if fixed then - b_stretch = 0 - b_shrink = 0 - else - b_stretch = gluefactor * b_amount - b_shrink = gluefactor * b_amount - end - end - - -- use a cache for predefined ones - - local function inject() - local n = new_glue(b_amount,b_stretch,b_shrink) - setattrs(n,false,a_skipcategory,b_category,a_skippenalty,b_penalty,a_skiporder,b_order or 1) - write_node(n) - end - - local function flush() - after() - if b_done then - inject() - b_done = false - end - before() - end - - -- local cmd = token.create("vspacingfromtempstring") - -- local cmd = token.create("vspacingpredefinedvalue") -- not yet known - - local function handler(multiplier, keyword, detail) - if not keyword then - report_vspacing("unknown directive %a",s) - else - local mk = map[keyword] - if mk then - lpegmatch(pattern,mk) - elseif keyword == k_fixed then - b_fixed = true - elseif keyword == k_flexible then - b_flexible = false - elseif keyword == k_category then - local category = tonumber(detail) - if category == packed then - b_packed = true - elseif category then - b_category = category - b_done = true - flush() - end - elseif keyword == k_order and detail then - local order = tonumber(detail) - if order then - b_order = order - end - elseif keyword == k_penalty and detail then - local penalty = tonumber(detail) - if penalty then - flush() - b_done = true - b_category = 3 - b_penalty = penalty - flush() - end - else - local amount, stretch, shrink - multiplier = tonumber(multiplier) or 1 - local sk = skip[keyword] - if sk then - -- multiplier, keyword - -- best, for now, todo: runlocal with arguments - expandmacro("vspacingpredefinedvalue",true,keyword) - -- expandmacro(cmd,true,keyword) - -- setmacro("tempstring",keyword) - -- runlocal(cmd) - -- nicest - -- runlocal(cache[keyword]) - -- fast - -- settoks("scratchtoks",keyword) - -- runlocal("vspacingfromscratchtoks") - -- middleground - -- setmacro("tempstring",keyword) - -- runlocal(ctx_vspacingfromtempstring) - -- - amount, stretch, shrink = texgetglue("scratchskip") - if not stretch then - stretch = 0 - end - if not shrink then - shrink = 0 - end - if stretch == 0 and shrink == 0 then - stretch = gluefactor * amount -- always unless grid - shrink = stretch -- always unless grid - end - else -- no check, todo: parse plus and minus - amount = toscaled(keyword) - stretch = gluefactor * amount -- always unless grid - shrink = stretch -- always unless grid - end - -- we look at fixed later - b_amount = b_amount + multiplier * amount - b_stretch = b_stretch + multiplier * stretch - b_shrink = b_shrink + multiplier * shrink - b_done = true - end - end - end - - -- alternatively we can make a table and have a keyword -> split cache but this is probably - -- not really a bottleneck - - local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler - pattern = (splitter + separator^1)^0 - - function vspacing.inject(grid,str) - if trace_vspacing then - -- ctx_pushlogger(report_vspacing) - end - b_done = false - b_packed = false - b_grid = gridsnapping - before() - lpegmatch(pattern,str) - after() - if b_done then - inject() - end - if b_packed then - ctx_ignoreparskip() - end - if trace_vspacing then - -- ctx_poplogger() - end - end - - function vspacing.injectpenalty(penalty) - local n = new_glue() - setattrs(n,false,a_skipcategory,categories.penalty,a_skippenalty,penalty,a_skiporder,1) - write_node(n) - end - - function vspacing.injectskip(amount) - local n = new_glue(amount) - setattrs(n,false,a_skipcategory,categories.largest,a_skippenalty,false,a_skiporder,1) - write_node(n) - end - - function vspacing.injectdisable(amount) - local n = new_glue() - setattrs(n,false,a_skipcategory,categories.disable,a_skippenalty,false,a_skiporder,1) - write_node(n) - end - -end - --- implementation - --- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display - -function vspacing.snapbox(n,how) - local sv = snapmethods[how] - if sv then - local box = getbox(n) - local list = getlist(box) - if list then - local s = getattr(list,a_snapmethod) - if s == 0 then - if trace_vsnapping then - -- report_snapper("box list not snapped, already done") - end - else - local wd, ht, dp = getwhd(box) - if false then -- todo: already_done - -- assume that the box is already snapped - if trace_vsnapping then - report_snapper("box list already snapped at (%p,%p): %s", - ht,dp,listtoutf(list)) - end - else - local h, d, ch, cd, lines, extra = snap_hlist("box",box,sv,ht,dp) - setprop(box,"snapper",{ - ht = h, - dp = d, - ch = ch, - cd = cd, - extra = extra, - current = current, - }) - setwhd(box,wd,ch,cd) - if trace_vsnapping then - report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", - h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) - end - setattr(box,a_snapmethod,0) -- - setattr(list,a_snapmethod,0) -- yes or no - end - end - end - end -end - --- I need to figure out how to deal with the prevdepth that crosses pages. In fact, --- prevdepth is often quite interfering (even over a next paragraph) so I need to --- figure out a trick. Maybe use something other than a rule. If we visualize we'll --- see the baselineskip in action: --- --- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page --- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page --- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page - --- We can register and copy the rule instead. - -do - - local insert_node_after = nuts.insert_after - local insert_node_before = nuts.insert_before - - local abovedisplayskip_code = gluecodes.abovedisplayskip - local belowdisplayskip_code = gluecodes.belowdisplayskip - local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip - local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip - - local w, h, d = 0, 0, 0 - ----- w, h, d = 100*65536, 65536, 65536 - - local trace_list = { } - local tracing_info = { } - local before = "" - local after = "" - - local function nodes_to_string(head) - local current = head - local t = { } - while current do - local id = getid(current) - local ty = nodecodes[id] - if id == penalty_code then - t[#t+1] = formatters["%s:%s"](ty,getpenalty(current)) - elseif id == glue_code then - t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current)) - elseif id == kern_code then - t[#t+1] = formatters["%s:%p"](ty,getkern(current)) - else - t[#t+1] = ty - end - current = getnext(current) - end - return concat(t," + ") - end - - local function reset_tracing(head) - trace_list, tracing_info, before, after = { }, false, nodes_to_string(head), "" - end - - local function trace_skip(str,sc,so,sp,data) - trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getwidth(data), sc or "-", so or "-", sp or "-") } - tracing_info = true - end - - local function trace_natural(str,data) - trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getwidth(data)) } - tracing_info = true - end - - local function trace_info(message, where, what) - trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) } - end - - local function trace_node(what) - local nt = nodecodes[getid(what)] - local tl = trace_list[#trace_list] - if tl and tl[1] == "node" then - trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } - else - trace_list[#trace_list+1] = { "node", nt } - end - end - - local function show_tracing(head) - if tracing_info then - after = nodes_to_string(head) - for i=1,#trace_list do - local tag, text = unpack(trace_list[i]) - if tag == "info" then - report_collapser(text) - else - report_collapser(" %s: %s",tag,text) - end - end - report_collapser("before: %s",before) - report_collapser("after : %s",after) - end - end - - local function trace_done(str,data) - if getid(data) == penalty_code then - trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getpenalty(data)) } - else - trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getwidth(data)) } - end - tracing_info = true - end - - local function forced_skip(head,current,width,where,trace) -- looks old ... we have other tricks now - if head == current then - if getsubtype(head) == baselineskip_code then - width = width - getwidth(head) - end - end - if width == 0 then - -- do nothing - elseif where == "after" then - head, current = insert_node_after(head,current,new_rule(w,h,d)) - head, current = insert_node_after(head,current,new_kern(width)) - head, current = insert_node_after(head,current,new_rule(w,h,d)) - else - local c = current - head, current = insert_node_before(head,current,new_rule(w,h,d)) - head, current = insert_node_before(head,current,new_kern(width)) - head, current = insert_node_before(head,current,new_rule(w,h,d)) - current = c - end - if trace then - report_vspacing("inserting forced skip of %p",width) - end - return head, current - end - - -- penalty only works well when before skip - - local discard = categories.discard - local largest = categories.largest - local force = categories.force - local penalty = categories.penalty - local add = categories.add - local disable = categories.disable - local nowhite = categories.nowhite - local goback = categories.goback - local packed = categories.packed - local overlay = categories.overlay - local enable = categories.enable - local notopskip = categories.notopskip - - -- [whatsits][hlist][glue][glue][penalty] - - local special_penalty_min = 32250 - local special_penalty_max = 35000 - local special_penalty_xxx = 0 - - -- this is rather messy and complex: we want to make sure that successive - -- header don't break but also make sure that we have at least a decent - -- break when we have succesive ones (often when testing) - - -- todo: mark headers as such so that we can recognize them - - local specialmethods = { } - local specialmethod = 1 - - specialmethods[1] = function(pagehead,pagetail,start,penalty) - -- - if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then - return - end - local current = pagetail - -- - -- nodes.showsimplelist(pagehead,0) - -- - if trace_specials then - report_specials("checking penalty %a",penalty) - end - while current do - local id = getid(current) - if id == penalty_code then - local p = properties[current] - if p then - local p = p.special_penalty - if not p then - if trace_specials then - report_specials(" regular penalty, continue") - end - elseif p == penalty then - if trace_specials then - report_specials(" context penalty %a, same level, overloading",p) - end - return special_penalty_xxx - elseif p > special_penalty_min and p < special_penalty_max then - if penalty < p then - if trace_specials then - report_specials(" context penalty %a, lower level, overloading",p) - end - return special_penalty_xxx - else - if trace_specials then - report_specials(" context penalty %a, higher level, quitting",p) - end - return - end - elseif trace_specials then - report_specials(" context penalty %a, higher level, continue",p) - end - else - local p = getpenalty(current) - if p < 10000 then - -- assume some other mechanism kicks in so we seem to have content - if trace_specials then - report_specials(" regular penalty %a, quitting",p) - end - break - else - if trace_specials then - report_specials(" regular penalty %a, continue",p) - end - end - end - end - current = getprev(current) - end - -- none found, so no reson to be special - if trace_specials then - if pagetail then - report_specials(" context penalty, discarding, nothing special") - else - report_specials(" context penalty, discarding, nothing preceding") - end - end - return special_penalty_xxx - end - - -- This will be replaced after 0.80+ when we have a more robust look-back and - -- can look at the bigger picture. - - -- todo: look back and when a special is there before a list is seen penalty keep ut - - -- we now look back a lot, way too often - - -- userskip - -- lineskip - -- baselineskip - -- parskip - -- abovedisplayskip - -- belowdisplayskip - -- abovedisplayshortskip - -- belowdisplayshortskip - -- topskip - -- splittopskip - - -- we could inject a vadjust to force a recalculation .. a mess - -- - -- So, the next is far from robust and okay but for the moment this overlaying - -- has to do. Always test this with the examples in spac-ver.mkvi! - - local function snap_topskip(current,method) - local w = getwidth(current) - setwidth(current,0) - return w, 0 - end - - local function check_experimental_overlay(head,current) - local p = nil - local c = current - local n = nil - local function overlay(p,n,mvl) - local p_wd, p_ht, p_dp = getwhd(p) - local n_wd, n_ht, n_dp = getwhd(n) - local skips = 0 - -- - -- We deal with this at the tex end .. we don't see spacing .. enabling this code - -- is probably harmless but then we need to test it. - -- - -- we could calculate this before we call - -- - -- problem: prev list and next list can be unconnected - -- - local c = getnext(p) - local l = c - while c and c ~= n do - local id = getid(c) - if id == glue_code then - skips = skips + getwidth(c) - elseif id == kern_code then - skips = skips + getkern(c) - end - l = c - c = getnext(c) - end - local c = getprev(n) - while c and c ~= n and c ~= l do - local id = getid(c) - if id == glue_code then - skips = skips + getwidth(c) - elseif id == kern_code then - skips = skips + getkern(c) - end - c = getprev(c) - end - -- - local delta = n_ht + skips + p_dp - texsetdimen("global","d_spac_overlay",-delta) -- for tracing - -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak - local k = new_kern(-delta) - head = insert_node_before(head,n,k) - if n_ht > p_ht then - local k = new_kern(n_ht-p_ht) - head = insert_node_before(head,p,k) - end - if trace_vspacing then - report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta) - end - return remove_node(head,current,true) - end - - -- goto next line - while c do - local id = getid(c) - if id == glue_code or id == penalty_code or id == kern_code then - -- skip (actually, remove) - c = getnext(c) - elseif id == hlist_code then - n = c - break - else - break - end - end - if n then - -- we have a next line, goto prev line - c = current - while c do - local id = getid(c) - if id == glue_code or id == penalty_code then -- kern ? - c = getprev(c) - elseif id == hlist_code then - p = c - break - else - break - end - end - if not p then - if a_snapmethod == a_snapvbox then - -- quit, we're not on the mvl - else - -- inefficient when we're at the end of a page - local c = tonut(texlists.page_head) - while c and c ~= n do - local id = getid(c) - if id == hlist_code then - p = c - end - c = getnext(c) - end - if p and p ~= n then - return overlay(p,n,true) - end - end - elseif p ~= n then - return overlay(p,n,false) - end - end - -- in fact, we could try again later ... so then no remove (a few tries) - return remove_node(head,current,true) - end - - local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail - if trace then - reset_tracing(head) - end - local current = head - local oldhead = head - local glue_order = 0 - local glue_data - local force_glue = false - local penalty_order = 0 - local penalty_data - local natural_penalty - local special_penalty - local parskip - local ignore_parskip = false - local ignore_following = false - local ignore_whitespace = false - local keep_together = false - local lastsnap - local pagehead - local pagetail - -- - -- todo: keep_together: between headers - -- - local function getpagelist() - if not pagehead then - pagehead = texlists.page_head - if pagehead then - pagehead = tonut(pagehead) - pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet - end - end - end - -- - local function compensate(n) - local g = 0 - while n and getid(n) == glue_code do - g = g + getwidth(n) - n = getnext(n) - end - if n then - local p = getprop(n,"snapper") - if p then - local extra = p.extra - if extra and extra < 0 then -- hm, extra can be unset ... needs checking - local h = p.ch -- getheight(n) - -- maybe an extra check - -- if h - extra < g then - setheight(n,h-2*extra) - p.extra = 0 - if trace_vsnapping then - report_snapper("removed extra space at top: %p",extra) - end - -- end - end - end - return n - end - end - -- - local function removetopsnap() - getpagelist() - if pagehead then - local n = pagehead and compensate(pagehead) - if n and n ~= pagetail then - local p = getprop(pagetail,"snapper") - if p then - local e = p.extra - if e and e < 0 then - local t = texget("pagetotal") - if t > 0 then - local g = texget("pagegoal") -- 1073741823 is signal - local d = g - t - if d < -e then - local penalty = new_penalty(1000000) - setlink(penalty,head) - head = penalty - report_snapper("force pagebreak due to extra space at bottom: %p",e) - end - end - end - end - end - elseif head then - compensate(head) - end - end - -- - local function getavailable() - getpagelist() - if pagehead then - local t = texget("pagetotal") - if t > 0 then - local g = texget("pagegoal") - return g - t - end - end - return false - end - -- - local function flush(why) - if penalty_data then - local p = new_penalty(penalty_data) - if trace then - trace_done("flushed due to " .. why,p) - end - if penalty_data >= 10000 then -- or whatever threshold? - local prev = getprev(current) - if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue - -- tricky case: spacing/grid-007.tex: glue penalty glue - head = insert_node_before(head,prev,p) - else - head = insert_node_before(head,current,p) - end - else - head = insert_node_before(head,current,p) - end - -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then - local props = properties[p] - if props then - props.special_penalty = special_penalty or penalty_data - else - properties[p] = { - special_penalty = special_penalty or penalty_data - } - end - -- end - end - if glue_data then - if force_glue then - if trace then - trace_done("flushed due to forced " .. why,glue_data) - end - head = forced_skip(head,current,getwidth(glue_data,width),"before",trace) - flush_node(glue_data) - else - local width, stretch, shrink = getglue(glue_data) - if width ~= 0 then - if trace then - trace_done("flushed due to non zero " .. why,glue_data) - end - head = insert_node_before(head,current,glue_data) - elseif stretch ~= 0 or shrink ~= 0 then - if trace then - trace_done("flushed due to stretch/shrink in" .. why,glue_data) - end - head = insert_node_before(head,current,glue_data) - else - -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w) - flush_node(glue_data) - end - end - end - - if trace then - trace_node(current) - end - glue_order, glue_data, force_glue = 0, nil, false - penalty_order, penalty_data, natural_penalty = 0, nil, nil - parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false - end - -- - if trace_vsnapping then - report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p", - texgetdimen("globalbodyfontstrutheight"), - texgetdimen("globalbodyfontstrutdepth"), - texgetdimen("bodyfontstrutheight"), - texgetdimen("bodyfontstrutdepth") - ) - end - if trace then - trace_info("start analyzing",where,what) - end - if snap and where == "page" then - removetopsnap() - end - while current do - local id = getid(current) - if id == hlist_code or id == vlist_code then - -- needs checking, why so many calls - if snap then - lastsnap = nil - local list = getlist(current) - local s = getattr(current,a_snapmethod) - if not s then - -- if trace_vsnapping then - -- report_snapper("mvl list not snapped") - -- end - elseif s == 0 then - if trace_vsnapping then - report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list)) - end - else - local sv = snapmethods[s] - if sv then - -- check if already snapped - local done = list and already_done(id,list,a_snapmethod) - if done then - -- assume that the box is already snapped - if trace_vsnapping then - local w, h, d = getwhd(current) - report_snapper("mvl list already snapped at (%p,%p): %s",h,d,listtoutf(list)) - end - else - local h, d, ch, cd, lines, extra = snap_hlist("mvl",current,sv,false,false) - lastsnap = { - ht = h, - dp = d, - ch = ch, - cd = cd, - extra = extra, - current = current, - } - setprop(current,"snapper",lastsnap) - if trace_vsnapping then - report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", - nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list)) - end - end - elseif trace_vsnapping then - report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) - end - setattr(current,a_snapmethod,0) - end - else - -- - end - -- tex.prevdepth = 0 - flush("list") - current = getnext(current) - elseif id == penalty_code then - -- natural_penalty = getpenalty(current) - -- if trace then - -- trace_done("removed penalty",current) - -- end - -- head, current = remove_node(head,current,true) - current = getnext(current) - elseif id == kern_code then - if snap and trace_vsnapping and getkern(current) ~= 0 then - report_snapper("kern of %p kept",getkern(current)) - end - flush("kern") - current = getnext(current) - elseif id == glue_code then - local subtype = getsubtype(current) - if subtype == userskip_code then - local sc, so, sp = getattrs(current,a_skipcategory,a_skiporder,a_skippenalty) - if not so then - so = 1 -- the others have no default value - end - if sp and sc == penalty then - if where == "page" then - getpagelist() - local p = specialmethods[specialmethod](pagehead,pagetail,current,sp) - if p then - -- todo: other tracer - -- - -- if trace then - -- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod) - -- end - special_penalty = sp - sp = p - end - end - if not penalty_data then - penalty_data = sp - elseif penalty_order < so then - penalty_order, penalty_data = so, sp - elseif penalty_order == so and sp > penalty_data then - penalty_data = sp - end - if trace then - trace_skip("penalty in skip",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - elseif not sc then -- if not sc then - if glue_data then - if trace then - trace_done("flush",glue_data) - end - head = insert_node_before(head,current,glue_data) - if trace then - trace_natural("natural",current) - end - current = getnext(current) - glue_data = nil - else - -- not look back across head - -- todo: prev can be whatsit (latelua) - local previous = getprev(current) - if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then - local pwidth, pstretch, pshrink, pstretch_order, pshrink_order = getglue(previous) - local cwidth, cstretch, cshrink, cstretch_order, cshrink_order = getglue(current) - if pstretch_order == 0 and pshrink_order == 0 and cstretch_order == 0 and cshrink_order == 0 then - setglue(previous,pwidth + cwidth, pstretch + cstretch, pshrink + cshrink) - if trace then - trace_natural("removed",current) - end - head, current = remove_node(head,current,true) - if trace then - trace_natural("collapsed",previous) - end - else - if trace then - trace_natural("filler",current) - end - current = getnext(current) - end - else - if trace then - trace_natural("natural (no prev)",current) - end - current = getnext(current) - end - end - glue_order = 0 - elseif sc == disable or sc == enable then - local next = getnext(current) - if next then - ignore_following = sc == disable - if trace then - trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - else - current = next - end - elseif sc == packed then - if trace then - trace_skip("packed",sc,so,sp,current) - end - -- can't happen ! - head, current = remove_node(head,current,true) - elseif sc == nowhite then - local next = getnext(current) - if next then - ignore_whitespace = true - head, current = remove_node(head,current,true) - else - current = next - end - elseif sc == discard then - if trace then - trace_skip("discard",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - elseif sc == overlay then - -- todo (overlay following line over previous - if trace then - trace_skip("overlay",sc,so,sp,current) - end - -- beware: head can actually be after the affected nodes as - -- we look back ... some day head will the real head - head, current = check_experimental_overlay(head,current,a_snapmethod) - elseif ignore_following then - if trace then - trace_skip("disabled",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - elseif not glue_data then - if trace then - trace_skip("assign",sc,so,sp,current) - end - glue_order = so - head, current, glue_data = remove_node(head,current) - elseif glue_order < so then - if trace then - trace_skip("force",sc,so,sp,current) - end - glue_order = so - flush_node(glue_data) - head, current, glue_data = remove_node(head,current) - elseif glue_order == so then - -- is now exclusive, maybe support goback as combi, else why a set - if sc == largest then - local cw = getwidth(current) - local gw = getwidth(glue_data) - if cw > gw then - if trace then - trace_skip("largest",sc,so,sp,current) - end - flush_node(glue_data) - head, current, glue_data = remove_node(head,current) - else - if trace then - trace_skip("remove smallest",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - end - elseif sc == goback then - if trace then - trace_skip("goback",sc,so,sp,current) - end - flush_node(glue_data) - head, current, glue_data = remove_node(head,current) - elseif sc == force then - -- last one counts, some day we can provide an accumulator and largest etc - -- but not now - if trace then - trace_skip("force",sc,so,sp,current) - end - flush_node(glue_data) - head, current, glue_data = remove_node(head,current) - elseif sc == penalty then - if trace then - trace_skip("penalty",sc,so,sp,current) - end - flush_node(glue_data) - glue_data = nil - head, current = remove_node(head,current,true) - elseif sc == add then - if trace then - trace_skip("add",sc,so,sp,current) - end - local cwidth, cstretch, cshrink = getglue(current) - local gwidth, gstretch, gshrink = getglue(glue_data) - setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink) - -- toto: order - head, current = remove_node(head,current,true) - else - if trace then - trace_skip("unknown",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - end - else - if trace then - trace_skip("unknown",sc,so,sp,current) - end - head, current = remove_node(head,current,true) - end - if sc == force then - force_glue = true - end - elseif subtype == lineskip_code then - if snap then - local s = getattr(current,a_snapmethod) - if s and s ~= 0 then - setattr(current,a_snapmethod,0) - setwidth(current,0) - if trace_vsnapping then - report_snapper("lineskip set to zero") - end - else - if trace then - trace_skip("lineskip",sc,so,sp,current) - end - flush("lineskip") - end - else - if trace then - trace_skip("lineskip",sc,so,sp,current) - end - flush("lineskip") - end - current = getnext(current) - elseif subtype == baselineskip_code then - if snap then - local s = getattr(current,a_snapmethod) - if s and s ~= 0 then - setattr(current,a_snapmethod,0) - setwidth(current,0) - if trace_vsnapping then - report_snapper("baselineskip set to zero") - end - else - if trace then - trace_skip("baselineskip",sc,so,sp,current) - end - flush("baselineskip") - end - else - if trace then - trace_skip("baselineskip",sc,so,sp,current) - end - flush("baselineskip") - end - current = getnext(current) - elseif subtype == parskip_code then - -- parskip always comes later - if ignore_whitespace then - if trace then - trace_natural("ignored parskip",current) - end - head, current = remove_node(head,current,true) - elseif glue_data then - local w = getwidth(current) - if w ~= 0 and w > getwidth(glue_data) then -flush_node(glue_data) - glue_data = current - if trace then - trace_natural("taking parskip",current) - end - head, current = remove_node(head,current) - else - if trace then - trace_natural("removed parskip",current) - end - head, current = remove_node(head,current,true) - end - else - if trace then - trace_natural("honored parskip",current) - end - head, current, glue_data = remove_node(head,current) - end - elseif subtype == topskip_code or subtype == splittopskip_code then - local next = getnext(current) - if next and getattr(next,a_skipcategory) == notopskip then - nuts.setglue(current) -- zero - end - if snap then - local s = getattr(current,a_snapmethod) - if s and s ~= 0 then - setattr(current,a_snapmethod,0) - local sv = snapmethods[s] - local w, cw = snap_topskip(current,sv) - if trace_vsnapping then - report_snapper("topskip snapped from %p to %p for %a",w,cw,where) - end - else - if trace then - trace_skip("topskip",sc,so,sp,current) - end - flush("topskip") - end - else - if trace then - trace_skip("topskip",sc,so,sp,current) - end - flush("topskip") - end - current = getnext(current) - elseif subtype == abovedisplayskip_code and remove_math_skips then - -- - if trace then - trace_skip("above display skip (normal)",sc,so,sp,current) - end - flush("above display skip (normal)") - current = getnext(current) - -- - elseif subtype == belowdisplayskip_code and remove_math_skips then - -- - if trace then - trace_skip("below display skip (normal)",sc,so,sp,current) - end - flush("below display skip (normal)") - current = getnext(current) - -- - elseif subtype == abovedisplayshortskip_code and remove_math_skips then - -- - if trace then - trace_skip("above display skip (short)",sc,so,sp,current) - end - flush("above display skip (short)") - current = getnext(current) - -- - elseif subtype == belowdisplayshortskip_code and remove_math_skips then - -- - if trace then - trace_skip("below display skip (short)",sc,so,sp,current) - end - flush("below display skip (short)") - current = getnext(current) - -- - else -- other glue - if snap and trace_vsnapping then - local w = getwidth(current) - if w ~= 0 then - report_snapper("glue %p of type %a kept",w,gluecodes[subtype]) - end - end - if trace then - trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) - end - flush("some glue") - current = getnext(current) - end - else - flush(trace and formatters["node with id %a"](id) or "other node") - current = getnext(current) - end - end - if trace then - trace_info("stop analyzing",where,what) - end - -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then - -- penalty_data = natural_penalty - -- end - if trace and (glue_data or penalty_data) then - trace_info("start flushing",where,what) - end - local tail - if penalty_data then - tail = find_node_tail(head) - local p = new_penalty(penalty_data) - if trace then - trace_done("result",p) - end - setlink(tail,p) - -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then - local props = properties[p] - if props then - props.special_penalty = special_penalty or penalty_data - else - properties[p] = { - special_penalty = special_penalty or penalty_data - } - end - -- end - end - if glue_data then - if not tail then tail = find_node_tail(head) end - if trace then - trace_done("result",glue_data) - end - if force_glue then - head, tail = forced_skip(head,tail,getwidth(glue_data),"after",trace) - flush_node(glue_data) - glue_data = nil - elseif tail then - setlink(tail,glue_data) -setnext(glue_data) - else - head = glue_data - end - texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler - end - if trace then - if glue_data or penalty_data then - trace_info("stop flushing",where,what) - end - show_tracing(head) - if oldhead ~= head then - trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) - end - end - return head - end - - local stackhead, stacktail, stackhack = nil, nil, false - - local function report(message,where,lst) - if lst and where then - report_vspacing(message,where,count_nodes(lst,true),nodeidstostring(lst)) - else - report_vspacing(message,count_nodes(lst,true),nodeidstostring(lst)) - end - end - - -- ugly code: we get partial lists (check if this stack is still okay) ... and we run - -- into temp nodes (sigh) - - local forceflush = false - - function vspacing.pagehandler(newhead,where) - if newhead then - local newtail = find_node_tail(newhead) -- best pass that tail, known anyway - local flush = false - stackhack = true -- todo: only when grid snapping once enabled - -- todo: fast check if head = tail - for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes - if id ~= glue_code then - flush = true - elseif subtype == userskip_code then - if getattr(n,a_skipcategory) then - stackhack = true - else - flush = true - end - elseif subtype == parskip_code then - -- if where == new_graf then ... end - if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then - -- texsetcount("c_spac_vspacing_ignore_parskip",0) - setglue(n) - -- maybe removenode - end - end - end - texsetcount("c_spac_vspacing_ignore_parskip",0) - - if forceflush then - forceflush = false - flush = true - end - - if flush then - if stackhead then - if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end - setlink(stacktail,newhead) - newhead = stackhead - stackhead = nil - stacktail = nil - end - if stackhack then - stackhack = false - if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end - newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) - else - if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end - end - return newhead - else - if stackhead then - if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end - setlink(stacktail,newhead) - else - if trace_collect_vspacing then report("%s > storing %s nodes in stack (initial): %s",where,newhead) end - stackhead = newhead - end - stacktail = newtail - end - end - return nil - end - - function vspacing.pageoverflow() - local h = 0 - if stackhead then - for n, id in nextnode, stackhead do - if id == glue_code then - h = h + getwidth(n) - elseif id == kern_code then - h = h + getkern(n) - end - end - end - return h - end - - function vspacing.forcepageflush() - forceflush = true - end - - local ignore = table.tohash { - "split_keep", - "split_off", - -- "vbox", - } - - function vspacing.vboxhandler(head,where) - if head and not ignore[where] and getnext(head) then - if getnext(head) then -- what if a one liner and snapping? - head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return head - end - end - return head - end - - function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod - local box = getbox(n) - if box then - local list = getlist(box) - if list then - list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod) - if aslist then - setlist(box,list) -- beware, dimensions of box are wrong now - else - setlist(box,vpack_node(list)) - end - end - end - end - -end - --- This one is needed to prevent bleeding of prevdepth to the next page --- which doesn't work well with forced skips. I'm not that sure if the --- following is a good way out. - -do - - local outer = texnest[0] - - local enabled = true - local trace = false - local report = logs.reporter("vspacing") - - trackers.register("vspacing.synchronizepage",function(v) - trace = v - end) - - directives.register("vspacing.synchronizepage",function(v) - enabled = v - end) - - local ignoredepth = -65536000 - - -- A previous version analyzed the number of lines moved to the next page in - -- synchronizepage because prevgraf is unreliable in that case. However, we cannot - -- tweak that parameter because it is also used in postlinebreak and hangafter, so - -- there is a danger for interference. Therefore we now do it dynamically. - - -- We can also support other lists but there prevgraf probably is ok. - - function vspacing.getnofpreviouslines(head) - if enabled then - if not thead then - head = texlists.page_head - end - local noflines = 0 - if head then - local tail = find_node_tail(tonut(head)) - while tail do - local id = getid(tail) - if id == hlist_code then - if getsubtype(tail) == linelist_code then - noflines = noflines + 1 - else - break - end - elseif id == vlist_code then - break - elseif id == glue_code then - local subtype = getsubtype(tail) - if subtype == baselineskip_code or subtype == lineskip_code then - -- we're ok - elseif subtype == parskip_code then - if getwidth(tail) > 0 then - break - else - -- we assume we're ok - end - end - elseif id == penalty_code then - -- we're probably ok - elseif id == rule_code or id == kern_code then - break - else - -- ins, mark, boundary, whatsit - end - tail = getprev(tail) - end - end - return noflines - end - end - - interfaces.implement { - name = "getnofpreviouslines", - public = true, - actions = vspacing.getnofpreviouslines, - } - - function vspacing.synchronizepage() - if enabled then - if trace then - local newdepth = outer.prevdepth - local olddepth = newdepth - if not texlists.page_head then - newdepth = ignoredepth - texset("prevdepth",ignoredepth) - outer.prevdepth = ignoredepth - end - report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth) - -- report("list %s",nodes.idsandsubtypes(head)) - else - if not texlists.page_head then - texset("prevdepth",ignoredepth) - outer.prevdepth = ignoredepth - end - end - end - end - - local trace = false - local last = nil - local vmode_code = tex.modelevels.vertical - local temp_code = nodecodes.temp - local getnest = tex.getnest - local getlist = tex.getlist - - trackers.register("vspacing.forcestrutdepth",function(v) trace = v end) - - -- abs : negative is inner - - function vspacing.checkstrutdepth(depth) - local nest = getnest() - if abs(nest.mode) == vmode_code and nest.head then - local tail = nest.tail - local id = tail.id - if id == hlist_code then - if tail.depth < depth then - tail.depth = depth - end - nest.prevdepth = depth - elseif id == temp_code and getnest("ptr") == 0 then - local head = getlist("page_head") - if head then - tail = nodes.tail(head) - if tail and tail.id == hlist_code then - if tail.depth < depth then - tail.depth = depth - end - nest.prevdepth = depth - -- only works in lmtx - texset("pagedepth",depth) - end - end - end - end - end - - interfaces.implement { - name = "checkstrutdepth", - arguments = "dimension", - actions = vspacing.checkstrutdepth, - } - - function vspacing.forcestrutdepth(n,depth,trace_mode,plus) - local box = texgetbox(n) - if box then - box = tonut(box) - local head = getlist(box) - if head then - local tail = find_node_tail(head) - if tail then - if getid(tail) == hlist_code then - local dp = getdepth(tail) - if dp < depth then - setdepth(tail,depth) - outer.prevdepth = depth - if trace or trace_mode > 0 then - nuts.setvisual(tail,"depth") - end - end - end - last = nil - if plus then - -- penalty / skip ... - local height = 0 - local sofar = 0 - local same = false - local seen = false - local list = { } - last = nil - while tail do - local id = getid(tail) - if id == hlist_code or id == vlist_code then - local w, h, d = getwhd(tail) - height = height + h + d + sofar - sofar = 0 - last = tail - elseif id == kern_code then - sofar = sofar + getkern(tail) - elseif id == glue_code then - if seen then - sofar = sofar + getwidth(tail) - seen = false - else - break - end - elseif id == penalty_code then - local p = getpenalty(tail) - if p >= 10000 then - same = true - seen = true - else - break - end - else - break - end - tail = getprev(tail) - end - texsetdimen("global","d_spac_prevcontent",same and height or 0) - end - end - end - end - end - - function vspacing.pushatsame() - -- needs better checking ! - if last then -- setsplit - nuts.setnext(getprev(last)) - nuts.setprev(last) - end - end - - function vspacing.popatsame() - -- needs better checking ! - nuts.write(last) - end - -end - --- interface - -do - - -- old variant - --- implement { --- name = "vspacing", --- actions = vspacing.analyze, --- scope = "private", --- arguments = "string" --- } - - -- new variant - - interfaces.implement { - name = "injectvspacing", - actions = vspacing.inject, - arguments = { "integer", "string" }, - } - - interfaces.implement { - name = "injectvpenalty", - actions = vspacing.injectpenalty, - arguments = "integer", - } - - interfaces.implement { - name = "injectvskip", - actions = vspacing.injectskip, - arguments = "dimension", - } - - interfaces.implement { - name = "injectdisable", - actions = vspacing.injectdisable, - } - - -- - - implement { - name = "synchronizepage", - actions = vspacing.synchronizepage, - scope = "private" - } - - implement { - name = "forcestrutdepth", - arguments = { "integer", "dimension", "integer" }, - actions = vspacing.forcestrutdepth, - scope = "private" - } - - implement { - name = "forcestrutdepthplus", - arguments = { "integer", "dimension", "integer", true }, - actions = vspacing.forcestrutdepth, - scope = "private" - } - - implement { - name = "pushatsame", - actions = vspacing.pushatsame, - scope = "private" - } - - implement { - name = "popatsame", - actions = vspacing.popatsame, - scope = "private" - } - - implement { - name = "vspacingsetamount", - actions = vspacing.setskip, - scope = "private", - arguments = "string", - } - - implement { - name = "vspacingdefine", - actions = vspacing.setmap, - scope = "private", - arguments = "2 strings", - } - - implement { - name = "vspacingcollapse", - actions = vspacing.collapsevbox, - scope = "private", - arguments = "integer" - } - - implement { - name = "vspacingcollapseonly", - actions = vspacing.collapsevbox, - scope = "private", - arguments = { "integer", true } - } - - implement { - name = "vspacingsnap", - actions = vspacing.snapbox, - scope = "private", - arguments = { "integer", "integer" } - } - - implement { - name = "definesnapmethod", - actions = vspacing.definesnapmethod, - scope = "private", - arguments = "2 strings", - } - - -- local remove_node = nodes.remove - -- local find_node_tail = nodes.tail - -- - -- interfaces.implement { - -- name = "fakenextstrutline", - -- actions = function() - -- local head = texlists.page_head - -- if head then - -- local head = remove_node(head,find_node_tail(head),true) - -- texlists.page_head = head - -- buildpage() - -- end - -- end - -- } - - implement { - name = "removelastline", - actions = function() - local head = texlists.page_head - if head then - local tail = find_node_tail(head) - if tail then - -- maybe check for hlist subtype 1 - local head = remove_node(head,tail,true) - texlists.page_head = head - buildpage() - end - end - end - } - - implement { - name = "showpagelist", -- will improve - actions = function() - local head = texlists.page_head - if head then - print("start") - while head do - print(" " .. tostring(head)) - head = head.next - end - end - end - } - - implement { - name = "pageoverflow", - actions = { vspacing.pageoverflow, context } - } - - implement { - name = "forcepageflush", - actions = vspacing.forcepageflush - } - -end diff --git a/tex/context/base/mkiv/spac-ver.mkxl b/tex/context/base/mkiv/spac-ver.mkxl deleted file mode 100644 index 92adce2c6..000000000 --- a/tex/context/base/mkiv/spac-ver.mkxl +++ /dev/null @@ -1,2468 +0,0 @@ -%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}{autosuffix,optimize} - -% 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 most general and often -%D 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 instance saying -%D -%D \starttyping -%D \setupinterlinespace[line=12pt] -%D \stoptyping -%D -%D sets things fixed for all sizes, which is definitely not what we want. Therefore -%D one can also say: -%D -%D \starttyping -%D \definebodyfontenvironment[9pt][interlinespace=11pt] -%D \stoptyping -%D -%D One can still use \type {\setupinterlinespace} (without arguments) to set the -%D interline space according to the 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} - -\permanent\def\normalskipamount - {\openlineheight - \ifgridsnapping \orelse \ifconditional\c_spac_whitespace_flexible - \s!plus \skipgluefactor\openlineheight - \s!minus\skipgluefactor\openlineheight - \fi - \relax} - -\ifdefined\bodyfontinterlinespace \else - \let\bodyfontinterlinespace\empty -\fi - -\permanent\protected\def\presetnormallineheight % each bodyfont - {\edef\normallineheight{\interlinespaceparameter\c!line}% - \iflocalinterlinespace \else - \edef\m_spac_normallineheight{\bodyfontinterlinespace}% - \ifempty\m_spac_normallineheight \else - \let\normallineheight\m_spac_normallineheight - \fi - \fi} - -\permanent\protected\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}} - -\permanent\protected\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 - {\ifempty\currentrelativeinterlinespace\else - \spacing\currentrelativeinterlinespace - \fi} - -\protected\def\spac_linespacing_setup_use - {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname - \let\currentinterlinespace\m_spac_interlinespace - \spac_linespacing_setup_specified_interline_space - % \else - % we only support named interlinespaces - \fi} - -\permanent\protected\def\useinterlinespaceparameter#1% see footnotes - {\edef\m_spac_interlinespace{#1\c!interlinespace}% - \ifempty\m_spac_interlinespace \else - \spac_linespacing_setup_use - \fi} - -\newtoks\everysetupglobalinterlinespace -\newtoks\everysetuplocalinterlinespace - -\newconditional\interlinespaceisset - -\installcorenamespace{interlinespace} - -\installcommandhandler \??interlinespace {interlinespace} \??interlinespace - -\installmacrostack\currentinterlinespace - -\permanent\overloaded\tolerant\protected\def\setupinterlinespace[#1]#*[#2]% - {\ifarguments - \settrue\interlinespaceisset - \spac_linespacing_synchronize_local - \or - \settrue\interlinespaceisset - \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname - \edef\currentinterlinespace{#1}% - \spac_linespacing_setup_specified_interline_space - %\dosetupspecifiedinterlinespaceindeed - \else - \spac_linespacing_setup_specified_or_relative[#1]% - \fi - \or - \settrue\interlinespaceisset - \setup_interlinespace[#1][#2]% - \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} - -\permanent\protected\def\dosetupcheckedinterlinespace#1% often a chain - {\edef\p_spac_checked_interlinespace{#1}% - \ifempty\p_spac_checked_interlinespace - \spac_linespacing_synchronize_local - \orelse\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check - \push_macro_currentinterlinespace - \let\currentinterlinespace\p_spac_checked_interlinespace - \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed - \iflocalinterlinespace - \the\everysetuplocalinterlinespace - \else - \localinterlinespacetrue - \the\everysetuplocalinterlinespace - \localinterlinespacefalse - \fi - \pop_macro_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} - -\permanent\protected\def\setuplocalinterlinespace[#1]% - {\localinterlinespacetrue - \push_macro_currentinterlinespace - \setupinterlinespace[#1]% - \pop_macro_currentinterlinespace - \localinterlinespacefalse} - -\let\switchtointerlinespace\setuplocalinterlinespace - -%D Helpers - -\newskip \s_spac_lastskip -\newdimen\d_spac_prevdepth -\newcount\c_spac_spacefactor -\newdimen\d_spac_prevcontent % set by lua - -% \permanent\overloaded\protected\def\removelastskip -% {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} - -\def\doifoutervmode - {\ifvmode - \ifinner - \doubleexpandafter\gobbleoneargument - \else - \doubleexpandafter\firstofoneargument - \fi - \else - \expandafter\gobbleoneargument - \fi} - -\protected\def\dosomebreak#1% - {\doifoutervmode - {\s_spac_lastskip\lastskip - \removelastskip - #1\relax - \ifzeropt\s_spac_lastskip - % avoid interference with footnotes - \else - \vskip\s_spac_lastskip - \fi}} - -\permanent\protected\def\packed - {\nointerlineskip} - -\permanent\protected\def\godown[#1]% - {\relax - \ifhmode\endgraf\fi - \ifvmode\nointerlineskip\vskip#1\relax\fi} - -\permanent\protected\def\smallskip{\vskip\smallskipamount} -\permanent\protected\def\medskip {\vskip\medskipamount} -\permanent\protected\def\bigskip {\vskip\bigskipamount} - -\permanent\protected\def\smallbreak - {\par - \ifvmode\ifdim\lastskip<\smallskipamount - \removelastskip - \penalty-\plusfifty - \smallskip - \fi\fi} - -\permanent\protected\def\medbreak - {\par - \ifvmode\ifdim\lastskip<\medskipamount - \removelastskip - \penalty-\plusonehundred - \medskip - \fi\fi} - -\permanent\protected\def\bigbreak - {\par - \ifvmode\ifdim\lastskip<\bigskipamount - \removelastskip - \penalty-\plustwohundred - \bigskip - \fi\fi} - -\permanent\protected\def\break {\penalty-\plustenthousand} % can be hmode or vmode -\permanent\protected\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode -\permanent\protected\def\allowbreak{\penalty \zerocount} % can be hmode or vmode - -\permanent\protected\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode -\permanent\protected\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode - -%D Made slightly more readable: - -\permanent\protected\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=} -\permanent\protected\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=} -\permanent\protected\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi} - -\def\spac_helpers_vglue_indeed - {\par - \ifvmode - \d_spac_prevdepth\prevdepth - \hrule\s!height\zeropoint - \nobreak - \vskip\s_spac_lastskip - \prevdepth\d_spac_prevdepth - \fi} - -\def\spac_helpers_hglue_indeed - {\dontleavehmode - \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: - -\pushoverloadmode - -\permanent\overloaded\protected\def\removelastskip % also in supp-box - {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} - -\popoverloadmode - -% The whitespace handler. We could cache settings but normally there are not -% that many in a set. - -\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 - -% \permanent\tolerant\protected\def\setupwhitespace[#1]% -% {\ifarguments -% \spac_whitespace_setup_nop -% \or -% \spac_whitespace_setup_yes{#1}% -% \fi} -% -% \def\spac_whitespace_setup_yes#1% -% {\edef\m_spac_whitespace_asked{#1}% -% \ifempty\m_spac_whitespace_asked -% \spac_whitespace_setup_nop -% \else -% \let\v_spac_whitespace_current\m_spac_whitespace_asked -% \spac_whitespace_setup -% \fi} - -\permanent\tolerant\protected\def\setupwhitespace[#1]% - {\ifarguments - \spac_whitespace_setup_nop - \orelse\iftok{#1}\emptytoks - \spac_whitespace_setup_nop - \else - \edef\v_spac_whitespace_current{#1}% - \spac_whitespace_setup - \fi} - -\def\spac_whitespace_setup_nop - {\ifx\v_spac_whitespace_current\v!none\else - \spac_whitespace_setup - \fi} - -\let\synchronizewhitespace\spac_whitespace_setup_nop - -\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} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]} -\permanent\protected\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 - -\permanent\tolerant\protected\def\startpacked[#1]% - {\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} - -\permanent\protected\def\stoppacked - {\par - \ifnum\c_spac_packed_level=\plusone \ifvmode - \endgroup - \fi \fi - \global\advance\c_spac_packed_level\minusone} - -\permanent\protected\def\startunpacked - {\directdefaultvspacing % \blank - \begingroup} - -\permanent\protected\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} - {\letfrozen\let\spac_lines_vbox\ruledvbox} - {\letfrozen\let\spac_lines_vbox\vbox} - -\let\v_spac_lines_around_action_set\relax -\let\m_spac_lines_around \empty - -\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} - -\permanent\tolerant\protected\def\startlinecorrection [#1]{\spac_lines_start_correction\plusone{#1}} -\permanent\tolerant\protected\def\startlocallinecorrection[#1]{\spac_lines_start_correction\plustwo{#1}} - -\protected\def\spac_lines_start_correction#1#2% - {\endgraf - \begingroup - \setconstant\c_spac_lines_correction_mode#1% - \edef\m_spac_lines_around{#2}% - \spac_lines_action_around - \d_spac_prevdepth\prevdepth - \spac_lines_initialize_corrections - \offbaselinecorrection % ??? - \setbox\scratchbox\spac_lines_vbox\bgroup - \ifcase\c_spac_lines_correction_mode - % nothing - \or - % global - \or - % local - \setlocalhsize - \hsize\localhsize - \forgetbothskips - \fi - \ignorespaces} - -\protected\def\spac_lines_stop_correction - {\removeunwantedspaces - \egroup - \ifgridsnapping - \spac_lines_stop_correction_ongrid - \else - \spac_lines_stop_correction_normal - \fi - \endgroup} - -\protected\def\spac_lines_stop_correction_ongrid - {\directcheckedvspacing\v!white % \blank[\v!white]% - \spac_lines_action_around - \snaptogrid\hpack{\box\scratchbox}% - \directcheckedvspacing\v!white - \spac_lines_action_around} - -\protected\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: - -\permanent\protected\def\correctwhitespace - {\dowithnextboxcs\correctwhitespacefinish\vbox} - -\permanent\protected\def\correctwhitespacefinish - {\startbaselinecorrection - \flushnextbox - \stopbaselinecorrection} - -\permanent\protected\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}} -\permanent\protected\def\horizontalstrut{\hpack {\strut}} - -%D Here follow some presets related to interline spacing and therefore also struts. -%D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used -%D a while after we decided that \LATEX\ was not flexible enough. After that -%D \CONTEXT\ evolved, from some wrapper code around (old) \LATEX\ (on a floppy -%D disk), to using modules from \INRSTEX\ (which also fit on a floppy) and finally -%D all written from scratch. I simply didn't understand all that \TEX\ code at that -%D time, and it was easier to figure it out myself. But \unknown\ some settings -%D stayed, as the height|/|depth ratios, and they never proved to be bad ones! The -%D same is true for the font size relations. - -%D \starttabulate -%D \NC \type {\lineheight} \NC the height of a line \NC \NR -%D \NC \type {\spacing{number}} \NC adapting the interline space \NC \NR -%D \NC \type {\normalbaselines} \NC initialize the interline spacing \NC \NR -%D \NC \type {\setstrut} \NC initialize \type {\strut} \NC \NR -%D \NC \type {\setnostrut} \NC disable the \type {\strut}, \type {\endstrut}, \type {\begstrut} \NC \NR -%D \NC \type {\setteststrut} \NC initialize the visual \type {\strut} \NC \NR -%D \NC \type {\resetteststrut} \NC disable the visual \type {\strut} \NC \NR -%D \NC \type {\setfontparameters} \NC synchronize parameters with foints \NC \NR -%D \stoptabulate -%D -%D \unknown\ and many more (this is a decades old list). -%D -%D The lineheight is the sum of the height and depth of \type {strut}, which is -%D an invisible blob that can be used to enforce the proper dimensions. -%D -%D Such a blob, when placed at the beginning of a paragraph can have side effects -%D that can be prevented with \type {\dontleavehmode}. Never use \type -%D {\leavevmode}! - -\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 - -\permanent\protected\def\topskipcorrection - {\simpletopskipcorrection - \vskip-\struttotal - \verticalstrut} - -\permanent\protected\def\simpletopskipcorrection - {\ifdim\topskip>\openstrutheight - % == \vskip\topskipgap - \vskip\topskip - \vskip-\openstrutheight - \fi} - -\permanent\protected\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} - -\protected\def\setmaxdepth - {\maxdepth\systemmaxdepthfactor\globalbodyfontsize} - -\newskip \usedbaselineskip % These used to be \normal... but that isn't pretty -\newskip \usedlineskip % in the token interface, so thes few now have new -\newdimen\usedlineskiplimit % names. They are public but not really user commands. - -\permanent\protected\def\normalbaselines - {\baselineskip \usedbaselineskip - \lineskip \usedlineskip - \lineskiplimit\usedlineskiplimit} - -\permanent\protected\def\flexiblebaselines - {\baselineskip \usedbaselineskip - \lineskip 1\usedlineskip \s!plus 1\s!fill - \lineskiplimit\usedlineskiplimit} - -\permanent\protected\def\setnormalbaselines % used in overload - {\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 - \usedbaselineskip\openlineheight - \ifgridsnapping\else - \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight - \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight - \fi - \usedlineskip\minimumlinedistance\relax % \onepoint\relax - \usedlineskiplimit\zeropoint\relax - \normalbaselines} - -\permanent\protected\def\spacing#1% vertical - {\ifgridsnapping - \let\spacingfactor\plusone - \else - \edef\spacingfactor{#1}% - \fi - \edef\systemtopskipfactor {\thewithoutunit\dimexpr#1\dimexpr\topskipfactor \points}% - \edef\systemmaxdepthfactor{\thewithoutunit\dimexpr#1\dimexpr\maxdepthfactor\points}% - \setnormalbaselines - \setstrut} - -% \protected\def\forgetverticalstretch % \forgetspacing -% {\spacing\plusone} - -\permanent\protected\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 - -\permanent\protected\def\saveinterlinespace - {\protected\edef\restoreinterlinespace - {\lineheight \the\lineheight - \openstrutheight \the\openstrutheight - \openstrutdepth \the\openstrutdepth - \openlineheight \the\openlineheight - \usedbaselineskip \the\usedbaselineskip - \usedlineskip \the\usedlineskip - \usedlineskiplimit \the\usedlineskiplimit - \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}% - \noexpand\normalbaselines}} - -%D This is the plain definition: -%D -%D \starttyping -%D \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi} -%D \stoptyping -%D -%D which could be: -%D -%D \starttyping -%D \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox} -%D \stoptyping -%D -%D But we do things differently. - -\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} - -% \protected\def\strut -% {\relax -% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} - -\let\normalstrut\strut - -%D The double \type {\hbox} construction enables us to backtrack boxes. - -\overloaded\let\strutht\undefined \newdimen\strutht -\overloaded\let\strutdp\undefined \newdimen\strutdp - -\permanent\protected\def\setstrut - {\ifgridsnapping - \setstrutgridyes - \else - \setstrutgridnop - \fi} - -\permanent\protected\def\setstrutgridyes - {\strutht\spacingfactor\dimexpr - \ifdim\minimumstrutheight>\zeropoint - \minimumstrutheight - \else - \strutheightfactor\dimexpr\normallineheight - \fi - \relax - \strutdp\dimexpr - \ifdim\minimumstrutdepth>\zeropoint - \minimumstrutdepth - \else - \normallineheight-\strutht - \fi - \relax - \dosetstrut} - -\permanent\protected\def\setstrutgridnop - {\strutht\spacingfactor\dimexpr - \ifdim\minimumstrutheight>\zeropoint - \minimumstrutheight - \else - \strutheightfactor\dimexpr\normallineheight - \fi - \relax - \strutdp\spacingfactor\dimexpr - \ifdim\minimumstrutdepth>\zeropoint - \minimumstrutdepth - \else - \strutdepthfactor\dimexpr\normallineheight - \fi - \relax - \dosetstrut} - -\permanent\protected\def\setcharstrut#1% - {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps - \strutht\ht\strutbox - \strutdp\dp\strutbox - \dosetstrut} - -\permanent\protected\def\settightstrut - {\setcharstrut{(}} - -\permanent\protected\def\setfontstrut - {\setcharstrut{(gplQT}} - -\permanent\protected\def\setcapstrut% could be M, but Q has descender - {\setcharstrut{Q}} - -%D Handy for math (used in mathml): - -\permanent\protected\def\charhtstrut - {\begingroup - \setcharstrut{GJY}% - \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht - \endgroup} - -\permanent\protected\def\chardpstrut - {\begingroup - \setcharstrut{gjy}% - \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint - \endgroup} - -%D Because of all the callbacks in mkiv, we avoid unnecessary boxes ... maybe use an -%D attribute so that we can tag boxes that don't need a treatment; tests with using -%D an attribute so far have shown that it's slower because testing the attribute -%D takes time too. - -\permanent\protected\def\dosetstrut - {\enforced\let\strut\normalstrut - \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo - % compensate rounding error /- 1sp to avoid too many - % 1sp baselineskips in for instance verbatim - % \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 strut; occasionally a -%D one scaled point difference can show up with the lineheight. This is more -%D 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} - -\permanent\protected\def\strut % still callbacks for \hbox{\strut} - {\relax - \dontleavehmode - \copy\strutbox} - -% \protected\def\strut % slightly faster -% {\relax -% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} - -\let\normalstrut\strut - -\permanent\protected\def\halfstrut - {\relax - \dontleavehmode - \begingroup - \setbox\scratchbox\copy\strutbox - \ht\scratchbox\dimexpr\strutht/\plustwo\relax - \dp\scratchbox\dimexpr\strutdp/\plustwo\relax - \box\scratchbox - \endgroup} - -\permanent\protected\def\quarterstrut - {\relax - \dontleavehmode - \begingroup - \setbox\scratchbox\copy\strutbox - \ht\scratchbox\dimexpr\strutht/\plusfour\relax - \dp\scratchbox\dimexpr\strutdp/\plusfour\relax - \box\scratchbox - \endgroup} - -\permanent\protected\def\depthstrut - {\relax - \dontleavehmode - \begingroup - \setbox\scratchbox\copy\strutbox - \ht\scratchbox\dimexpr\strutht-\struthtdp/\plustwo\relax % assumes that ht > lineheight/2 - \box\scratchbox - \endgroup} - -\permanent\protected\def\halflinestrut - {\relax - \dontleavehmode - \begingroup - \setbox\scratchbox\copy\strutbox - \ht\scratchbox\dimexpr\strutht-.5\strutht-.5\strutdp\relax - \box\scratchbox - \endgroup} - -\permanent\protected\def\noheightstrut - {\relax - \dontleavehmode - \begingroup - \setbox\scratchbox\copy\strutbox - \ht\scratchbox\zeropoint - \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 -%D Beware: using an unknown value results in char struts. - -\installcorenamespace{struts} - -\permanent\tolerant\protected\def\setupstrut[#1]% - {\edef\m_strut{#1}% - \ifcsname\??struts\m_strut\endcsname - \lastnamedcs - \else - \setcharstrut\m_strut - \fi} - -\permanent\protected\def\synchronizestrut#1% no [] parsing, faster for internal - {\edef\m_strut{#1}% - \ifcsname\??struts\m_strut\endcsname - \lastnamedcs - \else - \setcharstrut\m_strut - \fi} - -\permanent\protected\def\dosynchronizestrut#1% no [] parsing, faster for internal - {\ifcsname\??struts#1\endcsname - \lastnamedcs - \else - \setcharstrut{#1}% - \fi} - -\permanent\protected\def\showstruts % adapts .. is wrong - {\c_strut_visual_mode\zerocount - \setteststrut - \settestcrlf} - -\permanent\protected\def\showcolorstruts % adapts .. is wrong - {\c_strut_visual_mode\plusone - \setteststrut - \settestcrlf} - -\permanent\protected\def\setteststrut - {\def\strutwidth{.8pt}% - \setstrut} - -\permanent\protected\def\dontshowstruts - {\unsetteststrut - \settestcrlf} - -\permanent\protected\def\unsetteststrut - {\let\strutwidth\zeropoint - \setstrut} - -\def\autostrutfactor{1.1} - -\permanent\protected\def\setautostrut - {\begingroup - \setbox\scratchbox\copy\strutbox - \setstrut - \ifdim\strutht>\autostrutfactor\ht\scratchbox - \endgroup \setstrut - \orelse\ifdim\strutdp>\autostrutfactor\dp\scratchbox - \endgroup \setstrut - \else - \endgroup - \fi} - -\newbox\nostrutbox \setbox\nostrutbox\emptyhbox - -\newtoks\everysetnostrut - -\permanent\protected\def\setnostrut - {\the\everysetnostrut} - -\appendtoks - \setbox\strutbox\copy\nostrutbox - \enforced\let\strut \empty - \enforced\let\endstrut\empty - \enforced\let\begstrut\empty -\to \everysetnostrut - -%D When enabled, sigstruts will remove themselves if nothing goes inbetween. For -%D practical reasons we define some boundary characters here. - -\permanent\protected\def\leftboundary {\protrusionboundary\plusone} -\permanent\protected\def\rightboundary {\protrusionboundary\plustwo} -\permanent\protected\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals - -\newsignal\d_spac_struts_signal \setfalse\sigstruts - -\permanent\protected\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-\d_spac_struts_signal - \hskip\d_spac_struts_signal} - -\def\spac_struts_beg_normal - {\boundary\plusone - \strut - %\boundary\plusone - \penalty\plustenthousand - %\boundary\plusone - \hskip\zeropoint} - -\permanent\protected\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=\d_spac_struts_signal - \unskip - \unskip - \unpenalty - \setbox\scratchbox\lastbox - \else - \penalty\plustenthousand - \hskip\zeropoint - \strut - \fi} - -\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: - -\permanent\protected\def\pseudostrut - {\noindent} % better: \dontleavehmode - -\let\pseudobegstrut\pseudostrut -\let\pseudoendstrut\removeunwantedspaces - -\permanent\protected\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 -\letvalue{\??struts\v!auto }\setautostrut -\letvalue{\??struts\v!no }\setnostrut -\letvalue{\??struts\v!cap }\setcapstrut -\letvalue{\??struts\v!fit }\setfontstrut -\letvalue{\??struts\v!line }\setstrut -\letvalue{\??struts\s!default}\setstrut -\letvalue{\??struts\empty }\setstrut - -%D Handy: - -\def\baselinedistance{\the\lineheight} - -%D We need \type {\normaloffinterlineskip} because the new definition contains an -%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for -%D instance the visual debugger. - -\pushoverloadmode - -\overloaded\permanent\protected\def\offinterlineskip - {\baselineskip-\thousandpoint - \lineskip \zeropoint - \lineskiplimit\maxdimen - % We also need this here now; thanks to taco for figuring that out! - \def\minimumlinedistance{\zeropoint}} - -\overloaded\permanent\protected\def\nointerlineskip - {\prevdepth-\thousandpoint} - -\aliased\let\normaloffinterlineskip\offinterlineskip % knuth's original - -\popoverloadmode - -%D This is tricky. The prevdepth value is still set to the last one even if there is -%D nothing on the page. The same is true for prevgraf, which doesn't resemble the -%D value on the current page. -%D -%D So, here we kick in a checker but it has to happen after the output group and it -%D only has to be done once (output can trigger itself!). -%D -%D However, prevgraf is somehow bound to hangindent so we can get very nasty side -%D effects. So, in tne end we use our own variable! - -\ifdefined\getnofpreviouslines - % defined public at the lua end -\else - \let\getnofpreviouslines\!!zerocount -\fi - -\protected\def\page_otr_synchronize_page_yes - {\aftergroup\page_otr_synchronize_page_indeed - \global\enforced\let\page_otr_synchronize_page\relax} - -% \protected\def\page_otr_synchronize_page_indeed -% {\clf_synchronizepage -% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} -% -% This has to become an otr method: \s!page_otr_command_synchonize_page - -\protected\def\page_otr_synchronize_page_indeed - {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi - \global\enforced\let\page_otr_synchronize_page\page_otr_synchronize_page_yes} - -\let\page_otr_synchronize_page\page_otr_synchronize_page_yes - -\appendtoks - \page_otr_synchronize_page -\to \everyaftershipout - -%D My own one: - -\protected\def\spac_helpers_push_interlineskip_yes - {\enforced\edef\oninterlineskip - {\baselineskip \the\baselineskip - \lineskip \the\lineskip - \lineskiplimit\the\lineskiplimit - \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}% - \enforced\let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed - -\protected\def\spac_helpers_push_interlineskip_nop - {\enforced\let\oninterlineskip\setnormalbaselines} - -\pushoverloadmode - -\overloaded\permanent\protected\def\offinterlineskip - {\ifdim\baselineskip>\zeropoint - \spac_helpers_push_interlineskip_yes - \else - \spac_helpers_push_interlineskip_nop - \fi - \normaloffinterlineskip} - -\permanent\let\oninterlineskip\relax - -\popoverloadmode - -\permanent\protected\def\resetpenalties#1% - {\ifdefined#1% - \frozen#1\minusone - \fi} - -\permanent\protected\def\setpenalties#1#2#3% - {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text - \frozen#1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax - \fi} - -%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 - -\protected\def\spac_penalties_restore - {\global\enforced\let\restoreinterlinepenalty\relax - \overloaded\global\resetpenalties\interlinepenalties - \global\c_spac_keep_lines_together\zerocount} - -\protected\def\keeplinestogether#1% - {\ifnum#1>\c_spac_keep_lines_together - \global\c_spac_keep_lines_together#1% - \overloaded\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand - \global\enforced\let\restoreinterlinepenalty\spac_penalties_restore - \fi} - -\def\defaultdisplaywidowpenalty {50} -\def\defaultwidowpenalty {2000} % was: 1000 -\def\defaultclubpenalty {2000} % was: 800 -\def\defaultbrokenpenalty {100} -\def\defaultdoublehyphendemerits {10000} -\def\defaultfinalhyphendemerits {5000} -\def\defaultadjdemerits {10000} - -\def\defaultgriddisplaywidowpenalty {0} -\def\defaultgridwidowpenalty {0} -\def\defaultgridclubpenalty {0} -\def\defaultgridbrokenpenalty {0} -\def\defaultgriddoublehyphendemerits{10000} % always was so -\def\defaultgridfinalhyphendemerits {5000} % always was so -\def\defaultgridadjdemerits {10000} % always was so - -\permanent\protected\def\nopenalties - {\frozen\widowpenalty \zerocount - \frozen\clubpenalty \zerocount - \frozen\brokenpenalty \zerocount - \frozen\doublehyphendemerits\zerocount - \frozen\finalhyphendemerits \zerocount - \frozen\adjdemerits \zerocount} - -\permanent\protected\def\setdefaultpenalties - {\directsetup{\systemsetupsprefix\s!default}} - -\startsetups [\systemsetupsprefix\s!reset] - \resetpenalties\widowpenalties - \resetpenalties\clubpenalties - \resetpenalties\interlinepenalties -\stopsetups - -%D We use \directsetup because it's faster and we know there is no csl: - -\startsetups [\systemsetupsprefix\s!default] - - \directsetup{\systemsetupsprefix\s!reset} - - \frozen\widowpenalty \defaultwidowpenalty - \frozen\clubpenalty \defaultclubpenalty - \frozen\displaywidowpenalty \defaultdisplaywidowpenalty - \frozen\brokenpenalty \defaultbrokenpenalty - \frozen\doublehyphendemerits\defaultdoublehyphendemerits - \frozen\finalhyphendemerits \defaultfinalhyphendemerits - \frozen\adjdemerits \defaultadjdemerits - -\stopsetups - -\startsetups [\v!grid] [\systemsetupsprefix\s!default] - - \directsetup{\systemsetupsprefix\s!reset} - - \frozen\widowpenalty \defaultgridwidowpenalty - \frozen\clubpenalty \defaultgridclubpenalty - \frozen\displaywidowpenalty \defaultgriddisplaywidowpenalty - \frozen\brokenpenalty \defaultgridbrokenpenalty - \frozen\doublehyphendemerits\defaultgriddoublehyphendemerits - \frozen\finalhyphendemerits \defaultgridfinalhyphendemerits - \frozen\adjdemerits \defaultgridadjdemerits - -\stopsetups - -%D As an illustration: - -\startsetups [\systemsetupsprefix\v!strict] - - \directsetup{\systemsetupsprefix\s!reset} - - \setpenalties \widowpenalties \plustwo \maxdimen - \setpenalties \clubpenalties \plustwo \maxdimen - \frozen \brokenpenalty \maxdimen - \frozen \doublehyphendemerits \defaultdoublehyphendemerits - \frozen \finalhyphendemerits \defaultfinalhyphendemerits - \frozen \adjdemerits \defaultadjdemerits - -\stopsetups - -\setdefaultpenalties % will happen later in \setuplayout - -%D To be checked: - -\newbox\b_spac_struts_saved - -\permanent\protected\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox} -\permanent\protected\def\savedstrut{\copy \b_spac_struts_saved} - -%D Good old blank redone: - -%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} -\installcorenamespace{gridsnappersets} - -\newskip \bodyfontlineheight -\newdimen \bodyfontstrutheight -\newdimen \bodyfontstrutdepth - -\newskip \globalbodyfontlineheight % why a skip -\newdimen \globalbodyfontstrutheight -\newdimen \globalbodyfontstrutdepth - -\permanent\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi} -\permanent\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi} - -\def\spac_grids_set_local_snapping#1% - {\ifgridsnapping - \doifsomething{#1}% - {\spac_grids_snap_value_set{#1}% - \c_attr_snapvbox\c_attr_snapmethod}% - \fi} - -\def\spac_grids_expand_snapper#1% - {\edef\m_spac_snapper - {\ifempty\m_spac_snapper\else\m_spac_snapper,\fi - \ifcsname\??gridsnappersets#1\endcsname - \lastnamedcs\else#1% - \fi}} - -\permanent\protected\def\installsnapvalues#1#2% - {\let\m_spac_snapper\empty - \rawprocesscommacommand[#2]\spac_grids_expand_snapper - \edef\currentsnapper{#1:\m_spac_snapper}% - \ifcsname\??gridsnapperattributes\currentsnapper\endcsname - \scratchcounter\lastnamedcs % already defined - \else - \scratchcounter\clf_definesnapmethod{#1}{\m_spac_snapper}% - \setevalue{\??gridsnapperattributes\currentsnapper}{\the\scratchcounter}% - \fi - \setevalue{\??gridsnappers#1}{\c_attr_snapmethod\the\scratchcounter\relax}% - \letvalue{\??gridsnappersets#1}\m_spac_snapper} - -\permanent\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals - -\permanent\protected\def\usegridparameter#1% no checking here - {\edef\m_spac_grid_asked{#1\c!grid}% - \ifempty\m_spac_grid_asked - \c_attr_snapvbox\attributeunsetvalue - \else - \spac_grids_snap_value_set\m_spac_grid_asked - \c_attr_snapvbox\c_attr_snapmethod - \fi} - -\permanent\tolerant\protected\def\definegridsnapping[#1]#*[#2]% - {\installsnapvalues{#1}{#2}} - -\edef\spac_grids_snap_value_reset - {%\gridsnappingfalse - \c_attr_snapmethod\attributeunsetvalue} - -\def\spac_grids_snap_value_set#1% - {%\gridsnappingtrue - \begincsname\??gridsnappers#1\endcsname} - -% maybe: -% -% \def\spac_grids_snap_value_set#1% -% {%\gridsnappingtrue -% \ifcsname\??gridsnappers#1\endcsname -% \lastnamedcs -% \else -% \definegridsnapping[#1][#1]% -% \begincsname\??gridsnappers#1\endcsname -% \fi} - -\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 -% box centers a box rounded upwards (box:.5 -> tolerance) -% min centers a box rounded downwards -% max centers a box rounded upwards - -%D We're not downward compatible with \MKII ! Not yet in interface file: - -\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!verytolerant] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] - -\definegridsnapping[\v!tolerant:10] [\v!maxdepth:1.1,\v!maxheight:1.1,\v!strut] % 10 pct tolerance -\definegridsnapping[\v!tolerant:20] [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut] % 20 pct tolerance -\definegridsnapping[\v!tolerant:30] [\v!maxdepth:1.3,\v!maxheight:1.3,\v!strut] % 30 pct tolerance -\definegridsnapping[\v!tolerant:40] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] % 40 pct tolerance - -\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] -\definegridsnapping[\v!min] [\v!min] -\definegridsnapping[\v!max] [\v!max] - -\definegridsnapping[\v!middle] [\v!maxheight,\v!maxdepth] % used in placement - -\definegridsnapping[\v!math] [\v!maxdepth:1.05,\v!maxheight:1.05,\v!strut] % experimental, maybe 1.1 -\definegridsnapping[\v!math:\v!line] [\v!math,\v!line,\v!split] -\definegridsnapping[\v!math:\v!halfline] [\v!math,\v!halfline,\v!split] -\definegridsnapping[\v!math:-\v!line] [\v!math,-\v!line,\v!split] -\definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split] - -\permanent\protected\def\synchronizelocallinespecs - {\bodyfontlineheight \normallineheight - \bodyfontstrutheight\strutht - \bodyfontstrutdepth \strutdp} - -\permanent\protected\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: - -\permanent\protected\def\synchronizeskipamounts - {\bigskipamount - \skipfactor\baselineskip - \s!plus\skipgluefactor\baselineskip - \s!minus\skipgluefactor\baselineskip - \relax - \medskipamount \bigskipamount \divide\medskipamount \plustwo - \smallskipamount\bigskipamount \divide\smallskipamount\plusfour} - -%D Snapping. - -% \newif\ifgridsnapping % already defined - -\permanent\tolerant\protected\def\startgridsnapping[#1]% - {\snaptogrid[#1]\vbox\bgroup} - -\permanent\protected\def\stopgridsnapping - {\egroup} - -\permanent\tolerant\protected\def\placeongrid[#1]% - {\snaptogrid[#1]\vbox} % mark as done - -\permanent\tolerant\protected\def\snaptogrid[#1]% list or predefined - {\ifgridsnapping - \expandafter\spac_grids_snap_to_indeed % todo: move inline - \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\c_attr_snapmethod\relax - \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap - \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} - -\protected\def\synchronizegridsnapping - {\edef\askedgridmode{\layoutparameter\c!grid}% - \ifx\askedgridmode\v!no % official - \spac_grids_check_nop - \orelse\ifx\askedgridmode\v!off % for taco and luigi - \spac_grids_check_nop - \orelse\ifempty\askedgridmode % to be sure - \spac_grids_check_nop - \else - \spac_grids_check_yes - \fi} - -\permanent\protected\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing) - {\setlayoutparameter\c!grid{#1}\synchronizegridsnapping} - -\permanent\protected\def\checkgridmethod#1% - {\edef\p_grid{#1}% - \ifempty\p_grid - \let\checkedgridmethod\empty - \let\checkedgridscope \v!local - \else - \splitatcolon\p_grid\checkedgridscope\checkedgridmethod - \ifempty\checkedgridmethod - \ifx\checkedgridscope\v!local\orelse\ifx\checkedgridscope\v!global\else - \let\checkedgridmethod\checkedgridscope - \let\checkedgridscope \v!local - \fi - \fi - \fi} - -\permanent\protected\def\applygridmethod#1#2#3% content localsettings (used in head rendering) - {\checkgridmethod{#1}% - \ifx\checkedgridscope\v!global - \ifempty\checkedgridmethod \else - % we assume that the call is grouped because grouping here has the side - % effect that the eventually constructed line will get the value outside - % the group - % - % overkill: \setupgridsnapping[\checkedgridmethod]% - % maybe : \spac_grids_snap_value_auto\checkedgridmethod - \spac_grids_snap_value_set\checkedgridmethod - \fi - \hbox{#3}% - \else - % the extra hbox will trigger the global snapper on top of the local and - % we really need that in this case (compatibility etc etc) so here we don't - % het an already done hit (otherwise we would not snap) - \hbox\bgroup - \ifempty\checkedgridmethod\orelse\ifconditional\headisdisplay - #2% - \fi - \snaptogrid[\checkedgridmethod]\hbox{#3}% - \egroup - \fi} - -\protected\gdef\page_layouts_calculate_overshoot - {\ifgridsnapping\ifcase\layoutlines - \getnoflines\textheight - \textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax - \fi\fi} - -\protected\def\page_layouts_report_overshoot - {\page_layouts_calculate_overshoot - \ifdim\textovershoot>\zeropoint - \writestatus\m!layouts{gridmode,\space - noflines: \the\noflines,\space - textheight: \the\textheight,\space - textovershoot: \the\textovershoot\space - (maybe set number of lines instead)% - }% - \fi - \glet\page_layouts_report_overshoot\page_layouts_calculate_overshoot} - -\appendtoks - \page_layouts_report_overshoot -\to \everybeforepagebody - -%D Visualization: - -\definepalet - [grid] - [ one=red, - two=green, - three=blue, - four=gray] - -\permanent\protected\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 - -\permanent\protected\def\gridboxvbox - {\ifcase\gridboxlinemode - \vpack - \or - \ruledvpack - \or - \vpack - \or - \ruledvpack - \else - \ruledvpack - \fi} - -\permanent\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} - -\permanent\protected\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level - {\setbox#1\gridboxvbox to #3 % given size - {\forgetall - \resetvisualizers - \resetteststrut - \offinterlineskip - \hsize#2% - \ifcase\gridboxlinenomode\or\or\or - \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer - \or - \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner - \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\moveboxontogrid#1#2#3% will become obsolete, but it needs checking -% {} - -%D Helper: - -\protected\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} - -\permanent\tolerant\protected\def\definevspacingamount[#1]#*[#2]#*[#3]% can be combined - {\ifarguments - %setvalue{\??vspacingamount#1}{\lineheight}% - \or - \setvalue{\??vspacingamount#1}{\lineheight}% - \or - \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}% - \or - \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}% - \fi - \clf_vspacingsetamount{#1}} - -\def\spac_vspacing_no_topskip % use grouped - {\c_attr_skipcategory\pluseleven} - -%permanent\def\vspacingfromscratchtoks {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax} -\permanent\def\vspacingpredefinedvalue#1{\scratchskip\glueexpr\csname\??vspacingamount#1\endcsname\relax} -%permanent\def\vspacingfromtempstring {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax} - -% \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}} - -\permanent\tolerant\protected\def\definevspacing[#1]#*[#2]% - {\clf_vspacingdefine{#1}{#2}} - -%D The injector code (generated at the \LUA\ end). This will go away! - -\newtoks\everybeforeblankhandling -\newtoks\everyafterblankhandling - -\newconditional\c_space_vspacing_done -\newconditional\c_space_vspacing_fixed -\newconditional\c_space_ignore_parskip - -\appendtoks - \s_spac_vspacing_temp\zeropoint - \c_attr_skipcategory\plusone - \c_attr_skippenalty \attributeunsetvalue - \c_attr_skiporder \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 - -% The main spacer: - -% \protected\def\vspacing -% {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop} - -\tolerant\protected\def\vspacing[#1]% - {\ifarguments - \spac_vspacing_yes[\currentvspacing]% in the new mechanism no [] needed - \else - \spac_vspacing_yes[#1]% in the new mechanism no [] needed - \fi} - -\def\spac_vspacing_yes - {\ifinpagebody % somewhat weird - \expandafter\spac_vspacing_yes_indeed - \orelse\ifconditional\c_spac_packed_blank - \expandafter\spac_vspacing_yes_indeed - \else - \expandafter\spac_vspacing_yes_ignore - \fi} - -\def\spac_vspacing_nop - {\ifinpagebody % somewhat weird - \expandafter\spac_vspacing_nop_indeed - \orelse\ifconditional\c_spac_packed_blank - \expandafter\spac_vspacing_nop_indeed - \else - \expandafter\spac_vspacing_nop_ignore - \fi} - -\def\spac_vspacing_yes_indeed[#1]{\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi} -\def\spac_vspacing_nop_indeed {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\currentvspacing}\fi\fi} - -\def\spac_vspacing_yes_ignore[#1]{\ifmmode\else\par\fi} -\def\spac_vspacing_nop_ignore {\ifmmode\else\par\fi} - -\installcorenamespace{vspacing} - -\permanent\protected\def\directvspacing#1% - {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\iftok{#1}\emptytoks\currentvspacing\else#1\fi}\fi\fi} - -\def\spac_vspacing_dim_preset#1% - {\ifcsname\??vspacing#1\endcsname - \lastnamedcs - \else - \spac_vspacing_yes_preset{#1}% - \fi} - -\def\spac_vspacing_yes_preset#1% - {\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}% - %\writestatus{}{}% - %\writestatus{#1}{\expandafter\meaning\csname\??vspacing#1\endcsname}% - %\writestatus{}{}% - \csname\??vspacing#1\endcsname} - -\permanent\protected\def\directdefaultvspacing - {\ifinpagebody % somewhat weird - \directvspacing\currentvspacing - \orelse\ifconditional\c_spac_packed_blank - \directvspacing\currentvspacing - \fi} - -\permanent\protected\def\directcheckedvspacing - {\ifinpagebody % somewhat weird - \expandafter\directvspacing - \orelse\ifconditional\c_spac_packed_blank - \expandafter\directvspacing - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\useblankparameter#1% faster local variant - {\edef\m_spac_blank_asked{#1\c!blank}% - \ifempty\m_spac_blank_asked\else - \directvspacing\m_spac_blank_asked - \fi} - -%D Handy (and faster): - -\permanent\protected\def\directvpenalty#1{\ifmmode\else\par\ifvmode\clf_injectvpenalty#1\relax\fi\fi} -\permanent\protected\def\directvskip #1{\ifmmode\else\par\ifvmode\clf_injectvskip #1\relax\fi\fi} - -%D These depend on bigskipamount cum suis so we'd better sync them: - -\mutable\let\currentvspacing\s!default % hm, default, standard ... - -\permanent\tolerant\protected\def\setupvspacing[#1]% - {\ifarguments\else - \edef\currentvspacing{#1}% - \fi - \synchronizevspacing} - -\permanent\protected\def\synchronizevspacing - {\ifempty\currentvspacing % mistakenly had an \else - \let\currentvspacing\s!default - \fi - \spac_whitespace_setup_nop} - -\permanent\protected\def\restorestandardblank % or default ? - {\let\currentvspacing\v!standard} - -%D The \type {category:4} is default. - -\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!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible - -\permanent\def\bodyfontwhitespace - {\dimexpr - \ifzeropt\parskip - \zeropoint - \orelse\ifgridsnapping - \bodyfontlineheight - \else - \parskip - \fi - \relax} - -%D used in itemize \unknown\ 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!always] [category:0] % hm, internally it's discard -\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] -\definevspacing[\v!packed] [category:8] % noparskip (kind of special) -\definevspacing[\v!overlay] [category:9] -\definevspacing[\v!enable] [category:10] - -%definevspacing[\v!noparskip] [category:8] -%definevspacing[\v!notopskip] [category:11] - -\definevspacing[\v!weak] [order:0] -\definevspacing[\v!strong] [order:100] - -\definevspacing[\s!default] [\v!white] % was big for a while - -\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 -\newcount\c_spac_vspacing_special_done - -% 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names - -\protected\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m - {\begingroup - \scratchcounterone\numexpr\plusthree*#1+#2\relax - \scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax - %\writestatus{defined}{\v!samepage-\number#1-\number#2\space=>\space penalty:\the\scratchcountertwo}% - \normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}% - \endgroup} - -\protected\def\spac_vspacing_define_same_page#1% - {\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone - {\spac_vspacing_define_same_step\recurselevel\zerocount % before - \spac_vspacing_define_same_step\recurselevel\plusone % after - \spac_vspacing_define_same_step\recurselevel\plustwo}% % whatever - \global\c_spac_vspacing_special_done#1\relax} - -\spac_vspacing_define_same_page{12} % 12 levels should be more than enough as a start - -\def\spac_vspacing_same_page#1#2% level offset (starts at 0) - {\ifnum#1>\c_spac_vspacing_special_done - \spac_vspacing_define_same_page{#1}% - \fi - %\writestatus{used}{\v!samepage-\number#1-\number#2}% - \vspacing[\v!samepage-\number#1-\number#2]} - -\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 \type {\blank} -%D (we needed the first one while playing with the new code). - -% We keep this one as reference -% -% \protected\def\inhibitblank -% {\vspacing[\v!disable]} -% -% but use the following more efficient variant instead: - -\permanent\protected\def\inhibitblank{\ifmmode\else\par\ifvmode\clf_injectdisable\fi\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 care as it does -%D {\em not} work in tandem with the other spacing commands. - -\installcorenamespace{vspace} - -\permanent\tolerant\protected\def\definevspace[#1]#*[#2]#*[#3]% - {\ifarguments - \or - \letvalue{\??vspace:#1}\empty % or undefined? - \or - \setvalue{\??vspace:#1}{#2}% - \or - \setvalue{\??vspace#1:#2}{#3}% - \fi} - -\letvalue{\??vspace:\s!unknown}\zeropoint - -\def\spac_vspace_unknown - {\csname\??vspace:\s!unknown\endcsname} - -\permanent\tolerant\protected\def\vspace[#1]#*[#2]% - {\par - \ifvmode - \removelastskip - \vskip - \ifparameter#2\or - \ifcsname\??vspace#1:#2\endcsname - \lastnamedcs - \orelse\ifcsname\??vspace:#2\endcsname - \lastnamedcs - \else - \spac_vspace_unknown - \fi - \orelse\ifparameter#1\or - \ifcsname\??vspace:#1\endcsname - \lastnamedcs - \else - \spac_vspace_unknown - \fi - \else - \ifcsname\??vspace:\s!default\endcsname - \lastnamedcs - \else - \spac_vspace_unknown - \fi - \fi - \relax - \fi} - -%D Some preliminary code: a simple and fast hanger, for usage in macros. - -\installcorenamespace {hanging} - -\installdirectcommandhandler \??hanging {hanging} - -\setuphanging - [\c!distance=.5\emwidth, - \c!location=\v!left, - \c!n=\zerocount] - -\let\m_spac_hanging_location\empty - -\permanent\tolerant\protected\def\starthanging[#1]% - {\dontleavehmode\bgroup - \ifhastok={#1}% - \let\m_spac_hanging_location\empty - \setupcurrenthanging[#1]% - \else - \edef\m_spac_hanging_location{#1}% - \fi - \ifempty\m_spac_hanging_location - \edef\m_spac_hanging_location{\directhangingparameter\c!location}% - \fi - \dowithnextboxcs\spac_hanging_finish\hbox} - -\permanent\protected\def\stophanging - {\endgraf - \egroup} - -\def\spac_hanging_finish - {\scratchdistance\directhangingparameter\c!distance\relax - \ifdim\ht\nextbox>\strutht - \setbox\nextbox\tbox{\box\nextbox}% - \fi - \scratchcounter\directhangingparameter\c!n\relax - \ifnum\scratchcounter>\zerocount - \frozen\hangafter-\scratchcounter - \else - \getboxheight\scratchdimen\of\box\nextbox - \getnoflines\scratchdimen - \frozen\hangafter-\noflines - \fi - \ht\nextbox\strutht - \dp\nextbox\strutdp - \scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax - \ifx\m_spac_hanging_location\v!right - \frozen\hangindent\ifconditional\displaylefttoright-\fi\scratchwidth - \rlap{\hskip\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new - \else - \frozen\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} - -\let\stopfixed\relax - -\permanent\protected\def\startfixed - {\bgroup - \ifhmode - \expandafter\typo_fixed_start_h - \else - \expandafter\typo_fixed_start_v - \fi} - -\tolerant\def\typo_fixed_start_h[#1]% - {\enforced\let\stopfixed\typo_fixed_stop_h - \dowithnextbox{\typo_fixed_finish{#1}}% - \vbox\bgroup - %ignorespaces - \setlocalhsize} - -\protected\def\typo_fixed_stop_h - {%removeunwantedspaces - \egroup - \egroup} - -\tolerant\def\typo_fixed_start_v[#1]% - {\enforced\let\stopfixed\typo_fixed_stop_v - \startbaselinecorrection} - -\protected\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 - -\protected\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 - -%D Helper: - -\permanent\protected\def\checkedblank[#1]% - {\edef\p_blank{#1}% - \ifempty\p_blank - % ignore - \orelse\ifx\p_blank\v!none - % ignore - \else - \blank[\p_blank]% - \fi} - -% \setupwhitespace[line] -% \prerollblank[2*line] \the\prerolledblank -% \prerollblank[-2*line] \the\prerolledblank - -\newskip\prerolledblank - -\permanent\protected\def\prerollblank[#1]% - {\begingroup - \edef\p_blank{#1}% - \ifempty\p_blank - \global\prerolledblank\zeropoint - \orelse\ifx\p_blank\v!none - \global\prerolledblank\zeropoint - \else - % don't mess with \arskip here! - \scratchskip\plusten\lineheight - \setbox\scratchbox\vbox - {\vskip\scratchskip - \kern\zeropoint - \blank[\p_blank]}% - % \dimexpr doesn't work well with skips - \advance\scratchskip-\ht\scratchbox - \global\prerolledblank-\scratchskip - \fi - \endgroup} - -\newcount\c_spac_vspacing_ignore_parskip - -% \setupwhitespace[line] -% \setuphead[subject][after={\blank[packed]},style=\bfb] -% \subject{foo} -% test \par -% test \par -% \blank[packed] % \ignoreparskip -% test \par -% test \par -% \ignoreparskip -% test \par -% test \par -% \setuphead[subject][after={\blank[nowhite]},style=\bfb] -% \subject{foo} -% test \par -% test \par - -\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} - -\protect \endinput diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 01700f5fc..c96cba81a 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 09db66519..cbfa899a4 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/strc-bkm.mkxl b/tex/context/base/mkiv/strc-bkm.mkxl deleted file mode 100644 index c5bd87324..000000000 --- a/tex/context/base/mkiv/strc-bkm.mkxl +++ /dev/null @@ -1,182 +0,0 @@ -%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}{} - -% \enabledirectives[references.bookmarks.preroll] - -\unprotect - -%D Bookmarks are a very viewer dependent feature. They are mostly used as additional -%D table of contents and therefore relate directly to lists. -%D -%D A bookmark list is added to the document only when interaction is enabled. The -%D given lists are bookmarked and a second argument specifies the opened bookmark -%D 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 \type -%D {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 one does -%D not want \quotation {Contents} in a table of contents but it has to be in the -%D 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 - -\aliased\let\setupbookmarks\setupbookmark - -\permanent\protected\def\bookmark - {\iflocation - \expandafter\strc_bookmarks_bookmark_yes - \else - \expandafter\strc_bookmarks_bookmark_nop - \fi} - -\tolerant\def\strc_bookmarks_bookmark_yes[#1]#:#2% - {\begingroup - \simplifycommands - \ifnum\thenamedheadlevel{#1}>\zerocount - \clf_overloadbookmark{#1}{\detokenize\expandafter{\normalexpanded{#2}}}% - \else - \writetolist[#1]{#2}{}% todo: a dedicated bookmark writer - \fi - \endgroup} - -\tolerant\def\strc_bookmarks_bookmark_nop[#1]#:#2% - {} - -\permanent\protected\def\placebookmarks - {\iflocation - \expandafter\strc_bookmarks_place_yes - \else - \expandafter\gobblethreeoptionals - \fi} - -\let\m_bookmarks_names \empty -\let\m_bookmarks_opened\empty - -\tolerant\def\strc_bookmarks_place_yes[#1]#*[#2]#*[#3]% - {\begingroup - \edef\m_bookmarks_names{#1}% - \edef\m_bookmarks_opened{#2}% - \ifempty\m_bookmarks_names - \edef\m_bookmarks_names{\namedlistparameter\v!content\c!list}% - \fi - \ifempty\m_bookmarks_names - \let\m_bookmarks_names\v!all - \fi - \ifparameters\or\or - \doifelseassignment{#2}{\let\m_bookmarks_opened\empty\setupcurrentbookmark[#2]}\donothing - \or - \setupcurrentbookmark[#3]% no every so not all possible - \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/tex/context/base/mkiv/strc-blk.mkxl b/tex/context/base/mkiv/strc-blk.mkxl deleted file mode 100644 index 4cfbd51eb..000000000 --- a/tex/context/base/mkiv/strc-blk.mkxl +++ /dev/null @@ -1,171 +0,0 @@ -%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}{} - -\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}% - \frozen\setuevalue{\e!begin\currentblock}{\strc_blocks_begin{\currentblock}}% - \frozen\letvalue {\e!end \currentblock}\donothing -\to \everydefineblock - -% We need to prevent too much lookahead which will gobble newlines that are needed -% for buffers. See blocks-002.tex as example. - -% maybe: systemmode "block:" - -\let\m_block \empty -\let\m_subblock\empty - -\protected\def\strc_blocks_begin#1% - {\edef\m_block {#1}% - \let \m_subblock\empty - \doifelsenextoptionalcs\strc_blocks_begin_yes\strc_blocks_begin_nop} - -\protected\def\strc_blocks_begin_yes[#1]% - {\doifelseassignmentcs{#1}% - \strc_blocks_begin_indeed - \strc_blocks_begin_tagged - {#1}} - -\protected\def\strc_blocks_begin_tagged#1% - {\edef\m_subblock{#1}% - \doifelsenextoptionalcs\strc_blocks_begin_yes_yes\strc_blocks_begin_nop} - -\protected\def\strc_blocks_begin_yes_yes[#1]% - {\strc_blocks_begin_indeed{#1}} - -\protected\def\strc_blocks_begin_nop - {\strc_blocks_begin_indeed{}} - -\protected\def\strc_blocks_begin_indeed#1% - {\normalexpanded{\buff_pickup{\??block}{\e!begin\m_block}{\e!end\m_block}}% - {}% - {\clf_savestructureblock{\m_block}{\m_subblock}{#1}{\??block}}% - \plusone} - -\let\strc_blocks_setup\relax - -\newconstant \c_strc_blocks_index -\newconditional\c_strc_blocks_display - -\permanent\protected\def\dostarthiddenblock % called at lua end - {\begingroup - \visiblefalse % blocks float - \startnointerference - \strc_start_block} - -\permanent\protected\def\dostophiddenblock % called at lua end - {\strc_stop_block - \stopnointerference - \endgroup} - -\permanent\protected\def\dostartnormalblock % called at lua end - {\begingroup - \visibletrue - \strc_start_block} - -\permanent\protected\def\dostopnormalblock % called at lua end - {\strc_stop_block - \endgroup} - -\def\strc_start_block#1#2% - {\edef\currentblock{#2}% - \c_strc_blocks_index#1\relax - \strc_blocks_setup - \let\strc_blocks_setup\relax - \edef\p_alternative{\blockparameter\c!alternative}% - \ifx\p_alternative\v!text - \setfalse\c_strc_blocks_display - \else - \settrue\c_strc_blocks_display - \fi - \ifconditional\c_strc_blocks_display - \blockparameter\c!before - \fi - \begingroup - \usesetupsparameter\blockparameter\relax - \dostarttagged\t!block\currentblock - \useblockstyleandcolor\c!style\c!color - \blockparameter\c!inner % old - \ifconditional\c_strc_blocks_display - \usealignparameter\blockparameter - \else - \blockparameter\c!left - \fi - \ignorespaces} - -\def\strc_stop_block - {\removeunwantedspaces - \ifconditional\c_strc_blocks_display - \par - \else - \blockparameter\c!right - \fi - \dostoptagged - \endgroup - \ifconditional\c_strc_blocks_display - \blockparameter\c!after - \fi} - -\tolerant\def\strc_blocks_set_state[#1]#*[#2]#*[#3]% state name tag % todo: we could use the lua one directly - {\clf_setstructureblockstate{#1}{#2}{#3}} - -\tolerant\def\strc_blocks_select[#1]#*[#2]#*[#3]#*[#4]% state name tag setups - {\begingroup - \ifhastok={#3}% - \getparameters[\??blocktemp][\c!criterium=\v!text,#3]% - \def\strc_blocks_setup{\setupcurrentblock[#3]}% - \clf_selectstructureblock{#1}{#2}{}{\csname\??blocktemp\c!criterium\endcsname}% - \else - \getparameters[\??blocktemp][\c!criterium=\v!text,#4]% - \def\strc_blocks_setup{\setupcurrentblock[#4]}% - \clf_selectstructureblock{#1}{#2}{#3}{\csname\??blocktemp\c!criterium\endcsname}% - \fi - \endgroup} - -\permanent\def\blockuservariable#1% - {\clf_structureblockuservariable\c_strc_blocks_index{#1}} - -% hide : save, if [+] also hidden execute -% keep : save and normal execute -% use : normal execute unless [-] -% process: hidden execute unless [-] -% select : idem use - -\permanent\protected\def\hideblocks {\strc_blocks_set_state[hide]} -\permanent\protected\def\keepblocks {\strc_blocks_set_state[keep]} -\permanent\protected\def\useblocks {\strc_blocks_select [use]} -\permanent\protected\def\processblocks{\strc_blocks_select [process]} -\permanent\protected\def\selectblocks {\strc_blocks_select [use]} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-con.mklx b/tex/context/base/mkiv/strc-con.mklx deleted file mode 100644 index 08420a7ef..000000000 --- a/tex/context/base/mkiv/strc-con.mklx +++ /dev/null @@ -1,1158 +0,0 @@ -%D \module -%D [ file=strc-con, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Constructions, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Constructions} - -\registerctxluafile{strc-con}{} - -% todo: check why \copy .. probably mkii leftover -% -% todo: check if commands similar to lists -% todo: \strc_constructions_setup_counter\strc_constructions_setup_counter{#1} in setup ... synchronization -% -% ? : \def\showdnlisttext{\constructionparameter\c!listtext} % space in default -% -% maybe: pickup text and store in buffer ... -% -% \@@notemakeconstruction[##1]{}{##2}% -% \expandafter\endgroup\noteparameter\c!next}} -% -% todo: \currentconstructionattribute : can be a counter instead - -%D Constructions are just descriptions but a bit more abstract so that we can -%D conveniently build upon them. They are not really meant for users but module -%D writers might find them useful. We mention a couple of parameters but these are -%D only mentioned because in the shared code we map all resolvers to constructions. -%D -%D On top of constructions we build descriptions, enumerations, notes, labels and -%D maybe some day more. - -\unprotect - -%D Todo: - -\installcorenamespace{construction} - -\installcommandhandler \??construction {construction} \??construction - -\aliased\let\setupconstructions\setupconstruction - -\setupconstructions[% - %c!title=, - %c!text=, - % - %c!style=, - %c!color=, - %c!command=, - %c!align=, - % - %c!headstyle=, - %c!headcolor=, - %c!headalign=, - % - %c!titlestyle=, - %c!titlecolor=, - %c!titlecommand=, - %c!titleleft=, - %c!titleright=, - % - %c!closesymbol=, - %c!closecommand=, - % - \c!alternative=\v!left, - \c!display=\v!yes, - \c!width=7\emwidth, - \c!distance=\emwidth, - \c!stretch=.50, - \c!shrink=.25, - \c!titledistance=.5\emwidth, - %c!hang=, - %c!sample=, - \c!margin=\v!no, - \c!before=\blank, - \c!inbetween=\blank, - \c!after=\blank, - %c!indentnext=, - %c!indenting=, - % - \c!expansion=\v!no, - %c!xmlsetup=, - %s!catcodes=, -] - -%D Constructions and alike uses similar structures. In order to prevent issues -%D we freeze some states. There is some overhead in the intermediate define -%D step (as we could set them directly) but this is more flexible (and looks -%D nicer). Keep in mind that descriptions, enumeration and notations are all -%D independent and that we just remap the resolvers. - -% \defineconstruction[test][handler=description,level=1] -% \defineconstruction[test][parent][handler=description,level=3] - -\installcorenamespace{constructionmain} % frozen after definition -\installcorenamespace{constructionlevel} % frozen after definition -\installcorenamespace{constructionclass} % frozen after definition - -\let\currentconstructionmain \empty -\let\currentconstructionlevel \empty -\let\currentconstructionhandler\empty - -\settrue\c_strc_constructions_define_commands % use with care, might become a proper key - -\appendtoks - \ifempty\currentconstructionparent - \letvalue{\??constructionmain\currentconstruction}\currentconstruction - \definelist[\currentconstruction]% goodie - \else - \letvalue{\??constructionmain\currentconstruction}\currentconstructionparent - \definelist[\currentconstruction][\currentconstructionparent]% goodie - \fi - \instance\setevalue{\??constructionlevel\currentconstruction}{\number\constructionparameter\c!level}% - \instance\setevalue{\??constructionclass\currentconstruction}{\constructionparameter\s!handler}% -\to \everydefineconstruction - -% todo: inhibit this when we have a different handle .. current we cannot do \frozen - -\appendtoks - \ifconditional\c_strc_constructions_define_commands - %% \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}% - \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start[\currentconstruction]}% - \instance\setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}% - \fi -\to \everydefineconstruction - -%D Just a basic environment (mostly for testing). We will provide a 'setup' based -%D plugin once the rest is sorted out. - -\tolerant\protected\def\strc_constructions_start[#1]#*[#2]#*[#3]% - {\begingroup - \strc_constructions_initialize{#1}% - \strc_constructions_register[#3][\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#2]% - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\protected\def\strc_constructions_stop - {\csname\??constructionstophandler\currentconstructionhandler\endcsname - \endgroup} - -%D As we will build on top of the generic construction mechanism we have handlers -%D as a sort of plug in mechanism. In order to have some consistency we share -%D some namespaces. - -\installcorenamespace{constructioninitializer} -\installcorenamespace{constructionfinalizer} - -\installcorenamespace{constructionmainhandler} -\installcorenamespace{constructioncommandhandler} -\installcorenamespace{constructionstarthandler} -\installcorenamespace{constructionstophandler} - -\installcorenamespace{constructiontexthandler} -\installcorenamespace{constructionnotehandler} - -\protected\def\strc_constructions_initialize#1% class instance - {\edef\currentconstruction{#1}% - \enforced\let\currentconstructionhash\??construction - \let\currentconstructionlistentry\!!zerocount - \enforced\expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname - \enforced\expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname - \enforced\expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname - \csname\??constructioninitializer\currentconstructionhandler\endcsname} - -\protected\def\strc_constructions_finalize - {\csname\??constructionfinalizer\currentconstructionhandler\endcsname - \strc_constructions_discard} - -\newconditional\c_strc_constructions_number_state -\newconditional\c_strc_constructions_title_state - -\protected\setvalue{\??constructioninitializer\v!construction}% - {\setfalse\c_strc_constructions_number_state - \setfalse\c_strc_constructions_title_state} - -\protected\setvalue{\??constructionfinalizer\v!construction}% - {} - -%D We keep the command variant around but rather would move to the start-stop one. -%D Also, passing the title as argument has some history so we need to keep that as -%D well. - -% \ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi - -% \startuseMPgraphic{MyFrame} -% picture p ; numeric o ; path a, b ; pair c ; -% p := textext.rt("\FunnyFramed{\currentconstructiontext}") ; -% % p := textext.rt("\wrappedconstruction{\FunnyFramed{\currentconstructiontext}}") ; -% % p := textext.rt("\FunnyFramed{\wrappedconstruction{\currentconstructiontext}}") ; -% % p := textext.rt("\FunnyFramed{\wrappedcurrentconstruction}") ; -% ... -% \stopuseMPgraphic -% -% \defineoverlay[MyFrame][\useMPgraphic{MyFrame}] -% -% \defineframedtext -% [MyText] -% [frame=off, -% background=MyFrame] -% -% \defineenumeration[Theorem] -% [alternative=empty, -% before=\startMyText, -% after=\stopMyText] - -\newtoks\everyconstruction - -\permanent\protected\def\currentconstructiontext - {\begstrut - \csname\??constructiontexthandler\currentconstructionhandler\endcsname - \endstrut} - -\permanent\protected\def\currentconstructionsample - {\begstrut - \constructionparameter\c!text - \p_strc_constructions_sample - \endstrut} - -\permanent\protected\def\wrappedconstruction#1% - {\begingroup - \iftrialtypesetting \else - \currentconstructionsynchronize - \c_attr_destination\currentconstructionattribute\relax - \fi - #1% - \endgroup} - -\permanent\protected\def\wrappedcurrentconstruction - {\begingroup - \iftrialtypesetting \else - \currentconstructionsynchronize - \c_attr_destination\currentconstructionattribute\relax - \fi - \currentconstructiontext - \endgroup} - -\protected\setvalue{\??constructionmainhandler\v!construction}#1% - {\iftrialtypesetting \else - \begingroup - \currentconstructionsynchronize % reinstated - \c_attr_destination\currentconstructionattribute\relax % todo, whole text - \signalcharacter - \endgroup - \fi#1} - -\protected\setvalue{\??constructiontexthandler\v!construction}% - {\begingroup - \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext - \the\everyconstruction - \constructionparameter\c!headcommand - {\strut - \constructionparameter\c!text - \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}% - \endgroup} - -\protected\def\strc_constructions_stored_start - {\begingroup % brrr \endgroup elsewhere ... will be sorted out - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\protected\def\strc_constructions_stored_stop - {\csname\??constructionstophandler\currentconstructionhandler\endcsname} - -\newconstant\c_strc_constructions_nested_state % to be redone - -\def\resetconstructions % to be used in e.g. footnotes - {\c_strc_constructions_nested_state\zerocount} - -\protected\setvalue{\??constructioncommandhandler\v!construction}% - {\endgroup} - -\let\p_strc_constructions_sample \empty -\let\p_strc_constructions_align \empty -\let\p_strc_constructions_indenting \empty -\let\p_strc_constructions_width \empty -\let\p_strc_constructions_aligntitle \empty -\let\p_strc_constructions_renderingsetup\empty -\let\p_strc_constructions_headalign \empty -\let\p_strc_constructions_hang \empty -\let\p_strc_constructions_inbetween \empty -\let\p_strc_constructions_closesymbol \empty -\let\p_strc_constructions_distance \empty - -\newconditional\c_strc_constructions_distance_none - -\def\strc_constructions_set_width_and_distance - {\assignwidth - \p_strc_constructions_width - \constructionsheadwidth - {\unhcopy\constructionheadbox} - \constructionsheaddistance} - -\def\strc_constructions_preroll_head#content% - {\setbox\constructionheadbox\hbox - {\forgetall - \dontcomplain - \settrialtypesetting - \csname\??constructionmainhandler\currentconstructionhandler\endcsname#content}} - -\def\strc_constructions_ignore_head - {\constructionsheaddistance\zeropoint - \constructionsheadwidth \zeropoint - % we also need to make sure that no stretch creeps in (new per 2015-02-02, for Alan) - \settrue\c_strc_constructions_distance_none} - -\overloaded\let\currentconstructionhash\??construction - -\protected\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing - {\dostarttaggedchained\t!construction\currentconstruction\currentconstructionhash -% \dotagsetconstruction - \constructionparameter\c!before - \begingroup - \edef\currentconstructionalternative{\constructionparameter\c!alternative}% - \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% - % catch fuzzyness - \ifempty\p_strc_constructions_renderingsetup - \letconstructionparameter\c!alternative\v!left - \let\currentconstructionalternative\v!left - \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% - \else - \doifnotsetups\p_strc_constructions_renderingsetup - {\letconstructionparameter\c!alternative\v!left - \let\currentconstructionalternative\v!left - \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}}% - \fi - % - \doadaptleftskip{\constructionparameter\c!margin}% - \setlocalhsize % so we can use \localhsize in width assignments - \edef\p_strc_constructions_distance{\constructionalternativeparameter\c!distance}% - \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}% - \ifx\p_strc_constructions_distance\v!none - \settrue\c_strc_constructions_distance_none - \constructionsheaddistance\zeropoint - \else - \setfalse\c_strc_constructions_distance_none - \constructionsheaddistance\p_strc_constructions_distance\relax - \ifdim\constructionsheaddistance=\zeropoint - \ifx\p_strc_constructions_width\v!broad - \constructionsheaddistance\emwidth - \orelse\ifx\p_strc_constructions_width\v!line - \constructionsheaddistance\emwidth - \fi - \fi - \fi - % inefficient and not always needed, for instance not with margins so we will make checkers - % per alternative some day (especially in labels this is unwanted overhead) - % - % maybe we should have an option as i cannot oversee the consequences now - % - % \edef\p_strc_constructions_sample{\constructionparameter\c!sample}% - % \ifempty\p_strc_constructions_sample - % \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}% - \ifempty\p_strc_constructions_sample - \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}% - \ifempty\p_strc_constructions_align \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}% - \ifempty\p_strc_constructions_indenting \else - \indenting[\p_strc_constructions_indenting]% \use... - \fi - % - \dostoptagged % tag - \dostarttagged\t!constructioncontent\empty - %\freezeparagraphproperties - \updateparagraphshapes - \ignorespaces} % args not needed - -\protected\setvalue{\??constructionstophandler\v!construction}% - {\strc_constructions_close_symbol_place - \doifnot{\constructionparameter\c!display}\v!no\par - \dostoptagged % content - \dostoptagged % construction - \endgroup - \constructionparameter\c!after - \useindentnextparameter\constructionparameter - \strc_constructions_finalize -% \endgroup - \dorechecknextindentation} - -\protected\def\boxedconstructionhead#1% - {\doifelse{\constructionalternativeparameter\c!alignbottom}{\v!yes}\vbox\vtop - {\hsize\constructionsheadwidth - \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}% - \ifempty\p_strc_constructions_headalign \else - \setupalign[\p_strc_constructions_headalign]% \use... - \fi - #1}} - -\installcorenamespace{constructionalternative} -\installcorenamespace{constructionrenderings} - -% see lists: alternativemethods ... todo -% -% there will be a proper interface to variables - -\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative - -\setupconstructionalternative - [%c!left=, % no inheritance - %c!right=,% no inheritance - \c!width=\constructionparameter\c!width, - \c!distance=\constructionparameter\c!distance, - \c!stretch=\constructionparameter\c!stretch, - \c!shrink=\constructionparameter\c!shrink] - -\defineconstructionalternative - [\v!left] - [%\c!width=7em, - %\c!distance=1em, - \c!renderingsetup=\??constructionrenderings:\v!left] - -\defineconstructionalternative - [\v!right] - [%\c!width=7em, - %\c!distance=1em, - \c!renderingsetup=\??constructionrenderings:\v!right] - -\defineconstructionalternative - [\v!inmargin] - [\c!renderingsetup=\??constructionrenderings:\v!inmargin] - -\defineconstructionalternative - [\v!inleft] - [\c!renderingsetup=\??constructionrenderings:\v!inleft] - -\defineconstructionalternative - [\v!inright] - [\c!renderingsetup=\??constructionrenderings:\v!inright] - -\defineconstructionalternative - [\v!margin] - [\c!renderingsetup=\??constructionrenderings:\v!margin] - -\defineconstructionalternative - [\v!leftmargin] - [\c!renderingsetup=\??constructionrenderings:\v!leftmargin] - -\defineconstructionalternative - [\v!rightmargin] - [\c!renderingsetup=\??constructionrenderings:\v!rightmargin] - -\defineconstructionalternative - [\v!innermargin] - [\c!renderingsetup=\??constructionrenderings:\v!innermargin] - -\defineconstructionalternative - [\v!outermargin] - [\c!renderingsetup=\??constructionrenderings:\v!outermargin] - -\defineconstructionalternative - [\v!serried] - [\c!renderingsetup=\??constructionrenderings:\v!serried] - -\defineconstructionalternative - [\v!hanging] - [%\c!width=.75\emwidth - \c!renderingsetup=\??constructionrenderings:\v!hanging] - -\defineconstructionalternative - [\v!top] - [\c!renderingsetup=\??constructionrenderings:\v!top, - \c!width=\localhsize] - -\defineconstructionalternative - [\v!command] - [\c!renderingsetup=\??constructionrenderings:\v!command] - -\defineconstructionalternative - [\v!empty] - [\c!renderingsetup=\??constructionrenderings:\v!empty] - -\defineconstructionalternative - [\v!label] - [\c!renderingsetup=\??constructionrenderings:\v!label, - \c!width=] - -\newbox \constructionheadbox -\newskip \leftconstructionskip -\newskip \rightconstructionskip -\newdimen \constructionsheadwidth -\newdimen \constructionsheaddistance - -\def\strc_constructions_set_hang_box#1% messy left/rightskip - {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang - {\forgetall - \dontcomplain - \hsize\constructionsheadwidth\relax - \ifempty\p_strc_constructions_headalign - \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 - \ifempty\p_strc_constructions_headalign - \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% - {\ifempty\p_strc_constructions_hang - % nothing - \orelse\ifx\p_strc_constructions_hang\v!fit - \scratchdimen\htdp\constructionheadbox - \getnoflines\scratchdimen - \hangafter-\noflines - \orelse\ifx\p_strc_constructions_hang\v!broad - \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax - \getnoflines\scratchdimen - \hangafter-\noflines - \else - \hangafter-\p_strc_constructions_hang - \fi - \relax - \hangindent\ifx#1\v!right-\fi\constructionsheadwidth} - -\protected\def\flushconstructionheadbox - {\ifhbox\constructionheadbox\unhbox\else\box\fi\constructionheadbox} - -% The setups. These only deal with placement of the descriptor and initializing the -% environment. The wrapping happens elsewhere. - -% todo: optimize the setups with -% -% \ifconditional\c_strc_constructions_distance_none : no need for skip -% \ifzeropt\wd\constructionheadbox : no need for box and skips - -\startsetups[\??constructionrenderings:\v!left] - \edef\p_strc_constructions_hang{\constructionparameter\c!hang}% - \doifelsesetups{\??constructionrenderings:\v!left:\p_strc_constructions_hang} { - \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang} - } { - \directsetup{\??constructionrenderings:\v!left:\v!hanging} - } -\stopsetups - -\startsetups[\??constructionrenderings:\v!right] - \edef\p_strc_constructions_hang{\constructionparameter\c!hang} - \doifelsesetups{\??constructionrenderings:\v!right:\p_strc_constructions_hang} { - \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang} - } { - \directsetup{\??constructionrenderings:\v!right:\v!hanging} - } -\stopsetups - -\startsetups[\??constructionrenderings:\v!left:\v!none] - \enforced\let\\\crlf - \noindent - \strc_constructions_set_pure_box\v!flushleft - \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax - \rightskip\rightconstructionskip\relax - \llap { - \hpack to \leftskip { - \hskip\leftconstructionskip - \box\constructionheadbox % was copy - \hss - } - } - \nobreak - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!left:0] - \directsetup{\??constructionrenderings:\v!left:\v!none} -\stopsetups - -\startsetups[\??constructionrenderings:\v!left:] - \directsetup{\??constructionrenderings:\v!left:\v!none} -\stopsetups - -\startsetups[\??constructionrenderings:\v!right:\v!none] - \enforced\let\\\crlf - \noindent - \leftskip\leftconstructionskip - \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax - %\strc_constructions_pure_hang_box\raggedleft - \strc_constructions_set_pure_box\v!flushright - \rlap { - \hskip\dimexpr\hsize-\leftskip-\rightskip\relax - \copy\constructionheadbox - \hskip\rightconstructionskip - } - \nobreak - \advance\rightskip \constructionsheaddistance - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!right:0] - \directsetup{\??constructionrenderings:\v!right:\v!none} -\stopsetups - -\startsetups[\??constructionrenderings:\v!right:] - \directsetup{\??constructionrenderings:\v!right:\v!none} -\stopsetups - -\startsetups[\??constructionrenderings:\v!left:\v!margin]% - \enforced\let\\\crlf - \noindent - \strc_constructions_set_pure_box\v!flushleft - \llap { - \hpack to \constructionsheadwidth { - \box\constructionheadbox % was copy - \hss - } - \hskip\constructionsheaddistance - } - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!right:\v!margin]% - \enforced\let\\\crlf - \noindent - \strc_constructions_set_pure_box\v!flushright - \rlap { - \hskip\constructionsheaddistance - \hpack to \constructionsheadwidth { - \box\constructionheadbox % was copy - \hss - } - } - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!left:\v!hanging]% - \enforced\let\\\crlf - \dontcomplain - \advance\constructionsheadwidth \constructionsheaddistance - \strc_constructions_set_hang_box\v!flushleft - \strc_constructions_set_hang\v!left - \noindent - \llap { - \tpack to \zeropoint { - \box\constructionheadbox - } - } - \nobreak - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!right:\v!hanging]% - \enforced\let\\\crlf - \dontcomplain - \advance\constructionsheadwidth \constructionsheaddistance - \strc_constructions_set_hang_box\v!flushright - \strc_constructions_set_hang\v!right - \noindent - \rlap { - \hpack to \dimexpr\hsize-\leftskip-\rightskip\relax { - \hss - \tpack to \zeropoint { - \box\constructionheadbox - } - } - } - \nobreak - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!top] - % \strc_sectioning_prevent_page_break % commented per 31/5/2019 - \enforced\let\\\space - \noindent - \copy\constructionheadbox % why copy ? - \par - \nobreak - \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}% - \ifempty\p_strc_constructions_inbetween \else - \p_strc_constructions_inbetween - % shouldn't this move to after the fi? - \directcheckedvspacing\v!samepage - \fi - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -% why copy? historic reason? - -\startsetups[\??constructionrenderings:\v!margin] - \enforced\let\\\crlf - \noindent - \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!leftmargin] - \enforced\let\\\crlf - \noindent - \inleft[\c!scope=\v!local]{\flushconstructionheadbox}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!rightmargin] - \enforced\let\\\crlf - \noindent - \inright[\c!scope=\v!local]{\flushconstructionheadbox}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!innermargin] - \enforced\let\\\crlf - \noindent - \ininner[\c!scope=\v!local]{\flushconstructionheadbox}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!outermargin] - \enforced\let\\\crlf - \noindent - \inouter[\c!scope=\v!local]{\flushconstructionheadbox}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!inmargin] - \directsetup{\??constructionrenderings:\v!margin} -\stopsetups - -\startsetups[\??constructionrenderings:\v!inleft] - \directsetup{\??constructionrenderings:\v!leftmargin} -\stopsetups - -\startsetups[\??constructionrenderings:\v!inright] - \directsetup{\??constructionrenderings:\v!rightmargin} -\stopsetups - -\startsetups[\??constructionrenderings:\v!serried] - % already set? - \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace - \doifelsesetups{\??constructionrenderings:\v!serried:\p_strc_constructions_width} { - \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width} - } { - \directsetup{\??constructionrenderings:\v!serried:\v!wide} - } -\stopsetups - -\startsetups[\??constructionrenderings:\v!serried:\v!fit] - \enforced\let\\\crlf - \noindent - \flushconstructionheadbox - \nobreak - \hskip\constructionsheaddistance\relax - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!serried:\v!broad] - \enforced\let\\\crlf - \noindent - \flushconstructionheadbox - \ifconditional\c_strc_constructions_distance_none \else - \nobreak - \hskip\constructionsheaddistance - \s!plus \constructionalternativeparameter\c!stretch\constructionsheaddistance - \s!minus\constructionalternativeparameter\c!shrink \constructionsheaddistance - \relax - \fi - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!serried:] - \directsetup{\??constructionrenderings:\v!serried:\v!broad} -\stopsetups - -\startsetups[\??constructionrenderings:\v!serried:\v!wide] - \enforced\let\\\crlf - \noindent - \hbox to \constructionsheadwidth { - \flushconstructionheadbox - \hss - } - \nobreak - \hskip\constructionsheaddistance\relax - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!hanging] - % tricky: leftskipadaption is somewhat unpredictable - \enforced\let\\\crlf - \noindent - \advance\leftskip-\leftskipadaption\relax - \ifdim\leftskipadaption=\zeropoint - \leftskipadaption1.5\emwidth\relax % just some default - \ifnum\c_strc_constructions_nested_state=\plusone - \ifdim\leftskip>\zeropoint \relax - \leftskipadaption\leftskip - \fi - \fi - \fi - \ifnum\c_strc_constructions_nested_state>\zerocount % was \ifnum\c_strc_constructions_nested_state=\plusone - \advance\leftskip\leftskipadaption % but we're already further on - \fi - \hskip-\leftskipadaption\relax - \ifhbox\constructionheadbox \unhbox\else\box\fi\constructionheadbox - \ifconditional\c_strc_constructions_distance_none \else - % we used to have just a kern, but long lines look bad then - \scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi - \hskip \scratchdistance - \s!plus \constructionalternativeparameter\c!stretch\scratchdistance - \s!minus\constructionalternativeparameter\c!shrink \scratchdistance - \fi - \ifhmode - \ifx\p_strc_constructions_width\v!line - \hfill\break - \else - \allowbreak - \fi - \fi - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -%D \starttyping -%D \setupfootnotation[location=command,headcommand=\llap] -%D \stoptyping - -\startsetups[\??constructionrenderings:\v!command] - \noindent - \constructionparameter\c!headcommand{\flushconstructionheadbox} - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!empty] - \noindent - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -\startsetups[\??constructionrenderings:\v!label] - \dontleavehmode - \begingroup - \constructionparameter\c!headcommand{\flushconstructionheadbox} - \endgroup -\stopsetups - -\ifcase\contextlmtxmode \else - % just an empty check so that we can grep for contextlmtxmode in mkiv files -\fi - -% \definedescription[whatever][alternative=right:bottom] -% -% \startwhatever{just a small\\example} -% \input ward -% \stopwhatever - -\defineconstructionalternative - [\v!right:\v!bottom] - [%\c!width=7em, - %\c!distance=1em, - \c!alignbottom=\v!yes, - \c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom] - -\startsetups[\??constructionrenderings:\v!right:\v!bottom] - \enforced\let\\\crlf - \noindent - \leftskip\leftconstructionskip - \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax - \parfillskip\zeropoint - \strc_constructions_set_pure_box\v!flushright - \directparwrapper \relax {% - \hfilll - \rlap - {\kern\constructionsheaddistance - \copy\constructionheadbox}% - }% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -%D This next feature will get an lmtx implementation (probably by using a new generic -%D close mechanism). - -% you can use \placeclosesymbol or \qed to place a symbol at the end of a -% construction - -\installcorenamespace{constructionclosesymbol} - -\let\placeclosesymbol\donothing -\let\qed \donothing - -\def\strc_constructions_close_symbol_reset % no need for global - {\global\expandafter\settrue\csname\??constructionclosesymbol\currentconstruction\endcsname - \let\placeclosesymbol\strc_constructions_close_symbol_place - \let\qed \strc_constructions_close_symbol_place} - -\protected\def\strc_constructions_close_symbol_place - {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname - \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname - \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}% - \ifempty\p_strc_constructions_closesymbol \else - \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected - \fi - \fi} - -\newif\ifnoconstructioncaption - -%D The storage macros: - -\let\currentconstructionlistentry\!!zerocount - -\protected\def\strc_constructions_register - {\clf_doifelselisthasentry\numexpr\currentconstructionlistentry\relax - \strc_constructions_register_nop - \strc_constructions_register_yes} - -% \def\strc_constructions_register{\strc_constructions_register_yes} - -\def\strc_constructions_register_nop[#1][#2]% #1=optional user data #2=interfaced-settings - %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}} - {} - -\def\strc_constructions_discard - {\iftrialtypesetting - % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}% - \clf_discardfromlist\currentconstructionlistentry\relax - \fi} - -\let\currentconstructionlistnumber \!!zerocount -\let\currentconstructionsynchronize\relax -\let\currentconstructionattribute \attributeunsetvalue - -\def\strc_constructions_register_yes[#1][#2]% #1=optional user data #2=interfaced-settings - {\begingroup % similar to structure so we might generalize this - \setupcurrentconstruction[#2]% % xdef's will become edef's - \xdef\currentconstructionexpansion {\constructionparameter\c!expansion}% - \xdef\currentconstructionxmlsetup {\constructionparameter\c!xmlsetup}% - \xdef\currentconstructioncatcodes {\constructionparameter\s!catcodes}% - \xdef\currentconstructionlabel {\constructionparameter\c!label}% - \xdef\currentconstructionreference {\constructionparameter\c!reference}% - \xdef\currentconstructionreferenceprefix{\constructionparameter\c!referenceprefix}% - %xdef\currentconstructionshownumber {\constructionparameter\c!number}% - \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}% - % - \ifempty\currentconstructionexpansion - \glet\currentconstructionexpansion\v!no - \fi - % - \ifempty\currentconstructionreferenceprefix - \glet\currentconstructionreferenceprefix\referenceprefix - \fi - \ifx\currentconstructionexpansion\s!xml - \xmlstartraw - \xdef\currentconstructiontitle {\constructionparameter\c!title}% - \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% - \xdef\currentconstructionmarking {\constructionparameter\c!marking}% - \xdef\currentconstructionlist {\constructionparameter\c!list}% - \xmlstopraw - \ifempty\currentconstructionlist - \glet\currentconstructionlist\currentconstructiontitle - \fi - \glet\currentconstructioncoding\s!xml - \else - \ifx\currentconstructionexpansion\v!yes - \xdef\currentconstructiontitle {\constructionparameter\c!title}% - \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% - \xdef\currentconstructionmarking {\constructionparameter\c!marking}% - \xdef\currentconstructionlist {\constructionparameter\c!list}% - \else - \xdef\currentconstructiontitle {\detokenizedconstructionparameter\c!title}% - \xdef\currentconstructionbookmark{\detokenizedconstructionparameter\c!bookmark}% - \xdef\currentconstructionmarking {\detokenizedconstructionparameter\c!marking}% - \xdef\currentconstructionlist {\detokenizedconstructionparameter\c!list}% - \iflocation \ifempty\currentconstructionbookmark - \begingroup - \simplifycommands - \xdef\currentconstructionbookmark{\detokenize\expandafter{\normalexpanded{\constructionparameter\c!title}}}% - \endgroup - \fi \fi - \fi - \ifempty\currentconstructionlist - \glet\currentconstructionlist\currentconstructiontitle - \fi - \glet\currentconstructioncoding\s!tex - \fi - % - \ifx\currentconstructiontitle\v!none % will become obsolete - \global\noconstructioncaptiontrue\global\noconstructionnumbertrue - \fi - % - \ifnoconstructioncaption % then why analyze anyway? - \endgroup - \let\currentconstructionlistnumber \relax - \let\currentconstructionsynchronize\relax - \let\currentconstructionattribute \relax - \else - \setnextinternalreferences{construction}\currentconstructionmain % plural - \relax - \scratchcounter\clf_addtolist - metadata { - kind {construction} - name {\currentconstructionmain} - % level structures.sections.currentlevel() - catcodes \catcodetable - } - references { - internal \locationcount - order \locationorder - reference {\currentconstructionreference} - prefix {\currentconstructionreferenceprefix} - % block {\currentsectionblock} - % section structures.sections.currentid(), - } - titledata { - label {\detokenize\expandafter{\currentconstructionlabel}} - title {\detokenize\expandafter{\currentconstructiontitle}} - \ifx\currentconstructionbookmark\currentconstructiontitle \else - bookmark {\detokenize\expandafter{\currentconstructionbookmark}} - \fi - \ifx\currentconstructionlist\currentconstructiontitle \else - list {\detokenize\expandafter{\currentconstructionlist}} - \fi - } - \ifconditional\c_strc_constructions_number_state - prefixdata { - prefix {\constructionparameter\c!prefix} - separatorset {\constructionparameter\c!prefixseparatorset} - conversion {\constructionparameter\c!prefixconversion} - conversionset {\constructionparameter\c!prefixconversionset} - set {\constructionparameter\c!prefixset} - segments {\constructionparameter\c!prefixsegments} - connector {\constructionparameter\c!prefixconnector} - } - numberdata { - numbers {\currentconstructionnumber} - separatorset {\constructionparameter\c!numberseparatorset} - conversion {\constructionparameter\c!numberconversion} - conversionset {\constructionparameter\c!numberconversionset} - starter {\constructionparameter\c!numberstarter} - stopper {\constructionparameter\c!numberstopper} - segments {\constructionparameter\c!numbersegments} - } - \or - % symbol - \fi - userdata {\detokenize{#1}} - \relax - % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}% - \clf_setinternalreference - prefix {\currentconstructionreferenceprefix}% - reference {\currentconstructionreference}% - internal \locationcount - view {\interactionparameter\c!focus}% - \relax - \normalexpanded {% - \endgroup - \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}% - \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}% - \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}% - }% - \fi} - -% This is not so nice, some day I'll just store the number with the entry -% and deal with all at the Lua end, but first we need to be able to set -% macros. - -\permanent\protected\def\reinstateconstructionnumberentry#1% was xdef - {\edef\currentconstructionattribute {\clf_getinternallistreference#1}% - \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} - -\permanent\protected\def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real - {\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination - \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} - -\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}} - -% Helpers: - -\def\currentconstructionnumber{\constructionparameter\s!counter} - -\protected\def\strc_constructions_next_indeed #get#tag#level{\strc_counters_increment_sub{#get{#tag}\s!counter}{#level}} -\protected\def\strc_constructions_reset_indeed#get#tag#level{\strc_counters_reset_sub {#get{#tag}\s!counter}{#level}} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-des.mklx b/tex/context/base/mkiv/strc-des.mklx deleted file mode 100644 index e63512c7f..000000000 --- a/tex/context/base/mkiv/strc-des.mklx +++ /dev/null @@ -1,194 +0,0 @@ -%D \module -%D [ file=strc-des, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Descriptions, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Descriptions} - -\unprotect - -\installcorenamespace{description} - -\installcommandhandler \??description {description} \??description - -\aliased\let\setupdescriptions\setupdescription - -% \setupdescription % check with old -% [\c!alternative=\descriptionparameter\c!location, -% \c!location=\v!left] - -\setupdescription % check with old - [\c!alternative=\v!left, - \c!headstyle=\v!bold, - \c!titlestyle=\v!bold, - %\c!style=, - %\c!color=, - %\c!headcolor=, - %\c!titlecolor=, - \c!width=7\emwidth, - \c!distance=\emwidth, - \c!titledistance=.5\emwidth, - %\c!hang=, - %\c!sample=, - %\c!align=, - %\c!headalign=, - \c!margin=\v!no, - \c!before=\blank, - \c!inbetween=\blank, - \c!after=\blank, - \c!indentnext=\v!yes, - \c!indenting=\v!never, - \c!titleleft=(, - \c!titleright=), - %\c!closesymbol=, - \c!closecommand=\wordright, - \c!display=\v!yes, - %\c!command=, - \c!titlecommand=, - \c!expansion=\v!no, - %\c!xmlsetup=, - %\s!catcodes=, - \c!title=\v!yes, - %\c!text=, - ] - -\appendtoks - \ifempty\currentdescriptionparent - \defineconstruction[\currentdescription][\currentdescriptionparent][\s!handler=\v!description,\c!level=1]% - \else - \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]% - \fi - % We can combine these but in tracing (or errors) using a different caller is nicer. - \frozen\instance\setuevalue {\currentdescription}{\strc_descriptions_command[\currentdescription]}% - \frozen\instance\setuevalue{\e!start\currentdescription}{\strc_descriptions_start [\currentdescription]}% - \frozen\instance\setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}% -\to \everydefinedescription - -\let\p_strc_constructions_title \empty - -\protected\setvalue{\??constructioninitializer\v!description}% - {\let \currentdescription \currentconstruction - \enforced\let\constructionparameter \descriptionparameter - \enforced\let\constructionnamespace \??description - \enforced\let\detokenizedconstructionparameter\detokenizeddescriptionparameter - \enforced\let\letconstructionparameter \letdescriptionparameter - \enforced\let\useconstructionstyleandcolor \usedescriptionstyleandcolor - \enforced\let\setupcurrentconstruction \setupcurrentdescription - \edef\p_strc_constructions_title{\constructionparameter\c!title}% - \ifx\p_strc_constructions_title\v!yes - \settrue\c_strc_constructions_title_state - \else - \setfalse\c_strc_constructions_title_state - \fi} - -% We keep the command variant around but rather would move to the -% start-stop one. Also, passing the title as argument has some -% history so we need to keep that as well. - -% \startdescription [reference] text \stopdescription -% \startdescription [reference]{title} text \stopdescription -% \startdescription [title=,title=,reference=] text \stopdescription - -% A bit over the top, the optional title but mkii has it too. - -\tolerant\protected\def\strc_descriptions_start[#1]#*[#2]% - {\begingroup - \strc_constructions_initialize{#1}% - \ifhastok={#2}% - \expandafter\strc_descriptions_start_setups - \orelse\ifconditional\c_strc_constructions_title_state - \expandafter\strc_descriptions_start_title - \else - \expandafter\strc_descriptions_start_reference - \fi[#2]} - -\protected\def\strc_descriptions_start_setups[#1]% - {\setfalse\c_strc_constructions_title_state - \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\protected\tolerant\def\strc_descriptions_start_title[#1]#*#=% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\protected\def\strc_descriptions_start_reference[#1]% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\protected\def\strc_descriptions_stop - {\csname\??constructionstophandler\currentconstructionhandler\endcsname} - -% \description [reference] text \par -% \description [reference] {title} text \par - -\tolerant\protected\def\strc_descriptions_command[#1]#*[#2]#:#*#=% - {\begingroup - \strc_constructions_initialize{#1}% - \ifhastok={#2}% - \expandafter\strc_descriptions_command_setups - \orelse\ifconditional\c_strc_constructions_title_state - \expandafter\strc_descriptions_command_title - \else - \expandafter\strc_descriptions_command_reference - \fi[#2]} - -\protected\def\strc_descriptions_command_setups[#1]% - {\setfalse\c_strc_constructions_title_state - \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% - \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} - -\protected\tolerant\def\strc_descriptions_command_title[#1]#:#*#=% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% - \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} - -\protected\def\strc_descriptions_command_reference[#1]% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% - \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} - -%D Handlers: - -\letcsname\??constructionmainhandler \v!description\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname -\letcsname\??constructioncommandhandler\v!description\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname -\letcsname\??constructiontexthandler \v!description\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname - -\protected\setvalue{\??constructioncommandhandler\v!description}% - {\dowithpar - {\csname\??constructionstarthandler\v!construction\endcsname}% - {\csname\??constructionstophandler \v!construction\endcsname\endgroup}} - -\protected\setvalue{\??constructionstarthandler\v!description}% - {\dogotopar - {\csname\??constructionstarthandler\v!construction\endcsname}} - -\protected\setvalue{\??constructionstophandler\v!description}% - {\csname\??constructionstophandler\v!construction\endcsname - \endgroup} - -%D For historic reasons we have (from now on undocumented): - -\definedescription - [tab] - [\c!alternative=\v!left, - \c!headstyle=\v!normal, - \c!headcolor=, - \c!style=\v!normal, - \c!color=, - \c!width=\v!broad, - \c!sample=\kern4\emwidth, % was \hskip but that no longer is okay - \c!before=, - \c!after=] - -\protected\def\setuptab - {\setupdescription[tab]} - -%D Maybe we should remove this definition. - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-doc.mkxl b/tex/context/base/mkiv/strc-doc.mkxl deleted file mode 100644 index 046f0b086..000000000 --- a/tex/context/base/mkiv/strc-doc.mkxl +++ /dev/null @@ -1,45 +0,0 @@ -%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}{} - -\unprotect - -%D This will move: - -\permanent\protected\def\setstructuresynchronization#1% todo: use ctxcontext - {\clf_setinternalreference - prefix {\currentstructurereferenceprefix}% - reference {\currentstructurereference} - internal \locationcount - view {\interactionparameter\c!focus}% - \relax - \enforced\xdef\currentstructureattribute - {\the\lastdestinationattribute}% - \enforced\xdef\currentstructuresynchronize - {\currentstructuresynchronize - \strc_lists_inject_enhance{#1}}} - -\permanent\protected\def\setstructurecomponentsynchronization#1% todo: use ctxcontext - {\clf_setinternalreference - prefix {\currentstructurecomponentreferenceprefix}% - reference {\currentstructurecomponentreference} - internal \locationcount - view {\interactionparameter\c!focus}% - \relax - \enforced\xdef\currentstructurecomponentattribute {\the\lastdestinationattribute}% - \enforced\xdef\currentstructurecomponentsynchronize{\strc_lists_inject_enhance{#1}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-enu.mklx b/tex/context/base/mkiv/strc-enu.mklx deleted file mode 100644 index c593a65b0..000000000 --- a/tex/context/base/mkiv/strc-enu.mklx +++ /dev/null @@ -1,371 +0,0 @@ -%D \module -%D [ file=strc-enu, % moved from strc-des -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Enumerations, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Enumerations} - -\unprotect - -% command -> headcommand - -%D Enumerations are just super descriptions. Therefore we implement -%D them as an extension. After all, the keys don't clash. In order -%D to be able to differentiate between specific settings we use -%D some flags. Unfortunately we have some historic differences -%D in default values. Therefore we push an extra step in the -%D parent chain (we might do the same for regular descriptions). - -%D In order to be more flexible with theorems Aditya Mahajan added -%D support for titles and endsymbols. At the same time we added more -%D flexible support for inheriting numbers. -%D -%D \startbuffer -%D \defineenumeration[one] -%D \defineenumeration[two] [one] % clone one -%D \defineenumeration[three] [counter=one,style=slanted] % only use counter of one -%D \defineenumeration[four] [three] % clone three -%D \defineenumeration[five] [three] [counter=five] % clone three and use own counter -%D \defineenumeration[six] [three] [counter=four] % clone tree and use counter four (undefined) -%D -%D \startone test test 6 \stopone -%D \starttwo test test 7 \stoptwo -%D \startthree test test 8 \stopthree -%D \startfour test test 9 \stopfour -%D \startfive test test 2 \stopfive -%D \startsix test test 10 \stopsix -%D \stopbuffer -%D -%D \typebuffer \start \getbuffer \stop -%D -%D \starttyping -%D \setupenumerations[one] [prefix=yes,prefixsegments=section] -%D \setupenumerations[two] [prefix=yes,prefixsegments=section] -%D \setupenumerations[three][prefix=yes,prefixsegments=section] -%D \setupenumerations[four] [prefix=yes,prefixsegments=chapter:section] -%D \setupenumerations[five] [prefix=yes,prefixsegments=chapter:section] -%D \setupenumerations[six] [prefix=yes,prefixsegments=chapter:section] -%D \stoptyping - -% list and titles are experimental -% -% \definedescription[test] [location=left,hang=4,headalign={right},distance=1em,list=test] -% \defineenumeration[lemma][title=yes,right=:,textdistance=1em, location=top, titlestyle=\bs,list=lemma] -% \defineenumeration[ammel][title=yes,right=:,textdistance=.5em,location=left,titlestyle=\it,width=9em] -% -% \placelist[enumeration:lemma] -% \placelist[description:test][width=0pt] -% -% \starttest {something something something} \input zapf \stoptest -% \startlemma {with a title of a certain length} \input tufte \stoplemma -% \startammel {with a title} \input zapf \stopammel -% -% \defineenumeration[lemma][...] -% \defineenumeration[titledlemma][lemma][title=yes,right=:,text=lemma,list=lemma] - -\installcorenamespace{enumeration} - -\installcommandhandler \??enumeration {enumeration} \??enumeration - -\installcounterassociation{enumeration} - -\let\setupenumerations\setupenumeration - -\setupenumeration % check with old - [\c!alternative=\v!top, - \c!headstyle=\v!bold, - \c!titlestyle=\v!bold, - %\c!style=, - %\c!color=, - %\c!headcolor=, - %\c!titlecolor=, - \c!width=8\emwidth, - %\c!distance=\zeropoint, - \c!distance=\emwidth, - \c!titledistance=.5\emwidth, - %\c!hang=, - %\c!sample=, - %\c!align=, - %\c!headalign=, - \c!margin=\v!no, - \c!before=\blank, - \c!inbetween=\blank, - \c!after=\blank, - \c!indentnext=\v!yes, - \c!indenting=\v!never, - \c!titleleft=(, - \c!titleright=), - %\c!closesymbol=, - \c!closecommand=\wordright, - \c!display=\v!yes, - %\c!command=, - \c!titlecommand=, - \c!expansion=\v!no, - %\c!xmlsetup=, - %\s!catcodes=, - \c!way=\v!by\v!text, - \c!prefix=\v!no, - \c!prefixconnector=., - %\c!starter=, - %\c!stopper=, - \c!text=\currentenumeration, - \c!number=\v!yes, % else description - \c!start=0, - \c!state=\v!start, - \c!levels=4] - -% to be considered: -% -% \let\??construction\??enumeration -% -% with push/pop (also at definition time) - -\protected\def\strc_define_commands_enumeration#tag#level#parent% - {\doifelsenothing{#parent} - {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}% - \setevalue{\??enumeration#tag:\s!parent}{\??enumeration}}% - {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}% - \setevalue{\??enumeration#tag:\s!parent}{\??enumeration#parent}}% - \frozen\instance\setuevalue{\e!next #tag}{\strc_enumerations_next {#tag}{\number#level}}% obsolete - \frozen\instance\setuevalue{\c!reset#tag}{\strc_enumerations_reset {#tag}{\number#level}}% obsolete - %frozen\instance\setuevalue{\c!set #tag}{\strc_enumerations_set {#tag}{\number#level}}% obsolete - \frozen\instance\setuevalue {#tag}{\strc_enumerations_command[#tag]}% we could pass level here as well (faster) - \frozen\instance\setuevalue{\e!start#tag}{\strc_enumerations_start [#tag]}% we could pass level here as well (faster) - \frozen\instance\setuevalue{\e!stop #tag}{\strc_enumerations_stop }} - -\appendtoks - \ifempty\currentenumerationparent - % 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 - \ifempty\p_counter % - \let\p_counter\currentenumeration - \fi - \doifelsecounter\p_counter\donothing{\strc_enumerations_define_counter\p_counter}% - \letenumerationparameter\s!counter\p_counter - %\strc_enumerations_setup_counter\currentenumeration -\to \everydefineenumeration - -\let\p_strc_constructions_title \empty -\let\p_strc_constructions_number\empty - -\protected\setvalue{\??constructioninitializer\v!enumeration}% - {\let \currentenumeration \currentconstruction - \enforced\let\constructionparameter \enumerationparameter - \enforced\let\constructionnamespace \??enumeration - \enforced\let\detokenizedconstructionparameter\detokenizedenumerationparameter - \enforced\let\letconstructionparameter \letenumerationparameter - \enforced\let\useconstructionstyleandcolor \useenumerationstyleandcolor - \enforced\let\setupcurrentconstruction \setupcurrentenumeration - \edef\p_strc_constructions_number{\constructionparameter\c!number}% - \ifx\p_strc_constructions_number\v!yes - \settrue\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_save\currentconstructionnumber - \fi - \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel - \else - \setfalse\c_strc_constructions_number_state - \fi - \edef\p_strc_constructions_title{\constructionparameter\c!title}% - \ifx\p_strc_constructions_title\v!yes - \settrue\c_strc_constructions_title_state - \else - \setfalse\c_strc_constructions_title_state - \fi} - -\protected\setvalue{\??constructionfinalizer\v!enumeration}% - {\ifconditional\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_restore\currentconstructionnumber - \fi - \fi} - -%D Interfaces: - -\let\strc_enumerations_command\strc_descriptions_command -\let\strc_enumerations_start \strc_descriptions_start -\let\strc_enumerations_stop \strc_descriptions_stop - -\protected\def\strc_enumerations_next {\strc_constructions_next_indeed \namedenumerationparameter} % #1#2 -\protected\def\strc_enumerations_reset{\strc_constructions_reset_indeed\namedenumerationparameter} % #1#2 -%unexpanded\def\strc_enumerations_set {\strc_constructions_set_indeed \namedenumerationparameter} % #1#2 - -%D Counters (maybe we can share this code): (not ok yet, messy with notes) - -% Maybe we should move counters to the construction level as more derived mechanisms -% use it \unknown\ so don't depend on names here! - -\def\strc_enumerations_define_counter#tag% todo: move inline - {\definecounter[#tag]% - \registerenumerationcounter{#tag}} - -\appendtoks - \synchronizeenumerationcounters -\to \everysetupenumeration - -\appendtoks - \synchronizeenumerationcounters -\to \everydefineenumeration - -%D Initializer: - -%D The handlers. - -\newtoks\everyenumeration - -\letcsname\??constructionmainhandler \v!enumeration\expandafter\endcsname\csname\??constructionmainhandler \v!description\endcsname -\letcsname\??constructioncommandhandler\v!enumeration\expandafter\endcsname\csname\??constructioncommandhandler\v!description\endcsname -\letcsname\??constructionstarthandler \v!enumeration\expandafter\endcsname\csname\??constructionstarthandler \v!description\endcsname -\letcsname\??constructionstophandler \v!enumeration\expandafter\endcsname\csname\??constructionstophandler \v!description\endcsname - -\protected\setvalue{\??constructiontexthandler\v!enumeration}% - {\begingroup - \useconstructionstyleandcolor\c!headstyle\c!headcolor - \strc_enumerations_text - \endgroup} - -\protected\def\strc_enumerations_text - {\the\everyenumeration % will become obsolete - \ifconditional\c_strc_constructions_number_state - \ifx\currentconstructionreference\!!plustoken - \strc_enumerations_full_number_symbol - \orelse\ifx\currentconstructionreference\!!minustoken - \strc_enumerations_full_number_nop - \else - \strc_enumerations_full_number_coupling - \fi - \else - \strc_enumerations_full_number_nop - \fi} - -\protected\def\strc_enumerations_inject_text_with_space - {\edef\p_text{\constructionparameter\c!text}% - \ifempty\p_text \else - \p_text - \removeunwantedspaces - \nobreakspace - \fi} - -\protected\def\strc_enumerations_inject_extra_text - {\ifconditional\c_strc_constructions_title_state - \clf_doifelselisthastitle{\currentconstructionmain}\numexpr\currentconstructionlistentry\relax - \strc_enumerations_inject_extra_text_indeed - \donothing - \fi} - -\protected\def\strc_enumerations_inject_text - {\constructionparameter\c!numbercommand - {\constructionparameter\c!text}} - -% head ( number title ) - -\protected\def\strc_enumerations_inject_extra_text_indeed - {\begingroup - \hskip\constructionparameter\c!titledistance % we listen to the headstyle - \useconstructionstyleandcolor\c!titlestyle\c!titlecolor - \constructionparameter\c!titlecommand - {\constructionparameter\c!titleleft - \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax - \constructionparameter\c!titleright}% - \endgroup} - -\protected\def\strc_enumerations_inject_symbol % todo check - {\constructionparameter\c!left - \constructionparameter\c!symbol - \constructionparameter\c!right} - -\protected\def\strc_enumerations_inject_number - {\constructionparameter\c!left - \constructionparameter\c!starter - \clf_savedlistprefixednumber{\currentconstructionmain}\currentconstructionlistentry\relax - \constructionparameter\c!stopper - \constructionparameter\c!right} - -\protected\def\strc_enumerations_inject_text_and_number - {\constructionparameter\c!numbercommand - {\strc_enumerations_inject_text_with_space - \strc_enumerations_inject_number}} - -\protected\def\strc_enumerations_inject_text_and_symbol - {\constructionparameter\c!numbercommand - {\strc_enumerations_inject_text_with_space - \strc_enumerations_inject_symbol}} - -\protected\def\strc_enumerations_full_number_yes - {\constructionparameter\c!headcommand - {\begstrut - \strc_enumerations_inject_text_and_number - \strc_enumerations_inject_extra_text - \endstrut}} - -\protected\def\strc_enumerations_full_number_nop - {\constructionparameter\c!headcommand - {\begstrut - \strc_enumerations_inject_text - \strc_enumerations_inject_extra_text - \endstrut}} - -\protected\def\strc_enumerations_full_number_symbol - {\constructionparameter\c!headcommand - {\begstrut - \strc_enumerations_inject_text_and_symbol - \strc_enumerations_inject_extra_text - \endstrut}} - -% to be used in for instance: -% -% coupling=questions .... coupling=answers -% -% we will provide some more control, like skipping etc or reference relates - -% to do / to be checked - -\protected\def\strc_enumerations_full_number_coupling - {\iflocation - \strc_enumerations_full_number_yes - \else - \iftrialtypesetting \else - % \doenumerationregistercoupling - \fi - \strc_enumerations_full_number_yes - \edef\p_coupling{\constructionparameter\c!coupling}% - \ifempty\p_coupling \else - \symbolreference[order(construction:\p_coupling:\the\locationorder)]% - \fi - \fi} - -\protected\def\strc_enumerations_skip_number_coupling[#tag]% e.g. for questions with no answer - {\clf_setnextreferenceorder{construction}{#tag}} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-flt.mklx b/tex/context/base/mkiv/strc-flt.mklx deleted file mode 100644 index 994ca288a..000000000 --- a/tex/context/base/mkiv/strc-flt.mklx +++ /dev/null @@ -1,2599 +0,0 @@ -%D \module -%D [ file=strc-flt, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Float Numbering, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%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}{} - -\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} -\installcorenamespace{floatframed} - -\installframedcommandhandler \??float {float} \??float -\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption -\installframedcommandhandler \??floatframed {floatframed} \??floatframed - -\aliased\let\setupfloats \setupfloat -\aliased\let\setupcaption \setupfloatcaption -\aliased\let\setupcaptions\setupfloatcaption - -\permanent\protected\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!offset=\v!overlay, - \c!frame=\v!off, - % \c!expansion=, - % \c!prefix=, - % \c!prefixconnector=, - % \c!way=, - % \c!prefixsegments=, - % \c!way=, - % \c!blockway=, - % \c!sectionnumber=, - % \c!separator=, - % \c!starter=, - % \c!stopper=, - \c!suffixseparator=, % currently rather hard coded - \c!suffix=\floatcaptionsuffix, - \c!distance=\emwidth, % plus .5\emwidth minus .25\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!grid=, - %\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!sidespaceinbetween=\rootfloatparameter\c!spacebefore, - \c!spacebeforeside=, % extra, not part of, can be used to add whitespace before text - \c!spaceafterside=, % idem - \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=\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!small, % the flush side float step (big, medium, small : always depth) - \c!ntop=2, - \c!nbottom=0, - \c!nlines=4, % used? - \c!topoffset=\zeropoint, - \c!bottomoffset=\zeropoint, - \c!freeregion=\v!yes, - %\c!local=, - %\c!bottombefore=, % e.g. \vfill - %\c!bottomafter=, - %\c!default=, % default location - \c!sidethreshold=.5\strutdp, % set to "old" to check with old method - \c!numbering=\v!yes, - \c!compress=\v!yes, % when possible pack floats when flushing - \c!compressdistance=\emwidth] - -\setupfloatframed - [\c!frame=\v!off, - \c!offset=\v!overlay, - \c!strut=\v!no] - -\appendtoks - \doifelse{\floatparameter\c!compress}\v!yes\settrue\setfalse\c_page_floats_pack_flushed - \d_page_floats_compress_distance\floatparameter\c!compressdistance\relax -\to \everysetupfloat - -%D We need to do it again here: - -\setupfloat - [\c!compress=\v!yes, % when possible pack floats when flushing - \c!compressdistance=\emwidth] - -%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 - -\permanent\tolerant\protected\overloaded\def\definefloat[#1]#*[#2]#*[#3]% name+plural+parent | name+parent+settings - {\ifarguments\or - \strc_floats_define_c[#1][#1]% - \or - \doifelsecommandhandler\??float{#2}% - {\strc_floats_define_a[#1][#1][#2]}% - {\strc_floats_define_c[#1][#2]}% - \orelse\ifhastok={#3}% - \strc_floats_define_b[#1][#2][#3]% - \else - \strc_floats_define_a[#1][#2][#3]% - \fi} - -\def\strc_floats_define_a[#1][#2][#3]% name names parent - {\definefloatcaption[#1][#3]% - \definefloatframed[#1][#3]% - \definecounter[#1][#3]% - \definelist[#1][#3]% - \copylabeltext[#1=#3]% - \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]% - \definefloatframed[#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]% - \definefloatframed[#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% - {\frozen\instance\setuevalue{\e!place\e!listof#2}{\strc_lists_place[#1]}% call will change - \frozen\instance\setuevalue{\e!complete\e!listof#2}{\strc_lists_complete[#1][#2]}% call will change - \frozen\instance\setuevalue{\e!place#1}{\strc_floats_place[#1]}% - \frozen\instance\setuevalue{\e!start\e!place#1}{\strc_floats_start_place[#1]}% - \frozen\instance\setuevalue{\e!stop\e!place#1}{\strc_floats_stop_place}% - \frozen\instance\setuevalue{\e!start#1\e!text}{\strc_floats_start_text[#1]}% - \frozen\instance\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: - -\protected\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}} - -\permanent\protected\def\thecurrentfloatnumbersuffix - {\doifsomething{\floatcaptionparameter\c!suffix} - {\floatcaptionparameter\c!suffixseparator - \floatcaptionparameter\c!suffix - \floatcaptionparameter\c!suffixstopper}} - -\permanent\protected\def\thecurrentfloatnumber - {\ifnofloatcaption \orelse \ifnofloatnumber \orelse \ifx\currentfloatnumber\relax \else - \namedtaggedlabeltexts - \t!floatlabel \currentfloat - \t!floatnumber\currentfloat - {\begstrut - \floatcaptionparameter\c!numbercommand - {\clf_savedlistprefixednumber{\currentfloat}\currentfloatnumber\relax - \thecurrentfloatnumbersuffix}% - \endstrut}% - \fi} - -\permanent\protected\def\thecurrentfloatcaption - {\ifnofloatcaption \orelse \ifemptyfloatcaption \orelse \ifx\currentfloatnumber\relax \else - \dostarttagged\t!floattext\empty - \begstrut - \floatcaptionparameter\c!textcommand - {\clf_savedlisttitle{\currentfloat}\numexpr\currentfloatnumber\relax}% - \endstrut - \dostoptagged - \fi} - -%D Captions. - -\let\floatcaptionsuffix\empty % an optional suffix -\let\floatcaptionnumber\empty % a logical counter - -% For a while these were placeholders: -% -%D \starttyping -%D \protected\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption} -%D \protected\def\setfloatcaption {\dodoubleempty\strc_floats_set_caption} -%D -%D \def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]} -%D \def\strc_floats_set_caption [#tag][#reference]#caption{[not supported]} -%D -%D \protected\def\placefloatcaptiontext [#tag]{[not suported yet]} -%D \protected\def\placefloatcaptionnumber [#tag]{[not suported yet]} -%D \protected\def\placefloatcaptionreference[#tag]{[not suported yet]} -%D \stoptyping -%D -%D because in \MKII\ we had: -%D -%D \starttyping -%D \let\placefloatlabel \placefloatcaption -%D \let\placefloatlabeltext \placefloatcaptiontext -%D \let\placefloatlabelreference\placefloatcaptionreference -%D \stoptyping -%D -%D But as it was never advertised we don't provide it in \MKIV. However, at some -%D point HvdM wanted this: -%D -%D \starttyping -%D \placefigure {labeltext-1} {\externalfigure[figure-1]} -%D \placefloatcaption[figure][title={labeltext-2}] \externalfigure[figure-2] -%D \placefigure {labeltext-3} {\externalfigure[figure-3]} -%D \stoptyping -%D -%D So there you have it: - -\permanent\tolerant\protected\def\placefloatcaption[#category]#spacer[#settings]#spacer[#userdata]% - {\ifarguments\or\else % >= 2 - % we need at least a category and title - \dontleavehmode - \bgroup - \edef\currentfloat{#category}% - \let\currentfloatcaption\currentfloat - \resetfloatcaptionparameter\c!reference - \resetfloatcaptionparameter\c!title - \resetfloatcaptionparameter\c!marking - \resetfloatcaptionparameter\c!list - \resetfloatcaptionparameter\c!bookmark - \setupcurrentfloatcaption[#settings]% - \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% - \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi - \strc_counters_increment\currentfloatcounter - \strc_counters_register_component - \s!float - \setupcurrentfloatcaption - \floatcaptionparameter - \detokenizedfloatcaptionparameter - \relax - \relax - \relax - [\s!name=\currentfloat, - \s!counter=\currentfloatcounter,% - \s!hascaption=\v!yes,% - \s!hasnumber=\v!yes,% - \s!hastitle=\v!yes]% - [#userdata]% - \glet\previousfloatnumber \m_strc_counters_last_registered_index - \glet\currentfloatnumber \m_strc_counters_last_registered_index - \glet\currentfloatattribute \m_strc_counters_last_registered_attribute - \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize - % - % \iflocation - % \c_attr_destination\currentfloatattribute\relax - % \fi - \currentfloatsynchronize - \strc_floats_make_complete_caption - % - \iftrialtypesetting\strc_counters_restore\currentfloatcounter\fi - \egroup - \fi} - -\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]}% - \strc_floats_make_complete_caption_before - \synchronizedisplaydirection % temp hack, till we have a proper model - \noindent - \gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking - \begingroup - \ifnofloatcaption - \global\d_strc_floats_caption_height\zeropoint - \global\d_strc_floats_caption_depth \zeropoint - \else - \usefloatcaptionstyleandcolor\c!style\c!color - \clf_doifelselisthastitle{\currentfloat}\numexpr\currentfloatnumber\relax - \donothing - \emptyfloatcaptiontrue - \ifnofloatnumber \orelse \ifnofloatcaption \else - \ifemptyfloatcaption - \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}% - \else - \doifelsenothing{\floatcaptionparameter\c!spaceinbetween} - {\scratchskip\floatcaptionparameter\c!distance\relax - \setbox\scratchbox\hbox - {\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor - \thecurrentfloatnumber - \floatcaptionparameter\c!headseparator - \dotfskip\scratchskip}% - \doifelse{\floatcaptionparameter\c!hang}\v!yes - {\leftskip\wd\scratchbox - \llap{\box\scratchbox}} - {\unhbox\scratchbox}% - \emergencystretch.5\scratchskip} - {\hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}% - \blank[\floatcaptionparameter\c!spaceinbetween]}% - \fi - \fi - \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor - \global\d_strc_floats_caption_height\strutheight - \global\d_strc_floats_caption_depth \strutdepth - \thecurrentfloatcaption\endgraf - \fi - \endgroup - \strc_floats_make_complete_caption_after - \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}} - -%let\strc_floats_make_complete_caption_before\relax -\let\strc_floats_make_complete_caption_after \relax - -\def\strc_floats_make_complete_caption_before - {\doifelseframed\floatcaptionparameter\strc_floats_make_complete_caption_before_indeed\relax} - -\def\strc_floats_make_complete_caption_before_indeed - {\edef\m_strc_align{\floatcaptionparameter\c!align}% - \edef\m_strc_strut{\floatcaptionparameter\c!strut}% - \letfloatcaptionparameter\c!align\v!normal - \letfloatcaptionparameter\c!strut\v!no - \inheritedfloatcaptionframed - \bgroup - \letfloatcaptionparameter\c!align\m_strc_align - \letfloatcaptionparameter\c!strut\m_strc_strut - \let\strc_floats_make_complete_caption_after\egroup} - -% \definefloat [figure-1] [figure] -% \definefloat [figure-2] [figure] -% \setupfloat [figure-1] [location=left,leftmargin=10mm] -% \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 -% -% \protected\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) - \ifzeropt\wd\b_strc_floats_caption - \global\emptyfloatcaptiontrue - \ifnofloatnumber - \global\nofloatcaptiontrue - \fi - \else - \global\emptyfloatcaptionfalse - \setbox\b_strc_floats_caption\hpack{\hskip\leftskip\box\b_strc_floats_caption}% - \fi - \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 \glet\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}}% - \ifempty\strc_float_realpage - \glet\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 - \glet\lastplacedfloat\currentfloat - \let\m_strc_floats_saved_userdata\empty - \let\currentfloatcaption\currentfloat} - -\let\askedfloatmethod \empty -\let\askedfloatoptions\empty - -\def\strc_floats_reset_variables - {\global\emptyfloatcaptionfalse - \global\nofloatcaptionfalse - \global\nofloatnumberfalse - \glet\askedfloatmethod \empty - \glet\askedfloatoptions\empty} - -% place - -\let\floatlabel \empty -\let\floatcolumn \empty -\let\floatrow \empty -\let\floatlocation \empty -\let\floatlocationmethod\empty - -\def\strc_floats_analyze_location - {% more will be moved here - \let\floatlabel \empty - \let\floatcolumn\empty - \let\floatrow \empty - % - \edef\floatcaptionlocation{\floatcaptionparameter\c!location}% - % - \setfloatmethodvariables\floatlocation} - -\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 - -\ifdefined\dotagregisterfloat \else \let\dotagregisterfloat\gobbletwoarguments \fi - -\protected\def\strc_floats_place - {\flushnotes - \page_otr_command_flush_side_floats % here ! - \strc_floats_begin_group - \strc_floats_place_indeed} - -\tolerant\def\strc_floats_place_indeed[#tag]#spacer[#location]#spacer[#reference]#:#caption% - {\strc_floats_set_current_tag{#tag}% - \strc_floats_reset_variables - \xdef\askedfloatoptions{#location}% - \edef\floatlocation{#location}% - \ifempty\floatlocation - \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} - -\permanent\protected\def\placefloat% [#tag]% - {\flushnotes - \page_otr_command_flush_side_floats % here ! - \strc_floats_begin_group - \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 - -\protected\def\strc_floats_start_place - {\flushnotes - \page_otr_command_flush_side_floats % here ! - \strc_floats_begin_group - \strc_floats_start_place_indeed} - -%D We abuse the settings to pick up some float parameters too which makes it -%D messy. - -\tolerant\protected\def\strc_floats_start_place_indeed[#tag]#spacer[#settings]#spacer[#userdata]% - {\strc_floats_set_current_tag{#tag}% - \strc_floats_reset_variables - % save - \edef\m_location {\floatcaptionparameter\c!location}% - \edef\m_topoffset {\floatcaptionparameter\c!topoffset}% - \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}% - \edef\m_freeregion {\floatcaptionparameter\c!freeregion}% - % preset - \letfloatcaptionparameter \c!location \empty - \setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}% - \setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}% - \setexpandedfloatcaptionparameter\c!freeregion {\floatparameter\c!freeregion}% - \letfloatcaptionparameter \c!reference \empty - \letfloatcaptionparameter \c!title \empty - \letfloatcaptionparameter \c!marking \empty - \letfloatcaptionparameter \c!list \empty - \letfloatcaptionparameter \c!bookmark \empty - % pickup - \ifparameter#settings\or - \setupcurrentfloatcaption[#settings]% - \fi - \ifparameter#userdata\or - \setupcurrentfloatuserdata[#userdata]% - \def\m_strc_floats_saved_userdata{#userdata}% - \else - \let\m_strc_floats_saved_userdata\empty - \fi - % check - \edef\floatlocation{\floatcaptionparameter\c!location}% - \ifx\floatlocation\empty - \edef\floatlocation{\floatparameter\c!default}% - \fi - % inherit - \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}% - \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}% - \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}% - % restore - \letfloatcaptionparameter\c!location \m_location - \letfloatcaptionparameter\c!topoffset \m_topoffset - \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset - \letfloatcaptionparameter\c!freeregion \m_freeregion - % - \strc_floats_analyze_location - \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal - \bgroup - \ignorespaces} - -\protected\def\strc_floats_stop_place - {\removeunwantedspaces - \egroup} - -\permanent\protected\def\startplacefloat - {\flushnotes - \page_otr_command_flush_side_floats % here ! - \strc_floats_begin_group - \strc_floats_start_place_indeed} - -\aliased\let\stopplacefloat\strc_floats_stop_place - -% reserve - -\protected\def\strc_floats_reserve - {\flushnotes - \page_otr_command_flush_side_floats % here ! - \strc_floats_begin_group - \strc_floats_place_indeed} - -\def\strc_floats_reserve_box#settings% - {\begingroup - \setupcurrentfloat[\c!frame=\v!on,#settings]% - \inheritedfloatframed{}% - \endgroup} - -% text - -\protected\def\strc_floats_start_text - {\flushnotes % Here indeed? - \page_otr_command_flush_side_floats % Here indeed? - \strc_floats_begin_text_group - \strc_floats_start_text_indeed} - -\tolerant\protected\def\strc_floats_start_text_indeed[#tag]#spacer[#location]#spacer[#reference]% - {\strc_floats_place_indeed[#tag][\v!text,#location,\v!left][#reference]} - -\protected\def\strc_floats_stop_text - {\strc_floats_stop_text_indeed} - -% reserved text - -\tolerant\protected\def\strc_floats_start_reserve_text[#tag]#spacer[#settings]#spacer[#location]#spacer[#reference]#:#caption%% - {\flushnotes - \page_otr_command_flush_side_floats - \strc_floats_begin_text_group - \strc_floats_place_indeed[#tag][\v!text,#location,\v!left][#reference]{#caption}{\strc_floats_reserve_box{#settings}}} - -\protected\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} % hm -\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 - -\protected\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}} - -\protected\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 - {\page_postprocessors_linenumbers_box\nextbox % for aditya - \dostoptagged - \strc_floats_finish_placement} - \vbox} - -%D \starttyping -%D \definefloat -%D [one] [figure] -%D [default=right, -%D rightmargindistance=-20cm, -%D criterium=129pt, -%D fallback=rightmargin] -%D -%D \definefloat -%D [two] [figure] -%D [default=right, -%D rightmargindistance=-20cm, -%D criterium=129pt, -%D fallback=three] -%D -%D \definefloat -%D [three] [figure] -%D [default=rightmargin, -%D rightmargindistance=0cm] -%D -%D \placefloat[one]{}{\blackrule[width=30pt]} \samplefile{tufte} -%D \placefloat[one]{}{\blackrule[width=60pt]} \samplefile{tufte} -%D \placefloat[one]{}{\blackrule[width=90pt]} \samplefile{tufte} -%D \placefloat[one]{}{\blackrule[width=130pt]} \samplefile{tufte} -%D \placefloat[two]{}{\blackrule[width=130pt]} \samplefile{tufte} -%D \stoptyping - -\def\strc_floats_finish_placement - {\doifsomething{\floatparameter\c!criterium} - {\ifdim\wd\nextbox>\floatparameter\c!criterium\relax - \edef\forcedfloatmethod{\floatparameter\c!fallback}% - \ifempty\forcedfloatmethod \else - \doifelsecommandhandler\??float\forcedfloatmethod - {\let\currentfloat\forcedfloatmethod - \edef\floatlocation{\floatparameter\c!default}% - \let\forcedfloatmethod\floatlocation} - \donothing - \fi - \ifempty\forcedfloatmethod - \let\forcedfloatmethod\v!here - \fi - \fi}% - \strc_floats_check_extra_actions - \strc_floats_analyze_variables_two - \strc_floats_place_packaged_boxes - \dotagregisterfloat\askedfloatoptions\askedfloatmethod - \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 - -\newdimen\d_strc_floats_top -\newdimen\d_strc_floats_bottom -\newdimen\d_strc_floats_overflow - -% \def\strc_floats_calculate_skip#target#skip% -% {\begingroup -% \edef\askedfloatskip{\rootfloatparameter#skip}% -% \ifempty\askedfloatskip -% \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 -% \endgroup} - -\def\strc_floats_calculate_skip#target#skip% - {\begingroup - \edef\p_blank{\rootfloatparameter#skip}% - \ifx\p_blank\v!nowhite - \edef\p_blank{-\v!white}% - \fi - \prerollblank[\p_blank]% - \global#target\prerolledblank - \endgroup} - -\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 - % variable initializations - \global\d_page_sides_shift \zeropoint - \global\d_page_sides_maximum \zeropoint - \global\c_page_sides_align \zerocount - \global\c_page_sides_tolerance \zerocount - \global\c_page_sides_skipmode \zerocount - \global\c_strc_floats_rotation \zerocount - \global\d_page_sides_margin \floatparameter\c!margin - \global\d_page_sides_leftshift \floatparameter\c!leftmargindistance - \global\d_page_sides_rightshift \floatparameter\c!rightmargindistance - \global\d_page_sides_topoffset \floatparameter\c!topoffset - \global\d_page_sides_bottomoffset\floatparameter\c!bottomoffset - \global\c_page_sides_method \floatparameter\c!sidemethod - \global\c_page_one_float_method \floatparameter\c!textmethod - \global\c_page_floats_n_of_top \rootfloatparameter\c!ntop - \global\c_page_floats_n_of_bottom\rootfloatparameter\c!nbottom - \global\d_strc_floats_overflow \zeropoint - \ifconditional\c_strc_floats_par_float - \global\d_strc_floats_top \zeropoint - \global\d_strc_floats_bottom \zeropoint - \strc_floats_calculate_skip\d_page_sides_topskip \c!sidespacebefore - \strc_floats_calculate_skip\d_page_sides_bottomskip\c!sidespaceafter - \strc_floats_calculate_skip\d_page_sides_midskip \c!sidespaceinbetween - \strc_floats_calculate_skip\d_strc_floats_top \c!spacebeforeside - \strc_floats_calculate_skip\d_strc_floats_bottom \c!spaceafterside - \else - \global\d_page_sides_topskip \zeropoint - \global\d_page_sides_bottomskip \zeropoint - \strc_floats_calculate_skip\d_strc_floats_top \c!spacebefore - \strc_floats_calculate_skip\d_strc_floats_bottom\c!spaceafter - \fi - % keyword handling - \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\c_page_sides_skipmode \plusone }% - \doifinset\v!low \floatlocation{\global\c_page_sides_skipmode \plustwo }% - \doifinset\v!fit \floatlocation{\global\c_page_sides_skipmode \plusthree}% - \doifinset\v!tolerant \floatlocation{\global\c_page_sides_tolerance\plusone }% - \doifinset\v!verytolerant\floatlocation{\global\c_page_sides_tolerance\plustwo }% - \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}% - \doifinset\v!effective\floatlocation - {\letfloatparameter \c!leftmargin \effectiveleftskip - \letfloatparameter \c!rightmargin\effectiverightskip - \letfloatcaptionparameter\c!leftmargin \effectiveleftskip - \letfloatcaptionparameter\c!rightmargin\effectiverightskip}% - \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 - \doifelse{\floatparameter\c!freeregion}\v!yes - \settrue\setfalse\c_strc_floats_mark_as_free - \doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! ! - {\setfalse\c_page_floats_center_box_global - \setfalse\c_page_floats_center_box_local}} - -\permanent\def\naturalfloatheight{\the\naturalfloatwd} -\permanent\def\naturalfloatwidth {\the\naturalfloatht} -\permanent\def\naturalfloatdepth {\the\naturalfloatdp} - -\permanent\def\floatcaptionheight{\the\floatcaptionwd} -\permanent\def\floatcaptionwidth {\the\floatcaptionht} -\permanent\def\floatcaptiondepth {\the\floatcaptiondp} - -\newdimen\naturalfloatwd -\newdimen\naturalfloatht -\newdimen\naturalfloatdp - -\newdimen\floatcaptionwd -\newdimen\floatcaptionht -\newdimen\floatcaptiondp - -\def\strc_floats_set_natural_dimensions#box% - {\global\naturalfloatwd\wd#box\relax - \global\naturalfloatht\ht#box\relax - \global\naturalfloatdp\dp#box\relax} - -\def\strc_floats_set_caption_dimensions#box% - {\global\floatcaptionwd\wd#box\relax - \global\floatcaptionht\ht#box\relax - \global\floatcaptiondp\dp#box\relax} - -\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 - \ifempty\currentfloatattribute - % safeguard, can be samepage too - \orelse\ifnofloatcaption - \orelse\ifinsidesplitfloat - \ifconditional\splitfloatfirstdone - \else - attr \destinationattribute \currentfloatattribute - \fi - \else - attr \destinationattribute \currentfloatattribute - \fi - \fi} - -% \def\floatcaptionattribute -% {\iflocation -% \ifempty\currentfloatattribute -% % safeguard, can be samepage too -% \orelse\ifnofloatcaption -% % nothing -% \orunless\ifinsidesplitfloat -% attr \destinationattribute \currentfloatattribute -% \orunless\ifconditional\splitfloatfirstdone -% attr \destinationattribute \currentfloatattribute -% \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 - \glet\currentfloatnumber \previousfloatnumber - \glet\currentfloatattribute \empty - \glet\currentfloatsynchronize\relax - \else - \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% - \edef\currentfloatgroup {\floatcaptionparameter\c!group}% - \ifnofloatnumber - \orelse\ifnofloatcaption - \orelse\ifempty\currentfloatgroup - % independent - \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi - \strc_counters_increment\currentfloatcounter - \orelse\ifcase\strc_floats_group_index - % first in group - \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi - \strc_counters_increment\currentfloatcounter - \else - % next in group - \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]% - \glet\previousfloatnumber \m_strc_counters_last_registered_index - \glet\currentfloatnumber \m_strc_counters_last_registered_index - \glet\currentfloatattribute \m_strc_counters_last_registered_attribute - \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize - \fi - % - \iftrialtypesetting\else\global\setfalse\usesamefloatnumber\fi % 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 - \ifzeropt\htdp\floatbox - \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 \ifempty\p_availablewidth \hsize\else\p_availablewidth \relax\fi - \availablefloatheight\ifempty\p_availableheight\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 - -\permanent\def\doifelserightpagefloat - {\unless\ifdoublesided - \expandafter\firstoftwoarguments - \orelse\ifsinglesided - \expandafter\firstoftwoarguments - \orelse\ifodd\purenumber\strc_float_realpage\space - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\def\doifelseoddpagefloat - {\ifodd\purenumber\strc_float_realpage\space - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifrightpagefloatelse\doifelserightpagefloat -\aliased\let\doifoddpagefloatelse \doifelseoddpagefloat - -\appendtoks - \enforced\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 ! ! ! - -\permanent\protected\def\movesidefloat[#settings]% (-)n*line|x=,y= - {\global\d_page_sides_downshift \zeropoint - \global\d_page_sides_extrashift\zeropoint - \ifhastok={#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 - \else - \movedownsidefloat[#settings]% - \fi} - -\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}} - -\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}} - -\def\strc_floats_move_down#setting% - {\begincsname\??floatmovement#setting\endcsname} - -\def\strc_floats_move_down_line#sign% - {\ifscratchconditionone \else - \global\d_page_sides_downshift\zeropoint - \scratchconditiononetrue - \fi - \global\advance\d_page_sides_downshift#sign\lineheight} - -\def\strc_floats_move_down_hang#lines% - {\ifscratchconditiontwo \else - \global\c_page_sides_n_of_lines\zerocount - \scratchconditiontwotrue - \fi - \global\advance\c_page_sides_n_of_lines#lines\relax} - -\permanent\protected\def\movedownsidefloat[#settings]% already in core - {\unless\ifhastok:{#settings}% - \begingroup - \scratchconditiononefalse - \scratchconditiontwofalse - \normalexpanded{\dorepeatwithcommand[#settings]}\strc_floats_move_down - \endgroup - \fi} - -\permanent\protected\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 - \ifempty\extrafloatlocation \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 - \ifzeropt\d_page_sides_downshift\else - \global\setbox\floatbox\vpack - {\vskip\d_page_sides_downshift - \nointerlineskip - \box\floatbox}% - \fi - \edef\p_minwidth{\floatparameter\c!minwidth}% - \ifempty\p_minwidth - % 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}}% - \ifempty\p_maxwidth - % 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 % why is this - {\global\setbox\floatbox\hpack to \scratchwidth - {\doifnot{\floatparameter\c!location}\v!left\hss - \box\floatbox - \doifnot{\floatparameter\c!location}\v!right\hss}} - -\permanent\protected\def\placefloats - {\page_otr_command_flush_floats} - -\permanent\protected\def\betweenfloatblanko % assumes that spaceafter is present - {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,.... - -% keep as old 1 -% -% \protected\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 -% -% \protected\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}% - \ifempty\m_space\orelse\ifx\m_space\v!none\else - \directvspacing\m_space - \fi} - -\permanent\protected\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 % todo - {\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} - -\permanent\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 - -% keep these as reference: -% -% \def\strc_floats_align_content_indeed -% {\alignstrutmode\zerocount -% \doifnotcommon\floatcaptionlocation{\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} -% -% Test case: -% -% \setupfloats[location=left] -% \setupfloatcaption[width=max] -% -% \startfloatcombination -% \placefigure{}{} -% \placefigure{}{} -% \stopfloatcombination - -%D In a floatcombination we ignore the margins .. if that is ever needed we need another -%D state (instead of local). - -\def\strc_floats_align_indeed - {\alignedline{\floatparameter\c!location}\v!middle} - -\def\strc_floats_shift_indeed#1% - {\shiftalignedline{#1\c!leftmargin}{#1\c!rightmargin}{#1\c!innermargin}{#1\c!outermargin}} - -\def\strc_floats_align_content_indeed - {\alignstrutmode\zerocount - \ifx\forcedfloatmethod\v!local \else - \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} - {\strc_floats_shift_indeed\floatparameter}% - \expandafter\strc_floats_align_indeed - \fi} - -\def\strc_floats_align_caption_indeed - {\alignstrutmode\zerocount - \ifx\forcedfloatmethod\v!local - \expandafter\strc_floats_align_indeed_local - \else - \strc_floats_shift_indeed\floatcaptionparameter - \expandafter\strc_floats_align_indeed - \fi} - -% \def\strc_floats_align_indeed_local#1% -% {\begingroup -% \hsize\wd\floatbox -% \strc_floats_align_indeed{#1}% -% \endgroup} - -\let\strc_floats_align_indeed_local\firstofoneargument - -\newdimen\d_strc_floats_content -\newdimen\d_strc_float_temp_height -\newdimen\d_strc_float_temp_width - -\newconditional\c_floats_adapt_to_caption_width -\newconditional\c_floats_store_minimal_package - -\def\captionminwidth {15\bodyfontsize} % can become parameter (but what name) -\def\captionovershoot{2\emwidth} % can become parameter (but what name) - -\let\strc_floats_mark_pag_as_free\relax - -\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 - \strc_floats_set_caption_dimensions\voidbox - %\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}}% - \strc_floats_set_caption_dimensions\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 - \ifconditional\c_floats_store_minimal_package - % nothing - \orelse\ifcase\c_strc_floats_rotation - \doifnotinset\v!margin\floatlocation % brr, really needed! see wm - {\postcenterfloatbox\d_strc_floats_content - \strc_floats_mark_pag_as_free}% - % mark as free not done here - \else - \global\setbox\floatbox\vpack - {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\box\floatbox}}% - \strc_floats_mark_pag_as_free - \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_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 - \doifcommonelse\floatcaptionlocation{\v!top,\v!bottom} - {\strc_floats_prepare_page_caption_top_bottom} - {\ifx\p_strc_floats_caption_width\v!fit - \strc_floats_prepare_side_auto_caption - \orelse\ifx\p_strc_floats_caption_width\v!max - \strc_floats_prepare_side_auto_caption - \else - \strc_floats_prepare_side_width_caption - \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 - \orelse\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} - -\def\strc_floats_prepare_page_caption_top_bottom_fit_max - {\unless\ifx\p_strc_floats_caption_minwidth\v!fit - \strc_floats_prepare_stack_caption_fixed - \orelse\ifx\p_strc_floats_caption_width\v!max - \strc_floats_prepare_stack_caption_max - \orelse\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} - -\def\strc_floats_caption_set_align - {\edef\m_align{\v!reset\ifempty\p_strc_floats_caption_align\else,\fi\p_strc_floats_caption_align}% - \doifinset\v!tolerant \floatcaptionlocation{\edef\m_align{\m_align,\v!tolerant}}% - \doifinset\v!verytolerant\floatcaptionlocation{\edef\m_align{\m_align,\v!verytolerant}}% - \doifinset\v!stretch \floatcaptionlocation{\edef\m_align{\m_align,\v!stretch}}% - \setupalign[\m_align]} - -\def\strc_floats_prepare_side_auto_caption - {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax - \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 - \ifempty\p_strc_floats_caption_align - \raggedcenter % on purpose overloads align ! - \fi - \strc_floats_make_complete_caption}} - -\def\strc_floats_prepare_stack_caption_auto - {\ifempty\p_strc_floats_caption_align \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 - \ifconditional\c_floats_adapt_to_caption_width - \let\captionminwidth \!!zeropoint - \let\captionovershoot\!!zeropoint - \fi - \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}% -% \ifconditional\c_floats_adapt_to_caption_width -% \setbox\b_strc_floats_content\hpack to \captionhsize{\hss\box\b_strc_floats_content\hss}% -% \fi - \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}% - \orelse\if\empty\p_strc_floats_caption_align - \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} - -\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 \hpack \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\floatcaptionlocation - {\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 \hpack \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\floatcaptionlocation - {\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 - \setbox\scratchboxone\vbox{#2}% - \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content - \global\d_strc_floats_overflow\dimexpr\htdp\scratchboxone-\htdp\b_strc_floats_content\relax - \fi - \ht\scratchboxone\d_strc_float_temp_height - \everyrightofalignedline{\hsmash{\hskip#1\box\scratchboxone}}% - \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 - \setbox\scratchboxone\vbox{#2}% - \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content - \global\d_strc_floats_overflow\dimexpr\htdp\scratchboxone-\htdp\b_strc_floats_content\relax - \fi - \ht\scratchboxone\d_strc_float_temp_height - \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\scratchboxone\relax\box\scratchboxone}}% - \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[\floatcaptionlocation] - [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin, - \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin, - \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin, - \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[\floatcaptionlocation] - [ \v!low=>\let\next\strc_floats_build_box_low, - \v!middle=>\let\next\strc_floats_build_box_middle, - \v!high=>\let\next\strc_floats_build_box_high]% - \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 - {\doifelseinset\v!righthanging\floatcaptionlocation - {\strc_floats_flush_right_caption_hang} - {\doifelseinset\v!lefthanging\floatcaptionlocation - {\strc_floats_flush_left_caption_hang} - {\doifelseinset\v!hang\floatcaptionlocation - {\doifelseinset\v!outer\floatcaptionlocation - {\doifelserightpagefloat{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}} - {\doifelseinset\v!right\floatcaptiondirectives - {\strc_floats_flush_right_caption_hang} - {\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 - \hsize\d_strc_float_temp_width - \ifconditional\c_strc_floats_par_float - \strc_floats_locate_side_float{\box\b_strc_floats_caption}% - \vss\strc_floats_between_stack - \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 - \vpack to \noflines\lineheight{\unvbox\scratchbox}} - -\def\strc_floats_build_box_bottom_stack_grid - {\dp\b_strc_floats_caption\strutdepth - \setbox\scratchbox\vbox - {\d_strc_float_temp_width\wd\b_strc_floats_content - \hsize\d_strc_float_temp_width - \ifconditional\c_strc_floats_par_float - \hpack{\box\b_strc_floats_content}% - \vss\strc_floats_between_stack - \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 - \vpack 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 - \hsize\d_strc_float_temp_width - \ifconditional\c_strc_floats_par_float - \strc_floats_locate_side_float{\box\b_strc_floats_caption}% - \vss\strc_floats_between_stack\vss - \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\vpack - {\strc_floats_align_content{\copy\b_strc_floats_content}% - \strc_floats_align_caption{\copy\b_strc_floats_caption}}% - \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy - \vbox to \noflines\lineheight - {\d_strc_float_temp_width\wd\b_strc_floats_content - \hsize\d_strc_float_temp_width - \ifconditional\c_strc_floats_par_float - \hpack{\box\b_strc_floats_content}% - \vss\strc_floats_between_stack\vss - \strc_floats_locate_side_float{\box\b_strc_floats_caption}% - \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!lines=>\let\next\strc_floats_build_box_top_stack_stretch]% was \v!grid but interfered - \next} - -\def\strc_floats_build_box_bottom - {\let\next\strc_floats_build_box_bottom_stack_normal - \processfirstactioninset[\floatcaptionparameter\c!location] - [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid, - \v!lines=>\let\next\strc_floats_build_box_bottom_stack_stretch]% was \v!grid but interfered - \next} - -\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}} -\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}} - -\permanent\protected\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}} - -\def\strc_floats_build_box - {\strc_floats_build_box_before - \global\setbox\floatbox\vbox % pack ? probably not - {\strc_floats_set_local_hsize - \forgetall - \ifconditional\c_floats_store_minimal_package - \strc_floats_build_box_separate_make - \else - % \let\floatcaptionarrangement\s!default - \let\floatcaptionarrangement\v!bottom % for Alan - \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step - \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname - \lastnamedcs - \else - \strc_floats_build_box_default - \fi - \fi}% - \strc_floats_build_box_after} - -% \let\strc_floats_build_box_before\relax -% \let\strc_floats_build_box_after \relax - -\def\strc_floats_build_box_before - {\let\currentfloatframed\currentfloat - \floatwidth\wd - \ifdim\wd\b_strc_floats_content>\wd\b_strc_floats_caption - \b_strc_floats_content\else\b_strc_floats_caption - \fi} - -\def\strc_floats_build_box_after - {\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax} - -\def\strc_floats_build_box_after_indeed - {\global\setbox\floatbox\hpack - {\edef\m_width{\floatframedparameter\c!width}% - \ifx\m_width\v!fit - \let\m_width\floatwidth - \orelse\ifx\m_width\v!broad - \let\m_width\v!fit - \fi - \letfloatframedparameter\c!strut\v!no - \letfloatframedparameter\c!width\m_width - \inheritedfloatframedframed - {\box\floatbox}}} - -% special purpose: used in floatcombinations -% -% todo : keep float content and caption separated in local - -\newbox\b_strc_floats_separate_content -\newbox\b_strc_floats_separate_caption - -\def\strc_floats_build_box_separate_set - {\settrue\c_floats_adapt_to_caption_width - \settrue\c_floats_store_minimal_package} - -% \def\strc_floats_build_box_separate_make -% {\offinterlineskip -% \vpack to \onepoint{\box\b_strc_floats_content}\break -% \vpack to \onepoint{\box\b_strc_floats_caption}} - -%D Remark for \LMTX: we don't want to migrate inserts here so we unpack -%D (could be a flag). When migrated, the inserts end up in the vertical -%D list and we no longer have just a box (but inserts and lines again). - -\def\strc_floats_build_box_separate_make - {\savebox\??localfloatstack{\number\numexpr\c_strc_localfloats_n+1\relax:a}{\box\b_strc_floats_content}% - \savebox\??localfloatstack{\number\numexpr\c_strc_localfloats_n+1\relax:b}{\box\b_strc_floats_caption}} - -\protected\def\strc_floats_build_box_separate_split#1% - {\global\setbox\b_strc_floats_separate_content\vpack{\foundbox\??localfloatstack{\number#1:a}}% - \global\setbox\b_strc_floats_separate_caption\tpack{\foundbox\??localfloatstack{\number#1:b}}} - -% \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!rightmargin \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!leftmargin \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!innermargin \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!outermargin \strc_floats_build_box_side % added 2016-08-23 - -\installfloatboxbuilder \v!left \strc_floats_build_box_side -\installfloatboxbuilder \v!right \strc_floats_build_box_side -\installfloatboxbuilder \v!inner \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!outer \strc_floats_build_box_side % added 2016-08-23 - -\installfloatboxbuilder \v!lefthanging \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!righthanging \strc_floats_build_box_side % added 2016-08-23 -\installfloatboxbuilder \v!hang \strc_floats_build_box_side % added 2016-08-23 - -\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 - -\permanent\def\postcenterfloatbox#1% - {\scratchdimen - \ifcase\postcenterfloatmethod - #1% \wd\floatbox - \orelse\ifinsidecolumns - \ifpostponecolumnfloats\makeupwidth\else#1\fi - \orelse\ifdim#1>\hsize - \hsize - \else - \wd\floatbox - \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 - \orelse\ifconditional\c_page_floats_center_box_local - \donetrue - \else - \donefalse - \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}% \vpack >? - %\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}}% \hpack ? - %\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 - \orelse\ifx\p_strc_floats_caption_width\v!fit - \strc_floats_prepare_side_caption_fit - \else - \strc_floats_prepare_side_caption_width - \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? - \strc_floats_caption_set_align - \hsize\wd\b_strc_floats_content - \strc_floats_make_complete_caption}% - \else - % maybe we should listen to the align option here (now side floats need the max option - \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 - \ifconditional\c_floats_store_minimal_package \else - \setbox\floatbox\hpack{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently - \fi - \global\floatheight\htdp\floatbox - \global\floatwidth\wd\floatbox - \ifconditional\c_floats_store_minimal_package \else - \doifnotinset\v!margin\floatlocation % gaat namelijk nog fout - {\setbox\floatbox\vpack - {\parindent\zeropoint - \box\floatbox}}% - \fi - \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 and floatcombinations - -\permanent\protected\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn - {\clf_analysefloatmethod{#1}} % move definition to lua end - -\permanent\protected\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 - \ifempty\forcedfloatmethod \else - \let\floatmethod\forcedfloatmethod - \fi - \let\askedfloatmethod\floatmethod - \ifexporting \ifx\askedfloatmethod\v!here \else - \showmessage\m!floatblocks{15}{\askedfloatmethod,\v!here}% - \let\floatlocation\v!here - \fi \fi - % [] will go - \edef\floatlocationmethod{\floatmethod,\floatlocation}% - \csname\??floatmethods\currentoutputroutine:\floatmethod\endcsname - \fi} - -\installcorenamespace{floatsettings} - -\permanent\protected\def\installfloatmethod#1#2#3% routine keyword handler - {\setvalue{\??floatmethods#1:#2}{#3}} - -\permanent\protected\def\handlefloatmethod#1% - {\csname\??floatmethods\currentoutputroutine:#1\endcsname} - -% \protected\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}} -% -% \protected\def\startfloatmethodsettings#1#2 #3\stopfloatmethodsettings -% {\csname\??floatsettings#1:#2\endcsname\expandafter{\the\csname\??floatsettings#1:#2\endcsname#3}} -% -% \let\stopfloatmethodsettings\relax -% -% \protected\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} - -% can move to page-one: - -\installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here -\installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force -\installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left -\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 - -%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 - -\permanent\protected\def\resetlocalfloats - {\global\c_strc_localfloats_n\zerocount - \initializeboxstack\??localfloatstack} - -\permanent\protected\def\somelocalfloat - {\global\advance\c_strc_localfloats_n\plusone - \savebox\??localfloatstack{\number\c_strc_localfloats_n}{\box\floatbox}} - -\permanent\protected\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}} - -\permanent\protected\def\flushlocalfloats - {\getlocalfloats - \resetlocalfloats} - -% \protected\def\getlocalfloat#1% -% {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}}% \vbox{\restorebox...} - -\permanent\protected\def\getlocalfloat#1% - {\foundbox\??localfloatstack{\number#1}} % \vbox{\restorebox...} - -\permanent\protected\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/tex/context/base/mkiv/strc-ind.mkxl b/tex/context/base/mkiv/strc-ind.mkxl deleted file mode 100644 index 31d7eb575..000000000 --- a/tex/context/base/mkiv/strc-ind.mkxl +++ /dev/null @@ -1,128 +0,0 @@ -%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 - \frozen\instance\setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}% - \frozen\instance\setuevalue {\e!stop \currentindentedtext}{\strc_indentedtexts_stop}% - % to be avoided ... might go away - \frozen\instance\setuevalue {\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{0}}% - \frozen\instance\setuevalue {\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{1}}% - \frozen\instance\setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}% -\to \everydefineindentedtext - -\protected\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} - -\protected\def\strc_indentedtexts_stop - {\indentedtextparameter\c!after - \par - \endgroup} - -\permanent\tolerant\protected\def\startindentedtext[#1]% - {\strc_indentedtexts_start{#1}\c_strc_indentedtexts_nesting} - -\permanent\let\stopindentedtext\strc_indentedtexts_stop - -\protected\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/tex/context/base/mkiv/strc-ini.mklx b/tex/context/base/mkiv/strc-ini.mklx deleted file mode 100644 index 3897c1d2a..000000000 --- a/tex/context/base/mkiv/strc-ini.mklx +++ /dev/null @@ -1,81 +0,0 @@ -%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}{} - -\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. - -\permanent\tolerant\protected\def\defineresetset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:resets} {#name}{\detokenize{#set}}{\detokenize{#default}}true\relax} -\permanent\tolerant\protected\def\defineseparatorset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:separators} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} -\permanent\tolerant\protected\def\defineconversionset[#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:conversions}{#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} -\permanent\tolerant\protected\def\defineprefixset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:prefixes} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} - -\aliased\let\definestructureresetset \defineresetset -\aliased\let\definestructureseparatorset \defineseparatorset -\aliased\let\definestructureconversionset\defineconversionset -\aliased\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/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx deleted file mode 100644 index e2388eeec..000000000 --- a/tex/context/base/mkiv/strc-itm.mklx +++ /dev/null @@ -1,1886 +0,0 @@ -%D \module -%D [ file=strc-itm, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Itemgroups, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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}{} - -%D As we analyze/register widths and such we could as well push and pop the numbers -%D at the \LUA\ end (which saves a few calls). -%D -%D Cleaning up this module happened around the time when Kate Bush came up with the -%D nicest numbered list of words: 50 Words For Snow. It's therefore no surprise that -%D I had that cd running several times when updating this code. One of the -%D highlights of 2011. -%D -%D This module needs to be rewritten but that is tricky with respect to -%D compatibilitity. Basically each major variant (regular, text, columns, -%D horizontal, etc) needs to be on its own. - -% 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 -% -% \startitemize[n,repeat][width=0pt] -% \noitem \startitemize[a][width=2em] \item Item 1.a. \item Item 1.b. \stopitemize -% \noitem \startitemize[a][width=2em] \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 -\newconditional\c_strc_itemgroups_inline_head - -% 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 \orelse \ifempty\currentitemreference \else - \strc_itemgroups_insert_reference_indeed - \fi} - -\def\strc_itemgroups_insert_extra_reference - {\iftrialtypesetting \orelse \ifempty\currentitemreference \else - \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}% - \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 \locationcount % 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 - -\aliased\let\setupitemgroups\setupitemgroup - -\appendtoks - \frozen\instance\setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}% - \frozen\instance\setuevalue{\e!stop \currentitemgroup}{\stopitemgroup}% - \frozen\instance\setuevalue{\e!setup\currentitemgroup\e!endsetup}{\setupitemgroup[\currentitemgroup]}% obsolete - \let\currentparentitemgroup\currentitemgroup - \definecounter[\v_strc_itemgroups_counter]% -\to \everydefineitemgroup - -%D Global states - -\def\strc_itemgroups_store_continue_state#options#settings% - {\global\edefcsname\??itemgroupoption \currentitemgroup\endcsname{\strc_itemgroups_process_options{#options}}% - \global\defcsname \??itemgroupsetting\currentitemgroup\endcsname{\setupcurrentitemgroup[#settings]}} - -\def\strc_itemgroups_fetch_continue_state - {\csname\??itemgroupoption \currentitemgroup\endcsname - \csname\??itemgroupsetting\currentitemgroup\endcsname} - -\def\strc_itemgroups_reset_continue_state - {\global\letcsname\??itemgroupoption \currentitemgroup\endcsname\relax - \global\letcsname\??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} - -\protected\def\strc_itemgroups_process_options#options% - {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml - -% \installcommalistprocessorcommand \strc_itemgroups_process_option_list \strc_itemgroups_process_option -% -% \protected\def\strc_itemgroups_process_options#options% -% {\normalexpanded{\strc_itemgroups_process_option_list[#options]}} % expansion of options is handy for xml - -\def\strc_itemgroups_process_option#option% - {\edef\itemgroupconstantvalue{#option}% - \ifempty\itemgroupconstantvalue\else - \splitatasterisk\itemgroupconstantvalue\itemgroupfirst\itemgroupsecond - \ifempty\itemgroupsecond - \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} - -\def\strc_itemgroups_process_set_option_unpack - {\ifcase\c_strc_itemgroups_nesting\else - \setfalse\c_strc_itemgroups_pack - \fi} - -\setvalue{\??itemgroupkeyword\!!zerocount }{} % ignore 0 -\setvalue{\??itemgroupkeyword\v!packed }{\strc_itemgroups_process_set_option_pack} -\setvalue{\??itemgroupkeyword\v!unpacked }{\strc_itemgroups_process_set_option_unpack} -\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 }{\ifempty\itemgroupfirst - \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!headintext }{\settrue\c_strc_itemgroups_inline_head} -\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!notjoinedup}{\setfalse\c_strc_itemgroups_joined} -\setvalue{\??itemgroupkeyword\v!serried }{\edef\itemgroupfirst{-\ifempty\itemgroupfirst1\else\itemgroupfirst\fi}% - \letitemgroupparameter\c!factor\itemgroupfirst} -\setvalue{\??itemgroupkeyword\v!stopper }{\letitemgroupparameter\c!placestopper\v!yes} % keep {} -\setvalue{\??itemgroupkeyword\v!nostopper }{\letitemgroupparameter\c!placestopper\v!no} % keep {} -\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 }{\setitemgroupparameter\c!width {1.5\emwidth}% - \setitemgroupparameter\c!distance {.5\emwidth}% - %\letitemgroupparameter\c!factor \!!zerocount - \letitemgroupparameter\c!factor {\zerocount}% - \setitemgroupparameter\c!packcriterium{\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} - -% \installcommalistprocessorcommand \strc_itemgroups_preset_stage_one_list \strc_itemgroups_preset_stage_one_indeed -% -% \def\strc_itemgroups_preset_stage_one#options% -% {\normalexpanded{\strc_itemgroups_preset_stage_one_list[#options]}} - -\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 - \orelse\ifconditional\c_strc_itemgroups_joined - % \empty - \else - \itemgroupparameter\c!before - \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 - \orelse\ifconditional\c_strc_itemgroups_joined - % \empty - \else - \itemgroupparameter\c!after - \fi} - -\def\strc_itemgroups_between_command - {\ifconditional\c_strc_itemgroups_nowhite - \nowhitespace - \orelse\ifconditional\c_strc_itemgroups_joined - % \empty - \else - \itemgroupparameter\c!inbetween - \fi} - -\def\strc_itemgroups_before_head_command - {\ifconditional\c_strc_itemgroups_nowhite - \nowhitespace - \orelse\ifconditional\c_strc_itemgroups_joined - % \empty - \else - \itemgroupparameter\c!beforehead - \fi} - -\def\strc_itemgroups_after_head_command - {\ifconditional\c_strc_itemgroups_nowhite - \nowhitespace - \orelse\ifconditional\c_strc_itemgroups_joined - % \empty - \else - \itemgroupparameter\c!afterhead - \fi} - -% compatible setup command: - -\let\strc_itemgroups_normal_setup\setupitemgroup - -\permanent\overloaded\tolerant\protected\def\setupitemgroup[#category]#spacer[#levels]#spacer[#options]#spacer[#settings]% category level|each options|settings settings|options - {\ifarguments - % nothing to set up - \or - \edef\strc_itemgroups_setup_what{#levels}% - \strc_itemgroups_normal_setup[#category]% == settings - \or - \edef\strc_itemgroups_setup_what{#levels}% - \strc_itemgroups_setup_each{#category}{#levels}% - \or - \edef\strc_itemgroups_setup_what{#levels}% - \ifx\strc_itemgroups_setup_what\v!each - \strc_itemgroups_setup_each{#category}{#options}% - \else - \strc_itemgroups_setup_list{#levels}{#category}{#options}% - \fi - \or - \edef\strc_itemgroups_setup_what{#levels}% - \ifx\strc_itemgroups_setup_what\v!each - \strc_itemgroups_setup_each{#category}{#options}% - \strc_itemgroups_setup_each{#category}{#settings}% - \else - \strc_itemgroups_setup_list{#levels}{#category}{#options}% - \strc_itemgroups_setup_list{#levels}{#category}{#settings}% - \fi - \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_each#category#whatever% - {\ifcondition\validassignment{#whatever}% - \strc_itemgroups_normal_setup[#category][#whatever]% - \else - \strc_itemgroups_normal_setup[#category][\c!option={#whatever}]% - \fi} - -\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_setup_list#subcategories#category#whatever% - {\ifcondition\validassignment{#whatever}% - \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}% - \else - \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}% - \fi} - -\def\strc_itemgroups_increment_item_counter - {\ifconditional\c_strc_itemgroups_sub \else - \ifconditional\c_strc_itemgroups_symbol \else % \ifempty\strc_itemgroups_extra_symbol - \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel - \fi - \fi} - -\protected\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} - -\installcorenamespace{itemstopper} - -\setvalue{\??itemstopper\v!yes }{\itemgroupparameter\c!stopper} -\setvalue{\??itemstopper\v!display}{\ifconditional\c_strc_itemgroups_inline\else\itemgroupparameter\c!stopper\fi} -\setvalue{\??itemstopper\v!inline }{\ifconditional\c_strc_itemgroups_inline\itemgroupparameter\c!stopper\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=\begincsname\??itemstopper\itemgroupparameter\c!placestopper\endcsname, - \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}% - \ifempty\strc_itemgroups_tmp_symbol \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 - \orelse\ifnum\itemgroupparameter\c!factor>\zerocount - \d_strc_itemgroups_list_width\itemgroupparameter\c!step\relax - \ifzeropt\d_strc_itemgroups_list_width \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 - \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax - \let\currentitemgroup\savedcurrentitemgroup} - -\permanent\tolerant\protected\def\startitemgroup[#category]#spacer[#options]#spacer[#settings]% - {\begingroup % (1) - \nofarguments\lastarguments - \def\currentitemgroup{#category}% no nested mixing of itemgroups - \let\currentparentitemgroup\currentitemgroup - \global\advance\c_strc_itemgroups_nesting\plusone - \def\currentitemlevel{\number\c_strc_itemgroups_nesting}% - \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}% - \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}% - % - \edef\itemgroupoptions{\itemgroupparameter\c!option}% - \let\itemgroupextraoptions\empty - \ifcase\nofarguments - \strc_itemgroups_start_indeed{}% - \or - \strc_itemgroups_start_indeed{}% - \or - \ifhastok={#options}% - \strc_itemgroups_start_indeed{#options}% - \else - \edef\itemgroupextraoptions{#options}% - \strc_itemgroups_start_indeed{}% - \fi - \or - \edef\itemgroupextraoptions{#options}% - \strc_itemgroups_start_indeed{#settings}% - \fi} - -\def\strc_itemgroups_start_indeed#settings% - {\ifempty\itemgroupoptions - \let\itemgroupoptions\itemgroupextraoptions - \orelse\ifempty\itemgroupextraoptions - % ok - \else - \edef\itemgroupoptions{\itemgroupoptions,\itemgroupextraoptions}% - \fi - \begingroup % (2) - \the\itemgroupcommands - \setconditional\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 - \ifempty\itemgroupoptions - \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 - % - \ifconditional\c_strc_itemgroups_pack - \ifnum\currentnofitems>\itemgroupparameter\c!packcriterium\relax\else - \setfalse\c_strc_itemgroups_pack - \fi - \fi - % - \ifnum\c_strc_itemgroups_nesting=\plusone % NIEUW - \doadaptleftskip {\itemgroupparameter\c!margin}% - \doadaptleftskip {\itemgroupparameter\c!leftmargin}% - \doadaptrightskip{\itemgroupparameter\c!rightmargin}% - \fi - % - \doadaptleftskip {\itemgroupparameter\c!leftmargindistance}% - \doadaptrightskip{\itemgroupparameter\c!rightmargindistance}% - % - \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 - \ifempty\strc_itemgroups_used_symbol - \strc_itemgroups_set_symbol\strc_itemgroups_asked_symbol % ** default value - \ifempty\strc_itemgroups_used_symbol - \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\orelse\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 - \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 - \frozen\advance\leftskip\d_strc_itemgroups_list_width\relax - \fi - \fi - \ifempty\m_strc_itemgroups_repeat_start - \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\currentitemgroup:\currentitemlevel}#symbol} - -\def\strc_itemgroups_store_local_symbol#symbol% - {\letgvalue{\??itemgrouplocal\currentitemgroup:\currentitemlevel}#symbol} - -\def\strc_itemgroups_fetch_global_symbol - {\csname\??itemgroupglobal\currentitemgroup:\currentitemlevel\endcsname} - -\def\strc_itemgroups_fetch_local_symbol - {\csname\??itemgrouplocal\currentitemgroup:\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\currentitemgroup:\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 - \protected\def\startcolumns[#settings]{} - \protected\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 - -\permanent\protected\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 - \orelse\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 - % 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. - -\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 - -\tolerant\protected\def\startitemgroupitem[#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 - \begstrut % \strut - \nobreak % else problems with intext items - \seteffectivehsize % NEW ! - \hskip\d_strc_itemgroups_signal % concat - \itemgroupparameter\c!command} - -\protected\def\stopitemgroupitem - {\ifhmode - \endstrut % new per 2017-12-15 - \fi - \ifconditional\c_strc_itemgroups_text - % nothing - \else - \endgraf - \fi} - -\tolerant\protected\def\startitemgrouphead[#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]% - \startitemgroupitem[#reference]% - \pickupgroupedcommand - \strc_itemgroups_start_head_indeed - \strc_itemgroups_stop_head_indeed - \strc_itemgroups_head_body_indeed} - -\protected\def\stopitemgrouphead - {\dostoptagged - \stopitemgroupitem} - -\protected\def\strc_itemgroups_start_head_indeed - {\settrue\c_strc_itemgroups_head - \dotagsetitem\s!head% % weird place - \dostarttagged\t!itemhead\empty - \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces} - -\protected\def\strc_itemgroups_stop_head_indeed - {\removeunwantedspaces - \dostoptagged - \ifconditional\c_strc_itemgroups_inline_head - \space - \ignorespaces - \else - \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 - \fi} - -\protected\def\strc_itemgroups_head_body_indeed - {\dostarttagged\t!itembody\empty - \noindentation - \ignorespaces} - -% Simple commands. - -\protected\def\strc_itemgroups_start_do_item - {\startitemgroupitem} - -\protected\def\strc_itemgroups_start_no_item - {\let\currentitemreference\empty - \strc_itemgroups_increment_item_counter - %\advance\c_strc_itemgroups_n_of_items\plusone - \setbox\b_strc_itemgroups\emptyhbox - \strc_itemgroups_check_for_repeated - \ignorespaces} - -\protected\def\strc_itemgroups_start_button[#destination]% - {\edef\m_strc_itemgroups_destination{#destination}% - \startitemgroupitem} - -\protected\def\strc_itemgroups_start_symbol#text% - {\def\strc_itemgroups_extra_symbol{#text}% - \settrue\c_strc_itemgroups_symbol - \startitemgroupitem - \dotagsetitem\s!symbol} - -\protected\def\strc_itemgroups_start_dummy - {\strc_itemgroups_start_symbol - %\strut\strut} % two ? - \begstrut} - -\protected\def\strc_itemgroups_start_subitem - {\settrue\c_strc_itemgroups_sub - \startitemgroupitem - \dotagsetitem\s!sub} - -\protected\def\strc_itemgroups_start_edge#text% - {\strc_itemgroups_start_symbol - {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting - \dostarttagged\t!ignore\empty % for the moment, maybe an attribute - \hbox to \d_strc_itemgroups_list_width - {#text\hskip\itemgroupparameter\c!distance}% - \dostoptagged}} - -\protected\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} - -\protected\def\strc_itemgroups_start_text#text% - {\def\strc_itemgroups_extra_symbol{#text}% - \settrue\c_strc_itemgroups_symbol - \settrue\c_strc_itemgroups_txt - \startitemgroupitem} - -% \protected\def\strc_itemgroups_start_head -% {\settrue\c_strc_itemgroups_head -% \startitemgrouphead} - -\protected\def\strc_itemgroups_start_items - {\dosingleempty\strc_itemgroups_start_items_indeed} - -\protected\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost - {\strc_itemgroups_start_edge - {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}% - \unskip}} - -\protected\def\startspecialitemgroupitem[#name]% todo: frozen - {\ifcsname\??itemgroupstart#name\endcsname - \expandafter\lastnamedcs - \else - \expandafter\strc_itemgroups_start_do_item - \fi} - -\protected\def\stopspecialitemgroupitem % todo: frozen - {\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 -\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text - -\def\strc_itemgroups_optimize_breaks - {\ifcase\c_strc_itemgroups_column_depth - \ifconditional\c_strc_itemgroups_optimize - \ifcase\c_strc_itemgroups_max_items - \orelse\ifnum\c_strc_itemgroups_max_items=\plusthree - \ifnum\c_strc_itemgroups_n_of_items>\plusone - \strc_itemgroups_insert_nobreak - \fi - \orelse\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 - \orelse\ifnum\c_strc_itemgroups_max_items=\c_strc_itemgroups_n_of_items\relax - \strc_itemgroups_insert_nobreak - \orelse\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} - -\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 - -\protected\def\strc_itemgroups_start_head_sym#text% - {\def\strc_itemgroups_extra_symbol{#text}% - \settrue\c_strc_itemgroups_symbol - \settrue\c_strc_itemgroups_head - %\strc_itemgroups_start_head} - \startitemgrouphead} - -\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 \orelse \ifempty\m_strc_itemgroups_destination \else - \setbox\b_strc_itemgroups\hbox{\directgotobox{\box\b_strc_itemgroups}[\m_strc_itemgroups_destination]}% - \fi} - -\def\strc_itemgroups_check_indenting - {\setfalse\c_strc_itemgroups_indented_first - \ifempty\m_strc_itemgroups_indenting \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 - \ifempty\m_strc_itemgroups_repeat_start - \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 - \strc_itemgroups_optimize_breaks - \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 - \orelse\ifdim\d_strc_itemgroups_asked_width>\zeropoint - \strc_itemgroups_make_aligned_box - \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 - \ifzeropt\d_strc_itemgroups_asked_width - \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 - \orelse\ifconditional\c_strc_itemgroups_inline - \strc_itemgroups_handle_groups_inline_item - \orelse\ifconditional\c_strc_itemgroups_txt - \strc_itemgroups_handle_text_item - \else - \strc_itemgroups_handle_lapped_item_positive - \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\s!plus\interwordstretch\s!minus\interwordshrink}} - -\setvalue\??itemgroupdistance % catches empty value - {\let\m_strc_itemgroups_text_distance\zeropoint} - -\protected\def\strc_itemgroups_set_text_item_distance - {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}% - \ifempty\m_strc_itemgroups_text_distance - % - \orelse\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname - \lastnamedcs - \else - \strc_itemgroups_set_text_item_distance_indeed - \fi} - -\def\strc_itemgroups_set_text_item_distance_indeed - {\assignvalue - \m_strc_itemgroups_text_distance - \m_strc_itemgroups_text_distance - {.5\interwordspace\s!plus.5\emwidth}% - {\interwordspace \s!plus \emwidth}% - {\emwidth \s!plus \interwordstretch\s!minus\interwordshrink}} - -% \protected\def\strc_itemgroups_default_command -% {\EveryPar{\ignorespaces}% needed ? -% \ignorespaces} - -\protected\def\strc_itemgroups_default_command - {\ignorespaces} - -%D Special case: - -\protected\def\strc_itemgroups_head#text\par - {\startitemgrouphead{#text}} - -%D The local commands: - -\appendtoks - \enforced\let\item \strc_itemgroups_start_do_item - \enforced\let\sub \strc_itemgroups_start_subitem - \enforced\let\sym \strc_itemgroups_start_symbol - \enforced\let\ran \strc_itemgroups_start_edge - \enforced\let\its \strc_itemgroups_start_items - \enforced\let\mar \strc_itemgroups_start_margin - \enforced\let\noitem \strc_itemgroups_start_no_item - \enforced\let\itm \strc_itemgroups_start_do_item - \enforced\let\but \strc_itemgroups_start_button - \enforced\let\nop \strc_itemgroups_start_dummy - \enforced\let\txt \strc_itemgroups_start_text - \enforced\let\head \strc_itemgroups_head - \enforced\let\headsym \strc_itemgroups_start_head_sym - \enforced\let\startitem \startitemgroupitem - \enforced\let\stopitem \stopitemgroupitem - \enforced\let\starthead \startitemgrouphead - \enforced\let\stophead \stopitemgrouphead - \enforced\let\startspecialitem\startspecialitemgroupitem - \enforced\let\stopspecialitem \stopspecialitemgroupitem -\to \itemgroupcommands - -\ifx\currentinterface \s!english \else - - \def\next#1#2{\ifcsname#1\endcsname\else\enforced\letcsname#1\endcsname#2\fi} - - \etoksapp\itemgroupcommands{% - \next{\v!item }\strc_itemgroups_start_do_item - \next{\v!sub }\strc_itemgroups_start_subitem - \next{\v!sym }\strc_itemgroups_start_symbol - \next{\v!ran }\strc_itemgroups_start_edge - \next{\v!head }\strc_itemgroups_head - \next{\v!its }\strc_itemgroups_start_items - \next{\v!mar }\strc_itemgroups_start_margin - \next{\v!txt }\strc_itemgroups_start_text - \next{\e!start\v!item}\startitemgroupitem - \next{\e!stop \v!item}\stopitemgroupitem - \next{\e!start\v!head}\startitemgrouphead - \next{\e!stop \v!head}\stopitemgrouphead - } - -\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 - -\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} - -\protected\def\stopcollectitems % todo: frozen - {\ifconditional\c_strc_itemgroups_collecting - \c_strc_itemgroups_collected_done \zerocount - \c_strc_itemgroups_collected_current\zerocount - \ifnum\c_strc_itemgroups_collected_stored>\zerocount - \ifconditional\c_strc_itemgroups_horizontal - \strc_itemgroups_before_command - \setfalse\c_strc_itemgroups_first - \strc_itemgroups_collected_flush - %\strc_itemgroups_after_command % triggered elsewhere - \else - \strc_itemgroups_collected_flush - \fi - \fi - \fi} - -\protected\def\startcollectitems % todo: frozen - {\ifconditional\c_strc_itemgroups_collecting - \c_strc_itemgroups_collected_stored\zerocount - \letvalue{\e!start\v!item}\strc_itemgroups_collected_store - \fi} - -%D Left-overs: - -\protected\def\item % todo: frozen - {\strc_itemgroups_item_alone} - -\def\strc_itemgroups_item_alone[#category]#text\par - {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}% - \startitem#text\stopitem - \stopitemgroup} - -\protected\def\head % todo: frozen - {\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}% todo: frozen - {\startitemgroup[\v!itemize]% - \startitemgroupitem - \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}} % todo: frozen - -% \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: - -\permanent\tolerant\protected\def\itemtag[#reference]% we can reuse more - {% what if empty - \def\currentitemreference{#reference}% - \iftrialtypesetting - \strc_counters_save\v_strc_itemgroups_counter - \strc_itemgroups_increment_item_counter - \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!leftmargindistance=\zeropoint, - \c!rightmargindistance=\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!packcriterium=\zerocount, - \c!criterium=\v!all, % permits 0 and negative numbers - %\c!option=, - \c!textdistance=\v!space, % none big medium small - \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] - -%D This is really ugly I should get rid of the global mess, whuch is a side -%D effect of the simple \type {\item} interface that we're stuck with for -%D compatibility reasons. See footnotes for usage. It's probablynot robust -%D for mixed itemgroups so in the end I need to get rid of the globals. One -%D problem is that counters are set. - -\defineitemgroup - [\v!itemize:\v!note] - -\def\strc_itemgroups_push - {\edef\strc_itemgroups_pop - {\xdef\noexpand\currentitemlevel{\currentitemlevel}% - \global\c_strc_itemgroups_nesting \the\c_strc_itemgroups_nesting \relax - \global\c_strc_itemgroups_column_depth\the\c_strc_itemgroups_column_depth\relax}% - \global\c_strc_itemgroups_column_depth\zerocount - \global\c_strc_itemgroups_nesting \zerocount - \glet\currentitemlevel\!!zerocount - \enforced\permanent\protected\def\startitemize{\startitemgroup[\v!itemize:\v!note]}% - \enforced\permanent\protected\def\stopitemize {\stopitemgroup}} - -\let\strc_itemgroups_pop\relax - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-lab.mkxl b/tex/context/base/mkiv/strc-lab.mkxl deleted file mode 100644 index 95bfa82df..000000000 --- a/tex/context/base/mkiv/strc-lab.mkxl +++ /dev/null @@ -1,198 +0,0 @@ -%D \module -%D [ file=strc-lab, % was part of strc-des, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Labels, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Labels} - -\unprotect - -% todo: reset and increment will go - -%D Labels are implemented somewhat inefficient but have the advantage that they -%D can be controlled like other constructions. Who knows when that comes in -%D handy? - -\installcorenamespace{labels} - -\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one) - -\installcounterassociation{label} - -\let\setuplabels\setuplabel - -\setuplabel - [\c!alternative=\v!intext, - \c!headstyle=\v!bold, - \c!titlestyle=\v!bold, - \c!distance=\zeropoint, - \c!width=\v!fit, - \c!titledistance=.5\emwidth, - \c!margin=\v!no, - \c!titleleft=(, - \c!titleright=), - \c!display=\v!no, - \c!titlecommand=, - \c!expansion=\v!no, - \c!way=\v!by\v!text, - \c!prefix=\v!no, - \c!prefixconnector=., - \c!text=\currentlabel, - \c!number=\v!yes, % else description - \c!start=0, - \c!state=\v!start, - \c!levels=3] - -\protected\def\strc_define_commands_label#1#2#3% current level parent - {\doifelsenothing{#3} - {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}% - \setevalue{\??label#1:\s!parent}{\??label}}% - {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}% - \setevalue{\??label#1:\s!parent}{\??label#3}}% - \ifconditional\c_strc_constructions_define_commands - \frozen\instance\setuevalue{\e!next #1}{\strc_labels_next {#1}{\number#2}}% obsolete - \frozen\instance\setuevalue{\v!reset#1}{\strc_labels_reset{#1}{\number#2}}% obsolete % should be \e!reset anyway - %frozen\instance\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 - \frozen\instance\setuevalue{#1}{\strc_labels_command[#1]}% - \fi} - -% todo: \strc_labels_command for user - -\appendtoks - \ifempty\currentlabelparent - % 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 - \ifempty\p_counter % - \let\p_counter\currentlabel - \fi - \doifelsecounter\p_counter\donothing{\strc_labels_define_counter\p_counter}% - \letlabelparameter\s!counter\p_counter -\to \everydefinelabel - -\let\p_strc_constructions_title \empty -\let\p_strc_constructions_number\empty - -\newconditional\c_strc_constructions_number_keep - -\setvalue{\??constructioninitializer\v!label}% - {\let \currentlabel \currentconstruction - \enforced\let\constructionparameter \labelparameter - \enforced\let\constructionnamespace \??label - \enforced\let\detokenizedconstructionparameter\detokenizedlabelparameter - \enforced\let\letconstructionparameter \letlabelparameter - \enforced\let\useconstructionstyleandcolor \uselabelstyleandcolor - \enforced\let\setupcurrentconstruction \setupcurrentlabel - % shared with enumerations - \edef\p_strc_constructions_number{\constructionparameter\c!number}% - \ifx\p_strc_constructions_number\v!yes - \settrue\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_save\currentconstructionnumber - \fi - \ifconditional\c_strc_constructions_number_keep \else - \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel - \fi - \else - \setfalse\c_strc_constructions_number_state - \fi - \edef\p_strc_constructions_title{\constructionparameter\c!title}% - \ifx\p_strc_constructions_title\v!yes - \settrue\c_strc_constructions_title_state - \else - \setfalse\c_strc_constructions_title_state - \fi} - -\setvalue{\??constructionfinalizer\v!label}% - {\ifconditional\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_restore\currentconstructionnumber - \fi - \fi} - -%D Interfaces: - -\protected\def\strc_labels_command{\setfalse\c_strc_constructions_number_keep\strc_descriptions_command} -\protected\def\strc_labels_current{\settrue \c_strc_constructions_number_keep\strc_descriptions_command} - -\protected\def\strc_labels_next {\strc_constructions_next_indeed \namedlabelparameter} % #1#2 -\protected\def\strc_labels_reset {\strc_constructions_reset_indeed\namedlabelparameter} % #1#2 -%protected\def\strc_labels_set {\strc_constructions_set_indeed \namedlabelparameter} % #1#2 - -% similar to enumerations - -\def\strc_labels_define_counter#1% - {\definecounter[#1]% - \registerlabelcounter{#1}} - -\appendtoks - \synchronizelabelcounters -\to \everysetuplabel - -\appendtoks - \synchronizelabelcounters -\to \everydefinelabel - -% no start stop here - -\letcsname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname - -\protected\setevalue{\??constructioncommandhandler\v!label}% - {\csname\??constructionstarthandler\v!construction\endcsname - \csname\??constructionstophandler \v!construction\endcsname - \endgroup} - -\protected\setvalue{\??constructiontexthandler\v!label}% - {\begingroup - \useconstructionstyleandcolor\c!headstyle\c!headcolor - \strc_labels_text - \endgroup} - -\let\strc_labels_text\strc_enumerations_text - -% inline variant - -\defineconstructionalternative - [\v!intext] - [\c!renderingsetup=\??constructionrenderings:\v!intext] - -\startsetups[\??constructionrenderings:\v!intext] - \dontleavehmode\box\constructionheadbox -\stopsetups - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-lev.mklx b/tex/context/base/mkiv/strc-lev.mklx deleted file mode 100644 index b8b633c32..000000000 --- a/tex/context/base/mkiv/strc-lev.mklx +++ /dev/null @@ -1,101 +0,0 @@ -%D \module -%D [ file=strc-lev, -%D version=2010.09.23, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Automatic Levels, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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}{} - -\unprotect - -\unexpanded\def\definesectionlevels{\dodoubleargument\strc_levels_define} -\unexpanded\def\startsectionlevel {\dosingleempty \strc_levels_start_section} -\unexpanded\def\startsubjectlevel {\dosingleempty \strc_levels_start_subject} - -\unexpanded\def\strc_levels_define[#category][#list]{\clf_definesectionlevels{#category}{#list}} -\unexpanded\def\stopsectionlevel {\clf_stopsectionlevel} -\unexpanded\def\stopsubjectlevel {\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_section[#category]% - {\doifelseassignment{#category}% - {\clf_startsectionlevel\plusone{\v!default}{\currentnamedsection}[#category]}% - {\clf_startsectionlevel\plusone {#category}{\currentnamedsection}}} - -\unexpanded\def\strc_levels_start_subject[#category]% - {\doifelseassignment{#category}% - {\clf_startsectionlevel\plustwo{\v!default}{\currentnamedsection}[#category]}% - {\clf_startsectionlevel\plustwo {#category}{\currentnamedsection}}} - -\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!title}, - {\v!section,\v!subject}, - {\v!subsection,\v!subsubject}, - {\v!subsubsection,\v!subsubsubject}, - {\v!subsubsubsection,\v!subsubsubject}, - {\v!subsubsubsubsection,\v!subsubsubject}] - -\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/tex/context/base/mkiv/strc-lev.mkvi b/tex/context/base/mkiv/strc-lev.mkvi index cfb704fc9..b8b633c32 100644 --- a/tex/context/base/mkiv/strc-lev.mkvi +++ b/tex/context/base/mkiv/strc-lev.mkvi @@ -23,31 +23,33 @@ \unprotect -\permanent\tolerant\protected\def\definesectionlevels[#category]#spacer[#list]% - {\clf_definesectionlevels{#category}{#list}} % we could scan/use public at the lua end +\unexpanded\def\definesectionlevels{\dodoubleargument\strc_levels_define} +\unexpanded\def\startsectionlevel {\dosingleempty \strc_levels_start_section} +\unexpanded\def\startsubjectlevel {\dosingleempty \strc_levels_start_subject} -\permanent\tolerant\protected\def\startsectionlevel[#category]% +\unexpanded\def\strc_levels_define[#category][#list]{\clf_definesectionlevels{#category}{#list}} +\unexpanded\def\stopsectionlevel {\clf_stopsectionlevel} +\unexpanded\def\stopsubjectlevel {\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_section[#category]% {\doifelseassignment{#category}% {\clf_startsectionlevel\plusone{\v!default}{\currentnamedsection}[#category]}% {\clf_startsectionlevel\plusone {#category}{\currentnamedsection}}} -\permanent\protected\def\stopsectionlevel - {\clf_stopsectionlevel} % we could use public at the lua end - -\permanent\tolerant\protected\def\startsubjectlevel[#category]% +\unexpanded\def\strc_levels_start_subject[#category]% {\doifelseassignment{#category}% {\clf_startsectionlevel\plustwo{\v!default}{\currentnamedsection}[#category]}% {\clf_startsectionlevel\plustwo {#category}{\currentnamedsection}}} -\permanent\protected\def\stopsubjectlevel - {\clf_stopsectionlevel} % we could use public at the lua end - -\permanent\tolerant\protected\def\nostarthead[#category]#spacer[#settings]#spacer[#userdata]% +\unexpanded\def\strc_levels_start_nop[#category][#settings][#userdata]% {\blank \noindentation{\tttf[start missing section level #category]} \blank} -\permanent\tolerant\protected\def\nostarthead[#category]% +\unexpanded\def\strc_levels_stop_nop[#category]% {\blank \noindentation{\tttf[stop missing section level #category]} \blank} @@ -61,9 +63,9 @@ {\v!subsubsubsection,\v!subsubsubject}, {\v!subsubsubsubsection,\v!subsubsubject}] -\aliased\let\definestructurelevels\definesectionlevels -\aliased\let\startstructurelevel \startsectionlevel -\aliased\let\stopstructurelevel \stopsectionlevel +\let\definestructurelevels\definesectionlevels +\let\startstructurelevel \startsectionlevel +\let\stopstructurelevel \stopsectionlevel \protect \endinput diff --git a/tex/context/base/mkiv/strc-lnt.mklx b/tex/context/base/mkiv/strc-lnt.mklx deleted file mode 100644 index f24c93ee4..000000000 --- a/tex/context/base/mkiv/strc-lnt.mklx +++ /dev/null @@ -1,359 +0,0 @@ -%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} - -\aliased\let\setuplinenote\setupnote - -\newcount\c_strc_linenotes -\newtoks\everydefinelinenote - -\permanent\tolerant\protected\def\definelinenote[#1]#*[#2]#*[#3]% - {\ifarguments - % error - \orelse\ifcsname\??linenote#1\endcsname - % there might be files that define the default 'linenote' - \ifparameters\or\or - \setupnote[#1][#2]% - \or - \setupnote[#1][#3]% - \fi - \else - \ifparameters\or - \definenote[#1]% - \or - \definenote[#1][#2]% - \or - \definenote[#1][#2][#3]% - \fi - \pushmacro\currentnote - \edef\currentnote{#1} - \letcsname\??linenote\currentnote\expandafter\endcsname\csname\currentnote\endcsname % use copy command - \frozen\instance\setuevalue {\currentnote}{\strc_linenotes_direct{\currentnote}}% - \frozen\instance\setuevalue{\e!start\currentnote}{\strc_linenotes_start {\currentnote}}% - \frozen\instance\setuevalue{\e!stop \currentnote}{\strc_linenotes_stop }% - \the\everydefinelinenote - \popmacro\currentnote - \fi} - -\protected\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]}} - -\protected\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]} - -\protected\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]} - -\protected\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} - -\protected\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 - -\protected\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}% - \global\letcsname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from - \global\letcsname\??linenotespreviousto \currentnotation\endcsname\m_page_lines_current_to - \endgroup} - -% compression - -\installcorenamespace{linenotescompressmethod} - -% compress=yes|no -% compressmethod=separator|stopper - -\setvalue{\??linenotescompressmethod\v!separator}% - {\edef\p_compressseparator{\noteparameter\c!compressseparator}% - \scratchskip\noteparameter\c!compressdistance\relax - \ifempty\p_compressseparator - \hskip\scratchskip - \else - \hskip.5\scratchskip - \begingroup\p_compressseparator\endgroup - \hskip.5\scratchskip - \fi} - -\setvalue{\??linenotescompressmethod\v!stopper}% - {\edef\p_compressstopper{\noteparameter\c!compressstopper}% - \scratchskip\noteparameter\c!compressdistance\relax - \ifempty\p_compressstopper - \hskip\scratchskip - \else - \begingroup\p_compressstopper\endgroup - \hskip.5\scratchskip - \fi} - -\setvalue{\??linenotescompressmethod\v!space}% - {\hskip\noteparameter\c!compressdistance\relax} - -\def\strc_linenotes_check_compression - {\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 - {\begincsname\??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: - -\permanent\protected\def\doresetlinenotecompression#1% \strc_linenotes_reset_previous - {\global\letcsname\??linenotespreviousfrom#1\endcsname\empty - \global\letcsname\??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 - \hpack to \zeropoint - {\forgetall - \hsize\zeropoint - \hss - \vpack to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}% - {\color[blue]{\vl}}% - \vpack to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}% - \hss}% - \prewordbreak - \fi} - -\permanent\protected\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: - -\aliased\let\fromlinenote\startlinenote -\aliased\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/tex/context/base/mkiv/strc-lst.mklx b/tex/context/base/mkiv/strc-lst.mklx deleted file mode 100644 index 2e088766a..000000000 --- a/tex/context/base/mkiv/strc-lst.mklx +++ /dev/null @@ -1,1566 +0,0 @@ -%D \module -%D [ file=strc-lst, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Lists, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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}{} - -% 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 - -\aliased\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: - -\permanent\protected\def\usenestedliststyleandcolor#style#color% will change - {\useliststyleandcolor#style#color% - % how about style - \ifempty\currentcolorparameter \else - \resetinteractionparameter\c!color - \resetinteractionparameter\c!contrastcolor - \fi} - -\permanent\protected\def\doifelselist#tag% can also move to \installcommandhandler - {\ifcsname\namedlisthash{#tag}\s!parent\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiflistelse\doifelselist - -%D Regular list entries are bound to a specific location in order to get the right -%D pagenumber etc.\ associated. When pushing something inbetween (in mkiv) it ends -%D up directtly in the list. This is the default because otherwise users will wonder -%D why spacing might get messed up (due to an unseen but present node). It is -%D possible to 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} variable when -%D placing a list. The \type {command} option only pushes commands into the right -%D order, and \type {all} orders all entries (which might be too much). In this case -%D no specific location is needed with the inbetween method. Maybe additional -%D mechanisms show up some day. See \type {inbetween-001.tex} for an example. - -% command : location=none -% userdata : location=none -% simple : location=here - -\installcorenamespace {listlocations} - -% \permanent\protected\def\doifelseinlistentry#1% -% {\ifcsname\??listlocations#1\endcsname -% \ifnum\lastnamedcs=\structurelistlocation\relax -% \doubleexpandafter\firstoftwoarguments -% \else -% \doubleexpandafter\secondoftwoarguments -% \fi -% \else -% \expandafter\secondoftwoarguments -% \fi} - -\permanent\protected\def\doifelseinlistentry#1% - {\unless\ifcsname\??listlocations#1\endcsname - \expandafter\secondoftwoarguments - \orelse\ifnum\lastnamedcs=\structurelistlocation\relax - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifelseincurrentlistentry - {\doifelseinlistentry\currentlist} - -\permanent\protected\def\structurelistinject[#tag]% - {\begingroup - \edef\currentlist{#tag}% - \doifelse{\listparameter\c!state}\v!start\strc_lists_inject_yes\strc_lists_inject_nop} - -\tolerant\protected\def\strc_lists_inject_nop[#settings]#spacer[#userdata]% - {\endgroup} - -\def\strc_lists_inject_enhance#listindex% - {\expandafter\clf_deferredenhancelist\number#listindex\relax} - -\tolerant\protected\def\strc_lists_inject_yes[#settings]#spacer[#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 \locationcount - % 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}{\the\locationcount}% - \ifx\p_location\v!here - % this branch injects nodes ! - \strc_lists_inject_enhance{\currentlistnumber}% - \clf_setinternalreference - internal \locationcount - view {\interactionparameter\c!focus}% - \relax % this will change - \xdef\currentstructurelistattribute{\the\lastdestinationattribute}% - \dontleavehmode\hpack 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 {}{}{} - -\protected\def\strc_lists_inject_direct[#tag]% [#settings][#userdata] - {\begingroup - \edef\currentlist{#tag}% - \strc_lists_inject_yes} % [#settings][#userdata] - -\permanent\protected\def\writebetweenlist[#tag]% - {\begingroup - \edef\currentlist{#tag}% - \doifelse{\namedlistparameter{#tag}\c!state}\v!start - \strc_lists_write_between_yes - \strc_lists_write_between_nop} - -\tolerant\def\strc_lists_write_between_yes[#settings]#:#command% - {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]} - -\tolerant\def\strc_lists_write_between_nop[#settings]#:#command% - {\endgroup} - -\permanent\protected\def\writedatatolist[#tag]% - {\begingroup - \edef\currentlist{#tag}% - \doifelse{\namedlistparameter{#tag}\c!state}\v!start - \strc_lists_write_data_to_yes - \strc_lists_write_data_to_nop} - -\tolerant\def\strc_lists_write_data_to_yes[#settings]#spacer[#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} - -\tolerant\def\strc_lists_write_data_to_nop[#settings]#spacer[#userdata]% - {\endgroup} - -\permanent\protected\def\writetolist[#tag]% - {\begingroup - \edef\currentlist{#tag}% - \doifelse{\namedlistparameter{#tag}\c!state}\v!start - \strc_lists_write_to_yes - \strc_lists_write_to_nop} - -\tolerant\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}]} - -\tolerant\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 it possible to -%D flush for instance an nested (or merged) table of contents. Keep in mind that -%D placing a list is what we do most (think of tables of contents, figures, etc.\ -%D but other usage is also possible in which case low level commands have to be -%D used. - -\newtoks\everystructurelist - -\permanent\tolerant\protected\def\placelist[#taglist]#spacer[#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} - -\permanent\tolerant\protected\def\placerawlist[#tag]#spacer[#settings]% just one list - {\strc_lists_place_indeed\empty{#tag}{#settings}} - -\aliased\let\strc_lists_place\placelist % used in strc-flt - -\def\strc_lists_place_indeed#tag#list#settings% - {\begingroup - \the\t_lists_every_renderingcleanup % \let\currentlistentrylocation\empty - \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 originally introduced -%D to minimize the number for commands in a document source but nowadays that is -%D less an issue in the sense that the extra few lines are neglectable to the rest. - -\ifdefined\startnamedsection \else \let\startnamedsection\relax \fi -\ifdefined\stopnamedsection \else \let\stopnamedsection \relax \fi -\ifdefined\headtext \else \let\headtext \relax \fi - -\permanent\tolerant\protected\def\completelist[#tag]#spacer[#settings]% - {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#tag},\c!reference=#tag]}% {} around ref ? - \strc_lists_place[#tag][#settings]% - \stopnamedsection} - -\permanent\tolerant\protected\def\strc_lists_complete[#singular]#spacer[#plural]#spacer[#settings]% used in strc-flt - {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}% {} around ref ? - \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 - -\permanent\tolerant\protected\def\definecombinedlist[#tag]#spacer[#list]#spacer[#settings]% - {\definelist[#tag][\c!criterium=\v!local,\c!reference=,\c!alternative=,\c!list={#list},#settings]% inherits from root - \frozen\instance\setvalue{\e!setup#tag\e!endsetup}{\setupcombinedlist[#tag]}% - \frozen\instance\setvalue{\e!place#tag}{\placecombinedlist[#tag]}% - \frozen\instance\setvalue{\e!complete#tag}{\strc_lists_complete[#tag]}} - -\permanent\tolerant\protected\def\setupcombinedlist[#tag]#spacer[#settings]% - {\ifarguments\or\or - \setuplist[#tag][#settings]% we don't want to mess up the parent - \fi} - -\permanent\tolerant\protected\def\placecombinedlist[#tag]#spacer[#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} - -%D Given that some variables are set, we can ask for some properties of -%D an entry. - -\mutable\def\currentstructurelistnumber{0} % injection -\mutable\def\currentlistmethod {entry} % typesetting -\mutable\def\currentlistindex {0} % typesetting (maybe also a real counter) - -\permanent\protected\def\savedlistnumber #1#2{\clf_savedlistnumber {#1}\numexpr#2\relax} -\permanent\protected\def\savedlisttitle #1#2{\clf_savedlisttitle {#1}\numexpr#2\relax} -\permanent\protected\def\savedlistprefixednumber#1#2{\clf_savedlistprefixednumber{#1}\numexpr#2\relax} - -\newconditional\c_lists_show_realpage - -\installcorenamespace {listpagenumber} - -\setvalue{\??listpagenumber\v!always }{\settrue\c_lists_show_page\settrue\c_lists_has_page} -\setvalue{\??listpagenumber\v!yes }{\settrue\c_lists_show_page} -\setvalue{\??listpagenumber\s!realpage}{\settrue\c_lists_show_page\settrue\c_lists_show_realpage} - -\def\strc_lists_process_pagenumber#1% - {\begincsname\??listpagenumber#1\endcsname} - -\def\structurelistlocation - {\clf_listlocation\numexpr\currentlistindex\relax} - -\def\structurelistrealpagenumber - {\clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax} - -\protected\def\structurelistpagenumber - {\dostarttagged\t!listpage\empty - \ifconditional\c_lists_show_realpage - \clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax - \else - \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 - \fi - \dostoptagged} - -\permanent\protected\def\structurelistuservariable#name% - {\dostarttagged\t!listdata{#name}% - \clf_listuserdata{\currentlist}\currentlistindex{#name}% - \dostoptagged} - -\permanent\def\rawstructurelistuservariable#name% - {\clf_listuserdata{\currentlist}\currentlistindex{#name}} - -\permanent\protected\def\structurelistfirst {\structurelistuservariable\s!first } % s! -\permanent\protected\def\structurelistsecond{\structurelistuservariable\s!second} % s! - -\permanent\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! % was \protected -\permanent\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! % was \protected - -\permanent\protected\def\doifelsestructurelisthaspage - {\clf_doifelselisthaspage{\currentlist}\numexpr\currentlistindex\relax} - -\permanent\protected\def\doifelsestructurelisthasnumber - {\clf_doifelselisthasnumber{\currentlist}\numexpr\currentlistindex\relax} - -\aliased\let\doifstructurelisthaspageelse \doifelsestructurelisthaspage -\aliased\let\doifstructurelisthasnumberelse\doifelsestructurelisthasnumber - -\permanent\protected\def\structurelistgenerictitle - {\dostarttagged\t!listcontent\empty - \clf_listtitle{\currentlist}\currentlistindex\relax - \dostoptagged} - -\permanent\protected\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 ...) - -\protected\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} - -\protected\def\strc_lists_analyze#list#criterium#reference% - {\clf_analyzelist - names {#list} - criterium {#criterium} - reference {#reference} - \relax} - -\permanent\def\firststructureelementinlist#list% expandable - {\firstinset{#list}} - -\permanent\def\structurelistsize - {\clf_listsize} - -%D Depending on what kind of list we have (e.g.\ a section related one) processors -%D 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}] - -\permanent\protected\def\installstructurelistprocessor#tag#meaning% - {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}} - -\permanent\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 - \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\orelse - \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\lastnamedcs\orelse - \ifcsname\??structurelistprocessor\currentlist \endcsname\lastnamedcs\else - \strc_lists_entry_process_default\fi - \dostoptagged - \listextraparameter\c!after} - -\protected\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end! - {\clf_pushlist#index\relax - %\let\currentlistentrylocation\empty - \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 are used but -%D nevertheless structure is present. Beware, the list symbol macro gets an argument -%D passed, i.e. when this argument is not picked up, the symbol becomes a kind of -%D prefix. It's not really a user command (and might even get protected). - -\permanent\protected\def\listsymbol[#tag]#number% - {\begingroup - \edef\currentlist{#tag}% - \def\currentlistentrynumber{#number}% no edef else tag problems - \currentlistsymbol - \endgroup} - -%D For historical reasons we're stuck to symbols, so in order to generalize, we have -%D to hook it into the symbol handle. One way to deal with this is to use a -%D different key and as it makes sense to use setups instead of def's we use a new -%D key \quote {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] - -\permanent\protected\def\currentlistsymbol - {\edef\p_symbol{\listparameter\c!symbol}% - \doifelseinsymbolset\v!list\p_symbol - {\directsymbol\v!list\p_symbol} - {\directsymbol\v!list\s!default}} - -\protected\def\strc_lists_symbol_none - {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}% - \hpack to \scratchwidth{}} - -\protected\def\strc_lists_symbol_one - {\strut\symbol[bullet]} - -\protected\def\strc_lists_symbol_two - {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} - -\protected\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\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchdepth - \endgroup} - -\protected\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} - -\protected\def\strc_lists_symbol_default - {\dontleavehmode - \strut - \begingroup - \edef\currentlistlabel{\listparameter\c!label}% can be used in label - \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} -% -% \protected\def\installlistfiller#1#2% -% {\setuvalue{\??listfiller#1}{#2}} -% -% \protected\def\listfiller#1% -% {\begincsname\??listfiller#1\endcsname} -% -% \protected\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=\directlistparameter\c!command, - \c!symbol=.] - -\permanent\protected\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 .5\emwidth{\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 - -\permanent\tolerant\protected\def\definelistplacement[#tag]#spacer[#method]% - {\edef\p_method{#method}% - \ifempty\p_method - \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: : {\bla} - -\def\strc_lists_define_placement_yes#tag% - {\protected\defcsname\??listelementcommand#tag\endcsname##1##2##3} - -% direct definition: {\bla} - -\def\strc_lists_define_placement_nop#tag% - {\protected\defcsname\??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 - -\mutable\let\currentlistentrylocation \empty % watch the 'entry' in the name -\mutable\let\currentlistentrynumber \empty % watch the 'entry' in the name -\mutable\let\currentlistentrytitle \empty % watch the 'entry' in the name -\mutable\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 - \enforced\let\\\space - % so expanding this token register has to come *after* the font switch - \dontconvertfont % (**) this has to become an option (see publ) -\to \t_lists_every_renderingtext - -\appendtoks - % because we want to avoid redundant lua calls we expand the - % location beforehand - \ifempty\currentlistentrylocation - \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 - \setfalse\c_lists_show_page % necessary? - \processcommacommand[\listparameter\c!pagenumber]\strc_lists_process_pagenumber - \ifconditional\c_lists_has_page \else - \doifelsestructurelisthaspage\settrue\setfalse\c_lists_has_page - \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_realpage - \setfalse\c_lists_show_number -\to \t_lists_every_renderingcleanup - -\let\m_strc_list_alternative\empty % combined - -\protected\def\strc_lists_apply_renderingsetup - {\the\t_lists_every_renderingsetup - % now we group - \begingroup - \ifempty\m_strc_list_alternative - \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 - -\permanent\protected\def\currentlistentrytitlesynchronize - {\the\t_lists_every_renderingsynchronize} - -\permanent\protected\def\currentlistentrytitlerendered - {\currentlistentrytitlesynchronize\currentlistentrytitle} - -\startsetups[\??listrenderings:command] - \edef\p_command{\listalternativeparameter\c!command}% - \ifempty\p_command - [\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} - \ifempty\p_command - \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 - \orelse\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 - \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\hpack { - \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 - \ifzeropt\wd\b_strc_lists_page \else \ifdim\scratchdimen>\zeropoint\relax - \rightskip\scratchdimen\s!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 - \ifzeropt\wd\b_strc_lists_page\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} - \ifempty\p_symbol - \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\s!plus\emwidth\s!minus.25\emwidth\relax - \else - \hskip\scratchdistance\s!plus.5\scratchdistance\s!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 { - \ifempty\p_command - [ - \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 such -%D (for now). No interaction either as that is dealt with elsewhere. -%D -%D \currentlistsymbol -%D \currentlistentrynumber -%D \currentlistentrytitle -%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 - \ifzeropt\scratchoffset - \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 in an -%D 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 - -\permanent\def\listboxproperties {\strc_lists_get_reference_attribute} -\permanent\def\listrenderingsetup {\the\t_lists_every_renderingtext} -\permanent\def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize} - -\protected\def\strc_lists_interaction_check - {\iflocation - \strc_lists_interaction_check_yes - \else - \strc_lists_interaction_check_nop - \fi} - -\def\strc_lists_interaction_check_yes_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_yes_nop - {\a_strc_lists_reference \attributeunsetvalue - \a_strc_lists_destination\attributeunsetvalue - \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} - -\def\strc_lists_interaction_check_yes - {\ifempty\currentlistentrylocation - \strc_lists_interaction_check_yes_nop - \orelse\ifnum\currentlistentrylocation=\zerocount - \strc_lists_interaction_check_yes_nop - \else - \strc_lists_interaction_check_yes_yes - \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 - \c_attr_reference\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 - {\c_attr_destination\a_strc_lists_destination} - -\protected\def\strc_lists_set_style_color_normal#style#color#element% - {\useliststyleandcolor#style#color} - -\protected\def\strc_lists_set_style_color_special#style#color#element% - {\useliststyleandcolor#style#color% - \ifempty\currentcolorparameter - \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}% - \ifempty\p_maxwidth - \listparameter\c!textcommand{#text}% - \else - \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}% - \fi} - -% public helpers - -\permanent\protected\def\startcurrentlistentrywrapper - {\hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute\bgroup} - -\aliased\let\stopcurrentlistentrywrapper\egroup - -\aliased\let\currentlistentryreferenceattribute \strc_lists_get_reference_attribute -\aliased\let\currentlistentrydestinationattribute\strc_lists_get_destination_attribute -\aliased\let\currentlistentrylimitedtext \strc_lists_limitated_text - -% todo: - -\def\utilitylistlength{\listlength} % old name ... uses in styles - -\mutable\let\listlength\!!zerocount % better use listmode - -\permanent\tolerant\protected\def\determinelistcharacteristics[#list]#spacer[#settings]% - {\begingroup - \edef\currentlist{\firststructureelementinlist{#list}}% - \ifempty\currentlist - \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/tex/context/base/mkiv/strc-mar.mkxl b/tex/context/base/mkiv/strc-mar.mkxl deleted file mode 100644 index a15db8265..000000000 --- a/tex/context/base/mkiv/strc-mar.mkxl +++ /dev/null @@ -1,135 +0,0 @@ -%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}{} - -\unprotect - -%D Synchronizing marks is a rather tricky and messy business. When setting a mark, a -%D node is added to the list in order for to \TEX\ be able to figure out the 3 -%D current marks when a page is made (last mark on previous page, first on current -%D page, last on 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 one on the -%D previous page for instance. In \LUATEX\ we can clear a marks state register with -%D \type {\clearmarks} but since this is an immediate operation it might have -%D unwanted side effects when \TEX\ has collected several pages of text and -%D finishing off these pages uses marks. -%D -%D In \MKIV\ we provide an alternative model that permits some more control over the -%D way marks are used. It is not entirely compatible with \MKII\ or previous \MKIV\ -%D implementations but in practice this is not a real problem. It's also easier now -%D to extend this mechanism. - -\definesystemattribute [marks] [global] - -\installcorenamespace{marking} - -\installcommandhandler \??marking {marking} \??marking - -\newconditional\inhibitgetmarking % will become private -\newconditional\inhibitsetmarking % will become private - -\newtoks \everymarking - -\appendtoks - \clf_definemarking{\currentmarking}{\currentmarkingparent}% -\to \everydefinemarking - -\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}} -\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}} -\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} -\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded - -\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini - -\permanent\protected\tolerant\def\setmarking[#1]#:#2% - {\ifconditional\inhibitsetmarking\else - \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes - {\clf_setmarking{#1}{#2}}% - {\clf_setmarking{#1}{\detokenize{#2}}}% - \fi} - -\aliased\let\marking \setmarking -\aliased\let\doifmarkingelse\doifelsemarking - -% defaults - -\setupmarking - [\c!expansion=\v!no, - \c!separator=\space\emdash\space, - \c!filtercommand=\firstofoneargument, - \c!state=\v!start] - -% fetching, regular interface - -\permanent\protected\def\getmarking - {\ifconditional\inhibitgetmarking - \expandafter\strc_markings_get_nop - \else - \expandafter\strc_markings_get_yes - \fi} - -\tolerant\def\strc_markings_get_nop[#-]#*[#-]#*[#-]% - {} - -\tolerant\def\strc_markings_get_yes[#1]#*[#2]#*[#3]% - {\doif{\namedmarkingparameter{#1}\c!state}\v!start - {\begingroup - \setsystemmode\v!marking - \the\everymarking - \ifparameter#3\or - \clf_getmarking{#1}{#2}{#3}% - \else - \clf_getmarking{#1}{\v!page}{#2}% - \fi - \endgroup}} - -% the fetchers are fully expandable: [name][method] - -\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi} -\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi} -\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi} - -\aliased\let\fetchmark\fetchonemark - -% also fully expandable but here we have: [name][range][method] - -\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi} -\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi} -\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi} - -\aliased\let\fetchmarking\fetchonemarking - -\permanent\def\markingseparator#1{\namedmarkingparameter{#1}\c!separator} -\permanent\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/tex/context/base/mkiv/strc-mat.mkxl b/tex/context/base/mkiv/strc-mat.mkxl deleted file mode 100644 index e72be7d3e..000000000 --- a/tex/context/base/mkiv/strc-mat.mkxl +++ /dev/null @@ -1,1308 +0,0 @@ -%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}{} - -% -- 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=\v!math, - \c!location=\v!right, - \c!left=(, - \c!right=), - \c!expansion=\v!yes, % maybe automatically - \c!spacebefore=\v!big, - \c!spaceafter=\formulaparameter\c!spacebefore, - \c!width=\hsize, - \c!leftmargin=\zeropoint, - \c!rightmargin=\zeropoint, - \c!indentnext=\v!no, - \c!alternative=\s!default, - \c!strut=\v!no, - \c!numberstrut=\v!yes, % \v!no \v!yes \v!always - \c!distance=2\emwidth] - -\setupformulaframed - [%c!location=, - %c!width=, - %c!align=, - \c!offset=.5\exheight] - -\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? - \frozen\instance\setuevalue{\e!start\currentformula\v!formula}{\strc_formulas_start_formula{\currentformula}}% - \frozen\instance\setuevalue{\e!stop \currentformula\v!formula}{\strc_formulas_stop_formula}% -\to \everydefineformula - -\definelist[\v!formula] - -\permanent\setuvalue{\e!start\v!formula}{\strc_formulas_start_formula{}} -\permanent\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 - -\permanent\tolerant\protected\def\defineformulaalternative[#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 - -\protected\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 - \glet#3\m_strc_counters_last_registered_index - \glet#4\m_strc_counters_last_registered_synchronize - \glet#5\m_strc_counters_last_registered_attribute} - -% modes: 0=unset, 1=forced, 2=none, 3=reference - -\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_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_number_noneed - {\doif{\formulaparameter\c!numberstrut}\v!always\strut} - -\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\strc_formulas_place_number_noneed - \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 - -\permanent\protected\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 - {\edef\p_strut{\formulaparameter\c!numberstrut}% - \ifx\p_strut\v!always - \strut - \orelse\ifx\p_strut\v!yes - \strut - \fi - \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} - -\protected\def\strc_formulas_place_current_number - {\ifempty\namedformulaentry - \strc_formulas_handle_current_references - \labeltexts\currentformula{\convertedcounter[\v!formula][]}% - \else - \expandafter % hm, the next one reset \namedformulaentry - \strc_formulas_handle_current_references - \namedformulaentry - \fi} - -\permanent\def\theformuladestinationattribute#1% - {\iflocation\ifx#1\relax\orelse\ifempty#1\else - \c_attr_destination#1% - \glet#1\relax - \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 - -\mutable\let\currentformulasreference \empty -\mutable\let\currentformulareference \empty -\mutable\let\currentsubformulareference \empty -\mutable\let\currentnestedformulareference\empty - -\appendtoks - \glet\currentformulasreference \empty - \glet\currentformulareference \empty - \glet\currentsubformulareference \empty - \glet\currentnestedformulareference\empty -\to \everyresetformulas - -\mutable\let\currentformulassuffix \empty -\mutable\let\currentformulasuffix \empty -\mutable\let\currentsubformulasuffix \empty -\mutable\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 - {\ifempty\namedformulaentry - \strc_counters_increment\v!formula - \doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}% - \fi - \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. - -\pushoverloadmode - -\let\reqno\eqno % no longer valid as we just nil it - -\let\math_native_leqno\leqno -\let\math_native_reqno\reqno - -\protected\def\normaleqno#1{\writestatus\m!system{no native (l)eqno equation number support}} - -\let\normalleqno\normaleqno -\let\normalreqno\normaleqno - -\let\leqno\normaleqno -\let\reqno\normaleqno -\let\eqno \normaleqno - -\popoverloadmode - -%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: - -\abovedisplayskip \zeropoint -\abovedisplayshortskip \zeropoint % evt. 0pt minus 3pt -\belowdisplayskip \zeropoint -\belowdisplayshortskip \zeropoint % evt. 0pt minus 3pt - -\predisplaypenalty \zerocount -\postdisplaypenalty \zerocount % -5000 goes wrong, see penalty at \section -\mathdisplayskipmode \plusthree % because align also adds - -% \predisplaygapfactor \zerocount % default is 2000 - -\protected\def\strc_formulas_forget_display_skips - {\mathdisplayskipmode \plusthree - \abovedisplayskip \zeropoint - \belowdisplayskip \zeropoint - \abovedisplayshortskip\zeropoint - \belowdisplayshortskip\zeropoint} - -\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 -\newdimen\d_strc_formulas_display_width - -\newconstant\c_strc_formulas_mode % this will go away -\newconstant\c_strc_formulas_space_model - -\newconstant\c_strc_math_vertical % experiment - -\c_strc_formulas_mode \plustwo % 0=native 1=simple (old) 2=align (new) -\c_strc_formulas_space_model\plusthree % replaces \plusone, we might use \plusfour in the future - -\newconditional\c_strc_formulas_tight - -\newbox\b_strc_formulas_number -\newbox\b_strc_formulas_content - -\def\strc_formulas_flush_content_and_number - {\noindentation - % \dontleavehmode - \kern\d_strc_formulas_display_margin_left - \ifcase\wd\b_strc_formulas_number - \hbox to \displaywidth \bgroup - \hfill - \box\b_strc_formulas_content - \hfill - \egroup - \orelse\ifdim\dimexpr\wd\b_strc_formulas_content+\wd\b_strc_formulas_number\relax>\displaywidth - \vbox \bgroup - \hsize\displaywidth - \box\b_strc_formulas_content - \par - \ifx\p_location\v!left - \box\b_strc_formulas_number\hfill - \else - \hfill\box\b_strc_formulas_number - \fi - \egroup - \else - \hbox to \displaywidth \bgroup - \ifx\p_location\v!left - \rlap{\box\b_strc_formulas_number}% - \hfill\box\b_strc_formulas_content\hfill - \else - \hfill\box\b_strc_formulas_content\hfill - \llap{\box\b_strc_formulas_number}% - \fi - \egroup - \fi} - -\installcorenamespace{mathdisplayspacemodel} - -\setvalue{\??mathdisplayspacemodel\v!before:1}% old - {\ifx\p_spacebefore\v!none - % nothing - \else - \directvspacing\p_spacebefore - \fi} - -\setvalue{\??mathdisplayspacemodel\v!after:1}% old - {\prevdepth .5\strutdp - \edef\p_spaceafter{\formulaparameter\c!spaceafter}% - \ifx\p_spaceafter\v!none - % nothing - \else - \directvspacing\p_spaceafter - \fi} - -\setvalue{\??mathdisplayspacemodel\v!before:2}% old - {\ifx\p_spacebefore\v!none - % nothing - \else - \directvspacing\p_spacebefore - \fi - \prevdepth-\maxdimen} % texbook pagina 79-80 - -\setvalue{\??mathdisplayspacemodel\v!after:2}% old - {\prevdepth\lineheight - \edef\p_spaceafter{\formulaparameter\c!spaceafter}% - \ifx\p_spaceafter\v!none - % nothing - \else - \directvspacing\p_spaceafter - \fi} - -\setvalue{\??mathdisplayspacemodel\v!before:3}% - {% not ok, try \stopformula\par\startformula vs \stopformula\startformula - \let\m_spacebefore\empty - \ifvmode - \ifdim\lastskip>\zeropoint\else - \ifdim\prevdepth<\zeropoint\else - \ifdim\prevdepth<\strutdp - % maybe add a tracing option here - \ifgridsnapping - \let\m_spacebefore\v!depth - \else - \edef\m_spacebefore{\the\dimexpr\strutdp-\prevdepth\relax}% - \fi - \fi - \fi - \fi - \nointerlineskip - \fi - \ifempty\m_spacebefore - \ifx\p_spacebefore\v!none - % nothing - \orelse\ifempty\p_spacebefore - \directvspacing\currentvspacing - \else - \directvspacing{\p_spacebefore,\the\scratchdimen}% - \fi - \else - \ifx\p_spacebefore\v!none - \directvspacing{\m_spacebefore}% - \orelse\ifempty\p_spacebefore - \directvspacing{\m_spacebefore,\currentvspacing}% - \else - \directvspacing{\m_spacebefore,\p_spacebefore}% - \fi - \fi} - -\setvalue{\??mathdisplayspacemodel\v!after:3}% - {\prevdepth\strutdp % \directvspacing\v!depth - \ifx\p_spaceafter\v!none - % nothing - \orelse\ifempty\p_spaceafter - \directvspacing\currentvspacing - \else - \directvspacing\p_spaceafter - \fi} - -\newconditional\c_math_model_four_indeed - -\setvalue{\??mathdisplayspacemodel\v!before:4}% - {% not ok, try \stopformula\par\startformula vs \stopformula\startformula - \ifvmode - \ifinner - \csname\??mathdisplayspacemodel\v!before:3\endcsname - \else - \settrue\c_math_model_four_indeed - \forcestrutdepth - \nointerlineskip - \ifx\p_spacebefore\v!none - % nothing - \orelse\ifempty\p_spacebefore - \directvspacing\currentvspacing - \else - \directvspacing{\p_spacebefore,\the\scratchdimen}% - \fi - \fi - \else - \csname\??mathdisplayspacemodel\v!before:3\endcsname - \fi} - -\setvalue{\??mathdisplayspacemodel\v!after:4}% - {\ifconditional\c_math_model_four_indeed - \setfalse\c_math_model_four_indeed - \forcestrutdepth - \else - \prevdepth\strutdp % \directvspacing\v!depth - \fi - \ifx\p_spaceafter\v!none - % nothing - \orelse\ifempty\p_spaceafter - \directvspacing\currentvspacing - \else - \directvspacing\p_spaceafter - \fi} - -\permanent\protected\def\setdisplaymathspacemodel[#1]% - {\ifcsname\??mathdisplayspacemodel\v!before:\number#1\endcsname - \c_strc_formulas_space_model#1\relax - \fi} - -% \newtoks\everybeforedisplay -% \appendtoks\page_sides_check_floats_indeed\to\everybeforedisplay - -\permanent\protected\def\beforedisplayspace - {\ifhmode - \par - \fi - \ifvmode - \edef\p_spacebefore{\formulaparameter\c!spacebefore}% - \begincsname\??mathdisplayspacemodel\v!before:\number\c_strc_formulas_space_model\endcsname - \fi - \ifhmode - \par - \fi - \page_sides_check_floats_indeed} % probably needs more - -\permanent\protected\def\afterdisplayspace - {\ifhmode - \par - \fi - \ifvmode - \edef\p_spaceafter{\formulaparameter\c!spaceafter}% - \begincsname\??mathdisplayspacemodel\v!after:\number\c_strc_formulas_space_model\endcsname - \fi - \ifhmode - \par - \fi} - -\permanent\protected\def\setdisplaydimensions - {\displayindent\dimexpr - \d_strc_formulas_display_skip_left - +\d_strc_formulas_display_margin_left - \relax - \displaywidth\d_strc_formulas_display_width - %\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 - -\protected\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 - -\setvalue{\??formulaoption\v!packed}% - {\c_strc_formulas_space_model\zerocount} - -\setvalue{\??formulaoption\v!tight}% - {\settrue\c_strc_formulas_tight} - -\setvalue{\??formulaoption\v!middle}% - {\d_strc_formulas_display_skip_left \zeropoint - \d_strc_formulas_display_skip_right\zeropoint} - -\setvalue{\??formulaoption\v!depth}% - {\c_strc_formulas_space_model\plusfour} - -\setvalue{\??formulaoption\v!line}% - {\ifgridsnapping - \setformulaparameter\c!grid{\v!math:\v!line}% - \fi} - -\setvalue{\??formulaoption\v!halfline}% - {\ifgridsnapping - \setformulaparameter\c!grid{\v!math:\v!halfline}% - \fi} - -\setvalue{\??formulaoption-\v!line}% - {\ifgridsnapping - \setformulaparameter\c!grid{\v!math:-\v!line}% - \fi} - -\setvalue{\??formulaoption-\v!halfline}% - {\ifgridsnapping - \setformulaparameter\c!grid{\v!math:-\v!halfline}% - \fi} - -% when we have 1.0.6 we wil use \mathpenaltiesmode -% -% \prebinoppenalty -100 -% \prerelpenalty -100 - -\def\strc_math_set_split - {\edef\p_split{\formulaparameter\c!split}% - \ifx\p_split\v!yes - \global\c_strc_math_vertical\plusone - \orelse\ifx\p_split\v!page - \global\c_strc_math_vertical\plustwo - \else - \global\c_strc_math_vertical\zerocount - \fi - \ifcase\c_strc_math_vertical - % \mathpenaltiesmode \zerocount - \clf_setmathpenalties\zerocount - \clf_resetmathhang - \else - % \mathpenaltiesmode \plusone - \clf_setmathpenalties\plusone - \edef\p_hang{\formulaparameter\c!hang}% - \ifx\p_hang\v!none - \global\setfalse\c_strc_math_indent - \clf_resetmathhang - \else - \global\settrue\c_strc_math_indent - \clf_setmathhang {% - method {\p_hang}% - distance \formulaparameter\c!distance - }% - \fi - \fi} - -\setupformula - [\c!split=\v!no, - \c!distance=\zeropoint, - %\c!interlinespace=1.5\lineheight, - \c!interlinespace=, - \c!hang=\v!none] - -% for the moment (when testing) we use a penalty 1 - -\protected\def\strc_math_align_here{\ifmmode\penalty\plusone\fi}% -\protected\def\strc_math_break_here{\ifmmode\hfill\break \fi}% - -\appendtoks - \let\alignhere\strc_math_align_here - \let\breakhere\strc_math_break_here -\to \everymathematics - -\protected\def\strc_formulas_start_formula_indeed[#1][#2]% setting leftskip adaption is slow ! - {\ifhmode - \par - \fi - \bgroup % HERE - \iftrialtypesetting\else - \global\advance\c_strc_formulas_n\plusone - \fi - \def\currentformula{#1}% - \strc_math_set_split - \dostarttaggedchained\t!formula\currentformula\??formula - \setfalse\c_strc_formulas_tight - \d_strc_formulas_display_skip_left \leftskip - \d_strc_formulas_display_skip_right \rightskip - \d_strc_formulas_display_width \formulaparameter\c!width\relax - \d_strc_formulas_display_margin_left \formulaparameter\c!leftmargin\relax - \d_strc_formulas_display_margin_right\formulaparameter\c!rightmargin\relax - \ifsecondargument - \doifelseassignment{#2}% this is new, so that we can also set the grid - {\setupcurrentformula[#2]% - \edef\p_option{\formulaparameter\c!option}}% - {\edef\p_option{\formulaparameter\c!option}% - \edef\p_option{\ifempty\p_option\else\p_option,\fi#2}}% - \else - \edef\p_option{\formulaparameter\c!option}% - \fi - \ifempty\p_option \else - \rawprocesscommacommand[\p_option]\strc_formulas_option - \fi - \edef\p_margin{\formulaparameter\c!margin}% - \ifempty\p_margin \else - \dosetleftskipadaption\p_margin - \d_strc_formulas_display_margin_left\leftskipadaption - \fi - \let\strc_formulas_start_formula\strc_formulas_start_formula_nested - \strc_formulas_forget_display_skips - \the\everybeforedisplayformula - \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname} - -\protected\def\strc_formulas_start_formula_nested#1% - {\bgroup - \let\strc_formulas_stop_formula\strc_formulas_stop_formula_nested - \dostarttagged\t!subformula\empty} - -\protected\def\strc_formulas_stop_formula_nested - {\dostoptagged - \egroup} - -% tagging of formulanumbers is not ok (we get two display maths blobs) - -\newcount\c_strc_formulas_n - -\ifdefined\dotagregisterformula \else \let\dotagregisterformula\gobbleoneargument \fi - -\protected\def\strc_formulas_stop_formula - {\strc_formulas_place_number % in case it hasn't happened yet - \strc_formulas_flush_number % in case we are in native mode - \dostarttagged\t!formulacontent\empty - \dotagregisterformula\c_strc_formulas_n - \csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname - \dostoptagged - \dostoptagged - \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: - -\def\strc_formulas_set_grid_snapping - {\edef\p_grid{\formulaparameter\c!grid}% - \ifempty\p_grid \else - \spac_grids_snap_value_auto\p_grid - \fi} - -\appendtoks - \ifgridsnapping - \strc_formulas_set_grid_snapping - \fi -\to \everybeforedisplayformula - -% \protected\def\switchtoformulabodyfont -% {\switchtobodyfont} - -\setuvalue{\v!formula}{\dosingleempty\strc_formulas_formula} - -\def\strc_formulas_formula[#1]#2% todo: tagged - {\begingroup - \edef\p_direct{#1}% - \ifempty\p_direct \else - \rawprocesscommalist[\p_direct]\strc_formulas_option - \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 - -\permanent\protected\def\startdisplaymath - {\ifhmode - \par - \fi - \bgroup - \informulatrue - \beforedisplayspace - \setdisplaydimensions - \ifcase\c_strc_formulas_mode - \noindent % prevents that tex injects empty line (when using native display mechanism) - \Ucheckedstartdisplaymath - \the\everydisplay % new (probably too much) - \or - \setbox\b_strc_formulas_content\hbox\bgroup - \normalUstartmath - \displaystyle - \the\everydisplay % new (probably too much) - \else - \expandafter\startinnermath - \fi - \begingroup} % less interference with upcoming a \over b - -\permanent\protected\def\stopdisplaymath - {\endgroup % less interference with upcoming a \over b - \ifcase\c_strc_formulas_mode - \Ucheckedstopdisplaymath - \or - \normalUstopmath - \egroup - \strc_formulas_flush_content_and_number - \else - \expandafter\stopinnermath - \fi - \afterdisplayspace - \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} - -\permanent\protected\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} - -\permanent\protected\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) - -\permanent\protected\def\startnamedsubformulas - {\dosingleempty\strc_formulas_start_named_sub_formulas} - -\def\strc_formulas_start_named_sub_formulas[#1]#2% - {\setformulalistentry{#2}% - \startsubformulas[#1]} - -\permanent\protected\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 - -\permanent\protected\def\startformulas{\strc_formulas_start_formulas} - -\permanent\letcsname\e!stop\v!formulas\endcsname\relax - -\protected\def\strc_formulas_nested_formula_start - {\hbox to \displaywidth \bgroup - \hsize\displaywidth - \hss - %\Ustartmath - \dostarttagged\t!formulacontent\empty - \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname} - -\protected\def\strc_formulas_nested_formula_stop - {\csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname - \dostoptagged - %\Ustopmath - \hss - \egroup - \hss} - -\normalexpanded{\tolerant\def\noexpand\strc_formulas_start_formulas[#1]#:#2\csname\e!stop\v!formulas\endcsname}% - {\startformula - \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 - \enforced\protected\def\startformula - {\advance\scratchcounter\plusone - \expandafter\gobbleuntil\csname\e!stop\v!formula\endcsname}% - \scratchcounter\zerocount - #2% preroll - \hbox to \displaywidth \bgroup - \divide\displaywidth\scratchcounter - \hss - \enforced\let\startformula\strc_formulas_nested_formula_start - \enforced\let\stopformula \strc_formulas_nested_formula_stop - #2% - \egroup - \global\setfalse\c_strc_formulas_inside_formulas - \dostoptagged - \stopformula - \the\everyresetformulas - \hangafter\minusone % added for side floats - \hangindent\zeropoint} % added for side floats - -% place - -\def\m_strc_formulas_flag_inhibit{-} -\def\m_strc_formulas_flag_force {+} - -\def\strc_formulas_check_reference#1#2% - {#1\unless\ifempty\namedformulaentry % \relax % new 29/8/2010 - \plusthree - \orelse\ifempty#2% - \zerocount - \orelse\ifx#2\m_strc_formulas_flag_force - \plusone - \orelse\ifx#2\m_strc_formulas_flag_inhibit - \plustwo - \else - \plusthree - \fi} - -\permanent\protected\def\formulanumber - {\strc_formulas_number} % for the moment - -\tolerant\protected\def\strc_formulas_number[#1]% - {\def\currentformulareference{#1}% - \strc_formulas_place_number_in_box} - -\permanent\protected\def\placeformula {\global\settrue\c_strc_formulas_inside_place} -\permanent\protected\def\placesubformula{\global\settrue\c_strc_formulas_inside_place_sub} - -\tolerant\protected\def\strc_formulas_place[#1]% - {\def\currentplaceformulareference{#1}% - \let\currentplaceformulasuffix\empty - \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{} - -\protected\def\strc_formulas_place_yes#1% - {\def\currentplaceformulasuffix{#1}% - \strc_formulas_place_nop} - -\protected\def\strc_formulas_place_nop - {\doifelsenextchar$\strc_formulas_place_pickup\strc_formulas_place_indeed} % [ref]$$ [ref]\start - -\protected\def\strc_formulas_place_indeed - {\strc_formulas_place_numbering} - -\protected\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 - -\let\currentplaceformulareference\empty -\let\currentplaceformulasuffix \empty - -\permanent\tolerant\protected\def\startplaceformula[#1]% - {\begingroup - \global\settrue\c_strc_formulas_inside_place - \ifparameter#1\or - \expandafter\strc_formulas_start_place_yes - \else - \expandafter\strc_formulas_start_place_nop - \fi[#1]} - -\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}% - \ifempty\currentplaceformulatitle\else - \normalexpanded{\setformulalistentry{\currentplaceformulatitle}}% - \fi - \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{} - -\permanent\protected\def\stopplaceformula - {\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}% - \strc_formulas_check_reference\c_strc_formulas_nested_number_mode\currentnestedformulareference - \ifcase\c_strc_formulas_nested_number_mode - % nothing - \or - \glet\strc_formulas_place_number\relax - \expandafter\strc_formulas_number % hm, looks ahead for [] - \or - % nothing - \or - \glet\strc_formulas_place_number\relax - \expandafter\strc_formulas_number % hm, looks ahead for [] - \fi} - -\def\strc_formulas_place_number_indeed - {\strc_formulas_place_number_in_box} - -\def\strc_formulas_place_number_in_box - {\dostarttagged\t!formulacaption\empty - \global\setbox\b_strc_formulas_number\naturalhbox{\strc_formulas_number_indeed}% - \dostoptagged} - -\def\strc_formulas_flush_number - {\ifcase\c_strc_formulas_mode - \ifzeropt\wd\b_strc_formulas_number - % nothing to be done - \orelse\ifx\p_location\v!left - \math_native_leqno{\box\b_strc_formulas_number}% - \else - \math_native_reqno{\box\b_strc_formulas_number}% - \fi - \fi} - -% todo - -\permanent\tolerant\protected\def\placenamedformula[#1]% - {\ifarguments - \expandafter\strc_formulase_place_named_nop - \else - \expandafter\strc_formulase_place_named_yes - \fi[#1]} - -\def\strc_formulase_place_named_yes[#1]#2% - {\setformulalistentry{#2}% - \placeformula[#1]} - -\def\strc_formulase_place_named_nop[#1]#2% - {\setformulalistentry{#2}% - \placeformula} - -\mutable\let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks - -\permanent\protected\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/tex/context/base/mkiv/strc-not.mklx b/tex/context/base/mkiv/strc-not.mklx deleted file mode 100644 index 299873830..000000000 --- a/tex/context/base/mkiv/strc-not.mklx +++ /dev/null @@ -1,1972 +0,0 @@ -%D \module -%D [ file=strc-not, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Note Handling, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Note Handling} - -\registerctxluafile{strc-not}{} - -\unprotect - -% todo: finish local rendering -% todo: more p_strc_notations_* (outside trial loop) -% todo: see if we can now use \insertpenalties (>0 == some left) - -\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi -\ifdefined\dotagsetnotation \else \let\dotagsetnotation \relax \fi - -\protected\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often -\protected\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often - -%D \LMTX\ testcase: -%D -%D \starttyping -%D \hbox {\hbox{\footnote{HH1}\footnote{HH2}}} \par -%D \hbox {\hbox{x\footnote{XHH1}x\footnote{XHH2}}} \par -%D \vbox {\setbox0\hbox{\footnote{VH1}\footnote{VH2}}\box0} \par -%D \vbox {\hbox{\footnote{VH1}xxx\footnote{VH2}}} \par -%D \vbox {\hbox{\footnote{VH1}\footnote{VH2}} -%D \hbox{\footnote{VH1}\footnote{VH2}}} \par -%D \vbox {\hbox{x\footnote{XVH1}x\footnote{XVH2}}} \par -%D \vbox {\vbox{\footnote{VV1}\footnote{VV2}}} \par % two lines -%D \vbox {\vbox{x\footnote{XVV1}x\footnote{XVV2}}} \par -%D \stoptyping - -%D Notes have two handlers: notations and notes. Although notations can be defined -%D independently it makes not much sense. In principle we can treat notes as lists -%D but they are currently done as a variant on enumerations. I will provide a list -%D variant as well. One complication is that for page related notes inserts are used -%D and therefore notes are typeset immediately and descriptions are better suited -%D for that. For instance endnotes can as well be typeset using lists. - -% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number - -%D \macros -%D {setupnote,setupnotation} -%D -%D We can influence footnote typesetting with the setup command: -%D -%D \showsetup{setupnotation} -%D \showsetup{setupnote} -%D -%D The definition command indicate that we can frame the footnote area. The -%D footnotes themselves are treated as descriptions. -%D -%D \showsetup{definenote} -%D -%D It's sort of a custom to precede footnotes by a horizontal rule and although -%D fancy rules like -%D -%D \starttyping -%D \hbox to 10em{\hskip-3em\dotfill} -%D \stoptyping -%D -%D Are quite ligitimate, we default to a simple one 20\% of the text width. - -% \c!headstyle=\noteparameter\c!style, -% \c!headcolor=\noteparameter\c!color, - -\installcorenamespace{notation} - -\installcommandhandler \??notation {notation} \??notation - -\installcounterassociation{notation} - -\aliased\let\setupnotations\setupnotation - -\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}] -\definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}] - -\setupnotations % check with old - [\c!alternative=\v!note, - %\c!headstyle=, - %\c!titlestyle=, - %\c!style=, - %\c!color=, - %\c!headcolor=, - %\c!titlecolor=, - \c!numbercommand=\high, - %\c!symbolcommand=\lowllap, % experiment - %\c!indicator=\v!no, % was \v!yes in mkii for page notes - \c!width=\v!fit, - \c!titledistance=.5em, - \c!distance=.5em, - %\c!hang=, - %\c!sample=, - %\c!align=, - %\c!headalign=, - \c!margin=\v!no, - \c!before=, - \c!inbetween=, - \c!after=, - \c!indentnext=\v!yes, - \c!indenting=\v!never, - \c!titleleft=(, - \c!titleright=), - %\c!closesymbol=, - \c!closecommand=\wordright, - \c!display=\v!yes, - %\c!command=, - \c!titlecommand=, - \c!expansion=\v!no, - %\c!xmlsetup=, - %\s!catcodes=, - \c!way=\v!by\v!text, - \c!prefix=\v!no, - \c!prefixconnector=., - %\c!starter=, - %\c!stopper=, - \c!number=\v!yes, - \c!text=, - \c!start=0, - \c!state=\v!start, - \c!levels=3] - -%D The code here is mostly the same as enumerations but we want to keep them -%D isolated and at some point we might differentiate. - -% \installcorenamespace{noteclass} - -\protected\def\strc_define_commands_notation#tag#level#parent% - {\doifelsenothing{#parent} - {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}% - \setevalue{\??notation#tag:\s!parent}{\??notation}}% - {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}% - \setevalue{\??note #tag:\s!parent}{\??note#parent}% see later for \s!note - \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}% - \instance\setuevalue{\e!next #tag}{\strc_notations_next {#tag}{\number#level}}% obsolete - \instance\setuevalue{\c!reset#tag}{\strc_notations_reset {#tag}{\number#level}}% obsolete - \instance\setuevalue {#tag}{\strc_notations_command[#tag]}% - \instance\setuevalue{\e!start#tag}{\strc_notations_start [#tag]}% - \instance\setuevalue{\e!stop #tag}{\strc_notations_stop }} - -\appendtoks - \ifempty\currentnotationparent - % 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 - \ifempty\p_counter - \let\p_counter\currentnotation - \fi - \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}% - \letnotationparameter\s!counter\p_counter - %\strc_notes_setup_counter\currentnotation -\to \everydefinenotation - -\let\p_strc_constructions_title \empty -\let\p_strc_constructions_number\empty - -\protected\setvalue{\??constructioninitializer\v!notation}% - {\let \currentnotation \currentconstruction - \enforced\let\constructionparameter \notationparameter - \enforced\let\constructionnamespace \??notation - \enforced\let\detokenizedconstructionparameter\detokenizednotationparameter - \enforced\let\letconstructionparameter \letnotationparameter - \enforced\let\useconstructionstyleandcolor \usenotationstyleandcolor - \enforced\let\setupcurrentconstruction \setupcurrentnotation - \edef\p_strc_constructions_number{\constructionparameter\c!number}% - \ifx\p_strc_constructions_number\v!yes - \settrue\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_save\currentconstructionnumber - \fi - %\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel - \else - \setfalse\c_strc_constructions_number_state - \fi - \edef\p_strc_constructions_title{\constructionparameter\c!title}% - \ifx\p_strc_constructions_title\v!yes - \settrue\c_strc_constructions_title_state - \else - \setfalse\c_strc_constructions_title_state - \fi} - -\protected\setvalue{\??constructionfinalizer\v!notation}% - {\ifconditional\c_strc_constructions_number_state - \iftrialtypesetting - \strc_counters_restore\currentconstructionnumber - \fi - \fi} - -%D Notations (we simply needed a word that relates to notes and is and sounds like -%D description and enumeration) are a special case in the sense that they are -%D stored, rendered elsewhere and referered to from where they are specified. For -%D that reason they have a different set op main commands. - -% \notation[ref]{title} -% \notation[reference=,title=] -% \startnotation[ref] title \stopnotation - -\protected\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2 -\protected\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2 -%protected\def\strc_notations_set {\strc_constructions_set_indeed \namednotationparameter} % #1#2 - -\newconditional\c_strc_notations_anchored_next - -\def\strc_notations_finalize - {\ifconditional\c_strc_notations_anchored_next - \expandafter\strc_notations_finalize_next - \else - \expandafter\strc_notations_finalize_previous - \fi} - -\def\strc_notations_finalize_previous - {\normalexpanded{\endgroup\noteparameter\c!next}} - -\def\strc_notations_finalize_next - {\endgroup\ignorespaces} - -\tolerant\protected\def\strc_notations_command[#1]#*[#2]% - {\begingroup - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% - \strc_notes_synchronize - \edef\p_next{\noteparameter\c!anchor}% - \ifx\p_next\v!next % for now only two states - \settrue \c_strc_notations_anchored_next - \else - \setfalse\c_strc_notations_anchored_next - \fi - \ifnotesenabled - \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel - \fi - \ifhastok={#2}% - \expandafter\strc_notations_command_setups - \else - \expandafter\strc_notations_command_reference - \fi[#2]} - -\def\strc_notations_command_setups[#1]% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% - \strc_notations_wrapup} - -\tolerant\def\strc_notations_command_reference[#1]#*#=% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% - \strc_notations_wrapup} - -\def\strc_notations_wrapup - {\csname\??constructionnotehandler\currentconstructionhandler\endcsname - \strc_constructions_finalize - \strc_notations_finalize} - -\tolerant\protected\def\strc_notations_start[#1]#*[#2]% - {\begingroup - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% - \strc_notes_synchronize - \ifnotesenabled - \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel - \fi - \ifhastok={#2}% - \expandafter\strc_notations_start_setups - \else - \expandafter\strc_notations_start_reference - \fi[#2]} - -\protected\def\strc_notations_start_setups[#1]% - {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_setups_indeed[#1]{##1}}}% - \strc_pickup_yes} - -\protected\def\strc_notations_start_setups_indeed[#1]#*#2% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#2},\c!bookmark=,\c!list=,#1]% - \strc_notations_wrapup} - -\protected\def\strc_notations_start_reference[#1]% - {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_reference_indeed[#1]{##1}}}% - \strc_pickup_yes} - -\protected\def\strc_notations_start_reference_indeed[#1]#*#2% - {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% - \strc_notations_wrapup} - -\protected\def\strc_notations_stop - {} - -%D A complication is that we need to set up rather specific properties of e.g. -%D footnotes. It is for this reason that we introduce an extra level of -%D indirectness. This way notations don't bark on undefined macros when used in -%D combination. - -\protected\setvalue{\??constructionnotehandler\v!notation}% - {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname} - -\protected\setvalue{\??constructionnotehandler\v!notation:}% empty case - {[\currentconstructionhandler:\currentconstruction]} - -%D Here is a simple renderer for notes - -\defineconstructionalternative - [\v!note] - [\c!renderingsetup=\??constructionrenderings:\v!note] - -\startsetups[\??constructionrenderings:\v!note] - \noindent - \leftboundary % experiment, to be done in more places - \llap{\box\constructionheadbox\hskip\constructionparameter\c!distance}% - \useconstructionstyleandcolor\c!style\c!color - \ignorespaces -\stopsetups - -%D We now implement the note definer. - -\installcorenamespace{note} - -\installframedcommandhandler \??note {note} \??note - -\let\setupnotes\setupnote - -% These only concern the inline symbol/number and wrapping of the whole list. - -\setupnotes % not all make sense here - [\c!location=\v!page, - %\c!conversion=, - \c!rule=\v!on, - \c!before=\blank, - \c!bodyfont=\v!small, - \c!anchor=, % can also be v!next - %\c!style=, - %\c!color=, - %\c!after=, - %\c!rulecolor=, - %\c!rulecommand=, - \c!rulethickness=\linewidth, - \c!frame=\v!off, - \c!distance=.125em, % in the text between symbols - % \c!textseparator={,}, % optional separator - \c!columndistance=1em, - % \c!margindistance=.5em, - \c!align=, % also use instead of \c!tolerance - \c!split=\v!tolerant, - \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi - \c!height=\textheight, - \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice - \c!separator=,% - \c!textcommand=\high, - \c!textstyle=\tx, - %\c!textcolor=, - \c!interaction=\v!yes, - %\c!factor=, - %\c!scope=, % \v!text \v!page - \c!prefixconnector=., - %\c!next=\autoinsertnextspace, - \c!prefix=\v!no, - %\c!continue=\v!no, - \c!paragraph=\v!no, - \c!inbetween=\hskip\emwidth, - \c!symbol=\mathematics{*}, - \c!n=1] - -\setupnotes - [\c!expansion=\v!no, - \c!xmlsetup=, - \s!catcodes=] - -%D Insertions are part of notes. - -% \installcorenamespace{noteinsertion} - -\permanent\def\currentnoteinsertion {\noteparameter\s!insert} -\permanent\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}} - -\appendtoks - \ifempty\currentnoteparent - \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 - -%letcsname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname -\letcsname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess -\letcsname\??constructionstophandler \v!notation\expandafter\endcsname\csname\??constructionstophandler \v!enumeration \endcsname -\letcsname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname -\letcsname\??constructiontexthandler \v!notation\expandafter\endcsname\csname\??constructiontexthandler \v!enumeration \endcsname - -\protected\setvalue{\??constructionmainhandler\v!notation}#following% - {\iftrialtypesetting \else - \begingroup - \currentconstructionsynchronize - \c_attr_destination\currentconstructionattribute\relax % todo, whole text - \signalcharacter - \endgroup - \fi#following} - -\protected\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text - {\ifnotesenabled - % do be done elsewhere - % - %let\currentnote\currentconstructionmain - \let\currentnote\currentconstruction % else wrong inheritance - % - \iftrialtypesetting - \strc_notes_inject_dummy - \else - \begingroup - \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}% - \settrue\processingnote - \ifconditional\c_strc_notes_skip - \glet\lastnotesymbol\strc_notes_inject_symbol_nop - \else - \iftypesettinglines % otherwise problems with \type {xxx} - \ignorelines % makes footnotes work in \startlines ... \stoplines - \fi - \ifconditional\c_strc_notes_symbol - \strc_notes_inject_symbol_yes - \else - \unskip\unskip - \glet\lastnotesymbol\strc_notes_inject_symbol_yes - \fi - \fi - \ifconditional\postponingnotes % todo: per note class - \global\settrue\postponednote - \orelse\ifconditional\inlocalnotes % todo: per note class - \global\settrue\postponednote - \orelse\ifconditional\c_strc_notes_delayed - % probably end notes - \else - \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed - \fi - \endgroup - \fi - \fi - \ifconditional\c_strc_notes_skip - \global\setfalse\c_strc_notes_skip - \else - \kern\d_strc_notes_signal\relax % \relax is needed to honor spaces - \fi} - -%D Interaction in notes is somewhat complex due to the way notes get flushed. In -%D principle it is more or less the same as lists but where in lists we pack whole -%D entries, in notes this doesn't happen. Okay, in retrospect we could have made -%D descriptions lists but that will be a backward compatibility mess. At some point -%D a completely new mechanism might show up, but not now. Also, as notes are inserts -%D there is some extra mess to be kept in mind and it's easier to maintain two -%D mechanisms than to combine too much. -%D -%D Interaction is also complicated because we want to provide several variants. For -%D simple reference there is no need for anything special, as page references will -%D do and we store them in the list anyway. But if we want a destination with -%D dimensions we will use an additional destination because we can have only one -%D with the same name and we always have the number as one. - -% interaction: -% -% all : text and number -% number|yes: only number -% text : only text -% -% \dogetsimple : injects - -\installcorenamespace{noteinteractioninline} -\installcorenamespace{noteinteractiondisplay} - -\newconstant\a_strc_notes_symbol_reference -\newconstant\a_strc_notes_number_reference -\newconstant\a_strc_notes_text_reference -\newconstant\a_strc_notes_text_destination - -\let\strc_notes_get_reference_attribute_symbol \empty -\let\strc_notes_get_destination_attribute_symbol\empty - -\def\strc_notes_interaction_check_inline - {\edef\p_interaction{\noteparameter\c!interaction}% - \csname\??noteinteractioninline - \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi - \endcsname} - -\def\strc_notes_interaction_check_display - {\edef\p_interaction{\noteparameter\c!interaction}% - \csname\??noteinteractiondisplay - \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi - \endcsname} - -\def\currentnotenumber{0} - -\let\strc_notes_get_reference_attribute_symbol \empty -\let\strc_notes_get_destination_attribute_symbol\empty - -\let\strc_notes_set_reference_attribute_number\donothing -\let\strc_notes_set_reference_attribute_text \donothing -\let\strc_notes_set_destination_attribute_text\donothing - -% inline - -\def\strc_references_prepare_inline_references_nop - {\let\strc_notes_get_reference_attribute_symbol\empty - \let\strc_notes_get_destination_attribute_symbol\empty - \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop} - -% \def\strc_references_prepare_inline_references_yes -% {\strc_references_set_simple_reference{symb:\currentnote:\currentnotenumber}% destination -% \strc_references_get_simple_reference{internal(\clf_noteinternal{\currentnote}\currentnotenumber)}% reference -% \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% -% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% -% \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} - -\def\strc_references_prepare_inline_references_yes - {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% - \strc_references_set_simple_reference{*\currentnoteinternal}% destination - \strc_references_get_simple_reference{internal(\currentnoteinternal)}% reference - \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% - \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% - \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} - -\letvalue{\??noteinteractioninline\v!no }\strc_references_prepare_inline_references_nop -\letvalue{\??noteinteractioninline\v!all }\strc_references_prepare_inline_references_yes -\letvalue{\??noteinteractioninline\v!number}\strc_references_prepare_inline_references_yes -\letvalue{\??noteinteractioninline\v!text }\strc_references_prepare_inline_references_yes -\letvalue{\??noteinteractioninline\v!yes }\strc_references_prepare_inline_references_yes - -% display (for 'all' we need unique text and number attributes so we resolve twice -% as we otherwise don't get the number one which is lapped in the margin so we need -% to explicitly visit it) - -\def\strc_references_prepare_display_references_nop - {\let\strc_notes_set_reference_attribute_number\donothing - \let\strc_notes_set_reference_attribute_text\donothing - \let\strc_notes_set_destination_attribute_text\donothing - \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop} - -\def\strc_references_prepare_display_references_yes_number - {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% - \ifcase\currentnoteinternal\relax - \strc_references_prepare_display_references_nop - \else - \let\strc_notes_set_reference_attribute_text\donothing - \strc_references_get_simple_reference{*\currentnoteinternal}% reference - \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% - \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes - \fi} - -\def\strc_references_prepare_display_references_yes_text - {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% - \ifcase\currentnoteinternal\relax - \strc_references_prepare_display_references_nop - \else - \strc_references_get_simple_reference{*\currentnoteinternal}% reference - \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% - \let\strc_notes_set_reference_attribute_number\donothing - \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes - \fi} - -\def\strc_references_prepare_display_references_yes_all - {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% - \ifcase\currentnoteinternal\relax - \strc_references_prepare_display_references_nop - \else - \strc_references_get_simple_reference{*\currentnoteinternal}% reference - \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% - \strc_references_get_simple_reference{*\currentnoteinternal}% reference - \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% - \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes - \fi} - -\letvalue{\??noteinteractiondisplay\v!no }\strc_references_prepare_display_references_nop -\letvalue{\??noteinteractiondisplay\v!all }\strc_references_prepare_display_references_yes_all -\letvalue{\??noteinteractiondisplay\v!number}\strc_references_prepare_display_references_yes_number -\letvalue{\??noteinteractiondisplay\v!text }\strc_references_prepare_display_references_yes_text -\letvalue{\??noteinteractiondisplay\v!yes }\strc_references_prepare_display_references_yes_number - -\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor -\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor - -\protected\def\strc_notes_set_style_color_inline_yes#style#color% - {\usenotestyleandcolor#style#color% - \iflocation\strc_notes_set_style_color_special\fi} - -\protected\def\strc_notes_set_style_color_display_yes#style#color% - {\usenotationstyleandcolor#style#color% - \iflocation\strc_notes_set_style_color_special\fi} - -\def\strc_notes_set_style_color_special - {\iftrialtypesetting - % keep - \orelse\ifempty\currentcolorparameter - \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once - \setlocationcolorspecified\scratchcounter - \fi} - -\setvalue{\??constructiontexthandler\v!notation}% - {\begingroup - % we need to retrigger the reference as otherwise it gets lost because we don't do nested - % references with the same id ... maybe some day if we can figure out a nice heuristic ... - % the problem is that normally it's no issue but here we lap into the margin, so maybe that's - % a criterium - % \strc_notes_interaction_check_display - \strc_notes_set_reference_attribute_number - \dotagsetnotation - \strc_notes_set_style_color_display\c!headstyle\c!headcolor - \strc_enumerations_text - \endgroup} - -% in mkii the pointer only showed up in pagewise notes - -\protected\def\strc_notes_inject_pointer % todo calculate once - {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax - % unknown - \or - % same page - \or - \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}% - \or - \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}% - \fi} - -\protected\def\strc_notes_inject_symbol_yes - {\strc_notes_inject_symbol_indeed\conditionaltrue} - -\protected\def\strc_notes_inject_symbol_nop - {\strc_notes_inject_symbol_indeed\conditionalfalse} - -\definemargindata - [strc_notes_destination_margin] - [\v!left] - [\c!margin=\zeropoint, - \c!width=\zeropoint, - \c!style=, - \c!color=] - -\protected\def\strc_notes_inject_symbol_indeed#synchronize% - {\ifconditional\c_strc_notations_anchored_next\else - \removeunwantedspaces - \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} - \fi - \ifdim\lastkern=\d_strc_notes_signal - % \kern\noteparameter\c!distance % yes or no note font? or main text - \strc_notes_inject_separator - \fi - \nobreak - \begingroup - \strc_notes_interaction_check_inline - \strc_notes_set_style_color_inline\c!textstyle\c!textcolor - \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup - % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack - \strc_references_flush_destination_nodes % a bit late but ok - \dostarttagged\t!descriptionsymbol\currentnote - \dotagsetnotesymbol - \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}% - % the next one can cycle so we need to make sure it has no advance width - \doif{\noteparameter\c!indicator}\v!yes\strc_notes_inject_pointer - \dostoptagged - \egroup - \endgroup - \glet\lastnotesymbol\relax} - -\protected\def\strc_notes_inject_dummy % temp hack - {\removeunwantedspaces - \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} - \ifdim\lastkern=\d_strc_notes_signal - % \kern\noteparameter\c!distance % yes or no note font? or main text - \strc_notes_inject_separator - \fi - \nobreak - \hpack to .5\emwidth{}% - \glet\lastnotesymbol\relax} - -\protected\def\strc_notes_inject_separator % patch by WS due to request on list - {\edef\p_textseparator{\noteparameter\c!textseparator}% - \ifempty\p_textseparator - \kern\noteparameter\c!distance - \else - % skip or kern - \nobreak - \hbox\bgroup - \strc_notes_interaction_check_inline - \strc_notes_set_style_color_inline\c!textstyle\c!textcolor - \noteparameter\c!textcommand{\p_textseparator}% - \kern\noteparameter\c!distance - \egroup - \nobreak - \fi} - -% this needs a further cleanup ... soon as it's a slow mechanism -% -% -- set breakpoint in descriptions -% -- reset after trialtypesetting -% -- that way we can trick the symbol space - -% removed: -% -% \pushsomestates -% -% core-ins -> obsolete -% -% saveinsertiondata -% restoreinsertiondata -% saveinsertionbox -% eraseinsertionbackup -% restoreinsertionbackup - -\def\savenotedata {} % \writestatus{todo}{save note data}} -\def\restorenotedata {} % \writestatus{todo}{restore note data}} -\def\savenotecontent {} % \writestatus{todo}{save note content}} -\def\restorenotecontent{} % \writestatus{todo}{restore note content}} -\def\erasenotebackup {} % \writestatus{todo}{erase note backup}} - -% page-set: - -\def\enablenotes {\writestatus{todo}{enable notes}} -\def\disablenotes {\writestatus{todo}{disable notes}} -\def\savenotes {\writestatus{todo}{save notes}} -\def\flushsavednotes{\writestatus{todo}{flush notes}} - -% experiment: (compare scope=text and scope=page) -% -% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0] -% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] - -%D Footnotes are can be characterized by three components: -%D -%D \startitemize[packed] -%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes -%D [conversion=set 2]\footnote {a footnote}} -%D \item and a similar mark at the bottom of the page -%D \item followed by some additional text -%D \stopitemize -%D -%D Because footnotes are declared at the location of their reference they can be -%D seen as a special kind of floating bodies. Their placement is postponed but has -%D to be taken into account in the pagebreak calculations. This kind of calculations -%D are forced by using \type{\insert}s and dealing with all cases is not trivial. - -%D \macros -%D {notesenabled} -%D -%D We need a couple of states because at some moments we don't want to mess around -%D with inserts at all. Take for instance a table of contents. And so we can -%D temporary disable footnotes by saying -%D -%D \starttyping -%D \notesenabledfalse -%D \stoptyping - -\newif\ifnotesenabled \notesenabledtrue - -% better mark a note .. once flushed no more flushing - -%appendtoks \notesenabledfalse \to \everymarking -\appendtoks \notesenabledfalse \to \everybeforepagebody -\appendtoks \notesenabledfalse \to \everystructurelist % quick hack -\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack -\appendtoks \notesenabledfalse \to \everypreroll % quick hack - -%D Often we need to process the whole set of notes and to make that fast, we use a -%D token register: - -% we have several synchronizers: -% -% - after a definition -% - after a specific setup -% - after a general setup (inheritance of dimensions) -% - just before a note is typeset - -\newtoks\t_strc_notes - -\let\strc_notes_process_list\gobbleoneargument - -\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote - {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}% - \the\t_strc_notes} - -\newtoks\everychecknote % just before a note is typeset -\newtoks\everysynchronizenote % after a general setup has happened - -\appendtoks - \ifempty\currentnote \else - \setupnotations[\currentnote][]% also a synchronize - \fi -\to \everysynchronizenote - -\def\strc_notes_synchronize - {\the\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist - -\appendtoks - \strc_notes_process\strc_notes_synchronize -\to \everysetupnoteroot - -\appendtoks - \the\everysynchronizenote -\to \everydefinenote - -% \starttext -% text \startfootnote Test.\stopfootnote -% test \footnote{xxxx} \subfootnote{xxxx} -% test \footnote{xxxx} \subfootnote{xxxx} -% \stoptext - -\installcorenamespace{notecommand} -\installcorenamespace{notealign} -\installcorenamespace{notepenalty} -\installcorenamespace{noterule} - -\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname} -\permanent\protected\def\currentnoterulealign {\begincsname\??notealign \currentnote\endcsname} - -\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand} -\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards - -\permanent\protected\def\letcurrentnoterulecommand{\enforced\letcsname\??notecommand\currentnote\endcsname} -\permanent\protected\def\letcurrentnoterulealign {\enforced\letcsname\??notealign \currentnote\endcsname} - -\appendtoks - \enforced\letcsname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal - \enforced\letcsname\??notealign \currentnote\endcsname\lefttoright -\to \everysynchronizenote - -\def\strc_notes_set_rule - {\letcurrentnoterulecommand\relax % so we default to nothing - \letcurrentnoterulealign \relax - \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step} - -\def\strc_notes_set_rule_step#alternative% - {\begincsname\??noterule#alternative\endcsname} - -\def\strc_notes_set_rule_autodir - {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright} - -\setvalue{\??noterule \v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand} -\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal} -\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal} -\setvalue{\??noterule \v!left}{\letcurrentnoterulecommand\currentnoterulecommandnormal - \letcurrentnoterulealign \lefttoright} -\setvalue{\??noterule \v!right}{\letcurrentnoterulecommand\currentnoterulecommandnormal - \letcurrentnoterulealign \righttoleft} -\setvalue{\??noterule\v!paragraph}{\letcurrentnoterulecommand\currentnoterulecommandnormal - \letcurrentnoterulealign \strc_notes_set_rule_autodir} -\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax} - -\appendtoks - \strc_notes_set_rule -\to \everysynchronizenote - -\permanent\def\currentnotepenalty - {\ifcsname\??notepenalty\noteparameter\c!split\endcsname - \lastnamedcs - \else - \numexpr\noteparameter\c!split\relax - \fi} - -\setnewconstant\notepenaltytolerant \zerocount -\setnewconstant\notepenaltystrict 9999 -\setnewconstant\notepenaltyverystrict\maxdimen - -\letvalue{\??notepenalty\v!tolerant }\notepenaltytolerant -\letvalue{\??notepenalty\v!strict }\notepenaltystrict -\letvalue{\??notepenalty\v!verystrict}\notepenaltyverystrict -\letvalue{\??notepenalty }\notepenaltytolerant - -%D The following switch can be used to disable limiting the height of the footnote -%D area, something that is needed in multi column balancing. Use this switch with -%D care. - -\newif\ifnotelimit \notelimittrue % shared - -\def\strc_notes_set_factor - {\edef\p_factor{\noteparameter\c!factor}% - \ifempty\p_factor \else - \ifnum\p_factor<\zerocount \else -% \global - \count\currentnoteinsertionnumber\p_factor % new: global - \fi - \fi} - -\appendtoks - \strc_notes_set_factor -\to \everysynchronizenote - -% locations: - -\installcorenamespace{notelocationvariant} -\installcorenamespace{notepositionvariant} -\installcorenamespace{notedelayedvariant} -\installcorenamespace{notelocation} - -\newconditional\c_strc_notes_delayed - -\protected\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed} -\protected\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed} - -\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page} -\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns} -\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn} -\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn} -\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none} -\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes - \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text} -\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high} -\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom} - -\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let -\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let -\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let - -\protected\def\strc_notes_set_delayed - {\csname\??notedelayedvariant - \ifcsname\??notedelayedvariant\currentnote\endcsname - \currentnote - \else - \??notedelayedvariant - \fi - \endcsname} - -\protected\def\strc_notes_set_position - {\csname\??notepositionvariant - \ifcsname\??notepositionvariant\currentnote\endcsname - \currentnote - \else - \??notepositionvariant - \fi - \endcsname} - -\protected\def\strc_notes_set_location - {\csname\??notelocationvariant - \ifcsname\??notelocationvariant\currentnote\endcsname - \currentnote - \else - \??notelocationvariant - \fi - \endcsname} - -\protected\def\strc_notes_set_variants - {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}} - -\protected\def\strc_notes_set_location_step#alternative% the insert related one - {\begincsname\??notelocation#alternative\endcsname} - -\appendtoks - \strc_notes_set_variants - \strc_notes_set_delayed -\to \everysynchronizenote - -\newskip \s_strc_notes_distance % we need to implement stretch -\newcount\c_strc_notes_columns - -\newskip \s_strc_notes_before -\newskip \s_strc_notes_inbetween -\newconditional\c_strc_notes_first_flushed - -\appendtoks - \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}% - \ifempty\p_spacebefore - \global\s_strc_notes_before\zeropoint - \else - \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}% - \fi - \edef\p_spaceinbetween{\rootnoteparameter\c!spaceinbetween}% - \ifempty\p_spaceinbetween - \global\s_strc_notes_inbetween\zeropoint - \else - \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}% - \fi -\to \everysynchronizenote - -\def\strc_notes_set_distance - {\begingroup - \restoreglobalbodyfont - \setbox\scratchbox\vbox % no reuse as it can mirror - {\forgetall - \dontcomplain - \noteparameter\c!before - \placenoterule - \strut - \noteparameter\c!after}% - % also dp now - \scratchdimen\dimexpr\htdp\scratchbox-\lineheight\relax - \ifgridsnapping - \getnoflines\scratchdimen - \scratchdimen\noflines\lineheight - \fi - \expandafter\endgroup\expandafter - \s_strc_notes_distance\the\scratchdimen\relax} - -\def\strc_notes_set_columns - {\c_strc_notes_columns\noteparameter\c!n\relax - \ifcase\c_strc_notes_columns - \c_strc_notes_columns\plusone - \fi} - -\def\strc_notes_set_location_page - {\setfalse\c_strc_notes_delayed - \strc_notes_set_distance - \strc_notes_set_columns - \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]% - \global\count\currentnoteinsertionnumber\numexpr(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns\relax - \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi - \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} - -\def\strc_notes_set_location_columns - {\setfalse\c_strc_notes_delayed - \strc_notes_set_distance - \strc_notes_set_columns - \ifnum\currentnofcolumns=\zerocount - \c_strc_notes_columns\plusone - \fi - \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]% - \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax - \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi - \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} - -\def\strc_notes_set_location_somecolumn#whatcolumn% - {\setfalse\c_strc_notes_delayed - \strc_notes_set_distance - \strc_notes_set_columns - \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]% - \global\count\currentnoteinsertionnumber\plusthousand - \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi - \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} - -\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn} -\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn } - -\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes) - {\settrue\c_strc_notes_delayed - \clf_setnotestate{\currentnote}{store}% - \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]% - \global\count\currentnoteinsertionnumber\zerocount - \global\dimen\currentnoteinsertionnumber\maxdimen - \global\skip \currentnoteinsertionnumber\zeropoint} - -\let\strc_notes_set_location_none\strc_notes_set_location_text - -\def\strc_notes_set_properties - {\strc_notes_set_columns - \strc_notes_set_distance - \strc_notes_set_location - \strc_notes_set_delayed} - -\let\strc_notes_set_position_high\relax - -\def\strc_notes_set_position_bottom - {\settrue\c_notes_bottom_present} - -\appendtoks - \strc_notes_set_properties -\to \everysynchronizenote - -%D A fast checker for bottom notes being used: - -\newconditional\c_notes_bottom_present - -\def\strc_notes_check_if_bottom_present_indeed % in otr ! - {\ifvoid\currentnoteinsertionnumber\else - \strc_notes_set_position - \fi} - -\def\strc_notes_check_if_bottom_present_step - {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi} - -\def\strc_notes_check_if_bottom_present - {\setfalse\c_notes_bottom_present - \strc_notes_process\strc_notes_check_if_bottom_present_step} - -% Example of using factor: -% -% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0] -% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle] -% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] -% \starttext -% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} } -% \stoptext - -%D The noterule can be a graphic and therefore calling this setup macro at every -%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that -%D probably match those of the stretch component. A bit messy: - -\permanent\protected\def\placenoterule - {\begingroup - \currentnoterulealign - \currentnoterulecommand - \par - \endgroup} - -\permanent\protected\def\normalnoterule - {\ifvmode - \dontleavehmode \blackrule - [\c!color=\noteparameter\c!rulecolor, - \c!width=.2\hsize, - \c!height=\noteparameter\c!rulethickness, - \c!depth=\zeropoint]% - \endgraf - \kern\strutdepth - \fi} - -%D The formatting depends on the width of the table, so we have to set \type {n} to -%D zero. -%D -%D \starttyping -%D \startbuffer -%D \bTABLE -%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR -%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR -%D \eTABLE -%D \stopbuffer -%D -%D \startlocalfootnotes[n=0,location={text,none}] -%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes} -%D \stoplocalfootnotes -%D \stoptyping - -%D \macros -%D {footnote} -%D -%D A footnote can have a reference as optional argument and therefore its formal -%D specification looks like: -%D -%D \showsetup{footnote} -%D -%D This command has one optional command: the reference. By saying \type{[-]} the -%D number is omitted. The footnote command is not that sensitive to spacing, so it's -%D quite legal to say: -%D -%D \startbuffer -%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the -%D ground and not get confused \footnote {Or even crazy.} by all those obscure -%D \footnote {But fortunately readable.} parameters. -%D \stopbuffer -%D -%D \typebuffer -%D -%D When setting the \type{conversion} to \type{set 2} we get -%D something like: -%D -%D \bgroup -%D \startnarrower -%D \setupfootnotes[conversion=set 1] -%D \getbuffer -%D \stopnarrower -%D \egroup -%D -%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes. -%D The additional macro \type {\footnotetext} and the associated \type {\note} macro -%D were implemented at request of users on the mailing list and a suggestion by taco -%D to split of the symbol placement. I decided to merge this functionality with the -%D existing \type {\note} functionality. - -\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used -\newconditional\c_strc_notes_skip - -\permanent\protected\def\setnote [#tag]{\csname#tag\endcsname} -\permanent\protected\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname} - -\permanent\protected\def\handlenoteinsert#tag#id% - {\begingroup - \edef\currentnote{#tag}% - \strc_constructions_initialize{#tag}% - \strc_notes_synchronize - \the\everybeforenoteinsert - \insert\currentnoteinsertionnumber\bgroup - \the\everyinsidenoteinsert\relax - \usesetupsparameter\noteparameter % experimental - \useinterlinespaceparameter\noteparameter - \doifelse{\noteparameter\c!paragraph}\v!yes - {\nointerlineskip - \startvboxtohboxseparator - \noteparameter\c!inbetween - \stopvboxtohboxseparator - \startvboxtohbox - \handlenoteitself{#tag}{#id}% - \stopvboxtohbox} - {\handlenoteitself{#tag}{#id}}% - \egroup - \the\everyafternoteinsert - \endgroup} - -\permanent\protected\def\betweennoteitself#tag% used ? - {\edef\currentnote{#tag}% - \doif{\noteparameter\c!paragraph}\v!yes{\noteparameter\c!inbetween}} - -\permanent\protected\def\handlenoteitself#tag#id% - {\edef\currentnotenumber{#id}% - \edef\currentnote{#tag}% - \strc_constructions_initialize{#tag}% - \strc_notes_synchronize - \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache - % as we can have collected notes (e.g. in tables) we need to recover - % \currentdescriptionattribute and \currentdescriptionsynchronize - % - \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table) - % - \dontcomplain - %begingroup - \strc_notes_interaction_check_display - \strc_notes_set_reference_attribute_text - \strc_constructions_stored_start - \begstrut - \strc_references_flush_destination_nodes - \strc_notes_set_destination_attribute_text - \strc_notes_inject_text\relax - \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10 - \strc_constructions_stored_stop - %endgroup - } - -\protected\def\strc_notes_inject_text % hm main? - {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax} - -\let\startpushnote\relax -\let\stoppushnote \relax - -\newsignal\d_strc_notes_signal - -\newconditional\processingnote -\newconditional\postponednote - -\newtoks\everybeforenoteinsert -\newtoks\everyinsidenoteinsert -\newtoks\everyafternoteinsert - -\permanent\protected\def\doifelseinnote - {\ifconditional\processingnote - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\appendtoks - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax - \forgetall - \resetallattributes % new, we don't want color bleed into notes - \inheritmaintextcolor % but we do want to obey the textcolor -\to \everybeforenoteinsert - -\def\strc_notes_set_penalties - {% stored in insert node - \floatingpenalty \currentnotepenalty - % used when typesetting - \interlinepenalty\plushundred % plain value - % used when we need to split in columns - \ifnum\noteparameter\c!n>\plusone - \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated) - \fi} - -\appendtoks - \strc_notes_set_penalties - \forgetall % again - \strc_notes_set_bodyfont - \redoconvertfont % to undo \undo calls in in headings etc - \splittopskip\strutht % not actually needed here - \splitmaxdepth\strutdp % not actually needed here - % - % not: - % - % \leftmargindistance \noteparameter\c!margindistance - % \rightmargindistance\leftmargindistance - % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? - % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? - % \fi - % - \pickupattributes -\to \everyinsidenoteinsert - -%D Nasty, the might be more: - -\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert -\appendtoks \strc_itemgroups_pop \to \everyafternoteinsert - -% maybe but better use [scope=local] here -% -% \appendtoks -% \setfalse\inhibitmargindata -% \to \everyinsidenoteinsert - -\setupnotes - [\c!width=\v!auto] - -\permanent\protected\def\setnotehsize - {\ifinsidemulticolumns - \setnoteparameter\c!width{\makeupwidth}% - \else - \edef\p_width{\noteparameter\c!width}% - \ifx\p_width\v!auto - % \ifinsidecolumns - \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}% - % \else - % \setnoteparameter\c!width{\makeupwidth}% - % \fi - \orelse\ifempty\p_width - \setnoteparameter\c!width{\hsize}% - \fi - \fi - \hsize\noteparameter\c!width\relax} - -\appendtoks - % only needed when columns (could be three \set...) - \setnotehsize - \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% -\to \everyinsidenoteinsert - -%D Normally footnotes are saved as inserts that are called upon as soon as the -%D pagebody is constructed. The footnote insertion routine looks just like the -%D \PLAIN\ \TEX\ one, except that we check for the end note state. - -% testcase for split bottom alignment see (a) below -% -% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}} - -\newconditional\c_strc_notes_first_placed - -\permanent\protected\def\placenoteinserts - {\setfalse\c_strc_notes_first_placed - \strc_notes_process\strc_notes_place_inserts} - -\def\strc_notes_place_inserts - {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed - \ifconditional\c_strc_notes_delayed \else - \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test - \strc_notes_place_inserts_indeed - \settrue\c_strc_notes_first_placed - \fi - \fi} - -\def\strc_notes_place_inserts_indeed - {\relax - \ifdim\ht\currentnoteinsertionnumber>\zeropoint - \endgraf - \ifvmode - \whitespace - \ifconditional\c_strc_notes_first_placed - \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}% - \ifempty\p_spaceinbetween\else - \blank[\p_spaceinbetween]% - \fi - \else - \edef\p_spacebefore{\noteparameter\c!spacebefore}% - \ifempty\p_spacebefore\else - \blank[\p_spacebefore]% - \fi - \fi - \noteparameter\c!before - \fi - \placenoterule - \bgroup - \strc_notes_set_bodyfont - \setbox\scratchbox\hbox - {\strc_notes_flush_inserts}% - \page_postprocessors_linenumbers_deepbox\scratchbox - \setbox\scratchbox\hbox - {\setupcurrentnote - [\c!location=, - \c!width=\v!fit, - \c!height=\v!fit, - \c!strut=\v!no, - \c!offset=\v!overlay]% - \inheritednoteframed - {\ifzeropt\dp\scratchbox % this hack is needed because \vadjust - \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement - \else % hides the (always) present depth - \box\scratchbox - \fi}}% - \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}% - \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth - \ifvmode - \nointerlineskip % else sometimes empty line - \fi - \box\scratchbox - \egroup - \endgraf - \ifvmode - \noteparameter\c!after - \fi - \fi} - -\def\strc_notes_flush_inserts - {\ifcase\noteparameter\c!n\relax - % should not happen - \or - \strc_notes_flush_inserts_normal - \else - \strc_notes_flush_inserts_columns - \fi} - -\def\strc_notes_flush_inserts_normal - {\strc_notes_flush_global - \obeydepth} % (a) added , since split footnotes will not align properly - -\def\strc_notes_flush_inserts_columns - {\begingroup - \setnotehsize % probably still not ok for columns - \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% - \strc_notes_flush_global - \stopsimplecolumns - \endgroup} - -% idea: tag with attr and then just flush them again - -\def\strc_notes_flush_global - {\begingroup - \useinterlinespaceparameter\noteparameter - \doifelse{\noteparameter\c!paragraph}\v!yes - {\leftorrightvbox % cf mail from ws to list - {\starthboxestohbox - \iftrialtypesetting\unvcopy\else\unvbox\fi\currentnoteinsertionnumber - \stophboxestohbox}} - {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}% - \endgroup} - -%D Supporting end notes is surprisingly easy. Even better, we can combine this -%D feature with solving the common \TEX\ problem of disappearing inserts when -%D they're called for in deeply nested boxes. The general case looks like: -%D -%D \starttyping -%D \postponenotes -%D \.box{whatever we want with footnotes} -%D \flushnotes -%D \stoptyping -%D -%D This alternative can be used in headings, captions, tables etc. The latter one -%D sometimes calls for notes local to the table, which can be realized by saying -%D -%D \starttyping -%D \setlocalfootnotes -%D some kind of table with local footnotes -%D \placelocalfootnotes -%D \stoptyping -%D -%D Postponing is accomplished by simply redefining the (local) insert operation. A -%D not too robust method uses the \type{\insert} primitive when possible. This -%D method fails in situations where it's not entirely clear in what mode \TEX\ is. -%D Therefore the auto method can is to be overruled when needed. - -\newconditional\postponingnotes - -% we need a proper state: normal, postponing, flushing - -\permanent\protected\def\postponenotes % will be locally overloaded - {\ifcase\insertionmigrationmode - \ifconditional\postponingnotes\else - \global\settrue\postponingnotes - \enforced\glet\flushnotes\doflushnotes - \clf_postponenotes - \fi - \fi} - -\let\flushnotes\relax - -% also \ifcase\insertionmigrationmode here, needs testing: - -\permanent\protected\def\startpostponingnotes % experimental, page-mix - {\ifconditional\postponingnotes\else - \global\settrue\postponingnotes - %\glet\flushnotes\doflushnotes - \clf_postponenotes - \fi} - -\permanent\protected\def\stoppostponingnotes % experimental, page-mix - {\doflushnotes} - -\permanent\protected\def\doflushnotes - {\ifconditional\postponingnotes - \begingroup - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax - \ifconditional\postponednote - \ifhmode - % needed for tagging ... otherwise we get some weird node free error - \signalcharacter - \fi - \fi - \clf_flushpostponednotes% this also resets the states ! - \global\setfalse\postponednote - \global\setfalse\postponingnotes - \enforced\glet\flushnotes\relax - \endgroup - \fi} - -%D \macros -%D {startlocalfootnotes,placelocalfootnotes} -%D -%D The next two macros can be used in for instance tables, as we'll demonstrate -%D later on. -%D -%D \showsetup{startlocalfootnotes} -%D \showsetup{placelocalfootnotes} - -% todo: compatibility mode: when first arg is assignment or missing, then all - -\newtoks\everyplacelocalnotes - -\appendtoks - \enforced\let\flushnotes \relax - \enforced\let\postponenotes\relax -\to \everyplacelocalnotes - -\newconditional\inlocalnotes - -\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings) - {\def\localnoteslist{#list}% - \settrue\inlocalnotes - \processcommacommand[\localnoteslist]\strc_notes_local_start_step} - -\permanent\protected\def\stoplocalnotes - {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step - \setfalse\inlocalnotes} - -\let\p_strc_notes_continue\empty - -\def\strc_notes_local_start_step#tag% - {\p_strc_notes_continue{\noteparameter\c!continue}% - \ifx\p_strc_notes_continue\v!yes \else - \strc_counters_save{#tag}% - \strc_counters_reset{#tag}% - \fi - \clf_savenote{#tag}{store}} - -\def\strc_notes_local_stop_step#tag% - {\p_strc_notes_continue{\noteparameter\c!continue}% - \ifx\p_strc_notes_continue\v!yes \else - \strc_counters_restore{#tag}% - \fi - \clf_restorenote{#tag}} - -\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#settings]% - {\doif{\clf_getnotestate{#tag}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}} - -\def\strc_notes_local_place_indeed#settings#tag% - {\begingroup - \edef\currentnote{#tag}% is already set? - \the\everyplacelocalnotes - % beware, we cannot trust setting \currentnote here - \setupcurrentnote[#settings]% later we set height etc for framed - \strc_notes_place_local_alternative - \strc_notes_set_properties % restore globals (if needed) - \endgroup - }% TODO: just restore properties \the\everychecknote} % we need to restore the old state - -%D These commands can be used like: -%D -%D \startbuffer -%D \startlocalnotes[footnote] -%D \placetable -%D {Some Table} -%D \placeontopofeachother -%D {\starttable[|l|r|] -%D \HL -%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR -%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR -%D \HL -%D \stoptable} -%D {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]% -%D \placelocalnotes[footnote]} -%D \stoplocalnotes -%D \stopbuffer -%D -%D \typebuffer -%D -%D Because this table placement macro expect box content, and thanks to the grouping -%D of the local footnotes, we don't need additional braces. -%D -%D \getbuffer - -%D \macros -%D {placefootnotes} -%D -%D We still have no decent command for placing footnotes somewhere else than at the -%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can -%D be placed by using -%D -%D \showsetup{placefootnotes} - -\permanent\protected\def\placebottomnotes - {\strc_notes_process\strc_notes_place_inserts} - -\permanent\tolerant\protected\def\placenotes[#list]#spacer[#settings]% - {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}} - -\def\strc_notes_place_indeed#settings#tag% settings note - {\edef\currentnote{#tag}% grouping ? - \doifelse{\clf_getnotestate{#tag}}{store} - \strc_notes_local_place_indeed - \strc_notes_global_place_indeed - {#settings}{#tag}} - -\def\strc_notes_global_place_indeed#settings#tag% - {\begingroup - \setupnote[#tag][#settings]% - \strc_notes_place_inserts - \endgroup - \the\everysetupnote} % to be checked .. synchronize - -%D Placement - -\installcorenamespace{notealternative} - -\permanent\protected\def\installnotealternative#alternative#command% - {\setvalue{\??notealternative#alternative}{#command}} - -\permanent\protected\def\doifnotescollected#tag% - {\clf_doifnotecontent{#tag}} - -\def\strc_notes_place_local_alternative % will be a setup (wrapper) - {\doifnotescollected\currentnote - {\endgraf - \ifvmode - \whitespace - \noteparameter\c!before - \fi - \begingroup - \strc_notes_set_bodyfont - \csname\??notealternative\noteparameter\c!alternative\endcsname - \endgroup - \ifvmode - \noteparameter\c!after - \fi}} - -%D A stupid alternative is also provided: -%D -%D \starttyping -%D \setupfootnotes[location=text,alternative=none] -%D \stoptyping - -% setups ? - -\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}} - -\installnotealternative \v!none - {\flushlocalnotes\currentnote} - -\installnotealternative \empty - {\flushlocalnotes\currentnote} - -\installnotealternative \v!grid % test if n > 0 - {\begingroup - \setupcurrentnote[\c!location=]% - \snaptogrid\hbox - {\inheritednoteframed - {\flushlocalnotes\currentnote}}% - \endgroup} - -\installnotealternative \v!fixed % test if n > 0 - {\begingroup - \setupcurrentnote[\c!location=]% - \inheritednoteframed - {\flushlocalnotes\currentnote}% - \endgroup} - -\installnotealternative \v!columns % redundant - {\begingroup - \setupcurrentnote[\c!location=]% - \inheritednoteframed - {\edef\currentnotewidth{\noteparameter\c!width}% - \doifelsedimension\currentnotewidth\donothing - {\edef\currentnotewidth{\the\hsize}}% - \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]% - \flushlocalnotes\currentnote - \stopsimplecolumns}% - \endgroup} - -% 0:page 1:firstcolumn 2:lastcolumn - -\newconstant\c_strc_notes_page_location - -\protected\def\strc_notes_check_locations - {\edef\p_strc_notes_location{\rootnoteparameter\c!location}% - \c_strc_notes_page_location - \ifx\p_strc_notes_location\v!firstcolumn\plusone \else - \ifx\p_strc_notes_location\v!lastcolumn \plustwo \else - \zerocount\fi\fi} - -\appendtoks - \strc_notes_check_locations -\to \everysynchronizenote - -% still semi public (but will change) - -\newif\ifnotespresent - -\permanent\protected\def\checknotepresence - {\notespresentfalse - \strc_notes_process\strc_notes_check_presence} - -\def\strc_notes_check_presence - {\ifdim\ht\currentnoteinsertionnumber>\zeropoint - \notespresenttrue - \fi} - -%D \macros -%D {fakenotes} - - % used in page-mul - - \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi - - \protected\def\fakenotes - {\ifhmode\endgraf\fi\ifvmode - \calculatetotalclevernoteheight - \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi - \fi} - - \protected\def\fakepagenotes - {\ifhmode\endgraf\fi\ifvmode - \calculatetotalpagenoteheight - \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi - \fi} - - % used in page-not but not yet ok - - \newdimen\totalnoteheight - - \protected\def\additionaltotalnoteheight#insert% temp hacks anyway - {\dimexpr - \ifdim\ht#insert>\zeropoint - \ifcase\count#insert % - \zeropoint - \else % todo: divide by count - \ht#insert+\skip#insert% hm, no stretch but a dimen anyway - \fi - \else - \zeropoint - \fi - \relax} - - \def\docalculatetotalnoteheight - {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! ! - \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% - \fi} - - \def\docalculatetotalclevernoteheight - {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! ! - \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% - \fi} - - \def\docalculatetotalpagenoteheight - {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}} - - \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight} - \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight} - \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight} - -%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing -%D footnotes? The solution turned out to be rather simple: -%D -%D \starttyping -%D \everypar {...\flushnotes...} -%D \neverypar {...\postponenotes} -%D \stoptyping -%D -%D We can use \type {\neverypar} because in most commands sensitive to footnote -%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact, -%D this footnote implementation is the first to use this scheme. - -%D This is a nasty and new secondary footnote flusher. It can be hooked into \type -%D {\everypar} like: -%D -%D \starttyping -%D \appendtoks \synchronizenotes \to \everypar -%D \stoptyping - -\let\synchronizenotes\relax - -%D When typesetting footnotes, we have to return to the footnote specific bodyfont -%D size, which is in most cases derived from the global document bodyfont size. In -%D the previous macros we already used a footnote specific font setting macro. - -\def\strc_notes_set_bodyfont - {\let\strc_notes_set_bodyfont\relax - \restoreglobalbodyfont - \usebodyfontparameter\noteparameter - \usealignparameter\noteparameter} - -%D The footnote mechanism defaults to a traditional one column way of showing them. -%D By default we precede them by a small line. - -% end notes in the margin: -% -% \setuptexttexts -% [margin] -% [] [{\directsetup{notabene}}] -% -% \startsetups notabene -% \vbox to \textheight \bgroup -% \setupalign[tolerant] -% \topskipcorrection -% \placenotes[endnote][before=,after=] -% \vfilll -% \egroup -% \stopsetups - -\definenote [\v!footnote] -\definenote [\v!endnote ] [\c!location=\v!none] % else no break - -%D Compatibility macros: - -\permanent\protected\def\setupfootnotedefinition{\setupnotation [\v!footnote]} -\permanent\protected\def\setupfootnotes {\setupnote [\v!footnote]} -\permanent \def\footnotetext {\setnotetext [\v!footnote]} -\permanent\protected\def\placefootnotes {\strc_notes_place_footnotes [\v!footnote]} -\permanent\protected\def\placelocalfootnotes {\strc_notes_place_local_footnotes[\v!footnote]} -\permanent\protected\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote -\permanent\protected\def\stoplocalfootnotes {\stoplocalnotes } - -\tolerant\def\strc_notes_place_footnotes[#list]#spacer[#settings]% - {\ifarguments\or - \placenotes[#list][\c!height=\textheight]% - \or - \placenotes[#list][#settings,\c!height=\textheight]% - \fi} - -\tolerant\def\strc_notes_place_local_footnotes[#list]#spacer[#settings]% - {\ifarguments\or - \placelocalnotes[#list][\c!height=\textheight]% - \or - \placelocalnotes[#list][#settings,\c!height=\textheight]% - \fi} - -%D Goodies: -%D -%D \starttyping -%D \dorecurse {100} { -%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}} -%D } -%D \stoptyping - -\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}} - -\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage - -%D New trickery: - -%D \macros -%D {note} -%D -%D Refering to a note is accomplished by the rather short command: -%D -%D \showsetup{note} -%D -%D This command is implemented rather straightforward as: - -\installcorenamespace{notesymbol} - -\let\lastnotesymbol\relax % todo: per class - -\permanent\tolerant\protected\def\notesymbol[#tag]#spacer[#reference]% - {\ifnotesenabled - \dontleavehmode - \begingroup - \edef\currentnote{#tag}% - \usenotestyleandcolor\c!textstyle\c!textcolor - \iftok{#reference}\emptytoks - \noteparameter\c!textcommand\lastnotesymbol % check if command double - \else - \unskip - \noteparameter\c!textcommand{\in[#reference]}% command here? - \fi - \endgroup - \fi} - -\permanent\tolerant\protected\def\note[#tag]#spacer[#reference]% - {\iftok{#reference}\emptytoks - \notesymbol[\v!footnote][#tag]% - \else - \notesymbol[#tag][#reference]% - \fi} - -% will be redone if needed -% -% \def\ownnotesymbol#1% #1 gets number passed -% {\executeifdefined{\??notesymbol\currentnote}\empty} -% -% \protected\def\setnotesymbol[#1]#2#3% -% {\prewordbreak % prevent lookback -% \setgvalue{\??notesymbol#1}{#3} -% \strc_notes_inject_symbol} -% -% \protected\def\ownnote[#1]#2#3#4% -% {\setnotesymbol[#1]{#2}{#3}% -% \setnotetext [#1]{#4}} -% -% \defineconversion -% [ownnote] -% [\ownnotesymbol] - -% tricky: -% -% \enabletrackers[nodes.areas] -% \enabletrackers[nodes.references] -% \enabletrackers[nodes.destinations] -% -% \setupnotes[interaction=all,rule=no] -% \setupinteraction[state=start,focus=standard] -% -% \starttext -% \goto{\input tufte\relax}[page(2)] \par -% \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par -% \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par -% % \completecontent -% % \chapter{Chapter} -% % \dorecurse{5}{\input knuth} -% a\footnote{\input tufte\par\input ward\relax} -% \stoptext - -%D Bonus: - -\appendtoks - \setsystemmode\currentnote -\to \everysynchronizenote - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-num.mkxl b/tex/context/base/mkiv/strc-num.mkxl deleted file mode 100644 index 1ddbd511d..000000000 --- a/tex/context/base/mkiv/strc-num.mkxl +++ /dev/null @@ -1,687 +0,0 @@ -%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}{} - -\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 - -\aliased\let\setupcounters \setupcounter -\aliased\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] - -\permanent\def\autostructureprefixsegments#1% todo: \c!prefixsegments=\v!auto - {2:\thenamedheadlevel{\clf_way{#1\c!way}}} - -\appendtoks - \resetcounterparameter\s!counter -\to \everypresetcounter - -\appendtoks - \ifempty\currentcounterparent - \edef\p_start{\counterparameter\c!start}% - \clf_definecounter - name {\currentcounter}% - start \ifempty\p_start\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 - \ifempty\currentcounter \else - \edef\p_number{\counterparameter\c!number}% - \ifempty\p_number \else - \clf_setcounter{\counterparameter\s!name}\numexpr\p_number\relax - \letcounterparameter\c!number\empty - \fi - \edef\p_start{\counterparameter\c!start}% - \setexpandedcounterparameter\c!start{\ifempty\p_start0\else\number\p_start\fi}% - \strc_counters_check_setup - \fi -\to \everysetupcounter - -% % % % - -\permanent\def\strc_counters_way #1{\clf_way{\namedcounterparameter{#1}\c!way}} -\permanent\def\thenamedcounterlevel#1{\xthenamedheadlevel{\clf_way{\namedcounterparameter{#1}\c!way}}} - -\protected\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\ifempty\p_start\zerocount\else\p_start\fi\relax % bug in scanner - {\counterparameter\c!state}% - \fi} - -\permanent\protected\def\doifelsecounter #1{\clf_doifelsecounter{\namedcounterparameter{#1}\s!name}} -\permanent\protected\def\doifcounter #1{\clf_doifcounter {\namedcounterparameter{#1}\s!name}} -\permanent\protected\def\doifnotcounter #1{\clf_doifnotcounter {\namedcounterparameter{#1}\s!name}} - -\aliased\let\doifcounterelse\doifelsecounter - -\permanent\tolerant\protected\def\setcounter[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \else - \clf_setsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax - \fi} - -\permanent\tolerant\protected\def\setcounterown[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}\or - \else - \clf_setownsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}% - \fi} - -\permanent\tolerant\protected\def\restartcounter[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \else - \clf_restartsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax - \fi} - -\permanent\tolerant\protected\def\resetcounter[#1]#*[#2]% - {\ifarguments\or - \clf_resetcounter {\namedcounterparameter{#1}\s!name}\or - \else - \clf_resetsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax - \fi} - -\permanent\tolerant\protected\def\incrementcounter[#1]#*[#2]% - {\ifarguments\or - \strc_counters_increment_sub{#1}\plusone\or - \else - \strc_counters_increment_sub{#1}{#2}% - \fi} - -\permanent\tolerant\protected\def\decrementcounter[#1]#*[#2]% - {\ifarguments\or - \clf_decrementcounter {\namedcounterparameter{#1}\s!name}\or - \else - \clf_decrementsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax - \fi} - -\permanent\tolerant\protected\def\rawcounter[#1]#*[#2]% - {\ifarguments\or\or - \clf_countervalue {\namedcounterparameter{#1}\s!name}% - \else - \clf_subcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\lastcounter[#1]#*[#2]% - {\ifarguments\or\or - \clf_lastcountervalue {\namedcounterparameter{#1}\s!name}% - \else - \clf_lastsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\firstcounter[#1]#*[#2]% - {\ifarguments\or\or - \clf_firstcountervalue {\namedcounterparameter{#1}\s!name}% - \else - \clf_firstsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\prevcounter[#1]#*[#2]% - {\ifarguments\or\or - \clf_previouscountervalue {\namedcounterparameter{#1}\s!name}%} - \else - \clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\nextcounter[#1]#*[#2]% - {\ifarguments\or\or - \clf_nextcountervalue {\namedcounterparameter{#1}\s!name}% - \else - \clf_nextsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\countersubs[#1]#*[#2]% - {\ifarguments\or\or - \clf_subcountervalues {\namedcounterparameter{#1}\s!name}% - \else - \clf_subsubcountervalues{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or - \fi} - -\permanent\tolerant\protected\def\savecounter[#1]% - {\ifarguments\or - \clf_savecounter{\namedcounterparameter{#1}\s!name}% - \fi} - -\permanent\tolerant\protected\def\restorecounter[#1]% - {\ifarguments\or - \clf_restorecounter{\namedcounterparameter{#1}\s!name}% - \fi} - -\protected\def\strc_counters_set #1#2{\clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\protected\def\strc_counters_setown #1#2{\clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}} -\protected\def\strc_counters_restart #1#2{\clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\protected\def\strc_counters_reset #1{\clf_resetcounter {\namedcounterparameter{#1}\s!name}} -\protected\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}} - -\protected\def\strc_counters_set_sub #1#2#3{\clf_setsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax} -\protected\def\strc_counters_setown_sub #1#2#3{\clf_setownsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}} -\protected\def\strc_counters_restart_sub #1#2#3{\clf_restartsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax} -\protected\def\strc_counters_reset_sub #1#2{\clf_resetsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\protected\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} - -\protected\def\strc_counters_save #1{\clf_savecounter {\namedcounterparameter{#1}\s!name}} -\protected\def\strc_counters_restore #1{\clf_restorecounter {\namedcounterparameter{#1}\s!name}} - -\protected\def\strc_counters_incremented #1{\clf_incrementedcounter {\namedcounterparameter{#1}\s!name}} -\protected\def\strc_counters_decremented #1{\clf_decrementedcounter {\namedcounterparameter{#1}\s!name}} - -\protected\def\showcounter [#1]{\clf_showcounter {\namedcounterparameter{#1}\s!name}} -\protected\def\incrementedcounter[#1]{\clf_incrementedcounter{\namedcounterparameter{#1}\s!name}} % no \dosingleargument -\protected\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 - -\permanent\def\rawcountervalue [#1]{\clf_countervalue {\namedcounterparameter{#1}\s!name}} -\permanent\def\lastcountervalue [#1]{\clf_lastcountervalue {\namedcounterparameter{#1}\s!name}} -\permanent\def\firstcountervalue[#1]{\clf_firstcountervalue {\namedcounterparameter{#1}\s!name}} -\permanent\def\nextcountervalue [#1]{\clf_nextcountervalue {\namedcounterparameter{#1}\s!name}} -\permanent\def\prevcountervalue [#1]{\clf_previouscountervalue{\namedcounterparameter{#1}\s!name}} - -\permanent\def\rawsubcountervalue [#1]#*[#2]{\clf_subcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\permanent\def\lastsubcountervalue [#1]#*[#2]{\clf_lastsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\permanent\def\firstsubcountervalue[#1]#*[#2]{\clf_firstsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\permanent\def\nextsubcountervalue [#1]#*[#2]{\clf_nextsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} -\permanent\def\prevsubcountervalue [#1]#*[#2]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\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. - -\protected\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} - -\protected\def\strc_counters_increment#1% - {\strc_counters_increment_sub{#1}\plusone} - -% so far for the hack - -\permanent\tolerant\protected\def\convertedcounter[#1]#*[#2]% - {\begingroup - \edef\currentcounter{#1}% - \ifparameter#2\or\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} - -\permanent\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} - -\permanent\tolerant\protected\def\convertedsubcounter[#1]#*[#2]#*[#3]% #2 can be n or n:m - {\ifarguments\or - \convertedcounter[#1][]% - \else - \convertedcounter[#1][\c!numbersegments=#2,#3]% - \fi} - -\permanent\protected\def\doifdefinedcounter {\doifcommandhandler \??counter} -\permanent\protected\def\doifundefinedcounter {\doifnotcommandhandler \??counter} -\permanent\protected\def\doifelsedefinedcounter{\doifelsecommandhandler\??counter} - -\aliased\let\doifdefinedcounterelse\doifelsedefinedcounter - -%D What follows is a compatibility layer. Do we need this? - -\aliased\let \numberparameter \namedcounterparameter % {name}\c!key - -\aliased\let \definenumber \definecounter % [name] -\aliased\let \setupnumber \setupcounter % [name][setups] - -\aliased\let \setnumber \setcounter % [name]{value} -\aliased\let \resetnumber \resetcounter % [name] -\aliased\let \savenumber \savecounter % [name] -\aliased\let \restorenumber \restorecounter % [name] -\aliased\let \incrementnumber \incrementcounter % [name] -\aliased\let \decrementnumber \decrementcounter % [name] -\aliased\let \rawnumber \rawcounter % [name] -\aliased\let \getnumber \convertedcounter % [name] -\aliased\let \convertednumber \convertedcounter % [name] - -\aliased\let \doifdefinednumber \doifdefinedcounter % {number}{true} -\aliased\let \doifundefinednumber \doifnotdefinedcounter % {number}{true} -\aliased\let \doifelsedefinednumber \doifelsedefinedcounter % {number}{true}{false} -\aliased\let \doifdefinednumberelse \doifelsedefinedcounter % {number}{true}{false} - -\aliased\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_ - -\protected\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}% - \ifempty\currentname - \edef\currentname{#1}% - \fi - \edef\currentcounter{#3\s!counter}% - \ifempty\currentcounter - \let\currentcounter\currentname - \fi - % - \ifx\p_hascaption\v!yes - \strc_counters_register_component_list{#1}{#3}{#4}{#9}% - \orelse\ifempty\currentstructurecomponentreference - \strc_counters_register_component_none - \else - \strc_counters_register_component_page{#3}% - \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 - {\ifempty\currentstructurecomponentreferenceprefix - \let\currentstructurecomponentreferenceprefix\currentstructurereferenceprefix - \fi - \ifempty\currentstructurecomponentreferenceprefix - \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 \locationcount - % 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 - \ifempty\currentstructurecomponentlist - \glet\currentstructurecomponentlist\currentstructurecomponenttitle - \fi - \glet\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 \ifempty\currentstructurecomponentbookmark - \begingroup - \simplifycommands - \xdef\currentstructurecomponentbookmark{\detokenize\expandafter{\normalexpanded{#2\c!title}}}% - \endgroup - \fi \fi - \fi - \ifempty\currentstructurecomponentlist - \glet\currentstructurecomponentlist\currentstructurecomponenttitle - \fi - \glet\currentstructurecomponentcoding\s!tex - \fi - % - \setnextinternalreference - \scratchcounter\clf_addtolist %{ - metadata { - kind {#1} - name {\currentname} - % level structures.sections.currentlevel() - catcodes \ifempty\currentstructurecomponentcatcodes\catcodetable\else\csname\currentstructurecomponentcatcodes\endcsname\fi - coding {\currentstructurecomponentcoding} - \ifx\currentstructurecomponentcoding\s!xml - xmlroot {\xmldocument} - \fi - \ifempty\currentstructurecomponentxmlsetup \else - xmlsetup {\currentstructurexmlsetup} - \fi - } - references { - internal \locationcount - % 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}% - \setstructurecomponentsynchronization\m_strc_counters_last_registered_index - \glet\m_strc_counters_last_registered_attribute \currentstructurecomponentattribute - \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize} - -\let\m_strc_counters_last_registered_index \relax -\let\m_strc_counters_last_registered_attribute \relax -\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). - -\protected\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]} - -\protected\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} - -\protected\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% - \permanent\protected\def #6{\ifx#2\empty\the#5\else\strc_counter_setup_using_parameter#2#4\fi}% sync - \permanent\protected\def#7##1{\normalexpanded{#5{\the#5\strc_counter_setup_using_parameter{##1}\noexpand#4}}}} % register - -\permanent\protected\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: -% -% \protected\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} -% -% \protected\def\strc_counter_setup_pop -% {\let\counterparameter \savedcounterparameter -% \let\directcounterparameter \saveddirectcounterparameter -% \let\setexpandedcounterparameter \savedsetexpandedcounterparameter} -% -% \protected\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% -% \protected\def#6% sync -% {\strc_counter_setup_push -% \ifx#2\empty -% \the#5% -% \else -% \let\currentcounter\empty -% \the\everysetupcounter -% \fi -% \strc_counter_setup_pop}% -% \protected\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 -% \ifempty\currentcounter \else -% \edef\p_number{\counterparameter\c!number}% -% \ifempty\p_number \else -% \strc_counters_set\currentcounter\p_number -% \letcounterparameter\c!number\empty -% \fi -% \fi -% \to \everysetupcounter - -\stopcontextdefinitioncode - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-pag.mkxl b/tex/context/base/mkiv/strc-pag.mkxl deleted file mode 100644 index 07ac30d26..000000000 --- a/tex/context/base/mkiv/strc-pag.mkxl +++ /dev/null @@ -1,497 +0,0 @@ -%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}{} - -\unprotect - -\startcontextdefinitioncode - -% Allocation: - -\ifdefined\realpageno \else \permanent\countdef\realpageno \zerocount \fi \realpageno \plusone -\ifdefined\userpageno \else \permanent\countdef\userpageno \plusone \fi \userpageno \plusone -\ifdefined\subpageno \else \permanent\countdef\subpageno \plustwo \fi \subpageno \plusone % was \zerocount but that doesn't work well with bytext -\ifdefined\arrangeno \else \permanent\countdef\arrangeno \plusthree \fi \arrangeno \zerocount % ! -\ifdefined\pagenoshift \else \permanent\countdef\pagenoshift\plusfour \fi \pagenoshift\zerocount % ! -\ifdefined\lastpageno \else \permanent\countdef\lastpageno \plusfive \fi \lastpageno \zerocount % ! - -\ifdefined\pageno \else \aliased\let\pageno\userpageno \fi - -\def\realfolio{\the\realpageno} -\def\userfolio{\the\userpageno} -\def\subfolio {\the\subpageno } -\def\lastfolio{\the\lastpageno} - -\newtoks\everyinitializepagecounters - -\protected\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 - -\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}} - -\permanent\tolerant\protected\def\setuprealpagenumber[#1]{\strc_pagenumbers_save_state\s!realpage\setupcounter[\s!realpage][#1]\the\everysetuprealpagenumber} -\permanent\tolerant\protected\def\setupuserpagenumber[#1]{\strc_pagenumbers_save_state\s!userpage\setupcounter[\s!userpage][#1]\the\everysetupuserpagenumber} -\permanent\tolerant\protected\def\setupsubpagenumber [#1]{\strc_pagenumbers_save_state\s!subpage \setupcounter[\s!subpage ][#1]\the\everysetupsubpagenumber } - -\permanent\protected\def\resetrealpagenumber {} % not permitted -\permanent\protected\def\resetuserpagenumber {\strc_counters_reset\s!userpage} -\permanent\protected\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 - -\aliased\let\setuppagenumber\setupuserpagenumber -\aliased\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 - -\protected\def\strc_pagenumbers_page_state_push{\setxvalue{\??pagestatestack\c!state}{\namedcounterparameter\s!userpage\c!state}} -\protected\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!start] % was stop but start looks better in logging - -% Counters - -%permanent\def\firstrealpagenumber{\convertedcounter[\s!realpage][\c!type=\v!first]} -%permanent\def\firstuserpagenumber{\convertedcounter[\s!userpage][\c!type=\v!first]} -%permanent\def\firstsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!first]} - -%permanent\def\lastrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!last]} -%permanent\def\lastuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!last]} -%permanent\def\lastsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!last]} - -%permanent\def\prevrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!previous]} -%permanent\def\prevuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!previous]} -%permanent\def\prevsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!previous]} - -%permanent\def\nextrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!next]} -%permanent\def\nextuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!next]} -%permanent\def\nextsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!next]} - -\permanent\def\firstrealpage{\strc_counters_first\s!realpage} -\permanent\def\firstuserpage{\strc_counters_first\s!userpage} -\permanent\def\firstsubpage {\strc_counters_first\s!subpage } - -\permanent\def\prevrealpage {\strc_counters_prev \s!realpage} -\permanent\def\prevuserpage {\strc_counters_prev \s!userpage} -\permanent\def\prevsubpage {\strc_counters_prev \s!subpage } - -\permanent\def\nextrealpage {\strc_counters_next \s!realpage} -\permanent\def\nextuserpage {\strc_counters_next \s!userpage} -\permanent\def\nextsubpage {\strc_counters_next \s!subpage } - -\permanent\def\lastrealpage {\strc_counters_last \s!realpage} -\permanent\def\lastuserpage {\strc_counters_last \s!userpage} -\permanent\def\lastsubpage {\strc_counters_last \s!subpage } - -\aliased\let\firstpage\firstrealpage -\aliased\let\prevpage \prevrealpage -\aliased\let\nextpage \nextrealpage -\aliased\let\lastpage \lastrealpage - -% Compatibility counters: - -\permanent\def\nofrealpages {\lastrealpage} \permanent\def\totalnumberofpages{\lastrealpage} -\permanent\def\nofuserpages {\lastuserpage} \permanent\def\lastpagenumber {\lastuserpage} -\permanent\def\nofsubpages {\lastsubpage } - -% Renderers: - -\permanent\def\pagenumber {\strc_counters_raw\s!userpage} -\permanent\def\prefixedpagenumber {\directconvertedcounter\s!userpage\empty} % \userpagenumber - -\permanent\def\realpagenumber {\directconvertedcounter\s!realpage\empty} -\permanent\def\userpagenumber {\directconvertedcounter\s!userpage\empty} -\permanent\def\subpagenumber {\directconvertedcounter\s!subpage \empty} - -\permanent\def\firstrealpagenumber{\directconvertedcounter\s!realpage\v!first} -\permanent\def\firstuserpagenumber{\directconvertedcounter\s!userpage\v!first} -\permanent\def\firstsubpagenumber {\directconvertedcounter\s!subpage \v!first} - -\permanent\def\lastrealpagenumber {\directconvertedcounter\s!realpage\v!last} -\permanent\def\lastuserpagenumber {\directconvertedcounter\s!userpage\v!last} -\permanent\def\lastsubpagenumber {\directconvertedcounter\s!subpage \v!last} - -\permanent\def\prevrealpagenumber {\directconvertedcounter\s!realpage\v!previous} -\permanent\def\prevuserpagenumber {\directconvertedcounter\s!userpage\v!previous} -\permanent\def\prevsubpagenumber {\directconvertedcounter\s!subpage \v!previous} - -\permanent\def\nextrealpagenumber {\directconvertedcounter\s!realpage\v!next} -\permanent\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next} -\permanent\def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next} - -\protected\def\strc_pagenumbers_decrement_counters % only at the end - {\strc_counters_decrement\s!realpage - \strc_counters_decrement\s!userpage - \strc_counters_decrement\s!subpage} - -\protected\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 - -\permanent\def\realpage{\the\realpageno} -\permanent\def\userpage{\the\userpageno} -\permanent\def\subpage {\the\subpageno} - -% Hooks: - -\permanent\def\currentpage{\the\realpageno}% rather useless - -\appendtoks - \ifnum\realpageno>\lastpage \enforced\glet\lastpage\lastrealpage \fi -\to \everyinitializepagecounters - -% States: - -\newconditional\layoutisdoublesided % already defined: \newif\ifdoublesided -\newconditional\layoutissinglesided % already defined: \newif\ifsinglesided - -% Realpage and subpage numbers: - -\permanent\protected\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax} -\permanent\protected\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax} - -% Page numbers: (can move to lua) ... inconsistent names - -\installcorenamespace{pagenumberinc} -\installcorenamespace{pagenumberdec} - -\protected\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax} -\protected\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax} - -\permanent\protected\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax} -\permanent\protected\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax} - -\protected\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible - -\permanent\protected\def\decrementpagenumber{\csname\??pagenumberdec\namedcounterparameter\s!userpage\c!state\endcsname} -\permanent\protected\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} - -% some day ifsinglesided and ifdoublesided will become obsolete - -\newtoks\everysidedswitch - -\appendtoks - \singlesidedfalse \setfalse\layoutisdoublesided - \doublesidedfalse \setfalse\layoutissinglesided - \resetsystemmode\v!singlesided - \resetsystemmode\v!doublesided - \processallactionsinset - [\directpagenumberingparameter\c!alternative]% - [ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided, - \v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]% - \the\everysidedswitch - \pageduplexmode - \ifsinglesided - \ifdoublesided\plustwo\else\zerocount\fi - \else - \ifdoublesided\plusone\else\zerocount\fi - \fi - \page_backgrounds_recalculate - \strc_pagenumbers_set_location -\to \everysetuppagenumbering - -\appendtoks - \ifdefined\trackingmarginnotestrue - \ifdoublesided - \trackingmarginnotestrue - \else - \trackingmarginnotesfalse - \fi - \fi -\to \everysidedswitch - -\ifdefined \page_backgrounds_recalculate \else - \let\page_backgrounds_recalculate\relax -\fi - -\ifdefined \strc_pagenumbers_set_location \else - \let\strc_pagenumbers_set_location\relax -\fi - -\protected\def\strc_pagenumbers_flush_final_page - {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}% - \ifempty\p_strc_pagenumbers_page \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: - -\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\placepagenumber - {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo - \ifnum\c_strc_pagenumbers_state=\plusone - \labeltexts\v!pagenumber\pagenumber - \fi - \fi} - -\permanent\protected\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 - -\protected\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 - #2\ifx\m_strc_pagenumbers_state_new\v!start\plustwo\else\zerocount\fi - \fi} - -\appendtoks % todo: set state: none, start, stop, reset - \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage -\to \everysetuprealpagenumber - -\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}% - \ifempty\askeduserpagenumber \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}% - \ifempty\askedsubpagenumber \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 - -\protected\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/tex/context/base/mkiv/strc-ref.mklx b/tex/context/base/mkiv/strc-ref.mklx deleted file mode 100644 index 2f3475e50..000000000 --- a/tex/context/base/mkiv/strc-ref.mklx +++ /dev/null @@ -1,2196 +0,0 @@ -%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}{} -\registerctxluafile{strc-ref}{} -\registerctxluafile{node-ref}{optimize} - -\unprotect - -% 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 the core -%D features, although at a first glance probably nobody will notice. This is good, -%D because referencing should be as hidden as possible. -%D -%D Before we start implementing functionality we provide a way to set up this -%D mechanism. -%D -%D \showsetup{setupreferencing} -%D -%D In interactive documents verbose references don't always make sense (what is a -%D page number in an unnumbered document). By setting the \type{interaction} -%D variable, one can influences the way interactive references are set. - -\let\referenceprefix\empty - -\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 - -\permanent\protected\def\showreferences{\enabletrackers[nodes.references.show,nodes.destinations.show]} - -%D These are implemented in a low level form as: - -\permanent\tolerant\protected\def\textreference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}} -\permanent\tolerant\protected\def\pagereference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}} -\permanent\tolerant\protected\def\reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}} -\permanent\tolerant\protected\def\setreference [#labels]#spacer[#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}} - -\permanent\protected\def\dosetdirectpagereference#1{\strc_references_set_named_reference\s!page{#1}{}{}} % low level, maybe use _ - -\permanent\protected\def\usereferenceparameter#1% faster local variant - {\edef\m_strc_references_asked{#1\c!reference}% - \ifempty\m_strc_references_asked\else - \dosetdirectpagereference\m_strc_references_asked - \fi} - -%D Actually there is not much difference between a text and a full reference, but -%D it's the concept that counts. The low level implementation is: - -\newcount\lastreferenceattribute -\newcount\lastdestinationattribute - -\def\strc_references_finish#prefix#reference#internal% gets expanded anyway - {\normalexpanded{\clf_deferredenhancereference{#prefix}{#reference}}} - -\permanent\let\dofinishreference\strc_references_finish % used at lua end - -%D This is somewhat tricky: we want to keep the reference with the following word but -%D that word should also hyphenate. We need to find a better way. - -% 0 = nothing -% 1 = bind to following word - -\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} - - -\protected\def\strc_references_set_named_reference - {\ifreferencing - \expandafter\strc_references_set_named_reference_indeed - \else - \expandafter\gobblefourarguments - \fi} - -\newbox\b_strc_destination_nodes - -\protected\def\strc_references_flush_destination_nodes - {\ifvoid\b_strc_destination_nodes \else - \unhbox\b_strc_destination_nodes - \fi} - -\def\strc_references_placeholder - {\ifempty\dotaggedplaceholder\else - \c_attr_destination\lastdestinationattribute - \dotaggedplaceholder - \fi} - -\protected\def\strc_references_destination_point_yes - {\strc_references_inject_before % new - \dostarttagged\t!reference\empty - \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup - \strc_references_flush_destination_nodes - \strc_references_placeholder - \egroup - \dostoptagged - \strc_references_inject_after} - -\protected\def\strc_references_destination_point_nop - {\strc_references_inject_before % new - \dostarttagged\t!reference\empty - \dontleavehmode\hbox \bgroup - \strc_references_flush_destination_nodes - \strc_references_placeholder - \egroup - \dostoptagged - \strc_references_inject_after} - -\protected\def\strc_references_start_destination_nodes % messy but we need the delay - {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute - -\protected\def\strc_references_stop_destination_nodes - {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}} - -\protected\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} - \ifempty\currentreferencelabels - \lastdestinationattribute\attributeunsetvalue - \else - \ifx\currentreferenceexpansion\s!xml - \xmlstartraw - \xdef\currentreferencedata{#text}% data, no text else conflict - \xmlstopraw - \glet\currentreferencecoding\s!xml - \else - \ifx\currentreferenceexpansion\v!yes - \xdef\currentreferencedata{#text}% - \else - \xdef\currentreferencedata{\detokenize{#text}}% - \fi - \glet\currentreferencecoding\s!tex - \fi - % beware, the structures.references.set writes a - \setnextinternalreference - \strc_references_start_destination_nodes - \clf_setdestinationattribute - {% - references {% - internal \locationcount - % block {\currentsectionblock}% - view {\interactionparameter\c!focus}% - \ifempty\referenceprefix\else - prefix {\referenceprefix}% - \fi - reference {\currentreferencelabels}% - }% - metadata {% - kind {\currentreferencekind}% - \ifx\currentreferencekind\s!page\else - \ifx\currentreferencecoding\s!xml - xmlroot {\xmldocument}% - \fi - catcodes \catcodetable - \fi - }% - \ifempty\currentreferencedata\else - entries {% - text {\currentreferencedata}% - }% - \fi - \ifempty\currentreferenceuserdata\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_destination_point_yes - \orelse\ifvoid\b_strc_destination_nodes\else - \strc_references_destination_point_nop - \fi} - -\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable - {\ifreferencing - \edef\currentreferencelabels{#labels}% - \ifempty\currentreferencelabels - \setbox\b_strc_destination_nodes\emptyhbox - \lastdestinationattribute\attributeunsetvalue - \else - \strc_references_start_destination_nodes - \setnextinternalreference - \clf_setdestinationattribute - {% - references {% - internal \locationcount - % block {\currentsectionblock}% - view {\interactionparameter\c!focus}% - \ifempty\referenceprefix\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} - -\protected\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 \locationcount - % block {\currentsectionblock}% - view {\interactionparameter\c!focus}% - \ifempty\referenceprefix\else - prefix {\referenceprefix}% - \fi - reference {#labels}% - }% - metadata {% - kind {\s!full}% - }% - \ifempty\m_strc_references_text \else - entries {% - text {\m_strc_references_text}% - }% - \fi - \ifempty\m_strc_references_user \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_destination_point_yes - \orelse\ifvoid\b_strc_destination_nodes\else - \strc_references_destination_point_nop - \fi} - -\protected\def\strc_references_direct_full - {\strc_references_direct_full_user\empty} - -\permanent\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. - -\permanent\protected\def\boxreference[#1]% - {\begingroup - \dowithnextbox - {\strc_references_set_page_only_destination_attribute{#1}% - \hpack % \hbox - \ifnum\lastdestinationattribute=\attributeunsetvalue\else attr \destinationattribute \lastdestinationattribute \fi - {\box\b_strc_destination_nodes\box\nextbox}% - \endgroup}} - -\permanent\protected\def\hboxreference[#1]{\boxreference[#1]\hbox} -\permanent\protected\def\vboxreference[#1]{\boxreference[#1]\vbox} - -% \ifx\currentdestinationattribute\empty -% \begingroup\c_attr_destination\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}% - \ifempty\referenceprefix\else - prefix {\referenceprefix}% - \fi - reference {#label}% - internal \locationcount - }% - 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 \locationcount - }% - 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 - -\permanent\tolerant\protected\def\contentreference[#1]#*[#2]% - {\ifarguments - \expandafter\gobbletwoarguments - \or - \expandafter\strc_references_content_pickup_nop - \else - \expandafter\strc_references_content_pickup_yes - \fi{#1}{#2}} - -\def\strc_references_content_pickup_yes#1#2% - {\hbox\bgroup\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox} - -\def\strc_references_content_pickup_nop#1#2% - {\hbox\bgroup\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\hpack - {\framed[\c!frame=\v!off,#2]{\box\nextbox}}% - \strc_references_set_simple_reference{#1}% - \setbox\nextbox\hpack attr \destinationattribute \currentdestinationattribute % \hpack ? - {\strc_references_flush_destination_nodes - \box\nextbox}% - \setbox\nextbox\hpack{\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}% - \hpack attr \destinationattribute \currentdestinationattribute % \hpack ? - {\strc_references_flush_destination_nodes - \box\nextbox}% - \egroup} - -%D \macros -%D {everyreference} -%D -%D For rather tricky purposes, one can assign sanitizing macros to \type -%D {\everyreference} (no longer that relevant). - -\newevery \everyreference \relax - -%D This is really needed, since for instance Polish has a different alphabet and -%D needs accented entries in registers. - -\appendtoks - \cleanupfeatures -\to \everyreference - -%D We did not yet discuss prefixing. Especially in interactive documents, it's not -%D always easy to keep track of duplicate references. The prefix mechanism, which we -%D will describe later on, solves this problem. By (automatically) adding a prefix -%D one keeps references local, but the global ones in view. To enable this feature, -%D we explictly split the prefix from the reference. - -\let\referenceprefix\empty - -%D For a long time the only way to access an external file was to use the file -%D prefix (\type {somefile::}. However, when you split up a document, redefining the -%D references may be such a pain, that another approach is feasible. By setting the -%D \type {autofile} variable to \type {yes} or \type {page}, you can access the -%D reference directly. -%D -%D \starttabulate[||||] -%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR -%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 - -\permanent\protected\def\usereferences[#filename]{} % obsolete - -%D As mentioned we will also use the cross reference mechanism for navigational -%D purposes. The main reason for this is that we want to treat both categories -%D alike: -%D -%D \starttyping -%D \goto{go back}[PreviousJump] -%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 from a file. The pure -%D navigational ones don't need to be written to file, but both for fast processing -%D and transparant integration, they are saved internally as a sort of reference. We -%D can easily distinguish such system references from real cross reference ones by -%D their tag. -%D -%D We also use the odd/even characteristic to determine the 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) or pagenumbers -%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In -%D interactive documents we also have \type {\goto}, \type {\button} and alike. -%D These are more versatile and look like: -%D -%D \starttyping -%D \goto[reference] -%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 are references to a -%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT. -%D The last example shows that we can pass arguments to the actions. -%D -%D Now we've come to the testing step. As we can see below, this macro does bit more -%D than testing: it also resolves the reference. This means that whenever we test -%D for the existance of a reference at an outer level, we have all the relevant -%D properties of that reference avaliable inside the true branche~(\type {#2}). -%D -%D The prefix has to do with localizing references. When a prefix is set, looking -%D for a reference comes to looking for the prefixed one, and when not found, -%D looking for the non prefixed one. Consider for instance the prefix set to \type -%D {sidetrack}. -%D -%D \starttyping -%D \pagereference[important] -%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 the pagenumber -%D associated to this reference. But when we call for \type{important}, while the -%D prefix is still set, we will get the pagenumber bound to the prefixed one. -%D -%D {\em Some day, when processing time and memory are no longer -%D performance factors, we will introduce multi||level -%D prefixes.} -%D -%D Before we start analyzing, I introduce a general 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 true. - -\permanent\tolerant\protected\def\definereference[#name]#spacer[#specification]% - {\clf_definereference{\referenceprefix}{#name}{\detokenize{#specification}}} - -\permanent\protected\def\resetreference[#name]% - {\clf_resetreference{\referenceprefix}{#name}} - -\permanent\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 we only provide the -%D hooks. - -%D \macros -%D {highlighthyperlinks} -%D -%D The next switch can be used to make user hyperlinks are not highlighted when -%D clicked on. - -\newconditional\highlighthyperlinks \settrue\highlighthyperlinks - -%D \macros -%D {gotonewwindow} -%D -%D To make the {\em goto previous jump} feature more convenient when using more than -%D one file, it makes sense to force the viewer to open a new window for each file -%D opened. - -\newconditional\gotonewwindow \setfalse\gotonewwindow - -\permanent\def\expandtexincurrentreference % will happen in lua some time - {\ifcase\referencehastexstate\else\clf_expandcurrentreference\fi} - -\permanent\def\expandreferenceoperation#tag#content{\clf_setreferenceoperation#tag{#content}} -\permanent\def\expandreferencearguments#tag#content{\clf_setreferencearguments#tag{#content}} - -\permanent\def\doifelsereferencefound#label#yes#nop% - {\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% - {\expandtexincurrentreference - #yes}% - {#nop}} - -\aliased\let\doifreferencefoundelse\doifelsereferencefound - -%D The tester only splits the reference in components but does not look into them. -%D The following macro does a preroll and determines for instance the current real -%D reference pagenumber. The \type {\currentrealreference} macro does the same so -%D unless one wants to use the pagestate the next macro seldom needs to be called. -%D -%D The inner case is simple. Only two cases have to be taken -%D care of: -%D -%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 tolerant, depending on -%D 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 file and, when -%D enabled, in the left margin of the text. - -\let\unknownreference\gobbleoneargument - -%D When a reference is not found, we typeset a placeholder (two glyphs are often -%D enough to represent the reference text). - -\def\dummyreference{{\tttf ??}} -\def\emptyreference{{\tttf !!}} - -\installtextracker - {structures.referencing.show} - {\let\strc_references_dummy\strc_references_dummy_yes} - {\let\strc_references_dummy\strc_references_dummy_nop} - -\def\strc_references_dummy_nop - {\dummyreference} - -\def\strc_references_dummy_yes - {\dummyreference - \margindata - [\referencingparameter\c!labelalternative]% alternative? - [\c!style=\referencingparameter\c!labelstyle, - \c!color=\referencingparameter\c!labelcolor] - {\askedreference}} - -\let\strc_references_dummy\strc_references_dummy_nop - -\setupreferencing - [\c!labelalternative=\v!inleft, - \c!labelcolor=darkred, - \c!labelstyle=\smallinfofont] - -%D To prevent repetitive messages concerning a reference being defined, we set such -%D an unknown reference to an empty one after the first encounter. -%D -%D Apart from cross references supplied by the user, \CONTEXT\ generates cross -%D references itself. Most of them are not saved as a reference, but stored with -%D their source, for instance a list or an index entry. Such automatically -%D generated, for the user invisible, references are called {\em internal -%D references}. The user supplied ones are labeled as {\em external references}. -%D -%D A second important characteristic is that when we want to support different -%D backends (viewers), we need to support named destinations as well as page -%D numbers. I invite readers to take a glance at the special driver modules to -%D understand the fine points of this. As a result we will deal with {\em locations} -%D as well as {\em real page numbers}. We explictly call this pagenumber a real one, -%D because it is independant of the page numbering scheme used in the document. -%D -%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to -%D support sophisticated interactive \PDF\ files, lays in the mere fact that real -%D page numbers are available in most two pass data, like references, list data and -%D index entries. -%D -%D We will speak of \type {thisis...} when we are marking a location, and -%D \type {goto...} when we point to such a location. The latter one can be seen as a -%D hyperlink to the former one. In the next macros one we use constructs like: -%D -%D \starttyping -%D \dostart... -%D \dostop... -%D \stoptyping -%D -%D The flag \type {\iflocation} signals if we're in interactive mode. - -\ifdefined\buttonheight \else \newdimen\buttonheight \fi -\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi - -%D Internal references can best be set using the next few macros. Setting such -%D references to unique values is completely up to the macros that call them. -%D -%D \starttyping -%D \thisissomeinternal{tag}{identifier} -%D \gotosomeinternal {tag}{identifier}{pagenumber}{text} -%D \stoptyping -%D -%D We could do this in \LUA\ \unknown - -\newif \iflocation -\newcount\locationcount -\newcount\locationorder -\newbox \locationbox - -\permanent\def\nextinternalreference {\the\locationcount} -\permanent\def\nextinternalorderreference{\the\locationorder} - -\permanent\def\setnextinternalreference - {\global\advance\locationcount\plusone} - -\permanent\def\setnextinternalreferences#kind#name% plural - {\clf_setnextinternalreference{#kind}{#name}} - -\permanent\def\getinternalorderreference#kind#name% - {\clf_currentreferenceorder{#kind}{#name}} - -\permanent\def\thisissomeinternal#kind#name% only for old time sake, will go away - {\begingroup - \clf_setinternalreference - reference {#kind:#name}% no view - \relax - \hpack attr \destinationattribute\lastdestinationattribute{}% - \endgroup} - -\installcorenamespace{savedinternalreference} - -\letvalue{\??savedinternalreference\s!default}\!!zerocount - -\permanent\protected\def\storeinternalreference#1#2% - {\setxvalue{\??savedinternalreference\currentstructurename}{\number#2}} - -\newconditional\preferpagereferences - -\permanent\def\gotosomeinternal#kind#name#target#text% - {\ifconditional\preferpagereferences - \directgoto{#text}[page(#target)]% - \else - \directgoto{#text}[#kind:#name]% - \fi} - -\permanent\def\gotonextinternal#text#target% - {\directgoto{#text}[internal(#target)]} - -%D In this module we define three system references: one for handling navigational, -%D viewer specific, commands, another for jumping to special pages, like the first -%D or last one, and a third reference for linking tree like lists, like tables of -%D contents. The latter two adapt themselves to the current state. -%D -%D An example of an action is: -%D -%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 -%D One can also activate an automatic prefix mechanism. By setting the -%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to -%D \type {-} or empty, the prefix is reset. Other values become the prefix. - -\newcount\prefixcounter - -\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 - -\permanent\protected\def\setupglobalreferenceprefix[#prefix]% - {\xdef\referenceprefix{#prefix}} - -\permanent\protected\def\globalpushreferenceprefix#prefix% - {\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}} - -\permanent\protected\def\globalpopreferenceprefix - {\xdef\referenceprefix{\clf_popreferenceprefix}} - -\permanent\protected\def\pushreferenceprefix#prefix% - {\edef\referenceprefix{\clf_pushreferenceprefix{#prefix}}} - -\permanent\protected\def\popreferenceprefix - {\edef\referenceprefix{\clf_popreferenceprefix}} - -\def\m_strc_references_prefix_yes{+} -\def\m_strc_references_prefix_nop{-} - -\permanent\protected\def\setupreferenceprefix[#prefix]% - {\edef\p_prefix{#prefix}% - \ifempty\p_prefix - \let\referenceprefix\empty - \orelse\ifx\p_prefix\m_strc_references_prefix_yes - \letreferencingparameter\c!prefix\s!unknown - \global\advance\prefixcounter\plusone - \edef\referenceprefix{\the\prefixcounter}% - \orelse\ifx\p_prefix\m_strc_references_prefix_nop - \letreferencingparameter\c!prefix\s!unknown - \let\referenceprefix\empty - \orelse\ifx\p_prefix\s!unknown - % forget about it - \else - \let\referenceprefix\p_prefix - \fi} - -\appendtoks - \setupreferenceprefix[\referencingparameter\c!prefix] -\to \everysetupreferencing - -%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and -%D goto specific locations using \type {\goto}. The last one does not make that much -%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an -%D \type {\in} but fortunately that one only makes sense in math mode. -%D -%D Typesetting the reference is a bit more complicated than one would at first sight -%D expect. This is due to the fact that we distinguish three (five) alternative -%D calls: -%D -%D \placefigure -%D [here][three calls] -%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 document meant for paper, -%D one is tempted to use the last (most straightforward) alternative. When a -%D document is also meant voor electronic distribution, the former alternatives have -%D preference, because everything between the \type {\in} and~\type {[} becomes -%D active (and when asked for, typeset in a different color and typeface). - -\appendtoks - \ifdefined\in \let\normalmathin \in \protected\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi - \ifdefined\at \let\normalmathat \at \protected\def\at {\mathortext\normalmathat \strc_references_at } \else \let\at \strc_references_at \fi - \ifdefined\about \let\normalmathabout\about \protected\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi - \ifdefined\from \let\normalmathfrom \from \protected\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from \fi - \ifdefined\over \let\normalmathover \over \protected\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi -\to \everydump - -\permanent \def\filterreference #key{\clf_filterreference{#key}} % no checking, expanded -\permanent\protected\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 using \type {\ref}. - -\permanent\tolerant\protected\def\getreference[#key]#spacer[#label]% #key = number page title text default realpage ... - {\ifarguments\or - \strc_references_dummy - \else - \doifelsereferencefound{#label}{\clf_filterreference{#key}}\strc_references_dummy - \fi} - -\aliased\let\ref\getreference - -%D Special cases: - -\protected\def\strc_references_about[#label]% - {\dontleavehmode - \begingroup - \enforced\let\crlf\space - \enforced\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 representation of -%D references. A symbol reference does not show the specific data, like the number -%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$ -%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to -%D go. -%D -%D \starttyping -%D ... \somewhere{backward text}{forward text}[someref] ... -%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] - -\permanent\def\referencepagestate - {\numexpr\clf_referencepagestate - {rst::\number\nofreferencestates}% - \relax} - -\permanent\def\referencepagedetail - {\numexpr\clf_referencepagedetail - {rst::\number\nofreferencestates}% - true % - \ifconditional\pagestatespread false\ifdoublesided true\else false\fi\fi - \relax} - -\permanent\def\referencerealpage {\clf_referencerealpage} % todo: no need for wrapping -\permanent\def\referencecolumnnumber{\clf_referencecolumn} % todo: no need for wrapping - -% So we need : instead of \ but that's only lmtx: -% -% \def\referencecolumnnumber -% {\numexpr\dimexpr\clf_referenceposx-\cutspace\relax:\dimexpr\makeupwidth/\nofcolumns\relax+\plusone\relax} -% -% Tacos patch of the older one, kept here as illustration -% -% \def\referencecolumnnumber -% {\numexpr -% \dimexpr\clf_referenceposx-\cutspace-\makeupwidth/(2*\nofcolumns)\relax -% /\dimexpr \makeupwidth/ \nofcolumns \relax -% +\plusone -% \relax} - - -\permanent\protected\def\tracedpagestate - {{\blue\tttf(\ifcase\referencepagedetail unknown\or same\or previous\or next\or above\or below\else unknown\fi)}} - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\referencesymbol - {\hpack\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. - -\permanent\protected\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}}% - -\permanent\protected\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}} - -\permanent\protected\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\strc_references_dummy}[#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! -% -% \protected\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}} -% -% \protected\def\conditionalat {\strc_references_conditional\at} -% \protected\def\conditionalin {\strc_references_conditional\in} -% \protected\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 - -\permanent\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 - -\permanent\let\rightofreferencecontent\empty -\permanent\let\leftofreference \empty -\permanent\let\rightofreference \empty - -\permanent\protected\def\leftofreferencecontent - {\removeunwantedspaces - \nonbreakablespace - \ignorespaces} - -\installcorenamespace{referencinginteraction} - -\def\strc_references_interaction_all - {\the\leftreferencetoks - \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing - \leftofreference - \doifelsesometoks\leftreferencetoks\onlynonbreakablespace\relax % new, replace space by nonbreakable if present - \currentreferencecontent - \rightofreference - \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing - \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 - {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname - \expandafter\lastnamedcs - \else - \expandafter\strc_references_interaction_all - \fi} - -\newtoks\everyresetinatreference - -\appendtoks - \enforced\glet\leftofreference \relax - \enforced\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 - \enforced\let\leftofreferencecontent\empty - \fi - \rightreferencetoks - \ifsecondargument - {#right}% - \else - \defaultrightreferencetoks - \enforced\let\rightofreferencecontent\empty - \fi - % inefficient: double resolve - \doifelsereferencefound{#label} % we need to resolve the text - {\goto{\referencesequence}[#label]} - {\let\currentreferencecontent\strc_references_dummy - \goto{\referencesequence}[#label]}% - \strc_references_stop_goto} - -\protected\def\strc_references_in - {\strc_references_start_goto - \let\currentreferencecontent\currentreferencedefault - \strc_references_pickup_goto} - -\protected\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 Hoekwater. They can -%D be used for predefining reference 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 be defined with \type -%D {\setuplabeltext}. -%D -%D Watch out: the second argument is somewhat special and mostly meant for a suffix -%D to a number: -%D -%D \startbuffer -%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] -%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=] - -\protected\def\strc_references_apply_format#name% - {\strc_references_start_goto - \edef\currentreferenceformat{#name}% - \enforced\gdef\leftofreference {\referenceformatparameter\c!left }% - \enforced\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 - \ifempty\currentstyleparameter \else - \resetinteractionparameter\c!style - \fi - \ifempty\currentcolorparameter \else - \resetinteractionparameter\c!contrastcolor - \resetinteractionparameter\c!color - \fi - \ifx\currentreferenceformatlabel\autoreferencelabeltextflag - \edef\currentreferenceformatlabel{\autoreferencelabeltext}% - \fi - \ifx\currentreferenceformatautocase\v!yes - \setcharactercleaning[1]% - \fi - \ifempty\currentreferenceformatlabel - \defaultleftreferencetoks {\referenceformatparameter\c!text}% - \defaultrightreferencetoks\emptytoks - \else - \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}% - \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}% - \fi - \ifempty\currentreferenceformattype - \def\currentreferenceformattype{default}% - \fi - % - \ifempty\currentreferenceformatsetups - \def\currentreferencecontent{\filterreference\currentreferenceformattype}% - \else - \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}% - \fi - % - \enforced\let\leftofreferencecontent \empty - \enforced\let\rightofreferencecontent\empty - \strc_references_pickup_goto} - -\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key - -\permanent\protected\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 bound to cross -%D references. The \type {\goto} commands can be used to let users access another -%D part of the document. In this respect, interactive tables of contents and -%D registers can be considered goto's. Because in fact a \type {\goto} is just a -%D reference without reference specific data, the previous macros are implemented -%D using the goto functionality. -%D -%D \showsetup{goto} -%D -%D One important characteristic is that the first argument of \type {\goto} (and -%D therefore \type {\at} and \type {\in} is split at spaces. This means that, -%D although hyphenation is prevented, long references can cross line endings. - -% \starttext -% \setupinteraction[state=start] -% [\goto{state}[file(mk-last-state)]] -% [\goto{state} [file(mk-last-state)]] -% \stoptext - -\newconditional\uselocationstrut \settrue\uselocationstrut - -\permanent\def\extrareferencearguments - {highlight \luaconditional\highlighthyperlinks\space - newwindow \luaconditional\gotonewwindow\space - layer {\currentviewerlayer}} - -\permanent\protected\def\directgoto - {\ifconditional\uselocationstrut - \expandafter\strc_references_direct_goto - \else - \expandafter\strc_references_direct_goto_htdp - \fi} - -\permanent\protected\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 - -\permanent\def\revivesavedreferenceattribute % sometimes handy as no test etc needed - {\c_attr_reference\lastsavedreferenceattribute} - -\def\strc_references_direct_goto#content[#label]% no test for valid references - {\dontleavehmode - \begingroup - \c_attr_reference\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 - \c_attr_reference\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 - \c_attr_reference\attributeunsetvalue - \iflocation - \clf_injectreference - {\referenceprefix}% - {#label}% - {% - height \dimexpr\interactionparameter\c!height\relax - depth \dimexpr\interactionparameter\c!depth \relax - \extrareferencearguments - }% - \relax - \setlocationattributes - \c_attr_reference\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 - \c_attr_reference\attributeunsetvalue - \iflocation - \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% - {\expandtexincurrentreference - \clf_injectcurrentreferencehtdp - \ht\strutbox - \dp\strutbox - \relax - \setlocationattributes - \setstrut % can be option - \global\lastsavedreferenceattribute\lastreferenceattribute - \c_attr_reference\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 - \c_attr_reference\attributeunsetvalue - \iflocation - \setstrut % can be option - \strc_references_get_simple_reference{#internal}% - \global\lastsavedreferenceattribute\currentreferenceattribute - \c_attr_reference\currentreferenceattribute - \setlocationattributes - \dostarttagged\t!link\empty - #content% - \dostoptagged - \else - #content% - \fi - \endgroup} - -\permanent\protected\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} - -\permanent\protected\def\strc_references_start_goto_nop - {\let\stopgoto\strc_references_stop_goto_nop} - -\permanent\protected\def\strc_references_stop_goto_nop - {\endgroup} - -\protected\def\strc_references_start_goto_yes - {\expandtexincurrentreference - \clf_injectcurrentreferencehtdp - \ht\strutbox - \dp\strutbox - \relax - \setlocationattributes - \setstrut % can be option - \global\lastsavedreferenceattribute\lastreferenceattribute - \c_attr_reference\lastreferenceattribute - \dostarttagged\t!link\empty - \let\stopgoto\strc_references_stop_goto_yes} - -\protected\def\strc_references_stop_goto_yes - {\dostoptagged - \endgroup} - -\def\strc_references_goto_htdp#content#dummy[#label]% dummy gobbles spaces - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\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 - \c_attr_reference\lastreferenceattribute - \dostarttagged\t!link\empty - #content% - \dostoptagged}% - {#content}% - \else - #content% - \fi - \endgroup} - -\permanent\protected\def\directgotobox#content[#label]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\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} - -\permanent\protected\def\directgotospecbox#resolver#content[#label]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\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} - -\permanent\protected\def\directgotodumbbox#content[#label]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\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} - -\permanent\protected\def\gotobox#content[#label]% - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\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} - -\permanent\protected\def\gotowdhtbox#width#height[#label]% fast variant for overlays - {\dontleavehmode - \begingroup - \setbox\scratchbox\emptyhbox - \wd\scratchbox#width% - \ht\scratchbox#height% - \global\lastsavedreferenceattribute\attributeunsetvalue - \c_attr_reference\attributeunsetvalue - \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% - {\clf_injectcurrentreference - \global\lastsavedreferenceattribute\lastreferenceattribute - \hpack attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} - {\box\scratchbox}% - \endgroup} - -%D An reference to another document can be specified as a file or as an \URL. Both -%D are handled by the same mechanism and can be issued by saying something like: -%D -%D \starttyping -%D \goto[dictionary::the letter a] -%D \stoptyping -%D -%D One can imagine that many references to such a dictionary are made, so in most -%D cases such a document reference in an 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 care of loading the -%D 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 specified. This is logical -%D when one keeps in mind that a valid \URL\ can also be a mail address. - -\permanent\tolerant\protected\def\useurl[#label]#spacer[#url]#spacer[#file]#spacer[#description]% - {\clf_useurl{#label}{\detokenize{#url}}{\detokenize{#file}}{\detokenize{#description}}} - -\permanent\tolerant\protected\def\usefile[#label]#spacer[#file]#spacer[#description]% - {\clf_usefile{#label}{\detokenize{#file}}{\detokenize{#description}}} - -\aliased\let\useURL \useurl -\aliased\let\useexternaldocument\usefile - -\permanent\def\doifelseurldefined #label{\clf_doifelseurldefined {#label}} % todo: no wrap -\permanent\def\doifelsefiledefined#label{\clf_doifelsefiledefined{#label}} % todo: no wrap - -\aliased\let\doifurldefinedelse \doifelseurldefined -\aliased\let\doiffiledefinedelse\doifelsefiledefined - -%D \macros -%D {url,setupurl} -%D -%D We also have: \type {\url} for directly calling the description. So we can say: -%D -%D \starttyping -%D \useURL [one] [http://www.test.nl] -%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=] - -\permanent\protected\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 \URL's break ok, according -%D 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 also specify a suitable -%D name (the last argument). This name can be called upon with: -%D -%D \showsetup{from} -%D -%D We keep this for compatibility reasons, hence the hackery. - -\permanent\tolerant\protected\def\strc_references_from[#label]% - {\dontleavehmode - \goto{\clf_from{#label}}[fileorurl(#label)]} - -\permanent\def\dofromurldescription#content% called at the lua end - {#content} - -\permanent\def\dofromurlliteral#content% called at the lua end - {\useurlstyleandcolor\c!style\c!color - \hyphenatedurl{#content}} - -\aliased\let\dofromfiledescription\dofromurldescription -\aliased\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, very system dependant -%D references are implemented by abusing 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} - -\permanent\tolerant\protected\def\defineprogram[#name]#spacer[#program]#spacer[#description]% - {\clf_defineprogram{#name}{#program}{#description}} - -\permanent\protected\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 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. When documenting and -%D sanitizing the original reference macros, I decided to keep the present meaning -%D as well as to make this meaning available as a special reference method. So now -%D one can use: -%D -%D \starttyping -%D \gotopage{some text}[location] -%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} - -\permanent\tolerant\protected\def\definepage[#name]#spacer[#target]% - {\definereference[#name][page(#target)]} - -\permanent\protected\def\gotopage#text[#target]% - {\goto{#text}[\v!page(#target)]} - -%D The previous definitions are somewhat obsolete so we don't 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 references: -%D -%D \starttyping -%D \goto{print version}[print::chapter] -%D \stoptyping -%D -%D and alike. The title placement definition macros have a key \type {file}, which -%D is interpreted as the file to jump to, that is, when one clicks on the title. - -\permanent\tolerant\protected\def\coupledocument[#name]#spacer[#file]#spacer[#sections]#spacer[#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 generate a space between -%D 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. - -\permanent\protected\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}% - \ifempty\p_separator \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 used here and that -%D concern the way the pagenumbers refered 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} - -\permanent\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}% - }} - -\permanent\tolerant\protected\def\setupreferencestructureprefix[#kind]#spacer[#category]#spacer[#settings]% - {\ifarguments\or\or - \getparameters[\??referencingprefix:#kind][#category]% - \else - \getparameters[\??referencingprefix#kind:#category][#settings]% - \fi} - -\def\referencestructureprefixparameter#kind#name#category#parameter% - {\ifcsname\??referencingprefix#name:#category#parameter\endcsname - \lastnamedcs - \orelse\ifcsname\??referencingprefix#kind:#category#parameter\endcsname - \lastnamedcs - \orelse\ifcsname\??referencingprefix:#category#parameter\endcsname - \lastnamedcs - \fi} - -\permanent\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 - -\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/tex/context/base/mkiv/strc-reg.mkxl b/tex/context/base/mkiv/strc-reg.mkxl deleted file mode 100644 index 97933ffb8..000000000 --- a/tex/context/base/mkiv/strc-reg.mkxl +++ /dev/null @@ -1,1210 +0,0 @@ -%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}{} - -\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 - -\aliased\let\strc_registers_setup_saved\setupregister - -% maybe we should drop the plural form - -\permanent\tolerant\protected\overloaded\def\setupregister[#1]#*[#2]#*[#3]% - {\ifarguments\or - \strc_registers_setup_saved[#1]% - \or - \strc_registers_setup_saved[#1][#2]% - \or - \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}% - \processcommalist[#2]\strc_registers_setup_step - \fi} - -\permanent\tolerant\protected\def\setupregisters[#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!check=\v!yes, % check for weird see usage - %\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 \protected\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}]}% - \frozen\instance\setuevalue{\currentregister}{\strc_registers_insert_entry[\currentregister]}% - \frozen\instance\setuevalue{\e!see\currentregister}{\strc_registers_insert_see[\currentregister]}% - %frozen\instance\setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}% - % historic ballast - \frozen\instance\setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}% - \frozen\instance\setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}% - \frozen\instance\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: - -\glet\currentregistername \empty -\glet\currentregisternumber\!!zerocount - -\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 - \glet\currentregistercoding\s!xml} - -\def\strc_registers_register_page_expand_yes_entries - {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% - \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% - \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% - \glet\currentregistercoding\s!tex} - -\def\strc_registers_register_page_expand_nop_entries - {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}% - \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}% - \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}% - \glet\currentregistercoding\s!tex} - -\def\strc_registers_register_page_expand_xml - {\xmlstartraw - \xdef\currentregisterentries{\registerparameter\c!entries}% - \xmlstopraw - \glet\currentregistercoding\s!xml} - -\def\strc_registers_register_page_expand_yes - {\xdef\currentregisterentries{\registerparameter\c!entries}% - \glet\currentregistercoding\s!tex} - -\def\strc_registers_register_page_expand_nop - {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% - \glet\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}% - \ifempty\currentregisterentries - \ifx\currentregisterexpansion\s!xml - \strc_registers_register_page_expand_xml_entries - \orelse\ifx\currentregisterexpansion\v!yes - \strc_registers_register_page_expand_yes_entries - \else - \strc_registers_register_page_expand_nop_entries - \fi - \else - \ifx\currentregisterexpansion\s!xml - \strc_registers_register_page_expand_xml - \orelse\ifx\currentregisterexpansion\v!yes - \strc_registers_register_page_expand_yes - \else - \strc_registers_register_page_expand_nop - \fi - \fi - \ifempty\currentregisterkeys - \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 - \glet\currentregistername\currentregister - \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 - \ifempty\currentregisterxmlsetup \else - xmlsetup {\currentregisterxmlsetup}% - \fi - }% - references {% - \ifempty\currentregisterlabel \else - label {\currentregisterlabel}% - \fi -% view {\interactionparameter\c!focus}% - }% - entries {% - % we need a special one for xml, this is just a single one - \ifempty\currentregisterentries - entries { - {\currentregisterentriesa}% - {\currentregisterentriesb}% - {\currentregisterentriesc}% - } - \else - entry {\currentregisterentries}% - \fi - \ifempty\currentregisterkeys - keys { - {\currentregisterkeysa}% - {\currentregisterkeysb}% - {\currentregisterkeysc}% - } - \else - key {\currentregisterkeys}% - \fi - }% - userdata {\detokenize\expandafter{\normalexpanded{#3}}} - }% - \clf_setinternalreference - internal \locationcount - view {\interactionparameter\c!focus}% - \relax % this will change - \ifx\currentregisterownnumber\v!yes - \glet\currentregistersynchronize\relax - \else - \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\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 - \c_attr_destination\lastdestinationattribute - \signalcharacter % no \strut as it will be removed during cleanup - \dotagregisterlocation - \dostoptagged - \endgroup} - -\permanent\protected\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor - {\begingroup - \edef\currentregister{#1}% - \setnextinternalreference - \glet\currentregistername\currentregister - \xdef\currentregisternumber{\clf_storeregister - {% - metadata {% - name {\currentregister}% - } - entries {% - entry {#2}% - key {#3}% - }% - processors {% - entry {#4}% - page {#5}% - }% - }% - }% - % overlap with the above - % \clf_setinternalreference - % internal \locationcount - % view {\interactionparameter\c!focus}% - \relax % this will change - \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% - \currentregistersynchronize % here? - \dostarttagged\t!registerlocation\currentregister - \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup - \dotagregisterlocation - \dostoptagged - \endgroup} - -\let\dotagregisterlocation\relax % experiment - -\tolerant\protected\def\strc_registers_insert_entry[#1]#*[#2]% - {\def\currentregister{#1}% - \edef\p_ownnumber{\registerparameter\c!ownnumber}% - \ifx\p_ownnumber\v!yes - \expandafter\strc_registers_insert_entry_yes - \else - \expandafter\strc_registers_insert_entry_nop - \fi{#2}} - -% \def\strc_registers_insert_entry_nop#1#2% -% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} -% -% \def\strc_registers_insert_entry_yes#1#2#3% -% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} -% -% less tokens passed (nicer for tracing) .. could become installable - -\def\strc_registers_insert_entry_nop - {\ifvmode - \expandafter\strc_registers_insert_entry_nop_par - \else - \expandafter\strc_registers_insert_entry_nop_txt - \fi} - -\def\strc_registers_insert_entry_yes - {\ifvmode - \expandafter\strc_registers_insert_entry_yes_par - \else - \expandafter\strc_registers_insert_entry_yes_txt - \fi} - -\def\strc_registers_insert_entry_nop_par#1#2% - {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} - -\def\strc_registers_insert_entry_yes_par#1#2#3% - {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} - -\def\strc_registers_insert_entry_nop_txt#1#2% - {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}} - -\def\strc_registers_insert_entry_yes_txt#1#2#3% - {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}} - -%D This is one of the few commands where a stop has arguments. - -\permanent\tolerant\protected\def\startregister[#1]#*[#2]#*[#3]#*[#4]#*#:#5% - {\ifparameter#4\or - % #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} - -\permanent\tolerant\protected\def\stopregister[#1]#*[#2]% - {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}} - -% a synonym, so that we can nest with overlap without syntax check problems - -\aliased\let\openregisterrange \startregister -\aliased\let\closeregisterrange\stopregister - -% not yet document, not sure if this will stay: - -\permanent\tolerant\protected\def\setregisterentry[#1]#*[#2]#*[#3]% - {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} - -\permanent\tolerant\protected\def\finishregisterentry[#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 - \resetregisterparameter\c!entries - \resetregisterparameter\c!label - \resetregisterparameter\c!keys - \resetregisterparameter\c!alternative - \setupcurrentregister[#2]% - \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 - \glet\currentregistercoding\s!xml - \else - \ifx\currentregisterexpansion\v!yes - \xdef\currentregisterentries{\registerparameter\c!entries}% - \else - \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% - \fi - \glet\currentregistercoding\s!tex - \fi - % I hate this kind of mess ... but it's a user request. - \ifempty\currentregisterentries - \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 - -\permanent\tolerant\protected\def\setstructurepageregister[#1]#*[#2]#*[#3]% [register][settings][userdata] - {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} - -\permanent\tolerant\protected\def\startstructurepageregister[#1]#*[#2]#*[#3]#*[#4]% [register][tag][settings][userdata] - {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}} - -\permanent\tolerant\protected\def\stopstructurepageregister[#1]#*[#2]% - {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}} - -\let\openstructurepageregisterrange \startstructurepageregister -\let\closestructurepageregisterrange\stopstructurepageregister - -% So far. - -\tolerant\protected\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 - \glet\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 - \glet\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 \locationcount - view {\interactionparameter\c!focus}% - \relax % this will change - \dostarttagged\t!registerlocation\currentregister - \c_attr_destination\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 - -\permanent\tolerant\protected\def\determineregistercharacteristics[#1]#*[#2]% - {\begingroup - \setupregister[#1][#2]% - \edef\currentregister{\firstinset{#1}}% - \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 \ifempty\registerpageseparatorsymbol false\else true\fi - }% - }}% - \ifcase\utilityregisterlength\relax - \resetsystemmode\v!register - \else - \setsystemmode \v!register - \fi} - -\newtoks\everyplaceregister - -\appendtoks - \dontcomplain -\to \everyplaceregister - -\newconditional\c_strc_registers_text_interaction - -\permanent\tolerant\protected\def\placeregister[#1]#*[#2]% - {\ifarguments\else - \begingroup - %\forgetall - \setupregister[#1][#2]% can be a list - \edef\currentregister{\firstinset{#1}}% - \the\everyplaceregister - \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone - \startmixedcolumns[\currentregister]% - \strc_registers_place_indeed{#1}% - \stopmixedcolumns - \else - \strc_registers_place_indeed{#1}% - \fi - \endgroup - \fi} - -\def\strc_registers_place_indeed#1% - {\doifelse{\registerparameter\c!interaction}\v!text - \settrue\setfalse\c_strc_registers_text_interaction - \clf_processregister - {#1}% - {% - language {\registerparameter\s!language}% - method {\registerparameter\c!method}% - numberorder {\registerparameter\c!numberorder}% - check {\registerparameter\c!check}% - compress {\registerparameter\c!compress}% - criterium {\registerparameter\c!criterium}% - pagemethod {\registerparameter\c!pagemethod}% - pagenumber \ifempty\registerpageseparatorsymbol 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}% - -\def\strc_registers_limited_entry#1% - {\limitated left \currentregistermaxwidth sentinel {\unknown} text {#1} freeze true\relax} - -\aliased\let\limitedregisterentry\firstofoneargument - -\appendtoks - \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}% - \ifempty\currentregistermaxwidth - \enforced\let\limitedregisterentry\firstofoneargument - \else - \enforced\let\limitedregisterentry\strc_registers_limited_entry - \fi -\to \everyplaceregister - -\permanent\tolerant\protected\def\completeregister[#1]#*[#2]% - {\ifarguments\or - \begingroup - \edef\currentregister{\firstinset{#1}}% - \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}% - \placeregister[#1][#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} - -\permanent\def\defaultregistercharacter#1% - {\edef\currentregistercharacter{#1}% - \ifempty\currentregistercharacter - % skip - \orelse\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} - -\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 = - -\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 = - -\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 - -\permanent\protected\def\startregisteroutput - {\endgraf - \begingroup - \d_strc_registers_distance\registerparameter\c!distance\relax - \dostarttaggedchained\t!register\currentregister\??register - \forgeteverypar - \forgetparindent - \forgetparskip} - -\permanent\protected\def\stopregisteroutput - {\endgraf - \dostoptagged - \endgroup} - -\newdimen\d_strc_registers_hangindent -\newcount\c_strc_registers_hangafter - -\permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change - {\useregisterstyleandcolor#1#2% - % how about style - \ifconditional\c_strc_registers_text_interaction - \ifempty\currentcolorparameter \else - \resetinteractionparameter\c!color - \resetinteractionparameter\c!contrastcolor - \fi - \fi} - -\permanent\protected\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}% - \usenestedregisterstyleandcolor\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} - -\permanent\protected\def\stopregisterentries - {\endgraf - \dostoptagged - \endgroup} - -\permanent\protected\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} - -\permanent\protected\def\stopregisterentry - {\endgraf - \global\setconstant\c_strc_registers_page_state\zerocount - \dostoptagged - \endgroup} - -\permanent\protected\def\startregistersection#1% title - {\dostarttagged\t!registersection\empty - \dostarttagged\t!registertag\empty - \registercharacter{#1}\endgraf - \dostoptagged} - -\permanent\protected\def\stopregistersection - {\dostoptagged - \endgraf} - -\permanent\protected\def\startregisterpages - {\begingroup - \dostarttagged\t!registerpages\empty - \useregisterstyleandcolor\c!pagestyle\c!pagecolor - \registerparameter\c!pageleft} - -\permanent\protected\def\stopregisterpages - {\registerparameter\c!pageright - \dostoptagged - \endgroup} - -\permanent\protected\def\startregisterseewords - {\begingroup - \dostarttagged\t!registerpage\empty - \useregisterstyleandcolor\c!pagestyle\c!pagecolor} - -\permanent\protected\def\stopregisterseewords - {\dostoptagged - \endgroup} - -\permanent\protected\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} - -\permanent\protected\def\registeronepagerangeseparator - {|\endash|} % todo use \prewordbreak - -% \protected\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} - -\permanent\protected\def\withregisterpagecommand#1#2#3#4% - {\ifcase#3\relax - {\tt [entry\space not\space flushed]}% - \else - \def\currentregisterpageindex{#2}% - \iflocation - \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% - \else - \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% - \fi - \fi} - -\permanent\protected\def\pushcurrentregister#1% - {\let\m_current_register\currentregister - \edef\currentregister{#1}} - -\permanent\protected\def\popcurrentregister - {\let\currentregister\m_current_register} - -\permanent\protected\def\registeronepage#1#2#3#4#5% #1:class #2:processor content - {\pushcurrentregister{#1}% - \edef\p_pagenumber{\registerparameter\c!pagenumber}% - \ifx\p_pagenumber\v!no\else - \registerpageseparator - \global\setconstant\c_strc_registers_page_state\plusone - \dostarttagged\t!registerpage\empty - \withregisterpagecommand{#2}{#3}{#4}{#5}% - \dostoptagged - \fi - \popcurrentregister} - -\newconditional\c_strc_registers_following - -\appendtoks - \edef\p_compress{\registerparameter\c!compress}% - \ifx\p_compress\v!text - \settrue\c_strc_registers_following - \letregisterparameter\c!compress\v!yes - \else - \setfalse\c_strc_registers_following - \fi -\to \everyplaceregister - -\permanent\protected\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable - {\pushcurrentregister{#1}% - \edef\p_pagenumber{\registerparameter\c!pagenumber}% - \ifx\p_pagenumber\v!no\else - \registerpageseparator - \global\setconstant\c_strc_registers_page_state\plusone - \dostarttagged\t!registerpagerange\empty - \dostarttagged\t!registerfrompage\empty - \withregisterpagecommand{#2}{#3}{#4}{#5}% - \dostoptagged - \ifconditional\c_strc_registers_following - \ifnum#3=\numexpr#6-1\relax - \labeltext{following:\s!singular}% - \else - \labeltext{following:\s!plural}% - \fi - \else - \registeronepagerangeseparator - \dostarttagged\t!registertopage\empty - \withregisterpagecommand{#2}{#6}{#7}{#8}% - \fi - \dostoptagged - \dostoptagged - \fi - \popcurrentregister} - -\permanent\protected\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word - {\pushcurrentregister{#1}% - \def\currentregisterpageindex{#3}% - \iflocation - \def\currentregisterseeindex{#4}% - \ifconditional\c_strc_registers_text_interaction - \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% - \else - \doapplyregisterentrycommand{#2}{#5}% - \fi - \else - \let\currentregisterseeindex\empty - \doapplyregisterentrycommand{#2}{#5}% - \fi - \popcurrentregister} - -\permanent\protected\def\doapplyregisterentrycommand#1#2% processor text - {\dostarttagged\t!registercontent\empty - \ifempty\currentregisterseeindex \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} - -\permanent\protected\def\doapplyregisterseecommand#1#2% - {\ifempty\currentregisterseeindex - \applyprocessor{#1}{#2}% - \orelse\iflocation - \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]% - \else - \applyprocessor{#1}{#2}% - \fi} - -\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word - {\pushcurrentregister{#1}% - \ifnum#2=\plusone - \registerpageseparator - \fi - \global\setconstant\c_strc_registers_page_state\plustwo - \def\currentregisterpageindex{#5}% - \dostarttagged\t!registersee\empty - \settrue\c_strc_registers_page_done - \iflocation - \def\currentregisterseeindex{#6}% - \else - \let\currentregisterseeindex\empty - \fi - \ifnum#2=\plusone - \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% - \orelse\ifnum#2=#3\relax - \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% - \else - ,\space\doapplyregisterseecommand{#4}{#7}% - \fi - \dostoptagged - \popcurrentregister} - -\permanent\protected\def\doapplyregistersectioncommand#1#2% - {\ifempty\currentregistersectionindex - \applyprocessor{#1}{#2}% - \orelse\iflocation - \strc_references_goto_internal{\applyprocessor{#1}{#2}}[sectionindex:\currentregistersectionindex]% - \else - \applyprocessor{#1}{#2}% - \fi} - -\permanent\protected\def\defaultregistersection#1#2#3#4#5#6#7% class i n #4:processor #5:internal #6:sectionindex #7:word - {\pushcurrentregister{#1}% - \ifnum#2=\plusone - \registerpageseparator - \fi - \global\setconstant\c_strc_registers_page_state\plustwo - \def\currentregisterpageindex{#5}% - \dostarttagged\t!registersection\empty - \settrue\c_strc_registers_page_done - \iflocation - \def\currentregistersectionindex{#6}% - \else - \let\currentregistersectionindex\empty - \fi - \ifnum#2=\plusone\else - ,\space - \fi - \doapplyregistersectioncommand{#4}{#7}% - \dostoptagged - \popcurrentregister} - -\aliased\let\registersection \defaultregistersection -\aliased\let\registerseeword \defaultregisterseeword -\aliased\let\registerentry \defaultregisterentry -\aliased\let\registercharacter\defaultregistercharacter - -%D Experimental: -%D -%D \starttyping -%D \setupregister -%D [index] -%D [pagesegments=1:4, -%D pagemethod=section] -%D -%D \starttext -%D -%D \chapter {one} \section {alpha} -%D -%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page -%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page -%D -%D \chapter {one} \section {alpha} -%D -%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page -%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page -%D -%D \placeindex[n=1] -%D -%D \stoptext -%D \stoptyping - -%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 - -\permanent\def\registerpageuserdata #1#2{\clf_registeruserdata#1{#2}} -\permanent\def\currentregisterpageuserdata {\registerpageuserdata\currentregisterpageindex} % {#1} - -% not yet ok : new internal handler names - -\aliased\let\registerpageseparatorsymbol\empty - -\permanent\protected\def\registerpagebuttonsymbol - {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} - -\installcorenamespace{registersymbol} - -\setvalue{\??registersymbol n}% - {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} - -\setvalue{\??registersymbol a}% - {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} % now done via conversion - -\setvalue{\??registersymbol\v!none}% - {\enforced\frozen\let\registerpageseparatorsymbol\empty - \enforced\frozen\let\registeronepage\gobblefivearguments - \enforced\frozen\let\registerpagerange\gobbleeightarguments} - -\setvalue{\??registersymbol 1}% - {\enforced\frozen\let\registerpageseparatorsymbol\space - \enforced\frozen\def\registeronepage{\symbol[1]\gobblefivearguments}% - \enforced\frozen\def\registerpagerange{\symbol[1]\gobbleeightarguments}} - -\setvalue{\??registersymbol 2}% - {\enforced\frozen\let\registerpageseparatorsymbol\space - \enforced\frozen\def\registeronepage{\registerpagebuttonsymbol\gobblefivearguments}% - \enforced\frozen\def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}} - -\protected\def\setregisterpagerendering - {\doifelse{\registerparameter\c!pagenumber}\v!no - {\enforced\frozen\let \currentregisterpagesymbol\v!none} - {\enforced\frozen\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}% - \ifempty\currentregisterpagesymbol - \csname\??registersymbol n\endcsname - \orelse\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname - \csname\??registersymbol\currentregisterpagesymbol\endcsname - \else - \enforced\frozen\let\registerpageseparatorsymbol\space - \enforced\frozen\def\registeronepage{\registerparameter\c!symbol\gobblefivearguments}% - \enforced\frozen\def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}% - \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. - -\permanent \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax} -\permanent\protected\def\pageofinternal #1{\clf_pageofinternal#1\relax} - -\permanent\protected\def\linkedregisterentrylink#1#2#3#4% tag where before after - {\iflocation - \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax - \ifcase\scratchcounter\else - #3\relax - \goto{\symbol[#2]}[internal(\the\scratchcounter)]% - #4\relax - \fi - \else - % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax - % \ifcase\scratchcounter\else - % #3\relax - % \pageofinternal\scratchcounter - % #4\relax - % \fi - \fi} - -\permanent\protected\def\linkedregisterentry#1% - {\dontleavehmode - \begingroup - \setbox\scratchbox\hbox{#1}% - \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace - \unhbox\scratchbox - \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax - \endgroup} - -\permanent\protected\def\registerpacked#1#2% - {\iflocation - \hskip\d_strc_registers_distance\relax - \nobreak - \ifnum#1=#2\relax - \goto{\symbol[\v!somewhere]}[internal(#1)]% - \else - \goto{\symbol[\v!first]}[internal(#1)]% - \nobreakspace - \goto{\symbol[\v!last]}[internal(#2)]% - \fi - \fi} - -%D Default index: - -\defineregister - [\v!index] -% [\v!indices] - -\stopcontextdefinitioncode - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-ren.mkxl b/tex/context/base/mkiv/strc-ren.mkxl deleted file mode 100644 index 2d553964b..000000000 --- a/tex/context/base/mkiv/strc-ren.mkxl +++ /dev/null @@ -1,817 +0,0 @@ -%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 - -\protected\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} - -\protected\def\strc_rendering_initialize_style_and_color_display#1#2% - {\dontconvertfont - \edef\p_strc_rendering_interlinespace{\headparameter\c!interlinespace}% - \ifempty\p_strc_rendering_interlinespace - % 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} - -\protected\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 - -\permanent\def\headreferenceattributes - {\iflocation - % \ctxlua{structures.lists.taglocation(\the\locationcount)}% maybe ... tags entry as used - attr \destinationattribute \currentstructureattribute - attr \referenceattribute \currentstructurereferenceattribute - % attr \internalattribute \locationcount - \fi} - -\permanent\def\setinlineheadreferenceattributes - {\ifconditional\headisdisplay \else \iflocation - \c_attr_destination\currentstructureattribute - \c_attr_reference \currentstructurereferenceattribute - % \c_attr_internal \locationcount - \fi \fi} - -\permanent\protected\def\docheckheadreference - {\edef\currentheadinteraction{\headparameter\c!interaction}% - \ifx\currentheadinteraction\v!list - % setuphead[
][interaction=list,...] - \strc_references_get_simple_reference{*\the\locationcount}% - \let\currentstructurereferenceattribute\currentreferenceattribute - \orelse\ifx\currentheadinteraction\v!reference - % setuphead[
][interaction=reference,...] start
[backreference=abc,...] - \edef\currentheadbackreference{\structurevariable\c!backreference}% weird, was references.backreference - \ifempty\currentheadbackreference \else - \strc_references_get_simple_reference\currentheadbackreference - \let\currentstructurereferenceattribute\currentreferenceattribute - \fi - \else - % maybe auto: backreference when given, else list - \fi} - -% a bit messy ... empty in place instead of self .. might change (or use special -% whatsig (invisible user one) - -\protected\def\strc_rendering_place_head_text - {\strc_rendering_start_placement - \setheadmarking - \doresetstructureheadnumbercontent - \ifconditional\c_strc_sectioning_empty - \setbox\b_strc_rendering_head\hpack \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} - -\protected\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\hpack \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} - -\protected\def\strc_rendering_place_head_empty - {\hpack\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 - -\permanent\protected\def\headhbox{\hbox\headreferenceattributes} -\permanent\protected\def\headvbox{\vbox\headreferenceattributes} - -\permanent\protected\def\startlocalheadsetup{\bgroup\strc_rendering_initialize_spacing} -\permanent\protected\def\stoplocalheadsetup {\egroup} - -\protected\def\strc_rendering_initialize_spacing - {\forgetall % local ! - \edef\p_align{\headparameter\c!align}% - \ifempty\p_align \else - \setupalign[\p_align]% - \fi - \edef\p_tolerance{\headparameter\c!tolerance}% - \ifempty\p_tolerance \else - \setuptolerance[\p_tolerance]% - \fi - \edef\p_strut{\headparameter\c!strut}% - \ifx\p_strut\v!no - \setnostrut - \fi - \enforced\let\\\strc_rendering_shortcut_backslash} - -\protected\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 - \synctexpushline - \edef\p_aligntitle{\headparameter\c!aligntitle}% - \ifx\p_aligntitle\v!yes - \strc_rendering_initialize_hsize_local - \orelse\ifx\p_aligntitle\v!float - \strc_rendering_initialize_hsize_local - \else - \strc_rendering_initialize_hsize_global - \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_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\hpack{\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_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_sectioning_stay_on_this_line -% {\directcheckedvspacing{-\v!line,\v!samepage,\v!nowhite}% -% \directcheckedvspacing\v!disable} -% -% we now use \ignoreparskip, so: - -\def\strc_sectioning_stay_on_this_line - {\directcheckedvspacing{-\v!line,\v!samepage}% - \directcheckedvspacing\v!disable} - -\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 - \setbox\b_strc_rendering_head\hbox - {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax - \box\b_strc_rendering_head - \getheadsyncs % a latelua why not in the box - }% - \ifgridsnapping - \applygridmethod - {\headparameter\c!grid}% - {\ifconditional\headisdisplay - \strc_rendering_initialize_style_and_color_display\c!textstyle\c!textcolor - \fi}% - {\box\b_strc_rendering_head} - \else - \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 % a latelua why not in the box - \else - % somehow this goes ok even when we push in the margin probably because we gobble pars - % in the process of collecting index entries etc - \strut - \flushnotes % new, here since we're in par mode - \unhbox\b_strc_rendering_head - \getheadsyncs % a latelua - \ifconditional\headissomewhere - \strc_sectioning_stay_on_this_line % test case: alternative=margintext and \startparagraph .. - \else - %\hskip\headnumberdistance\s!plus\headnumberdistance\s!minus.25\dimexpr\headnumberdistance\relax - \hskip\headtextdistance\relax - \strc_sectioning_inject_continuous_signal - \fi - \fi - \ifconditional\headisdisplay - \ifvmode - \ifgridsnapping % important, font related depth, see comment - \prevdepth\strutdp - \else - \prevdepth\d_strc_rendering_local_depth - \fi - \fi - \fi - \synctexpopline - \egroup - \egroup - \ifconditional\headisdisplay - \useindentnextparameter\headparameter - \orelse\ifconditional\headissomewhere - \ignoreparskip - \noindentation - \else - \ignoreparskip - \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 - -\permanent\tolerant\protected\def\defineheadplacement[#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 -\newskip \headtextdistance -\newdimen\headnumberdistance -\newdimen\headnumberwidth - -% \newconditional\headshownumber % defined already -% \newconditional\headisdisplay % defined already - -\protected\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}% - \ifempty\currentheadrenderingalternative - \let\currentheadrenderingalternative\v!vertical - \fi - \ifx\currentheadrenderingalternative\v!horizontal - \global\setfalse\headisdisplay % global - \global\setfalse\headissomewhere % global - \orelse\ifx\currentheadrenderingalternative\v!somewhere - \global\setfalse\headisdisplay % global - \global\settrue \headissomewhere % global - \else - \global\settrue \headisdisplay % global - \global\setfalse\headissomewhere % global - \fi} - -\protected\def\strc_rendering_initialize_dimensions - {\headwidth \headparameter\c!width \relax % \zeropoint == unset - \headnumberwidth \headparameter\c!numberwidth \relax % \zeropoint == unset - \headnumberdistance\headparameter\c!distance \relax - \headtextdistance \headparameter\c!textdistance\relax - \headtextwidth \headparameter\c!textwidth \relax} % \zeropoint == unset - -\permanent\protected\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} - -\permanent\protected\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} - -\permanent\protected\def\fakedheadnumber{\vphantom{0}} % needed for mathplus - -% \permanent\protected\def\fakeheadnumbercontent -% {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}} - -\permanent\protected\def\fakeheadnumbercontent - {\edef\p_hidenumber{\headparameter\c!hidenumber}% - \ifx\p_hidenumber\v!yes\else - \hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}% - \fi} - -\permanent\protected\def\strc_rendering_inject_number_and_text - {\edef\p_command{\headparameter\c!command}% assumes \protected definition - \ifempty\p_command - \directsetup\currentheadrenderingsetup - \else - \p_command\headnumbercontent\headtextcontent - \fi} - -\protected\def\strc_rendering_inject_text - {\edef\p_command{\headparameter\c!command}% assumes \protected definition - \ifempty\p_command - \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 - \ifzeropt\headwidth \else - \ifzeropt\headnumberwidth - \ifzeropt\headtextwidth \else - \headnumberwidth\dimexpr\headwidth-\headtextwidth\relax - \fi - \else - \ifzeropt\headtextwidth - \headtextwidth\dimexpr\headwidth-\headnumberwidth\relax - \fi - \fi - \hsize\headwidth - \fi - \ifzeropt\headnumberwidth \else - \headnumberdistance\zeropoint - \fi - \setbox\scratchbox\hbox \ifzeropt\headnumberwidth\else to \headnumberwidth\fi{\headnumbercontent} - \scratchdimen\dimexpr\wd\scratchbox+\headnumberdistance\relax - \ifzeropt\headtextwidth \else - \hsize\dimexpr\scratchdimen+\headtextwidth\relax - \fi - \hangindent\scratchdimen - \hangafter \plusone - \noindent - \box\scratchbox - \hskip\headnumberdistance - \else - \ifzeropt\headtextwidth - \ifzeropt\headwidth \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 - \dontleavehmode % in case there is no strut, else side effects with llap - \begstrut % use one \strut here! - \ifconditional\headshownumber - \doifelsesomething {\headparameter\c!location} { - % kind of new - \margindata [\headparameter\c!location] { - \headnumbercontent - } - } { - % normal backward compatible variant - \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 - \enforced\let\\\endgraf - \enforced\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 - \setbox\scratchboxone\hbox { - \headnumbercontent - } - \setbox\scratchboxtwo\vbox { - \headsetupspacing - \advance\hsize-\wd\scratchboxone\relax - \headtextcontent - } - \hpack { - \box\scratchboxone - \hskip\headnumberdistance - \box\scratchboxtwo - } - \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 - \setbox\scratchboxone\hbox { - \headnumbercontent - } - \setbox\scratchboxtwo\vtop { - \headsetupspacing - \advance\hsize-\wd\scratchboxone\relax - \headtextcontent - } - \hpack { - \box\scratchboxone - \hskip\headnumberdistance - \box\scratchboxtwo - } - \else - \vtop{ - \headsetupspacing - \noindent - \headtextcontent - } - \fi -\stopsetups - -% see typo-mar.mkiv: -% -% \defineheadalternative -% [\v!margintext] - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-sbe.mkxl b/tex/context/base/mkiv/strc-sbe.mkxl deleted file mode 100644 index bb6ba789a..000000000 --- a/tex/context/base/mkiv/strc-sbe.mkxl +++ /dev/null @@ -1,139 +0,0 @@ -%D \module -%D [ file=strc-sbe, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Section Block Environments, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Section Block Environments} - -\unprotect - -% \def\ChapterEntry#1#2#3% -% {chapter : \hbox to \hsize{\strut\bf#2\hss#3}\endgraf\placelist[section]} -% -% \startfrontmatter % optional -% \placelist[chapter][alternative=command,command=\ChapterEntry,criterium=text] \page -% \stopfrontmatter % optional -% -% \startbodymatter % optional -% \chapter{first} \section{one} test \section{two} test \page -% \chapter{second} \section{alpha} test \section{beta} test \page -% \stopbodymatter % optional - -\installcorenamespace{sectionblock} - -\installcommandhandler \??sectionblock {sectionblock} \??sectionblock - -\setupsectionblock - [\c!number=\v!yes, - \c!page=\v!right] % otherwise marks are reset too soon - -\newtoks\everybeforesectionblock -\newtoks\everyaftersectionblock - -\let\strc_sectionblock_define_normal\definesectionblock - -\permanent\overloaded\tolerant\protected\def\definesectionblock[#1]#*[#2]#*[#3]% singular plural settings - {\strc_sectionblock_define_normal[#1][#3]% - %\expandafter\newif\csname if#2\endcsname % obsolete - \strc_sectionblock_set_environment{#1}\empty - \frozen\setuvalue{\e!start#2}{\startsectionblock[#1]}% - \frozen\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}% - \ifempty\p_strc_sectionblock_page \else - \page[\p_strc_sectionblock_page]% - \fi} - -\appendtoks - \strc_sectionblock_handle_page - \resetallstructuremarks - \strc_sectionblock_get_environment\currentsectionblock - \sectionblockparameter\c!before % don't move - \dostarttagged\t!division\currentsectionblock % no parents -\to \everybeforesectionblock - -\appendtoks - \sectionblockparameter\c!after % don't move - \strc_sectionblock_handle_page - \dostoptagged - \resetallstructuremarks -\to \everyaftersectionblock - -\permanent\tolerant\protected\def\setsectionblock[#1]#*[#2]% used to set the default - {\edef\currentsectionblock{#1}% from now on we assume a value - \setupcurrentsectionblock[#2]% - \clf_setsectionblock{#1} - bookmark {\sectionblockparameter\c!bookmark}% - \relax} - -\let\currentsectionblock\empty % was \s!unknown - -\permanent\tolerant\protected\def\startsectionblock[#1]#*[#2]% - {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push) - \begingroup - \edef\currentsectionblock{#1}% from now on we assume a value - \setupcurrentsectionblock[#2]% - \clf_pushsectionblock{#1} - bookmark {\sectionblockparameter\c!bookmark}% - \relax - %\csname #1true\endcsname % obsolete - \setsystemmode\currentsectionblock - \the\everybeforesectionblock\relax - \showmessage\m!structures1\currentsectionblock} - -\permanent\protected\def\stopsectionblock - {\showmessage\m!structures2\currentsectionblock - \the\everyaftersectionblock\relax - \clf_popsectionblock - \endgroup} - -%D \starttyping -%D \startsectionblockenvironment[frontpart] -%D \setupnumber[userpage][numberconversion=romannumerals,start=1] -%D \stopsectionblockenvironment -%D -%D \startsectionblockenvironment[bodypart] -%D \setupnumber[userpage][numberconversion=numbers,start=1] -%D \stopsectionblockenvironment -%D -%D \startsectionblockenvironment[backpart] -%D \setupnumber[userpage][numberconversion=numbers,start=1] -%D \stopsectionblockenvironment -%D -%D \starttext -%D \startfrontmatter \chapter{test} \stopfrontmatter -%D \startbodymatter \chapter{test} \stopbodymatter -%D \startappendices \chapter{test} \stopappendices -%D \stoptext -%D \stoptyping - -\installcorenamespace{sectionblockenvironment} - -\protected\def\strc_sectionblock_set_environment#1#2% - {\setvalue{\??sectionblockenvironment#1}{#2}} - -\protected\def\strc_sectionblock_get_environment#1% - {\csname\??sectionblockenvironment#1\endcsname} - -\protected\setvalue{\e!start\v!sectionblockenvironment}% - {\dosingleargument\strc_sectionblock_environment_start} - -\letvalue{\e!stop\v!sectionblockenvironment}\relax - -\def\strc_sectionblock_environment_start[#1]% evt \pushendofline \popendofline - {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-sec.mkxl b/tex/context/base/mkiv/strc-sec.mkxl deleted file mode 100644 index 9a0ebbb54..000000000 --- a/tex/context/base/mkiv/strc-sec.mkxl +++ /dev/null @@ -1,1321 +0,0 @@ -%D \module -%D [ file=strc-sec, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Sectioning, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D In retrospect I should have gone futher and move more to the -%D \LUA\ end but here we are now. Maybe some day. - -\writestatus{loading}{ConTeXt Structure Macros / Sectioning} - -\unprotect - -\startcontextdefinitioncode - -\installcorenamespace{structure} - -\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters - -\setupstructure % not a user command so we might need to change the name - [\c!number=, - \c!level=, - \c!name=, - \c!title=, - \c!bookmark=, - \c!marking=, - \c!list=, - \c!label=, - \c!coupling=, - \c!ownnumber=, - % \c!interaction=\v!list, - \c!sectionseparatorset=\s!default, - \c!sectionconversionset=\s!default, - \c!sectionstopper=, - \c!sectionstarter=, - \c!sectionsegments=, - \c!sectionresetset=, - \c!reference=, - \c!backreference=, - \c!expansion=\v!no, - \c!xmlsetup=, - \s!catcodes=, - \c!saveinlist=\v!yes] - -% maybe flags for list, bm, mark - -\def\m_strc_references_prefix_yes{+} -\def\m_strc_references_prefix_nop{-} - -\let\currentstructurereferenceprefix\empty - -\installglobalmacrostack\currentstructurereferenceprefix - -\def\strc_sectioning_set_reference_prefix - {\ifempty\currentstructurereferenceprefix - % nothing - \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes - \global\advance\prefixcounter \plusone % temp here - \setupglobalreferenceprefix[\the\prefixcounter]% - \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop - \setupglobalreferenceprefix[]% - \else - \setupglobalreferenceprefix[\currentstructurereferenceprefix]% - \fi - \glet\currentstructurereferenceprefix\referenceprefix} - -% why xdef ? - -\setupstructure - [\c!label={\headparameter{\currentsectionblock\c!label}}, - \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed - \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi, - \c!level=\currentheadlevel, - \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi, - \c!expansion=\headparameter\c!expansion, - \c!xmlsetup=\headparameter\c!xmlsetup, - \s!catcodes=\headparameter\s!catcodes, - \c!sectionresetset=\headparameter\c!sectionresetset, - \c!sectionseparatorset=\headparameter\c!sectionseparatorset, - \c!sectionconversionset=\headparameter\c!sectionconversionset, - \c!sectionconversion=\headparameter\c!conversion, % just for compatibility - \c!sectionstarter=\headparameter\c!sectionstarter, - \c!sectionstopper=\headparameter\c!sectionstopper, - \c!sectionset=\headparameter\c!sectionset, - \c!sectionsegments=\headparameter\c!sectionsegments, - \c!reference=\headparameter\c!reference, - \c!referenceprefix=\headparameter\c!referenceprefix, - \c!criterium=\headparameter\c!criterium] - -% see lists/neat-001.tex for usage of: - -\permanent\def\namedstructureheadlocation#1% expandable, maybe [#1] - {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname} - -% The next directive only makes sense when we have sort of garanteed outcome (math is not so -% nice for instance). -% -% \enabledirectives[references.bookmarks.preroll] - -\newconditional\c_strc_bookmarks_preroll - -\installtexdirective - {references.bookmarks.preroll} - {\settrue \c_strc_bookmarks_preroll} - {\setfalse\c_strc_bookmarks_preroll} - -\def\strc_sectioning_autobookmark#1% - {\begingroup - % \settrialtypesetting - \the\everypreroll - \nodestostring\tempstring{#1}% - \glet\currentstructurebookmark\tempstring - \endgroup} - -% zeros: -% -% \setuphead[subsection][criterium=all] -% -% \dorecurse{3} { -% \chapter{Blabla} \subsection{bla 1 1} \subsection{bla 1 2} -% \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2} -% } - -\protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported) - {\begingroup - \setupstructure[\c!name={#1},#2]% - \xdef\currentstructurename {\structureparameter\c!name}% - \xdef\currentstructurecoupling {\structureparameter\c!coupling}% - \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number - \xdef\currentstructurelevel {\structureparameter\c!level}% - \edef\currentstructureexpansion {\structureparameter\c!expansion}% - \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}% - \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}% - \xdef\currentstructurelabel {\structureparameter\c!label}% - \xdef\currentstructurereference {\structureparameter\c!reference}% - \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}% - \xdef\currentstructurebackreference {\structureparameter\c!backreference}% - \xdef\currentstructureshownumber {\structureparameter\c!number}% - \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}% - \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}% - \xdef\currentstructureplaceholder {\structureparameter\c!placeholder}% - \ifx\currentstructureexpansion\s!xml - \xmlstartraw - \xdef\currentstructuretitle {\structureparameter\c!title}% - \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% - \xdef\currentstructuremarking {\structureparameter\c!marking}% - \xdef\currentstructurelist {\structureparameter\c!list}% - \xmlstopraw - \iflocation \ifempty\currentstructurebookmark \ifconditional\c_strc_bookmarks_preroll - \strc_sectioning_autobookmark\currentstructuretitle - \fi \fi \fi - \ifempty\currentstructurelist - \glet\currentstructurelist\currentstructuretitle - \fi - \glet\currentstructurecoding\s!xml - \else - \ifx\currentstructureexpansion\v!yes - \xdef\currentstructuretitle {\structureparameter\c!title}% - \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% - \xdef\currentstructuremarking {\structureparameter\c!marking}% - \xdef\currentstructurelist {\structureparameter\c!list}% - \iflocation \ifempty\currentstructurebookmark \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 \ifempty\currentstructurebookmark - \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 - \ifempty\currentstructurelist - \glet\currentstructurelist\currentstructuretitle - \fi - \glet\currentstructurecoding\s!tex - \fi - \setnextinternalreference - \storeinternalreference\currentstructurename{\the\locationcount}% - \strc_sectioning_set_reference_prefix - \clf_setsectionentry - references { - internal \locationcount - % block {\currentsectionblock} - prefix {\currentstructurereferenceprefix} - reference {\currentstructurereference} - backreference {\currentstructurebackreference} - } - directives { - resetset {\structureparameter\c!sectionresetset} - } - metadata { - kind {section} - name {\currentstructurename} - catcodes \ifempty\currentstructurecatcodes\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space - coding {\currentstructurecoding} - \ifx\currentstructurecoding\s!xml - xmlroot {\xmldocument} - \fi - \ifempty\currentstructurexmlsetup \else - xmlsetup {\currentstructurexmlsetup} - \fi - \ifx\currentstructuresaveinlist\v!no - nolist \space true\space - \fi - \ifx\currentstructureincrementnumber\v!yes - increment {\currentstructureincrementnumber} - \fi - } - titledata { - label {\detokenize\expandafter{\currentstructurelabel}} - title {\detokenize\expandafter{\currentstructuretitle}} - \ifx\currentstructurebookmark\currentstructuretitle \else - bookmark {\detokenize\expandafter{\currentstructurebookmark}} - \fi - \ifx\currentstructuremarking\currentstructuretitle \else - marking {\detokenize\expandafter{\currentstructuremarking}} - \fi - \ifx\currentstructuresaveinlist\v!no \else - \ifx\currentstructurelist\currentstructuretitle \else - list {\detokenize\expandafter{\currentstructurelist}} - \fi - \fi - } - numberdata { - % block {\currentsectionblock} - \ifx\currentstructureshownumber\v!no - hidenumber \space true\space % space needed for parser - \fi - separatorset {\structureparameter\c!sectionseparatorset} - conversionset {\structureparameter\c!sectionconversionset} - conversion {\structureparameter\c!sectionconversion} - starter {\structureparameter\c!sectionstarter} - stopper {\structureparameter\c!sectionstopper} - set {\structureparameter\c!sectionset} - segments {\structureparameter\c!sectionsegments} - ownnumber {\currentstructureownnumber} - language {\currentlanguage}% for the moment, needed for bookmarks conversion - criterium {\structureparameter\c!criterium} - } - userdata {\detokenize{#3}}% will be converted to table at the lua end - \relax - \xdef\currentstructurelistnumber{\clf_currentsectiontolist}% - % \currentstructuresynchronize has to be called someplace, since it introduces a node - \setstructuresynchronization\currentstructurelistnumber - \endgroup} - -\let\currentsectioncountervalue \!!zerocount % redefined later -\let\previoussectioncountervalue\!!zerocount % redefined later - -% We can access the (stored) data with the following macros. -% -% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}} -% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2} -% -% \setuphead[chapter][command=\MyHeadCommand] -% \setuplist[chapter][alternative=command,command=\MyListCommand] -% -% \starttext -% \setupheadertexts[chapter] -% \setupinteraction[state=start] -% \placebookmarks[chapter] -% \placelist[chapter] -% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps] -% \stopchapter -% \stoptext - -% todo: #1 => "#1" ... adapt lua code for name and number - -\permanent\def\structurenumber {\clf_structurenumber} -\permanent\def\structuretitle {\clf_structuretitle} -\permanent\def\structurevariable #1{\clf_structurevariable {#1}} -\permanent\def\structureuservariable #1{\clf_structureuservariable {#1}} -\permanent\def\structurecatcodedget #1{\clf_structurecatcodedget {#1}} % bad name -\permanent\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name -\permanent\def\structureautocatcodedget #1#2{\clf_structureautocatcodedget {#1}{#2}} -\permanent\def\namedstructurevariable #1#2{\clf_namedstructurevariable {#1}{#2}} -\permanent\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}} - -% compatibility issue: -% -% \def\setfullsectionnumber #1{} -% \def\preparefullnumber #1{} -% \def\fullsectionnumber {1--1--1} -% \def\makesectionnumber [#1]{} -% \def\makesectionformat {} -% \def\sectionformat {1--1-1-1-1-1-1} -% \def\composedsectionnumber{} -% \def\@@kolist{} - -% \setuphead[section] [separator=\separatorlist{?,!,*}] -% \setuphead[subsection][separator=\separatorlist{??,!!,**}] -% -% \let\spr\separatorlist % this will enable this feature -% -% \setuphead[section] [separator={?,!,*}] -% \setuphead[subsection][separator={??,!!,**}] -% -% \setupheads[separator={A,B,C,D,E,F}] -% \chapter{test} -% \section{test} \subsection{test} \subsection{test} -% \section{test} \subsection{test} \subsection{test} - -% lua interface / names and interface might change - -% \newconditional\c_strc_rendering_continuous % not used (mkii ?) - -\permanent\def\setstructurelevel #1#2{\clf_setstructurelevel {#1}{#2}} % name, level|parent -\permanent\def\getstructurelevel #1{\clf_getstructurelevel {#1}} % name -\permanent\def\setstructurenumber #1#2{\clf_setstructurenumber #1{#2}} % level, number (+/-) -\permanent\def\getstructurenumber #1{\clf_getstructurenumber \numexpr#1\relax} % level -\permanent\def\getsomestructurenumber #1#2{\clf_getsomestructurenumber #1{#2}} % level, what -\permanent\def\getfullstructurenumber #1{\clf_getfullstructurenumber \numexpr#1\relax} % level -\permanent\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}} % level, what -\permanent\def\getspecificstructuretitle #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}} - -% structure heads (like \startchapter) - -% \c!deeptextcommand, \c!deepnumbercommand: undefined ! -% \c!before \c!after \c!distance -% \c!page \c!header \c!text \c!footer=, -% \c!numbercommand \c!textcommand \c!ownnumber \c!number -% \c!file \c!grid \c!margintext -% \c!expansion \c!xmlsetup \s!catcode - -\installcorenamespace{head} -\installcorenamespace{headlevel} -\installcorenamespace{headincrement} -\installcorenamespace{headplace} -\installcorenamespace{headmarkyes} -\installcorenamespace{headmarknop} - -\installcommandhandler \??head {head} \??head - -\installmacrostack\currenthead -\installmacrostack\currentheadparent - -\setuphead [% - %\c!after=, - %\c!align=, - %\c!aligntitle=, - \c!alternative=\v!normal, - %\c!before=, - %\c!color=, - %\c!command=, - \c!continue=\v!yes, - %\c!coupling=, - %\c!deepnumbercommand=, - %\c!deeptextcommand=, - %\c!default=, - \c!distance=\zeropoint, - \c!textdistance=\zeropoint, - \c!textwidth=\zeropoint, % signal too - \c!numberwidth=\zeropoint, % signal too - \c!width=\zeropoint, % signal too - \c!expansion=\v!no, - %\c!file=, - %\c!footer=, - %\c!grid=, - \c!hang=\v!none, - %\c!header=, - \c!incrementnumber=\v!yes, - \c!indentnext=\v!no, - %\c!label=, - %\c!limittext=\languageparameter\c!limittext, - \c!margin=\zeropoint, - %\c!margintext=, - \c!number=\v!yes, - \c!numbercolor=\headparameter\c!color, - \c!textcolor=\headparameter\c!color, - \c!numberstyle=\headparameter\c!style, - \c!textstyle=\headparameter\c!style, - %\c!numbercommand=, - %\c!textcommand=, - \c!ownnumber=\v!no, - %\c!page=, - \c!placehead=\v!yes, - \c!sectionconversionset=\s!default, - \c!sectionnumber=\v!yes, - %\c!sectionsegments=, - \c!sectionseparatorset=\s!default, - \c!sectionset=\v!all, - \c!interlinespace=, - %\c!sectionstopper=, - %\c!sectionstarter=, - %\c!strut=, - %\c!style=, - %\c!text=, - %\c!tolerance=, - %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace - %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace - %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace - ] - -\aliased\let\setupheads\setuphead % will go - -\appendtoks - \ifempty\currentheadparent - \edef\currentheaddefault{\headparameter\c!default}% - \edef\currentheadsection{\headparameter\c!section}% - \ifx\currenthead\currentheaddefault - \let\currentheadparent\currentheadsection - \orelse\ifempty\currentheaddefault - \let\currentheadparent\currentheadsection - \else - \let\currentheadparent\currentheaddefault - \fi - \normalexpanded {% - \setheadparameter{\c!label}{\currenthead}% - \setheadparameter{\c!coupling}{\currenthead}% - \setheadparameter{\s!parent}{\??head\currentheadparent}% - \definemarking[\currenthead] [\currentheadsection]% - \definemarking[\currenthead\v!number][\currentheadsection]% - \setupmarking [\currenthead] [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]% - \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]% - }% - \doifelselist\currenthead\donothing - {\definelist[\currenthead][\c!prefix=\v!no]}% - % we can't do this now for backward compatibility reasons - % \doifelselist\currenthead\donothing - % {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% - \else - \normalexpanded {% - \setheadparameter{\c!label}{\currenthead}% - \setheadparameter{\c!coupling}{\currentheadparent}% - \definemarking[\currenthead] [\currentheadparent]% - \definemarking[\currenthead\v!number][\currentheadparent\c!number]% - }% - \doifelselist\currenthead\donothing - {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% - \fi - \presetlabeltext[\currenthead=]% - \the\everysetuphead -\to \everydefinehead - -\newtoks\everyredefinehead - -\appendtoks - \the\everyredefinehead -\to \everydefinehead - -\appendtoks - \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}% -\to \everyredefinehead - -\appendtoks - % beware, this is a global register - \begingroup - \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}% - \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}% - \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}% - \clf_registersection {\currenthead} { - coupling {\currentsectionheadcoupling} - section {\currentsectionheadsection} - level \space \currentsectionlevel \space % space needed for parser - parent {\currentheadparent} - }% - \endgroup -\to \everyredefinehead - -\appendtoks - \frozen\instance\setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}% - \frozen\instance\setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}% -\to \everydefinehead - -% so \subject as well as \section will need two commands when ownnumber -% is used (one can disable it anyway for subject) .. this is not downward -% compatible but better - -\appendtoks - \ifempty\currenthead \else - \doifelse{\headparameter\c!ownnumber}\v!yes - {\instance\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}} - {\instance\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}% - \fi -\to \everysetuphead - -\permanent\protected\def\doredefinehead#1#2% called at lua end - {\push_macro_currenthead - \push_macro_currentheadparent - \edef\currenthead{#1}% - \edef\currentheadparent{#2}% - \the\everyredefinehead\relax - \pop_macro_currentheadparent - \pop_macro_currenthead} - -\let\currentnamedsection\empty - -\installmacrostack\currentnamedsection - -% structure sections (the parents of chapter etc) - -\let\firstsectionname\empty -\let\lastsectionname \empty - -\let\resetallstructuremarks \relax -\let\resetcurrentstructuremarks \relax -\let\resetcurrentstructuremarkswithpage\relax - -\def\resetallstructuremarks {\resetmarking[\firstsectionname]} % will become option (was \v!section-1) -\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option -%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option - -% We could use a commandhandler here but sections are somewhat special in the -% sense that we have two ways of chaining: the main section (levels) as well -% as rendering (head). - -% -2 = text -% -1 = manual -% 0 = block -% +1 = structurelevel 1 .. n - -\newcount\maxstructuredepth - -\permanent\def\sectionlevel#1% - {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname} - -\permanent\def\namedsectionlevel#1#2% direct indirect - {\csname\??headlevel - \ifcsname\??headlevel#1\endcsname - #1% - \orelse\ifcsname\??headlevel#2\endcsname - #2% - \else - \v!none - \fi - \endcsname} - -\permanent\def\xthenamedheadlevel#1% - {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}} - -\setvalue{\??headlevel\v!block}{0} -\setvalue{\??headlevel\v!none }{-1} -\setvalue{\??headlevel\v!text }{-2} -\setvalue{\??headlevel\v!head }{-3} - -\newtoks\everydefinesection - -\permanent\protected\def\definesection[#1]% - {\ifcsname\??headlevel#1\endcsname \else - \edef\currentsection{#1}% not used, will go - \edef\currenthead{#1}% - \global\advance\maxstructuredepth\plusone - \setevalue{\??headlevel#1}{\the\maxstructuredepth}% - \setstructurelevel{#1}{\sectionlevel{#1}}% - \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER - \the\everydefinesection - % so far for these default inheritances - \definemarking[#1]% - \ifnum\maxstructuredepth>\plusone - \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child - \fi - \xdef\lastsectionname{#1}% - \ifempty\firstsectionname - \glet\firstsectionname\lastsectionname - \fi - \fi} - -\permanent\tolerant\protected\def\setupsection[#1]#*[#2]#*[#3]% - {\ifparameter#1\else - \push_macro_currenthead - \edef\currenthead{\ifcsname\??headlevel#1\endcsname#1\else\sectionheadsection{#1}\fi}% - \ifparameter#3\or - \edef\currenthead{\currenthead#2}% not used at any more in mkiv (sets now) - \setupcurrenthead[#3]% - \else - \setupcurrenthead[#2]% - \fi - \pop_macro_currenthead - \fi} - -% we share the parameters as sections are roots of heads so eventually we can -% consider \definesection -> \definehead with one argument - -\appendtoks - % This is a rather practical default that we don't want to - % be part of the parent chain lookup mechanism; it's also - % mkii compatible. Somewhat weird that it's part of the - % top level structure but it will be flattened anyway. - \let\currenthead\currentsection % - \setheadparameter\c!textstyle {\directheadparameter\c!style}% - \setheadparameter\c!textcolor {\directheadparameter\c!color}% - \setheadparameter\c!numberstyle{\directheadparameter\c!style}% - \setheadparameter\c!numbercolor{\directheadparameter\c!color}% -\to \everydefinesection - -% head -> head - -\permanent\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}} % can be done at lua end -\permanent\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}} % can be done at lua end - -\permanent\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling} -\permanent\def\sectionheadsection #1{\namedheadparameter{#1}\c!section} - -% head construction - -\newconditional\currentstructureown - -\newtoks\everybeforehead % hook, todo: before/after keys -\newtoks\everyafterhead % hook, todo: before/after keys - -\permanent\tolerant\protected\def\strc_sectioning_handle_own[#1]#*[#2]#:#*#=#*#=% [ref] {nr} {title} - {\settrue\currentstructureown - \triggerautostructurelevel - \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title -- - -\permanent\tolerant\protected\def\strc_sectioning_handle_nop[#1]#*[#2]% [ref] {title} / for taco: [key=value] variant - {\setfalse\currentstructureown - \triggerautostructurelevel - \ifhastok={#2}% - \expandafter\strc_sectioning_handle_nop_indeed_yes - \else - \expandafter\strc_sectioning_handle_nop_indeed_nop - \fi - {#1}{#2}} - -\def\strc_sectioning_handle_nop_indeed_yes#1#2% - {\strc_sectioning_handle{#1}{#2}{}} - -\def\strc_sectioning_handle_nop_indeed_nop#1#2#3% - {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- - -\permanent\tolerant\protected\def\strc_sectioning_start[#1]#*[#2]#*[#3]% for the moment no grouping, too annoying with page breaks - {\push_macro_currentnamedsection - \push_macro_currentstructurereferenceprefix - \edef\currentnamedsection{#1}% - \setfalse\currentstructureown - %\globalpushmacro\currenthead % this does not work out well - \xdef\currenthead{#1}% - \setsystemmode\currenthead % new, also here now - \headparameter\c!beforesection % beware, no users vars set yet - \the\everybeforehead - \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here) - % potential: \bgroup (can be optional: grouped = yes) - \headparameter\c!insidesection} - -\permanent\protected\def\strc_sectioning_stop[#1]% !!! also used at lua end - {\dostoptagged - \dostoptagged - % potential: \egroup - %\globalpopmacro\currenthead % so we do a hard recover - \xdef\currenthead{#1}% recover - \headparameter\c!aftersection - \the\everyafterhead - \resetsystemmode\currenthead - \pop_macro_currentstructurereferenceprefix - \pop_macro_currentnamedsection} % new, also here now - -\aliased\let\dostarthead\strc_sectioning_start % used at lua end -\aliased\let\dostophead \strc_sectioning_stop % used at lua end - -% todo: add grouping but where: before/after trickery .. probably inside because one can always add -% grouping to the before/after settings - -\aliased\let\startnamedsection\strc_sectioning_start - -\permanent\protected\def\stopnamedsection - {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}} - -% \newconditional\structurereversesectionnumbers % todo: key/val - -\newconditional\c_strc_sectioning_to_list -\newconditional\c_strc_sectioning_increment -\newconditional\c_strc_sectioning_place -\newconditional\c_strc_sectioning_empty -\newconditional\c_strc_sectioning_hidden -\newconditional\c_strc_sectioning_section - -\newconditional\headshownumber % public -\newconditional\headisdisplay % public -\newconditional\headissomewhere % public - -\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} -\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list} -\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} -\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} - -\protected\def\strc_sectioning_initialize_increment - {\edef\currentheadincrement{\headparameter\c!incrementnumber}% - \ifcsname\??headincrement\currentheadincrement\endcsname - \lastnamedcs - \else - \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list - % \filterheadnumber - \fi} - -\permanent\protected\def\filterheadnumber - {\settrue\c_strc_sectioning_increment - \settrue\c_strc_sectioning_to_list - \ifempty\currentproduct - % todo : filter from other toc (number, file, title) - % use : \currentheadincrement as spec - \fi} - -\setvalue{\??headplace\v!yes}% - {\setfalse\c_strc_sectioning_empty - \settrue \c_strc_sectioning_place - \setfalse\c_strc_sectioning_hidden - \setfalse\c_strc_sectioning_section} - -\setvalue{\??headplace\v!empty}% - {\settrue \c_strc_sectioning_empty - \settrue \c_strc_sectioning_place - \setfalse\c_strc_sectioning_hidden - \setfalse\c_strc_sectioning_section} - -\setvalue{\??headplace\v!no}% - {\settrue \c_strc_sectioning_empty - \setfalse\c_strc_sectioning_place - \setfalse\c_strc_sectioning_hidden - \setfalse\c_strc_sectioning_section} - -\setvalue{\??headplace\v!hidden}% - {\settrue \c_strc_sectioning_empty - \setfalse\c_strc_sectioning_place - \settrue \c_strc_sectioning_hidden - \setfalse\c_strc_sectioning_section} - -\setvalue{\??headplace\v!section}% - {\settrue \c_strc_sectioning_empty - \setfalse\c_strc_sectioning_place - \settrue \c_strc_sectioning_hidden - \settrue \c_strc_sectioning_section} - -\protected\def\strc_sectioning_initialize_placement - {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes} - -\newmode\v!sectionnumber - -\def\dosetstructureheadnumbercontent - {\setsystemmode\v!sectionnumber - \settrue\headshownumber} % why ? - -\def\doresetstructureheadnumbercontent - {\resetsystemmode\v!sectionnumber - \setfalse\headshownumber} % why ? - -\protected\def\strc_sectioning_initialize_number - {\edef\p_number{\sectionblockparameter\c!number}% - \ifx\p_number\v!yes - \edef\p_number{\headparameter\c!number}% - \ifx\p_number\v!yes - \settrue\headshownumber - \else - \setfalse\headshownumber - \fi - \else - \setfalse\headshownumber - \fi} - -% Beware, we do need some node for anchoring marks and normally a zwnj will -% do but it interferes so we deal with it at the \LUA\ end. - -\newtoks\everyheadsynchronization - -% \appendtoks -% \currentstructuresynchronize -% \to \everyheadsynchronization - -\aliased\let\currentstructuresynchronize\donothing - -\appendtoks - \currentstructuresynchronize - \enforced\glet\currentstructuresynchronize\donothing -\to \everyheadsynchronization - -\protected\def\theheadsynchonization - {% no, interferes: \signalcharacter - \the\everyheadsynchronization} - -% BEWARE: \marking[section]{my text} does not work as we use list indices instead -% so we need a 'keep track of raw set option' (or maybe a funny internal prefix) - -\permanent\protected\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this} - {\strc_sectioning_delayed_flush - \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}} - -\let\deepstructurenumbercommand\relax -\let\deepstructuretitlecommand \relax - -\permanent\protected\def\fullheadnumber - {\edef\currentheadlabeltag{\currentsectionblock\c!label}% - \dostarttagged\t!sectionnumber\empty - \labeltexts - {\headparameter\currentheadlabeltag} - {\ifx\deepstructurenumbercommand\relax - \structurenumber - \else - \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}% - \fi}% - \dostoptagged} - -\permanent\protected\def\fullheadtitle - {\dostarttagged\t!sectiontitle\empty - \ifx\deepstructuretitlecommand\relax - \structuretitle - \else - \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}% - \fi - \dostoptagged} - -\let\currenthead \empty -\let\currentheadcoupling\empty -\let\currentheadsection \empty -\let\currentheadlevel \!!zerocount -\let\currentheadcounter \!!zerocount - -\let\strc_show_used\relax - -\installtextracker - {structures.showused} - {\let\strc_show_used\clf_showstructure} - {\let\strc_show_used\relax} - -\appendtoks - \strc_show_used -\to \everystoptext - -\protected\def\strc_sectioning_report{\clf_reportstructure} - -\ifdefined\strc_rendering_initialize_style_and_color \else - - \protected\def\strc_rendering_initialize_style_and_color#1#2% - {\dontconvertfont - \useheadstyleandcolor\c!style\c!color - \useheadstyleandcolor#1#2% - \setupinterlinespace} - -\fi - -\permanent\tolerant\protected\def\placeheadtext[#1]% - {\dontleavehmode - \begingroup - \protected\def\\{\space}% messy here, but the default (and needs to be grouped) - \global\settrue\headisdisplay % triggers interlinespace checking - \edef\currenthead{#1}% maybe only when #1 is given - \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor - \relax - \getspecificstructuretitle{\thenamedheadlevel{#1}}% - \endgraf - \endgroup} - -\permanent\tolerant\protected\def\placeheadnumber[#1]% - {\dontleavehmode - \begingroup - \global\settrue\headisdisplay % triggers interlinespace checking - \edef\currenthead{#1}% maybe only when #1 is given - \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor - \relax - \getfullstructurenumber{\thenamedheadlevel{#1}}% - \endgraf - \endgroup} - -\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi - -\newtoks\everybeforesectionheadhandle -\newtoks\everyaftersectionheadhandle - -\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller) - {\xdef\currenthead {#1}% - \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}% - \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}% - \xdef\currentheadlevel {\sectionlevel \currentheadsection}% - % - %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}% - % - \strc_sectioning_initialize_autolevel - \strc_sectioning_initialize_increment - \strc_sectioning_initialize_placement - \strc_sectioning_initialize_number - % - \the\everybeforesectionheadhandle - % - % todo: also mark (for header) - % - % we might remove the lower level - % - % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}% - % -% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call - % - % \currentstructuresynchronize % will move - % - \let\getheadnumber\empty - \let\getheadtitle \empty - \let\getheadsyncs \empty - \ifconditional\c_strc_sectioning_increment - \ifconditional\c_strc_sectioning_place - \strc_sectioning_before_yes - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs\theheadsynchonization - \let\getheadtitle\fullheadtitle - \ifconditional\headshownumber - \let\getheadnumber\fullheadnumber - \strc_rendering_place_head_number_and_text - \else - \strc_rendering_place_head_text - \fi - \dostoptagged - \strc_sectioning_after_yes - \orelse\ifconditional\c_strc_sectioning_hidden - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs\theheadsynchonization - \ifconditional\c_strc_sectioning_section - \strc_rendering_place_head_section - \else - \strc_rendering_place_head_hidden % only something when tracing - \fi - \dostoptagged - \else - \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs\theheadsynchonization - \strc_rendering_place_head_empty % just flush 'm - \dostoptagged - \strc_sectioning_after_nop - \fi - \else - \ifconditional\c_strc_sectioning_place - \strc_sectioning_before_yes - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs\theheadsynchonization - \let\getheadtitle\fullheadtitle - \strc_rendering_place_head_text - \dostoptagged - \strc_sectioning_after_yes - \orelse\ifconditional\c_strc_sectioning_hidden - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \let\getheadsyncs\theheadsynchonization - \dostarttagged\t!sectioncaption\empty - \ifconditional\c_strc_sectioning_section - \strc_rendering_place_head_section - \else - \strc_rendering_place_head_hidden % only something when tracing - \fi - \dostoptagged - \else - % do nothing / should be vbox to 0pt - \strc_sectioning_before_nop - \strc_sectioning_register{#1}{#2}{#3}% after optional \page - \strc_sectioning_report - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs\theheadsynchonization - \strc_rendering_place_head_empty % just flush 'm - \dostoptagged - \strc_sectioning_after_nop - \fi - \fi - % - \the\everyaftersectionheadhandle - % - \setfalse\c_strc_sectioning_ignore_page - % ignorespaces prevents spaces creeping in when after=\dontleavehmode - \dostarttagged\t!sectioncontent\empty - \ifempty\currentstructureplaceholder - \ifconditional\headisdisplay - \doubleexpandafter\ignorespaces - \else - \doubleexpandafter\ignorepars - \fi - \else - \expandafter\strc_sectioning_placeholder - \fi} - -%D \starttyping -%D \startsubject[placeholder=todo,title=one] -%D whatever one -%D \stopsubject -%D \stoptyping - -\def\strc_sectioning_placeholder - {\placeholder[\currentstructureplaceholder]% - \gobblenested{\e!start\currenthead}{\e!stop\currenthead}{\e!stop\currenthead}} - -% typesetting (the getters are public) - -\protected\def\strc_rendering_place_head_number_and_text - {\setheadmarking - \getheadnumber/\getheadtitle - \getheadsyncs} - -\protected\def\strc_rendering_place_head_text - {\setheadmarking - \getheadtitle - \getheadsyncs} - -\protected\def\strc_rendering_place_head_empty - {\setheadmarking - \getheadsyncs} - -\installcorenamespace{hiddenheadattr} -\installcorenamespace{hiddenheadsync} - -% todo: when in the page builder we need to resolve the marking immediately -% because otherwise we have an async - -\newbox\b_sectioning_delayed - -\def\strc_sectioning_delayed_flush - {\ifvoid\b_sectioning_delayed\else - \smashedbox\b_sectioning_delayed - \fi} - -\protected\def\strc_rendering_place_head_section % see hidden below - {\global\setbox\b_sectioning_delayed\hpack\bgroup - \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% - \hpack\headreferenceattributes{}% also does the mark - \theheadsynchonization - \egroup} - -\protected\def\strc_rendering_place_head_hidden % maybe trialtypesetting check - {\setxvalue{\??hiddenheadattr\currenthead}% - {\headreferenceattributes}% can be used when making a box - \setxvalue{\??hiddenheadsync\currenthead}% - {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax - \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% - \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference - \theheadsynchonization}} % and it's a node anyway - -\permanent\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname} -\permanent\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname} - -\permanent\protected\def\placerawheaddata [#1]{\synchronizehead{#1}} -\permanent\protected\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}} -\permanent\protected\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}} - -\permanent\protected\def\repeathead[#1]% - {\begingroup - \setupinteraction[\c!state=\v!stop]% - \def\currenthead{#1} - \strc_sectioning_initialize_placement - \strc_sectioning_initialize_number - \dostarttagged\t!sectioncaption\empty - \let\getheadsyncs \relax - \def\getheadtitle {\getmarking[#1]} - \def\getheadnumber{\getmarking[#1\v!number]} - \strc_sectioning_before_yes - \ifconditional\headshownumber - \strc_rendering_place_head_number_and_text - \else - \strc_rendering_place_head_text - \fi - \dostoptagged - \strc_sectioning_after_yes - \endgroup} - -% \setuphead[chapter][placehead=hidden] -% \chapter {test} -% -% %(\synchronizehead{chapter}) % \getheadsyncs -% %(\getfullstructurenumber{\thenamedheadlevel{chapter}}) -% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}}) -% -% (\placerawheaddata [chapter]) -% (\placerawheadnumber[chapter]) -% (\placerawheadtext [chapter]) - -% pagebreaks - -\letvalue{\??headmarknop\v!page }\donothing -\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks} -\letvalue{\??headmarknop\s!unknown}\donothing - -\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks} -\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks} -\letvalue{\??headmarkyes\s!unknown}\donothing - -\def\strc_sectioning_check_layout - {\edef\p_page{\headparameter\c!page}% - \ifempty\p_page - \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}% - \ifempty\p_header \else - \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing - \fi - \edef\p_text{\headparameter\c!text}% - \ifempty\p_text \else - \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing - \fi - \edef\p_footer{\headparameter\c!footer}% - \ifempty\p_footer \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 \d_strc_sectioning_continuous_signal - -\protected\def\strc_sectioning_inject_continuous_signal - {\ifhmode - \hskip\d_strc_sectioning_continuous_signal\relax - \fi} - -% \let\dotagsectionlevel\relax - -\def\strc_sectioning_before_yes - {\strc_sectioning_check_before\strc_sectioning_handle_page_yes - \headparameter\c!inbetween - \dostarttaggedchained\t!section\currenthead\??head -% \dotagsectionlevel - } - -\def\strc_sectioning_before_nop - {\strc_sectioning_check_before\strc_sectioning_handle_page_nop - \headparameter\c!inbetween - \dostarttagged\currenthead\empty} % this is a weird one .. needs checking - -\def\strc_sectioning_empty_correction - {\ifconditional\c_strc_sectioning_empty - % this needs checking - \penalty\plustenthousand - \vskip-\lineheight - \kern\zeropoint - \prevdepth\strutdepth - \fi} - -\def\strc_sectioning_after_nop - {} - -\def\strc_sectioning_check_before#1% - {\ifhmode - \scratchcounter\lastpenalty - \unpenalty % no beauty in this - \ifdim\lastskip=\d_strc_sectioning_continuous_signal - % no page break - \ifconditional\c_strc_sectioning_ignore_page - \setfalse\c_strc_sectioning_ignore_page - \else - \global\c_strc_sectioning_preceding_level\currentheadlevel - \nobreak - \fi - % \global\settrue\c_strc_rendering_continuous - \else - \penalty\scratchcounter - % \global\setfalse\c_strc_rendering_continuous - #1% - \fi - \else - % \global\setfalse\c_strc_rendering_continuous - #1% - \fi} - -%permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} -%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} - -\permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} -%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} -\permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax} - -\let\previoushead\empty - -\def\strc_sectioning_handle_page_nop - {\edef\p_continue{\headparameter\c!continue}% - \ifx\p_continue\v!yes - \ifx\currenthead\previoushead % not really needed - \strc_sectioning_check_layout - \orelse\ifnum\previoussectioncountervalue=\zerocount - \strc_sectioning_check_layout - \orelse\ifnum\currentsectioncountervalue>\zerocount - \strc_sectioning_check_layout - \fi - \else - \strc_sectioning_check_layout - \fi - \glet\previoushead\currenthead} - - -\def\strc_sectioning_handle_page_yes - {\ifconditional\c_strc_sectioning_ignore_page - \setfalse\c_strc_sectioning_ignore_page - \else - % beware, these numbers are not yet know here - \strc_sectioning_handle_page_nop - \edef\p_aligntitle{\headparameter\c!aligntitle}% - \ifx\p_aligntitle\v!float - \ifconditional\c_strc_sectioning_auto_break - \spac_vspacing_same_page\currentheadlevel\zerocount - \fi - \headparameter\c!before\relax - \indent - \else - \page_otr_command_flush_side_floats - \ifconditional\c_strc_sectioning_auto_break - \spac_vspacing_same_page\currentheadlevel\zerocount - \fi - \headparameter\c!before\relax - \fi - \global\c_strc_sectioning_preceding_level\currentheadlevel - \fi - \glet\previoushead\currenthead} - -\def\strc_sectioning_depth_correction - {\ifvmode - \edef\p_depthcorrection{\headparameter\c!depthcorrection}% - \ifx\p_depthcorrection\v!strut - \prevdepth\strutdepth - \fi - \fi} - -\def\strc_sectioning_after_yes - {\ifconditional\headisdisplay - \ifconditional\c_strc_sectioning_auto_break - \spac_vspacing_same_page\currentheadlevel\plusone - \fi - \strc_sectioning_empty_correction - \headparameter\c!after - \strc_sectioning_depth_correction - \fi} - -\protected\def\strc_sectioning_prevent_page_break % see strc-con - {\ifconditional\c_strc_sectioning_auto_break - \spac_vspacing_same_page\currentheadlevel\plustwo - \fi} - - -% We do support negative numbers but it can have side effects that we won't catch: -% -% \chapter{some} \setupheadnumber[chapter][3] \chapter{more} -% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d} - -\permanent\def\thenamedheadlevel#1% - {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}} - -\permanent\tolerant\protected\def\setupheadnumber[#1]#*[#2]% todo: reset if at other level - {\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}} - -\def\currentheadnumber{0} % ==> \currentheadnumber - -\permanent\protected\def\determineheadnumber[#1]% - {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}} - -% The previous macro is been replaced by the expandable: - -\permanent\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}} -\permanent\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}} - -\permanent\tolerant\protected\def\headnumber[#1]#*[#2]% simple case is just a number - {\getsomefullstructurenumber{\ifparameter#1\or\thenamedheadlevel{#1}\fi}{#2}} - -\permanent\tolerant\protected\def\someheadnumber[#1]#*[#2]% - {\dontleavehmode - \begingroup - \edef\currenthead{#1}% - \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}% - \endgroup} - -\aliased\let\sectioncountervalue\structurevalue - -\def\currentheadtext{obsolete,\space use marks} - -% list references, will be redone in lua when we need it - -\let\startlistreferences\relax -\let\stoplistreferences \relax - -% experimental - -\newconditional\c_strc_sectioning_auto_levels - -\appendtoks - \settrue\c_strc_sectioning_auto_levels -\to \everyenableelements - -\protected\def\strc_sectioning_initialize_autolevel - {\ifconditional\c_strc_sectioning_auto_levels - \clf_autonextstructurelevel\currentheadlevel\relax - \global\setfalse\c_strc_sectioning_auto_levels - \fi} - -\permanent\protected\def\triggerautostructurelevel - {\global\settrue\c_strc_sectioning_auto_levels} - -\permanent\protected\def\finalizeautostructurelevels - {\clf_autofinishstructurelevels} - -\permanent\protected\def\finalizeautostructurelevel - {\dostoptagged - \dostoptagged} - -\appendtoks - \finalizeautostructurelevels -\to \everystoptext - -\stopcontextdefinitioncode - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-syn.mkxl b/tex/context/base/mkiv/strc-syn.mkxl deleted file mode 100644 index d658e5467..000000000 --- a/tex/context/base/mkiv/strc-syn.mkxl +++ /dev/null @@ -1,658 +0,0 @@ -%D \module -%D [ file=strc-syn, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Synonyms and Sorting, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting} - -\registerctxluafile{strc-syn}{} - -%D Although we could nowadays build this on top of regular lists we keep this -%D more efficient variant around. Eventually we can add some options to lists -%D that also provide such functionality but at the cost of much more overhead. -%D -%D We show a usage of both synonyms and sorts, which are deep down variants of -%D so called simple lists. A definition looks like this: -%D -%D \startbuffer -%D \definesynonyms -%D [myabbreviation] -%D -%D \setupsynonyms -%D [myabbreviation] -%D [headstyle=bold, -%D headcolor=darkred, -%D synonymstyle=boldslanted, -%D synonymcolor=darkblue, -%D textstyle=slanted, -%D textcolor=darkgreen, -%D style=normal, -%D color=darkyellow] -%D -%D \definesorting -%D [mylogo] -%D -%D \setupsorting -%D [mylogo] -%D [style=bold, -%D color=darkmagenta] -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D More complex definitions involves commands to call up meanings and such. The -%D use of the defined commands is as follows: \ -%D -%D \startbuffer -%D \myabbreviation [FIRST] {TheFirst} {The First Words} -%D \myabbreviation [SECOND] {TheSecond} {The Second Words} -%D \myabbreviation [THIRD] {TheThird} {The Third Words} -%D -%D \mylogo [FOURTH] {TheFourth} -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D By default a synonym is just typeset and flagges as being used, so that in -%D a list it wil be shows with its meaning. You can however also expand the -%D meaning automatically at first use: -%D -%D \startbuffer -%D \setupsynonyms[myabbreviation][alternative=first] -%D -%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. -%D -%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D We can change the order, as demonstrated in: -%D -%D \startbuffer -%D \resetshownsynonyms[myabbreviation] -%D -%D \setupsynonyms[myabbreviation][alternative=last] -%D -%D We have \FIRST\ and \THIRD\ or \FOURTH. -%D -%D We have \FIRST\ and \THIRD\ or \FOURTH. -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D A list is called up with: -%D -%D \startbuffer -%D \placelistofsynonyms[myabbreviation] -%D -%D \placelistofsorts[mylogo] -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D The lists are constructions (like descriptions are) and can be set up -%D likewise. - -% todo: add 'define only' option to descriptions, then add sorting (also based on key) -% and call to definition -> replaces this module - -\unprotect - -% split but common in lua - -\permanent\protected\def\preprocessexpansion#1#2#3#4% do this at the lua end if still needed - {\ifx#1\s!xml - \xmlstartraw - \xdef#2{#4}% - \xmlstopraw - \glet#3\s!xml - \else - \ifx#1\v!yes - \xdef#2{#4}% - \else - \xdef#2{\detokenize{#4}}% - \fi - \glet#3\s!tex - \fi} - -%D We now use a simple list variant: - -\installcorenamespace {simplelist} - -\installcommandhandler \??simplelist {simplelist} \??simplelist - -\let\setupsimplelists\setupsimplelist - -\setupsimplelists[% - %c!title=, - %c!text=, - % - %c!style=, - %c!color=, - %c!command=, - %c!align=, - % - %c!headstyle=, - %c!headcolor=, - %c!headalign=, - % - %c!titlestyle=, - %c!titlecolor=, - %c!titlecommand=, - %c!titleleft=, - %c!titleright=, - % - %c!closesymbol=, - %c!closecommand=, - % - \c!alternative=\v!left, - \c!display=\v!yes, - \c!width=7\emwidth, - \c!distance=\emwidth, - \c!titledistance=.5\emwidth, - %c!hang=, - %c!sample=, - \c!margin=\v!no, - \c!before=\startpacked, - \c!inbetween=\blank, - \c!after=\stoppacked, - %c!indentnext=, - %c!indenting=, - % - \c!expansion=\v!no, - %c!xmlsetup=, - %s!catcodes=, - \s!language=\currentmainlanguage, -] - -\appendtoks - \setfalse\c_strc_constructions_define_commands - \ifempty\currentsimplelistparent - \defineconstruction[\currentsimplelist][\s!handler=\v!simplelist,\c!level=1]% - \else - \defineconstruction[\currentsimplelist][\currentsimplelistparent][\s!handler=\v!simplelist,\c!level=1]% - \fi - \settrue\c_strc_constructions_define_commands -\to \everydefinesimplelist - -\setuvalue{\??constructioninitializer\v!simplelist}% - {\let \currentsimplelist \currentconstruction - \enforced\let\constructionparameter \simplelistparameter - \enforced\let\constructionnamespace \??simplelist - \enforced\let\detokenizedconstructionparameter\detokenizedsimplelistparameter - \enforced\let\letconstructionparameter \letsimplelistparameter - \enforced\let\useconstructionstyleandcolor \usesimpleliststyleandcolor - \enforced\let\setupcurrentconstruction \setupcurrentsimplelist} - -\setuvalue{\??constructionfinalizer\v!simplelist}% - {} - -\setuvalue{\??constructiontexthandler\v!simplelist}% - {\begingroup - \useconstructionstyleandcolor\c!headstyle\c!headcolor - \the\everyconstruction - \constructionparameter\c!headcommand - {\strut - \currentsimplelistentry}% - \endgroup} - -% And we build on top of this. - -\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi -\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi - -\definesimplelist - [\v!synonym] - [\c!state=\v!start, - %\c!synonymstyle=, - %\c!textstyle=, - %\c!headstyle=, - %\c!headcolor=, - %\c!criterium=, - \c!location=\v!left, - \c!width=5\emwidth, - \c!distance=\zeropoint, - %\c!sample=, - %\c!hang=, - %\c!align=, - %\c!before=, - %\c!inbetween=, - %\c!after=, - \c!indentnext=\v!no, - %\c!expansion=, - \c!method=] - -\aliased\let\setupsynonyms\setupsimplelist - -\permanent\tolerant\protected\def\definesynonyms[#1]#*[#2]#*[#3]#*[#4]% name plural \meaning \use - {\ifnum\lastarguments=\plusfour - \protected\instance\def#4##1{\strc_synonyms_insert{#1}{##1}}% name tag - \frozen\instance\setuvalue{#1}{\definesynonym[\v!no][#1]}% \name - \else - \frozen\instance\setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name - \fi - \ifparameter#3\or - \frozen\instance\protected\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning - \fi - \edef\currentsynonym{#1}% - % - %\checksynonymparent - %\setupcurrentsynonym[\s!single={#1},\s!multi={#2}]% - \setfalse\c_strc_constructions_define_commands - \definesimplelist - [\currentsynonym]% - [\v!sorting] - [\s!single={#1},% - \s!multi={#2}]% - \settrue\c_strc_constructions_define_commands - \ifparameter#2\or - % - \presetheadtext[#2=\Word{#2}]% changes the \if...argument - % - % These will go away. Actually the overloads catched this empty case! - % - \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsynonyms[#1]}% obsolete definition - \instance\setuvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument - \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}% - \fi} - -\permanent\tolerant\protected\def\definesynonym[#1]#*[#2]#*[#3]% - {\begingroup - \edef\currentsynonymoption{#1}% - \edef\currentsynonym{#2}% - \edef\currentsynonymtag{#3}% - \strc_synonyms_define_entry} - -\def\strc_synonyms_define_entry#1#2% - {\let\currentsimplelist\currentsynonym - \ifempty\currentsynonymtag - \edef\currentsynonymtag{#1}% - \fi - \ifempty\currentsynonymtag \else - % this is not that efficient, esp when we load a big list - \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}% - \preprocessexpansion\currentsynonymexpansion\m_synonyms_text \currentsynonymcoding{#1}% - \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#2}% - % - \clf_registersynonym - {\currentsynonym}% - {synonym}% - {% - metadata {% - catcodes \catcodetable - coding {\currentsynonymcoding}% - \ifx\currentsynonymcoding\s!xml - xmlroot {\xmldocument}% - \fi - }% - definition {% - tag {\currentsynonymtag}% - synonym {\m_synonyms_text}% - meaning {\m_synonyms_meaning}% - % used false - }% - }% - \relax - \ifx\currentsynonymoption\v!yes - \instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}% - \fi - \fi - \endgroup} - -\permanent\tolerant\protected\def\registersynonym [#1]#*[#2]{\clf_registerusedsynonym{#1}{#2}} -\permanent \protected\def\currentsynonymname {\clf_synonymname{\currentsimplelist}{\currentsynonymtag}} -\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning{\currentsimplelist}{\currentsynonymtag}} -\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused{\currentsimplelist}{\currentsynonymtag}} -\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}} -\permanent \protected\def\resetusedsynonyms [#1]{\clf_resetusedsynonyms{#1}} -\permanent \protected\def\resetshownsynonyms [#1]{\clf_resetshownsynonyms{#1}} - -\aliased\let\rawsynonymname \clf_synonymname -\aliased\let\rawsynonymmeaning\clf_synonymmeaning - -\installcorenamespace{simplelistalternative} % specific ways of rendering a list -\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local) - -\installcommandhandler \??simplelistalternative {simplelistalternative} \??simplelistalternative - -\setupsimplelist - [\v!synonym] - [\c!alternative=\v!normal] - -\protected\def\strc_synonyms_insert_meaning#1#2% name tag - {\dontleavehmode % otherwise we don't get it right at the beginning of a par - \begingroup - \def\currentsimplelist{#1}% - \def\currentsynonymtag{#2}% - \fastsetup{\??simplelistrenderings::\v!text}% - \endgroup} - -\protected\def\strc_synonyms_insert#1#2% name tag - {\dontleavehmode % otherwise we don't get it right at the beginning of a par - \begingroup - \edef\currentsimplelist{#1}% - \let\currentsynonym\currentsimplelist % for a while - \def\currentsynonymtag{#2}% - \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% - \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative - {\let\currentsimplelistalternative\v!normal}% - \fastsetup{\??simplelistrenderings:\v!synonym:\currentsimplelistalternative}% - \normalexpanded{\endgroup\simplelistparameter\c!next}} - -% \setupsimplelistalternative -% [\c!command=\directsimplelistparameter\c!command] - -\definesimplelistalternative - [\v!normal] - [\c!inbetween=\space, - \c!left=(, - \c!right=)] - -\definesimplelistalternative - [\v!first] - [\v!normal] - -\definesimplelistalternative - [\v!last] - [\v!normal] - -\startsetups[\??simplelistrenderings::\v!synonym] - \begingroup - \dostarttaggedchained\t!synonym\currentsynonym\??simplelist - \dotagsynonym - \usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor - \simplelistparameter\c!synonymcommand{\currentsynonymname}% - \dostoptagged - \endgroup -\stopsetups - -\startsetups[\??simplelistrenderings::\v!text] - \begingroup - \usehyphensparameter\simplelistparameter - \usesimpleliststyleandcolor\c!textstyle\c!textcolor - \simplelistparameter\c!textcommand{\currentsynonymmeaning}% - \endgroup -\stopsetups - -\startsetups[\??simplelistrenderings:\v!synonym:\v!normal] - \fastsetup{\??simplelistrenderings::\v!synonym} -\stopsetups - -\startsetups[\??simplelistrenderings:\v!synonym:\v!first] - \fastsetup{\??simplelistrenderings::\v!synonym} - \doifelsecurrentsynonymshown \donothing { - \simplelistalternativeparameter\c!inbetween - \simplelistalternativeparameter\c!left - \fastsetup{\??simplelistrenderings::\v!text} - \simplelistalternativeparameter\c!right - } -\stopsetups - -\startsetups[\??simplelistrenderings:\v!synonym:\v!last] - \doifelsecurrentsynonymshown { - \fastsetup{\??simplelistrenderings::\v!synonym} - } { - \fastsetup{\??simplelistrenderings::\v!text} - \simplelistalternativeparameter\c!inbetween - \simplelistalternativeparameter\c!left - \fastsetup{\??simplelistrenderings::\v!synonym} - \simplelistalternativeparameter\c!right - } -\stopsetups - -\permanent\tolerant\protected\def\placelistofsynonyms[#1]#*[#2]% - {\begingroup - \edef\currentsimplelist{#1}% - \doifelsecommandhandler\??simplelist\currentsimplelist - {\strc_constructions_initialize{#1}% - \setupcurrentsimplelist[#2]% - \let\synonymentry\strc_synonym_normal - % so we can hook tabulate into before and after - \normalexpanded{\simplelistparameter\c!before - \noexpand\clf_processsynonyms - {#1}% - {% - criterium {\simplelistparameter\c!criterium}% - language {\simplelistparameter\s!language}% - method {\simplelistparameter\c!method}% - }% - \relax - \simplelistparameter\c!after}% - \relax}% - {}% todo: message that invalid - \endgroup} - -\permanent\tolerant\protected\def\completelistofsynonyms[#1]#*[#2]% - {\begingroup - \edef\currentsimplelist{#1}% - \doifelsecommandhandler\??simplelist\currentsimplelist - {\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% - \strc_synonyms_place_list[#1][#2]% - \page - \stopnamedsection}% - {}% todo: message that invalid - \endgroup} - -\protected\def\strc_synonym_normal#1#2#3#4% - {\begingroup - \def\currentsimplelistentry{#3}% - \csname\??constructionstarthandler\v!construction\endcsname - #4% - \csname\??constructionstophandler\v!construction\endcsname - \endgroup} - -%D Sorting (a simplified version of synonym). - -\definesimplelist - [\v!sorting] - [\c!state=\v!start, - %\c!command=, % we test for defined ! - %\c!criterium=, - %\c!style=, - \c!before=\startpacked, - \c!after=\stoppacked, - %\c!expansion=, - \c!method=] - -\aliased\let\setupsorting\setupsimplelist - -% if #3=\relax or \v!none, then no command but still protected - -\permanent\tolerant\protected\def\definesorting[#1]#*[#2]#*[#3]% - {\ifnum\lastarguments=\plusthree - \doifnot{#3}\v!none - {\ifx#3\relax \else - \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}% - \fi}% - \frozen\instance\setuvalue{#1}{\definesort[\v!no][#1]}% - \else - \frozen\instance\setuvalue{#1}{\definesort[\v!yes][#1]}% - \fi - \edef\currentsorting{#1}% - \setfalse\c_strc_constructions_define_commands - \definesimplelist - [\currentsorting]% - [\v!sorting] - [\s!single={#1},% - \s!multi={#2}]% - \settrue\c_strc_constructions_define_commands - \ifparameter#2\or - % - \presetheadtext[#2=\Word{#2}]% changes the \if...argument - % - % These will go away. Actually the overloads catched this empty case! - % - % - \presetheadtext[#2=\Word{#2}]% after \ifthirdargument -) - % - \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition - \instance\setuvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}% - \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}% - \fi} - -\permanent\tolerant\protected\def\definesort[#1]#*[#2]#*[#3]% - {\begingroup - \edef\currentsortingoption{#1}% - \edef\currentsorting{#2}% - \edef\currentsortingtag{#3}% - \strc_sorting_define_entry} - -\def\strc_sorting_define_entry#1% - {\let\currentsimplelist\currentsimplelist - \ifempty\currentsortingtag - \edef\currentsortingtag{#1}% - \fi - \ifempty\currentsortingtag \else - \edef\currentsortingexpansion{\simplelistparameter\c!expansion}% - \preprocessexpansion\currentsortingexpansion\currentsortingtext\currentsortingcoding{#1}% - \clf_registersynonym - {\currentsorting}% - {sorting}% - {% - metadata {% - catcodes \catcodetable - coding {\currentsortingcoding}% - \ifx\currentsortingcoding\s!xml - xmlroot {\xmldocument}% - \fi - }% - definition {% - tag {\currentsortingtag}% - synonym {\currentsortingtext}% - % used false - }% - }% - \relax - \ifx\currentsortingoption\v!yes - \instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}% - \fi - \fi - \endgroup} - -\permanent\protected\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}} -\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}} -\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}} - -\setupsimplelist - [\v!sorting] - [\c!alternative=\v!normal] - -\protected\def\strc_sorting_insert#1#2% name tag - {\dontleavehmode % otherwise we don't get it right at the beginning of a par - \begingroup - % no kap currently, of .. we need to map cap onto WORD - \edef\currentsorting{#1}% - \edef\currentsortingtag{#2}% - \let\currentsimplelist\currentsorting - \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% - \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative - {\let\currentsimplelistalternative\v!normal}% - \fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}% - \normalexpanded{\endgroup\simplelistparameter\c!next}} - -% or: -% -% \doifelsesetups{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative} -% {\fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}} -% {\fastsetup{\??simplelistrenderings:\v!sorting:\v!normal}} - -\startsetups [\??simplelistrenderings:\v!sorting:\v!normal] - \fastsetup{\??simplelistrenderings::\v!sorting}% -\stopsetups - -\startsetups [\??simplelistrenderings::\v!sorting] - \begingroup - \dostarttaggedchained\t!sorting\currentsorting\??simplelist - \dotagsorting - \usesimpleliststyleandcolor\c!style\c!color - \currentsortingname - \dostoptagged - \endgroup -\stopsetups - -\permanent\tolerant\protected\def\registersort[#1]#*[#2]% - {\clf_registerusedsynonym{#1}{#2}} - -% before after -% -% maybe just 'commandset' and then combine - -\permanent\tolerant\protected\def\placelistofsorts[#1]#*[#2]% - {\begingroup - \edef\currentsimplelist{#1}% - \strc_constructions_initialize{#1}% - \setupcurrentsimplelist[#2]% - \edef\p_simplelist_command{\simplelistparameter\c!command}% - \ifempty\p_simplelist_command - \let\synonymentry\strc_sorting_normal - \else - \let\synonymentry\strc_sorting_command - \fi - % so we can hook tabulate into before and after - \normalexpanded{\simplelistparameter\c!before - \noexpand\clf_processsynonyms - {#1}% - {% - criterium {\simplelistparameter\c!criterium}% - language {\simplelistparameter\s!language}% - method {\simplelistparameter\c!method}% - }% - \relax - \simplelistparameter\c!after}% - \endgroup} - -\permanent\tolerant\protected\def\completelistofsorts[#1]#*[#2]% - {\begingroup - \edef\currentsimplelist{#1}% - \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% - \strc_sorting_place_list[#1][#2]% - \page - \stopnamedsection - \endgroup} - -\def\strc_sorting_command#1#2#3#4% #4 is meaning but empty here - {\p_simplelist_command{#1}{#2}{#3}} - -\def\strc_sorting_normal#1#2#3#4% #4 is meaning but empty here - {\begingroup - \usesimpleliststyleandcolor\c!style\c!color - #3% - \endgroup - \par} - -%D Presets. - -% To be considered: -% -% \setupsimplelist -% [\v!sorting] -% [\c!headstyle=\simplelistparameter\c!synonymstyle, -% \c!headcolor=\simplelistparameter\c!synonymcolor, -% \c!style=\simplelistparameter\c!textstyle, -% \c!color=\simplelistparameter\c!textcolor] - -\definesynonyms - [\v!abbreviation] - [\v!abbreviations] - [\infull] - -\setupsynonyms - [\v!abbreviation] - [\c!hyphens=\v!no, % new, not yet in setup definitions - \c!textstyle=\v!capital] - -\definesorting - [\v!logo] - [\v!logos] -% [\logogram] % no - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-tag.lmt b/tex/context/base/mkiv/strc-tag.lmt deleted file mode 100644 index 11049abe0..000000000 --- a/tex/context/base/mkiv/strc-tag.lmt +++ /dev/null @@ -1,615 +0,0 @@ -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 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 texgetattribute = tex.getattribute -local texsetattribute = tex.setattribute - -local taglist = allocate() -- access by attribute -local specifications = allocate() -- access by fulltag -local labels = allocate() -local stack = { } -local chain = { } -local ids = { } -local enabled = false -local tagcontext = { } -local tagpatterns = { } -local lasttags = { } -local stacksize = 0 -local metadata = nil -- applied to the next element -local documentdata = { } -local extradata = false - -local tags = structures.tags -tags.taglist = taglist -- can best be hidden -tags.labels = labels -tags.patterns = tagpatterns -tags.specifications = specifications - -function tags.current() - if stacksize > 0 then - return stack[stacksize] -- maybe copy or proxy - end -end - --- Tags are internally stored as: --- --- 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 { -- todo: more "record = true" to improve formatting - - 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" }, - sectioncaption = { pdf = "Div", nature = "display", record = true }, - 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" }, - linenumber = { pdf = "Span", nature = "inline" }, - - 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" }, - tableheadcell = { pdf = "TH", nature = "mixed" }, - tablehead = { pdf = "THEAD", nature = "display" }, - tablebody = { pdf = "TBODY", nature = "display" }, - tablefoot = { pdf = "TFOOT", nature = "display" }, - - tabulate = { pdf = "Table", nature = "display" }, - tabulaterow = { pdf = "TR", nature = "display" }, - tabulatecell = { pdf = "TD", nature = "mixed" }, - tabulateheadcell = { pdf = "TH", nature = "mixed" }, - tabulatehead = { pdf = "THEAD", nature = "display" }, - tabulatebody = { pdf = "TBODY", nature = "display" }, - tabulatefoot = { pdf = "TFOOT", nature = "display" }, - - 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" }, - listtext = { pdf = "Span", nature = "inline" }, - - 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" }, - reference = { pdf = "Span", nature = "inline" }, - - margintextblock = { pdf = "Span", nature = "inline" }, - margintext = { pdf = "Span", nature = "inline" }, - marginanchor = { pdf = "Span", nature = "inline" }, - - math = { pdf = "Div", nature = "inline" }, -- no display - mn = { pdf = "Span", nature = "mixed" }, - 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" }, - - publications = { pdf = "Div", nature = "display" }, - publication = { pdf = "Div", nature = "mixed" }, - pubfld = { pdf = "Span", nature = "inline" }, - - block = { pdf = "Div", nature = "display" }, - userdata = { pdf = "Div", nature = "display" }, - -} - -tags.properties = properties - -local patterns = setmetatableindex(function(t,tag) - local v = topattern("^" .. tag .. ">") - t[tag] = v - return v -end) - -function tags.locatedtag(tag) - local attribute = texgetattribute(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[texgetattribute(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.getmetadata() - return documentdata or { } -end - -function tags.registerextradata(name,serializer) - if type(serializer) == "function" then - if extradata then - extradata[name] = serializer - else - extradata = { [name] = serializer } - end - end -end - -function tags.getextradata() - return extradata -end - -function tags.start(tag,specification) - if not enabled then - codeinjections.enabletags() - 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 userdata == "" then - specification.userdata = nil - elseif 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 - -- - texsetattribute(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 - texsetattribute(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 - texsetattribute(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 = "strc_tags_start", - public = true, - protected = true, - actions = starttag, - arguments = "argument", -} - -implement { - name = "strc_tags_stop", - public = true, - protected = true, - actions = tags.stop, -} - -implement { - name = "strc_tags_start_userdata", - public = true, - protected = true, - actions = function(tag,userdata) starttag(tag,{ userdata = userdata }) end, - arguments = { "optional", "optional" }, -} - -implement { - name = "strc_tags_start_detail", - public = true, - protected = true, - actions = function(tag,detail) starttag(tag,{ detail = detail }) end, - arguments = "2 arguments", -} - -implement { - name = "strc_tags_start_ignore", - public = true, - protected = true, - actions = function(detail) starttag("ignore",{ detail = detail }) end, - arguments = { "argument" }, -} - -implement { - name = "strc_tags_start_chained", - public = true, - protected = true, - actions = function(tag,detail,parents) starttag(tag,{ detail = detail, parents = parents }) end, - arguments = "3 arguments", -} - -implement { - name = "strc_tags_set_aspect", - public = true, - protected = true, - actions = tags.setaspect, - arguments = "2 arguments" -} - -implement { - name = "settagproperty", - actions = tags.setproperty, - arguments = "3 arguments" -} - -implement { - name = "setelementbackendtag", - public = true, - protected = true, - actions = tags.setproperty, - arguments = { "optional", "'backend'", "optional" }, -} - -implement { - name = "setelementnature", - public = true, - protected = true, - actions = tags.setproperty, - arguments = { "optional", "'nature'", "optional" }, -} - -implement { - name = "strc_tags_get_element_tag", - public = true, - protected = true, - actions = { tags.elementtag, context } -} - -implement { - name = "strc_tags_set_element_user_properties", - public = true, - protected = true, - actions = tags.setuserproperties, - arguments = { "optional", "optional" }, -} - -implement { - name = "doifelseinelement", - public = true, - protected = true, - actions = { structures.atlocation, commands.testcase }, - arguments = "argument", -} - -implement { - name = "settaggedmetadata", - public = true, - protected = true, - actions = tags.registermetadata, - arguments = "optional", -} diff --git a/tex/context/base/mkiv/strc-tag.mkxl b/tex/context/base/mkiv/strc-tag.mkxl deleted file mode 100644 index 08d8fef6c..000000000 --- a/tex/context/base/mkiv/strc-tag.mkxl +++ /dev/null @@ -1,531 +0,0 @@ -%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}{autosuffix} - -\unprotect - -%D Eventually these labels will either move to the modules where they're used, or -%D they will en dup in mult-tag. - -\definetagconstant{document} % Div - -\definetagconstant{division} % Div -\definetagconstant{paragraph} % P -\definetagconstant{p} % P -\definetagconstant{construct} % Span -\definetagconstant{highlight} % Span - -\definetagconstant{section} % Sect -\definetagconstant{sectioncaption} % Div -\definetagconstant{sectiontitle} % H -\definetagconstant{sectionnumber} % H -\definetagconstant{sectioncontent} % Div - -\definetagconstant{itemgroup} % L -\definetagconstant{item} % Li -\definetagconstant{itemtag} % Lbl -\definetagconstant{itemcontent} % LBody -\definetagconstant{itemhead} % Div -\definetagconstant{itembody} % Div - -\definetagconstant{description} % Li -\definetagconstant{descriptiontag} % Lbl -\definetagconstant{descriptioncontent} % LBody -\definetagconstant{descriptionsymbol} % Span - -\aliastagconstant{construction} {description} -\aliastagconstant{constructiontag} {descriptiontag} -\aliastagconstant{constructioncontent}{descriptioncontent} -\aliastagconstant{constructionsymbol} {descriptionsymbol} - -\definetagconstant{verbatimblock} % Code -\definetagconstant{verbatimlines} % Code -\definetagconstant{verbatimline} % Code -\definetagconstant{verbatim} % Code - -\definetagconstant{lines} % Code -\definetagconstant{line} % Code -\definetagconstant{linenumber} % Span - -\definetagconstant{sorting} % Span -\definetagconstant{synonym} % Span - -\definetagconstant{register} % Div -\definetagconstant{registerlocation} % Span -\definetagconstant{registersection} % Div -\definetagconstant{registertag} % Span -\definetagconstant{registerentries} % Div -\definetagconstant{registerentry} % Span -\definetagconstant{registercontent} % Span -\definetagconstant{registersee} % Span -\definetagconstant{registerpages} % Span -\definetagconstant{registerpage} % Span -\definetagconstant{registerpagerange} % Span -\definetagconstant{registerfrompage} % Span -\definetagconstant{registertopage} % Span -\definetagconstant{registerseparator} % Span - -\definetagconstant{table} % Table -\definetagconstant{tablerow} % TR -\definetagconstant{tablecell} % TD -\definetagconstant{tableheadcell} % TH -\definetagconstant{tablehead} % THEAD -\definetagconstant{tablebody} % TBODY -\definetagconstant{tablefoot} % TFOOT - -\definetagconstant{tabulate} % Table -\definetagconstant{tabulaterow} % TR -\definetagconstant{tabulatecell} % TD -\definetagconstant{tabulateheadcell} % TH -\definetagconstant{tabulatehead} % THEAD -\definetagconstant{tabulatebody} % TBODY -\definetagconstant{tabulatefoot} % TFOOT - -\definetagconstant{math} % math -\definetagconstant{mtable} % Table -\definetagconstant{mtr} % TR -\definetagconstant{mtd} % TD -\definetagconstant{maction} % -\definetagconstant{mstacker} -\definetagconstant{mstackertop} -\definetagconstant{mstackermid} -\definetagconstant{mstackerbot} - -\aliastagconstant{mtablerow} {mtr} -\aliastagconstant{mtablecell}{mtd} - -\definetagconstant{munderover} % special cases -\definetagconstant{munder} % special cases -\definetagconstant{mover} % special cases - -\definetagconstant{list} % TOC -\definetagconstant{listitem} % TOCI -\definetagconstant{listtag} % Lbl -\definetagconstant{listcontent} % P -\definetagconstant{listdata} % P -\definetagconstant{listpage} % Reference -\definetagconstant{listtext} % Span - -\definetagconstant{delimited} % BlockQuote -%definetagconstant{delimited} % Quote -\definetagconstant{delimitedsymbol} % Span -\definetagconstant{delimitedcontent} % Span - -\aliastagconstant{delimitedblock}{delimited} - -\definetagconstant{subsentence} % Span -\definetagconstant{subsentencecontent} % Span -\definetagconstant{subsentencesymbol} % Span - -\definetagconstant{float} % Div -\definetagconstant{floatcaption} % Caption -\definetagconstant{floatlabel} % Span -\definetagconstant{floattext} % Span -\definetagconstant{floatnumber} % Span -\definetagconstant{floatcontent} % P - -\definetagconstant{image} % P - -\definetagconstant{mpgraphic} % P - -\definetagconstant{formulaset} % Div -\definetagconstant{formula} % Div -\definetagconstant{formulacaption} % Span -\definetagconstant{formulalabel} % Span -\definetagconstant{formulanumber} % P -\definetagconstant{formulacontent} % P -\definetagconstant{subformula} % Div - -\definetagconstant{link} % Link -\definetagconstant{reference} % Span - -\definetagconstant{margintext} % Span -\definetagconstant{margintextblock} % Div -\definetagconstant{marginanchor} % Span - -% we might opt for verbose variants so this is experimental: - -\definetagconstant{label} % Span -\definetagconstant{number} % Span - -\definetagconstant{ignore} % Span -\definetagconstant{private} % Span - -\definetagconstant{mid} % Span -\definetagconstant{sub} % Span -\definetagconstant{sup} % Span -\definetagconstant{subsup} % Span - -\definetagconstant{unit} % Span -\definetagconstant{quantity} % Span -%definetagconstant{number} % Span - -\definetagconstant{combination} % Span -\definetagconstant{combinationpair} % Span -\definetagconstant{combinationcontent} % Span -\definetagconstant{combinationcaption} % Span - -\definetagconstant{publications} % Span -\definetagconstant{publication} % Span -\definetagconstant{pubfld} % Span - -\definetagconstant{block} % Div -\definetagconstant{userdata} % Div - -% \setuptaglabeltext -% [en] -% [\t!document=document] - -% the real code - -\definesystemattribute[tagged][public] -\definesystemattribute[image] [public] - -% \setelementbackendtag [#1][#2] % define at the lua end -% \setelementnature [#1][#2] % define at the lua end - -\permanent\protected\def\ignoretagsinexport[#1]{\clf_ignoretagsinexport{#1}} % todo: public implementor - -\installcorenamespace{tagging} - -\installsetuponlycommandhandler \??tagging {tagging} - -\def\strc_tags_report_hyphen#1% - {\writestatus\m!languages{setting #1 to U+00AD}} - -\protected\def\strc_tags_patch_hyphen - {% for the moment here - \ifnum\languageparameter\s!lefthyphenchar>\zerocount - \setuplanguage[\s!default][\s!lefthyphenchar="AD]% - \strc_tags_report_hyphen\s!lefthyphenchar - \fi - \ifnum\languageparameter\s!righthyphenchar>\zerocount - \setuplanguage[\s!default][\s!righthyphenchar="AD]% - \strc_tags_report_hyphen\s!righthyphenchar - \fi - \let\strc_tags_report_hyphen\gobbleoneargument} - -% 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. - -% \strc_tags_start_userdata % defined at the lua end -% \strc_tags_stop % defined at the lua end -% \strc_tags_set_aspect % defined at the lua end -% \strc_tags_get_element_tag % defined at the lua end -% \strc_tags_set_element_user_properties % defined at the lua end - -\permanent\protected\def\strc_tags_element_start_yes - {\iftrialtypesetting - \expandafter\gobbletwooptionals - \else - \expandafter\strc_tags_start_userdata - \fi} - -\permanent\protected\def\strc_tags_element_stop_yes - {\iftrialtypesetting - % nothing - \else - \expandafter\strc_tags_stop - \fi} - -\protected\def\strc_tags_enable_elements - {\strc_tags_patch_hyphen - \enforced\let\startelement \strc_tags_element_start_yes - \enforced\let\stopelement \strc_tags_element_stop_yes - \enforced\let\dosettagproperty\strc_tags_set_aspect} - -\protected\def\strc_tags_disable_elements - {\enforced\let\startelement \gobbletwooptionals - \enforced\let\stopelement \relax - \enforced\let\dosettagproperty\gobbletwoarguments} - -% beware: making these unexpanded spoils tables (noalign problem) - -\def\strc_tags_enabled_start_no_detail - {\iftrialtypesetting - \expandafter\gobbleoneargument - \else - \expandafter\strc_tags_start - \fi} - -\def\strc_tags_enabled_start_detail - {\iftrialtypesetting - \expandafter\gobbletwoarguments - \else - \expandafter\strc_tags_start_detail - \fi} - -\def\strc_tags_enabled_start_chained - {\iftrialtypesetting - \expandafter\gobblethreearguments - \else - \expandafter\strc_tags_start_chained_indeed - \fi} - -\def\strc_tags_enabled_start_ignore - {\iftrialtypesetting - \expandafter\gobbleoneargument - \else - \expandafter\strc_tags_start_ignore - \fi} - -\def\strc_tags_enabled_stop - {\iftrialtypesetting - % do nothing - \else - \expandafter\strc_tags_stop - \fi} - -\def\strc_tags_start_chained_indeed#1#2#3{\strc_tags_start_chained{#1}{#2}{\getcurrentparentchain#3{#2}}} - -\newconditional\c_strc_tags_enabled - -\permanent\let\dotaggedplaceholder\empty - -\immutable\chardef\strc_tags_placeholder_char\zerocount % "FFFC - -\protected\def\strc_tags_enable_indeed - {\enforced\let\dotaggedplaceholder \strc_tags_placeholder_char - \enforced\let\dostarttagged \strc_tags_enabled_start_detail - \enforced\let\dostarttaggednodetail\strc_tags_enabled_start_no_detail - \enforced\let\dostarttaggedchained \strc_tags_enabled_start_chained - \enforced\let\dostoptagged \strc_tags_enabled_stop - \enforced\let\dostartignoretagging \strc_tags_enabled_start_ignore - \enforced\let\dostopignoretagging \strc_tags_stop} - -\protected\def\strc_tags_enable - {% once enable one is toast - \global\settrue\c_strc_tags_enabled - % and gets: - \strc_tags_enable_indeed} - -\protected\def\strc_tags_disable - {\ifconditional\c_strc_tags_enabled - % so now all are artifacts - \enforced\let\dotaggedplaceholder \strc_tags_placeholder_char - \enforced\let\dostarttagged \gobbletwoarguments - \enforced\let\dostarttaggednodetail\gobbleoneargument - \enforced\let\dostarttaggedchained \gobblethreearguments - \enforced\let\dostoptagged \donothing - \else - % initial - \enforced\let\dotaggedplaceholder \empty - \enforced\let\dostarttagged \gobbletwoarguments - \enforced\let\dostarttaggednodetail\gobbleoneargument - \enforced\let\dostarttaggedchained \gobblethreearguments - \enforced\let\dostoptagged \donothing - \enforced\let\dostartignoretagging \donothing - \enforced\let\dostopignoretagging \donothing - \fi} - -% for luigi (beware: fully expandable): - -\protected\def\strc_tags_setup_element_user_properties - {\iftrialtypesetting - \expandafter\gobbletwooptionals - \else - \expandafterstrc_set_element_user_properties - \fi} - -\protected\def\strc_tags_enable_properties - {\enforced\let\getelementtag \strc_tags_get_element_tag - \enforced\let\setupelementuserproperties\strc_tags_set_element_user_properties} - -\protected\def\strc_tags_disable_properties - {\enforced\let\getelementtag \donothing - \enforced\let\setupelementuserproperties\gobbletwooptionals} - -%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 - -\permanent\protected\def\forgettagging - {\c_attr_tagged\attributeunsetvalue} - -\setuptagging - [\c!state=\v!stop, - \c!method=\v!auto] - -% 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=] - -\ifdefined\dotagparagraph \else \let\dotagparagraph\gobbleoneargument \fi - -\permanent\tolerant\protected\def\startparagraph[#1]#*[#2]% - {\endgraf % we end before the group - \begingroup - \ifarguments - \let\currentparagraph\empty - \or - \ifhastok={#1}% - \let\currentparagraph\empty - \setupcurrentparagraph[#1] - \else - \edef\currentparagraph{#1}% - \fi - \or - \edef\currentparagraph{#1}% - \setupcurrentparagraph[#2]% - \fi - \useparagraphstyleandcolor\c!style\c!color - \usealignparameter\paragraphparameter - \usesetupsparameter\paragraphparameter - \dostarttagged\t!paragraph\currentparagraph - \dotagparagraph{\paragraphparameter\c!align}} - -\permanent\protected\def\stopparagraph - {\dostoptagged - \endgraf % we end inside the group - \endgroup} - -\aliased\let\startpar\startparagraph -\aliased\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 - -% This doesn't work well either, so instead we handle the ornaments in the tagging -% in a different way (see attr -> false code). - -% \appendtoks -% \dostartignoretagging -% \to \everybeforepagebody -% -% \appendtoks -% \dostopignoretagging -% \to \everyafterpagebody - -% \doifelseinelement{structure:section} {yes} {no} -% \doifelseinelement{structure:chapter} {yes} {no} -% \doifelseinelement{division:*-structure:chapter} {yes} {no} - -\aliased\let\doifinelementelse\doifelseinelement % define at the lua end - -\permanent\protected\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} - -\permanent\protected\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 here we get some as -%D child of the document root and some as child 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 - -% \settaggedmetadata[#1] % define at the lua end - -%D An overload: - -\pushoverloadmode - -\aliased\let\strc_tagged_saved_bpar\bpar -\aliased\let\strc_tagged_saved_epar\epar - -\enforced\permanent\protected\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar} -\enforced\permanent\protected\def\epar{\strc_tagged_saved_epar\dostoptagged} - -\popoverloadmode - -% \permanent\def\untagged{attr \taggedattribute\attributeunsetvalue} - -\protect diff --git a/tex/context/base/mkiv/strc-tnt.mkxl b/tex/context/base/mkiv/strc-tnt.mkxl deleted file mode 100644 index 4129117f0..000000000 --- a/tex/context/base/mkiv/strc-tnt.mkxl +++ /dev/null @@ -1,117 +0,0 @@ -%D \module -%D [ file=strc-tnt, -%D version=2019.05.30, % based on older code -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Text 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. - -\unprotect - -%D \macros -%D {definetextnote,setuptextnote} -%D -%D \startbuffer -%D \definetextnote -%D [textnote] -%D -%D \startbuffer -%D Test test test \textnote [n=5] {alpha}. test test test test tets test test -%D \textnote [n=10] {beta}. Test test test test tets test test \textnote [n=12] -%D {gamma}. Test test test test tets test test \textnote [n=24] {delta}. Test test -%D test test test test \textnote {epsilon} test test \textnote [n=*] {zeta}. -%D \stopbuffer -%D -%D \blank {\setuptextnote[empty=yes] \getbuffer\par} \blank -%D \blank {\setuptextnote[empty=number] \getbuffer\par} \blank -%D \blank {\setuptextnote[empty=none] \getbuffer\par} \blank -%D \blank { \getbuffer\par} \blank -%D -%D \blank[2*big] -%D -%D \placenotes[textnote:note][criterium=text] -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\installcorenamespace{textnote} - -\installcommandhandler \??textnote {textnote} \??textnote - -\definebar - [\v!textnote:\v!underbar] - [\v!underbar] - -\definenote - [\v!textnote:\v!note] - -\setuptextnote - [\c!rule=\v!textnote:\v!underbar, - \c!note=\v!textnote:\v!note, - \c!n=10] % * will use the real space - -\appendtoks - \frozen\instance\setuevalue{\currenttextnote}{\educ_textnote[\currenttextnote]}% -\to \everydefinetextnote - -\tolerant\protected\def\educ_textnote[#1]#*[#2]#:#3% - {\dontleavehmode - \begingroup - \def\currenttextnote{#1}% - \ifparameter#2\or\setupcurrenttextnote[#2]\fi - \edef\p_n{\textnoteparameter\c!n}% - \edef\p_empty{\textnoteparameter\c!empty}% - \edef\currentbar{\textnoteparameter\c!rule}% - \edef\currentnote{\textnoteparameter\c!note}% - \ifx\p_n\wildcardsymbol - \donefalse - \ifx\p_empty\v!yes - \donetrue - \orelse\ifx\p_empty\v!number - \donetrue - \orelse\ifx\p_empty\v!none - \donetrue - \fi - \ifdone - \setupbar[\currentbar][\c!empty=\v!yes]% - \fi - \inlinebar[\currentbar]\bgroup - \wordboundary#3% - \ifx\p_empty\v!yes - \setnotetext[\currentnote]{#3}% - \orelse\ifx\p_empty\v!number - \runninghbox{\resetbar\setnote[\currentnote]{#3}}% - \orelse\ifx\p_empty\v!none - \setupnote[\currentnote][\c!location=\v!none]% - \runninghbox{\resetbar\setnote[\currentnote]{#3}}% - \fi - \egroup - \else - \inlinebar[\currentbar]\bgroup - \scratchcounter\numexpr\p_n/\plustwo\relax - \ifx\p_empty\v!yes - \interwordspacesbefore\scratchcounter - \setnotetext[\currentnote]{#3}% - \interwordspacesafter\scratchcounter - \orelse\ifx\p_empty\v!number - \interwordspacesbefore\scratchcounter - \zwnj\runninghbox{\resetbar\setnote[\currentnote]{#3}}\zwnj - \interwordspacesafter\scratchcounter - \orelse\ifx\p_empty\v!none - \setupnote[\currentnote][\c!location=\v!none]% - \interwordspacesbefore\scratchcounter - \zwnj\runninghbox{\resetbar\setnote[\currentnote]{#3}}\zwnj - \interwordspacesafter\scratchcounter - \else - #3% - \fi - \egroup - \fi - \endgroup} - -\protect \endinput diff --git a/tex/context/base/mkiv/strc-usr.mkxl b/tex/context/base/mkiv/strc-usr.mkxl deleted file mode 100644 index 28d398194..000000000 --- a/tex/context/base/mkiv/strc-usr.mkxl +++ /dev/null @@ -1,169 +0,0 @@ -%D \module -%D [ file=strc-bkm, -%D version=2009.04.01, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Bookmarks, -%D author=Wolfgang Schuster, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Structure Macros / Userdata} - -\registerctxluafile{strc-usr}{} - -%D It's a bit like blocks that also use buffers but more lightweight and with -%D inplace settings. -%D -%D \starttyping -%D \defineuserdata [test] [style=italic] -%D -%D \samplefile{klein} -%D -%D \startuserdata [before=\blank,after=\blank,color=red] -%D \samplefile{greenfield} -%D \stopuserdata -%D -%D \samplefile{sapolsky} -%D -%D \startuserdata [test] -%D \samplefile{bryson} -%D \stopuserdata -%D -%D \samplefile{jojomayer} -%D -%D \startuserdata [test] [before=\blank,after=\blank,color=red] -%D \samplefile{linden} -%D \stopuserdata -%D -%D \samplefile{montgomery} -%D \stoptyping -%D -%D Or from \LUA: -%D -%D \starttyping -%D \startluacode -%D context.startuserdata({color="blue"}) -%D context.samplefile("klein") -%D context.stopuserdata() -%D \stopluacode -%D \stoptyping -%D -%D An example of an alternative: -%D -%D \starttyping -%D \defineuserdataalternative [epigraph] [renderingsetup=userdata:epigraph] -%D -%D \startsetups [userdata:epigraph] -%D \startframedtext [location=right,frame=off,align={flushleft,broad},style=\tfx,offset=.25ex,width=.5\textwidth] -%D \begstrut\inlinebuffer[userdata]\endstrut -%D \hairline -%D \wordright{\userdataparameter{author}} -%D \stopframedtext -%D \stopsetups -%D -%D \defineuserdata -%D [epigraph] -%D [alternative=epigraph] -%D -%D \startuserdata [epigraph] [author={Sean B. Carrol}] -%D The fraction of fossil olfactory receptor genes is significantly higher in -%D all species with full color vision. This suggests that the evolution of -%D trichromatic vision --- which allows these primates to detect food, mates, -%D and danger with visual cues --- has reduced their reliance on the sense of -%D smell. -%D \stopuserdata -%D -%D \startuserdata [epigraph] [author={Sean B. Carrol}] -%D \samplefile{carrol} -%D \stopuserdata -%D \stoptyping - -\unprotect - -\installnamespace {userdata} -\installnamespace {userdataalternative} -\installnamespace {userdatarenderings} - -\installcommandhandler \????userdata {userdata} \????userdata -\installcommandhandler \????userdataalternative {userdataalternative} \????userdataalternative - -\permanent\protected\def\startuserdata - {\begingroup - \let\currentuserdata\empty - \doifelsenextoptionalcs\userdata_start_delayed\userdata_start_indeed} - -% This variant works only when the userdata instance exists while the assignment check -% can also be used with undefined instances which falls back to the global settings. -% -% \def\userdata_start_delayed[#1]% -% {\ifcsname\nameduserdatahash{\detokenize\expandafter{\normalexpanded{#1}}}\s!parent\endcsname -% \expandafter\userdata_start_delayed_name -% \else -% \expandafter\userdata_start_delayed_parameters -% \fi[#1]} - -\def\userdata_start_delayed[#1]% - {\doifelseassignmentcs{#1}% - \userdata_start_delayed_parameters - \userdata_start_delayed_name - [#1]} - -\def\userdata_start_delayed_parameters[#1]% - {\setupcurrentuserdata[#1]% - \userdata_start_indeed} - -\def\userdata_start_delayed_name[#1]% - {\edef\currentuserdata{#1}% - \checkuserdataparent - \doifelsenextoptionalcs\userdata_start_delayed_parameters\userdata_start_indeed} - -\def\userdata_start_indeed - {\grabbufferdatadirect\s!userdata{\csstring\startuserdata}{\csstring\stopuserdata}} - -\permanent\protected\def\stopuserdata - {\userdataparameter\c!before % HH: moved, so we obey the outer spacing - \dostarttagged\t!userdata\currentuserdata % HH: added, maybe move up ? - \begingroup - \useuserdatastyleandcolor\c!style\c!color - \usealignparameter\userdataparameter % HH: added - \edef\currentuserdataalternative{\userdataparameter\c!alternative}% - \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else - \let\currentuserdataalternative\s!default - \fi - \usesetupsparameter\userdataparameter - \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}% - \directsetup\p_renderingsetup - \endgroup - \dostoptagged - \userdataparameter\c!after % HH: moved - \endgroup} - -\permanent\protected\def\getuserdata - {\getbufferdata[\s!userdata]} - -\permanent\protected\def\getinlineuserdata - {\inlinebuffer[\s!userdata]} - -\defineuserdataalternative - [\s!default] - [\c!renderingsetup=\????userdatarenderings:\s!default] - -% \startsetups[\????userdatarenderings:\s!default] -% \userdataparameter\c!before -% \usesetupsparameter\userdataparameter -% \getbufferdata[\s!userdata] -% \userdataparameter\c!after -% \stopsetups - -\startsetups[\????userdatarenderings:\s!default] - \getuserdata -\stopsetups - -\setupuserdata - [\c!alternative=\s!default] - -\protect diff --git a/tex/context/base/mkiv/supp-box.lmt b/tex/context/base/mkiv/supp-box.lmt deleted file mode 100644 index 41013da9a..000000000 --- a/tex/context/base/mkiv/supp-box.lmt +++ /dev/null @@ -1,1335 +0,0 @@ -if not modules then modules = { } end modules ['supp-box'] = { - version = 1.001, - optimize = true, - 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 report_hyphenation = logs.reporter("languages","hyphenation") - -local tonumber, next, type = tonumber, next, type - -local lpegmatch = lpeg.match - -local tex = tex -local context = context -local nodes = nodes - -local implement = interfaces.implement - -local nodecodes = nodes.nodecodes - -local disc_code = nodecodes.disc -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glue_code = nodecodes.glue -local penalty_code = nodecodes.penalty -local glyph_code = nodecodes.glyph -local par_code = nodecodes.par - -local indent_code = nodes.listcodes.indent - -local hmode_code = tex.modelevels.horizontal - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - ------ getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getboth = nuts.getboth -local getdisc = nuts.getdisc -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getattribute = nuts.getattribute -local getbox = nuts.getbox -local getdirection = nuts.getdirection -local getwidth = nuts.getwidth -local getheight = nuts.getheight -local getdepth = nuts.getdepth -local getwhd = nuts.getwhd -local takebox = nuts.takebox - ------ setfield = nuts.setfield -local setlink = nuts.setlink -local setboth = nuts.setboth -local setnext = nuts.setnext -local setprev = nuts.setprev -local setbox = nuts.setbox -local setlist = nuts.setlist -local setdisc = nuts.setdisc -local setwidth = nuts.setwidth -local setheight = nuts.setheight -local setdepth = nuts.setdepth -local setshift = nuts.setshift -local setsplit = nuts.setsplit -local setattrlist = nuts.setattrlist -local setwhd = nuts.setwhd -local setglue = nuts.setglue - -local flush_node = nuts.flush_node -local flush_list = nuts.flush_list -local copy_node = nuts.copy -local copy_list = nuts.copy_list -local find_tail = nuts.tail -local getdimensions = nuts.dimensions -local hpack = nuts.hpack -local vpack = nuts.vpack -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse -local free = nuts.free -local findtail = nuts.tail -local reverse = nuts.reverse -local effective_glue= nuts.effective_glue - -local nextdisc = nuts.traversers.disc -local nextdir = nuts.traversers.dir -local nexthlist = nuts.traversers.hlist - -local listtoutf = nodes.listtoutf - -local nodepool = nuts.pool -local new_penalty = nodepool.penalty -local new_hlist = nodepool.hlist -local new_glue = nodepool.glue - -local setlistcolor = nodes.tracers.colors.setlist - -local texget = tex.get -local texgetbox = tex.getbox -local texsetdimen = tex.setdimen -local texgetnest = tex.getnest - -local function hyphenatedlist(head,usecolor) - local current = head and tonut(head) - while current do - local id = getid(current) - local prev, next = getboth(current) - if id == disc_code then - local pre, post, replace = getdisc(current) - 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) - end - setdisc(current) - if pre then - setlink(prev,new_penalty(10000),pre) - setlink(find_tail(pre),current) - end - if post then - setlink(current,new_penalty(10000),post) - setlink(find_tail(post),next) - end - 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 nextdisc, 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(n) - -- we just hyphenate (as we pass a hpack) .. a bit too much casting but ... - local l = languages.hyphenators.handler(tonode(checkedlist(n))) - report_hyphenation("show: %s",listtoutf(l,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 command then - command = context[command] - end - if method == "char" or method == "character" then - if spaced then - spaced = context.space - end - local words = lpegmatch(split_char,str) - for i=1,#words do - local word = words[i] - if word == " " then - if spaced then - spaced() - end - elseif command then - command(word) - else - context(word) - end - end - elseif method == "word" then - if spaced then - spaced = context.space - end - local words = lpegmatch(split_word,str) - for i=1,#words do - local word = words[i] - if spaced and i > 1 then - spaced() - end - if command then - command(word) - else - context(word) - end - end - elseif method == "line" then - if spaced then - spaced = context.par - end - local words = lpegmatch(split_line,str) - for i=1,#words do - local word = words[i] - if spaced and i > 1 then - spaced() - end - if command then - 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 - flush_node(temp) - end - -- done - setnext(tail) - setlist(current) - end - current = next - end - local result = new_hlist() - setlist(result,head) - setbox(target,result) - -- setbox(target,new_hlist(head)) - end -} - -implement { - name = "hboxtovbox", - arguments = "integer", - actions = function(n) - local b = getbox(n) - local factor = texget("baselineskip",false) / texget("hsize") - setdepth(b,0) - setheight(b,getwidth(b) * 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 = 0 - local h = 0 - local d = 0 - local l = getlist(getbox(n)) - if l then - w, h, d = getdimensions(l) - end - texsetdimen("lastnaturalboxwd",w) - texsetdimen("lastnaturalboxht",h) - texsetdimen("lastnaturalboxdp",d) - return w, h, d -end - -implement { - name = "getnaturaldimensions", - arguments = "integer", - actions = getnaturaldimensions -} - -implement { - name = "naturalwd", - arguments = "integer", - actions = function(n) - getnaturaldimensions(n) - context.lastnaturalboxwd(false) - end -} - -implement { - name = "getnaturalwd", - arguments = "integer", - actions = function(n) - local w = 0 - local h = 0 - local d = 0 - local l = getlist(getbox(n)) - if l then - w, h, d = getdimensions(l) - end - context("\\dimexpr%i\\scaledpoint\\relax",w) - end -} - -local function setboxtonaturalwd(n) - local old = takebox(n) - local new = hpack(getlist(old)) - setlist(old,nil) - flush_node(old) - setbox(n,new) -end - -implement { - name = "setnaturalwd", - arguments = "integer", - actions = setboxtonaturalwd -} - -nodes.setboxtonaturalwd = setboxtonaturalwd - -local doifelse = commands.doifelse - -do - - local dirvalues = nodes.dirvalues - local lefttoright_code = dirvalues.lefttoright - local righttoleft_code = dirvalues.righttoleft - - local function firstdirinbox(n) - local b = getbox(n) - if b then - local l = getlist(b) - if l then - for d in nextdir, l do - return getdirection(d) - end - for h in nexthlist, l do - return getdirection(h) - end - end - end - return lefttoright_code - end - - nodes.firstdirinbox = firstdirinbox - - implement { - name = "doifelserighttoleftinbox", - arguments = "integer", - actions = function(n) - doifelse(firstdirinbox(n) == righttoleft_code) - end - } - -end - --- new (handy for mp) .. might move to its own module - -do - - local takebox = nuts.takebox - local flush_list = nuts.flush_list - local copy_list = nuts.copy_list - local getwhd = nuts.getwhd - local setbox = nuts.setbox - local new_hlist = nuts.pool.hlist - - local boxes = { } - nodes.boxes = boxes - local cache = table.setmetatableindex("table") - local report = logs.reporter("boxes","cache") - local trace = false - - trackers.register("nodes.boxes",function(v) trace = v end) - - function boxes.save(category,name,b) - name = tonumber(name) or name - local b = takebox(b) - if trace then - report("category %a, name %a, %s (%s)",category,name,"save",b and "content" or "empty") - end - cache[category][name] = b or false - end - - function boxes.savenode(category,name,n) - name = tonumber(name) or name - if trace then - report("category %a, name %a, %s (%s)",category,name,"save",n and "content" or "empty") - end - cache[category][name] = tonut(n) or false - end - - function boxes.found(category,name) - name = tonumber(name) or name - return cache[category][name] and true or false - end - - function boxes.direct(category,name,copy) - name = tonumber(name) or name - local c = cache[category] - local b = c[name] - if not b then - -- do nothing, maybe trace - elseif copy then - b = copy_list(b) - else - c[name] = false - end - if trace then - report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty") - end - if b then - return tonode(b) - end - end - - function boxes.restore(category,name,box,copy) - name = tonumber(name) or name - local c = cache[category] - local b = takebox(box) - if b then - flush_list(b) - end - local b = c[name] - if not b then - -- do nothing, maybe trace - elseif copy then - b = copy_list(b) - else - c[name] = false - end - if trace then - report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty") - end - setbox(box,b or nil) - end - - function boxes.dimensions(category,name) - name = tonumber(name) or name - local b = cache[category][name] - if b then - return getwhd(b) - else - return 0, 0, 0 - end - end - - function boxes.reset(category,name) - name = tonumber(name) or name - local c = cache[category] - if name and name ~= "" then - local b = c[name] - if b then - flush_list(b) - c[name] = false - end - if trace then - report("category %a, name %a, reset",category,name) - end - else - for k, b in next, c do - if b then - flush_list(b) - end - end - cache[category] = { } - if trace then - report("category %a, reset",category) - end - end - end - - implement { - name = "putboxincache", - arguments = { "string", "string", "integer" }, - actions = boxes.save, - } - - implement { - name = "getboxfromcache", - arguments = { "string", "string", "integer" }, - actions = boxes.restore, - } - - implement { - name = "directboxfromcache", - arguments = "2 strings", - actions = { boxes.direct, context }, - -- actions = function(category,name) local b = boxes.direct(category,name) if b then context(b) end end, - } - - implement { - name = "directcopyboxfromcache", - arguments = { "string", "string", true }, - actions = { boxes.direct, context }, - -- actions = function(category,name) local b = boxes.direct(category,name,true) if b then context(b) end end, - } - - implement { - name = "copyboxfromcache", - arguments = { "string", "string", "integer", true }, - actions = boxes.restore, - } - - implement { - name = "doifelseboxincache", - arguments = "2 strings", - actions = { boxes.found, doifelse }, - } - - implement { - name = "resetboxesincache", - arguments = "string", - actions = boxes.reset, - } - -end - -implement { - name = "lastlinewidth", - actions = function() - local head = tex.lists.page_head - -- list dimensions returns 3 value but we take the first - context(head and getdimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0) - end -} - -implement { - name = "shiftbox", - arguments = { "integer", "dimension" }, - actions = function(n,d) - setshift(getbox(n),d) - end, -} - -implement { name = "vpackbox", arguments = "integer", actions = function(n) setbox(n,(vpack(takebox(n)))) end } -implement { name = "hpackbox", arguments = "integer", actions = function(n) setbox(n,(hpack(takebox(n)))) end } - -implement { name = "vpackedbox", arguments = "integer", actions = function(n) context(vpack(takebox(n))) end } -implement { name = "hpackedbox", arguments = "integer", actions = function(n) context(hpack(takebox(n))) end } - -implement { - name = "scangivendimensions", - public = true, - protected = true, - arguments = { - { - { "width", "dimension" }, - { "height", "dimension" }, - { "depth", "dimension" }, - }, - }, - actions = function(t) - texsetdimen("givenwidth", t.width or 0) - texsetdimen("givenheight",t.height or 0) - texsetdimen("givendepth", t.depth or 0) - end, -} - -local function stripglue(list) - local done = false - local first = list - while first do - local id = getid(first) - if id == glue_code or id == penalty_code then - first = getnext(first) - else - break - end - end - if first and first ~= list then - -- we have discardables - setsplit(getprev(first),first) - flush_list(list) - list = first - done = true - end - if list then - local tail = findtail(list) - local last = tail - while last do - local id = getid(last) - if id == glue_code or id == penalty_code then - last = getprev(last) - else - break - end - end - if last ~= tail then - -- we have discardables - flush_list(getnext(last)) - setnext(last) - done = true - end - end - return list, done -end - -local function limitate(t) -- don't pack the result ! - local text = t.text - if text then - text = tonut(text) - else - return - end - local sentinel = t.sentinel - if sentinel then - sentinel = tonut(sentinel) - local s = getlist(sentinel) - setlist(sentinel) - free(sentinel) - sentinel = s - else - return tonode(text) - end - local width = getwidth(text) - local list = getlist(text) - local done = false - if t.strip then - list, done = stripglue(list) - if not list then - setlist(text) - setwidth(text,0) - return text - elseif done then - width = getdimensions(list) - setlist(text,list) - end - end - local left = t.left or 0 - local right = t.right or 0 - local total = left + right - if total < width then - local last = nil - local first = nil - local maxleft = left - local maxright = right - local swidth = getwidth(sentinel) - if maxright > 0 then - maxleft = maxleft - swidth/2 - maxright = maxright - swidth/2 - else - maxleft = maxleft - swidth - end - for n in traverse_id(glue_code,list) do - local width = getdimensions(list,n) - if width > maxleft then - if not last then - last = n - end - break - else - last = n - end - end - if last and maxright > 0 then - for n in traverse_id(glue_code,last) do - local width = getdimensions(n) - if width < maxright then - first = n - break - else - first = n - end - end - end - if last then - local rest = getnext(last) - if rest then - local tail = findtail(sentinel) - if first and getid(first) == glue_code and getid(tail) == glue_code then - setwidth(first,0) - end - if last and getid(last) == glue_code and getid(sentinel) == glue_code then - setwidth(last,0) - end - if first and first ~= last then - local prev = getprev(first) - if prev then - setnext(prev) - end - setlink(tail,first) - end - setlink(last,sentinel) - setprev(rest) - flush_list(rest) - end - end - end - setlist(text) - free(text) - - if t.freeze then - local l = hpack(list,total,"exactly") - for n in traverse_id(glue_code,list) do - setglue(n,(effective_glue(n,l))) - end - setlist(l) - flush_node(l) - end - - return tonode(list) -end - -implement { - name = "limitated", - public = true, - protected = true, - arguments = { - { - { "left", "dimension" }, - { "right", "dimension" }, - { "text", "hbox" }, - { "sentinel", "hbox" }, - { "strip", "boolean" }, - { "freeze", "boolean" }, - } - }, - actions = function(t) - context.dontleavehmode() - context(limitate(t)) - end, -} - --- only in lmtx: - -implement { - name = "widthuptohere", - public = true, - usage = "value", - actions = function() - local n = texgetnest() - local w = 0 - if n.mode == hmode_code then - local h = hpack(getnext(tonut(n.head))) - w = getwidth(h) - setlist(h) - free(h) - end - return tokens.values.dimension, w - end, -} - -implement { - name = "doifelseindented", - public = true, - protected = true, - actions = function() - local n = texgetnest() - local b = false - if n.mode == hmode_code then - n = tonut(n.head) - while n do - n = getnext(n) - if n then - local id = getid(n) - if id == hlist_code then - if getsubtype(n) == indent_code then - b = getwidth(n) > 0 - break - end - elseif id ~= par_code then - break - end - end - end - end - commands.doifelse(b) - end, -} - -implement { - name = "noflinesinbox", - public = true, - protected = false, - arguments = "integer", - actions = function(n) - local c = 0 - local b = getbox(n) - if b then - b = getlist(b) - if b then - for n, id in traverse(b) do - if id == hlist_code or id == vlist_code then - c = c + 1 - end - end - end - end - context(c) - end, -} - -do - - local takebox = tex.takebox - - implement { - name = "thebox", - public = true, - arguments = "integer", - actions = function(n) - context(takebox(n)) - end - } - -end - --- only in lmtx - -implement { - name = "reversevboxcontent", - protected = true, - public = true, - arguments = "integer", - actions = function(n) - local b = getbox(n) - local l = b and getid(b) == vlist_code and getlist(b) - if l and getnext(l) then - setlist(b,reverse(l)) -- no re-vpack here! - end - end -} - --- only in lmtx - -do - - local scaninteger = tokens.scanners.integer - local scanbox = tokens.scanners.box - local scandimen = tokens.scanners.dimen - - local setsubtype = nuts.setsubtype - local removenode = nuts.remove - local getnormalizedline = nuts.getnormalizedline -- we can optimize this - local getdimensions = nuts.dimensions - local getrangedimensions = nuts.rangedimensions - - local setprop = nuts.setprop - local getprop = nuts.getprop - - local listcodes = nodes.listcodes - local line_code = listcodes.line - local equation_code = listcodes.equation - local unknown_code = listcodes.unknown - - local values = tokens.values - local dimension_value = values.dimension - local cardinal_value = values.cardinal - local direct_value = values.direct - - -- todo: make helper that formats - - local reporterror = logs.texerrormessage - - -- The first variant did a linear lookup but for large boxes and lots of - -- analysis that is not nice. Okay, in practice performance is quite ok - -- (milliseconds for thousands of access) but still ... the next is nicer - -- and it's part of the experimental fun stuff anyway. - - local function countlines(box) - local prop = getprop(box,"boxlines") - if not prop then - local line = 0 - local list = getlist(box) - prop = { } - if list then - for n, subtype in nexthlist, list do - if subtype == line_code then -- or subtype == equation_code then - line = line + 1 - prop[line] = n - end - end - end - setprop(box,"boxlines",prop) - end - return prop - end - - local function boxlinecount(what) - local n = scaninteger() - local box = getbox(n) - if what == "value" then - return cardinal_value, box and #countlines(box) or 0 - end - end - - local function findline() - local n = scaninteger() - local line = scaninteger() - local box = getbox(n) - if box then - local prop = getprop(box,"boxlines") - if not prop then - prop = countlines(box) - end - local found = prop[line] - if found then - local props = getprop(found,"lineproperties") - if not props then - props = getnormalizedline(found) - props.width, props.height, props.depth = getwhd(found) - setprop(found,"lineproperties",props) - end - return props, line, found, box - end - end - reporterror("no line %i in box %i",line,n) - end - - local function findrange() - local n = scaninteger() - local first = scaninteger() - local last = scaninteger() - local box = getbox(n) - if box then - local prop = getprop(box,"boxlines") - if not prop then - prop = countlines(box) - end - if first > 0 and last <= #prop then - for i = first, last do - local found = prop[i] - local props = getprop(found,"lineproperties") - if not props then - props = getnormalizedline(found) - props.width, props.height, props.depth = getwhd(found) - setprop(found,"lineproperties",props) - end - end - return prop, first, last, box - end - end - reporterror("no lines %i - %i in box %i",first,last,n) - end - - local function getline(props,line,found,box,value) - local p, n = getboth(found) - local temp = new_hlist() - setsubtype(temp,getsubtype(found)) - setwhd(temp,getwhd(found)) - if found == getlist(box) then - setlink(temp,n) - setlist(box,temp) - else - setlink(p,temp,n) - end - getprop(box,"boxlines")[line] = temp - setboth(found) - setsubtype(found, unknown_code) - if value then - return direct_value, found - else - context(tonode(found)) - end - end - - local function copyline(props,line,found,box,value) - found = copy_node(found) - setsubtype(found, unknown_code) - if value then - return direct_value, found - else - context(tonode(found)) - end - end - - local function setline(props,line,found,box) - local p, n = getboth(found) - local temp = scanbox() - if temp then - temp = tonut(temp) - if found == getlist(box) then - setlink(temp,n) - setlist(box,temp) - else - setlink(p,temp,n) - end - flush_node(found) - getprop(box,"boxlines")[line] = temp - end - end - - local function naturaldimensions(p,l,found) - if not p.naturalwidth then - p.naturalwidth, p.naturalheight, p.naturaldepth = getdimensions(getlist(found)) - end - return p - end - - local function rangedimensions(p,f,l,box) - local w, h, d = getrangedimensions(box,p[f],getnext(p[l]),true) - return { width = w, height = h, depth = d } - end - - local getters_one = { - - ["wd"] = function(p,l,found) return dimension_value, p.width end, - ["ht"] = function(p,l,found) return dimension_value, p.height end, - ["dp"] = function(p,l,found) return dimension_value, p.depth end, - ["ls"] = function(p,l,found) return dimension_value, p.leftskip end, - ["rs"] = function(p,l,found) return dimension_value, p.rightskip end, - ["lh"] = function(p,l,found) return dimension_value, p.lefthangskip end, - ["rh"] = function(p,l,found) return dimension_value, p.righthangskip end, - ["lp"] = function(p,l,found) return dimension_value, p.parfillleftskip end, - ["rp"] = function(p,l,found) return dimension_value, p.parfillrightskip end, - ["in"] = function(p,l,found) return dimension_value, p.indent end, - - ["nw"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturalwidth end, - ["nh"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturalheigth end, - ["nd"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturaldepth end, - - ["get"] = function(p,l,found,box) return getline(p,l,found,box,true) end, - } - - local getters_two = { - ["wd"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).width end, - ["ht"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).height end, - ["dp"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).depth end, - } - - local setters_one = { - ["wd"] = function(p,l,found) return setwidth (found,scandimen(false,false,true)) end, - ["ht"] = function(p,l,found) return setheight(found,scandimen(false,false,true)) end, - ["dp"] = function(p,l,found) return setdepth (found,scandimen(false,false,true)) end, - ["set"] = setline, - ["get"] = getline, - ["copy"] = copyline, - } - - local function boxline(name,what) - local props, line, found, box = findline() - if not found then - -- - elseif what == "value" then - local getter = getters_one[name] - if getter then - return getter(props,line,found,box) - end - else - local setter = setters_one[name] - if setter then - return setter(props,line,found,box) - end - end - end - - -- - - local function boxrange(name,what) - local prop, first, last, box = findrange() - if not prop then - -- - elseif what == "value" then - local getter = getters_two[name] - if getter then - return getter(prop,first,last,box) - end - else - local setter = setters_two[name] - if setter then - return setter(prop,first,last,box) - end - end - end - - local function define_one(name,action) - implement { - name = name, - public = true, - usage = "value", - actions = function(what) return boxline(action,what) end, - } - end - - local function define_two(name,action) - implement { - name = name, - public = true, - usage = "value", - actions = function(what) return boxrange(action,what) end, - } - end - - implement { - name = "boxlines", - public = true, - usage = "value", - actions = boxlinecount, - } - - define_one("boxline", "get") - define_one("setboxline", "set") - define_one("copyboxline", "copy") - define_one("boxlineht", "ht") - define_one("boxlinedp", "dp") - define_one("boxlinewd", "wd") - define_one("boxlinels", "ls") - define_one("boxliners", "rs") - define_one("boxlinelh", "lh") - define_one("boxlinerh", "rh") - define_one("boxlinelp", "lp") - define_one("boxlinerp", "rp") - define_one("boxlinein", "in") - define_one("boxlinenw", "nw") - define_one("boxlinenh", "nh") - define_one("boxlinend", "nd") - - define_two("boxrangewd", "wd") - define_two("boxrangeht", "ht") - define_two("boxrangedp", "dp") - -end - -do - - local getbox = tex.getbox - local setfield = nodes.setfield - local getfield = nodes.getfield - local flush = nodes.flush - local copynode = nodes.copy - - local function get(n,field,copy) - local b = getbox(n) - if b then - local p = getfield(b,field) - if copy then - p = copynode(p) - else - setfield(b,field) - end - context(p) - end - end - - local function set(n,l,field) - local b = getbox(n) - if b then - setfield(b,field,l) - else - flush(l) - end - end - - implement { - name = "prelistbox", - public = true, - usage = "value", - arguments = { "integer", '"pre"' }, - actions = get, - } - - implement { - name = "postlistbox", - public = true, - usage = "value", - arguments = { "integer", '"post"' }, - actions = get, - } - - implement { - name = "prelistcopy", - public = true, - usage = "value", - arguments = { "integer", '"pre"', true }, - actions = get, - } - - implement { - name = "postlistcopy", - public = true, - usage = "value", - arguments = { "integer", '"post"', true }, - actions = get, - } - - implement { - name = "setprelistbox", - public = true, - usage = "value", - arguments = { "integer", "box", '"pre"' }, - actions = set, - } - - implement { - name = "setpostlistbox", - public = true, - usage = "value", - arguments = { "integer", "box", '"post"' }, - actions = set, - } - -end diff --git a/tex/context/base/mkiv/supp-box.mkxl b/tex/context/base/mkiv/supp-box.mkxl deleted file mode 100644 index fe08876ac..000000000 --- a/tex/context/base/mkiv/supp-box.mkxl +++ /dev/null @@ -1,2901 +0,0 @@ -%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}{autosuffix,optimize} - -%D And some dimensions: - -\newdimen\givenwidth -\newdimen\givenheight -\newdimen\givendepth - -% \fixupboxesmode\plusone % gone: is now the default - -%D This module implements some box manipulation macros. Some are quite simple, some -%D are more advanced and when understood well, all can be of use. -%D -%D \macros -%D {strutdp,strutht,strutwd} -%D -%D The next shortcuts save memory and keying. The width is normally zero points (if -%D not, you're in trouble). These shortcuts can be used like a dimension, opposite -%D to the core macros \type {\strutdepth} and alike, which are values. - -%D These will be overloaded in spac-ver: - -\def\strutdp {\dp\strutbox} -\def\strutht {\ht\strutbox} -\def\strutwd {\wd\strutbox} -\def\struthtdp{\htdp\strutbox} -\def\strutgap {\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 ugly \type {@} in \type -%D {\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 need to save the \TEX\ -%D \DIMENSION\ \type{\prevdepth} and append it later on. The name \type {\nextdepth} -%D suits this purpose well. - -\newdimen\nextdepth - -%D \macros -%D {smashbox, smashboxed, smashedbox} -%D -%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of -%D a box to zero. The most resolute one is presented first. - -% \permanent\protected\def\smashbox#1% -% {\wd#1\zeropoint -% \ht#1\zeropoint -% \dp#1\zeropoint} -% -% \permanent\protected\def\smashboxed#1% -% {\wd#1\zeropoint -% \ht#1\zeropoint -% \dp#1\zeropoint -% \box#1\relax} - -%D \macros -%D {hsmashbox,vsmashbox} -%D -%D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or -%D vertical, one can use: - -% \permanent\protected\def\hsmashbox#1% -% {\wd#1\zeropoint} -% -% \permanent\protected\def\vsmashbox#1% -% {\ht#1\zeropoint -% \dp#1\zeropoint} - -%D The next implementation is less sensitive for spurious spaces. - -\newcount\c_boxes_register - -\permanent\protected\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} - -\permanent\protected\def\hsmashbox - {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register} - -\def\syst_boxes_hsmashed_boxes_register - {\wd\c_boxes_register\zeropoint} - -\permanent\protected\def\vsmashbox - {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register} - -\def\syst_boxes_vsmashed_boxes_register - {\ht\c_boxes_register\zeropoint - \dp\c_boxes_register\zeropoint} - -\permanent\protected\def\smashedbox - {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register} - -\protected\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} - -\let\smashboxed\smashedbox - -%D \macros -%D {hsmash,vsmash, -%D hsmashed,vsmashed} -%D -%D While the previous macros expected a \BOX, the next act on a content. They are -%D some subtle differences betreen the smash and smashed alternatives. The later -%D ones reduce all dimensions to zero. - -\permanent\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox} -\permanent\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox} -\permanent\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox} -\permanent\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox} - -\protected\def\syst_boxes_hsmashed_nextbox - {\wd\nextbox\zeropoint - \box\nextbox - \egroup} - -\protected\def\syst_boxes_vsmashed_nextbox - {\ht\nextbox\zeropoint - \dp\nextbox\zeropoint - \box\nextbox - \egroup} - -\protected\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 - -\permanent\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} -\permanent\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} - -%D First we define a helper. We use a \LUATEX\ feature in order to avoid -%D mathpalettes. - -\newcount\c_boxes_math_style - -\protected\def\syst_boxes_math_set_nextbox#1% - {\c_boxes_math_style\normalmathstyle - \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 well as is potentially -%D catcode safer. It is needed by the math module (although the \type {\leavevmode} -%D is not added here). - -\permanent\protected\def\smash - {\begingroup - \futureexpandis[\syst_boxes_smash_yes\syst_boxes_smash_nop} - -\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 - \orelse\ifx\nexttoken\bgroup - \expandafter\syst_boxes_smash_hbox - \else - \expandafter\syst_boxes_smash_text - \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} - -\def\syst_boxes_lower_nextbox_dp - {\setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}} - -%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 not grab an argument in -%D the non||math case, which is better. -%D -%D Due to a complicated call to \type {\mathpallete} and thereby \type -%D {\mathchoice}, the next macro looks ugly. We also take care of non||braced -%D arguments. - -\permanent\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed } -\permanent\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v} -\permanent\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h} - -\def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make } -\def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v} -\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 - \orelse\ifx\nexttoken\bgroup - \expandafter\syst_boxes_phantom_hbox - \else - \expandafter\syst_boxes_phantom_text - \fi} - -\def\syst_boxes_phantom_indeed_v - {\ifmmode - \expandafter\syst_boxes_phantom_math_v - \orelse\ifx\nexttoken\bgroup - \expandafter\syst_boxes_phantom_hbox_v - \else - \expandafter\syst_boxes_phantom_text_v - \fi} - -\def\syst_boxes_phantom_indeed_h - {\ifmmode - \expandafter\syst_boxes_phantom_math_h - \orelse\ifx\nexttoken\bgroup - \expandafter\syst_boxes_phantom_hbox_h - \else - \expandafter\syst_boxes_phantom_text_h - \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}. - -\permanent\protected\def\mathstrut{\vphantom(} % can be made faster by inlining - -%D \macros -%D {getboxheight} -%D -%D Although often needed, \TEX\ does not support arithmics 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 it accepts \type {{12}} as -%D well as \type {12} as box number. - -\permanent\protected\def\getboxheight#1\of#2\box#3% - {\def\next{#1\htdp\c_boxes_register}% - \afterassignment\next\c_boxes_register=#3} - -%D For a long time the following three macros were part of the grid snapping core -%D module, but it makes more sense to 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 (dimensie) in een aantal -%D regels en kent dit toe aan \type {\noflines}. -%D -%D \starttyping -%D \getnoflines{dimensie} -%D \stoptyping -%D -%D Er wordt gedeeld door \type {\openlineheight} en een hoogte van~0pt komt overeen -%D met 0~regels. The raw alternative does not round. -%D -%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 -%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 - -\permanent\protected\def\getnoflines#1% - {\noflinesheight#1\relax - \ifzeropt\noflinesheight - \noflines\zerocount - \orelse\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} - -\permanent\protected\def\getroundednoflines#1% - {\noflinesheight#1\relax - \ifzeropt\noflinesheight - \noflines\zerocount - \orelse\ifdim\noflinesheight>\zeropoint - \advance\noflinesheight\roundingeps - \divide\noflinesheight\openlineheight - \noflines\noflinesheight - \else - \advance\noflinesheight-\roundingeps - \divide\noflinesheight\openlineheight - \noflines\noflinesheight - \fi} - -\permanent\protected\def\getrawnoflines#1% - {\noflinesheight#1\relax - \ifzeropt\noflinesheight - \noflines\zerocount - \orelse\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} - -%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 returns it it \type -%D {\noflines}. The macro works reasonable well as long as the content can be -%D unboxed. -%D -%D \starttyping -%D \determinenoflines{test\\test} -%D \determinenoflines{\bfd test\\test} -%D \determinenoflines{\definedfont[Sans at 40pt]test\\test} -%D \stoptyping - -% \def\syst_boxes_determine_noflines % can be mkiv'd -% {\beginofshapebox -% \unvbox\nextbox -% \endofshapebox -% \globalscratchcounter\zerocount -% \reshapebox{\global\advance\globalscratchcounter\plusone}% -% \expandafter\egroup\expandafter\noflines\the\globalscratchcounter\relax} - -\def\syst_boxes_determine_noflines - {\expandafter\egroup\expandafter\noflines\noflinesinbox\nextbox\relax} - -\permanent\protected\def\determinenoflines - {\bgroup - \forgetall - \enforced\let\crlf\endgraf - \enforced\let\\\endgraf - \dowithnextboxcs\syst_boxes_determine_noflines\vbox} - -%D \macros -%D {doiftextelse, doiftext} -%D -%D When \type {\doifelse} cum suis hopelessly fail, for instance because we pass -%D data, we can fall back on the next macro: -%D -%D \starttyping -%D \doiftextelse {data} {then branch} {else branch} -%D \doiftext {data} {then branch} -%D \stoptyping - -\permanent\protected\def\doifelsetext#1% - {\begingroup - \setbox\scratchbox\hbox % no \hpack because we can have fallbacks - {\settrialtypesetting - \ignorespaces#1\removeunwantedspaces}% - \ifzeropt\wd\scratchbox - \endgroup\expandafter\secondoftwoarguments - \else - \endgroup\expandafter\firstoftwoarguments - \fi} - -\permanent\protected\def\doiftext#1% - {\begingroup - \setbox\scratchbox\hbox % no \hpack because we can have fallbacks - {\settrialtypesetting - \ignorespaces#1\removeunwantedspaces}% - \ifzeropt\wd\scratchbox - \endgroup\expandafter\gobbleoneargument - \else - \endgroup\expandafter\firstofoneargument - \fi} - -% more efficient but maybe fragile: -% -% \nospacing#1}% - -\let\doiftextelse\doifelsetext - -%D \macros -%D {dowithnextbox,nextbox} -%D -%D Sometimes we want a macro to grab a box and do something on the content. One -%D could pass an argument to a box, but this can violate the specific \CATCODES\ of -%D its content and leads to unexpected results. The next macro treats the following -%D braced text as the content of a box and manipulates it afterwards in a predefined -%D way. -%D -%D The first argument specifies what to do with the content. This content is -%D available in \type {\nextbox}. The second argument is one of \type {\hbox}, \type -%D {\vbox} or \type {\vtop}. The third argument must be grouped with \type {\bgroup} -%D and \type {\egroup}, \type {{...}} or can be a \type {\box} specification. -%D -%D In \CONTEXT\ this macro is used for picking up a box and treating it according to -%D earlier specifications. We use for 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 is needed because -%D \type {\afterassignment} is executed inside the box. - -\permanent\protected\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} - -\permanent\protected\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 \protected\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 \orelse\ifx#2\vbox -%D \afterassignment\syst_boxes_with_next_box_indeed -%D \orelse\ifx#2\vtop -%D \afterassignment\syst_boxes_with_next_box_indeed -%D \orelse\ifx#2\normalvcenter -%D \afterassignment\syst_boxes_with_next_box_indeed -%D \else -%D \afterassignment\syst_boxes_with_next_box -%D \fi -%D \setbox\nextbox#2} -%D \stoptyping -%D -%D This alternative also accepts \type {\box0} and alike, but we don't really need -%D this functionality now. - -%D \macros -%D {nextboxht,nextboxwd,nextboxdp,flushnextbox} -%D -%D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing -%D parameters. - -\permanent\def\nextboxht {\ht\nextbox} -\permanent\def\nextboxwd {\wd\nextbox} -\permanent\def\nextboxdp {\dp\nextbox} -\permanent\def\nextboxhtdp{\htdp\nextbox} - -\permanent\protected\def\flushnextbox{\box\nextbox} - -%D \macros -%D {dowithnextboxcontent} -%D -%D But, occasionally we do need to pass some local settings without wanting to use -%D additional grouping. Therefore we provide: -%D -%D \starttyping -%D \dowithnextboxcontent{inside}{after}{box content} -%D \stoptyping -%D -%D {\em todo: Search source for potential usage!} - -% \protected\def\dowithnextboxcontent#1#2% inside, after -% {\def\syst_boxes_with_next_box_one{#2}% -% \def\syst_boxes_with_next_box_two{#1}% -% \afterassignment\syst_boxes_with_next_box_content_indeed -% \setbox\nextbox} -% -% \protected\def\dowithnextboxcontentcs#1#2% inside, after -% {\let\syst_boxes_with_next_box_one#2% -% \let\syst_boxes_with_next_box_two#1% -% \afterassignment\syst_boxes_with_next_box_content_indeed -% \setbox\nextbox} - -\permanent\unexpanded\def\dowithnextboxcontent#1#2% inside, after - {\afterassigned{#1\aftergrouped{#2}}% - \setbox\nextbox} - -\permanent\unexpanded\def\dowithnextboxcontentcs#1#2% inside, after - {\afterassigned{#1\aftergroup#2}% - \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 way. We want the macros to -%D work in both math and text mode. - -\def\syst_boxes_do_rlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup} -\def\syst_boxes_do_llap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup} -\def\syst_boxes_do_clap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup} -\def\syst_boxes_do_tlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup} -\def\syst_boxes_do_blap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup} - -\def\syst_boxes_rlap {\begingroup\dowithnextboxcs\syst_boxes_do_rlap\hbox} -\def\syst_boxes_llap {\begingroup\dowithnextboxcs\syst_boxes_do_llap\hbox} -\def\syst_boxes_clap {\begingroup\dowithnextboxcs\syst_boxes_do_clap\hbox} -\def\syst_boxes_math_clap{\mathpalette\syst_boxes_do_math_clap} -\def\syst_boxes_math_llap{\mathpalette\syst_boxes_do_math_llap} -\def\syst_boxes_math_rlap{\mathpalette\syst_boxes_do_math_rlap} - -\def\syst_boxes_do_math_clap#1#2{\syst_boxes_clap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} -\def\syst_boxes_do_math_llap#1#2{\syst_boxes_llap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} -\def\syst_boxes_do_math_rlap#1#2{\syst_boxes_rlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} - -\permanent\protected\def\rlap{\mathortext\syst_boxes_math_rlap\syst_boxes_rlap} -\permanent\protected\def\llap{\mathortext\syst_boxes_math_llap\syst_boxes_llap} -\permanent\protected\def\clap{\mathortext\syst_boxes_math_clap\syst_boxes_clap} -\permanent\protected\def\tlap{\begingroup\dowithnextboxcs\syst_boxes_do_tlap\vbox} -\permanent\protected\def\blap{\begingroup\dowithnextboxcs\syst_boxes_do_blap\vbox} - -%D \macros -%D {beginofshapebox, -%D reshapebox, doreshapebox, -%D flushshapebox, -%D innerflushshapebox, -%D shapebox, -%D ifreshapingbox} -%D -%D The next utility macro originates from some linenumbering mechanism. Due to -%D \TEX's advanced way of typesetting paragraphs, it's not easy to do things on a -%D line||by||line basis. This macro is able to reprocess a given box and can act -%D upon its vertical boxed components, such as lines. The unwinding sequence in this -%D macro is inspired by a \NTG\ workshop of David Salomon in June 1992. -%D -%D First we have to grab the piece of text we want to act upon. This is done by -%D 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} and do something -%D with it's vertical components. We can make as much passes as needed. When we're -%D done, the box can be unloaded with \type {\flushshapebox}. The only condition in -%D this scheme is that \type {\reshapebox} must somehow unload the \BOX\ \type -%D {\shapebox}. -%D -%D An important aspect is that the content is unrolled bottom||up. The next example -%D illustrates this maybe 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 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 available after flushing. -%D Another feature is that only the last reshaping counts. Multiple reshaping can be -%D 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 introduce no new concepts. -%D Nearly all books on \TEX\ show similar solutions for unwinding \BOXES. -%D -%D Some macros, like footnote ones, can be sensitive for reshaping, which can result -%D in an endless loop. We therefore offer: -%D -%D \starttyping -%D \ifreshapingbox -%D \stoptyping -%D -%D Some \CONTEXT\ commands are protected this way. Anyhow, reshaping is aborted -%D after 100 dead cycles. -%D -%D By the way, changing the height and depth of \BOX\ \type {\shapebox} results in -%D bad spacing. This means that for instance linenumbers etc. should be given zero -%D height and depth before being lapped into the margin. The previous examples -%D ignore this side effect, but beware! -%D -%D This is ancient stuff and proably not used any more but we keep it around or -%D maybe turn it into a module some day. It shows the kind of struggling that we -%D needed before \LUATEX\ came around. - -\newif \ifsomeshapeleft -\newif \ifreshapingbox -\newif \ifreshapingfailed % may save redundant runs - -\newbox \shapebox -\newcount \shapepenalty -\newdimen \shapekern -\newskip \shapeskip - -\newbox \newshapebox -\newbox \oldshapebox -\newbox \tmpshapebox - -\newcount \shapecounter - -\newevery \everyshapebox \relax - -\def\shapesignal{.12345678pt} % or 12345sp - -\permanent\protected\def\reshapebox#1% - {\doreshapebox - {#1}% - {\penalty\shapepenalty}% - {\kern \shapekern }% - {\vskip \shapeskip }} - -\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip - {\global\reshapingfailedfalse - \ifzeropt\ht\oldshapebox - \setbox\newshapebox\emptyvbox - \else - \setbox\newshapebox\vbox % can be \vpack - {\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 (we can use \type {\vpack} too). - -\permanent\protected\def\insertshapesignal - {\hpack to \shapesignal{\strut\hss}% plus \strut - \prevdepth\strutdp} % never \nointerlineskip - -\permanent\protected\def\restoreshapebox % compensates for the signal - {\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}} - -\permanent\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip - {\ifnum\lastnodetype=\gluenodecode - \shapeskip\lastskip - \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}% - \unskip - \orelse\ifnum\lastnodetype=\kernnodecode - \shapekern\lastkern - \global\setbox\tmpshapebox\vbox{#3\unvbox\tmpshapebox}% - \unkern - \orelse\ifnum\lastnodetype=\penaltynodecode - \shapepenalty\lastpenalty - \global\setbox\tmpshapebox\vbox{#2\unvbox\tmpshapebox}% - \unpenalty - \orelse\ifnum\lastnodetype<\zeropoint - \exitloop - \else - \setbox\shapebox\lastbox - \ifvoid\shapebox - \orelse\ifdim\wd\shapebox=\shapesignal\relax - \exitloop - \else - \shapecounter\zerocount - \global\setbox\tmpshapebox\vbox{#1\unvbox\tmpshapebox}% - \fi - \fi - \ifnum\shapecounter>100 % can be less - \global\reshapingfailedtrue - \message{!!forced exit from shapebox \the\lastnodetype !!}% - \restoreshapebox - \exitloop - \else - \advance\shapecounter \plusone - \fi} - -\permanent\protected\def\beginofshapebox - {\setbox\oldshapebox\vbox - \bgroup - \reshapingboxtrue - \the\everyshapebox - \insertshapesignal} - -\permanent\protected\def\endofshapebox - {\endgraf - \egroup} - -\let\beginshapebox\beginofshapebox -\let\endshapebox \endofshapebox - -\permanent\protected\def\flushshapebox - {\bgroup - \ifzeropt\ht\newshapebox - \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 - \orelse\ifinner - % not watertight and not ok - \donefalse - \orelse\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 - \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} - -\permanent\protected\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} directly. This macro -%D takes four arguments, that take care 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 {\shapebox}, one can best -%D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and -%D depth of the line. - -\permanent\protected\def\shapedhbox % lines with non strutted dimensions have - {\expanded{\dowithnextbox % interlineskip so if we want the original - {\ht\nextbox\the\ht\shapebox % spacing, we need to preserve the original - \dp\nextbox\the\dp\shapebox % height and depth which is definitely - \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 report some more -%D advanced statistics. -%D -%D \starttyping -%D \showhyphens{dohyphenatedword} -%D \stoptyping - -\permanent\protected\def\doshowhyphenatednextbox - {\clf_showhyphenatedinlist\nextbox} - -\permanent\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua) - {\dowithnextboxcs\doshowhyphenatednextbox\hpack} - -%D The following macros are seldom used but handy for tracing. -%D -%D \starttyping -%D \hyphenatedword{dohyphenatedword} -%D \hyphenatedpar {\dorecurse{10}{dohyphenatedword }} -%D \hyphenatedfile{tufte} -%D \stoptyping - -\def\syst_boxes_hyphenatednextbox {\clf_hyphenatedlist\nextbox false\relax\unhbox\nextbox} -\def\syst_boxes_hyphenatednextboxcolor{\clf_hyphenatedlist\nextbox true \relax\unhbox\nextbox} - -\permanent\protected\def\hyphenatedword {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} -\permanent\protected\def\hyphenatedpar {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} -\permanent\protected\def\hyphenatedfile #1{\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}} -\permanent\protected\def\hyphenatedcoloredword{\dowithnextboxcs\syst_boxes_hyphenatednextboxcolor\hbox} - -%D \macros -%D {processtokens} -%D -%D We fully agree with (most) typographers that inter||letter spacing is only -%D permitted in fancy titles, we provide a macro that can be used to do so. Because -%D this is (definitely and fortunately) no feature of \TEX, we have to step through -%D 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 {\\}, \type {{}} and \type {\ -%D } are handled as space too. - -%D This can be done in a more modern way but for nostalgic reasons we keep it. - -\permanent\protected\def\processtokens#1#2#3#4#5% - {\begingroup - \def\lastcharacter{\lastcharacter}% hm, recursive ? - \enforced\permanent\def\space{ }% - \enforced\let\\\space - \def\before {#1}% - \def\between{#2}% - \def\after {#3}% - \def\white {#4}% - \let\savedbefore\before - \syst_boxes_processtokens#5\lastcharacter - \endgroup} - -\def\syst_boxes_processtokens% the space after = is essential - {\afterassignment\syst_boxes_do_processtokens\let\nextprocessedtoken= } - -\def\syst_boxes_redo_processedtoken - {\dowithnextbox - {\before{\copy\nextbox}% \before can use nextbox several times - \let\before\between - \syst_boxes_processtokens} - \hbox\bgroup} - -\def\syst_boxes_do_processtokens - {\ifx\nextprocessedtoken\lastcharacter - \after - \orelse\ifx\nextprocessedtoken\bgroup - \expandafter\syst_boxes_redo_processedtoken - \else - \expandafter\if\space\nextprocessedtoken - \after\white - \let\before\savedbefore - \else - \before\nextprocessedtoken - \let\before\between - \fi - \expandafter\syst_boxes_processtokens - \fi} - -%D \macros -%D {doboundtext} -%D -%D Sometimes there is not enough room to show the complete (line of) text. In such a -%D situation we can strip of some characters by using \type {\doboundtext}. When the -%D text is wider than the given width, it's split and the third argument is -%D appended. When the text to be checked is packed in a command, we'll have to use -%D \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 third argument into -%D account, which leads to a bit more complex macro than needed at first sight. -%D -%D Sort of obsolete I guess: - -\def\syst_boxes_boundtext#1% - {\setbox\scratchboxone\hbox{#1}% - \advance\scratchdimen -\wd\scratchboxone - \ifdim\scratchdimen>\zeropoint\relax#1\fi} - -\permanent\protected\def\doboundtext#1#2#3% still used? - {\hbox - {\setbox\scratchbox\hbox{#1}% - \scratchdimen#2\relax - \ifdim\wd\scratchbox>\scratchdimen - \setbox\scratchbox\hbox{#3}% - \advance\scratchdimen -\wd\scratchbox - \handletokens#1\with\syst_boxes_boundtext - \fi - \box\scratchbox}} - -%D \macros -%D {limitatetext} -%D -%D A bit more beautiful alternative for the previous command is the next one. This -%D command is more robust because we let \TEX\ do most of the job. The previous -%D command works better 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 sentinel is optional. -%D This is about the third version. - -\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi -\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi - -%D See \MKIV\ file for the older implementation. - -\permanent\protected\def\limitatetext#1#2#3% - {\splitatcomma{#2}\leftlimit\rightlimit - \limitated - left \leftlimit - \ifempty\rightlimit\else - right \rightlimit - \fi - strip true - sentinel {#3} - text {#1} - \relax} - -%D Undocumented bonus (see wiki): -%D -%D \starttyping -%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown} -%D \stoptyping - -\permanent\protected\def\limitatefirstline#1#2#3% - {\hbox\bgroup\strut % \hpack - \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 % \hpack - {\ifx\clip\undefined - \box\plusone - \orelse\ifdim\wd\plusone>\hsize - \lower\strutdepth\hpack{\clip[\c!width=\hsize,\c!height=\lineheight]{\hpack{\raise\strutdepth\box\plusone}}}% - \else - \box\plusone - \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 - -\permanent\protected\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} - -\permanent\protected\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: - -\permanent\protected\def\applytocharacters#1% - {\dontleavehmode - \dowithnextbox{\clf_applytobox - method {char}% - box \nextbox - command {\csstring#1}% - nested true% - \relax}% - \hbox} - -\permanent\protected\def\applytowords#1% - {\dontleavehmode - \dowithnextbox{\clf_applytobox - method {word}% - box \nextbox - command {\csstring#1}% - nested true% - \relax}% - \hbox} - -%D The old call: - -\permanent\protected\def\processwords#1% - {\processisolatedwords{#1}\processword} - -\let\processword\relax - -\permanent\protected\def\applytosplitstringchar#1#2% - {\dontleavehmode\clf_processsplit - data {#2}% - command {\csstring#1}% - method {char}% - \relax} - -\permanent\protected\def\applytosplitstringword#1#2% - {\dontleavehmode\clf_processsplit - data {#2}% - command {\csstring#1}% - method {word}% - \relax} - -\permanent\protected\def\applytosplitstringline#1#2% - {\dontleavehmode\clf_processsplit - data {#2}% - command {\csstring#1}% - method {line}% - \relax} - -\permanent\protected\def\applytosplitstringcharspaced#1#2% - {\dontleavehmode\clf_processsplit - data {#2}% - command {\csstring#1}% - method {char}% - spaced true% - \relax} - -\permanent\protected\def\applytosplitstringwordspaced#1#2% - {\dontleavehmode\clf_processsplit - data {#2}% - command {\csstring#1}% - method {word}% - spaced true% - \relax} - -\permanent\protected\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 and and limits the -%D size to the height and depth of a \type {\strut}. The resulting bottom||alligned -%D box can be used 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 the first two lines -%D would have ended up in the text. This macro can be useful when building -%D complicated menus, headers and footers and|/|or margin material. - -\permanent\protected\def\sbox - {\vpack\bgroup - \dowithnextboxcs\syst_boxes_sbox_finish\vbox} - -\def\syst_boxes_sbox_finish - {\boxyoffset\nextbox-\strutdp - \dp\nextbox\strutdp - \ht\nextbox\strutht - \box\nextbox - \egroup} - -%D A variant on this: -%D -%D \starttyping -%D xx \ruledhbox{\inlinedbox{\tfd test}} xx -%D \stoptyping - -\permanent\protected\def\inlinedbox - {\bgroup - \dowithnextboxcs\syst_boxes_inlined_finish\hbox} - -\def\syst_boxes_inlined_finish - {\boxyoffset\nextbox-\dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax - \ht\nextbox\strutht - \dp\nextbox\strutdp - \box\nextbox - \egroup} - -%D \macros -%D {struttedbox} -%D -%D This boxing macro limits the height and depth to those of a strut. - -\permanent\protected\def\struttedbox - {\hpack\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 and strutheight. Watch -%D how we preserve the depth when it equals strutdepth. - -\permanent\protected\def\topskippedbox - {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox} - -\def\syst_boxes_topskippedbox_finish - {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}% - \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 with positive or -%D negative offsets. This command can be used in well defined areas where no offset -%D options are available. We first used it when building a button inside the margin -%D footer, where the button should have a horizontal offset and should be centered -%D with respect to the surrounding box. The last of the three examples we show below -%D 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 and \type {\vrule} is -%D 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 \type {height}. -%D Observing readers can see that we use \TEX's own scanner for grabbing these -%D arguments: \type {#1#} reads everyting till the next brace and passes it to both -%D rules. The setting of the box dimensions at the end is needed for special cases. -%D The dimensions of the surrounding box are kept intact. This commands handles -%D positive and negative dimensions (which is why we need two boxes with rules). - -\permanent\protected\def\centeredbox#1#% height +/-dimen width +/-dimen - {\bgroup - \dontcomplain - \forgetall - \scangivendimensions#1\relax - \advance\vsize\givenheight - \advance\hsize\givenwidth - \dowithnextboxcs\syst_boxes_centered_finish - \hbox} - -\def\syst_boxes_centered_finish - {\boxxoffset\nextbox.5\dimexpr - \hsize - -\wd\nextbox - -\givenwidth - \relax - \boxyoffset\nextbox.5\dimexpr - \vsize - -\ht\nextbox - +\dp\nextbox - -\givenheight - \relax - \wd\nextbox\dimexpr\hsize-\givenwidth \relax - \ht\nextbox\dimexpr\vsize-\givenheight\relax - \dp\nextbox\zeropoint - \box\nextbox - \egroup} - -%D For those who don't want to deal with \type {\hsize} and \type {\vsize}, we have: -%D -%D \starttyping -%D \centerednextbox width 2bp height 2bp -%D {\framed[width=100bp,height=100bp]{}} -%D \stoptyping -%D -%D Do you see why we call this one \type {next}? - -\permanent\protected\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 {content} -%D \stoptyping -%D -%D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local -%D dimensions are supported. - -\permanent\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen - {\bgroup - \dowithnextbox - {\setlocalhsize - \setbox\scratchbox\hpack{\vrule\s!width \zeropoint#1}% - \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi - \setbox\scratchbox\vpack{\hrule\s!height\zeropoint#1}% - \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi - \vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}% - \egroup}% - \hbox} - -%D \macros -%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines} -%D -%D These macros are copied from the \TEX book, page~397, and extended by a macro -%D 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 footnotes. The following -%D flags influence the process. - -\newif\ifalignrigidcolumns -\newif\ifstretchrigidcolumns -\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections - -\permanent\protected\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 - -\permanent\protected\def\rigidcolumnbalance#1% - {\ifnum\rigidcolumns=1 % tzt ook h/d correctie - \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax - \else - \vbox % \vpack - {\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\vtop - \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 pages 398 and 399 of the -%D \TEX book. These macros can be used 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 what they're meant -%D for. - -\newdimen\vboxtohboxslack -\newdimen\hboxestohboxslack - -%D Create line and fake height of paragraph by messign with heights: a nice hack by -%D DEK himself. - -%\protected\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} -% -% \protected\def\startvboxtohbox -% {\bgroup -% \setvboxtohbox -% \setbox\scratchbox\hbox\bgroup} -% -% \protected\def\stopvboxtohbox -% {\ifcase\vboxtohboxslack\else\hskip\zeropoint\s!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 - -\permanent\protected\def\startvboxtohboxseparator - {\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup} - -\permanent\protected\def\stopvboxtohboxseparator - {\egroup} - -\permanent\protected\def\startvboxtohbox - {\begingroup - \setbox\scratchbox\hbox\bgroup} - -\permanent\protected\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: - -\permanent\protected\def\convertvboxtohbox - {\makehboxofhboxes - \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack - \noindent\unhbox\scratchboxone\par} - -\permanent\protected\def\makehboxofhboxes - {\setbox\scratchboxone\emptyhbox - \loop % \doloop { .. \exitloop .. } - \setbox\scratchboxtwo\lastbox - \ifhbox\scratchboxtwo - \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}% - \repeat} - -\permanent\protected\def\removehboxes - {\setbox\scratchboxone\lastbox - \ifhbox\scratchboxone - {\removehboxes}\unhbox\scratchboxone - \fi} - -% And one special for notes: - -\permanent\protected\def\starthboxestohbox - {\bgroup - \setbox\scratchbox\vbox\bgroup} - -\permanent\protected\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. Let's first look at the -%D macro and then show an example. - -\newbox \unhhedbox -\newbox \hhbox -\newdimen \lasthhboxwidth -\newskip \hhboxindent - -\permanent\protected\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}% \hpack - \fi - \ht\hhbox\strutht - \dp\hhbox\strutdp - \ifzeropt\hhboxindent\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\syst_boxes_hboxofvbox - {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}% - \unhbox1 - \egroup} - -\permanent\protected\def\hboxofvbox - {\bgroup - \afterassignment\syst_boxes_hboxofvbox - \scratchcounter=} - -%D This macro can be used to break a paragraph apart and treat each line seperately, -%D for instance, making it clickable. The main complication is that we want to be -%D able to continue the 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 we've build in the -%D line that connects the two paragraphs. - -%D \macros -%D {doifcontent} -%D -%D When processing depends on the availability of content, one can give the next -%D 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 \type {\vbox}. If the -%D dimension of this box suggest some content, the resulting box is unboxed and -%D surrounded by the first two arguments, else the third arguments is executed. - -\permanent\protected\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 document, but definitely -%D generates a confusing message. - -%D \macros -%D {processboxes} -%D -%D The next macro gobble boxes and is for instance used for overlays. First we show -%D the general handler. - -\newbox\processbox % public : this is the one where \nextbox's end up in - -\permanent\protected\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} - -\protected\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 - -\permanent\def\boxisempty#1% - {\ifdim\wd#1=\zeropoint - \ifdim\ht#1=\zeropoint - \ifdim\dp#1=\zeropoint - \zerocount - \else - \plusone - \fi - \else - \plusone - \fi - \else - \plusone - \fi} - -\def\syst_boxes_overlay_process - {\ifcase\boxisempty\nextbox\else - \syst_boxes_overlay_process_indeed - \fi} - -\def\syst_boxes_overlay_process_indeed - {%\removeunwantedspaces % already done - \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi - \ifdim\ht\nextbox>\ht\processbox - \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}}} - -\permanent\protected\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 specified, here being zero. - -\permanent\protected\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 accept something like -%D \type {to 3cm}, but align to the left, middle and right. These box types can be -%D used to typeset paragraphs. - -\def\syst_boxes_lrc_process#1% - {\bgroup - \forgetall - \enforced\let\\\endgraf - #1% - \let\nexttoken} - -\permanent\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft } -\permanent\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter} -\permanent\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright } - -\permanent\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft } -\permanent\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter} -\permanent\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright } - -%D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align -%D boxes, like in: -%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 - -\permanent\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} -\permanent\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} - -\def\syst_boxes_tbox_finish - {\scratchheight\ht\strutbox - \scratchdepth\dimexpr\htdp\nextbox-\scratchheight\relax - \ht\nextbox\scratchheight - \dp\nextbox\scratchdepth - \boxyoffset\nextbox-\scratchdepth - \box\nextbox - \egroup} - -\def\syst_boxes_bbox_finish - {\scratchdepth\dp\strutbox - \scratchheight\dimexpr\htdp\nextbox-\scratchdepth\relax - \dp\nextbox\scratchdepth - \ht\nextbox\scratchheight - \boxyoffset\nextbox-\scratchdepth - \box\nextbox - \egroup} - -%D \macros -%D {lhbox,mhbox,rhbox} -%D -%D A few more boxes. - -\def\syst_boxes_lhbox{\hpack to \hsize{\box\nextbox\hss }} -\def\syst_boxes_mhbox{\hpack to \hsize{\hss\box\nextbox\hss}} -\def\syst_boxes_rhbox{\hpack to \hsize{\hss\box\nextbox }} - -\permanent\protected\def\lhbox{\dowithnextboxcs\syst_boxes_lhbox\hbox} -\permanent\protected\def\mhbox{\dowithnextboxcs\syst_boxes_mhbox\hbox} -\permanent\protected\def\rhbox{\dowithnextboxcs\syst_boxes_rhbox\hbox} - -\let\lefthbox \lhbox -\let\midhbox \mhbox -\let\righthbox\rhbox - -%D \macros -%D {boxofsize} -%D -%D Sometimes we need to construct a box with a height or width made up of several -%D dimensions. Instead of cumbersome 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 negative values. -%D Dimension registers are also accepted. - -\newdimen\sizeofbox - -\permanent\protected\def\boxofsize#1% - {\bgroup - \sizeofbox\zeropoint - \scratchdimen\zeropoint - \def\docommand - {\advance\sizeofbox\scratchdimen - \futurelet\nexttoken\dodocommand}% - \def\dodocommand - {\ifx\nexttoken\bgroup - \expanded{\egroup#1 to \the\sizeofbox}% - \else - \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen - \fi}% - \docommand} - -%D Some new, still undocumented features: - -% limitatetext -> beter {text} als laatste !! -% -% \limitvbox -% \limithbox - -\permanent\protected\def\limitatelines#1#2% size sentinel - {\dowithnextbox - {\scratchdimen#1\hsize - \ifdim\wd\nextbox>\scratchdimen - \setbox\nextbox\hbox - {\advance\scratchdimen -.1\hsize - \limitatetext{\unhbox\nextbox}{\scratchdimen}{\nobreak#2}}% - \fi - \unhbox\nextbox} - \hbox} - -\permanent\protected\def\fittoptobaselinegrid % weg hier - {\dowithnextbox - {\bgroup - \par - \scratchdimen\ht\nextbox - \ht\nextbox\strutht - \dp\nextbox\strutdp - \hpack{\box\nextbox} - \prevdepth\strutdp - \doloop - {\advance\scratchdimen -\lineheight - \ifdim\scratchdimen<\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\hpack - {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} - -\permanent\protected\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} - -\permanent\protected\def\placedbox - {\iftraceboxplacement\ruledhbox\else\hbox\fi} - -\newdimen\boxoffset -\newdimen\boxhdisplacement -\newdimen\boxvdisplacement - -\permanent\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox} -\permanent\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox} -\permanent\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox} -\permanent\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox} -\permanent\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox} -\permanent\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox} -\permanent\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox} -\permanent\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox} - -\let\topleftbox \lefttopbox -\let\toprightbox \righttopbox -\let\bottomleftbox \leftbottombox -\let\bottomrightbox\rightbottombox - -\def\syst_boxes_rightbox_finish - {\global\boxhdisplacement\boxoffset - \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_leftbox_finish - {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax - \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_topbox_finish - {\global\boxhdisplacement-.5\wd\nextbox - \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_bottombox_finish - {\global\boxhdisplacement-.5\wd\nextbox - \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_lefttopbox_finish - {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax - \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_righttopbox_finish - {\global\boxhdisplacement\boxoffset - \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_leftbottombox_finish - {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax - \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_rightbottombox_finish - {\global\boxhdisplacement\boxoffset - \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\permanent\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox} -\permanent\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox} -\permanent\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox} -\permanent\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox} - -\def\syst_boxes_middlebox_finish - {\global\boxhdisplacement-.5\wd\nextbox - \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_baselinemiddlebox_finish - {\global\boxhdisplacement\dimexpr-.5\wd\nextbox-\boxoffset\relax - \global\boxvdisplacement-\boxoffset - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_baselineleftbox_finish - {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax - \global\boxvdisplacement-\boxoffset - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -\def\syst_boxes_baselinerightbox_finish - {\global\boxhdisplacement\boxoffset - \global\boxvdisplacement-\boxoffset - \boxcursor - \boxxmove\nextbox \boxhdisplacement - \boxymove\nextbox-\boxvdisplacement - \box\nextbox - \egroup} - -%D \macros -%D {obox} -%D -%D Experimental, not yet frozen: - -\permanent\protected\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: - -\permanent\protected\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 have implemented a box -%D 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} - -\permanent\protected\def\setstackbox#1#2% - {\ifcsname\??stackbox#1:#2\endcsname\else - \expandafter\newbox\csname\??stackbox#1:#2\endcsname - \fi - \global\setbox\csname\??stackbox#1:#2\endcsname\vbox} - -\permanent\protected\def\initializeboxstack#1% - {\def\docommand##1{\setstackbox{#1}{##1}{}}% - \ifcsname\??stacklst#1\endcsname - \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand - \fi - \letgvalueempty{\??stacklst#1}} - -\permanent\protected\def\savebox#1#2% stack name - {% beware, \setxvalue defines the cs beforehand so we cannot use the - % test inside the { } - \ifcsname\??stacklst#1\endcsname - %\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}} - -\permanent\protected\def\flushbox#1#2% unwrapped - {\ifcsname\??stackbox#1:#2\endcsname - \box\lastnamedcs - \else - \emptybox - \fi} - -\permanent\protected\def\restorebox#1#2% unwrapped - {\ifcsname\??stackbox#1:#2\endcsname - \copy\lastnamedcs - \else - \emptybox - \fi} - -\permanent\protected\def\foundbox#1#2% wrapped - {\vpack - {\ifcsname\??stackbox#1:#2\endcsname - \copy\lastnamedcs - \fi}} - -\permanent\protected\def\doifelsebox#1#2% - {\ifcsname\??stackbox#1:#2\endcsname - \ifvoid\lastnamedcs - \doubleexpandafter\secondoftwoarguments - \else - \doubleexpandafter\firstoftwoarguments - \fi - \else - \expandafter\secondoftwoarguments - \fi} - -\let\doifboxelse\doifelsebox - -%D This one is cheaper (the above is no longer used that much): - -\installcorenamespace {boxstack} - -\newcount\c_syst_boxes_stack - -\mutable\let\b_syst_boxes_stack\relax - -\protected\def\syst_boxes_stack_allocate - {\newbox\b_syst_boxes_stack - \letcsname\??boxstack\number\c_syst_boxes_stack\endcsname\b_syst_boxes_stack} - -\protected\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} - -\protected\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} - -\permanent\protected\def\localpushbox {\syst_boxes_push\relax} -\permanent\protected\def\localpopbox {\syst_boxes_pop \relax} - -\permanent\protected\def\globalpushbox{\syst_boxes_push\global} -\permanent\protected\def\globalpopbox {\syst_boxes_pop \global} - -%D And here is a more modern one (not yet in i-*): -%D -%D \starttyping -%D \dorecurse {100} { -%D \setbox\zerocount\hbox{test \recurselevel} -%D \putboxincache{foo}{\recurselevel}\zerocount -%D \copyboxfromcache{foo}{\recurselevel}\zerocount -%D \iftrue -%D \setbox\zerocount\hbox{\directboxfromcache{foo}{\recurselevel}}% -%D \else -%D \getboxfromcache{foo}{\recurselevel}\zerocount -%D \fi -%D } -%D \resetboxesincache{foo} -%D \stoptyping - -\permanent\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax} -\permanent\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax} -\permanent\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}} -\permanent\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax} -\permanent\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}} -\permanent\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}} -\permanent\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}} - -\permanent\protected\def\putnextboxincache#1#2% - {\dowithnextbox{\putboxincache{#1}{#2}\nextbox}} - -%D \macros -%D {removedepth, obeydepth} -%D -%D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes -%D sure we have depth. Both macros leave the \type {\prevdepth} untouched. - -\permanent\protected\def\removedepth - {\ifvmode - \ifdim\prevdepth>\zeropoint - \kern-\prevdepth - \fi - \fi} - -\permanent\protected\def\obeydepth - {\par % watch out for changes in math formulas - \ifvmode\ifdim\prevdepth<\zeropoint\orelse\ifdim\prevdepth<\strutdp - \kern\dimexpr\strutdp-\prevdepth\relax - \prevdepth\strutdp - \fi\fi} - -\permanent\protected\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. - -\permanent\protected\def\removebottomthings - {\dorecurse\plusfive{\unskip\unkern\unpenalty}} - -\permanent\protected\def\removelastskip % \ifvmode the plain tex one \fi, overloaded to \permanent in spac-ver - {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} - -%D \macros -%D {makestrutofbox} -%D -%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so -%D it will go away. - -\permanent\protected\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 construction). Nice stuff for -%D a tips and tricks maps article. -%D -%D \starttyping -%D \raisebox{100pt}\hbox{test} -%D \hsmash{\raisebox{100pt}\hbox{test}} -%D \stoptyping - -\permanent\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted -\permanent\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted - -\def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish} -\def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish} - -\def\syst_boxes_raise_finish - {\boxyoffset\nextbox\scratchdimen - \ht\nextbox\strutht - \dp\nextbox\strutdp - \box\nextbox - \egroup} - -\def\syst_boxes_lower_finish - {\boxyoffset\nextbox-\scratchdimen - \ht\nextbox\strutht - \dp\nextbox\strutdp - \box\nextbox - \egroup} - -% vcenter in text, we kunnen vcenter overloaden - -\permanent\protected\def\halfwaybox - {\hpack\bgroup - \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox} - -\def\syst_boxes_halfwaybox_finish - {\dp\nextbox\zeropoint - \lower.5\ht\nextbox\box\nextbox - \egroup} - -\permanent\protected\def\depthonlybox - {\tpack\bgroup - \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox} - -\def\syst_boxes_depthonlybox_finish - {\hsize\wd\nextbox - \kern\zeropoint\box\nextbox - \egroup} - -%D New: - -\permanent\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi} -\permanent\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi} - -%D And even rawer: - -\let\naturalvcenter\normalvtop % will go away - -% \appendtoks \let\vcenter\normalvcenter \to \everymathematics - -%D \macros -%D {frozenhbox} -%D -%D A not so well unhboxable box can be made with: - -\permanent\protected\def\frozenhbox - {\hpack\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} - -\permanent\protected\def\setboxllx #1#2{\edefcsname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} -\permanent\protected\def\setboxlly #1#2{\edefcsname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} - -\permanent\protected\def\gsetboxllx#1#2{\global\edefcsname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} -\permanent\protected\def\gsetboxlly#1#2{\global\edefcsname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} - -\permanent\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi} -\permanent\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi} - -\permanent\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence -\permanent\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence - -%D \macros -%D {shownextbox} -%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 - -\permanent\protected\def\shownextbox % seldom used - {\dowithnextbox - {\bgroup - \showboxbreadth\maxdimen - \showboxdepth \maxdimen - \scratchcounter\interactionmode - \batchmode - \showbox\nextbox - \box\nextbox - \interactionmode\scratchcounter - \egroup}} - -\permanent\protected\def\spreadhbox#1% rebuilds \hbox{} - {\bgroup - \ifhbox#1\relax - \setbox\scratchboxtwo\emptybox - \unhbox#1% - \doloop - {\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip - \setbox\scratchboxone\lastbox - \ifvoid\scratchboxone - \exitloop - \else - \setbox\scratchboxtwo\hbox - {\ifhbox\scratchboxone \spreadhbox\scratchboxone\else\box\scratchboxone\fi - \ifvoid\scratchboxtwo \else\hss\unhbox\scratchboxtwo\fi}% - \fi}% - \ifvoid\scratchboxtwo\else\unhbox\scratchboxtwo\fi - \else - \box#1% - \fi - \egroup} - -% Why not ... - -\showboxbreadth\plusthousand -\showboxdepth \plusthousand - -%D Moved from cont-new: -%D -%D \starttyping -%D \minimalhbox 100pt {test} -%D \stoptyping - -\permanent\protected\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: - -\permanent\protected\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 - -\let\getnaturalwd\clf_getnaturalwd % no intermediate -\let\setnaturalwd\clf_setnaturalwd % no intermediate - -\permanent\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox} - -\let\doifrighttoleftinboxelse\doifelserighttoleftinbox - -%D New, used in high/low: - -\definesystemattribute [runningtext] [public] - -\permanent\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-* - -%D To complement lua (yet undocumented): - -\permanent\protected\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup -\permanent\protected\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup -\permanent\protected\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup - -\permanent\protected\def\sethboxregister#1{\setbox#1\hbox} -\permanent\protected\def\setvboxregister#1{\setbox#1\vbox} -\permanent\protected\def\setvtopregister#1{\setbox#1\vtop} - -\permanent\protected\def\flushboxregister#1{\box\numexpr#1\relax} - -\permanent\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup -\permanent\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup -\permanent\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup - -%D For whatever third party package needs it: -%D -%D \starttyping -%D \newlocalbox\BoxOne -%D \newlocalbox\BoxTwo -%D -%D \setbox\BoxOne\hbox{Box One} -%D \setbox\BoxTwo\hbox{Box Two} -%D -%D [\box\BoxTwo] [\box\BoxOne] -%D \stoptyping - -\installcorenamespace{localbox} - -\permanent\protected\def\newlocalbox#1% - {\expandafter\let\expandafter#1\csname\??localbox\string#1\endcsname - \ifx#1\relax - \syst_aux_new_localbox#1% - \fi} - -\def\syst_aux_new_localbox#1% - {\expandafter\newbox\csname\??localbox\string#1\endcsname - \newlocalbox#1} - -%D Who knows when this comes in handy: - -\permanent\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax} - -%D Keep as reference: - -% \protected\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox} -% \protected\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop} - -%D This one keeps dimensions and sets the shift field (and so it's more for testing -%D than for real usage): - -\permanent\protected\def\shiftbox {\clf_shiftbox} -\permanent\protected\def\vpackbox {\clf_vpackbox} -\permanent\protected\def\hpackbox {\clf_hpackbox} -\permanent\protected\def\vpackedbox{\clf_vpackedbox} -\permanent\protected\def\hpackedbox{\clf_hpackedbox} - -%D This one has been moved from a 2 decade old file. It makes something boxed -%D sit on the baseline. - -\protected\def\linebox - {\hpack\bgroup\dowithnextbox - {\scratchdimen\dimexpr\dimexpr\htdp\nextbox-\lineheight\relax/2+\dp\strutbox\relax - \setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}% - \ht\nextbox\ht\strutbox - \dp\nextbox\dp\strutbox - \box\nextbox - \egroup} - \hbox} - -%D \macros -%D {widthuptohere} -%D -%D Implemented at the \LUA\ end: -%D -%D \startbuffer -%D widthuptohere:\the\widthuptohere\crlf -%D widthuptohere : \the\widthuptohere (space without stretch or shrink!) -%D \stopbuffer -%D -%D \typebuffer \blank \getbuffer \blank -%D -%D Implemented elsewhere: -%D -%D \starttyping -%D \boxlines -%D \boxline -%D \copyboxline -%D \setboxline -%D \boxlineht [] -%D \boxlinedp [] -%D \boxlinewd [] -%D \boxlinels -%D \boxliners -%D \boxlinelh -%D \boxlinerh -%D \boxlinelp -%D \boxlinerp -%D \boxlinein -%D \boxrangeht -%D \boxrangedp -%D \boxrangewd -%D \stoptyping - -% To be discussed with ws. -% -% \installcorenamespace{namedboxes} -% -% \protected\def\newnamedbox#1% -% {\ifcsname\??namedboxes#1\endcsname\else -% \expandafter\newbox\csname\??namedboxes#1\endcsname -% \fi} -% -% \protected\def\namedbox#1{\csname\??namedboxes#1\endcsname} - -%D Implemented elsewhere: -%D -%D \startbuffer -%D \setbox0\hbox{test \footnote{test}} (\prelistbox0) (\postlistbox0) -%D \setprelistbox0\hbox{BEFORE} \setpostlistbox0\hbox{AFTER} -%D \box0 -%D \stopbuffer -%D -%D \typebuffer \blank \getbuffer \blank -%D -%D \starttyping -%D \prelistbox -%D \postlistbox -%D \prelistcopy -%D \postlistcopy -%D \setprelistbox -%D \setpostlistbox -%D \stoptyping - -\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 -% -% \protected\def\withwordsinstring#1#2% command str -% {\ctxcommand{withwords(\!!bs#1\!!es,\!!bs#2\!!es)}} -% -% \protected\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/tex/context/base/mkiv/supp-dir.mkxl b/tex/context/base/mkiv/supp-dir.mkxl deleted file mode 100644 index e6c2a5869..000000000 --- a/tex/context/base/mkiv/supp-dir.mkxl +++ /dev/null @@ -1,54 +0,0 @@ -%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. - -\unprotect - -\chardef\directionlefttoright\zerocount -\chardef\directionrighttoleft\plusone - -\edef\??bdir{\ifdefined\bodydir bdir\else direction\fi} - -\protected\edef\naturalhbox {\hbox \??bdir\directionlefttoright} -\protected\edef\naturalvbox {\vbox \??bdir\directionlefttoright} -\protected\edef\naturalvtop {\vtop \??bdir\directionlefttoright} -\protected\edef\naturalhpack {\hpack \??bdir\directionlefttoright} -\protected\edef\naturalvpack {\vpack \??bdir\directionlefttoright} -\protected\edef\naturaltpack {\tpack \??bdir\directionlefttoright} - -\protected\edef\reversehbox {\hbox \??bdir\directionrighttoleft} -\protected\edef\reversevbox {\vbox \??bdir\directionrighttoleft} -\protected\edef\reversevtop {\vtop \??bdir\directionrighttoleft} -\protected\edef\reversehpack {\hpack \??bdir\directionrighttoleft} -\protected\edef\reversevpack {\vpack \??bdir\directionrighttoleft} -\protected\edef\reversetpack {\tpack \??bdir\directionrighttoleft} - -\ifdefined\bodydir - \let\bodydir \undefined \let\normalbodydir \undefined - \let\bodydirection\undefined \let\normalbodydirection\undefined -\fi - -\ifdefined\pagedir - \let\pagedir \undefined \let\normalpagedir \undefined - \let\pagedirection\undefined \let\normalpagedirection\undefined -\fi - -% \expanded{\defineactivecharacter \number"2000E} {\textdirection\directionrighttoleft\relax} -% \expanded{\defineactivecharacter \number"2000F} {\textdirection\directionlefttoright\relax} - -\def\syst_direction_string#1{\ifcase#1=\plusone r2l\else l2r\fi} - -\protected\def\showdirsinmargin - {\normalexpanded{\inleft{\naturalhbox - {\ttxx[\syst_direction_string\pardirection,\syst_direction_string\textdirection]}}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/supp-mat.mkxl b/tex/context/base/mkiv/supp-mat.mkxl deleted file mode 100644 index 7e0086fc8..000000000 --- a/tex/context/base/mkiv/supp-mat.mkxl +++ /dev/null @@ -1,180 +0,0 @@ -%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 a support module. -%D There is nothing spectacular here. It may move 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. This can lead to -%D confusing and errorprone situations when macros insert \type {$}. When for -%D 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 definitely -%D complain about this. A more save definition would have been: -%D -%D \starttyping -%D \def\MyPlus{\mathematics{\,+\,}} -%D \stoptyping -%D -%D Which is implemented (in \type{syst-ini.mkiv}) as: - -\permanent\protected\def\Ucheckedstartdisplaymath - {\ifinner - \ifhmode - \normalUstartmath - \let\Ucheckedstopdisplaymath\normalUstopmath - \else - \normalUstartdisplaymath - \let\Ucheckedstopdisplaymath\normalUstopdisplaymath - \fi - \else - \normalUstartdisplaymath - \let\Ucheckedstopdisplaymath\normalUstopdisplaymath - \fi} - -\aliased\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 - -\aliased\let\startimath\Ustartmath -\aliased\let\stopimath \Ustopmath -\aliased\let\startdmath\Ustartdisplaymath % \Ucheckedstartdisplaymath -\aliased\let\stopdmath \Ustopdisplaymath % \Ucheckedstopdisplaymath - -\permanent\protected\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi} -\permanent\protected\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi} -\permanent\protected\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi} -\permanent\protected\def\textmath #1{\dontleavehmode\ifmmode#1\else\begingroup\everymath\emptytoks\normalstartimath#1\normalstopimath\endgroup\fi} % \mathsurround\zeropoint - -\aliased\let\stopmathmode\relax - -\permanent\protected\def\startmathmode % nested variant - {\relax\ifmmode - \begingroup - \enforced\let\stopmathmode\endgroup - \else - \normalstartimath - \enforced\let\stopmathmode\normalstopimath - \fi} - -\permanent\protected\def\nomathematics#1% - {\relax\ifmmode\hbox{#1}\else#1\fi} - -\aliased\let\m \mathematics % \mathematics will be overloaded later -\aliased\let\math\mathematics % \mathematics will be overloaded later - -%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 - -\permanent\protected\def\displaymathematics#1{\relax\ifmmode#1\else\strc_formulas_start_formula{}#1\strc_formulas_stop_formula\fi} -\permanent\protected\def\inlinemathematics {\dontleavehmode\mathematics} -%permanent\protected\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi} - -% better, esp when used in bTABLE ... eTABLE - -\permanent\protected\def\automathematics - {\relax - \ifhmode - \expandafter\inlinemathematics - \orelse\ifintable - \doubleexpandafter\inlinemathematics - \else - \doubleexpandafter\displaymathematics - \fi} - -%D \macros -%D {dimension, nodimension} -%D -%D The next few macros are used for typesetting dimensions in such a way that -%D spacing is acceptable. I won't spend much words on these macros, because they -%D will be overloaded in the units module. -%D -%D REPLACED (keep commented): - -\newsignal\dimensionsignal - -\def\dimensiontypeface {\tf} -\def\dimensionhalfspace {\,} - -\protected\def\dimension#1% - {\pushmacro\dodimensionsignal - \gdef\dodimensionsignal{\kern\dimensionsignal}% - \ifzeropt\lastskip - \ifzeropt\lastkern - \ifmmode - \mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% - \else - \mathematics{\dimensiontypeface#1}% - \fi - \orelse\ifdim\lastkern=\dimensionsignal - \mathematics{\dimensionhalfspace\dimensiontypeface#1}% - \else - \unkern\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% - \fi - \else - \unskip\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% - \fi - \dodimensionsignal - \popmacro\dodimensionsignal} - -\protected\def\nodimension#1% - {\unskip#1\glet\dodimensionsignal\relax} - -% experiment, not yet to be used - -% \protected\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} - -\aliased\let\superscript \Usuperscript -\aliased\let\subscript \Usubscript -\aliased\let\nosuperscript \Unosuperscript -\aliased\let\nosubscript \Unosubscript -\aliased\let\superprescript \Usuperprescript -\aliased\let\subprescript \Usubprescript -\aliased\let\nosuperprescript\Unosuperprescript -\aliased\let\nosubsprecript \Unosubprescript - -\protect \endinput diff --git a/tex/context/base/mkiv/symb-emj.mkxl b/tex/context/base/mkiv/symb-emj.mkxl deleted file mode 100644 index 96c4c0859..000000000 --- a/tex/context/base/mkiv/symb-emj.mkxl +++ /dev/null @@ -1,26 +0,0 @@ -%D \module -%D [ file=symb-emj, -%D version=2017.04.21, -%D title=\CONTEXT\ Symbol Libraries, -%D subtitle=Emoji, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Symbol Libraries / Emoji} - -\registerctxluafile{symb-emj}{} - -\unprotect - -\permanent \def\expandedemoji#1{\clf_resolvedemoji{#1}} -\permanent\protected\def\resolvedemoji#1{\clf_resolvedemoji{#1}} -\permanent\protected\def\checkedemoji #1{\clf_checkedemoji {#1}} -\permanent\protected\def\emoji #1{\dontleavehmode{\setdirectsymbolicfont{emoji}\clf_resolvedemoji{#1}}} -\permanent\protected\def\robustemoji #1{\dontleavehmode{\setdirectsymbolicfont{emoji}\clf_checkedemoji {#1}}} - -\protect \endinput diff --git a/tex/context/base/mkiv/symb-ini.mkxl b/tex/context/base/mkiv/symb-ini.mkxl deleted file mode 100644 index 53a1f8979..000000000 --- a/tex/context/base/mkiv/symb-ini.mkxl +++ /dev/null @@ -1,341 +0,0 @@ -%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 {core-con} module. I -%D decided to move them here when symbolsets saw the light. Let their light shine. - -\writestatus{loading}{ConTeXt Symbol Libraries / Initialization} - -\registerctxluafile{symb-ini}{} - -\unprotect - -%D \macros -%D {definesymbol, symbol} -%D -%D Converting numbers or levels into a character, romannumeral, symbol or something -%D else, is supported by many \CONTEXT\ commands. Therefore we need a mechanism for -%D linking such numbers to their counterparts. -%D -%D First we take care of symbols. These are for instance used in enumerations and -%D itemizations. We have: -%D -%D \showsetup{definesymbol} -%D \showsetup{symbol} -%D -%D Symbols are simply linked to a tag. Such tags can be numbers or strings. -%D -%D \starttyping -%D \definesymbol [1] [$\bullet$] -%D \definesymbol [level 5] [$\star$] -%D \stoptyping - -\installcorenamespace{symbol} -\installcorenamespace{symbols} -\installcorenamespace{symbolset} -\installcorenamespace{symboldefault} - -%D For now we only have one option. - -\installparameterhandler\??symbols {symbols} -\installsetuphandler \??symbols {symbols} - -\appendtoks - \doifelse{\symbolsparameter\c!stylealternative}\v!math - \settrue\setfalse\prefermathovertextchar -\to \everysetupsymbols - -\setupsymbols - [\c!stylealternative=\v!text] - -\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 subsystem for resolving -%D values. - -\permanent\tolerant\protected\def\definesymbol[#1]#*[#2]#*[#3]% - {\ifparameter#3\or - \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} - -\permanent\protected\def\doifelseinsymbolset#1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} -\permanent\protected\def\doifinsymbolset #1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} -\permanent\protected\def\doifelsesymbolset #1{\ifcsname\??symbolset#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} - -\aliased\let\doifinsymbolsetelse\doifelseinsymbolset -\aliased\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 - -\permanent\def\symbolset#1{\begincsname\??symbolset#1\endcsname} % no [#1], to be used in commalists etc - -%D Since symbols are used frequently in interactive documents, we speed up this one. -%D Well, that was history, 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}. - -\permanent\tolerant\protected\def\symbol[#1]#*[#2]% - {\ifarguments - \expandafter\symb_place_argument - \or - \symb_place_argument{#1}% - \or - \dontleavehmode - \edef\currentsymbol{#2}% - \ifcsname\??symbol#1:#2\endcsname - \symb_place_indeed{#1:#2}% maybe use \lastnamescs - \orelse\ifcsname\??symboldefault#1\endcsname - \symb_place_named{#1}% maybe use \lastnamescs - \else - \symb_place_normal - \fi - \fi} - -\def\symb_place_argument#1% - {\dontleavehmode - \edef\currentsymbol{#1}% - \ifcsname\??symbol\currentsymbolset:#1\endcsname - \symb_place_indeed{\currentsymbolset:#1}% - \else - \symb_place_normal - \fi} - -\def\symb_place_normal - {\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_indeed#1% \relax's prevent lookahead problems - {\settrue\c_symb_found - \begingroup - \the\everysymbol - \csname\??symbol#1\endcsname\relax - \endgroup} - -\letvalue{\??symbol}\firstofoneargument - -\permanent\def\directsymbol#1#2% no \relax, there can be an argument, see lists - {\begincsname\??symbol#1:#2\endcsname} - -\protected\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}% - \orelse\ifcsname\??symboldefault#1\endcsname - \symb_place_named{#1}% - \fi} - -\def\symb_place_named#1% \relax's prevent lookahead problems - {\begingroup - \setbox\scratchbox\hbox\bgroup - \the\everysymbol - \getglyphstyled - {\csname\??symboldefault#1\endcsname}% - {\tochar{n:\currentsymbol}}% - \relax - \egroup - \ifdim\wd\scratchbox>\zeropoint - \unhbox\scratchbox - \endgroup - \setxvalue{\??symbol#1:\currentsymbol}% - {\symb_place_named_indeed{#1}{\currentsymbol}}% - \settrue\c_symb_found - \else - \endgroup - \fi} - -\protected\def\symb_place_named_indeed#1#2% \relax's prevent lookahead problems - {\settrue\c_symb_found - \begingroup - \the\everysymbol - \getglyphstyled - {\csname\??symboldefault#1\endcsname}% - {\tochar{n:#2}}% - \relax - \endgroup} - -\def\symb_place_retry#1% - {\ifcsname\??symbol:#1\endcsname - \symb_place_indeed{:#1}% - \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 size or running font -%D size (which is better). - -\ifdefined\externalfigure \else \def\externalfigure[#1][#2]{#1} \fi - -\def\defaultsymbolfactor{10} -\def\defaultsymbolheight{1.25ex} - -\permanent\tolerant\protected\def\figuresymbol[#1]#*[#2]% - {\externalfigure[#1][\c!reset=\v!yes,\c!symbol=\v!yes,\c!height=\defaultsymbolheight,#2]} - -\permanent\tolerant\protected\def\definefiguresymbol[#1]#*[#2]#*[#3]% - {\ifarguments\or\else - \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}} - -\permanent\protected\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} - -\aliased\let\doifsymboldefinedelse\doifelsesymboldefined - -%D \macros -%D {setupsymbolset,startsymbolset} -%D -%D From these macro definitions one can deduce that symbols can be grouped in -%D 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} - -\permanent\tolerant\protected\def\startsymbolset[#1]#*[#2]% - {\pushmacro\m_symb_current_set - \def\m_symb_current_set{#1}% - \ifarguments\or\or - \getdummyparameters[\s!font=,#2]% - \edef\p_font{\dummyparameter\s!font}% - \ifempty\p_font\else - \letvalue{\??symboldefault#1}\p_font - \fi - \fi} - -\permanent\protected\def\stopsymbolset - {\popmacro\m_symb_current_set} - -\permanent\protected\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 - -\permanent\protected\def\resetsymbolset - {\t_symb_setups\emptytoks} - -\permanent\protected\def\forcesymbolset[#1]% - {\t_symb_setups{\symb_fetch{#1}}} - -%D \macros -%D {showsymbolset} -%D -%D \showsetup{showsymbolset} - -\fetchruntimecommand \showsymbolset \f!symb_run - -%D \macros -%D {usesymbols} -%D -%D \showsetup{usesymbols} - -\permanent\protected\def\usesymbols[#1]{\clf_usesymbols{#1}} - -%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. - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-aux.lmt b/tex/context/base/mkiv/syst-aux.lmt deleted file mode 100644 index c0de8a953..000000000 --- a/tex/context/base/mkiv/syst-aux.lmt +++ /dev/null @@ -1,747 +0,0 @@ - if not modules then modules = { } end modules ['syst-aux'] = { - version = 1.001, - comment = "companion to syst-aux.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- slower than lpeg: --- --- utfmatch(str,"(.?)(.*)$") --- utf.sub(str,1,1) - -local tonumber, next, type = tonumber, next, type -local utfsub = utf.sub -local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match -local find, formatters = string.find, string.formatters - -local context = context -local implement = interfaces.implement -local setmacro = interfaces.setmacro -local setcatcode = tex.setcatcode -local texget = tex.get -local utf8character = lpeg.patterns.utf8character -local settings_to_array = utilities.parsers.settings_to_array -local settings_to_set = utilities.parsers.settings_to_set - -local pattern = C(utf8character^-1) * C(P(1)^0) - -implement { - name = "getfirstcharacter", - arguments = "string", - actions = function(str) - local first, rest = lpegmatch(pattern,str) - setmacro("firstcharacter",first) - setmacro("remainingcharacters",rest) - end -} - -implement { - name = "thefirstcharacter", - arguments = "string", - actions = function(str) - local first, rest = lpegmatch(pattern,str) - context(first) - end -} - -implement { - name = "theremainingcharacters", - arguments = "string", - actions = function(str) - local first, rest = lpegmatch(pattern,str) - context(rest) - end -} - -local pattern = C(utf8character^-1) -local ctx_doifelse = commands.doifelse - -implement { - name = "doifelsefirstchar", - arguments = "2 strings", - actions = function(str,chr) - ctx_doifelse(lpegmatch(pattern,str) == chr) - end -} - -implement { - name = "getsubstring", - arguments = "3 strings", - actions = function(str,first,last) - context(utfsub(str,tonumber(first),tonumber(last))) - end -} - --- function commands.addtocommalist(list,item) --- if list == "" then --- context(item) --- else --- context("%s,%s",list,item) -- using tex.print is some 10% faster --- end --- end --- --- function commands.removefromcommalist(list,item) --- if list == "" then --- context(item) --- else --- -- okay, using a proper lpeg is probably faster --- -- we could also check for #l = 1 --- local l = settings_to_array(list) --- local t, n = { } --- for i=1,#l do --- if l[i] ~= item then --- n = n + 1 --- t[n] = item --- end --- end --- if n == 0 then --- context(item) --- else --- context(concat(list,",")) --- end --- end --- end - -local pattern = (C((1-P("%"))^1) * Carg(1)) / function(n,d) - return formatters["%.0fsp"](d * tonumber(n)/100) end * P("%") * P(-1) -- .0 ? - --- percentageof("10%",65536*10) - -implement { - name = "percentageof", - arguments = { "string", "dimen" }, - actions = function(str,dim) - context(lpegmatch(pattern,str,1,dim) or str) - end -} - --- \gdef\setpercentdimen#1#2% --- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} - -local space = P(" ") / "" -local spaces = P(" ")^0 / "" -local nohash = 1 - P("#") -local digit = R("09") -local double = P("##") / "#" -local single = P("#") -local sentinel = spaces * (nohash^1 / "\\%0") -local whatever = S("+-/*_^=:") + digit -local sargument = (single * digit)^1 -local dargument = (double * digit)^1 -local swhatever = (single * whatever)^1 -local dwhatever = (double * whatever)^1 - --- different ones: - -local space = P(" ") -local spaces = space^0 - --- see syst-aux.lua for historic variants - -local global = nil -local protected = nil -local expanded = nil -local optional = nil -local tolerant = nil -local instance = nil -local frozen = nil -local csname = nil -local rest = nil - -local function catcodes_s() - setcatcode(32,10) -- space - setcatcode(13, 5) -- endofline -end - -local function catcodes_n() - setcatcode(32, 9) -- ignore - setcatcode(13, 9) -- ignore -end - -local function oldoption(s) - if optional > 1 then - optional = optional - 1 - return s .. "#*" - else - return s - end -end - -local option = ( - P("single") * Cc(1) - + P("double") * Cc(2) - + P("triple") * Cc(3) - + P("quadruple") * Cc(4) - + P("quintuple") * Cc(5) - + P("sixtuple") - ) * (P("empty") + P("argument")) - -local pattern = ( - ( - spaces * ( - ( P("spaces") * space / catcodes_s ) - + ( P("nospaces") * space / catcodes_n ) - + ( P("global") * space / function() global = true end) - + ( P("protected") * space / function() protected = true end) - + ( P("expanded") * space / function() expanded = true end) - + ( P("tolerant") * space / function() tolerant = true end) - + ( P("instance") * space / function() instance = true end) - + ( P("frozen") * space / function() frozen = true end) - + ( P("unexpanded") * space / function() protected = true end) - + ( option * space / function(s) tolerant = true - optional = s end) - ) - )^0 - * spaces * ( C((1-S(" #["))^1) ) - * spaces * Cs( - (Cs(P("[") * dargument * P("]")) / oldoption + dwhatever)^1 * sentinel^-1 * double^-1 - + (Cs(P("[") * sargument * P("]")) / oldoption + swhatever)^1 * sentinel^-1 * single^-1 - + sentinel^-1 * (double+single)^-1 - ) -) - -local ctx_dostarttexdefinition = context.dostarttexdefinition - -local function texdefinition_one(str) - global = false - protected = false - expanded = false - optional = 0 - tolerant = false - instance = false - frozen = false - csname, rest = lpegmatch(pattern,str) - ctx_dostarttexdefinition() -end - -local function texdefinition_two() - context ( - (tolerant and [[\tolerant]] or "") .. (frozen and [[\frozen]] or "") .. (protected and [[\protected]] or "") .. (instance and [[\instance]] or "") .. - [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) .. - [[\csname ]] .. csname .. [[\endcsname ]] .. - rest - ) -end - -implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" } -implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" } - -do - - -- Quite probably we don't yet have characters loaded so we delay some - -- aliases. - - local _lower_, _upper_, _strip_ - - _lower_ = function(s) - if characters and characters.lower then - _lower_ = characters.lower - return _lower_(s) - end - return string.lower(s) - end - - _upper_ = function(s) - if characters and characters.upper then - _upper_ = characters.upper - return _upper_(s) - end - return string.upper(s) - end - - _strip_ = function(s) - -- or utf.strip - if string.strip then - _strip_ = string.strip - return _strip_(s) - end - return s - end - - local function lower(s) context(_lower_(s)) end - local function upper(s) context(_upper_(s)) end - local function strip(s) context(_strip_(s)) end - - implement { name = "upper", arguments = "string", actions = upper } - implement { name = "lower", arguments = "string", actions = lower } - implement { name = "strip", arguments = "string", actions = strip } - -end - -implement { - name = "converteddimen", - arguments = { "dimen", "string" }, - actions = function(dimen,unit) - context(number.todimen(dimen,unit or "pt","%0.5f")) -- no unit appended (%F) - end -} - --- where, not really the best spot for this: - -implement { - name = "immediatemessage", - arguments = { "'message'", "string" }, - actions = logs.status -} - -implement { - name = "resettimer", - actions = function() - statistics.resettiming("whatever") - statistics.starttiming("whatever") - end -} - -implement { - name = "benchmarktimer", - actions = function() - statistics.benchmarktimer("whatever") - end -} - -implement { - name = "elapsedtime", - actions = function() - statistics.stoptiming("whatever") - context(statistics.elapsedtime("whatever")) - end -} - -implement { - name = "elapsedsteptime", - arguments = "integer", - actions = function(n) - statistics.stoptiming("whatever") - local t = statistics.elapsed("whatever")/(n > 0 and n or 1) - if t > 0 then - context("%0.9f",t) - else - context(0) - end - end -} - -local accuracy = table.setmetatableindex(function(t,k) - local v = formatters["%0." ..k .. "f"] - t[k] = v - return v -end) - -implement { - name = "rounded", - arguments = "integer", - actions = function(n,m) context(accuracy[n](m)) end -} - --- not faster but just less tracing: - -local ctx_protected_cs = context.protected.cs -- more efficient - -local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments -local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments -local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument -local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument - -context.firstoftwoarguments = ctx_firstoftwoarguments -context.secondoftwoarguments = ctx_secondoftwoarguments -context.firstofoneargument = ctx_firstofoneargument -context.gobbleoneargument = ctx_gobbleoneargument - -local ctx_iftrue = context.iftrue -local ctx_iffalse = context.iffalse - -local hash = utilities.parsers.hashes.settings_to_set - -local function doifelsecommon(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_secondoftwoarguments() - else - ctx_firstoftwoarguments() - end - return - end - local ba = find(a,",",1,true) - local bb = find(b,",",1,true) - if ba and bb then - local ha = hash[a] - local hb = hash[b] - -- local ha = settings_to_set(a) - -- local hb = settings_to_set(b) - for k in next, ha do - if hb[k] then - setmacro("commalistelement",k) - ctx_firstoftwoarguments() - return - end - end - elseif ba then - if hash[a][b] then - -- if settings_to_set(a)[b] then - setmacro("commalistelement",b) - ctx_firstoftwoarguments() - return - end - elseif bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_firstoftwoarguments() - return - end - end - setmacro("commalistelement","") - ctx_secondoftwoarguments() -end - -local function doifcommon(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_gobbleoneargument() - else - ctx_firstofoneargument() - end - return - end - local ba = find(a,",",1,true) - local bb = find(b,",",1,true) - if ba and bb then - local ha = hash[a] - local hb = hash[b] - -- local ha = settings_to_set(a) - -- local hb = settings_to_set(b) - for k in next, ha do - if hb[k] then - setmacro("commalistelement",k) - ctx_firstofoneargument() - return - end - end - elseif ba then - if hash[a][b] then - -- if settings_to_set(a)[b] then - setmacro("commalistelement",b) - ctx_firstofoneargument() - return - end - elseif bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_firstofoneargument() - return - end - end - setmacro("commalistelement","") - ctx_gobbleoneargument() -end - -local function doifnotcommon(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_firstofoneargument() - else - ctx_gobbleoneargument() - end - return - end - local ba = find(a,",",1,true) - local bb = find(b,",",1,true) - if ba and bb then - local ha = hash[a] - local hb = hash[b] - -- local ha = settings_to_set(a) - -- local hb = settings_to_set(b) - for k in next, ha do - if hb[k] then - setmacro("commalistelement",k) - ctx_gobbleoneargument() - return - end - end - elseif ba then - if hash[a][b] then - -- if settings_to_set(a)[b] then - setmacro("commalistelement",b) - ctx_gobbleoneargument() - return - end - elseif bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_gobbleoneargument() - return - end - end - setmacro("commalistelement","") - ctx_firstofoneargument() -end - --- local function hascommonargumentcondition(a,b) --- if a == b then --- setmacro("commalistelement",a) --- if a == "" then --- ctx_iffalse() --- else --- ctx_iftrue() --- end --- return --- end --- local ba = find(a,",",1,true) --- local bb = find(b,",",1,true) --- if ba and bb then --- local ha = hash[a] --- local hb = hash[b] --- for k in next, ha do --- if hb[k] then --- setmacro("commalistelement",k) --- ctx_iftrue() --- return --- end --- end --- elseif ba then --- if hash[a][b] then --- setmacro("commalistelement",b) --- ctx_iftrue() --- return --- end --- elseif bb then --- if hash[b][a] then --- setmacro("commalistelement",a) --- ctx_iftrue() --- return --- end --- end --- setmacro("commalistelement","") --- ctx_iffalse() --- end - -local function doifelseinset(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_secondoftwoarguments() - else - ctx_firstoftwoarguments() - end - return - end - local bb = find(b,",",1,true) - if bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_firstoftwoarguments() - return - end - end - setmacro("commalistelement","") - ctx_secondoftwoarguments() -end - -local function doifinset(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_gobbleoneargument() - else - ctx_firstofoneargument() - end - return - end - local bb = find(b,",",1,true) - if bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_firstofoneargument() - return - end - end - setmacro("commalistelement","") - ctx_gobbleoneargument() -end - -local function doifnotinset(a,b) - if a == b then - setmacro("commalistelement",a) - if a == "" then - ctx_firstofoneargument() - else - ctx_gobbleoneargument() - end - return - end - local bb = find(b,",",1,true) - if bb then - if hash[b][a] then - -- if settings_to_set(b)[a] then - setmacro("commalistelement",a) - ctx_gobbleoneargument() - return - end - end - setmacro("commalistelement","") - ctx_firstofoneargument() -end - -implement { - name = "doifelsecommon", - actions = doifelsecommon, - arguments = "2 strings", -} - -implement { - name = "doifcommon", - actions = doifcommon, - arguments = "2 strings", -} - -implement { - name = "doifnotcommon", - actions = doifnotcommon, - arguments = "2 strings", -} - --- implement { --- name = "hascommonargumentcondition", --- actions = hascommonargumentcondition, --- arguments = "2 strings", --- arguments = { "argument", "argument" }, --- } - -implement { - name = "doifelseinset", - actions = doifelseinset, - arguments = "2 strings", --- arguments = { "argument", "argument" }, -} - -implement { - name = "doifinset", - actions = doifinset, - arguments = "2 strings", -} - -implement { - name = "doifnotinset", - actions = doifnotinset, - arguments = "2 strings", -} - --- done elsewhere: --- --- local function firstinset(a) --- local aa = hash[a] --- context(aa and aa[1] or a) --- end --- --- implement { --- name = "firstinset", --- actions = firstinset, --- arguments = "string", --- private = false, --- } - --- implement { --- name = "stringcompare", --- arguments = "2 strings", --- actions = function(a,b) --- context((a == b and 0) or (a > b and 1) or -1) --- end --- } --- --- implement { --- name = "doifelsestringafter", --- arguments = "2 strings", --- actions = function(a,b) --- ctx_doifelse((a == b and 0) or (a > b and 1) or -1) --- end --- } --- --- implement { --- name = "doifelsestringbefore", --- arguments = "2 strings", --- actions = function(a,b) --- ctx_doifelse((a == b and 0) or (a < b and -1) or 1) --- end --- } - --- implement { -- not faster than addtocommalist --- name = "additemtolist", -- unique --- arguments = "2 strings", --- actions = function(l,s) --- if l == "" or s == l then --- -- s = s --- elseif find("," .. l .. ",","," .. s .. ",") then --- s = l --- else --- s = l .. "," .. s --- end --- context(s) --- end --- } - -local bp = number.dimenfactors.bp - -implement { - name = "tobigpoints", - actions = function(d) context("%.5F",bp * d) end, - arguments = "dimension", -} - -implement { - name = "towholebigpoints", - actions = function(d) context("%r",bp * d) end, - arguments = "dimension", -} - --- for now here: - -local function getshape(s) - local t = texget(s) - local n = t and #t or 0 - context(n) - if n > 0 then - for i=1,n do - local ti = t[i] - if type(ti) == "table" then - context(" %isp %isp",ti[1],ti[2]) - else - context(" %i",ti) - end - end - end -end - -implement { - name = "getparshape", - public = true, - actions = function() getshape("parshape") end, -} -implement { - name = "getclubpenalties", - public = true, - actions = function() getshape("clubpenalties") end, -} -implement { - name = "getinterlinepenalties", - public = true, - actions = function() getshape("interlinepenalties") end, - } -implement { - name = "getdisplaywidowpenalties", - public = true, - actions = function() getshape("displaywidowpenalties") end, -} -implement { - name = "getwidowpenalties", - public = true, - actions = function() getshape("widowpenalties") end, -} diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl deleted file mode 100644 index 5410590a6..000000000 --- a/tex/context/base/mkiv/syst-aux.mkxl +++ /dev/null @@ -1,6678 +0,0 @@ -%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 In the process of being adapted to \LMTX\ flags so a bit of a mess now. Also -%D our playground. - -\registerctxluafile{syst-aux}{autosuffix} -\registerctxluafile{syst-mac}{autosuffix} - -%D This file is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv} where -%D you can find some more pure \TEX\ or \LUATEX\ variants. There are quite some -%D helpers here and many no longer are used but we keep them around because they -%D have always been there. However, the implementation in \LMTX\ can be somewhat -%D different that in \MKIV, because it's also a kind of a playground for new -%D features. Of course nostalgia also plays a role. -%D -%D For the original code we refer to \type {syst-aux.mkii} and its follow up \type -%D {syst-aux.mkiv}. These also have historic versions. As usual, the upgrade went -%D through stages. First I wrote variants usign the new \type {\ignorearguments} -%D feature, then I decided to implement a few more conditionals and new fancy code -%D could be ditched before it was even published. I kept some as examples. -%D -%D Of course I couldn't do this without Wolfgang looking over my shoulder. Changing -%D core code is kind of tricky. - -\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 \protected\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. So, effectively we have two ways to -%D protect a macro. - -\pushoverloadmode - -\aliased\let\unexpanded\normalprotected - -\popoverloadmode - -%D We're definitely in \LMTX\ mode here. - -\aliased \let\startlmtxmode\relax -\aliased \let\stoplmtxmode \relax -\permanent\def\startmkivmode#-\stopmkivmode{} -\permanent\let\stopmkivmode \relax - -%D As we don't have namespace definers yet, we use a special one. Later we will -%D do a better job. - -\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 - -\permanent\protected\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 this one: - -\def\normalspace{ } - -\newif\if!!donea \newif\if!!doneb \newif\if!!donec % soon obsolete in lmtx -\newif\if!!doned \newif\if!!donee \newif\if!!donef % soon obsolete in lmtx - -\immutable\def\!!zerocount {0} % alongside \zerocount -\immutable\def\!!minusone {-1} % ... -\immutable\def\!!plusone {1} % ... -\immutable\def\!!plustwo {2} % ... -\immutable\def\!!plusthree {3} % ... -\immutable\def\!!plusfour {4} % ... -\immutable\def\!!plusfive {5} % ... -\immutable\def\!!plussix {6} % ... -\immutable\def\!!plusseven {7} % ... -\immutable\def\!!pluseight {8} % ... -\immutable\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. Of course, expanding them costs time, so -%D that's the price to pay. More are defined elsewhere. Of course we later pay a -%D price when they need to be expanded. - -% \def\v!prefix! {v!} -% \def\c!prefix! {c!} -% \def\s!prefix! {s!} -% -% \def\s!next {next} -% \def\s!default {default} -% \def\s!dummy {dummy} -% \def\s!unknown {unknown} -% -% \def\s!do {do} -% \def\s!dodo {dodo} -% -% \def\s!complex {complex} -% \def\s!simple {simple} -% -% \def\s!start{start} -% \def\s!stop {stop} - -% \immutable\def\s!empty {empty} - -%D Sometimes we pass macros as arguments to commands that don't expand them before -%D interpretation. Such commands can be enclosed with \type {\expanded}, like: -%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 - -\pushoverloadmode - -\permanent\protected\def\expanded#1% - {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded} - -\popoverloadmode - -\permanent\protected\def\startexpanded#1\stopexpanded - {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded} - -\aliased\let\stopexpanded\relax - -%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when -%D possible. After all, we can make not expandable macros now. The name clash is an -%D unfortunate fact and in retrospect I should nto have agreed to a primitive having -%D that same name. - -% 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. These zero references prevent intermediate storage. In principle that -%D is more efficient but it probably won't be noticed. It's anyway cheaper on memory -%D access. We use versions that don't even store the arguments. - -%permanent\def\gobbleoneargument #-{} -\permanent\def\gobbletwoarguments #-#-{} -\permanent\def\gobblethreearguments #-#-#-{} -\permanent\def\gobblefourarguments #-#-#-#-{} -\permanent\def\gobblefivearguments #-#-#-#-{} -\permanent\def\gobblesixarguments #-#-#-#-{} -\permanent\def\gobblesevenarguments #-#-#-#-#-{} -\permanent\def\gobbleeightarguments #-#-#-#-#-#-{} -\permanent\def\gobbleninearguments #-#-#-#-#-#-#-{} - -\permanent\tolerant\def\gobbleoneoptional [#-]{} -\permanent\tolerant\def\gobbletwooptionals [#-]#*[#-]{} -\permanent\tolerant\def\gobblethreeoptionals[#-]#*[#-]#*[#-]{} -\permanent\tolerant\def\gobblefouroptionals [#-]#*[#-]#*[#-]#*[#-]{} -\permanent\tolerant\def\gobblefiveoptionals [#-]#*[#-]#*[#-]#*[#-]#*[#-]{} - -%D Reserved macros for tests: - -\aliased\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 This macro has a long history. Among the things we had to deal with was ignoring -%D blank spaces but in the meantime we can use some \LUATEX\ trickery. Older versions -%D use more code and can be find in the \MKIV\ and \MKII\ files. - -% \mutable\let\next \relax -% \mutable\let\nextnext \relax % kind of obsolete -% \mutable\let\nextnextnext \relax % kind of obsolete -% \mutable\let\nexttoken \relax - -\permanent\protected\def\doifelsenextchar#1#2#3% #1 should not be {} ! - {\def\m_syst_action_yes{#2}% - \def\m_syst_action_nop{#3}% - \futureexpandis#1\m_syst_action_yes\m_syst_action_nop} - -\permanent\protected\def\doifelsenextcharcs % #1#2#3% #1 should not be {} ! - {\futureexpandis} - -\aliased\let\doifnextcharelse \doifelsenextchar -\aliased\let\doifnextcharcselse\doifelsenextcharcs - -%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. Here we use a lookahead primitive that ignores (blank) spaces -%D which makes for less tracing clutter than the original definition. It's also -%D faster bit that will probably go unnoticed. Of course, hard||core \TEX ies whose -%D reputations depends on understanding obscure macro definitions will love the more -%D low level variants. - -\permanent\protected\def\doifelsenextoptional#1#2% - {\def\m_syst_action_yes{#1}% - \def\m_syst_action_nop{#2}% - \futureexpandis[\m_syst_action_yes\m_syst_action_nop} - -\permanent\protected\def\doifelsenextoptionalcs - {\futureexpandis[} - -\aliased\let\doifnextoptionalelse \doifelsenextoptional -\aliased\let\doifnextoptionalcselse\doifelsenextoptionalcs - -\permanent\protected\def\doifelsenextbgroup#1#2% - {\def\m_syst_action_yes{#1}% - \def\m_syst_action_nop{#2}% - \futureexpandis\bgroup\m_syst_action_yes\m_syst_action_nop} - -\permanent\protected\def\doifelsenextbgroupcs % #1#2 - {\futureexpandis\bgroup} - -\aliased\let\doifnextbgroupelse \doifelsenextbgroup -\aliased\let\doifnextbgroupcselse\doifelsenextbgroupcs - -\permanent\protected\def\doifelsenextparenthesis#1#2% - {\def\m_syst_action_yes{#1}% - \def\m_syst_action_nop{#2}% - \futureexpandis(\m_syst_action_yes\m_syst_action_nop} - -\aliased\let\doifnextparenthesiselse\doifelsenextparenthesis - -%D The next one is handy in predictable situations: - -\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} - -\permanent\protected\def\doifelsefastoptionalcheck#1#2% - {\def\m_syst_action_yes{#1}% - \def\m_syst_action_nop{#2}% - \futureexpandis[\m_syst_action_yes\m_syst_action_nop} - -\permanent\protected\def\doifelsefastoptionalcheckcs - {\futureexpandis[} - -\aliased\let\doiffastoptionalcheckelse \doifelsefastoptionalcheck -\aliased\let\doiffastoptionalcheckcselse\doifelsefastoptionalcheckcs - -%D Here's one for skipping spaces and pars, handy for: -%D -%D \starttyping -%D \hbox -%D -%D {a few lines later} -%D \stoptyping -%D -%D like: -%D -%D \starttyping -%D \def\somecommand{\dowithnextbox{\box\nextbox}\ruledhbox} -%D -%D \assumelongusagecs\somecommand -%D -%D \bgroup -%D oeps -%D \egroup -%D \stoptyping -%D -%D The original kind of clumsy but working version is now replaced by a simple -%D macro. And it can be even less code in \LUAMETATEX: - -\aliased\let\assumelongusagecs\expandafterpars % so we can replace it - -%D It's used to skip over empty lines in some constructs that we like to set up -%D spacy. We already permit par tokens (and equivalents) in math and some other -%D places visa engine features. And, \type {\long} stuff has been dropped for a long -%D time already (it is still optional in \lUATEX). But the \quote {long} in the -%D name kind of stuck. - -%D \macros -%D {blankspace} -%D -%D Here is how this works. The \type {\let} primitive first picks up the to be let -%D name. Then it scans for an optional equal and when that is found it will skip the -%D next space, which is why we need an extra one to achieve our goal. Such a \type -%D {\blankspace} has the meaning \typ {blank space}. A typical \TEX ie definition: - -\normalexpanded{\permanent\let\noexpand\blankspace=\space\space} - -%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}=\... = \glet\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. - -\permanent\def\setvalue #1{\expandafter\defcsname#1\endcsname} -\permanent\def\setgvalue #1{\global\defcsname#1\endcsname} -\permanent\def\setevalue #1{\edefcsname#1\endcsname} -\permanent\def\setxvalue #1{\global\edefcsname#1\endcsname} -\permanent\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname -\permanent\def\letvalue #1{\letcsname#1\endcsname} -\permanent\def\letgvalue #1{\global\letcsname#1\endcsname} -\permanent\def\resetvalue #1{\letcsname#1\endcsname\empty} -\permanent\def\undefinevalue#1{\letcsname#1\endcsname\undefined} -\permanent\def\ignorevalue#1#2{\letcsname#1\endcsname\empty} - -\permanent\def\setuvalue #1{\protected\defcsname#1\endcsname} -\permanent\def\setuevalue #1{\protected\edefcsname#1\endcsname} -\permanent\def\setugvalue #1{\protected\global\defcsname#1\endcsname} -\permanent\def\setuxvalue #1{\protected\global\edefcsname#1\endcsname} - -\permanent\protected\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 tokens will -%D save us some $300\times4=1200$ bytes of format file on a 32~bit system. Not that -%D it matters much today. But nowadays we can just alias to a primitive: - -\aliased\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 -%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 -%D -%D Suppression of errors while constructing a control sequence is one of the (few) -%D things that I remember being discussed in the perspective of \ETEX\ but it was -%D rejected because it was not considered useful. Well, in \LUATEX\ we can surpress -%D it and that is what we do in \MKIV. We're probably the only macro package that -%D needs it. That kind of configuration happens elsewhere. These macros are (mostly -%D for historic reasons) fully expandable. - -\permanent\def\doifelseundefined#1% - {\ifcsname#1\endcsname - \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments - \fi} - -\permanent\def\doifelsedefined#1% - {\ifcsname#1\endcsname - \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments - \fi} - -\permanent\def\doifundefined#1% - {\ifcsname#1\endcsname - \expandafter\gobbleoneargument\else\expandafter\firstofoneargument - \fi} - -\permanent\def\doifdefined#1% - {\ifcsname#1\endcsname - \expandafter\firstofoneargument\else\expandafter\gobbleoneargument - \fi} - -\aliased\let\doifundefinedelse\doifelseundefined -\aliased\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: - -\permanent\protected\def\letbeundefined#1% - {\letcsname#1\endcsname\undefined} % or use \undefinevalue to match \setvalue - -\permanent\protected\def\localundefine#1% conditional - {\ifcsname#1\endcsname\letcsname#1\endcsname\undefined\fi} - -\permanent\protected\def\globalundefine#1% conditional - {\ifcsname#1\endcsname\global\letcsname#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}. - -\permanent\protected\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} - -\aliased\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 -%D -%D Again, we use some of the new primitives in \LUAMETATEX. Using straightforward -%D \type {\edef}'s and \type {\ifx} comparison works as well, but this saves tokens -%D and, more important, tracing clutter. - -\permanent\protected\def\doifelse#1#2% - {\iftok{#1}{#2}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doif#1#2% - {\iftok{#1}{#2}% - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnot#1#2% - {\iftok{#1}{#2}% - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \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, but we use the dedicated empty checker -%D here. - -\permanent\protected\def\doifelseempty#1% - {\def\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifemptyelse\doifelseempty - -\permanent\protected\def\doifempty#1% - {\def\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotempty#1% - {\def\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \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} - -%D These are normally only used for keywords, i.e.\ strings so we can delegate -%D the work to \LUA: - -%unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}} -%unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}} -%unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}} -% % \let\firstinset \clf_firstinset - -% These don't accept spaces after commas: -% -% \protected\def\doifelseinset#1#2% -% {\ifhasxtoks{,#1,}{,#2,}% -% \expandafter\firstoftwoarguments -% \else -% \expandafter\secondoftwoarguments -% \fi} - -% \protected\def\doifinset#1#2% -% {\ifhasxtoks{,#1,}{,#2,}% -% \expandafter\firstofoneargument -% \else -% \expandafter\gobbleoneargument -% \fi} - -% \protected\def\doifnotinset#1#2% -% {\ifhasxtoks{,#1,}{,#2,}% -% \expandafter\gobbleoneargument -% \else -% \expandafter\firstofoneargument -% \fi} - -% But these do: - -\immutable\edef\a!comma{\expandtoken \ignorecatcode \commaasciicode} -\immutable\edef\a!space{\expandtoken \ignorecatcode \spaceasciicode} - -\normalexpanded { - - \permanent \protected \def \noexpand \doifelseinset#1#2% - {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% - \noexpand\expandafter\noexpand\firstoftwoarguments - \noexpand\else - \noexpand\expandafter\noexpand\secondoftwoarguments - \noexpand\fi} - - \permanent \protected \def \noexpand \doifinset#1#2% - {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% - \noexpand\expandafter\noexpand\firstofoneargument - \noexpand\else - \noexpand\expandafter\noexpand\gobbleoneargument - \noexpand\fi} - - \permanent \protected \def \noexpand \doifnotinset#1#2% - {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% - \noexpand\expandafter\noexpand\gobbleoneargument - \noexpand\else - \noexpand\expandafter\noexpand\firstofoneargument - \noexpand\fi} - -} - -%D Done. - -\aliased\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} - -\permanent\protected\def\doifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} % todo: define in lua -\permanent\protected\def\doifcommon #1#2{\clf_doifcommon {#1}{#2}} % todo: define in lua -\permanent\protected\def\doifnotcommon #1#2{\clf_doifnotcommon {#1}{#2}} % todo: define in lua - -\aliased\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 Or expanded: -%D -%D \blank \getbuffer \blank -%D -%D The original definitions can be found elsewhere and need a bit more code. In case of -%D issues, consult the \MKIV\ variant or previous \LMTX\ variants in the repository. -%D -%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 this macro has its -%D limits. We use a new \LUAMETATEX\ feature that intercepts invalid macro arguments -%D by quitting when \type {\ignorearguments} is seen. That's why we act on the -%D arguments state. Again it permits leaner and meaner macro definitions with a bit -%D less clutter in tracing. - -\let\commalistcommand\empty - -\protected\def\syst_helpers_process_comma_item#+,% - {\ifarguments - \expandafter\syst_helpers_process_comma_item_gobble - \orelse\ifparameter#1\or - \commalistcommand{#1}% - \expandafter\syst_helpers_process_comma_item_next - \else - \expandafter\syst_helpers_process_comma_item_gobble - \fi} - -% \def\syst_helpers_process_comma_item_next -% {\expandafterspaces\syst_helpers_process_comma_item} - -% \protected\def\processcommalist[#1]#2% -% {\pushmacro\commalistcommand -% \def\commalistcommand{#2}% -% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments -% \popmacro\commalistcommand} - -% \protected\def\processcommacommand[#1]#2% -% {\pushmacro\commalistcommand -% \def\commalistcommand{#2}% -% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments -% \popmacro\commalistcommand} - -% \permanent\protected\def\processcommalist[#*#+]#2% -% {\pushmacro\commalistcommand -% \def\commalistcommand{#2}% -% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments -% \popmacro\commalistcommand} -% -% \permanent\protected\def\processcommacommand[#*#+]#2% -% {\pushmacro\commalistcommand -% \def\commalistcommand{#2}% -% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments -% \popmacro\commalistcommand} - -\tolerant\protected\def\syst_helpers_process_comma_item#*#1,% - {\ifarguments\or - \commalistcommand{#1}% - \expandafter\syst_helpers_process_comma_item_next - \fi} - -\def\syst_helpers_process_comma_item_next - {\expandafterspaces\syst_helpers_process_comma_item} - -\permanent\protected\def\processcommalist[#1]#2% - {\pushmacro\commalistcommand - \def\commalistcommand{#2}% - \syst_helpers_process_comma_item#1\ignorearguments\ignorearguments\ignorearguments - \popmacro\commalistcommand} - -\permanent\protected\def\processcommacommand[#1]#2% - {\pushmacro\commalistcommand - \def\commalistcommand{#2}% - \normalexpanded{\syst_helpers_process_comma_item#1}\ignorearguments\ignorearguments\ignorearguments - \popmacro\commalistcommand} - -% \let\syst_helpers_process_comma_item_next_a \syst_helpers_process_comma_item_next -% \def\syst_helpers_process_comma_item_next_b#0\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_a} -% \def\syst_helpers_process_comma_item_next_c#0\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} -% \def\syst_helpers_process_comma_item_gobble#0\ignorearguments{} - -\let\syst_helpers_process_comma_item_next_a \syst_helpers_process_comma_item_next -\def\syst_helpers_process_comma_item_next_b#-\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_a} -\def\syst_helpers_process_comma_item_next_c#-\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} -\def\syst_helpers_process_comma_item_gobble#-\ignorearguments{} - -\permanent\protected\def\quitcommalist {\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} -\permanent\protected\def\quitprevcommalist{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_c} - -%D \startbuffer -%D \def\foo#1{(#1)} -%D <\processcommalist[a,b,c,d]\foo> -%D -%D \def\foo#1{(#1)} -%D \def\oof#1{<\processcommalist[#1]\foo>} -%D <\processcommalist[{a,b},{c,d}]\oof> -%D -%D \def\foo#1{(#1)\quitcommalist} -%D <\processcommalist[a,b,c,d]\foo> -%D -%D \def\foo#1{(#1)} -%D \def\oof#1{<\processcommalist[#1]\foo\quitcommalist>} -%D <\processcommalist[{a,b},{c,d}]\oof> -%D -%D \def\foo#1{(#1)\quitcommalist} -%D \def\oof#1{<\processcommalist[#1]\foo>} -%D <\processcommalist[{a,b},{c,d},{e,f}]\oof> -%D -%D \def\foo#1{(#1)\quitprevcommalist} -%D \def\oof#1{<\processcommalist[#1]\foo>} -%D <\processcommalist[{a,b},{c,d},{e,f}]\oof> -%D \stopbuffer -%D -%D \typebuffer \blank \getbuffer \blank - -%D The argument to \type{\command} is not delimited. Because we often use \type {[]} -%D 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 - -\permanent\protected\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 - -\permanent\protected\def\startprocesscommalist[#1]#2\stopprocesscommalist - {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% - \processcommalist[#1]\syst_helpers_comma_list_step} - -\permanent\protected\def\startprocesscommacommand[#1]#2\stopprocesscommacommand - {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% - \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step} - -\aliased\let\stopprocesscommalist \relax -\aliased\let\stopprocesscommacommand\relax - -%D \macros -%D {processaction, -%D processfirstactioninset, -%D processallactionsinset} -%D -%D \CONTEXT\ makes extensive use of a sort of case or switch command. Depending of -%D the presence of one or more provided items, some actions is taken. These macros -%D can be nested without problems. -%D -%D \starttyping -%D \processaction [x] [x=>a,y=>b,z=>c] -%D \processfirstactioninset [x,y,z] [x=>a,y=>b,z=>c] -%D \processallactionsinset [x,y,z] [x=>a,y=>b,z=>c] -%D \stoptyping -%D -%D We can supply both a \type {default} action and an action to be undertaken when -%D 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 the keyword \type -%D {default} and executed the related action if present. When \type {#1} is non -%D empty and not in the list, the action related to \type {unknown} is executed. -%D Both keywords must be at the end of list \type{#2}. Afterwards, the actually -%D found keyword is available in \type {\commalistelement}. An advanced example of -%D the use of this macro can be found in \PPCHTEX, where we completely rely on \TEX\ -%D for interpreting user supplied keywords like \type {SB}, \type {SB1..6}, \type -%D {SB125} etc. -%D -%D In the meantime we follow a different approach, often somewhat more heavy on the -%D number of control sequences used, but that is no lomger a real issue. The code -%D has been simplified and nwo uses the macro stack mechanism. If needed I can make -%D this more hip and a bit faster now but \unknown\ it's seldom used nowadays as we -%D have better ways now. - -\protected\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} - -\protected\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 - \orelse\ifx\m_syst_string_two\s!unknown - \def\commalistelement{#3}% beware of loops - #2% - \fi} - -\permanent\protected\def\processaction[#1]#2[% - {\edef\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \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\syst_helpers_do_process_action[} - -\protected\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} - -\permanent\protected\def\processfirstactioninset[#1]% - {\edef\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \expandafter\processaction - \else - \expandafter\syst_helpers_process_first_action_in_set_indeed - \fi - [#1]} - -\tolerant\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#*[#2]% - {\def\syst_helpers_do_process_action##1% - {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}% - \processcommalist[#2]\syst_helpers_do_do_process_action}% - \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action} - -\protected\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]% - {\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} - -\tolerant\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#*[#2]% - {\globalpushmacro\syst_process_action_in_set_all - \def\syst_process_action_in_set##1% - {\def\syst_process_action_in_set_one####1{\syst_helpers_do_compare_process_action_d[####1][##1]}% - \processcommalist[#2]\syst_process_action_in_set_one}% - \processcommacommand[#1]\syst_process_action_in_set - \globalpopmacro\syst_process_action_in_set_all} - -\permanent\protected\def\processallactionsinset[#1]% - {\edef\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \expandafter\processaction - \else - \expandafter\syst_helpers_process_all_actions_in_set_indeed - \fi[#1]} - -%D These macros use: - -% \protected\def\processnextcommalist#1[#2#3]% -% {\pushmacro\commalistcommand -% \def\commalistcommand{#1}% -% \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments -% \popmacro\commalistcommand} - -\permanent\protected\def\processnextcommalist#1[#2#3]% - {\pushmacro\commalistcommand - \def\commalistcommand{#1}% - \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments - \popmacro\commalistcommand} - -%D \macros -%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter} -%D -%D Sometimes the action to be undertaken depends on the next character. This macro -%D get this character and puts it in \type {\firstcharacter}. -%D -%D \starttyping -%D \getfirstcharacter {string} -%D \stoptyping -%D -%D A two step expansion is used to prevent problems with complicated arguments, for -%D instance arguments that consist of two or more expandable tokens. - -\let\firstcharacter \empty -\let\remainingcharacters\empty - -\permanent\protected\def\getfirstcharacter #1{\clf_getfirstcharacter{#1}} -\permanent\protected\def\doifelsefirstchar #1#2{\clf_doifelsefirstchar{#1}{#2}} -\permanent\protected\def\thefirstcharacter #1{\clf_thefirstcharacter{#1}} -\permanent\protected\def\theremainingcharacters#1{\clf_theremainingcharacters{#1}} - -\aliased\let\doiffirstcharelse\doifelsefirstchar - -%D \macros -%D {doifinstringelse, doifincsnameelse} -%D -%D We can check for the presence of a substring in a given sequence of characters. -%D -%D \starttyping -%D \doifinstringelse {substring} {string} {then ...} {else ...} -%D \stoptyping -%D -%D \startbuffer -%D \doifinstringelse{abc}{foo bar abc}{Y}{N}=Y\par -%D \doifinstringelse{abc}{foo bar cab}{Y}{N}=N\par -%D \doifinstring {abc}{foo bar abc}{Y}=Y\par -%D \doifinstring {abc}{foo bar cab}{Y}\par -%D \doifnotinstring {abc}{foo bar abc}{Y}\par -%D \doifnotinstring {abc}{foo bar cab}{Y}=Y\par -%D \doifinstringelse{}{foo bar abc}{Y}{N}=N\par -%D \doifinstring {}{foo bar abc}{N}\par -%D \doifnotinstring {}{foo bar abc}{Y}=Y\par -%D \doifinstringelse{x}{}{Y}{N}=N\par -%D \doifinstring {x}{}{N}\par -%D \doifnotinstring {x}{}{Y}=Y\par -%D \doifinstringelse{}{}{Y}{N}=N\par -%D \doifinstring {}{}{N}\par -%D \doifnotinstring {}{}{Y}=Y\par -%D \stopbuffer -%D -%D \typebuffer \blank \getbuffer \blank - -%D I keep the following as example code: - -% \let\syst_helpers_do_do_if_in_string_else\relax -% \let\syst_helpers_do_do_if_in_string \relax -% \let\syst_helpers_do_do_if_not_in_string \relax -% -% \let\m_syst_sub_string \empty -% -% \protected\def\doifelseinstring#1% -% {\edef\m_syst_sub_string{#1}% expand #1 here -% \ifempty\m_syst_sub_string -% \expandafter\thirdofthreearguments -% \else -% \expandafter\syst_helpers_do_if_in_string_else -% \fi} -% -% \let\doifinstringelse\doifelseinstring -% -% \protected\def\syst_helpers_do_if_in_string_else#1% ##2 can be {abc} -% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string_else##1\m_syst_sub_string##2}% -% {\ifarguments -% \or -% \expandafter\syst_helpers_do_if_in_string_else_nop -% \or -% \expandafter\syst_helpers_do_if_in_string_else_yes -% \fi}% -% \normalexpanded{\syst_helpers_do_do_if_in_string_else#1}\e_o_t\ignorearguments\ignorearguments} -% -% \protected\def\syst_helpers_do_if_in_string_else_delimited#1% ##2 can be {abc} -% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string_else##1,\m_syst_sub_string,##2}% -% {\ifarguments -% \or -% \expandafter\syst_helpers_do_if_in_string_else_nop -% \or -% \expandafter\syst_helpers_do_if_in_string_else_yes -% \fi}% -% \normalexpanded{\syst_helpers_do_do_if_in_string_else,#1,}\e_o_t\ignorearguments\ignorearguments} -% -% \protected\def\doifinstring#1% -% {\edef\m_syst_sub_string{#1}% expand #1 here -% \ifempty\m_syst_sub_string -% \expandafter\gobbletwoarguments -% \else -% \expandafter\syst_helpers_do_if_in_string -% \fi} -% -% \protected\def\syst_helpers_do_if_in_string#1% ##2 can be {abc} -% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string##1\m_syst_sub_string##2}% -% {\ifarguments -% \or -% \expandafter\syst_helpers_do_if_in_string_nop -% \or -% \expandafter\syst_helpers_do_if_in_string_yes -% \fi}% -% \normalexpanded{\syst_helpers_do_do_if_in_string#1}\e_o_t\ignorearguments\ignorearguments} -% -% \protected\def\doifnotinstring#1% -% {\edef\m_syst_sub_string{#1}% expand #1 here -% \ifempty\m_syst_sub_string -% \expandafter\secondoftwoarguments -% \else -% \expandafter\syst_helpers_do_if_not_in_string -% \fi} -% -% \protected\def\syst_helpers_do_if_not_in_string#1% ##2 can be {abc} -% {\normalexpanded{\protected\def\syst_helpers_do_do_if_not_in_string##1\m_syst_sub_string##2}% -% {\ifarguments -% \or -% \expandafter\syst_helpers_do_if_not_in_string_nop -% \or -% \expandafter\syst_helpers_do_if_not_in_string_yes -% \fi}% -% \normalexpanded{\syst_helpers_do_do_if_not_in_string#1}\e_o_t\ignorearguments\ignorearguments} -% -% \def\syst_helpers_do_if_in_string_else_yes#0\ignorearguments\ignorearguments#2#0{#2} -% \def\syst_helpers_do_if_in_string_else_nop#0\ignorearguments#0#3{#3} -% \def\syst_helpers_do_if_in_string_yes #0\ignorearguments\ignorearguments#2{#2} -% \def\syst_helpers_do_if_in_string_nop #0\ignorearguments#0{} -% \def\syst_helpers_do_if_not_in_string_yes #0\ignorearguments\ignorearguments#0{} -% \def\syst_helpers_do_if_not_in_string_nop #0\ignorearguments#2{#2} - -\permanent\protected\def\doifelseinstring#1#2% - {\ifhasxtoks{#1}{#2}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifinstring#1#2% - {\ifhasxtoks{#1}{#2}% - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotinstring#1#2% - {\ifhasxtoks{#1}{#2}% - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\aliased\let\doifinstringelse\doifelseinstring - -%D The next one one of those variants that we used when speed was more of an issue -%D that today. Now we just expand the lot. We just use an alias now: - -\aliased\let\doifelseincsname\doifelseinstring -\aliased\let\doifincsnameelse\doifinstringelse - -%D \macros -%D {doifnumberelse,doifnumber,doifnotnumber} -%D -%D The next macro executes a command depending of the outcome of a test on numerals. -%D We now use a \LUATEX\ feature that permits a more robust checking, but you might -%D want to take a look at the originals. It's typically one of these new features -%D that probably only \CONTEXT\ will use, which is probably true for more such -%D features that no one ever asked for (but they are pretty generic in nature -%D anyway). - -\permanent\def\doifelsenumber#1% - {\ifchknum#1\or - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\def\doifnumber#1% - {\ifchknum#1\or - \expandafter\firstoftwoarguments - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\def\doifnotnumber#1% - {\ifchknum#1\or - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\let\doifnumberelse\doifelsenumber - -%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 - -% todo: use the push back dimen trickery - -\permanent\def\percentdimen#1#2% dimen percentage (with %) - {\dimexpr\clf_percentageof{#2}\dimexpr#1\relax} - -\permanent\protected\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 slow. When one is -%D desperately in need of faster alternatives and when the conditions are -%D predictable safe, the \type {\raw} alternatives come into focus. A major drawback -%D is that they do not take \type {\c!constants} into account, simply because no -%D expansion is done. This is no problem with \type {\rawprocesscommalist}, because -%D this macro does not 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, spoil the search process. -%D The gain in speed depends on the length of the argument (the longer the argument, -%D the less we gain). The question is: do we still need these raw variants? - -\permanent\protected\def\makerawcommalist[#1]#2% use \processnext ... here - {\scratchtoks\emptytoks - \def\syst_helpers_do_make_raw_comma_list##1{\iftok\scratchtoks\emptytoks\scratchtoks{##1}\else\toksapp\scratchtoks{,##1}\fi}% - \processcommalist[#1]\syst_helpers_do_make_raw_comma_list - \edef#2{\the\scratchtoks}} - -% beware: in mkiv { } were lost so it was not compatible with the non raw - -\aliased\let\rawprocesscommalist \processcommalist % can go -\aliased\let\rawprocesscommacommand\processcommacommand % can go - -%D Here is one without nesting .. still needed? - -\protected\def\syst_helpers_process_fast_comma_item#1,% - {\ifarguments - \expandafter\syst_helpers_process_comma_item_gobble - \or - \fastcommalistcommand{#1}% - \expandafter\syst_helpers_process_fast_comma_item_next - \fi} - -\protected\def\syst_helpers_process_fast_comma_item_next - {\expandafterspaces\syst_helpers_process_fast_comma_item} - -\permanent\protected\def\fastprocesscommalist[#1]#2% - {\let\fastcommalistcommand#2% - \expandafterspaces\syst_helpers_process_fast_comma_item#1\ignorearguments\ignorearguments\ignorearguments} - -\permanent\protected\def\fastprocesscommacommand[#1]#2% - {\let\fastcommalistcommand#2% - \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_fast_comma_item#1}\ignorearguments\ignorearguments\ignorearguments} - -% \def\rawdoifelseinset#1#2{\doifinstringelse{,#1,}{,#2,}} -% \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}} - -\def\syst_helpers_do_if_else_in_set#1% - {\ifhasxtoks{,\m_syst_sub_string,}{,#1,}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\protected\def\rawdoifelseinset#1% - {\edef\m_syst_sub_string{#1}% expand #1 here - \ifempty\m_syst_sub_string - \expandafter\thirdofthreearguments - \else - \expandafter\syst_helpers_do_if_else_in_set - \fi} - -\aliased\let\rawdoifinsetelse\rawdoifelseinset - -\def\syst_helpers_do_if_in_set#1% - {\ifhasxtoks{,\m_syst_sub_string,}{,#1,}% - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\rawdoifinset#1% or just alias this one - {\edef\m_syst_sub_string{#1}% expand #1 here - \ifx\m_syst_sub_string\m_syst_two_commas - \expandafter\gobbletwoarguments - \else - \expandafter\syst_helpers_do_if_in_set - \fi} - -%D Some more raw material: - -\def\syst_helpers_raw_process_action#1=>#2,% - {\ifarguments - %\expandafter\syst_helpers_raw_process_action_gobble - \or - \expandafter\syst_helpers_raw_process_action_gobble - \or - \edef\m_syst_string_two{#1}% - \ifx\m_syst_string_one\m_syst_string_two - \def\m_syst_helpers_process_action{#2}% - \expandafter\expandafter\expandafter\syst_helpers_raw_process_action_gobble - \else - \ifx\s!unknown\m_syst_string_two - \def\m_syst_helpers_process_action_unknown{#2}% - \fi - \expandafter\expandafter\expandafter\syst_helpers_raw_process_action_next - \fi - \fi} - -\def\syst_helpers_raw_process_action_gobble#-\ignorearguments - {} - -\def\syst_helpers_raw_process_action_next - {\expandafterspaces\syst_helpers_raw_process_action} - -\protected\def\xrawprocessaction[#1]#2[#3]% - {\edef\m_syst_string_one{#1}% - \ifempty\m_syst_string_one - \let\m_syst_string_one\s!default - \fi - \let\m_syst_helpers_process_action\relax - \let\m_syst_helpers_process_action_unknown\relax - \syst_helpers_raw_process_action#3\ignorearguments\ignorearguments\ignorearguments - \ifx\m_syst_helpers_process_action\relax - \m_syst_helpers_process_action_unknown - \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 \type -%D {\let} and \type {\expandafter} in the test. -%D -%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{\defcsname #1#2\endcsname} % takes #3 -\def\dosetevalue #1#2{\edefcsname #1#2\endcsname} % takes #3 -\def\dosetgvalue #1#2{\global\edefcsname#1#2\endcsname} % takes #3 -\def\doresetvalue #1#2{\letcsname #1#2\endcsname\empty} -\def\doignorevalue#1#2#3{\letcsname #1#2\endcsname\empty} -\def\docopyvalue #1#2#3{\defcsname #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. - -\protected\def\showassignerror#1#2% - {\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}} - -\protected\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 - -\permanent\protected\def\getparameters {\dogetparameters\dosetvalue} -\permanent\protected\def\geteparameters {\dogetparameters\dosetevalue} -\permanent\protected\def\getgparameters {\dogetparameters\dosetgvalue} -\permanent\protected\def\getxparameters {\dogetparameters\dosetxvalue} -\permanent\protected\def\forgetparameters{\dogetparameters\doignorevalue} - -\aliased\let\getexpandedparameters\geteparameters - -\def\syst_helpers_grab_parameter_error#1% - {\showassignerror{#1}{\the\inputlineno\space(\m_syst_parameter_n)}} - -\def\syst_helpers_grab_parameter#1,% - {\ifarguments - % done - \else - \syst_helpers_grab_parameter_okay#1,\ignorearguments - \expandafter\syst_helpers_grab_parameter_next - \fi} - -\def\syst_helpers_grab_parameter_okay#1=#2,% - {\ifarguments - \or - \syst_helpers_grab_parameter_error{#1}% - \or - \m_syst_parameter_s\m_syst_parameter_n{#1}{#2}% - \fi} - -\def\syst_helpers_grab_parameter_next - {\expandafterspaces\syst_helpers_grab_parameter} - -\permanent\protected\def\dogetparameters#1[#2]#*[#3]% - {\def\m_syst_parameter_n{#2}% - \let\m_syst_parameter_s#1% - \expandafterspaces\syst_helpers_grab_parameter#3\ignorearguments\ignorearguments} - -%D \macros -%D {getemptyparameters} -%D -%D Sometimes we explicitly want variables to default to an empty string, so we -%D welcome: -%D -%D \starttyping -%D \getemptyparameters [label] [...=...,...=...] -%D \stoptyping - -\permanent\protected\def\getemptyparameters[#1]#*[#2]% - {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}% - \processcommalist[#2]\syst_helpers_get_empty_parameters} - -%D We now just alias these as there is no need for a speedup. These have not been used -%D for a long time in core code. - -\let\doassign \getparameters -\let\doeassign \geteparameters -\let\undoassign\forgetparameters - -%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 worth the -%D trouble and tokens. - -\permanent\protected\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]} - -\permanent\protected\def\processassignmentcommand[#1]% - {\normalexpanded{\processassignmentlist[#1]}} - -\permanent\protected\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist - {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}% - \processassignmentlist[#1]\currentassignmentlistcommand} - -\permanent\protected\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand - {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}% - \normalexpanded{\processassignmentlist[#1]}\currentassignmentlistcommand} - -%D \macros -%D {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 {copyparameters} -%D -%D Some \CONTEXT\ commands take their default setups from others. All commands that -%D are able to provide backgounds or rules around some content, for instance default -%D to the standard command for ruled boxes. Is situations like this 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 for use in a -%D multi||lingual environment. - -\permanent\protected\def\copyparameters[#1]#*[#2]#*[#3]% - {\doifnot{#1}{#2} - {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#2}}% ##1 - \processcommalist[#3]\syst_helpers_copy_parameter}} - -% %D \macros -% %D {ifparameters,checkparameters} -% %D -% %D A slightly different one is \type {\checkparameters}, which also checks on the -% %D presence of a~\type {=}. -% %D -% %D The boolean \type {\ifparameters} can be used afterwards. Combining both in one -% %D \type {\if}||macro would lead to problems with nested \type {\if}'s. -% %D -% %D \starttyping -% %D \checkparameters[argument] -% %D \stoptyping -% -% \newif\ifparameters -% -% \protected\def\checkparameters[#1]% -% {\ifhastok={#1}\parameterstrue\else\parametersfalse\fi} - -%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#0,% no #- as we need to count - {\ifarguments\or - \advance\commalistcounter\plusone - \expandafter\syst_helpers_get_comma_list_size - \fi} - -\protected\def\getcommalistsize[% - {\futureexpand]\syst_helpers_get_comma_list_size_nop\syst_helpers_get_comma_list_size_yes} - -\def\syst_helpers_get_comma_list_size_yes#+]% - {\commalistcounter\zerocount - \syst_helpers_get_comma_list_size #1,\ignorearguments\ignorearguments - \edef\commalistsize{\the\commalistcounter}} - -\def\syst_helpers_get_comma_list_size_nop]% - {\commalistcounter\zerocount - \let\commalistsize\!!zerocount} - -\permanent\protected\def\getcommacommandsize[#1]% - {\normalexpanded{\getcommalistsize[#1]}} - -%D Filters: - -% \def\syst_helpers_gobble_comma_list#0\ignorearguments{} - -\def\syst_helpers_gobble_comma_list#-\ignorearguments{} - -\def\syst_helpers_get_from_comma_list#1,% - {\ifarguments \or - \advance\commalistcounter \minusone - \ifcase\commalistcounter - \def\commalistelement{#1}% - \expandafter\expandafter\expandafter\syst_helpers_gobble_comma_list - \else - \expandafter\expandafter\expandafter\syst_helpers_get_from_comma_list_next - \fi - \fi} - -\def\syst_helpers_get_from_comma_list_next - {\expandafterspaces\syst_helpers_get_from_comma_list} - -\permanent\protected\def\getfromcommalist[#1]#*[#2]% - {\let\commalistelement\empty - \commalistcounter#2\relax - \expandafterspaces\syst_helpers_get_from_comma_list#1\ignorearguments\ignorearguments} - -\permanent\protected\def\getfromcommacommand[#1]% - {\normalexpanded{\getfromcommalist[#1]}} - -%D Watertight (and efficient) solutions are hard to find, due to the handling of -%D braces during parameters passing and 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 alternative, which can -%D handle 9~elements at most. -%D -%D \starttyping -%D \dogetcommalistelement1\from a,b,c\to\commalistelement -%D \stoptyping - -\def\syst_helpers_get_comma_list_element#1,#2,#3,#4,#5,#6,#7,#8,#9,% - {\ifcase\scratchcounter\or#1\or#2\or#3\or#4\or#5\or#6\or#7\or#8\or#9\fi - \syst_helpers_gobble_comma_list} - -\permanent\protected\def\dogetcommacommandelement#1\from#2\to#3% - {\scratchcounter#1\relax - \edef#3{\normalexpanded{\syst_helpers_get_comma_list_element#2\ignorearguments\ignorearguments}}} - -%D \macros -%D {dosingleargument,dodoubleargument,dotripleargument, -%D doquadrupleargument,doquintupleargument,dosixtupleargument, -%D doseventupleargument} -%D -%D When working with delimited arguments, spaces and lineendings can interfere. The -%D next set of macros uses \TEX' internal scanner for grabbing everything between -%D arguments. Forgive me the funny names. -%D -%D \starttyping -%D \dosingleargument \command = \command[#1] -%D \dodoubleargument \command = \command[#1][#2] -%D \dotripleargument \command = \command[#1][#2][#3] -%D \doquadrupleargument \command = \command[#1][#2][#3][#4] -%D \doquintupleargument \command = \command[#1][#2][#3][#4][#5] -%D \dosixtupleargument \command = \command[#1][#2][#3][#4][#5][#6] -%D \doseventupleargument\command = \command[#1][#2][#3][#4][#5][#6][#7] -%D \stoptyping -%D -%D These macros can be used in the following way: -%D -%D \starttyping -%D \def\dosetupsomething[#1][#2]% -%D {... #1 ... #2 ...} -%D -%D \protected\def\setupsomething -%D {\dodoubleargument\dosetupsomething} -%D \stoptyping -%D -%D The implementation can be surprisingly simple and needs no further explanation, -%D 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 two||step solution when -%D getting five or more arguments. -%D -%D When developing more and more of the real \CONTEXT, we started using some -%D alternatives that provided empty arguments (in fact optional ones) whenever the -%D user failed to supply them. Because this more complicated macros enable us to do -%D some checking, we reimplemented the non||empty ones. - -%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 wanted arguments are -%D indeed supplied by the user. - -\newcount\nofarguments - -\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 use the \type -%D {\if...argument} boolean. For novice: watch the stepwise doubling of \type {#}'s. - -%D NB : experimental versions in cont-exp.mkiv - -%D Common: - -\newtoks\t_syst_aux - -% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux} -% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux} -% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux} -% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux} -% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux} -% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux} -% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux} -% -% %D Single: -% -% \protected\def\dosingleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop} -% -% \def\syst_helpers_single_empty_one_nop -% {\firstargumentfalse -% \the\t_syst_aux[]} -% -% %D Double -% -% \protected\def\dodoubleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop} -% -% % \def\syst_helpers_double_empty_one_yes[#1]% -% % {\firstargumenttrue -% % \toksapp\t_syst_aux{[{#1}]}% -% % \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} -% % -% % nicer is: -% -% \def\syst_helpers_double_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} -% -% \def\syst_helpers_double_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_double_empty_two_nop -% {\secondargumentfalse -% \the\t_syst_aux[]} -% -% % Triple -% -% \protected\def\dotripleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop} -% -% \def\syst_helpers_triple_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop} -% -% \def\syst_helpers_triple_empty_two_yes[#+]% -% {\secondargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop} -% -% \def\syst_helpers_triple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \the\t_syst_aux[][][]} -% -% \def\syst_helpers_triple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_triple_empty_three_nop -% {\thirdargumentfalse -% \the\t_syst_aux[]} -% -% %D Quadruple: -% -% \protected\def\doquadrupleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop} -% -% \def\syst_helpers_quadruple_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop} -% -% \def\syst_helpers_quadruple_empty_two_yes[#+]% -% {\secondargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop} -% -% \def\syst_helpers_quadruple_empty_three_yes[#+]% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop} -% -% \def\syst_helpers_quadruple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux[][][][]} -% -% \def\syst_helpers_quadruple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux[][][]} -% -% \def\syst_helpers_quadruple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_quadruple_empty_four_nop -% {\fourthargumentfalse -% \the\t_syst_aux[]} -% -% %D Quintuple: -% -% \protected\def\doquintupleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop} -% -% \def\syst_helpers_quintuple_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop} -% -% \def\syst_helpers_quintuple_empty_two_yes[#+]% -% {\secondargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop} -% -% \def\syst_helpers_quintuple_empty_three_yes[#+]% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop} -% -% \def\syst_helpers_quintuple_empty_four_yes[#+]% -% {\fourthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop} -% -% \def\syst_helpers_quintuple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux[][][][][]} -% -% \def\syst_helpers_quintuple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux[][][][]} -% -% \def\syst_helpers_quintuple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux[][][]} -% -% \def\syst_helpers_quintuple_empty_four_nop -% {\fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_quintuple_empty_five_nop -% {\fifthargumentfalse -% \the\t_syst_aux[]} -% -% %D Sixtuple: -% -% \protected\def\dosixtupleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop} -% -% \def\syst_helpers_sixtuple_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop} -% -% \def\syst_helpers_sixtuple_empty_two_yes[#+]% -% {\secondargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop} -% -% \def\syst_helpers_sixtuple_empty_three_yes[#+]% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop} -% -% \def\syst_helpers_sixtuple_empty_four_yes[#+]% -% {\fourthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop} -% -% \def\syst_helpers_sixtuple_empty_five_yes[#+]% -% {\fifthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop} -% -% \def\syst_helpers_sixtuple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \the\t_syst_aux[][][][][][]} -% -% \def\syst_helpers_sixtuple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \the\t_syst_aux[][][][][]} -% -% \def\syst_helpers_sixtuple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \the\t_syst_aux[][][][]} -% -% \def\syst_helpers_sixtuple_empty_four_nop -% {\fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \the\t_syst_aux[][][]} -% -% \def\syst_helpers_sixtuple_empty_five_nop -% {\fifthargumentfalse -% \sixthargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_sixtuple_empty_six_nop -% {\sixthargumentfalse -% \the\t_syst_aux[]} -% -% %D Seventuple: -% -% \protected\def\doseventupleempty#1% -% {\t_syst_aux{#1}% -% \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop} -% -% \def\syst_helpers_seventuple_empty_one_yes[#+]% -% {\firstargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop} -% -% \def\syst_helpers_seventuple_empty_two_yes[#+]% -% {\secondargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop} -% -% \def\syst_helpers_seventuple_empty_three_yes[#+]% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop} -% -% \def\syst_helpers_seventuple_empty_four_yes[#+]% -% {\fourthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop} -% -% \def\syst_helpers_seventuple_empty_five_yes[#+]% -% {\fifthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop} -% -% \def\syst_helpers_seventuple_empty_six_yes[#+]% -% {\sixthargumenttrue -% \toksapp\t_syst_aux{[#1]}% -% \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop} -% -% \def\syst_helpers_seventuple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][][][][][][]} -% -% \def\syst_helpers_seventuple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][][][][][]} -% -% \def\syst_helpers_seventuple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][][][][]} -% -% \def\syst_helpers_seventuple_empty_four_nop -% {\fourthargumentfalse -% \fifthargumentfalse -% \sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][][][]} -% -% \def\syst_helpers_seventuple_empty_five_nop -% {\fifthargumentfalse -% \sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][][]} -% -% \def\syst_helpers_seventuple_empty_six_nop -% {\sixthargumentfalse -% \seventhargumentfalse -% \the\t_syst_aux[][]} -% -% \def\syst_helpers_seventuple_empty_seven_nop -% {\seventhargumentfalse -% \the\t_syst_aux[]} - -%tolerant\def\syst_single_empty#1\relax[#+]% -\tolerant\def\syst_single_empty#1\relax[#2]% - {\ifarguments - \or\firstargumentfalse - \or\firstargumenttrue - \fi - #1[#2]} - -%tolerant\def\syst_double_empty#1\relax[#2]#*[#3]% -\tolerant\def\syst_double_empty#1\relax[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse - \or\firstargumenttrue \secondargumentfalse - \or\firstargumenttrue \secondargumenttrue - \fi - #1[#2][#3]} - -%tolerant\def\syst_triple_empty#1\relax[#2]#*[#3]#*[#4]% -\tolerant\def\syst_triple_empty#1\relax[#+]#*[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue - \fi - #1[#2][#3][#4]} - -%tolerant\def\syst_quadruple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]% -\tolerant\def\syst_quadruple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue - \fi - #1[#2][#3][#4][#5]} - -%\tolerant\def\syst_quintuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]% -\tolerant\def\syst_quintuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue - \fi - #1[#2][#3][#4][#5][#6]} - -%tolerant\def\syst_sixtuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]% -\tolerant\def\syst_sixtuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue - \fi - #1[#2][#3][#4][#5][#6][#7]} - -%tolerant\def\syst_seventuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]#*[#8]% -\tolerant\def\syst_seventuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse\seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumenttrue - \fi - #1[#2][#3][#4][#5][#6][#7][#8]} - -\permanent\protected\def\dosingleempty #1{\syst_single_empty #1\relax} -\permanent\protected\def\dodoubleempty #1{\syst_double_empty #1\relax} -\permanent\protected\def\dotripleempty #1{\syst_triple_empty #1\relax} -\permanent\protected\def\doquadrupleempty #1{\syst_quadruple_empty #1\relax} -\permanent\protected\def\doquintupleempty #1{\syst_quintuple_empty #1\relax} -\permanent\protected\def\dosixtupleempty #1{\syst_sixtuple_empty #1\relax} -\permanent\protected\def\doseventupleempty#1{\syst_seventuple_empty#1\relax} - -%D Aliases: - -\aliased\let\dosingleargument \dosingleempty -\aliased\let\dodoubleargument \dodoubleempty -\aliased\let\dotripleargument \dotripleempty -\aliased\let\doquadrupleargument \doquadrupleempty -\aliased\let\doquintupleargument \doquintupleempty -\aliased\let\dosixtupleargument \dosixtupleempty -\aliased\let\doseventupleargument\doseventupleempty - -%D \macros -%D {strippedcsname} -%D -%D The next macro can be very useful when using \type{\csname} like in: -%D -%D \starttyping -%D \csname if\strippedcsname\something\endcsname -%D \stoptyping -%D -%D This expands to \type{\ifsomething}. - -\aliased\let\strippedcsname\csstring - -%D \macros -%D {complexorsimple,complexorsimpleempty} -%D -%D Setups can be optional. A command expecting a setup is prefixed by \type -%D {\complex}, a command without one gets the prefix \type {\simple}. Commands like -%D 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 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, but changed into more -%D versatile (more object oriented) ones using the \type {\get..argument} commands. - -\permanent\protected\def\complexorsimple#1% - {\doifelsenextoptional - {\firstargumenttrue \csname\s!complex\csstring#1\endcsname} - {\firstargumentfalse\csname\s!simple \csstring#1\endcsname}} - -\permanent\protected\def\complexorsimpleempty#1% - {\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 worthwile to offer two -%D more alternatives. Watch the build in protection. - -\protected\def\syst_helpers_complex_or_simple#1#2% - {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#2}} - -\protected\def\syst_helpers_complex_or_simple_empty#1% - {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#1[]}} - -\permanent\protected\def\definecomplexorsimple#1% - {\protected\edef#1{\syst_helpers_complex_or_simple - \expandafter\noexpand\csname\s!complex\csstring#1\endcsname - \expandafter\noexpand\csname\s!simple \csstring#1\endcsname}} - -\permanent\protected\def\definecomplexorsimpleempty#1% - {\protected\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 -%D We can add additional definitions later when we have defined \type {\appendtoks}. - -\newconditional\c_syst_helpers_permit_spaces_between_groups - -\permanent\protected\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups} -\permanent\protected\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 the lot in -%D pieces so that we have no nested \type {\nextarguments} potentially being an -%D \type {conditional} token. Okay, these macros are not called that often but it -%D saves crap when tracing. - -% \protected\def\dosinglegroupempty#1% -% {\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop} -% -% \def\syst_helpers_single_group_empty_one_nop -% {\firstargumentfalse -% \the\t_syst_aux{}} -% -% \protected\def\dodoublegroupempty#1% -% {\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop} -% -% % \def\syst_helpers_group_double_empty_one_yes#1% -% % {\firstargumenttrue -% % \toksapp\t_syst_aux{{#1}}% -% % \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} -% % -% % nicer is: -% -% \def\syst_helpers_group_double_empty_one_yes#+% -% {\firstargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} -% -% \def\syst_helpers_group_double_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \the\t_syst_aux{}{}} -% -% \def\syst_helpers_group_double_empty_two_nop -% {\secondargumentfalse -% \the\t_syst_aux{}} -% -% \protected\def\dotriplegroupempty#1% -% {\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop} -% -% \def\syst_helpers_group_triple_empty_one_yes#+% -% {\firstargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop} -% -% \def\syst_helpers_group_triple_empty_two_yes#+% -% {\secondargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop} -% -% \def\syst_helpers_group_triple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \the\t_syst_aux{}{}{}} -% -% \def\syst_helpers_group_triple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \the\t_syst_aux{}{}} -% -% \def\syst_helpers_group_triple_empty_three_nop -% {\thirdargumentfalse -% \the\t_syst_aux{}} -% -% \protected\def\doquadruplegroupempty#1% -% {\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop} -% -% \def\syst_helpers_group_quadruple_empty_one_yes#+% -% {\firstargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop} -% -% \def\syst_helpers_group_quadruple_empty_two_yes#+% -% {\secondargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop} -% -% \def\syst_helpers_group_quadruple_empty_three_yes#+% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop} -% -% \def\syst_helpers_group_quadruple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux{}{}{}{}} -% -% \def\syst_helpers_group_quadruple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux{}{}{}} -% -% \def\syst_helpers_group_quadruple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \the\t_syst_aux{}{}} -% -% \def\syst_helpers_group_quadruple_empty_four_nop -% {\fourthargumentfalse -% \the\t_syst_aux{}} -% -% \protected\def\doquintuplegroupempty#1% -% {\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop} -% -% \def\syst_helpers_group_quintuple_empty_one_yes#+% -% {\firstargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop} -% -% \def\syst_helpers_group_quintuple_empty_two_yes#+% -% {\secondargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop} -% -% \def\syst_helpers_group_quintuple_empty_three_yes#+% -% {\thirdargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop} -% -% \def\syst_helpers_group_quintuple_empty_four_yes#+% -% {\fourthargumenttrue -% \toksapp\t_syst_aux{#1}% -% \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop} -% -% \def\syst_helpers_group_quintuple_empty_one_nop -% {\firstargumentfalse -% \secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux{}{}{}{}{}} -% -% \def\syst_helpers_group_quintuple_empty_two_nop -% {\secondargumentfalse -% \thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux{}{}{}{}} -% -% \def\syst_helpers_group_quintuple_empty_three_nop -% {\thirdargumentfalse -% \fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux{}{}{}} -% -% \def\syst_helpers_group_quintuple_empty_four_nop -% {\fourthargumentfalse -% \fifthargumentfalse -% \the\t_syst_aux{}{}} -% -% \def\syst_helpers_group_quintuple_empty_five_nop -% {\fifthargumentfalse -% \the\t_syst_aux{}} - -\tolerant\def\syst_single_group_empty#1\relax#_% - {\ifarguments - \or\firstargumentfalse - \or\firstargumenttrue - \fi - #1#2} - -\tolerant\def\syst_double_group_empty#1\relax#_#*#_% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse - \or\firstargumenttrue \secondargumentfalse - \or\firstargumenttrue \secondargumenttrue - \fi - #1#2#3} - -\tolerant\def\syst_triple_group_empty#1\relax#_#*#_#*#_% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue - \fi - #1#2#3#4} - -\tolerant\def\syst_quadruple_group_empty#1\relax#_#*#_#*#_#*#_% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue - \fi - #1#2#3#4#5} - -\tolerant\def\syst_quintuple_group_empty#1\relax#_#*#_#*#_#*#_#*#_% - {\ifarguments - \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse - \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue - \fi - #1#2#3#4#5#6} - -\permanent\protected\def\dosinglegroupempty #1{\syst_single_group_empty #1\relax} -\permanent\protected\def\dodoublegroupempty #1{\syst_double_group_empty #1\relax} -\permanent\protected\def\dotriplegroupempty #1{\syst_triple_group_empty #1\relax} -\permanent\protected\def\doquadruplegroupempty #1{\syst_quadruple_group_empty #1\relax} -\permanent\protected\def\doquintuplegroupempty #1{\syst_quintuple_group_empty #1\relax} - -%D These macros can explictly take care of spaces, which means that the next -%D definition and calls are valid: -%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 used to select -%D arguments. Their names explain their functionality. - -\permanent\def\firstofoneargument #1{#1} - -\permanent\def\firstoftwoarguments #1#-{#1} -\permanent\def\secondoftwoarguments #-#1{#1} - -\permanent\def\firstofthreearguments #1#-#-{#1} -\permanent\def\secondofthreearguments #-#1#-{#1} -\permanent\def\thirdofthreearguments #-#-#1{#1} - -\permanent\def\firstoffourarguments #1#-#-#-{#1} -\permanent\def\secondoffourarguments #-#1#-#-{#1} -\permanent\def\thirdoffourarguments #-#-#1#-{#1} -\permanent\def\fourthoffourarguments #-#-#-#1{#1} - -\permanent\def\firstoffivearguments #1#-#-#-#-{#1} -\permanent\def\secondoffivearguments #-#1#-#-#-{#1} -\permanent\def\thirdoffivearguments #-#-#1#-#-{#1} -\permanent\def\fourthoffivearguments #-#-#-#1#-{#1} -\permanent\def\fifthoffivearguments #-#-#-#-#1{#1} - -\permanent\def\firstofsixarguments #1#-#-#-#-#-{#1} -\permanent\def\secondofsixarguments#-#1#-#-#-#-{#1} -\permanent\def\thirdofsixarguments #-#-#1#-#-#-{#1} -\permanent\def\fourthofsixarguments#-#-#-#1#-#-{#1} -\permanent\def\fifthofsixarguments #-#-#-#-#1#-{#1} -\permanent\def\sixthofsixarguments #-#-#-#-#-#1{#1} - -\permanent\protected\def\firstofoneunexpanded #1{#1} - -\permanent\protected\def\firstoftwounexpanded #1#-{#1} -\permanent\protected\def\secondoftwounexpanded #-#1{#1} - -\permanent\protected\def\firstofthreeunexpanded #1#-#-{#1} -\permanent\protected\def\secondofthreeunexpanded#-#1#-{#1} -\permanent\protected\def\thirdofthreeunexpanded #-#-#1{#1} - -%D \macros -%D {globalletempty,letempty, -%D letvalueempty,letgvalueempty, -%D letvaluerelax,letgvaluerelax} -%D -%D Trivial: - -\permanent\protected\def\letempty #1{\let #1\empty} -\permanent\protected\def\globalletempty#1{\glet#1\empty} - -\permanent\protected\def\letvalueempty #1{\letcsname #1\endcsname\empty} -\permanent\protected\def\letgvalueempty#1{\global\letcsname#1\endcsname\empty} -\permanent\protected\def\letvaluerelax #1{\letcsname #1\endcsname\relax} -\permanent\protected\def\letgvalurelax #1{\global\letcsname#1\endcsname\relax} - -\permanent\protected\def\relaxvalueifundefined#1% - {\ifcsname#1\endcsname \else - \letcsname#1\endcsname\relax - \fi} - -%D \macros -%D {wait} -%D -%D The next macro hardly needs explanation. Because no nesting is to be expected, we -%D can reuse \type {\wait} within \type {\wait} itself. - -\protected\def\wait - {\begingroup - \read16 to \wait - \endgroup} - -%D \macros -%D {writestring,writeline, -%D writestatus,statuswidth,normalwritestatus} -%D -%D Maybe one didn't notice, but we've already introduced a macro for showing -%D messages. In the multi||lingual modules, we will also introduce a mechanism for -%D message passing. For 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 of the identification -%D string with the macro \type {\statuswidth}. - -\setnewconstant\statuswidth 15 -%setnewconstant\statuswrite 128 % \pluscxxviii - -\ifdefined\writestring \else - - \protected\def\writestring{\immediate\write\statuswrite} - \protected\def\writeline {\writestring{}} - -\fi - -\protected\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 / todo permanent at lua end - -%D \macros -%D {rawgetparameters} -%D -%D A raw and dirty alternative for \type {\getparameters}; no checking is done! - -\def\syst_helpers_grab_raw_parameter#1=#2,% - {\ifarguments\or\or - \defcsname\m_syst_parameter_n#1\endcsname{#2}% - \expandafter\syst_helpers_grab_raw_parameter_next - \fi} - -\def\syst_helpers_grab_raw_parameter_next - {\expandafterspaces\syst_helpers_grab_raw_parameter} - -\permanent\protected\def\rawgetparameters#1[#2]#*[#3]% - {\def\m_syst_parameter_n{#2}% - %\expandafterspaces\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} - \expandafter\expandafterspaces\expandafter\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} - -%D \macros -%D {doglobal, -%D redoglobal,dodoglobal,resetglobal} -%D -%D The two macros \type {\redoglobal} and \type{\dodoglobal} are used in this and -%D some other modules to enforce a user specified \type {\doglobal} action. The last -%D and often only global assignment in a macro is done with \type {\dodoglobal}, but -%D all preceding ones with \type {\redoglobal}. When using only alternatives, one -%D can reset this mechanism with \type {\resetglobal}. - -\permanent\protected\def\resetglobal - {\enforced\let\redoglobal\relax - \enforced\let\dodoglobal\relax} - -\resetglobal - -\permanent\protected\def\doglobal - {\ifx\redoglobal\relax - \enforced\let\redoglobal\global - \enforced\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 - {\enforced\let\redoglobal\syst_helpers_redo_global - \enforced\let\dodoglobal\syst_helpers_dodo_global} - -%D Whatever (will be overtoaded): - -\protected\def\define#1% - {\ifdefined#1% - \message{[\noexpand#1is already defined]}% - \protected\expandafter\def\expandafter\gobbleddefinition - \else - \protected\expandafter\def - \fi#1} - -\permanent\protected\def\redefine#1% - {\ifdefined#1% - \message{[\noexpand#1is redefined]}% - \fi - \protected\def#1} - -\permanent\protected\def\definemacro#1% - {\ifdefined#1% - \message{[\noexpand#1is already defined]}% - \protected\expandafter\def\expandafter\gobbleddefinition - \else - \protected\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] - -\bgroup \obeylines - -\permanent\protected\gdef\starttexdefinition% - {\bgroup% - \obeylines% - \syst_helpers_start_tex_definition} - -\gdef\syst_helpers_start_tex_definition#1 - {\catcode\endoflineasciicode\ignorecatcode% - \clf_texdefinition_one{#1}} - -\aliased\glet\stoptexdefinition\relax - -\permanent\gdef\dostarttexdefinition#1\stoptexdefinition% - {\egroup% - \clf_texdefinition_two{#1}} - -\egroup - -% \protected\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace - -\permanent\protected\def\texdefinition#1{\begincsname#1\endcsname} - -%D \macros -%D {newcounter, -%D increment,decrement} -%D -%D Unfortunately the number of \COUNTERS\ in \TEX\ is limited, but fortunately we -%D can store numbers in a macro. We can increment such pseudo \COUNTERS\ with \type -%D {\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 \type {\counter} is 20, 16, 17 -%D and~18. Of course there is 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 at~0. It is -%D nevertheless better to define a \COUNTER\ explicitly. One reason could be that -%D the \COUNTER\ can be part of a test with \type {\ifnum} and this conditional does -%D not accept undefined macro's. The \COUNTER\ in our example can for instance be -%D defined with: -%D -%D \starttyping -%D \newcounter\counter -%D \stoptyping -%D -%D The command \type {\newcounter} must not be confused with \type {\newcount}! Of -%D course this mechanism is much slower than using \TEX's \COUNTERS\ directly. In -%D practice \COUNTERS\ (and therefore our pseudo counters too) are seldom the -%D bottleneck in the processing of a text. Apart from some other incompatilities we -%D want to mention a pitfal 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 second number after -%D reading \type {\pseudocounter}, while in the second test, it stops reading after -%D having encountered a real one. Tests like the first one therefore can give -%D unexpected results, for instance execution of \type {\doif} even if both numbers -%D are unequal. - -\def\zerocountervalue{0} - -\permanent\protected\def\newcounter#1% - {\dodoglobal\let#1\zerocountervalue} - -%D Nowadays we don't mind a few more tokens if we can gain a 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% - {\def\m_syst_action_yes{\syst_helpers_do_do_do_increment#1}% - \def\m_syst_action_nop{\syst_helpers_do_do_do_increment#1,\plusone}% - \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop} - -\def\syst_helpers_do_do_decrement(#1% - {\def\m_syst_action_yes{\syst_helpers_do_do_do_decrement#1}% - \def\m_syst_action_nop{\syst_helpers_do_do_do_decrement#1,\plusone}% - \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop} - -\permanent\protected\def\increment{\doifelsenextcharcs(\syst_helpers_do_do_increment\syst_helpers_do_increment} -\permanent\protected\def\decrement{\doifelsenextcharcs(\syst_helpers_do_do_decrement\syst_helpers_do_decrement} - -\permanent\protected\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}} -\permanent\protected\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}} - -\permanent\protected\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname} -\permanent\protected\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname} - -%D \macros -%D {newsignal} -%D -%D When writing advanced macros, we cannot do without signaling. A signal is a small -%D (invisible) kern or penalty that signals the next macro that something just -%D happened. This macro can take any action depending on the previous signal. -%D Signals must be unique and the next macro takes care of that. -%D -%D \starttyping -%D \newsignal\somesignal -%D \stoptyping -%D -%D Signals old dimensions and can be used in skips, kerns and tests like \type -%D {\ifdim}. - -\newdimen\d_syst_maximum_signal % step is about 0.00025pt - -\permanent\protected\def\newsignal#1% - {\ifdefined#1\else - \advance\d_syst_maximum_signal2\scaledpoint % to be save in rounding - \immutable\dimensiondef#1\d_syst_maximum_signal - \fi} - -%D \macros -%D {strippedcsname} -%D -%D The next macro can be very useful when using \type {\csname} like in: -%D -%D \starttyping -%D \csname if\strippedcsname\something\endcsname -%D \stoptyping - -\aliased\let\checkedstrippedcsname\csstring - -%D \macros -%D {savenormalmeaning} -%D -%D We will use this one in: - -\permanent\protected\def\savenormalmeaning#1% - {\ifcsname normal\csstring#1\endcsname \else - \letcsname 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 the other hand its -%D recursion engine is quite unique. We therefore identify the for||looping macros -%D by this method. The most simple alternative is the one that only needs a number. -%D -%D \starttyping -%D \dorecurse {n} {whatever we want} -%D \stoptyping -%D -%D This macro can be nested without problems and therefore be used in situations -%D where \PLAIN\ \TEX's \type {\loop} macro ungracefully fails. The current value of -%D the counter is available in \type {\recurselevel}, before as well as after the -%D \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 \type {\recurselevel} concern the -%D outer loop, while the third and fifth one concern the inner loop. The depth of -%D the nesting is available for inspection in \type {\recursedepth}. -%D -%D Both \type {\recurselevel} and \type {\recursedepth} are macros. The real -%D \COUNTERS\ are hidden from the user because we don't want any interference. -%D -%D We now use the macro stack which is somewhat leaner and meaner and a little -%D faster too. - -% left overs: too much \protected here - -\newcount\outerrecurse -\newcount\innerrecurse - -\def\recursedepth{\the\outerrecurse} -\def\recurselevel{0} - -\let\recurseaction\relax -\let\recursestring\empty - -% \let\syst_helpers_stepwise_next\relax - -% \protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step -% {\ifnum#1>#2\relax -% \expandafter\syst_helpers_stepwise_recurse_nop -% \else -% \def\recurselevel{#1}% -% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter -% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} - -\protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step - {\ifnum#1>#2\relax - \expandafter\gobblefourarguments - \else - \def\recurselevel{#1}% -% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter -% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} - \doubleexpandafter\syst_helpers_stepwise_recurse_yes - \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} - -\protected\def\syst_helpers_stepwise_recurse_yes - {\syst_helpers_recurse_content - \syst_helpers_stepwise_recurse} - -\protected\def\syst_helpers_stepwise_reverse#1#2#3% from to step - {\ifnum#1<#2\relax -% \expandafter\syst_helpers_stepwise_recurse_nop - \expandafter\gobblefourarguments - \else - \def\recurselevel{#1}% - \innerrecurse#1\relax - \advance\innerrecurse#3\relax -% \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter -% \fi\expandafter{\the\innerrecurse}{#2}{#3}} - \doubleexpandafter\syst_helpers_stepwise_reverse_yes - \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} - -\protected\def\syst_helpers_stepwise_reverse_yes - {\syst_helpers_recurse_content - \syst_helpers_stepwise_reverse} - -% \protected\def\syst_helpers_stepwise_exit -% {\syst_helpers_stepwise_recurse_nop\relax} - -\permanent\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 a special case of the -%D more general: -%D -%D \starttyping -%D \dostepwiserecurse {from} {to} {step} {action} -%D \stoptyping -%D -%D This commands accepts positive and negative steps. Illegal values are handles as -%D good as possible and the macro accepts numbers and \COUNTERS. -%D -%D \starttyping -%D \dostepwiserecurse {1} {10} {2} {...} -%D \dostepwiserecurse {10} {1} {-2} {...} -%D \stoptyping -%D -%D Because the simple case (n=1) is used often, we implement it more efficiently: - -\permanent\protected\def\dorecurse#1% - {\ifcase#1\relax - \expandafter\gobbletwoarguments - \or - \expandafter\syst_helpers_recurse_y - \else - \expandafter\syst_helpers_recurse_x - \fi{#1}} - -\protected\def\syst_helpers_recurse_indeed#1#2% from to -% {\ifnum#1>#2 % - {\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}} - -\protected\def\syst_helpers_recurse_indeed_yes - {\syst_helpers_recurse_content - \syst_helpers_recurse_indeed} - -\protected\def\syst_helpers_recurse_indeed_nop#0#0#0% - {} - -%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 - -\permanent\protected\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 (a combinations of) -%D conditions. We therefore implement a straightforward loop, which can only be left -%D when we explictly exit it. Nesting is supported. First we present a more -%D 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 \type {\loopdepth}. - -\aliased\let\endofloop\donothing % maybe \syst_helpers_loop_end - -\permanent\protected\def\doloop#1% - {\global\advance\outerrecurse \plusone - \globalpushmacro\recurseaction - \globalpushmacro\recurselevel - \protected\gdef\recurseaction##1##2{#1}% - \enforced\let\endofloop\syst_helpers_loop - \syst_helpers_loop1}% no \plusone else \recurselevel wrong - -\protected\def\syst_helpers_loop#1% - {\def\recurselevel{#1}% - \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}} - -\protected\def\syst_helpers_loop_yes - {\syst_helpers_recurse_content - \endofloop} - -\protected\def\syst_helpers_loop_nop#0% - {\enforced\let\endofloop\syst_helpers_loop - \globalpopmacro\recurselevel - \globalpopmacro\recurseaction - \global\advance\outerrecurse\minusone} - -\permanent\protected\def\exitloop % \exitloop quits at end - {\enforced\let\endofloop\syst_helpers_loop_nop} - -\permanent\protected\def\exitloopnow#0\endofloop % \exitloopnow quits directly - {\syst_helpers_loop_nop} - -%D The loop is executed at least once, so beware of situations 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} statement that should -%D 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 means of a -%D \type {#1}. I decided to pass the more frequently used level as \type {#1} and -%D the less favoured depth as \type {#2}. The 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 expansion here. -%D -%D \starttyping -%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}} -%D \stoptyping - -\def\syst_helpers_recurse_content - {\normalexpanded{\recurseaction{\recurselevel}{\the\outerrecurse}}} - -\protected\def\syst_helpers_recurse_x#1#2% - {\global\advance\outerrecurse\plusone - \globalpushmacro\recurseaction - \globalpushmacro\recurselevel - \protected\gdef\recurseaction##1##2{#2}% - \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}% - \globalpopmacro\recurselevel - \globalpopmacro\recurseaction - \global\advance\outerrecurse\minusone} - -\protected\def\syst_helpers_recurse_y#1#2% - {\global\advance\outerrecurse\plusone - \globalpushmacro\recurseaction - \globalpushmacro\recurselevel - \let\recurselevel\!!plusone - \protected\gdef\recurseaction##1##2{#2}% - \syst_helpers_recurse_content - \globalpopmacro\recurselevel - \globalpopmacro\recurseaction - \global\advance\outerrecurse\minusone} - -% \protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 -% {\global\advance\outerrecurse \plusone -% \globalpushmacro\recurseaction -% \globalpushmacro\recurselevel -% \protected\gdef\recurseaction##1##2{#4}% -% \normalexpanded{\ifcmpnum#3\zerocount -% \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's -% \syst_helpers_stepwise_exit -% \else -% \syst_helpers_stepwise_reverse -% \fi -% \or -% \syst_helpers_stepwise_exit -% \or -% \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's -% \syst_helpers_stepwise_exit -% \else -% \syst_helpers_stepwise_recurse -% \fi -% \fi{\number#1}{\number#2}{\number#3}}% -% \globalpopmacro\recurselevel -% \globalpopmacro\recurseaction -% \global\advance\outerrecurse\minusone} - -\permanent\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 ... todo: remove unused helpers - {\global\advance\outerrecurse \plusone - \globalpushmacro\recurseaction - \globalpushmacro\recurselevel - \protected\gdef\recurseaction##1##2{#4}% - \normalexpanded{\ifcmpnum#3\zerocount - \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's - \doubleexpandafter\gobbletwoarguments - \else - \tripleexpandafter\syst_helpers_stepwise_reverse - \fi - \or - \doubleexpandafter\gobbletwoarguments - \orelse\ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's - \doubleexpandafter\gobbletwoarguments - \else - \doubleexpandafter\syst_helpers_stepwise_recurse - \fi\normalexpanded{{\number#1}{\number#2}{\number#3}}}% - \globalpopmacro\recurselevel - \globalpopmacro\recurseaction - \global\advance\outerrecurse\minusone} - -% \protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0% -% {} - -\newcount\fastloopindex -\newcount\fastloopfinal - -\let\m_syst_helpers_fast_loop_cs\relax - -\permanent\protected\def\dofastloopcs#1% - {\fastloopfinal#1\relax - \ifcase\fastloopfinal - \expandafter\gobbleoneargument - \else - \expandafter\syst_helpers_fast_loop_cs - \fi} - -\protected\def\syst_helpers_fast_loop_cs#1% - {\let\m_syst_helpers_fast_loop_cs#1% - \fastloopindex\plusone - \syst_helpers_fast_loop_cs_step} - -\protected\def\syst_helpers_fast_loop_cs_step - {\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_step - \fi} - -% Helper: - -\permanent\protected\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 - -\permanent\protected\def\doloopoverlist#1#2% - {\global\advance\outerrecurse\plusone - \globalpushmacro\recurseaction - \globalpushmacro\recursestring - \protected\gdef\recurseaction##1{\edef\recursestring{##1}#2}% - \processcommacommand[#1]\recurseaction - \globalpopmacro\recursestring - \globalpopmacro\recurseaction - \global\advance\outerrecurse\minusone} - -%D This is some \LMTX\ experiment: -%D -%D Think of: -%D -%D \starttyping -%D \domatch {(\letterpercent w+) *(\letterpercent w*)} {aa bb cc dd} { -%D [ -%D \domatch{(\letterpercent w)(\letterpercent w)} {#1} {(##1 ##2)} -%D \domatch{(\letterpercent w)(\letterpercent w)} {#2} {(##1 ##2)} -%D ] -%D } -%D -%D and: -%D -%D \stoptyping -%D -%D \starttyping -%D \def\MyMacro#1{(#1)} \ctxluamatch \MyMacro {(.)} {abcd} -%D \stoptyping - -\permanent\protected\def\doloopovermatch#1#2#3% - {\pushmacro\matchloopcommand - \def\matchloopcommand##1##2##3##4##5##6##7##8##9{#3}% - \ctxluamatch\matchloopcommand{#1}{#2}% - \popmacro\matchloopcommand} - -\permanent\def\doloopovermatched#1#2#3% - {\beginlocalcontrol - \pushmacro\matchloopcommand - \def\matchloopcommand##1##2##3##4##5##6##7##8##9{#3}% - \endlocalcontrol - \the\ctxluamatch\matchloopcommand{#1}{#2}% - \beginlocalcontrol - \popmacro\matchloopcommand - \endlocalcontrol} - -%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} - -\permanent\protected\def\newevery#1#2% - {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere - \ifx#2\relax\orelse\ifdefined#2\else - \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname - \frozen\protected\edef#2{\syst_helpers_every#1\csname\??extraevery\csstring#1\endcsname}% - \fi} - -\protected\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 - -\permanent\protected\def\forgeteverypar - {\everypar{\the\neverypar}} - -%D Which we're going to use indeed! When the second argument equals \type {\relax}, -%D the first token list is created unless it is already defined. -%D -%D Technically spoken we could have used the method we are going to present in the -%D visual debugger. First we save the primitive \type{\everypar}: -%D -%D \starttyping -%D \let\normaleverypar=\everypar -%D \stoptyping -%D -%D Next we allocate a \TOKENLIST\ named \type{\everypar}, which means that -%D \type{\everypar} is no longer a primitive but something like \type{\toks44}. -%D -%D \starttyping -%D \newtoks\everypar -%D \stoptyping -%D -%D Because \TEX\ now executes \type{\normaleverypar} instead of \type{\everypar}, we -%D are ready to assign some tokens to 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 every time he expects -%D 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 confusing situations, -%D especially when other packages are used, but it's this kind of tricks that make -%D \TEX\ so powerful. - -%D \macros -%D {convertargument,convertcommand,convertvalue} -%D -%D Some persistent experimenting led us to the next macro. This macro converts a -%D parameter or an expanded macro to it's 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 or the terminal -%D without problems. In \CONTEXT\ we use this macro for generating registers and -%D 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 assignments. - -\permanent\protected\def\convertvalue#1\to - {\expandafter\convertcommand\csname#1\endcsname\to} - -\permanent\protected\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 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 seperation. The next -%D command takes care of propper handling of such multi||faced commands. -%D -%D \starttyping -%D \doifassignmentelse {...} {then ...} {else ...} -%D \stoptyping -%D -%D So -%D \startbuffer -%D \doifelseassignment{a=b}{Y}{N} -%D \doifelseassignment{a+b}{Y}{N} -%D -%D \ifcondition\validassignment {a=b}Y\else N\fi -%D \ifcondition\novalidassignment{a=b}N\else Y\fi -%D \ifcondition\novalidassignment {ab}Y\else N\fi -%D \stopbuffer -%D -%D \typebuffer gives: \blank \getbuffer \blank - -\permanent\protected\def\doifelseassignment#1% - {\ifhastok={#1}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifelseassignmentcs#1#2#3% - {\ifhastok={#1}% - \expandafter#2% - \else - \expandafter#3% - \fi} - -\aliased\let\doifassignmentelse \doifelseassignment -\aliased\let\doifassignmentelsecs\doifelseassignmentcs - -\newif\ifassignment - -\permanent\protected\def\docheckassignment#1% - {\ifhastok={#1}% - \assignmenttrue - \else - \assignmentfalse - \fi} - -\permanent\protected\def\validassignment #1{\ifhastok={#1}} % can become: {\ifhastok=} as we enforce {} -\permanent\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone} % or use unless - -%D In \ETEX\ we can use \type {\detokenize} and gain some speed, but in general far -%D less that 1\% for \type {\convertargument} and nil for \type {\convertcommand}. -%D This macro is more robust than the pure \TEX\ one, something I found out when -%D primitives like \type {\jobname} were fed (or something undefined). - -\permanent\protected\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}} -\permanent\protected\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok - -\permanent\protected\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}} -\permanent\protected\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}} -\permanent\protected\def\edefconvertedargument#1#2{\edef#1{#2}% - \edef#1{\detokenize\expandafter{#1}}} -\permanent\protected\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}} -\permanent\protected\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}} -\permanent\protected\def\xdefconvertedargument#1#2{\xdef#1{#2}% - \xdef#1{\detokenize\expandafter{#1}}} - -%D When you try to convert a primitive command, you'll find out that the \ETEX\ -%D method fails on for instance \type {\jobname} in the sense that it returns the -%D filename instead of just \type {\jobname}. So far this does not give real -%D problems. - -%D This is typically a macro that one comes to after reading the \TEX book -%D carefully. Even then, the definite solution was found after rereading the \TEX -%D book. The first implementation was: -%D -%D \starttyping -%D \def\doconvertargument#1->#2\\\\{#2} -%D \stoptyping -%D -%D The \type {-}, the delimiter \type {\\\\} and the the second argument are -%D completely redundant. - -%D \macros -%D {showvalue} -%D -%D Ahandy macro, for testing purposes only: - -\permanent\protected\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 meanings expand to -%D something \type {->}. This is no problem in the \ETEX\ implementation, but since -%D we want 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. - -\permanent\protected\def\doifelsemeaning#1#2% - {\edef\m_syst_string_one{\normalmeaning#1}% - \def \m_syst_string_two{#2}% - \edef\m_syst_string_two{\normalmeaning\m_syst_string_two}% - \ifx\m_syst_string_one\m_syst_string_two - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifmeaningelse\doifelsemeaning - -%D \macros -%D {doifsamestringselse,doifsamestring,doifnotsamestring} -%D -%D The next comparison macro converts the arguments into expanded strings. This -%D command can be used to compare for instance \type {\jobname} with a name stored -%D 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} - -\permanent\protected\def\doifelsesamestring{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments} -\permanent\protected\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument } -\permanent\protected\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument } - -\aliased\let\doifsamestringelse\doifelsesamestring - -%D These are obsolete in MTX: -%D -%D \starttyping -%D \ConvertToConstant #1#2#3 -%D \CheckConstantAfter #1#2 -%D \ConvertConstantAfter #1#2#3 -%D \stoptyping - -%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. - -\permanent\protected\def\assignifempty#1#2% - {\iftok{#1}\emptytoks \def#1{#2}\fi} - -%D \macros -%D {gobbleuntil,grabuntil,gobbleuntilrelax, -%D processbetween,processuntil} -%D -%D In \TEX\ gobbling usually stand for skipping arguments, so here are our gobbling -%D macros. -%D -%D In \CONTEXT\ we use a lot of \type {\start}||\type {\stop} like constructions. -%D Sometimes, the \type {\stop} is used as a hard coded delimiter like in: %D -%D \starttyping -%D \protected\def\startcommand#1\stopcommand% -%D {... #1 ...} -%D \stoptyping -%D -%D In many cases the \type {\start}||\type {\stop} pair is defined at format -%D generation time or during a job. This means that we cannot hardcode the \type -%D {\stop} criterium. Only after completely understanding \type {\csname} and \type -%D {\expandafter} I was able to to implement a solution, starting with: -%D -%D \starttyping -%D \grabuntil{stop}\command -%D \stoptyping -%D -%D This commands executes, after having encountered \type {\stop} the command \type -%D {\command}. This command receives as argument the text preceding the \type -%D {\stop}. This means that: -%D -%D \starttyping -%D \protected\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 - -\protected\def\syst_helpers_grab#1#2% - {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed} - -\permanent\protected\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 - -\permanent\protected\def\processbetween#1#2% - {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}} - -% \protected\def\gobbleuntil#1% -% {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed} -% -% \protected\def\gobbleuntilrelax#1\relax -% {} - -\permanent\protected\def\gobbleuntil#1% - {\def\syst_helpers_gobble_indeed##-#1{}\syst_helpers_gobble_indeed} - -\permanent\protected\def\gobbleuntilrelax#-\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 - -\permanent\protected\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 form \type{#1} are fixed -%D the the moment the argument is read in. Normally this is no problem, but for -%D instance verbatim environments adapt the \CATCODES\ of characters and therefore -%D are not always happy with already fixed tokens. -%D -%D Another problem arises when the argument is grouped not by \type {{}} but by -%D \type {\bgroup} and \type {\egroup}. Such an argument fails, because the \type -%D {\bgroup} is een as the argument (which is quite normal). -%D -%D The next macro offers a solution for both unwanted 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 at the end of the line. -%D The solution mentioned before does not work here. We also handle -%D -%D \starttyping -%D to be \bold{bold} or not, that's the question -%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 - -\protected\def\syst_helpers_handle_group_nop - {\ifnum\currentgrouptype=\semisimplegroupcode - \expandafter\syst_helpers_handle_group_nop_a - \else - \expandafter\syst_helpers_handle_group_nop_b - \fi} - -\def\syst_helpers_handle_group_nop_a - {\begingroup - \aftergroup\m_syst_helpers_handle_group_a - \aftergroup\endgroup - \m_syst_helpers_handle_group_b} - -\def\syst_helpers_handle_group_nop_b - {\bgroup - \aftergroup\m_syst_helpers_handle_group_a - \aftergroup\egroup - \m_syst_helpers_handle_group_b} - -\protected\def\syst_helpers_handle_group_normal - {\bgroup - \afterassignment\m_syst_helpers_handle_group_normal_before - \let\next=} - -\def\m_syst_helpers_handle_group_normal_before - {\bgroup - \m_syst_helpers_handle_group_b - \bgroup - \aftergroup\m_syst_helpers_handle_group_a - \aftergroup\egroup - \aftergroup\egroup} - -\protected\def\syst_helpers_handle_group_simple% no inner group (so no kerning interference) - {\bgroup - \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_b} - -\def\m_syst_helpers_handle_group_simple_after - {\m_syst_helpers_handle_group_a - \egroup}% - -\protected\def\syst_helpers_handle_group_pickup% no inner group (so no kerning interference) - {\bgroup - \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_a - \aftergroup\egroup - \aftergroup\m_syst_helpers_handle_group_p - \m_syst_helpers_handle_group_b} - -\protected\def\syst_helpers_handle_group_nop_x - {\ifnum\currentgrouptype=\semisimplegroupcode - \begingroup - \aftergroup\endgroup - \else - \bgroup - \aftergroup\egroup - \fi - \m_syst_helpers_handle_group_b} - -\protected\def\syst_helpers_handle_group_normal_x - {\bgroup - \afterassignment\m_syst_helpers_handle_group_normal_before_x - \let\next=} - -\def\m_syst_helpers_handle_group_normal_before_x - {\bgroup - \m_syst_helpers_handle_group_b - \bgroup - \aftergroup\egroup - \aftergroup\egroup} - -%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 fact that \type -%D {\futurelet} obeys blank spaces, and a line||ending token is treated as a blank -%D space. So the final implementation became: - -\permanent\protected\def\groupedcommand#1#2% - {\def\m_syst_helpers_handle_group_b{#1}% - \def\m_syst_helpers_handle_group_a{#2}% - \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} - -\permanent\protected\def\groupedcommandcs#1#2% - {\let\m_syst_helpers_handle_group_b#1% - \let\m_syst_helpers_handle_group_a#2% - \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} - -\permanent\protected\def\simplegroupedcommand#1#2% - {\def\m_syst_helpers_handle_group_b{#1}% - \def\m_syst_helpers_handle_group_a{#2}% - \futureexpandis\bgroup\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop} - -\permanent\protected\def\pickupgroupedcommand#1#2#3% - {\def\m_syst_helpers_handle_group_b{#1}% - \def\m_syst_helpers_handle_group_a{#2}% - \def\m_syst_helpers_handle_group_p{#3}% - \futureexpandis\bgroup\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop} - -\permanent\protected\def\triggergroupedcommand#1% - {\def\m_syst_helpers_handle_group_b{#1}% - \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} - -\permanent\protected\def\triggergroupedcommandcs#1% - {\let\m_syst_helpers_handle_group_b#1% - \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} - -%D Users should be aware of the fact that grouping can interfere with ones paragraph -%D settings that are executed after the paragraph is closed. One should therefore -%D explictly close the paragraph with \type {\par}, else the settings will be -%D forgotten and not applied. So it's: -%D -%D \starttyping -%D \def\BoldRaggedCenter% -%D {\groupedcommand{\raggedcenter\bf}{\par}} -%D \stoptyping - -%D \macros -%D {checkdefined} -%D -%D The bigger the system, the greater the change that user defined commands collide -%D with those that are part of the system. The next macro gives a warning when a -%D command is already defined. We considered blocking the definition, but this is -%D 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 \type {CAPITALS}. This suggestion -%D is feasible, because \CONTEXT only defines lowcased macros. - -\protected\def\showdefinederror#1#2% - {\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}} - -\protected\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 first grabbing the -%D contents of the paragraph and processing this contents grouped. The next macro -%D for instance typesets 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. When we started -%D typesetting with \TEX, we already had produced lots of text in plain \ASCII. In -%D producing such simple formatted texts, we adopted an open layout, and when -%D switching to \TEX, we continued this open habit. Although \TEX\ permits a cramped -%D and badly formatted source, it adds to confusion and sometimes introduces errors. -%D 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 specifications. The -%D definition of the macro handling \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 ways. The recent version, -%D the fourth one in a row, originally was far more complicated, but some -%D functionality has been moved to other macros. -%D -%D We start with the more simple but in some cases more appropriate alternative is -%D \type {\GotoPar}. This one leaves \type {\par} unchanged and is therefore more -%D robust. On the other hand, \type {\AfterPar} is not supported. - -\let\syst_helpers_par_before\relax -\let\syst_helpers_par_around\relax - -\permanent\protected\def\dowithpar#1#2% - {\globalpushmacro\syst_helpers_par_around - \def\syst_helpers_par_around##1\par{#1##1#2\globalpopmacro\syst_helpers_par_around}% - \expandafter\syst_helpers_par_around\ignorepars} - -\permanent\protected\def\dogotopar#1% - {\globalpushmacro\syst_helpers_par_before - \def\syst_helpers_par_before{#1\globalpopmacro\syst_helpers_par_before}% - \expandafter\syst_helpers_par_before\ignorepars} - -\aliased\let\dogotoparcs\dogotopar - -\permanent\protected\def\dogotoparstart - {\ignorepars} - -%D This is old and kind of obsolete: - -\newtoks\BeforePar -\newtoks\AfterPar - -\permanent\protected\def\GetPar - {\expanded - {\dowithpar - {\the\BeforePar - \BeforePar\emptytoks} - {\the\AfterPar - \BeforePar\emptytoks - \AfterPar\emptytoks}}} - -\permanent\protected\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 macros expect an -%D argument, it interprets a grouped sequence of characters a one token. While this -%D adds to robustness and less ambiguous situations, we sometimes want to be a bit -%D more flexible, or at least want to be a bit more tolerant 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 chapters, sections etc. The -%D commands responsible for these activities accept several alternative ways of -%D argument passing. In these examples, the \type {\par} can be omitted when an -%D 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 - -\permanent\protected\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. When we want to act -%D upon words we can use the \type{w} alternative. -%D -%D \starttyping -%D \dowithwargument\command -%D \dowithwargument{... \command ...} -%D \stoptyping -%D -%D The main difference bwteen two alternatives is in the handling of \type {\par}'s. -%D This time the space token acts 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 - -\permanent\protected\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 \type {\dorecurse}. The -%D next alternative however, suits 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 a row. In both -%D commands, the \type {n*} is optional. When this specification is missing, the -%D command executes once. - -\permanent\protected\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}% - \orelse\ifnum#1<\zerocount - %\normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}% - \dorecurse{-#1}{#4{-#2#3}}% - \orelse\ifx#2+% - \dorecurse{#1}{#4{#3}}% - \else - \dorecurse{#1}{#4{#2#3}}% - \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 are macros. This save -%D some unneeded expansion. But now we just alias. - -\aliased\let\doifelsestringinstring\doifelseinstring -\aliased\let\doifstringinstringelse\doifelseinstring - -%D \macros -%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce, -%D doifintokselse,flushtoks,dotoks} -%D -%D We use tokenlists sparsely within \CONTEXT, because the comma separated lists are -%D more suitable for the user 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 Knuth's \TEX book. - -\newtoks\t_syst_helpers_scratch -\let \m_syst_helpers_scratch\empty - -\permanent\protected\def\appendtoks#1\to#2% - {\ifx\dodoglobal\relax - \expandafter\toksapp - \else - \resetglobal - \expandafter\gtoksapp - \fi#2{#1}} - -\permanent\protected\def\prependtoks#1\to#2% - {\ifx\dodoglobal\relax - \expandafter\tokspre - \else - \resetglobal - \expandafter\gtokspre - \fi#2{#1}} - -% \def\syst_helpers_append_toks_indeed -% {\ifx\dodoglobal\relax -% \expandafter\toksapp -% \else -% \resetglobal -% \expandafter\gtoksapp -% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} -% -% \def\syst_helpers_prepend_toks_indeed -% {\ifx\dodoglobal\relax -% \expandafter\tokspre -% \else -% \resetglobal -% \expandafter\gtokspre -% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} -% -% \protected\def\appendtoksonce#1\to#2% -% {\let\m_syst_helpers_scratch#2% -% \t_syst_helpers_scratch{#1}% -% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else -% \syst_helpers_append_toks_indeed -% \fi} -% -% \protected\def\prependtoksonce#1\to#2% -% {\let\m_syst_helpers_scratch#2% -% \t_syst_helpers_scratch{#1}% -% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else -% \syst_helpers_prepend_toks_indeed -% \fi} - -\permanent\protected\def\appendtoksonce#1\to#2% - {\ifhasxtoks{#1}#2\else - \appendtoks#1\to#2% - \fi} - -\permanent\protected\def\prependtoksonce#1\to#2% - {\ifhasxtoks{#1}{#2}\m_syst_helpers_scratch\else - \prependtoks#1\to#2% - \fi} - -%D The test macro: - -\permanent\protected\def\doifelseintoks#1#2% #1 en #2 zijn toks - {\ifhasxtoks#1#2% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifintokselse\doifelseintoks - -%D Moved from \type {lxml-ini.tex} to here. This one is for generators that collect -%D stuff piecewise, which is sometimes hard on mechanisms that grab content using -%D 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 - -\permanent\protected\def\startcollect #1\stopcollect {\toksapp \collectingtoks{#1}} -\permanent\protected\def\startexpandedcollect#1\stopexpandedcollect{\etoksapp\collectingtoks{#1}} - -\permanent\protected\def\startcollecting{\collectingtoks\emptytoks} -\permanent\protected\def\stopcollecting {\the\collectingtoks} - -\permanent\protected\def\collect {\toksapp \collectingtoks} -\permanent\protected\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]} - -\permanent\protected\def\removetoks#1\from#2% - {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3^^^^0004% - {\def\m_syst_string_one{##3}% - \ifempty\m_syst_string_one#2{##1}\else#2{##1##2}\fi}% - \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty^^^^0004} - -%D Also: - -\permanent\protected\def\appendetoks#1\to#2% - {\ifx\dodoglobal\relax - \expandafter\etoksapp - \else - \resetglobal - \expandafter\xtoksapp - \fi#2{#1}} - -\permanent\protected\def\prependetoks#1\to#2% - {\ifx\dodoglobal\relax - \expandafter\etokspre - \else - \resetglobal - \expandafter\xtokspre - \fi#2{#1}} - -%D Hm. - -\permanent\protected\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} - -\aliased\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 the second one. The -%D alternative looking more or less like the first one did not always give the -%D results we needed. Both implementations show some insight in the manipulation of -%D arguments. - -\let\syst_helpers_split_string\relax - -\permanent\protected\def\beforesplitstring#1\at#2\to#3% - {\def\syst_helpers_split_string##1#2##0^^^^0004% no #- as we need to count - {\ifarguments - \let#3\empty - \or - \let#3\empty - \else - \def#3{##1}% - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -\permanent\protected\def\aftersplitstring#1\at#2\to#3% - {\def\syst_helpers_split_string##0#2##2^^^^0004% no #- as we need to count - {\ifarguments - \let#3\empty - \or - \def#3{#1}% - \else - \def#3{##2}% - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -%D \macros -%D {splitstring,greedysplitstring} -%D -%D A bonus macro. - -\permanent\protected\def\splitstring#1\at#2\to#3\and#4% - {\def\syst_helpers_split_string##1#2##2^^^^0004% - {\ifarguments - \let#3\empty - \let#4\empty - \or - \def#3{#1}% - \let#4\empty - \else - \def#3{##1}% - \def#4{##2}% - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -\permanent\protected\def\greedysplitstring#1\at#2\to#3\and#4% - {\def\syst_helpers_split_string##1#2##2^^^^0004% - {\ifarguments - \let#3\empty - \let#4\empty - \or - \def#3{#1}% - \let#4\empty - \else - \def#3{##1}% - \def#4{##2}% - \def\syst_helpers_split_string####1#2####2^^^^0004% - {\ifarguments - \or - \else - \expandafter\def\expandafter#3\expandafter{#3####1}% - \def#4{####2}% - \syst_helpers_split_string####2^^^^0004\ignorearguments\ignorearguments - \fi}% - \syst_helpers_split_string##2^^^^0004\ignorearguments\ignorearguments - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -%D \macros -%D {beforetestandsplitstring, -%D aftertestandsplitstring, -%D testandsplitstring} - -\aliased\let\beforetestandsplitstring\beforesplitstring - -\permanent\protected\def\aftertestandsplitstring#1\at#2\to#3% - {\def\syst_helpers_split_string##0#2##2^^^^0004% no #- as we need to count - {\ifarguments - \let#3\empty - \or - \let#3\empty - \else - \def#3{##2}% - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -\permanent\protected\def\testandsplitstring#1\at#2\to#3\and#4% - {\def\syst_helpers_split_string##1#2##2^^^^0004% - {\ifarguments - \let#3\empty - \let#4\empty - \or - \let#3\empty - \let#4\empty - \else - \def#3{##1}% - \def#4{##2}% - \fi}% - \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} - -%D \macros -%D {splitatperiod, splitatcomma, splitatasterisk, splitatcolon, splitatcolons} - -\protected\def\syst_helpers_splitatperiod #1.#2.#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} -\protected\def\syst_helpers_splitatcomma #1,#2,#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} -\protected\def\syst_helpers_splitatasterisk #1*#2*#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} -\protected\def\syst_helpers_splitatcolon #1:#2:#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} -\protected\def\syst_helpers_splitatcolons #1::#2::#-^^^^0004#3#4{\edef#3{#1}\edef#4{#2}} - -\permanent\protected\def\splitatperiod #1{\normalexpanded{\syst_helpers_splitatperiod #1}..^^^^0004} -\permanent\protected\def\splitatcomma #1{\normalexpanded{\syst_helpers_splitatcomma #1},,^^^^0004} % not at ", " -\permanent\protected\def\splitatasterisk#1{\normalexpanded{\syst_helpers_splitatasterisk#1}**^^^^0004} -\permanent\protected\def\splitatcolon #1{\normalexpanded{\syst_helpers_splitatcolon #1}::^^^^0004} -\permanent\protected\def\splitatcolons #1{\normalexpanded{\syst_helpers_splitatcolons #1}::::^^^^0004} - -%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: - -\permanent\protected\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 later want the tools to -%D append or remove items from such a list. When we add an item, we first check if -%D it's already 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 implementation of the -%D second command is more complecated, because we have to take leading spaces into -%D account. Keep in mind that users may provide lists with spaces after the commas. -%D When one item is left, we also have to get rid of 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. A fast appending alternative, -%D without any testing, is 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: - -\permanent\protected\def\appendtocommalist#1#2% - {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}} - -\permanent\protected\def\prependtocommalist#1#2% - {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}} - -\permanent\protected\def\addtocommalist#1#2% {item} \cs - {\rawdoifelseinset{#1}#2\resetglobal - {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}}} - -\permanent\protected\def\pretocommalist#1#2% {item} \cs - {\rawdoifelseinset{#1}#2\resetglobal - {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}}} - -\permanent\protected\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} - -\aliased\let\robustdoifinsetelse\robustdoifelseinset - -\permanent\protected\def\robustaddtocommalist#1#2% {item} \cs - {\robustdoifelseinset{#1}#2\resetglobal - {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}}} - -\permanent\protected\def\robustpretocommalist#1#2% {item} \cs - {\robustdoifelseinset{#1}#2\resetglobal - {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}}} - -\permanent\protected\def\xsplitstring#1#2% \cs {str} - %{\def\syst_helpers_split_string##1,#2,##2,#2,##3\\% - {\def\syst_helpers_split_string##1,#2,##2,#2,##-\\% - {\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} -\def\acleanedupcommalist#1,,#-\relax{#1} - -\permanent\protected\def\removefromcommalist#1#2% to be sped up - {\rawdoifelseinset{#1}#2% - {\normalexpanded{\xsplitstring\noexpand#2{#1}}% - \dodoglobal\edef#2% - {\ifempty\m_syst_string_one - \m_syst_string_two - \else - \m_syst_string_one\ifempty\m_syst_string_two\else,\m_syst_string_two\fi - \fi}} - \resetglobal} - -%D \macros -%D {substituteincommalist} -%D -%D Slow but seldom used, so for the moment we stick to this 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 - \ifempty\m_syst_string_two \else - \edef\m_syst_string_four{\ifempty\m_syst_string_four\else\m_syst_string_four,\fi\m_syst_string_two}% - \fi - \else - \edef\m_syst_string_four{\ifempty\m_syst_string_four\else\m_syst_string_four,\fi#1}% - \fi} - -\permanent\protected\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% we can use #+ here too - {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax - \ifempty\newcommalistelement\else - \ifempty\m_syst_helpers_comma_list_target - \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 - \ifempty\m_syst_helpers_comma_list_target - \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} - -\permanent\protected\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 fact that the way they -%D handle expansion as well as the fact that they can be nested. This makes them -%D kind of useless for 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} - -\permanent\protected\def\globalprocesscommalist[#1]#2% - {\glet\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} -% -% Okay, not really an impressive extension to the engine, but better than some macro -% that is demonstrating deeper understanding of \TEX. It's anyway a trivial extension -% anyway. There are actually many examples of very advanced macros and exposure of -% how clever one is that could be done cheap in the engine. It's just that at the time -% that \TEX\ was written, it made no sense to add a lot of that. After decades we know -% what extras we need. - -\permanent\def\withoutpt#1{\thewithoutunit\dimexpr#1} % best use the primitive directly - -%D The capitals are needed because \type {p} and \type {t} have catcode~12, while -%D macronames only permit tokens with the catcode~11. As a result we cannot use the -%D \type {.group} primitives. Those who want to know more about this kind of -%D manipulations, we advice to study the \TEX book in detail. Because this macro -%D does not do any assignment, we can use it in the following way too. - -% \def\PtToCm#1% -% {\withoutpt\the\dimexpr0.0351459804\dimexpr#1\relax\relax cm} - -\permanent\def\PtToCm#1{\thewithoutunit\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} - -\permanent\def\dimensiontocount#1#2{#2\numexpr\dimexpr#1\relax/\maxcard\relax} -\permanent\def\numberofpoints #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax} - -%D \macros -%D {swapdimens,swapskips,swapcounts,swapmacros, -%D globalswapdimens,globalswapcounts,globalswapmacros} -%D -%D Simple but effective are the next two macros. There name exactly states their -%D purpose. - -\newdimen\d_syst_helpers_swapped -\newskip \s_syst_helpers_swapped -\newcount\c_syst_helpers_swapped -\let \m_syst_helpers_swapped\relax - -% \protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped} -% \protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped} -% \protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped} -% \protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped} - -\aliased\let\swapdimens\swapcsvalues -\aliased\let\swapskips \swapcsvalues -\aliased\let\swapcounts\swapcsvalues -\aliased\let\swapmacros\swapcsvalues - -% \protected\def\globalswapdimens#1#2{\d_syst_helpers_swapped#1\global#1#2\global#2\d_syst_helpers_swapped} -% \protected\def\globalswapskips #1#2{\s_syst_helpers_swapped#1\global#1#2\global#2\s_syst_helpers_swapped} -% \protected\def\globalswapcounts#1#2{\c_syst_helpers_swapped#1\global#1#2\global#2\c_syst_helpers_swapped} -% \protected\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet#1#2\glet#2\m_syst_helpers_swapped} - -\permanent\protected\def\globalswapdimens{\global\swapcsvalues} -\permanent\protected\def\globalswapskips {\global\swapcsvalues} -\permanent\protected\def\globalswapcounts{\global\swapcsvalues} -\permanent\protected\def\globalswapmacros{\global\swapcsvalues} - -%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 - -\permanent\let\pushmacro\localpushmacro -\permanent\let\popmacro \localpopmacro - -%D \macros -%D {setlocalhsize,distributedhsize} -%D -%D Sometimes we need to work with the \type{ \hsize} that is corrected for -%D indentation and left and right skips. The corrected value is available in \type -%D {\localhsize}, which needs to be calculated with \type {\setlocalhsize} first. %D -%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 value provided is added -%D to \type {\localhsize}. - -\newdimen\localhsize - -\protected\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} - -\permanent\def\availablehsize - {\dimexpr - \hsize-\leftskip-\rightskip - \ifnum\hangafter<\zerocount - \ifdim\hangindent>\zeropoint-\else+\fi\hangindent - \fi - \relax} - -\permanent\def\distributedhsize#1#2#3% - {\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax} - -\permanent\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 \type {\if} commands can be used to access macros (or variables) that are -%D normally accessed by using \type {\getvalue}. Using these alternatives safes us -%D three tokens per call. Anyone familiar with the not||values ones, can derive -%D their meaning from the definitions. - -\permanent\protected\def\doifvalue#1#2% - {\iftok{\csname#1\endcsname}{#2}% - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifnotvalue#1#2% - {\iftok{\csname#1\endcsname}{#2}% - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\doifelsevalue#1#2% - {\iftok{\csname#1\endcsname}{#2}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifnothing#1% - {\iftok{#1}\emptytoks - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifsomething#1% - {\iftok{#1}\emptytoks - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\doifelsenothing#1% - {\iftok{#1}\emptytoks - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\doifelsesomething#1% - {\iftok{#1}\emptytoks - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\permanent\protected\def\doifvaluenothing#1% - {\iftok{\csname#1\endcsname}\emptytoks - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\protected\def\doifvaluesomething#1% - {\iftok{\csname#1\endcsname}\emptytoks - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\doifelsevaluenothing#1% - {\iftok{\csname#1\endcsname}\emptytoks - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifvalueelse \doifelsevalue -\aliased\let\doifnothingelse \doifelsenothing -\aliased\let\doifsomethingelse \doifelsesomething -\aliased\let\doifvaluenothingelse\doifelsevaluenothing - -%D \macros -%D {doifemptyelsevalue, doifemptyvalue, doifnotemptyvalue} -%D -%D Also handy: - -\permanent\def\doifelseemptyvalue#1% - {\expandafter\ifempty\csname#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifemptyvalueelse\doifelseemptyvalue - -\permanent\def\doifemptyvalue#1% - {\expandafter\ifempty\csname#1\endcsname - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\permanent\def\doifnotemptyvalue#1% - {\expandafter\ifempty\csname#1\endcsname - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -%D \macros -%D {doifallcommonelse} -%D -%D A complete match of two sets can be tested with \type {\doifallcommonelse}, where -%D the first two 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} - -\permanent\protected\def\doifelseallcommon{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments} -\permanent\protected\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument } -\permanent\protected\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments } - -\aliased\let\doifallcommonelse\doifelseallcommon - -%D \macros -%D {DOIF,DOIFELSE,DOIFNOT} -%D -%D \TEX\ is case sensitive. When comparing arguments, this feature sometimes is less -%D desirable, for instance when we compare filenames. The next three alternatives -%D upcase their 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: - -\protected\def\syst_helpers_do_IF#1#2% - {\uppercase{\iftok{#1}{#2}}% - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\protected\def\syst_helpers_do_IF_NOT#1#2% - {\uppercase{\iftok{#1}{#2}}% - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\protected\def\syst_helpers_do_IF_ELSE#1#2% - {\uppercase{\iftok{#1}{#2}}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\protected\def\syst_helpers_do_IF_INSTRING_ELSE#1#2% - {\uppercase{\doifelseinstring{#1}{#2}}} - -\permanent\protected\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete -\permanent\protected\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete -\permanent\protected\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete -\permanent\protected\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 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 in the set~\type -%D {#1}. The second one calls for \typ {\command [##1][#2]} and the third, well one -%D may guess. These commands support constructions like: -%D -%D \starttyping -%D \def\dodefinesomething[#1][#2]% -%D {\getparameters[\??xx#1][#2]} -%D -%D \protected\def\definesomething% -%D {\dodoubleargumentwithset\dodefinesomething} -%D \stoptyping -%D -%D Which accepts calls like: -%D -%D \starttyping -%D \definesomething[alfa,beta,...][variable=...,...] -%D \stoptyping - -%% \let\syst_helpers_with_set_step\relax -%% \let\m_syst_helpers_with_set_command\empty -%% -%% \def\syst_helpers_with_set_double[#1][#2]% -%% {\doifsomething{#1}% -%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}% -%% \processcommalist[#1]\syst_helpers_with_set_step}} -%% -%% \def\syst_helpers_with_set_triple[#1][#2][#3]% -%% {\doifsomething{#1}% -%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}% -%% \processcommalist[#1]\syst_helpers_with_set_step}} -%% -%% \def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command -%% \def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command -%% -%% \def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command -%% \def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command - -\let\syst_helpers_with_set_step\relax % maybe push pop - -\permanent\tolerant\protected\def\dodoubleemptywithset#1#*[#2]#*[#3]% - {\doifsomething{#2}% - {\def\syst_helpers_with_set_step##1{#1[##1][#3]}% - \processcommalist[#1]\syst_helpers_with_set_step}} - -\permanent\tolerant\protected\def\dotripleemptywithset#1#*[#2]#*[#3]#*[#4]% - {\doifsomething{#2}% - {\def\syst_helpers_with_set_step##1{#1[##1][#3][#4]}% - \processcommalist[#1]\syst_helpers_with_set_step}} - -\aliased\let\dodoubleargumentwithset\dodoubleemptywithset -\aliased\let\dotripleargumentwithset\dotripleemptywithset - -%D \macros -%D {stripcharacters,stripspaces} -%D -%D The next command was needed first when we implemented the \CONTEXT\ interactivity -%D macros. When we use labeled destinations, we often cannot use all the characters -%D we want. We therefore strip some of the troublemakers, like spaces, from the -%D labels before we write them to the \DVI||file, which passes them to for instance -%D a \POSTSCRIPT\ 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 to enclosed in \type -%D {{}}. - -\let\m_syst_helpers_strip_character\empty - -\permanent\protected\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} - -\permanent\protected\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, like \type -%D {\convert...}. - -\permanent\protected\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 tables of contents, -%D references, two||pass optimizations, sorted lists etc. This file is loaded as -%D many times as needed. During such a pass we skip the commands thate are of no use -%D at that moment. Because we don't want to come into trouble with undefined -%D auxiliary commands, we call the macros in a way similar to \type {\getvalue}. The -%D next macro take care of such executions and when not defined, gobbles the -%D unwanted arguments. -%D -%D \starttyping -%D \executeifdefined{name}\gobbleoneargument -%D \stoptyping -%D -%D We can of course gobble more arguments using the appropriate gobbling command. - -\permanent\def\executeifdefined#1% #2 / never change this one again - {\ifcsname#1\endcsname - \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -%D This one also has the advantage that it is fully expandable and that it can be -%D used after an assignment. - -%D \macros -%D {doifsomespaceelse} -%D -%D The next command checks a string on the presence of a space and executed a -%D command accordingly. -%D -%D \starttyping -%D \doifsomespaceelse {tekst} {then ...} {else ...} -%D \stoptyping -%D -%D We use this command in \CONTEXT\ for determing if an argument must be broken into -%D words when made interactive. Watch the use of \type {\noexpand}. - -%D Is this one still needed? - -% \def\syst_helpers_if_some_space_else#1 #2#3^^^^0004{\if\noexpand#2@} -% -% \def\doifelsesomespace#1% % #2#3% -% {\syst_helpers_if_some_space_else#1 @ @^^^^0004% #3\else#2\fi} -% \expandafter\secondoftwoarguments -% \else -% \expandafter\firstoftwoarguments -% \fi} - -\permanent\edef\doifelsesomespace#1% - {\noexpand\ifhastok\space{#1}% - \noexpand\expandafter\noexpand\firstoftwoarguments - \noexpand\else - \noexpand\expandafter\noexpand\secondoftwoarguments - \noexpand\fi} - -\aliased\let\doifsomespaceelse\doifelsesomespace - -%D \macros -%D {processseparatedlist} -%D -%D Maybe a bit late, but here is a more general version of the \type -%D {\processcommalist} command. This time we don't handle nesting but accept -%D 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 argument, which we remove -%D afterwards. - -\let\syst_helpers_process_separated_list_step\relax - -% \def\syst_helpers_process_separated_list#1]#*[#2]#3% -% {\def\syst_helpers_process_separated_list_step##1##2#2% -% {\def\m_syst_string_one{##2}% suggested by VZ -% \if]##1% -% \let\syst_helpers_process_separated_list_step\relax -% \orelse\ifx\blankspace\m_syst_string_one -% #3{##1}% -% \orelse\if]##2% -% \let\syst_helpers_process_separated_list_step\relax -% \else -% #3{##1##2}% -% \fi -% \syst_helpers_process_separated_list_step}% -% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} - -% \def\syst_helpers_process_separated_list#1]#*[#2]#3% -% {\def\syst_helpers_process_separated_list_step##1##2#2% -% {\def\m_syst_string_one{##2}% suggested by VZ -% \if]##1% -% \orelse\ifx\blankspace\m_syst_string_one -% #3{##1}% -% \expandafter\syst_helpers_process_separated_list_step -% \orelse\if]##2% -% \else -% #3{##1##2}% -% \expandafter\syst_helpers_process_separated_list_step -% \fi -% }% -% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} - -% \permanent\protected\def\processseparatedlist[% -% {\syst_helpers_process_separated_list\relax} - -\permanent\protected\def\processseparatedlist[#+]#*[#2]#3% - {\tolerant\def\syst_helpers_process_separated_list_step##1#2% - {\ifarguments\or - #3{##1}% - \expandafter\syst_helpers_process_separated_list_step - \fi}% - \syst_helpers_process_separated_list_step#1\ignorearguments\ignorearguments} - -%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 defined -%D 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 - -\permanent\protected\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 - \orelse\ifx#2####2% - \let\syst_helpers_process_any_list_step\relax - \else - #4{####1####2}% - \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 containing keywords. -%D Assignments are treated accordingly, 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 we decided best not -%D to do so. - -% \protected\def\processassignlist#1[#2]#3% -% {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]% -% {\doif{##3}\relax{#3{##1}}}% -% \def\syst_helpers_process_assign_list_step##1% -% {\syst_helpers_process_assign_list_assign[##1==\relax]}% -% \processcommalist[#2]\syst_helpers_process_assign_list_step} - -\permanent\protected\def\processassignlist#1[#2]#3% - {\def\syst_helpers_process_assign_list_assign[##1=##-=##2]% - {\doif{##2}\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 index entries, the next -%D 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 sort. - -\let\m_syst_helpers_untexed\empty - -\permanent\protected\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} - -\permanent\protected\def\untexargument{\untexsomething\convertargument} -\permanent\protected\def\untexcommand {\untexsomething\convertcommand} - -%D \macros -%D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints} -%D -%D One characteristic of \POSTSCRIPT\ and \PDF\ is that both used big points (\TEX's -%D bp). The next macros convert points and scaled points into big points. The magic -%D factor $72/72.27$ can be found in most \TEX\ related books. -%D -%D \starttyping -%D \ScaledPointsToBigPoints {number} \target -%D \ScaledPointsToWholeBigPoints {number} \target -%D \stoptyping - -\aliased\let\tobigpoints \clf_tobigpoints % todo: permanent at lua end -\aliased\let\towholebigpoints\clf_towholebigpoints % todo: permanent at lua end - -\permanent\protected\def\PointsToBigPoints #1#2{\edef#2{\tobigpoints #1}} % can be avoided -\permanent\protected\def\PointsToWholeBigPoints #1#2{\edef#2{\towholebigpoints#1}} % can be avoided -\permanent\protected\def\ScaledPointsToBigPoints #1#2{\edef#2{\tobigpoints #1\scaledpoint}} % obsolete -\permanent\protected\def\ScaledPointsToWholeBigPoints#1#2{\edef#2{\towholebigpoints#1\scaledpoint}} % obsolete - -%D \macros -%D {PointsToReal} -%D -%D Points can be stripped from their suffix by using \type {\withoutpt}. The next -%D macro enveloppes this macro. -%D -%D \starttyping -%D \PointsToReal {dimension} \target -%D \stoptyping - -% \protected\def\PointsToReal#1#2% -% {\edef#2{\withoutpt\the\dimexpr#1}} - -\permanent\protected\def\PointsToReal#1#2% - {\edef#2{\thewithoutunit\dimexpr#1}} - -%D \macros -%D {dontleavehmode} -%D -%D Sometimes when we enter a paragraph with some command, the first token gets the -%D whole first line. We can prevent this by saying: -%D -%D \starttyping -%D \dontleavehmode -%D \stoptyping -%D -%D This command is used in for instance the language module \type {lang-ini}. The -%D first version was: -%D -%D \starttyping -%D \def\dontleavehmode{\ifhmode\orelse\ifmmode\else$ $\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 interfering grouping -%D at the cost of a box. -%D -%D \starttyping -%D \newbox\b_syst_helpers_dlh -%D -%D \protected\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}. -%D -%D These macros are sort of obsolete as we never use uppercase this way. But -%D nevertheless we provide them: - -\permanent\def\utfupper#1{\clf_upper{#1}} % expandable -\permanent\def\utflower#1{\clf_lower{#1}} % expandable - -\permanent\protected\def\uppercasestring#1\to#2{\dodoglobal\edef#2{\clf_upper{#1}}} -\permanent\protected\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 expansion. What we want is -%D 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 specific tokens in a -%D 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}, takes a real counter. -%D The macro can be preceded by \type {\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\privatescratchcounter\plusone - \fi - \expandafter\syst_helpers_count_token - \fi} - -\permanent\protected\def\counttoken#1\in#2\to#3% - {\privatescratchcounter\zerocount - \def\m_syst_string_one{#1}% - \def\m_syst_string_two{\end}% - \syst_helpers_count_token#2\end - \dodoglobal#3\privatescratchcounter} - -\permanent\protected\def\counttokens#1\to#2% - {\privatescratchcounter\zerocount - \def\syst_helpers_count_token##1{\advance\privatescratchcounter\plusone}% - \handletokens#1\with\syst_helpers_count_token - \dodoglobal#2\privatescratchcounter} - -%D \macros -%D {splitofftokens} -%D -%D Running this one not always gives the expected results. Consider for instance the -%D macro for which I originally wrote this token handler. - -\permanent\protected\def\splitofftokens#1\from#2\to#3% slow but hardly used - {\ifnum#1>\zerocount - \privatescratchcounter#1\relax - \def\syst_helpers_split_off_tokens##1% - {\ifnum\privatescratchcounter>\zerocount - \advance\privatescratchcounter \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 up there. The reason for this is not that logical but follows from \TEX's -%D However, the characters that we expect to find in \type {\test} just don't show -%D sometimes 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 that are \type {\let} -%D are not expanded! -%D -%D \unprotect\getbuffer[next]\protect -%D -%D That's why we finally end up with a macro that looks ahead by using an -%D assignment, this time by using \type {\futurelet}, and grabbing an argument as -%D well. That way we can handle the sentinal, a blank space and grouped tokens. - -\protected\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface - {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed} - -\permanent\protected\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 - \orelse\ifx\nexthandledtoken\end - \expandafter\gobbletwoarguments % also gobble the \end - \else - \expandafter\syst_helpers_handle_tokens_indeed_two - \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 one does a trial -%D typesetting run, for instance to determine dimensions. Some mechanisms, like -%D object inclusion, can fail on such trials. Temporary setting the next boolean to -%D true, helps a lot. The second boolena can be used to inhibit processing -%D completely. - -\newif\ifvisible \visibletrue - -\newtoks\everysettrialtypesetting -\newtoks\everyresettrialtypesetting - -\permanent\protected\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so -\permanent\protected\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 sometimes makes sense to -%D limit the precission. The next macro rounds a real number to two digits. It takes -%D one argument and only works in \ETEX. - -\permanent\def\integerrounding #1{\clf_rounded\zerocount\numexpr#1\relax} -\permanent\def\onedigitrounding #1{\clf_rounded\plusone \numexpr#1\relax} -\permanent\def\twodigitrounding #1{\clf_rounded\plustwo \numexpr#1\relax} -\permanent\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 \protected\def\starthans% -%D {\processcontent{stophans}\test{\message{\test}\wait}} -%D \stoptyping - -\permanent\protected\def\processcontent#1% - {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname} - -\protected\def\syst_helpers_process_content#1#2#3% - {\protected\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. - -\permanent\tolerant\protected\def\dogobblesingleempty [#-]{} -\permanent\tolerant\protected\def\dogobbledoubleempty[#-]#*[#-]{} - -\aliased\let\gobblesingleempty\dogobblesingleempty % also used -\aliased\let\gobbledoubleempty\dogobbledoubleempty % also used - -%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 assignment inside a box. -%D The \type {\empty}'s permits gobbling while preventing spurious \type {\relax}'s. - -\permanent\protected\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick - {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty} - -\permanent\protected\def\freezedimensionwithunit#1#2% - {\setdimensionwithunit\privatescratchdimen#1{#2}\edef#1{\the\privatescratchdimen}} - -%D \macros -%D {doifsometokselse, doifsometoks} -%D -%D Not that fast I guess, but here's a way to test for token registers being empty. - -\permanent\protected\def\doifelsesometoks#1% - {\iftok#1\emptytoks - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -\permanent\protected\def\doifsometoks#1% - {\iftok#1\emptytoks - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\doifemptytoks#1% - {\iftok#1\emptytoks - \expandafter\firstofoneargument - \else - \expandafter\gobbleoneargument - \fi} - -\aliased\let\doifsometokselse\doifelsesometoks - -%D \macros -%D {startstrictinspectnextcharacter} -%D -%D This one is for the bibliography module (still?): - -\let\syst_helpers_strict_inspect_next_character[ - -\def\syst_helpers_strict_inspect_next_character% no user macro ! - {\ifx\nexttoken[% - \expandafter\m_syst_action_yes - \else - \expandafter\m_syst_action_nop - \fi} - -\permanent\protected\def\strictdoifelsenextoptional#1#2% - {\def\m_syst_action_yes{#1}% - \def\m_syst_action_nop{#2}% - \futurelet\nexttoken\syst_helpers_strict_inspect_next_character} - -\aliased\let\strictdoifnextoptionalelse\strictdoifelsenextoptional - -%D \macros -%D {gobblespacetokens} -%D -%D This macro needs a speed-up! - -%\def\gobblespacetokens -% {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do ! - -\permanent\def\gobblespacetokens - {\afterassignment\nexttoken\let\nexttoken=} - -%D \macros -%D {verbatimargument} -%D -%D As the name says, this macro converts its argument to a (rather safe) string. - -\aliased\let\verbatimstring\detokenize - -%D These are needed in ordinal number conversions: - -\permanent\def\lastdigit#1% - {\expandafter\thelastdigit\number#1\relax} - -\permanent\def\thelastdigit#1#2% - {\ifx#2\relax#1\else\expandafter\thelastdigit\expandafter#2\fi} - -\permanent\def\lasttwodigits#1% - {\expandafter\thelasttwodigits\expandafter0\number#1\relax} - -\permanent\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}} - -\permanent\protected\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 number, especially in -%D full expandable macros where using \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 with a space- and -%D relax-less \type {\purenumber}. This macro works ok with \type {\the}, \type -%D {\number} as well as \ETEX's \type {\numexpr}. - -\permanent\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 macros mood}. - -\permanent\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} - -\permanent\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} - -\permanent\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} - -\permanent\tolerant\protected\def\definemeasure[#1]#*[#2]{\defcsname \??measure#1\endcsname{#2}} -\permanent\tolerant\protected\def\freezemeasure[#1]#*[#2]{\edefcsname\??measure#1\endcsname{\the\dimexpr#2}} - -\permanent\protected\def\setmeasure #1#2{\defcsname \??measure#1\endcsname{#2}} % quick way -\permanent\protected\def\setgmeasure#1#2{\global\defcsname \??measure#1\endcsname{#2}} % quick way -\permanent\protected\def\setemeasure#1#2{\edefcsname \??measure#1\endcsname{\the\dimexpr#2}} % quick way -\permanent\protected\def\setxmeasure#1#2{\global\edefcsname\??measure#1\endcsname{\the\dimexpr#2}} % quick way - -\permanent\def\measure {\the\measured} -\permanent\def\measured#1{\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} - -% #2 could be omitted, but we want to support spaces -% -% \setmeasure {x} {1cm} -% \setmeasure {xx} {1cm} -% \setmeasure {xxx}{1cm} - -%D \macros -%D {definequantity} -%D -%D These do the same but for numbers. - -\installsystemnamespace{quantity} - -\permanent\tolerant\protected\def\definequantity[#1]#*[#2]{\defcsname \??quantity#1\endcsname{#2}} -\permanent\tolerant\protected\def\freezequantity[#1]#*[#2]{\edefcsname\??quantity#1\endcsname{\the\numexpr#2}} - -\permanent\protected\def\setquantity #1#2{\defcsname \??quantity#1\endcsname{#2}} % quick way -\permanent\protected\def\setgquantity#1#2{\global\defcsname \??quantity#1\endcsname{#2}} % quick way -\permanent\protected\def\setequantity#1#2{\edefcsname \??quantity#1\endcsname{\the\numexpr#2}} % quick way -\permanent\protected\def\setxquantity#1#2{\global\edefcsname\??quantity#1\endcsname{\the\numexpr#2}} % quick way - -\permanent\def\quantity {\the\quantitied} -\permanent\def\quantitied #1{\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} -\permanent\def\directquantity#1{\the\numexpr#1\relax} - -% let\quantified\quantitied - -%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 - -\permanent\def\dividedsize#1#2#3% size gap n - {\dimexpr - \ifnum\dimexpr#1\relax>\plusone - (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1% - \fi - \relax} - -%D \macros -%D {doifdimensionelse} -%D -%D This is a dirty one: we simply append a unit and discard it when needed. - -\permanent\def\doifelsedimension#1% - {\ifchkdim#1\or - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifdimensionelse\doifelsedimension - -%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 - -\aliased\let\doifelsedimenstring\doifelsedimension -\aliased\let\doifdimenstringelse\doifelsedimenstring - -%D \macros -%D {comparedimension,comparedimensioneps} -%D -%D We no longer use the \MKIV\ dirty trick. These are obsolete anyway. - -\newdimen \roundingeps \roundingeps=10sp -\newconstant\compresult - -\permanent\def\comparedimension#1#2% - {\compresult - \ifdim#1<#2% - \zerocount - \orelse\ifdim#1<#2% - \plusone - \else - \plustwo - \fi} - -\permanent\def\comparedimensioneps#1#2% todo: use eps feature - {\compresult - \ifdim\dimexpr#1-#2\relax<\roudingeps - \zerocount - \orelse\ifdim\dimexpr#2-#1\relax<\roudingeps - \zerocount - \orelse\ifdim#1<#2% - \plusone - \else - \plustwo - \fi} - -% pretty ugly but fast - -% \copycsname xxx\endcsname\csname ..\endcsname - -\permanent\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} - -% \letcscsname \crap \csname ..\endcsname -% \letcsnamecs \csname ..\endcsname\crap -% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname - -\permanent\protected\def\letcscsname {\expandafter\let\expandafter} -\permanent\protected\def\letcsnamecs {\expandafter\let} -\permanent\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} - -% another one, add an item to a commalist - -\permanent\protected\def\addvalue#1#2% cs item - {\ifcsname#1\endcsname\else\letcsname#1\endcsname\empty\fi - \normalexpanded{\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}} - -%D Are these ever used? Anyway, these variants are somewhat more efficient than -%D the \MKIV variants for larger strings. - -% A variant: -% -% \permanent\def\unspaced#1% -% {\localcontrolled{\begingroup\catcode\spaceasciicode\ignorecatcode}% -% \tokenized{#1}% -% \localcontrolled{\endgroup}} -% -% but we can also do this: - -\permanent\def\unspaced#1% - {\tokenized \s!catcodetable \ctdcatcodes {#1}} - -\permanent\protected\def\unspaceargument#1\to#2% - {\edef#2{\tokenized \s!catcodetable \ctdcatcodes {#1}}} - -\protected\def\unspaceafter#1#2% - {\expandafter#1\expandafter{\tokenized \s!catcodetable \ctdcatcodes {#2}}} - -\permanent\protected\def\doifelsehasspace#1% - {\expandafter\ifhastok\space{#1}% - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifhasspaceelse\doifelsehasspace - -% this will replace loadfile once and alike !!! todo - -\installsystemnamespace{flag} - -\protected\def\setflag #1{\dodoglobal\letcsname\??flag#1\endcsname\zerocount} -\protected\def\resetflag#1{\dodoglobal\letcsname\??flag#1\endcsname\plusone} - -\permanent\def\flag#1{\csname\??flag#1\endcsname} - -\permanent\def\doifelseflagged#1% - {\expandafter\ifx\csname\??flag#1\endcsname\relax - \expandafter\secondoftwoarguments - \orelse\ifcase\csname\??flag#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doifflaggedelse\doifelseflagged - -\permanent\def\doifnotflagged#1% - {\expandafter\ifx\csname\??flag#1\endcsname\relax - \expandafter\firstofoneargument - \orelse\ifcase\csname\??flag#1\endcsname - \expandafter\gobbleoneargument - \else - \expandafter\firstofoneargument - \fi} - -\permanent\protected\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey - {\defcsname#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\privatescratchcounter - \endgroup - \doubleexpandafter\secondoftwoarguments - \else - \endgroup - \doubleexpandafter\firstoftwoarguments - \fi - \else - \endgroup - \expandafter\secondoftwoarguments - \fi} - -% used ? - -\permanent\def\doifelsenonzeropositive#1% - {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\privatescratchcounter=0#1\relax\empty\end} - -\aliased\let\doifnonzeropositiveelse\doifelsenonzeropositive - -% here ? - -\protected\def\dosetrawvalue #1#2#3{\defcsname #1#2\endcsname{#3}} -\protected\def\dosetrawevalue#1#2#3{\edefcsname #1#2\endcsname{#3}} -\protected\def\dosetrawgvalue#1#2#3{\global\defcsname #1#2\endcsname{#3}} -\protected\def\dosetrawxvalue#1#2#3{\global\edefcsname#1#2\endcsname{#3}} - -\permanent\protected\def\getrawparameters {\dogetparameters\dosetrawvalue } -\permanent\protected\def\getraweparameters {\dogetparameters\dosetrawevalue} -\permanent\protected\def\getrawgparameters {\dogetparameters\dosetrawgvalue} -\permanent\protected\def\getrawxparameters {\dogetparameters\dosetrawxvalue} - -\permanent\protected\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete - -%D Sort of obsolete: - -\newcount\c_syst_helpers_mod - -\permanent\protected\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} - -\permanent\protected\def\dosetdivision#1#2#3% - {#3#1\divide#3 #2\relax} - -\permanent\protected\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}} -\permanent\protected\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}} - -\def\syst_helpers_unprotected#1\par - {#1\protect} - -\protected\def\unprotected - {\unprotect - \syst_helpers_unprotected} - -\aliased\let\resettimer \clf_resettimer % todo: at lua end -\aliased\let\elapsedtime \clf_elapsedtime % todo: at lua end -\aliased\let\elapsedseconds\elapsedtime - -\let\elapsedsteps\!!zerocount - -\permanent\protected\def\elapsedsteptime % unexpanded ! a bit useless but who knows ... - {\clf_elapsedsteptime\elapsedsteps\relax} - -\newcount\c_syst_helpers_test_feature_n -\newcount\c_syst_helpers_test_feature_m - -\def\currentfeaturetest{\number\c_syst_helpers_test_feature_n} - -\permanent\protected\def\testfeature#1#2% - {\c_syst_helpers_test_feature_m#1\relax - \xdef\elapsedsteps{\number\c_syst_helpers_test_feature_m}% - \def\syst_helpers_test_feature_yes - {\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_yes - \fi}% - \def\syst_helpers_test_feature_nop - {\advance\c_syst_helpers_test_feature_n\plusone - \ifnum\c_syst_helpers_test_feature_n>\c_syst_helpers_test_feature_m\else - \expandafter\syst_helpers_test_feature_nop - \fi}% - \retestfeature} - -\permanent\protected\def\retestfeature % timer support is new per 10/5/2005 - {\bgroup - \ifcase\interactionmode\let\wait\relax\fi - \clf_resettimer - \c_syst_helpers_test_feature_n\zerocount - \syst_helpers_test_feature_nop - \clf_benchmarktimer - \writestatus\m!system - {starting feature test: % - \number\c_syst_helpers_test_feature_m\space steps}% - \c_syst_helpers_test_feature_n\zerocount - \syst_helpers_test_feature_yes - \writestatus\m!system - {feature test done: % - \number\c_syst_helpers_test_feature_m\space steps, % - \clf_elapsedtime\space seconds, % - \clf_elapsedsteptime\elapsedsteps\space\space per step}% - \egroup} - -\permanent\protected\def\showtimer#1% - {\writestatus{runtime}{\elapsedseconds\space s / #1}} - -\permanent\protected\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 - -\permanent\protected\def\freezedimenmacro#1% - {\edef#1{\the\dimexpr#1}} - -%D The next macro negates a macro (dimension or number, or actually, whatever. It's -%D 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 - -\permanent\def\negated#1{\if-#1\else-#1\fi} % does only work in macros or text - -\def\gobbleassigndimen#1\\{} - -\permanent\def\assigndimen#1#2% - {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\} - -\permanent\protected\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}} -\permanent\protected\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname} -\permanent\protected\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname} - -\protected\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}} - -\permanent\protected\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname} -\permanent\protected\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 \type -%D {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 - \ifempty\m_syst_helpers_range_to\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}}}% - -\permanent\protected\def\processranges[#1]#2% #1= n:m,p,q:r - {\def\m_helpers_range_action{#2}% - \processcommacommand[#1]\syst_helpers_with_range} - -\permanent\protected\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 - -\permanent\protected\def\ignoreimplicitspaces - {\doifelsenextchar\relax\relax\relax} - -%D \macros -%D {processwords} -%D -%D Not that sophisticated but sometimes users (like in metafun). - -%D This will be overloaded. - -\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 - -\permanent\protected\def\startnointerference % not even grouped ! - {\setbox\b_syst_helpers_no_interference\vbox - \bgroup} - -\permanent\protected\def\stopnointerference - {\egroup - \setbox\b_syst_helpers_no_interference\emptybox} - -%D A variant for \type {\executeifdefined}: - -\permanent\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 is not -%D set in the font! (This will be overloaded) - -\protected\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. - -\permanent\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 - -\permanent\def\docheckedpair#1% - {\syst_helpers_checked_pair#1,,\_o_e_p_} - -% \def\syst_helpers_checked_pair#1,#2,#0\_o_e_p_ -% {#1,#2} - -\def\syst_helpers_checked_pair#1,#2,#-\_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). - -\permanent\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} - -\permanent\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} - -\permanent\def\constantdimen#1% - {\ifdim#1=\zeropoint - \zeropoint - \else - \the#1\relax - \fi} - -\permanent\def\constantdimenargument#1% - {\ifdim#1=\zeropoint - \zeropoint - \else - {\the#1}% - \fi} - -\permanent\def\constantemptyargument#1% - {\ifempty#1% - \noexpand\empty - \else - {#1}% - \fi} - -%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: - -\permanent\def\getsubstring#1#2#3{\clf_getsubstring{#3}{#1}{#2}} - -%D Other dimensions than pt (used in mb-mp) - -\permanent\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}} - -% \protected\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 -% \orelse\ifx\m_case_temp\s!default -% \expandafter\firstofoneargument -% \else -% \expandafter\syst_aux_case_nop -% \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 -\permanent\def\ntimes#1#2{\clf_ntimes{#1}\numexpr#2\relax} % 0.33 - -%D Experiment (sometimes looks nicer in code): - -\permanent\protected\def\sameargumentscondition#1#2% - {\edef\m_syst_string_one{#1}% - \edef\m_syst_string_two{#2}% - \ifx\m_syst_string_one\m_syst_string_two} - -\permanent\protected\def\emptyargumentcondition#1% - {\edef\m_syst_string_one{#1}% - \ifempty\m_syst_string_one} - -%D New (also serves as an example): -%D -%D \starttyping -%D \commandflags\defineframed -%D \stoptyping - -\permanent\def\commandflags#1% - {\beginlocalcontrol\begingroup\scratchtoks\emptytoks\donefalse - \ifflags#1= \frozenflagcode\etoksapp\scratchtoks{\ifdone \space\fi frozen}\donetrue\fi - \ifflags#1=\permanentflagcode\etoksapp\scratchtoks{\ifdone \space\fi permanent}\donetrue\fi - \ifflags#1=\immutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi immutable}\donetrue\fi - \ifflags#1=\primitiveflagcode\etoksapp\scratchtoks{\ifdone \space\fi primitive}\donetrue\fi - \ifflags#1= \mutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi mutable}\donetrue\fi - \ifflags#1=\noalignedflagcode\etoksapp\scratchtoks{\ifdone \space\fi noaligned}\donetrue\fi - \ifflags#1= \instanceflagcode\etoksapp\scratchtoks{\ifdone \space\fi instance}\donetrue\fi - %\ifflags#1= \reservedflagcode\etoksapp\scratchtoks{\ifdone \space\fi reserved}\donetrue\fi - \ifflags#1= \tolerantflagcode\etoksapp\scratchtoks{\ifdone \space\fi tolerant}\donetrue\fi - \ifflags#1=\protectedflagcode\etoksapp\scratchtoks{\ifdone \space\fi protected}\donetrue\fi - \expandafter\endgroup\expandafter\endlocalcontrol\the\scratchtoks} - -%D \macros -%D {resetmacros} -%D -%D The next macro can be used to reset a macro: -%D -%D \starttyping -%D \resetmacros[startfoo,\stopfoo] -%D \stoptyping - -\permanent\protected\def\syst_reset_macro#1% - {\overloaded\letcsname\csstring#1\endcsname\undefined} % so only frozen (instances( - -\permanent\protected\def\resetmacros[#1]% - {\processcommalist[#1]\syst_reset_macro} - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-con.mkxl b/tex/context/base/mkiv/syst-con.mkxl deleted file mode 100644 index ed4a4f3c5..000000000 --- a/tex/context/base/mkiv/syst-con.mkxl +++ /dev/null @@ -1,88 +0,0 @@ -%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}{} - -\unprotect - -%D \macros{lchexnumber,uchexnumber,lchexnumbers,uchexnumbers} -%D -%D In addition to the uppercase hex conversion, as needed in math families, we -%D occasionally need a lowercase one. - -\permanent\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax} -\permanent\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax} -\permanent\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax} -\permanent\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax} - -\aliased\let\hexnumber\uchexnumber - -%D \macros{octnumber} -%D -%D For \UNICODE\ remapping purposes, we need octal numbers. - -\permanent\def\octnumber#1{\clf_octnumber\numexpr#1\relax} - -%D \macros{hexstringtonumber,octstringtonumber} -%D -%D This macro converts a two character hexadecimal number into a decimal number, -%D thereby taking care of lowercase characters as well. - -\permanent\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax} -\permanent\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax} - -%D \macros{rawcharacter} -%D -%D This macro can be used to produce proper 8 bit characters that we sometimes need -%D in backends and round||trips. - -\permanent\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax} - -%D \macros{twodigits, threedigits} -%D -%D These macros provides two or three digits always: - -\permanent\def\twodigits #1{\ifnum #1<10 0\fi\number#1} -\permanent\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1} - -%D \macros{modulonumber} -%D -%D In the conversion macros described in \type {core-con} we need a wrap||around -%D method. The following solution is provided by Taco. -%D -%D The \type {modulonumber} macro expands to the mathematical modulo of a positive -%D integer. It is crucial for it's application that this macro is fully exandable. -%D -%D The expression inside the \type {\numexpr} itself is somewhat bizarre because -%D \ETEX\ uses a rounding division instead of truncation. If \ETEX's division would -%D have behaved like \TEX's normal\type {\divide}, then the expression could have -%D been somewhat simpler, like \type {#2-(#2/#1)*#1}. This works just as well, but a -%D bit more complex. - -%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} -%permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} - -%D \macros{setcalculatedsin,setcalculatedcos,setcalculatedtan} - -\permanent\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}} -\permanent\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}} -\permanent\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}} - -%D \macros{formatted,format} - -\permanent \def\formatted#1{\ctxcommand{format(#1)}} % not clf -\permanent\protected\def\format #1{\ctxcommand{format(#1)}} % not clf - -%D The \type {\modulatednumber} and \type {\realnumber} macros have been removed. - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-fnt.mkxl b/tex/context/base/mkiv/syst-fnt.mkxl deleted file mode 100644 index f0f023f6e..000000000 --- a/tex/context/base/mkiv/syst-fnt.mkxl +++ /dev/null @@ -1,47 +0,0 @@ -%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 - -\immutable\protected\def\fontslantperpoint {\fontdimen\plusone } -\immutable\protected\def\fontinterwordspace {\fontdimen\plustwo } -\immutable\protected\def\fontinterwordstretch{\fontdimen\plusthree} -\immutable\protected\def\fontinterwordshrink {\fontdimen\plusfour } -\immutable\protected\def\fontexheight {\fontdimen\plusfive } -\immutable\protected\def\fontemwidth {\fontdimen\plussix } -\immutable\protected\def\fontextraspace {\fontdimen\plusseven} - -\immutable\protected\def\slantperpoint {\fontdimen\plusone \font} -\immutable\protected\def\interwordspace {\fontdimen\plustwo \font} -\immutable\protected\def\interwordstretch {\fontdimen\plusthree\font} -\immutable\protected\def\interwordshrink {\fontdimen\plusfour \font} -\immutable\protected\def\exheight {\fontdimen\plusfive \font} -\immutable\protected\def\emwidth {\fontdimen\plussix \font} -\immutable\protected\def\extraspace {\fontdimen\plusseven\font} - -\aliased\let\mathaxisheight\Umathaxis % takes style - -\permanent\def\currentspaceskip{\interwordspace\s!plus\interwordstretch\s!minus\interwordshrink\relax} - -\permanent\def\currentspacevalue{\the\interwordspace - \ifzeropt\interwordstretch\else{ plus }\the\interwordstretch\fi - \ifzeropt\interwordshrink \else{ minus }\the\interwordshrink \fi} - -\permanent\def\usedspacevalue{\ifzeropt\spaceskip\the\spaceskip\else\currentspacevalue\fi} - -\permanent\def\mathstacktotal{\dimexpr\Umathstacknumup\scriptstyle+\Umathstackdenomdown\scriptstyle\relax} -\permanent\def\mathstackvgap {\Umathstackvgap\scriptstyle} - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv index b1ba9e0f3..6b84d33df 100644 --- a/tex/context/base/mkiv/syst-ini.mkiv +++ b/tex/context/base/mkiv/syst-ini.mkiv @@ -583,6 +583,17 @@ \protected\def\uedef{\protected\edef} \protected\def\uxdef{\protected\xdef} +% For now: + +\protected\def\defUmathtopaccent #1#2#3#4{\global\instance\protected\def#1{\Umathaccent "#2 "#3 "#4 }} +\protected\def\defUmathbotaccent #1#2#3#4{\global\instance\protected\def#1{\Umathbotaccent "#2 "#3 "#4 }} +\protected\def\defUdelimiterover #1#2#3#4{\global\instance\protected\def#1{\Udelimiterover "#2 "#3 }} +\protected\def\defUdelimiterunder #1#2#3#4{\global\instance\protected\def#1{\Udelimiterunder "#2 "#3 }} +\protected\def\defUdelimiter #1#2#3#4{\global\instance\protected\def#1{\Udelimiter "#2 "#2 "#4 }} +\protected\def\defUradical #1#2#3{\global\instance\protected\def#1{\Uradical "#2 "#3 }} +\protected\def\defUroot #1#2#3{\global\instance\protected\def#1{\Uroot "#2 "#3 }} +\protected\def\defUmathchar #1#2#3#4{\global\instance\Umathchardef #1 "#2 "#3 "#4 } + %D For a while we keep the following, as systems like tikz need it. Best %D not use that one \CONTEXT. diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl deleted file mode 100644 index d495e12af..000000000 --- a/tex/context/base/mkiv/syst-ini.mkxl +++ /dev/null @@ -1,1096 +0,0 @@ -%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. -%D -%D First we define a bunch of constants. Normally we would \type {\setconstant} -%D but we're prestine and have no macros defined yet. Abstraction also makes it -%D possible to avoid the \type {^^} in the input. - -\immutable\integerdef\escapecatcode 0 -\immutable\integerdef\begingroupcatcode 1 -\immutable\integerdef\endgroupcatcode 2 -\immutable\integerdef\mathshiftcatcode 3 -\immutable\integerdef\alignmentcatcode 4 -\immutable\integerdef\endoflinecatcode 5 -\immutable\integerdef\parametercatcode 6 -\immutable\integerdef\superscriptcatcode 7 -\immutable\integerdef\subscriptcatcode 8 -\immutable\integerdef\ignorecatcode 9 -\immutable\integerdef\spacecatcode 10 -\immutable\integerdef\lettercatcode 11 -\immutable\integerdef\othercatcode 12 % finally obsolete: \let\other \othercatcode -\immutable\integerdef\activecatcode 13 % finally obsolete: \let\active\activecatcode -\immutable\integerdef\commentcatcode 14 -\immutable\integerdef\invalidcatcode 15 - -%chardef\zeroasciicode 0 -\immutable\integerdef\tabasciicode 9 -\immutable\integerdef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode -\immutable\integerdef\formfeedasciicode 12 -\immutable\integerdef\endoflineasciicode 13 % somewhat messy but this can be the active \par -\immutable\integerdef\endoffileasciicode 26 -\immutable\integerdef\spaceasciicode 32 -\immutable\integerdef\exclamationmarkasciicode 33 % ! used in namespace protection -\immutable\integerdef\doublequoteasciicode 34 % " -\immutable\integerdef\hashasciicode 35 -\immutable\integerdef\dollarasciicode 36 -\immutable\integerdef\commentasciicode 37 -\immutable\integerdef\ampersandasciicode 38 -\immutable\integerdef\singlequoteasciicode 39 % ' -\immutable\integerdef\primeasciicode 39 % ' -\immutable\integerdef\leftparentasciicode 40 -\immutable\integerdef\rightparentasciicode 41 -\immutable\integerdef\commaasciicode 44 -\immutable\integerdef\hyphenasciicode 45 -\immutable\integerdef\periodasciicode 46 -\immutable\integerdef\forwardslashasciicode 47 % / -\immutable\integerdef\colonasciicode 58 -\immutable\integerdef\lessthanasciicode 60 % < used as alternative verbatim { -\immutable\integerdef\morethanasciicode 62 % > used as alternative verbatim } -\immutable\integerdef\questionmarkasciicode 63 % ? used in namespace protection -\immutable\integerdef\atsignasciicode 64 % @ used in namespace protection -\immutable\integerdef\leftbracketasciicode 91 -\immutable\integerdef\backslashasciicode 92 % `\\ -\immutable\integerdef\rightbracketasciicode 93 -\immutable\integerdef\circumflexasciicode 94 -\immutable\integerdef\underscoreasciicode 95 -\immutable\integerdef\leftbraceasciicode 123 % `\{ -\immutable\integerdef\barasciicode 124 % `\| -\immutable\integerdef\rightbraceasciicode 125 % `\} -\immutable\integerdef\tildeasciicode 126 % `\~ -\immutable\integerdef\delasciicode 127 - -\aliased\let\percentasciicode\commentasciicode - -%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored -\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space -\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later) -%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line -\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt) -%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space -\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character -\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift -%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character -\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab -%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character -\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts -\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts -\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character -\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character -\catcode\tildeasciicode \activecatcode % `\~ tilde is active -%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid - -\chardef\statuswrite 128 % we need to get rid of this one - -%D First we need to initialization the primitives. Because \CONTEXT\ is already a -%D pretty old macro package, we have a couple of issues with respect to primitives. -%D The \ETEX\ engine added a few as did \PDFTEX. The \LUATEX\ engine added even -%D more. This means that there can be a potential clash between primitives and -%D existing macros. The most noticeable ones are: -%D -%D \starttyping -%D \protected -%D \expanded -%D \unexpanded -%D \stoptyping -%D -%D Because we had macros like that before the primitives showed up. The protection -%D related macros were there before we even knew about extensions to the engine. -%D When the expansion related ones were introduced, we originally came up with -%D different names but due to requests we used the current names, somethng that in -%D retrospect was a bad idea: they should have gotten different names in \LUATEX, if -%D only because at that time only \CONTEXT\ was using them in rolling releases. -%D Anyway, we're now stuck with this situation, and it means that one should use the -%D \type {\normal...} variants in low level code: -%D -%D \starttyping -%D \normalexpanded -%D \normalprotected -%D \normalunexpanded -%D \stoptyping -%D -%D In the end not using different names in \LUATEX\ for these kind of backfires. It -%D makes not much sense to fix this in \LUAMETATEX\ because we're now to long on the -%D road. It is actually the reason why we have the option in \LUATEX\ to alias all -%D primitives in one go using a prefix. Actually this trick could be used to recover -%D a primitive meaning: just enable it with some prefix and \type {\let} the -%D original to that. But \unknown\ we prevent that trick below. -%D -%D The code below differs from \LUATEX: in \LUAMETATEX\ all primitives are already -%D available; it cannot limit itself to being \TEX\ or \ETEX. It could not do that -%D anyway because there are differences (no backend, to mention one). - -\directlua { - local primitives = tex.extraprimitives() % "tex","etex","luatex" - tex.enableprimitives("normal",primitives) % could default to everything - function tex.enableprimitives() end % so we kind of protect what's there -} - -\permanent\def\space{ } -\permanent\def\empty{} - -\permanent\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed -\permanent\letcharcode \tildeasciicode \ % tilde -\permanent\letcharcode \spaceasciicode \space % space - -\permanent\defcsname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab -\permanent\defcsname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed -\permanent\defcsname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return - -%D For now: - -\permanent\def\gobbleoneargument#-{} % will be defined later on anyway - -%D First we define a simplified version of the \CONTEXT\ protection mechanism. Later -%D we will implement a better variant. - -\def\unprotect - {\edef\protect - {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax - \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax - \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax - \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax - \let\protect\relax}% - \catcode\atsignasciicode \lettercatcode - \catcode\exclamationmarkasciicode\lettercatcode - \catcode\questionmarkasciicode \lettercatcode - \catcode\underscoreasciicode \lettercatcode} - -\let\protect\relax - -\unprotect - -%D Some pretty important definitions: - -\immutable\let\bgroup={ -\immutable\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 - -% use \chardef instead for min and max -% -% will be blocked: \newfamily \newlanguage - -\permanent\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change -\permanent\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535 -\permanent\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0 -\permanent\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023 -\permanent\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 -\permanent\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191 -\permanent\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 -\permanent\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 -\permanent\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 -\permanent\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 -\permanent\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private -\permanent\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 -\permanent\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023 - -\permanent\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read -\permanent\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write -\permanent\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register -\permanent\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context -\permanent\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert -\permanent\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context -\permanent\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context - -\permanent\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end -\permanent\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end - -\immutable\integerdef\zerocount = 0 -\immutable\integerdef\plusone = 1 -\immutable\integerdef\minusone = -1 - -\immutable\integerdef\normalpagebox = 255 % hardcoded in pdftex/xetex - -% A few traditional allocations (these might go): - -\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. - -\protected\permanent\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register} -\protected\permanent\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register} -\protected\permanent\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register} -\protected\permanent\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register} -\protected\permanent\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \integerdef\c_syst_max_allocated_register} -\protected\permanent\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register} -\protected\permanent\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \integerdef\c_syst_max_allocated_read} -\protected\permanent\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \integerdef\c_syst_max_allocated_write} -\protected\permanent\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \integerdef\c_syst_max_allocated_register} -\protected\permanent\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert} -\protected\permanent\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\integerdef\c_syst_max_allocated_language} % not needed in context -\protected\permanent\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \integerdef\c_syst_max_allocated_family} % not needed in context - -\aliased\let\newfam\newfamily - -\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might become the default - -% Watch out, for the moment we disable the check for already being defined -% later we will revert this but first all chardefs must be replaced. - -\protected\def\setconstant {} -\protected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax} - -\protected\def\newconstant#1% - {\ifx#1\relax - %\writestatus{!!!!!!!!!!}{\string #1 => RELAX}% - \unletfrozen#1% - \newcount#1% - \orelse\ifdefined#1% - %\writestatus{!!!!!!!!!!}{\string #1 => DEFINED}% - \else - \newcount#1% - \fi} - -\protected\def\setnewconstant#1{\newconstant#1#1} - -% %D The next definitions are really needed (in \CONTEXT): - -\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J} - -%D One reason to start high with allocation is that it permits us to allocate -%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a -%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 - %\protected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}} - \frozen\protected\def\writestatus#1#2{\message{#1: #2}} -\fi - -\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name - {\ifnum#1<#4\relax - \global\advance#1\plusone - \permanent\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 - \orelse\ifx#5\relax - \expandafter\syst_basics_allocate_yes - \else - \expandafter\syst_basics_allocate_nop - \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}. - -% \protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register} -% \protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register} - -%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use -%D the attributes directly but always allocate then first. For instance attribute~0 -%D is reserved for special purposes (this might change). Attributes in the range -%D 128-1023 are private and should not be touched. - -\permanent\integerdef\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone - -% \permanent\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} - -% %D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force -% %D strings instead of tokens that take more memory. -% -% \permanent\protected\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. The private ones are used in cases where we don't want to -%D intrude on normal scratch ones. - -\newcount \scratchcounter \newcount \globalscratchcounter \newcount \privatescratchcounter -\newdimen \scratchdimen \newdimen \globalscratchdimen \newdimen \privatescratchdimen -\newskip \scratchskip \newskip \globalscratchskip \newskip \privatescratchskip -\newmuskip\scratchmuskip \newmuskip\globalscratchmuskip \newmuskip\privatescratchmuskip -\newtoks \scratchtoks \newtoks \globalscratchtoks \newtoks \privatescratchtoks -\newbox \scratchbox \newbox \globalscratchbox \newbox \privatescratchbox - -\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 - -\newcount\globalscratchcounterone -\newcount\globalscratchcountertwo -\newcount\globalscratchcounterthree - -\mutable\let\scratchmacro \relax -\mutable\let\scratchmacroone\relax -\mutable\let\scratchmacrotwo\relax - -%D \macros -%D {tempstring} - -\mutable\let\tempstring\empty - -%D \macros -%D {scratchwidth, scratchheight, scratchdepth, scratchoffset, scratchdistance} -%D -%D A few more scratch dimensions: - -\newdimen\scratchwidth -\newdimen\scratchheight -\newdimen\scratchdepth -\newdimen\scratchtotal - -\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 \immutable\zeroskip 0pt plus 0pt minus 0pt -\newdimen \zeropoint \immutable\zeropoint 0pt -\newdimen \onepoint \immutable\onepoint 1pt -\newdimen \halfapoint \immutable\halfapoint 0.5pt -\newdimen \maxdimen \immutable\maxdimen 16383.99999pt % 1073741823sp -\newcount \maxcount \immutable\maxcount 2147483647 -\newdimen \onebasepoint \immutable\onebasepoint 1bp -\newdimen \scaledpoint \immutable\scaledpoint 1sp -\newdimen \thousandpoint \immutable\thousandpoint 1000pt -\newmuskip\zeromuskip \immutable\zeromuskip 0mu -\newmuskip\onemuskip \immutable\onemuskip 1mu - -\newmuskip\muquad \immutable\muquad 18mu - -\aliased\let\points \onepoint -\aliased\let\halfpoint\halfapoint - -\newtoks \emptytoks - -%D And even more: (todo: countdefs 60+). Watch out, we need a count for a negative constant -%D but can use chardefs for positive ones. Actually, because we have plenty of counters we -%D can also use counts for those. - -%permanent\integerdef\minusone -1 -\permanent\integerdef\minustwo -2 -%permanent\integerdef\zerocount 0 -%permanent\integerdef\plusone 1 -\permanent\integerdef\plustwo 2 -\permanent\integerdef\plusthree 3 -\permanent\integerdef\plusfour 4 -\permanent\integerdef\plusfive 5 -\permanent\integerdef\plussix 6 -\permanent\integerdef\plusseven 7 -\permanent\integerdef\pluseight 8 -\permanent\integerdef\plusnine 9 -\permanent\integerdef\plusten 10 -\permanent\integerdef\pluseleven 11 -\permanent\integerdef\plustwelve 12 -\permanent\integerdef\plussixteen 16 -\permanent\integerdef\plusfifty 50 -\permanent\integerdef\plushundred 100 -\permanent\integerdef\plusonehundred 100 -\permanent\integerdef\plustwohundred 200 -\permanent\integerdef\plusfivehundred 500 -\permanent\integerdef\pluscxxvii 127 -\permanent\integerdef\pluscxxviii 128 -\permanent\integerdef\pluscclv 255 -\permanent\integerdef\pluscclvi 256 -\permanent\integerdef\plusthousand 1000 -\permanent\integerdef\plustenthousand 10000 -\permanent\integerdef\plustwentythousand 20000 -\permanent\integerdef\medcard 32768 -\permanent\integerdef\maxcard 65536 % pdftex has less mathchars -\permanent\integerdef\maxcardminusone 65535 - -%D \macros -%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded} -%D -%D A few handy shortcuts - -\permanent\let\singleexpandafter \expandafter -\permanent\def\doubleexpandafter{\expandafter\expandafter\expandafter} -\permanent\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter} - -%D We prefer the more readable variant than in plain \TEX. User should only -%D use \type {\emptybox}: - -\newbox\voidbox % public - -\permanent\def\unvoidbox{\unhbox\voidbox} -\permanent\def\emptybox {\box \voidbox} % used in initializations so no attributes -\permanent\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes -\permanent\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes - -\aliased\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode - -%D \macros -%D {dontcomplain} -%D -%D We need this one soon: - -\permanent\protected\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. - -\aliased\let\p@ \onepoint -\aliased\let\m@ne \minusone -\aliased\let\z@ \zeropoint -\aliased\let\@ne \plusone -\aliased\let\tw@ \plustwo -\aliased\let\thr@@ \plusthree -\aliased\let\sixt@@n\plussixteen -\aliased\let\@cclv \pluscclv -\aliased\let\@cclvi \pluscclvi -\aliased\let\voidb@x\voidbox - -\newtoks \toks@ %scratchtoks - -%D We define \type {\newif} a la plain \TEX, but will redefine it later. As Knuth -%D says: -%D -%D \startnarrower -%D And here's a different sort of allocation: for example, -%D -%D \starttyping -%D \newif\iffoo -%D \stoptyping -%D -%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}. -%D \stopnarrower - -% \protected\def\newif#1% -% {\count@\escapechar -% \escapechar\minusone -% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }% -% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}% -% \new_if#1{false}% the condition starts out false -% \escapechar\count@} -% -% \def\new_if#1#2% -% {\csname\expandafter\if@\string#1#2\endcsname} -% -% \bgroup % `if' is required -% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}} -% \egroup - -% We use \csstring so there is no need to push/pop escapechar. -% We use different names so that we get a better error message. -% -% \protected\def\newif#1% -% {\let\new_if_saved\newif -% \let\newif\new_if_check -% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }% -% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}% -% \new_if_cs#1{false}% -% \let\newif\new_if_saved} -% -% \protected\def\new_if_cs#1#2% -% {\csname\expandafter\newif\csstring#1#2\endcsname} -% -% We wrap all into one macro (the frozen stuff adds 10% runtime): - -\permanent\protected\def\newif#1% - {\permanent\protected\global\defcsname\expandafter\new_if_check\csstring#1true\endcsname {\overloaded\frozen\let#1\iftrue }% - \permanent\protected\global\defcsname\expandafter\new_if_check\csstring#1false\endcsname{\overloaded\frozen\let#1\iffalse}% - \csname\expandafter\new_if_check\csstring#1false\endcsname} - -\normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}} - -%D Let's test this one: - -\newif\ifdone -\newif\iffound - -\newif\ifscratchcondition -\newif\ifscratchconditionone -\newif\ifscratchconditiontwo - -\let\htdp\boxtotal - -%D A few shortcuts: - -\permanent\protected\def\udef {\protected\def } -\permanent\protected\def\ugdef{\protected\gdef} -\permanent\protected\def\uedef{\protected\edef} -\permanent\protected\def\uxdef{\protected\xdef} - -%D For a while we keep the following, as systems like tikz need it. Best -%D not use that one \CONTEXT. - -\aliased\let\active\activecatcode - -%D Constants to be used with \type {\interactionmode}. - -\permanent\integerdef\batchmodecode \zerocount -\permanent\integerdef\nonstopmodecode \plusone -\permanent\integerdef\scrollmodecode \plustwo -\permanent\integerdef\errorstopmodecode \plusthree - -%D Of course we want even bigger log files, so we copied this from the \ETEX\ -%D source files. -%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 - -\permanent\protected\def\tracingall - {\tracingonline \plusone - \tracingcommands \plusthree - \tracingmacros \plustwo - \tracingoutput \plusone - \tracingpages \plusone - \tracingparagraphs\plusone - \tracingrestores \plusone - \tracinggroups \plusone - \tracingifs \plusone - \tracingnesting \plustwo - \tracingassigns \plustwo - \tracingmath \plusone - \tracingalignments\plusone - \showboxbreadth \maxcount - \showboxdepth \maxcount} - -\permanent\protected\def\loggingall - {\tracingall - \tracingonline \zerocount} - -\permanent\protected\def\tracingnone - {\showboxdepth \plusthree - \showboxbreadth \plusfive - \tracingalignments\zerocount - \tracingmath \zerocount - \tracingassigns \zerocount - \tracingnesting \zerocount - \tracingifs \zerocount - \tracinggroups \zerocount - \tracingrestores \zerocount - \tracingparagraphs\zerocount - \tracingpages \zerocount - \tracingoutput \zerocount - \tracingmacros \zerocount - \tracingcommands \zerocount - \tracingonline \zerocount} - -%D When we want to see a box we can as well show all of it. - -\showboxdepth \maxdimen -\showboxbreadth\maxdimen - -%D Just for tracing purposes we set: - -\tracingstats\plusone - -%D This is only used when we load \CONTEXT: - -\permanent\def\pushoverloadmode - {\edef\popoverloadmode{\overloadmode\the\overloadmode}% - \overloadmode\zerocount} - -\newtoks\everydump - -\pushoverloadmode - -\protected\def\dump - {\the\everydump - \global\everydump\emptytoks - \pushoverloadmode - \glet\dump\relax - \popoverloadmode - %let\pushoverloadmode\relax - %let\popoverloadmode\relax -% \tracingall - \normaldump} - -\permanent\protected\def\input - {\normalinput} - -\popoverloadmode - -%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: - -\aliased\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef -\aliased\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef - -% \permanent\protected\def\settrue #1{\integerdef#1\conditionaltrue } -% \permanent\protected\def\setfalse#1{\integerdef#1\conditionalfalse} -% -% \permanent\protected\def\settruevalue #1{\expandafter\integerdef\csname#1\endcsname\conditionaltrue } -% \permanent\protected\def\setfalsevalue#1{\expandafter\integerdef\csname#1\endcsname\conditionalfalse} - -\permanent\protected\def\settrue #1{\enforced\let#1\conditionaltrue } -\permanent\protected\def\setfalse #1{\enforced\let#1\conditionalfalse} -\permanent\protected\def\setconditional#1{\enforced\let#1} - -\permanent\protected\def\settruevalue #1{\enforced\letcsname#1\endcsname\conditionaltrue } -\permanent\protected\def\setfalsevalue#1{\enforced\letcsname#1\endcsname\conditionalfalse} - - -\aliased\let\newconditional\setfalse -\aliased\let\ifconditional \ifcase - -\aliased\let\then\relax % so that we can say: \ifnum1>2\then -) - -\permanent\def\truecondition {\iftrue} -\permanent\def\falsecondition{\iffalse} - -% This one has to be unprotected otherwise we get a files-ends-to-soon but it's ok -% as conditions expand anyway. - -\permanent\def\quitcondition{\orelse\iffalse} - -%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. - -\permanent\protected\def\newmacro #1{\let#1\empty} -\permanent\protected\def\setnewmacro#1{\let#1} - -\permanent\protected\def\newfraction#1{\let#1\!!plusone} - -\def\!!zerocount{0} % later redefined -\def\!!plusone {1} % later redefined - -%D It would be handy to have a primitive \type {\unless\ifcase} because then we -%D could use nicer values. Anyhow, this conditional code used to be in the \type -%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 - -\aliased\let\ifzeropt\ifcase - -% these token list helpers might move to syst-aux.mkiv -% -% we assume a \cs. not toks0 or so -% -% \protected\def\appendtotoks #1#{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=} -% \protected\def\prependtotoks#1#{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=} - -\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp - -\permanent\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=} -\permanent\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=} - -% \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}} -% \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}} - -\permanent\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=} -\permanent\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=} - -\def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}} -\def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}} - -\def\syst_toks_append_g {\global\syst_toks_append_l } -\def\syst_toks_prepend_g{\global\syst_toks_prepend_l} - -\permanent\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next} -\permanent\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next} - -\def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp} -\def\syst_toks_add_g{\global\syst_toks_add_l} - -\permanent\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes -\permanent\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes - -%D \macros -%D {begcsname} -%D -%D Handy for \ETEX-only usage (avoids making \type {\relax}'s: - -% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi} - -\aliased\let\begcsname\begincsname - -%D Now come a few macros that might be needed in successive loading. We redefine the -%D \type {\par} primitive pretty soon so that we get the equivalents right. - -% too tricky: \par is use more often than a par starts so we have too much change -% that we get assymetrical behaviour -% -% \newtoks\everyendpar -% -% \protected\def\endpar{\the\everyendpar\normalpar} -% \protected\def\par {\endpar} -% -% \protected\def\reseteverypar -% {\everypar \emptytoks -% \everyendpar\emptytoks} - -\permanent\protected\def\reseteverypar - {\everypar\emptytoks} - -\aliased\let\endgraf\par % plain, a kind of funny name -%aliased\let\endline\cr % plain, not needed and probably also confusing - -\permanent\protected\def\null{\hpack{}} - -%D The following two might be overloaded later on but some modules need then -%D earlier. These functionality is reflected in the name and will not change. - -% \bgroup -% \catcode`\^^M=\activecatcode% -% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}% -% \glet^^M\par% -% \egroup -% -% \bgroup -% \gdef\obeyspaces{\catcode`\ \activecatcode}% -% \obeyspaces\glet =\space% -% \egroup - -\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par } % check if these can be \permanent -\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} % check if these can be \permanent - -% %D A constant: -% -% \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}. - -\permanent\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go - -%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type -%D {\repeat} skippable (clever trick): - -\permanent\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: - -\permanent\countdef\pageno\zerocount \pageno\plusone % first page is number 1 - -%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides -%D the value. - -\permanent\def\folio{\the\pageno} % kind of expected and therefore reserved - -%D The following registers are kind of standard and (for the moment) we define -%D them here. This might change. - -\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 Sometimes kerns make more sense than glue but we need to be in the -%D right mode: - -\permanent\protected\def\vkern {\ifhmode\par \fi\kern} -\permanent\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} - -\permanent\protected\def\vpenalty{\ifhmode\par \fi\penalty} -\permanent\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} - -%D Again a few kind-of-extensions the core. These come from plain \TEX\ but -%D are probably not used in \CONTEXT. - -\newskip \hideskip \hideskip = -1000pt plus 1fill -\newskip \centering \centering = 0pt plus 1000pt minus 1000pt - -\permanent\def\hidewidth % for alignment entries that can stick out - {\hskip\hideskip} - -\permanent\def\ialign % initialized \halign - {\everycr\emptytoks - \tabskip\zeroskip - \halign} - -\newcount \mscount - -\permanent\def\spanomit{\span\omit} % bypass error message - -\permanent\def\multispan#1% - {\omit - \mscount#1\relax - \loop - \ifnum\mscount>\plusone - \spanomit \advance\mscount\minusone - \repeat} - -\let\nopdfcompression \relax % later -\let\onlypdfobjectcompression\relax % later -\let\maximumpdfcompression \relax % later -\let\normalpdfcompression \relax % later - -%D Basic status stuff. - -% \newif\ifproductionrun % already defined - -%D For those who expect this \unknown - -\ifx\fmtname \undefined \immutable\def\fmtname {ConTeXt Initial TeX} \fi -\ifx\fmtversion\undefined \immutable\def\fmtversion{3.1415926} \fi - -%D A few bonus macros: - -%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} -\permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} -\permanent\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax} - -%D These could be set at the \LUA\ end instead: - -\immutable\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}} -\immutable\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}} -\immutable\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}} - -%D We have no reason not to enable this: - -\savingvdiscards\plusone - -%D We only can set this one via directives (system.synctex) and we only support -%D the context variant. This will go away completely. - -\newcount\synctex % \let\normalsynctex\synctex - -%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero. - -% \voffset\zeropoint \overloaded\let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset -% \hoffset\zeropoint \overloaded\let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset - -\matheqnogapstep\zerocount % for now - -%D Now we define a few helpers that we need in a very early stage. We have no -%D message system yet but redundant definitions are fatal anyway. - -\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes - -\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>} -%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet - -\protected\def\installsystemnamespace#1% will be redefined - {\ifcsname ??#1\endcsname - \immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}% - \else - \global\advance\c_syst_helpers_n_of_namespaces\plusone - \immutable\edefcsname ??#1\endcsname{\v_interfaces_prefix_template_system}% - \fi} - -%D It makes more sense to have these here: - -\aliased\let\normalsuperscript \Usuperscript -\aliased\let\normalsubscript \Usubscript -\aliased\let\normalnosuperscript\Unosuperscript -\aliased\let\normalnosubscript \Unosubscript -\aliased\let\normalstartimath \Ustartmath -\aliased\let\normalstopimath \Ustopmath -\aliased\let\normalstartdmath \Ustartdisplaymath -\aliased\let\normalstopdmath \Ustopdisplaymath - -%D Also better here: - -\immutable\def\wildcardsymbol{*} - -%D For a while we will keep these useless numbers as for instance tikz checks for them: - -\immutable\integerdef\eTeXversion 2 -\immutable\def \eTeXrevision {2} - -%D Experiment: - -\glyphdimensionsmode\plusone - -%D Just in case users use this: - -\aliased\let\immediateassign \immediate -\aliased\let\immediateassigned\localcontrolled - -%D Needed: - -\mutable\let\nexttoken \relax -\mutable\let\next \relax -\mutable\let\nextnext \relax -\mutable\let\nextnextnext\relax - -%D For now here: will get a proper solution - -\pushoverloadmode -\mutable\let\par\par -\popoverloadmode - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-lua.lmt b/tex/context/base/mkiv/syst-lua.lmt deleted file mode 100644 index 673c99ae3..000000000 --- a/tex/context/base/mkiv/syst-lua.lmt +++ /dev/null @@ -1,434 +0,0 @@ -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 load, type, tonumber = load, type, tonumber -local find, gsub = string.find, string.gsub -local concat = table.concat -local utfchar = utf.char -local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat - -local xmath = xmath or math -local xcomplex = xcomplex or { } - -local scan_next = token.scan_next or token.get_next -local scan_cmdchr = token.scan_cmdchr_expanded -local scan_token = token.scan_token - -local get_csname = token.get_csname ------ get_macro = token.get_macro ------ put_next = token.put_next - -local cmd = tokens.commands -local letter_code = cmd.letter -local other_char_code = cmd.other_char -local spacer_code = cmd.spacer -local other_char_code = cmd.other_char -local relax_code = cmd.relax -local register_int_code = cmd.register_int -local internal_int_code = cmd.internal_int -local register_dimen_code = cmd.register_dimen -local internal_dimen_code = cmd.internal_dimen -local register_glue_code = cmd.register_glue -local internal_glue_code = cmd.internal_glue -local register_toks_code = cmd.register_toks -local internal_toks_code = cmd.internal_toks -local char_given_code = cmd.char_given -local math_given_code = cmd.math_given -local xmath_given_code = cmd.xmath_given -local some_item_code = cmd.some_item - -local getdimen = tex.getdimen -local getglue = tex.getglue -local getcount = tex.getcount -local gettoks = tex.gettoks -local gettex = tex.get - -local context = context -commands = commands or { } -local commands = commands -local context = context -local implement = interfaces.implement -local dimenfactors = number.dimenfactors - -local ctx_protected_cs = context.protected.cs -- more efficient -local ctx_firstoftwoarguments = context.firstoftwoarguments -local ctx_secondoftwoarguments = context.secondoftwoarguments -local ctx_firstofoneargument = context.firstofoneargument -local ctx_gobbleoneargument = context.gobbleoneargument - -implement { -- will be overloaded later - name = "writestatus", - arguments = "2 strings", - actions = logs.status, -} - -function commands.doifelse(b) - if b then - ctx_firstoftwoarguments() - else - ctx_secondoftwoarguments() - end -end - -function commands.doifelsesomething(b) - if b and b ~= "" then - ctx_firstoftwoarguments() - else - ctx_secondoftwoarguments() - end -end - -function commands.doif(b) - if b then - ctx_firstofoneargument() - else - ctx_gobbleoneargument() - end -end - -function commands.doifsomething(b) - if b and b ~= "" then - ctx_firstofoneargument() - else - ctx_gobbleoneargument() - end -end - -function commands.doifnot(b) - if b then - ctx_gobbleoneargument() - else - ctx_firstofoneargument() - end -end - -function commands.doifnotthing(b) - if b and b ~= "" then - ctx_gobbleoneargument() - else - ctx_firstofoneargument() - 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, - public = true, -} - -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 = "2 strings", - actions = function(a,b) - if a == b then - ctx_firstoftwoarguments() - else - ctx_secondoftwoarguments() - end - end -} - -implement { - name = "doifsame", - arguments = "2 strings", - actions = function(a,b) - if a == b then - ctx_firstofoneargument() - else - ctx_gobbleoneargument() - end - end -} - -implement { - name = "doifnotsame", - arguments = "2 strings", - actions = function(a,b) - if a == b then - ctx_gobbleoneargument() - else - ctx_firstofoneargument() - end - end -} - --- This is a bit of a joke as I never really needed floating point expressions (okay, --- maybe only with scaling because there one can get numbers that are too large for --- dimensions to deal with). Of course one can write a parser in \TEX\ speak but then --- one also needs to implement a bunch of functions. It doesn't pay of so we just --- stick to the next gimmick. It looks inefficient but performance is actually quite --- efficient. - -do - - local result = { "return " } - local word = { } - local r = 1 - local w = 0 - - local report = logs.reporter("system","expression") - - local function unexpected(c) - report("unexpected token %a",c) - end - - local function unexpected(c) - report("unexpected token %a",c) - end - - local function expression() - local w = 0 - local r = 1 - while true do - local n, i = scan_cmdchr() - if n == letter_code then - w = w + 1 ; word[w] = utfchar(i) - else - if w > 0 then - -- we could use a metatable for all math, complex and factors - local s = concat(word,"",1,w) - local d = dimenfactors[s] - if d then - r = r + 1 ; result[r] = "*" - r = r + 1 ; result[r] = 1/d - else - if xmath[s] then - r = r + 1 ; result[r] = "xmath." - elseif xcomplex[s] then - r = r + 1 ; result[r] = "xcomplex." - end - r = r + 1 ; result[r] = s - end - w = 0 - end - if n == other_char_code then - r = r + 1 ; result[r] = utfchar(i) - elseif n == spacer_code then - -- r = r + 1 ; result[r] = " " - elseif n == relax_code then - break - elseif n == register_int_code or n == internal_int_code then - r = r + 1 ; result[r] = getcount(i) - elseif n == register_dimen_code or n == internal_dimen_code then - r = r + 1 ; result[r] = getdimen(i) - elseif n == register_glue_code or n == n == register_dimen_code_glue_code then - r = r + 1 ; result[r] = getglue(i) - elseif n == register_toks_code or n == n == register_dimen_code_toks_code then - r = r + 1 ; result[r] = gettoks(i) - elseif n == char_given_code or n == math_given_code or n == xmath_given_code then - r = r + 1 ; result[r] = i - elseif n == some_item_code then - local n = get_csname(t) - if n then - local s = gettex(n) - if s then - r = r + 1 ; result[r] = s - else - unexpected(c) - end - else - unexpected(c) - end - -- elseif n == call_code then - -- local n = get_csname(t) - -- if n then - -- local s = get_macro(n) - -- if s then - -- r = r + 1 ; result[r] = s - -- else - -- unexpected(c) - -- end - -- else - -- unexpected(c) - -- end - -- elseif n == the_code or n == convert_code or n == lua_expandable_call_code then - -- put_next(t) - -- scan_token() -- expands - else - unexpected(c) - end - end - end - local code = concat(result,"",1,r) - local func = load(code) - if type(func) == "function" then - context(func()) - else - report("invalid lua %a",code) - end - end - - implement { - public = true, - name = "expression", - actions = expression, - } - -end - -do - - -- This is some 20% slower than native but we only provide this for compatibility - -- reasons so we don't care that much about it. Eventually we can drop the - -- built-in method. - - local channels = { } - - local findbinfile = resolvers.findbinfile - local loadbinfile = resolvers.loadbinfile - local opentexfile = resolvers.opentexfile - - local scaninteger = tokens.scanners.integer - local scankeyword = tokens.scanners.keyword - local scanstring = tokens.scanners.string - local scancsname = tokens.scanners.csname - - local setmacro = tokens.setters.macro - local vrbcatcodes = tex.vrbcatcodes - - implement { - name = "openin", - public = true, - usage = "value", - actions = function() - local n = scaninteger() - scankeyword("=") - local s = scanstring(true) - local c = channels[n] - if c then - c:close() - end - local f = findbinfile(s,"tex") - if f then - channels[n] = opentexfile(f) - else - channels[n] = false - end - end, - } - - implement { - name = "closein", - public = true, - usage = "value", - actions = function() - local n = scaninteger() - local c = channels[n] - if c then - c:close() - end - channels[n] = false - end, - } - - implement { - name = "read", - public = true, - usage = "value", - actions = function(prefix) - local n = scaninteger() - scankeyword("to") - local m = scancsname(true) - local c = channels[n] - local s = c and c:reader() - if s then - s = gsub(s," *$"," ") -- or just "", no need to fake tex here - else - channels[n] = false - -- s = "\\par" - s = "" -- no need to fake tex here - end - setmacro(m, s, prefix) -- checks for frozen - end, - } - - implement { - name = "readline", - public = true, - usage = "value", - actions = function(prefix) - local n = scaninteger() - scankeyword("to") - local m = scancsname(true) - local c = channels[n] - local s = c and c:reader() - if s then - -- should we strip spaces at the end? - else - channels[n] = false - s = "" - end - setmacro(vrbcatcodes, m, s, prefix) -- checks for frozen - end, - } - - local boolean_value = tokens.values.boolean - - implement { - name = "ifeof", - public = true, - usage = "condition", - actions = function() - local n = scaninteger() - return boolean_value, not channels[n] - end, - } - - -- for the moment here: - - local getnest = tex.getnest - - implement { - name = "ifmvl", - public = true, - usage = "condition", - actions = function() - return boolean_value, getnest("ptr") == 0 - end, - } - -end diff --git a/tex/context/base/mkiv/syst-lua.mkxl b/tex/context/base/mkiv/syst-lua.mkxl deleted file mode 100644 index 615562200..000000000 --- a/tex/context/base/mkiv/syst-lua.mkxl +++ /dev/null @@ -1,100 +0,0 @@ -%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}{autosuffix} - -\unprotect - -\permanent\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}} -\permanent\def\expdoif #1#2{\clf_doifsame {#1}{#2}} -\permanent\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} - -%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road -%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type -%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see -%D other useful applications. - -\permanent\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} -\permanent\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} -\permanent\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} - -% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3 -% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5 - -\permanent\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} -\permanent\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}} - -\aliased\let\expdoifcommonelse\expdoifelsecommon -\aliased\let\expdoifinsetelse \expdoifelseinset - -%D We define these here, just in case. This permits \typefile {self} otherwise -%D nested b|/|e sep problems. - -\immutable\def\luastringsep{===} - -\immutable\edef\!!bs{[\luastringsep[} -\immutable\edef\!!es{]\luastringsep]} - -\permanent\overloaded\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}} - -%D We can omit the tex.ctxcatcodes here as nowadays we seldom change the regime at -%D the \TEX\ end: - -%def\luaexpr#1{\ctxlua{context (tostring(#1))}} % more efficient: -\permanent\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled - -%D But as we only use write 16 we could as well do all in \LUA\ and ignore the rest. -%D Okay, we still can do writes here but only when not blocked. - -\aliased\let\syst_write_execute\clf_execute % always {...} - -%D There is a probably rather useless \type {\expression} command that can mix \LUA\ numeric -%D expressions with \TEX\ commands (for as far that makes sense) that works like this: -%D -%D \starttyping -%D \mathchardef\foooo 1234 -%D \def \mymacro {123.45} -%D \scratchdimen 123pt -%D \scratchskip 123pt -%D \scratchtoks {34} -%D -%D \testfeatureonce{10000}{\edef\foo{\expression -%D round( -%D 12.3 * \scratchdimen -%D - (12.3 * \scratchskip) / 2 -%D + 2 ^ 3 -%D * ( -%D - sqrt(12) -%D - 10pt -%D - \foooo -%D + \luatexversion -%D - \mymacro -%D + \scratchtoks -%D + \the\scratchcounter -%D + \number\scratchcounter -%D ) -%D ) -%D \relax}} -%D -%D \expression string.format("\letterpercent f",\elapsedtime/50000) \relax -%D \stoptyping -%D -%D The final \type {\relax} is mandate because we also accept spaces. Of course we -%D could have avoided it by using outer parenthesis but this is cleaner anyway. -%D -%D The \LMTX\ version supports te \type {xmath} and \type {xcomplex} functions and -%D therefore one can have expressions that don't work in \MKIV. - -% maybe: \let\texexpr\expression - -\protect \endinput diff --git a/tex/context/base/mkiv/syst-mac.lmt b/tex/context/base/mkiv/syst-mac.lmt deleted file mode 100644 index 410a49f8b..000000000 --- a/tex/context/base/mkiv/syst-mac.lmt +++ /dev/null @@ -1,117 +0,0 @@ -if not modules then modules = { } end modules ['syst-mac'] = { - 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" -} - --- This is kind of tricky and might not work for all csnames but as long as we use --- it in a controlled way, we're okay. The engine implementation might be changed --- a bit (no need to go through strings, but fetching a cs index and passing that --- back also takes time). - --- Another approach is to have the predefined stack operate use private stacks and --- then the pop doesn't need the cs. But ... we then also need to store stuff in --- the format so that complicates maters more than I'm willing to do. - -local insert, remove = table.insert, table.remove - -local push_macro = token.push_macro -local pop_macro = token.pop_macro -local scan_csname = token.scan_csname -local create_token = token.create -local gobble_token = token.gobble - -local context = context -local implement = interfaces.implement - -local report = logs.reporter("system","macrostack") - -local stack = table.setmetatableindex("table") - -local function pushmacro(name,global) - local s = push_macro(name,global) - if s then - insert(stack[name],s) - else - report("no macro %a to push",name) - insert(stack[name],false) - end -end - -local function popmacro(name) - local s = remove(stack[name]) - if s then - pop_macro(s) - else - report("no macro %a to pop",name) - end -end - -tokens.pushmacro = pushmacro -tokens.popmacro = popmacro - -implement { - name = "localpushmacro", - public = true, - protected = true, - actions = function() - pushmacro(scan_csname()) - end -} - -implement { - name = "globalpushmacro", - public = true, - protected = true, - actions = function() - pushmacro(scan_csname(),true) - end -} - -implement { - name = "localpopmacro", - public = true, - protected = true, - actions = function() - popmacro(scan_csname()) - end -} - -implement { - name = "globalpopmacro", - public = true, - protected = true, - actions = function() - popmacro(scan_csname()) - end -} - -implement { - name = "showmacrostack", - public = true, - protected = true, - actions = function() - local n = scan_csname() - local s = stack[n] - local m = #s - report("%s : %i stack slots used",n,m) - for i=1,m do - report("% 3i %S",i,s[i]) - end - end -} - -implement { - name = "gobblenested", - public = true, - protected = true, - arguments = "3 strings", - actions = function(start,stop,command) - gobble_token(create_token(start),create_token(stop)) - if command then - context[command]() - end - end -} diff --git a/tex/context/base/mkiv/tabl-com.mkxl b/tex/context/base/mkiv/tabl-com.mkxl deleted file mode 100644 index 791db656b..000000000 --- a/tex/context/base/mkiv/tabl-com.mkxl +++ /dev/null @@ -1,92 +0,0 @@ -%D \module -%D [ file=tabl-com, -%D version=2009.08.22, -%D title=\CONTEXT\ Table Macros, -%D subtitle=Common Code, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Table Macros / Common Code} - -\unprotect - -\pushoverloadmode - -% maybe frozen instead - -\permanent\let\AR\relax -\permanent\let\BA\relax -\permanent\let\BC\relax -\permanent\let\BH\relax -\permanent\let\BL\relax -\permanent\let\BR\relax -\permanent\let\CC\relax -\permanent\let\CL\relax -\permanent\let\CM\relax -\permanent\let\CR\relax -\permanent\let\DB\relax -\permanent\let\DC\relax -\permanent\let\DL\relax -\permanent\let\DR\relax -\permanent\let\DV\relax -\permanent\let\EH\relax -\permanent\let\EQ\relax -\permanent\let\ER\relax -\permanent\let\FB\relax -\permanent\let\FL\relax -\permanent\let\FR\relax -\permanent\let\HC\relax -\permanent\let\HL\relax -\permanent\let\HQ\relax -\permanent\let\HR\relax -\permanent\let\LB\relax -\permanent\let\LC\relax -\permanent\let\LT\relax -\permanent\let\LL\relax -\permanent\let\LR\relax -\permanent\let\MC\relax -\permanent\let\ML\relax -\permanent\let\MR\relax -\permanent\let\NA\relax -\permanent\let\NB\relax -\permanent\let\NC\relax -\permanent\let\ND\relax -\permanent\let\NF\relax -\permanent\let\NG\relax -\permanent\let\NI\relax -\permanent\let\NL\relax -\permanent\let\NN\relax -\permanent\let\NP\relax -\permanent\let\NR\relax -\permanent\let\PB\relax -\permanent\let\RC\relax -\permanent\let\RQ\relax -\permanent\let\SL\relax -\permanent\let\SM\relax -\permanent\let\SR\relax -\permanent\let\TB\relax -\permanent\let\TL\relax -\permanent\let\TR\relax -\permanent\let\VL\relax -\permanent\let\VC\relax -\permanent\let\VD\relax -\permanent\let\VN\relax -\permanent\let\VS\relax -\permanent\let\VT\relax -\permanent\let\XC\relax - -\popoverloadmode - -\installmacrostack\BC -\installmacrostack\EC -\installmacrostack\EQ -\installmacrostack\NC -\installmacrostack\NN -\installmacrostack\NR - -\protect \endinput diff --git a/tex/context/base/mkiv/tabl-frm.mkxl b/tex/context/base/mkiv/tabl-frm.mkxl deleted file mode 100644 index 9bbc510c5..000000000 --- a/tex/context/base/mkiv/tabl-frm.mkxl +++ /dev/null @@ -1,261 +0,0 @@ -%D \module -%D [ file=tabl-frm, -%D version=2017.04.11, -%D title=\CONTEXT\ Table Macros, -%D subtitle=Framed Tables, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D For Thomas Schmitz who needed 3000 pages long tables. - -\unprotect - -\writestatus{loading}{ConTeXt Table Macros / Framed Tables} - -\installcorenamespace{framedtable} -\installcorenamespace{framedtablerow} -\installcorenamespace{framedtablecolumn} - -\newcount\c_tabl_framed_c -\newcount\c_tabl_framed_r -\newdimen\d_tabl_framed_h -\newdimen\d_tabl_framed_d -\newdimen\b_tabl_framed - -\initializeboxstack\??framedtable - -\defineframed[\??framedtable] -\defineframed[\??framedtablerow][\??framedtable] -\defineframed[\??framedtablecolumn][\??framedtable] - -\setupframed - [\??framedtable] - [\c!distance=\zeropoint, - \c!before=, - \c!after=, - \c!inbetween=] - -\setupframed - [\??framedtablerow] - [\c!strut=\v!no, - \c!offset=\v!overlay] - -% \defineframedtable[foo] -% \defineframedtable[bar][foo] - -\permanent\tolerant\protected\def\defineframedtable[#1]#*[#2]% - {\ifarguments\or - \defineframed[\??framedtable#1][\??framedtable]% - \or - \defineframed[\??framedtable#1][\??framedtable#2]% - \fi} - -% \setupframedtable[foo][...] - -\permanent\tolerant\protected\def\setupframedtable[#1]#*[#2]% - {\ifarguments\or - \setupframed[\??framedtable][#1]% - \or - \ifcsname\??framed:\??framedtable#1\endcsname \else - \defineframed[\??framedtable#1][\??framedtable]% - \fi - \setupframed[\??framedtable#1][#2]% - \fi} - -% \setupframedtable[1][...] -% \setupframedtable[foo][1][...] - -\permanent\tolerant\protected\def\setupframedtablerow[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \ifcsname\??framed:\??framedtablerow:#1\endcsname \else - \defineframed[\??framedtablerow:#1][\??framedtable]% - \fi - \setupframed[\??framedtablerow:#1][#2]% - \or - \ifcsname\??framed:\??framedtable#1\endcsname \else - \defineframed[\??framedtable#1][\??framedtable]% - \fi - \ifcsname\??framed:\??framedtablerow#1:#2\endcsname \else - \defineframed[\??framedtablerow#1:#2][\??framedtable#1]% - \fi - \setupframed[\??framedtablerow#1:#2][#3]% - \fi} - -\permanent\tolerant\protected\def\setupframedtablecolumn[#1]#*[#2]#*[#3]% - {\ifarguments\or\or - \ifcsname\??framed:\??framedtablecolumn:#1\endcsname \else - \defineframed[\??framedtablecolumn:#1][\??framedtable]% - \fi - \setupframed[\??framedtablecolumn:#1][#2]% - \or - \ifcsname\??framed:\??framedtable#1\endcsname \else - \defineframed[\??framedtable#1][\??framedtable]% - \fi - \ifcsname\??framed:\??framedtablecolumn#1:#2\endcsname \else - \defineframed[\??framedtablecolumn#1:#2][\??framedtable#1]% - \fi - \setupframed[\??framedtablecolumn#1:#2][#3]% - \fi} - -\permanent\tolerant\protected\def\startframedtable[#1]#*[#2]% - {\begingroup - \forgetall - \ifhastok={#1}% - \let\currentframedtable\empty - \setupframed[\??framedtable][#1]% - \else - \edef\currentframedtable{#1}% - \setupframed[\??framedtable][#2]% - \fi - \edef\currentframed{\??framedtable\currentframedtable}% - \c_tabl_framed_r\zerocount - \d_tabl_framed_d\framedparameter\c!distance - \framedparameter\c!before} - -\permanent\protected\def\stopframedtable - {\framedparameter\c!after - \endgroup} - -% a two pass variant that deals with the height .. so no catcode changes here - -\tolerant\protected\def\pack_framed_start_framed_whatever[#1]% - {\pack_framed_initialize - \bgroup - \setupcurrentframed[#1]% here ! - \pack_framed_process_indeed - \bgroup - \ignorespaces} - -% \permanent\protected\def\startframedrow -% {\advance\c_tabl_framed_r\plusone -% \c_tabl_framed_c\zerocount -% \d_tabl_framed_h\zeropoint -% \bgroup -% \edef\currentframed{\number\c_tabl_framed_r}% -% \edef\currentframed -% {\??framedtablerow\currentframedtable -% \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname -% :\currentframed -% \orelse\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname -% :\v!each -% \fi}% -% \pack_framed_start_framed_whatever} -% -% \permanent\protected\def\stopframedrow -% {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row -% \stopframed -% \nointerlineskip -% \vskip\zeropoint\relax -% \framedparameter\c!inbetween} - -\protected\def\tabl_framed_flush_row - {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% - \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} - -\newcount\c_tabl_framed_pass - -\permanent\let\stopframedrow\relax - -\permanent\protected\def\startframedrow#1\stopframedrow - {\advance\c_tabl_framed_r\plusone - \startframedrow_one#1\stopframedrow_one - \startframedrow_two#1\stopframedrow_two} - -\tolerant\def\startframedrow_one[#-]% - {\bgroup - \c_tabl_framed_pass\plusone - \c_tabl_framed_c\zerocount - \d_tabl_framed_h\zeropoint - \settrialtypesetting} - -\protected\def\stopframedrow_one - {\normalexpanded{\egroup\d_tabl_framed_h\the\d_tabl_framed_h\relax}} - -\def\startframedrow_two - {\bgroup - \c_tabl_framed_c\zerocount - \c_tabl_framed_pass\plustwo - \edef\currentframed{\number\c_tabl_framed_r}% - \edef\currentframed - {\??framedtablerow\currentframedtable - \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname - :\currentframed - \orelse\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname - :\v!each - \fi}% - \pack_framed_start_framed_whatever} - -\protected\def\stopframedrow_two - {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row - \stopframed - \nointerlineskip - \vskip\zeropoint\relax - \framedparameter\c!inbetween} - -\protected\def\tabl_framed_flush_row_two - {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% - \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} - -\permanent\protected\def\startframedcell - {\advance\c_tabl_framed_c\plusone - \setbox\b_tabl_framed\hpack\bgroup - %\bgroup - \edef\currentframed{\number\c_tabl_framed_c}% - \edef\currentframed - {\??framedtablecolumn\currentframedtable - \ifcsname\??framedtablecolumn\currentframedtable:\currentframed\endcsname - :\currentframed - \orelse\ifcsname\??framedtablecolumn\currentframedtable:\v!each\endcsname - :\v!each - \fi}% - \ifcase\c_tabl_framed_pass - \or - \letframedparameter\c!background\empty - \letframedparameter\c!frame\v!off - \or - \letframedparameter\c!height\d_tabl_framed_h - \fi - \pack_framed_start_framed_whatever} - -\permanent\protected\def\stopframedcell - {\stopframed - %\egroup - \ifcase\c_tabl_framed_pass - \or - \ifdim\ht\b_tabl_framed>\d_tabl_framed_h - \d_tabl_framed_h\ht\b_tabl_framed - \fi - \else - \savebox\??framedtable{\number\c_tabl_framed_c}{\box\b_tabl_framed}% - \fi} - -\protect \endinput - -\starttext - -\setupframedtablecolumn [1] [width=3cm,background=color,backgroundcolor=red] -\setupframedtablecolumn [2] [width=4cm,background=color,backgroundcolor=green,align=normal] -% \setupframedtablerow [each] [background=color,backgroundcolor=blue,strut=no] -% \setupframedtablerow [each] [strut=no,offset=overlay] - -\startframedtable[inbetween=\kern-0.4pt,distance=-0.4pt] - -\testfeatureonce{10000}{ -% \testfeatureonce{10}{ - \startframedrow - \startframedcell%[backgroundcolor=yellow] - test - \stopframedcell - \startframedcell - test \par test - \stopframedcell - \stopframedrow -} -\stopframedtable - -\stoptext diff --git a/tex/context/base/mkiv/tabl-ltb.mkxl b/tex/context/base/mkiv/tabl-ltb.mkxl deleted file mode 100644 index 5058e26f8..000000000 --- a/tex/context/base/mkiv/tabl-ltb.mkxl +++ /dev/null @@ -1,813 +0,0 @@ -%D \module -%D [ file=tabl-ltb, -%D version=2002.10.31, % updated 2016.01.08 -%D title=\CONTEXT\ Table Macros, -%D subtitle=Line Tables, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D This module was made for some special project where we needed to typeset tables -%D spanning spanning many pages horizontally and vertically, with repeated header -%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a -%D table, which is why the table can go into a buffer or file. As said, tables can -%D be real huge but performance is still quite okay (there is room for some speed -%D up). The code has been adapted to \MKIV\ but the functionality is the same as in -%D \MKII. - -% \BH \BC .. \EC \BC .. \EC \EH % append -% \BR \BC .. \EC \BC .. \EC \ER -% -% or -% -% \NC .. \NC .. \NC \NR (todo: optional last \NC) - -% alternative: -% -% (1) direct run, save content in macro, but only if needed -% -% todo -% -% (2) buffered table content -% -% \startbuffer -% \startlinetablehead -% \stoplinetablehead -% \startlinetablebody -% \stoplinetablebody -% \stopbuffer -% -% \processlinetablebuffer[buffer] -% -% in buffer : head and body -% -% (3) unbuffered run, multipass -% -% - run with starting width zero / prev run -% - clip on prev run -% - flush real widths - -\writestatus{loading}{ConTeXt Table Macros / Line Tables} - -\unprotect - -\installcorenamespace{linetable} -\installcorenamespace{linetablepart} -\installcorenamespace{linetablewidth} -\installcorenamespace{linetableheight} -\installcorenamespace{linetabledepth} - -\newconditional \c_tabl_lines_preroll -\newconditional \c_tabl_lines_in_table - -\newdimen \d_tabl_lines_width -\newdimen \d_tabl_lines_height -%newdimen \d_tabl_lines_depth - -\newbox \b_tabl_lines_cell - -\newcount \c_tabl_lines_n_of_columns -\newcount \c_tabl_lines_n_of_rows -\newcount \c_tabl_lines_n_of_lines -\newcount \c_tabl_lines_n_of_parts -\newcount \c_tabl_lines_part \c_tabl_lines_part\plusone -\newcount \c_tabl_lines_step \c_tabl_lines_step\plusone -\newcount \c_tabl_lines_line -\newcount \c_tabl_lines_row -\newcount \c_tabl_lines_rows -\newcount \c_tabl_lines_column -\newcount \c_tabl_lines_subcol - -\newconstant \c_tabl_lines_hmode -\newconstant \c_tabl_lines_page -\newconstant \c_tabl_lines_repeat -\newconstant \c_tabl_lines_split_state -\newconstant \c_tabl_lines_head_state -\newconstant \c_tabl_lines_mode - -\newtoks \t_tabl_lines_head - -\newconditional \linetableautoheight \settrue\linetableautoheight - -\initializetablebox\zerocount % holds repeater - -\pushoverloadmode - -\permanent\tolerant\protected\def\setuplinetable[#1]#*[#2]#*[#3]% - {\ifarguments\or - \getparameters[\??linetable][#1]% - \or - \getparameters[\??linetable#1:][#2]% - \or - \getparameters[\??linetable#1:#2][#3]% - \fi} - -\permanent\def\linetableparameter#1% - {\begincsname\??linetable#1\endcsname} - -\permanent\protected\def\doifelselinetablecparameter#1% - {\ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname - \expandafter\firstoftwoarguments - \orelse\ifcsname\??linetable c:#1\endcsname - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\aliased\let\doiflinetablecparameterelse\doifelselinetablecparameter - -\permanent\def\linetablecparameter#1% - {\begincsname - \??linetable - \ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname - c:\number\c_tabl_lines_column - \orelse\ifcsname\??linetable c:#1\endcsname - c:% - \fi - #1% - \endcsname} - -\permanent\def\linetablerparameter#1% faster, leaner and meaner - {\begincsname - \??linetable - \ifnum\c_tabl_lines_row=\zerocount % geen ifcase - \ifcsname\??linetable r:\v!header#1\endcsname - r:\v!header - \orelse\ifcsname\??linetable r:0#1\endcsname - r:0% - \fi - \else - \ifcsname\??linetable r:\number\c_tabl_lines_row#1\endcsname - r:\number\c_tabl_lines_row - \orelse\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname - r:\v!oddeven\c_tabl_lines_row - \fi - \fi - #1% - \endcsname} - -\protected\def\tabl_lines_set - {\edef\p_lines{\linetableparameter\c!lines}% - \ifx\p_lines\v!fit - \tabl_lines_set_indeed - \else - \global\c_tabl_lines_n_of_lines\p_lines - \fi} - -\protected\def\tabl_lines_set_indeed - {% whitespace already added by vertical strut - %\triggerpagebuilder - \scratchdimen - \ifdim\pagegoal<\maxdimen - \dimexpr\pagegoal-\pagetotal\relax - \else - \textheight - \fi - \getrawnoflines\scratchdimen - \global\c_tabl_lines_n_of_lines\noflines - \ifconditional\c_tabl_lines_preroll \else \ifnum\c_tabl_lines_n_of_lines<\plustwo - \page - \tabl_lines_set - \fi \fi} - -\def\tabl_lines_step_cell - {\advance\scratchdimen\linetablecparameter\c!width - \global\advance \c_tabl_lines_column\plusone - \advance\scratchskip \linetablecparameter\c!distance} - -\permanent\tolerant\protected\def\startlinetablecell[#1]% - {\global\setbox\b_tabl_lines_cell\hbox\bgroup - \ifparameter#1\or - \getparameters[\??linetable c:\number\c_tabl_lines_column][#1]% - \fi - \global\c_tabl_lines_step\linetablecparameter\c!nx\relax - \ifcase\c_tabl_lines_step\or - \scratchdimen\linetablecparameter\c!width - \scratchskip \linetablecparameter\c!distance - \else - \scratchdimen \zeropoint - \scratchskip \zeropoint - \scratchcounter\c_tabl_lines_column - \dorecurse\c_tabl_lines_step\tabl_lines_step_cell - \global\c_tabl_lines_column\scratchcounter - \fi - \c_tabl_lines_mode - \ifconditional\c_tabl_lines_preroll - \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi - \else - \zerocount - \fi - \ifcase\c_tabl_lines_mode - \ifcase\c_tabl_lines_hmode - % nothing - \or - % fit, keep it simple - \or - \c_tabl_lines_mode\plusone % line - \else - % some already calculated height - \fi - \fi - \setbox\scratchbox\hbox - \bgroup - \dontcomplain - \hskip\linetablecparameter\c!leftoffset\relax - % 0 = width, unknown height - % 1 = width, fixed height - % 2 = no width, auto hsize - \ifnum\c_tabl_lines_mode<\plustwo - \advance\scratchdimen-\linetablecparameter\c!leftoffset - \advance\scratchdimen-\linetablecparameter\c!rightoffset - \fi - \ifcase\c_tabl_lines_mode - \dosetraggedcommand{\linetablecparameter\c!align}% - \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup - \hsize\scratchdimen - \raggedcommand - \else - \setalignmentswitch{\linetablecparameter\c!align}% - \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup - \ifcase\alignmentswitch\hss\or\hss\fi - \fi - \dousestyleparameter{\linetablecparameter\c!style}% - \dousecolorparameter{\linetablecparameter\c!color}% - \begstrut \ignorespaces} - -\permanent\protected\def\stoplinetablecell - {\unskip \endstrut - \ifcase\c_tabl_lines_mode - \endgraf - \else - \ifcase\alignmentswitch\else\hss\fi - \fi - \egroup - \hskip\linetablecparameter\c!rightoffset - \egroup - \ifconditional\c_tabl_lines_preroll - \box\scratchbox - \else - \tabl_lines_wrap_up - \fi - \egroup} - -\def\tabl_lines_wrap_up - {\edef\p_background{\linetablecparameter\c!background}% - \ifx\p_background\v!color - \ifconditional\linetableautoheight - \tabl_lines_wrap_up_auto - \else - \tabl_lines_wrap_up_line - \fi - \else - \box\scratchbox - \fi} - -% \startuseMPgraphic{one} -% path p, q ; -% numeric r ; -% r := RuleThickness ; -% p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ; -% q := p topenlarged -r bottomenlarged -r ; -% draw q ; -% setbounds currentpicture to p; -% \stopuseMPgraphic -% -% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt] -% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt] -% -% \startlinetable -% \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} -% \stoplinetable - -\def\tabl_lines_wrap_up_auto - {\edef\p_height{\linetablerparameter{x\c!height}}% - \edef\p_depth {\linetablerparameter{x\c!depth }}% - \hpack - {\blackrule - [ \c!color=\linetablecparameter\c!backgroundcolor, - \c!type=\linetablecparameter\c!type, - \c!mp=\linetablecparameter\c!mp, - \c!rulethickness=\linetablecparameter\c!rulethickness, - \c!height=\ifempty\p_height\ht\scratchbox\else\p_height\fi, - \c!depth=\ifempty\p_depth \dp\scratchbox\else\p_depth \fi, - \c!width=\wd\scratchbox]% - \hskip-\wd\scratchbox\box\scratchbox}} - -\def\tabl_lines_wrap_up_auto_r - {\hpack - {\blackrule - [ \c!color=\linetablerparameter\c!backgroundcolor, - \c!type=\linetablerparameter\c!type, - \c!mp=\linetablerparameter\c!mp, - \c!rulethickness=\linetablerparameter\c!rulethickness, - \c!height=\ht\scratchbox, - \c!depth=\dp\scratchbox, - \c!width=\wd\scratchbox]% - \hskip-\wd\scratchbox\box\scratchbox}} - -\def\tabl_lines_wrap_up_line - {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}} - -\def\tabl_lines_save_part - {\global\setbox\tablebox\c_tabl_lines_part - \ifcase\c_tabl_lines_part\relax - \box\scratchbox % just storing - \else - \vbox - {\ifvoid\tablebox\c_tabl_lines_part\else\unvbox\tablebox\c_tabl_lines_part\fi - \edef\p_background{\linetablerparameter\c!background}% - \ifx\p_background\v!color - \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}% - \else - \edef\p_type{\linetablerparameter\c!type}% - \ifempty\p_type - \box\scratchbox - \else - \tabl_lines_wrap_up_auto_r - \fi - \fi - \endgraf - \linetablerparameter\c!after}% - \fi} - -\def\tabl_lines_flush_parts - {\global\advance\c_tabl_lines_line\plusone - \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines - % keep collecting - \else - \ifconditional\c_tabl_lines_preroll - % forget about them - \else - \dorecurse\c_tabl_lines_n_of_parts - {\c_tabl_lines_part\recurselevel - \dp\tablebox\c_tabl_lines_part\strutdepth - % noindent en endgraf needed else whitespace mess-up! - \whitespace % here not after verticalstrut - \ifdim\topskipgap=\zeropoint\else - \verticalstrut - \nobreak - \kern-\struttotal - \kern-\parskip - \nobreak - \nointerlineskip % fix topskip - \fi - \noindent\strut - \hpack to \hsize{\box\tablebox\c_tabl_lines_part\hss}% - \endgraf - \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax - \linetableparameter\c!inbetween - \fi}% - \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows - \linetableparameter\c!inbetween - \else - % after, later - \fi - \c_tabl_lines_head_state\plusthree - \global\setbox\tablebox\zerocount\emptybox % here - \fi - % reset \c_tabl_lines_row will be an option, currently - % starts at zero after split - \global\c_tabl_lines_row\zerocount - \global\c_tabl_lines_line\zerocount - \global\c_tabl_lines_page\zerocount - \global\d_tabl_lines_width\zeropoint - \tabl_lines_set - \fi} - -\def\tabl_lines_start_part - {\global\c_tabl_lines_subcol\zerocount - \setbox\scratchbox\hbox\bgroup - \dousestyleparameter{\linetablerparameter\c!style}% - \dousecolorparameter{\linetablerparameter\c!color}% - \ignorespaces} - -\def\tabl_lines_stop_part - {\ifnum\c_tabl_lines_part>\zerocount - \unskip \unskip % remove last intercolumn skip (distance+fill) - \fi - \egroup - \ifconditional\c_tabl_lines_preroll \else - \ifcase\c_tabl_lines_part - % we're collecting the repeater - \else - \ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch\else - \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}% - \fi - \fi - \fi} - -\def\tabl_lines_check_part - {\global\advance\d_tabl_lines_width\wd\b_tabl_lines_cell - \global\advance\c_tabl_lines_column\c_tabl_lines_step - \global\advance\c_tabl_lines_subcol\c_tabl_lines_step - \relax - %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait - % from now on the column counter is already incremented - \ifcase\c_tabl_lines_split_state - \ifconditional\c_tabl_lines_preroll \else - \box\b_tabl_lines_cell - % the columncounter is one ahead ! - \hskip\scratchskip - \fi - %%% - \donefalse - \ifcase\c_tabl_lines_repeat\else - % calculate ahead - \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax - \donetrue % collecting repeater - \fi - \fi - %%%% - \ifdone - % collecting repeater - \else - \ifnum\c_tabl_lines_column>\csname\??linetablepart\number\c_tabl_lines_part\endcsname\relax - \donetrue - \fi - \fi - \ifdone - \tabl_lines_stop_part - \ifconditional\c_tabl_lines_preroll \else - \tabl_lines_save_part - \fi - \ifcase\c_tabl_lines_page \or - \global\c_tabl_lines_page \plustwo - \else - \global\c_tabl_lines_page \plusone - \fi - \global\advance\c_tabl_lines_part\plusone - \global\d_tabl_lines_width\wd\tablebox\zerocount - \tabl_lines_start_part - \fi - \else - \donefalse - \scratchconditiononefalse - \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 - \scratchconditiononetrue - % collecting repeater - \orelse\ifdim\d_tabl_lines_width>\hsize - \donetrue - \else - \global\advance\d_tabl_lines_width\scratchskip - \ifdim\d_tabl_lines_width>\hsize % ? - \donetrue - \fi - \fi - \ifdone - \tabl_lines_stop_part - \tabl_lines_save_part - \ifcase\c_tabl_lines_page \or - \global\c_tabl_lines_page \plustwo - \else - \global\c_tabl_lines_page \plusone - \fi - \global\advance\c_tabl_lines_part\plusone - \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts - \global\c_tabl_lines_n_of_parts\c_tabl_lines_part - \initializetablebox\c_tabl_lines_part - \fi - \global\d_tabl_lines_width\wd\b_tabl_lines_cell - \tabl_lines_start_part - \ifscratchconditionone \else \ifcase\c_tabl_lines_repeat \else - % check for left/right page - \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi\ifdone - % insert repeater - \global\advance\d_tabl_lines_width\wd\tablebox\zerocount - \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\tablebox\zerocount - \fi - \fi \fi - \fi - \ifconditional\c_tabl_lines_preroll \else - \box\b_tabl_lines_cell - % the columncounter is one ahead ! - %\dorecurse\c_tabl_lines_step{\strut\hfil}% - \strut - \hskip\scratchskip - \fi - \fi} - -\permanent\protected\def\startlinetablerun % to do: quit when nested - {\bgroup - \dontcomplain - \settrue\c_tabl_lines_in_table - % autowidth - \doif{\linetableparameter\c!maxwidth}\v!fit - {\setuplinetable[\c!maxwidth=\zeropoint]}% - \processaction - [\linetableparameter\c!stretch] - [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch - \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch - \c_tabl_lines_repeat\linetableparameter\c!nleft - \c_tabl_lines_split_state % = - \ifdim\linetableparameter\c!maxwidth>\zeropoint - \zerocount \else \plusone - \fi - % optional prevdepth correction - \ifconditional\c_tabl_lines_preroll - \global\c_tabl_lines_n_of_rows\zerocount - \else - \linetableparameter\c!before - \fi - \global\c_tabl_lines_rows\zerocount - \global\c_tabl_lines_n_of_columns\zerocount - \global\c_tabl_lines_n_of_parts\zerocount - \scratchcounter\zerocount - \def\docommand##1% - {\global\advance\c_tabl_lines_n_of_parts\plusone - \advance\scratchcounter##1% - \setxvalue{\??linetablepart\number\c_tabl_lines_n_of_parts}{\the\scratchcounter}}% - \processcommacommand[\linetableparameter\c!n]\docommand - \initializetableboxes\c_tabl_lines_n_of_parts - \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater - \global\c_tabl_lines_step\plusone - \global\c_tabl_lines_line\zerocount - \global\c_tabl_lines_row \zerocount - \global\c_tabl_lines_column\zerocount - \global\c_tabl_lines_subcol\zerocount - \global\d_tabl_lines_width\zeropoint - \ifconditional\c_tabl_lines_preroll \else \ifdim\pagetotal>\zeropoint - \verticalstrut\kern-\struttotal - \fi \fi - \tabl_lines_set - \tabl_lines_check_page - \enforced\let\BR\tabl_lines_BR - \enforced\let\ER\tabl_lines_ER - \enforced\let\BH\tabl_lines_BR - \enforced\let\EH\tabl_lines_ER - \enforced\let\BC\tabl_lines_BC - \enforced\let\EC\tabl_lines_EC - \enforced\let\NC\tabl_lines_NC - \enforced\let\NR\tabl_lines_NR - \tabl_lines_flush_head} - -\permanent\protected\def\stoplinetablerun - {\global\c_tabl_lines_line\maxcard - \c_tabl_lines_head_state\zerocount % blocked - \tabl_lines_flush_parts - \ifconditional\c_tabl_lines_preroll \else - \linetableparameter\c!after - \fi - \global\c_tabl_lines_part\zerocount - \global\c_tabl_lines_n_of_parts\zerocount - \egroup} - -\permanent\def\checklinecolumndimension#1#2#3% - {\global\edef#1\number#3\endcsname - {\expandafter\ifx\csname#1\number#3\endcsname\relax - \the#2\b_tabl_lines_cell - \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell - \the#2\b_tabl_lines_cell - \else - \csname#1\number#3\endcsname - \fi}} - -\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column} -\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row} -\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row} - -\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented - {\ifnum\c_tabl_lines_head_state=1\else - \global\advance\c_tabl_lines_row\plusone - \global\advance\c_tabl_lines_rows\plusone - \fi - \global\c_tabl_lines_column\plusone - \global\c_tabl_lines_subcol\plusone - \d_tabl_lines_height\zeropoint - \edef\p_height{\linetablerparameter\c!height}% - \ifempty\p_height - \c_tabl_lines_hmode \zerocount - \orelse\ifx\p_height\v!fit - \c_tabl_lines_hmode \plusone - \orelse\ifx\p_height\v!line - \c_tabl_lines_hmode \plustwo - \else - \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax - \fi - \tabl_lines_start_part} - -\permanent\protected\def\tabl_lines_BC - {\startlinetablecell} - -\permanent\protected\def\tabl_lines_EC - {\stoplinetablecell - \ifconditional\c_tabl_lines_preroll - \tabl_lines_check_width - \tabl_lines_check_height - \tabl_lines_check_depth - \fi - \tabl_lines_check_part} - -\permanent\protected\def\tabl_lines_ER - {% \stoplinetablecell - % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR - \tabl_lines_stop_part - \tabl_lines_save_part - \advance\c_tabl_lines_column \minusone - \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns - \global\c_tabl_lines_n_of_columns\c_tabl_lines_column - \fi - \tabl_lines_flush_parts - \global\c_tabl_lines_column\zerocount - \global\d_tabl_lines_width \zeropoint - \ifcase\c_tabl_lines_repeat - \global\c_tabl_lines_part\plusone - \else - \global\c_tabl_lines_part\zerocount % repeater - \fi - \tabl_lines_check_page - \tabl_lines_flush_head} - -\def\tabl_lines_check_page - {\global\c_tabl_lines_page\zerocount - \ifcase\c_tabl_lines_repeat \else \ifcase\c_tabl_lines_page - \doif{\linetableparameter\c!repeat}\v!no - {\global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo}% - \fi \fi} - -\def\tabl_lines_flush_head - {\ifcase\c_tabl_lines_head_state - % 0 blocked - \or - % 1 doing head - \or - % 2 head done - \or - % 3 trigger flush - \c_tabl_lines_head_state\plusone - \the\t_tabl_lines_head\relax - \c_tabl_lines_head_state\plustwo - \fi} - -\permanent\protected\def\tabl_lines_NC % first time special treatment - {\relax - \ifcase\c_tabl_lines_column - \tabl_lines_BR - \else - \tabl_lines_EC - \fi - \tabl_lines_BC} % beware, this will result in BR BC EC BC NR - -\permanent\protected\def\tabl_lines_NR - {\stoplinetablecell % dummy - \tabl_lines_ER} - -\permanent\protected\def\startlinetable - {\startlinetablerun} - -\permanent\protected\def\stoplinetable - {\stoplinetablerun} - -\permanent\protected\def\startlinetableanalysis - {\bgroup - \settrue\c_tabl_lines_preroll - \settrialtypesetting - \startlinetablerun} - -% \protected\def\stoplinetableanalysis -% {\stoplinetablerun -% \egroup -% \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows -% \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n} -% {\setevalue{\??linetable r:\recurselevel x\c!height}{\getvalue{\??linetableheight\recurselevel}}% -% \setevalue{\??linetable r:\recurselevel x\c!depth }{\getvalue{\??linetabledepth \recurselevel}}% -% \letgvalue{\??linetableheight\recurselevel}\!!zeropoint -% \letgvalue{\??linetabledepth \recurselevel}\!!zeropoint} -% \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n} -% {\setevalue{\??linetable c:\recurselevel\c!width}{\getvalue{\??linetablewidth\recurselevel}}% -% \letgvalue{\??linetablewidth\recurselevel}\!!zeropoint}} % init next table - -\permanent\protected\def\stoplinetableanalysis - {\stoplinetablerun - \egroup - \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows - \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n} - {\setevalue{\??linetable r:##1x\c!height}{\csname\??linetableheight##1\endcsname}% - \setevalue{\??linetable r:##1x\c!depth }{\csname\??linetabledepth ##1\endcsname}% - \letgvalue{\??linetableheight##1}\zeropoint - \letgvalue{\??linetabledepth ##1}\zeropoint} - \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n} - {\setevalue{\??linetable c:##1\c!width}{\csname\??linetablewidth##1\endcsname}% - \letgvalue{\??linetablewidth##1}\zeropoint}} % init next table - -% todo: store in box instead of macro - -\aliased\let\stoplinetablehead\relax - -\permanent\protected\def\startlinetablehead#1\stoplinetablehead - {\ifconditional\c_tabl_lines_in_table - \t_tabl_lines_head\emptytoks - \fi - \c_tabl_lines_head_state\plusthree % full - \t_tabl_lines_head{#1}% - \ifconditional\c_tabl_lines_in_table - \tabl_lines_flush_head - \fi} - -\permanent\protected\def\tabl_lines_BH - {\ifx\EC\relax - % signal, grabbing lines - \else - \t_tabl_lines_head\emptytoks - \fi - \push_macro_BC - \push_macro_EC - \enforced\permanent\protected\def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}% - \enforced\permanent \let\EC\relax} % signal - -\permanent\protected\def\tabl_lines_EH - {\pop_macro_EC - \pop_macro_BC - \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead} - -\permanent\let\startlinetablebody\relax -\permanent\let\stoplinetablebody \relax - -\protected\def\processlinetablebuffer - {\dosingleempty\tabl_lines_process_buffer} - -\def\tabl_lines_process_buffer[#1]% - {\bgroup - \enforced\let\startlinetable\relax - \enforced\let\stoplinetable \relax - \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis - \startlinetablerun \getbuffer[#1]\stoplinetablerun - \egroup} - -\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1] - {\bgroup - \enforced\let\startlinetable\relax - \enforced\let\stoplinetable \relax - \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis - \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun - \egroup} - -\popoverloadmode - -\setuplinetable - [\c!n=\maxcard, - \c!lines=\maxcard, - \c!nx=\plusone, - \c!nleft=\zerocount, - \c!repeat=\v!yes, % when nleft > 0, repeat on both pages - \c!before=, - \c!after=, - \c!inbetween=\page, - \c!distance=\zeropoint, - \c!stretch=\v!no, - \c!align=\c!right, - \c!leftoffset=.25\exheight, - \c!rightoffset=\linetableparameter\c!leftoffset, - \c!maxwidth=\zeropoint, - \c!width=5\emwidth, - \c!height=\v!fit, % \v!line = faster - \c!background=, - \c!backgroundcolor=, - \c!rulethickness=\linewidth] - -\protect - -\continueifinputfile{tabl-ltb.mkxl} - -\setuplinetable[n=6,m={2,2,2},lines=25] % m ? - -\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red] -\setuplinetable[c][4] [width=3cm,background=color,backgroundcolor=yellow] -\setuplinetable[c][6] [width=3cm,background=color,backgroundcolor=magenta] -\setuplinetable[r][odd] [background=color,backgroundcolor=gray] -\setuplinetable[r][even][background=color,backgroundcolor=green] - -\starttext - -\showframe \showstruts - -\setuppagenumbering[alternative=doublesided]\page[left] - -\startlinetable -\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR -\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} -\stoplinetable - -\startlinetable -\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx - \NC yy \NC ddddd \NC eeee \NC ff \NC \NR -\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} -\stoplinetable - -% \startbuffer[lt] -% \NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC ee \NC ff \NC \NR -% \NC aaa\crlf aaa \NC b \NC cc \NC ddd \NC eeee \NC f \NC \NR -% \stopbuffer -% -% \processlinetablebuffer[lt] - -\stoptext diff --git a/tex/context/base/mkiv/tabl-mis.mkxl b/tex/context/base/mkiv/tabl-mis.mkxl deleted file mode 100644 index 14bd08b46..000000000 --- a/tex/context/base/mkiv/tabl-mis.mkxl +++ /dev/null @@ -1,294 +0,0 @@ -%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 - -\permanent\tolerant\protected\def\somekindoftab[#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 \CONTEXT\ and -%D mostly served as a table mechanism capable of dealing with paragraphs. Nowadays -%D 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} - -\installframedcommandhandler \??paragraphs {paragraphs} \??paragraphs - -\setupparagraphs - [\c!n=3, - \c!offset=\zeropoint, - \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!frame=\v!off, - \c!top=\vss, - \c!bottom=\vfill] - -\aliased\let\typo_paragraphs_setup_saved\setupparagraphs - -\overloaded\permanent\tolerant\protected\def\setupparagraphs[#1]#*[#2]#*[#3]% we are downward compatible with [each] and [1,3] - {\ifarguments\or - \typo_paragraphs_setup_saved[#1]% - \or - \typo_paragraphs_setup_saved[#1][#2]% - \or - \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}% - \fi} - -\appendtoks - \frozen\instance\letvalue{\e!next \currentparagraphs}\nextparagraphs - \frozen\instance\letvalue\currentparagraphs\nextparagraphs - \frozen\instance\setuevalue{\e!start\currentparagraphs}{\startparagraphs[\currentparagraphs]}% - \frozen\instance\letvalue{\e!stop \currentparagraphs}\stopparagraphs - %frozen\instance\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 - -\permanent\protected\def\startparagraphs[#1]% quite slow - {\bgroup % (1) - \edef\currentparagraphs{#1}% - % \paragraphsparameter\c!before - \edef\p_width{\paragraphsparameter\c!width}% - \ifempty\p_width - \d_typo_paragraphs_width\availablehsize - \else - \d_typo_paragraphs_width\p_width\relax - \fi - \advance\d_typo_paragraphs_width-2\dimexpr\paragraphsparameter\c!offset\relax - \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}% - \ifempty\p_width - \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 - \enforced\let\\\typo_paragraphs_next % downward compatible - \edef\p_offset{\paragraphsparameter\c!offset}% - \doifelsedimension\p_offset - {\scratchoffset\p_offset}% - {\scratchoffset\zeropoint}% - \setbox\scratchbox\hpack - \bgroup % (2) - \forgetall - \advance\hsize-2\scratchoffset - \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} - -\permanent\protected\def\stopparagraphs - {\stopparagraphscell - \egroup % (2) - \letparagraphsparameter\c!align\v!flushleft % normal - \paragraphsparameter\c!before - \dontleavehmode\inheritedparagraphsframed{\box\scratchbox}% - \paragraphsparameter\c!after - \egroup} % (1) - -\permanent\protected\def\nextparagraphs - {\stopparagraphscell - \startparagraphscell} - -\permanent\protected\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 \ifempty\p_height \orelse\ifx\p_height\v!fit \else to \p_height \fi - \bgroup % (2) - \blank[\v!disable]% - \paragraphsparameter\c!top - \hsize\ifempty\p_width \d_typo_paragraphs_auto \else \p_width \fi \relax - \usealignparameter\paragraphsparameter - \paragraphsparameter\c!inner - \everypar{\begstrut\everypar\emptytoks}% - \ignorespaces - \paragraphsparameter\c!command} - -\permanent\protected\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/tex/context/base/mkiv/tabl-ntb.mkxl b/tex/context/base/mkiv/tabl-ntb.mkxl deleted file mode 100644 index 8883a29e3..000000000 --- a/tex/context/base/mkiv/tabl-ntb.mkxl +++ /dev/null @@ -1,2172 +0,0 @@ -%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 different -%D approach with settings there, this mechanism will stay. In fact each of them has -%D its advantages. This module could be sped up a bit and made more efficient by -%D delegating some housekeeping to \LUA\ but it's not worth the effort. The code -%D could me made more readable but again, there is no real purpose in it. If needed -%D I can squeeze out a few more percentages 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 - -% \protected\def\startrow {\bTR} -% \protected\def\stoprow {\eTR} -% \protected\def\startcell#1\stopcell{\bTD#1\eTD} -% \let\stopcell \relax -% \let\startcelltable \bTABLE -% \let\stopcelltable \eTABLE - -% \starttext -% \startcelltable -% \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 trying to speed up -%D the many cell calculations, some optimizations were rejected in order not to -%D complicate this 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 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 - -\protected\def\tabl_ntb_cell_start - {% \inhibitblank - \dotagTABLEcell - %\tabl_ntb_next_level - \font_styles_math_reset - \usenaturaltablelocalstyleandcolor\c!style\c!color - \everypar\t_tabl_ntb_cell_start - \font_styles_math_start} - -\protected\def\tabl_ntb_cell_stop - {\font_styles_math_stop - \ifhmode - \the\t_tabl_ntb_cell_stop - \par % added 13/4/2006 - \orelse\ifdim\prevdepth<\zeropoint % =-1000pt ? - % not sure yet:\naturaltablelocalparameter\c!right - \vskip-\strutdp - \else - \removebottomthings - \fi} - -% maybe: -% -% \protected\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 -% \ifhmode -% % \removeunwantedspaces -% \orelse\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 For tagging and export: - -\newconstant \c_tabl_ntb_head -\newconstant \c_tabl_ntb_body -\newconstant \c_tabl_ntb_foot -\newconditional \c_tabl_ntb_okay - -%D We have already prepared the previous macros for nesting, so we only have to pop -%D in the right ones: - -\newcount\c_tabl_level - -\installglobalmacrostack\m_tabl_ntb_saved_row -\installglobalmacrostack\m_tabl_ntb_saved_col - -\protected\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}\push_macro_m_tabl_ntb_saved_row - \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\push_macro_m_tabl_ntb_saved_col - \else - \global\intabletrue - \fi} - -\protected\def\tabl_ntb_table_pop - {\ifnum\m_tabl_tbl_level>\plusone - \pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row - \pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col - \else - \global\intablefalse - \fi} - -\protected\def\tabl_ntb_next_level - {\advance\c_tabl_level\plusone - \edef\m_tabl_tbl_level{\the\c_tabl_level}} - -\protected\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 - -\permanent\protected\def\bTABLEnested{\tabl_ntb_next_level\bTABLE} -\permanent\protected\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level} - -\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{naturaltablebck} -%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\letcsname\??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\letcsname\??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{\letcsname\??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{\edefcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\def\tabl_ntb_set_col#1#2{\edefcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\def\tabl_ntb_set_row#1#2{\edefcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} - -\def\tabl_ntb_let_tag#1#2{\letcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\def\tabl_ntb_let_col#1#2{\letcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\def\tabl_ntb_let_row#1#2{\letcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} - -%def\tabl_ntb_set_wd#1#2{\global\edefcsname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! -\def\tabl_ntb_set_ht#1#2{\global\edefcsname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! - -%def\tabl_ntb_let_wd#1#2{\global\letcsname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! -\def\tabl_ntb_let_ht#1#2{\global\letcsname\??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{\global\edefcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_set_hei#1{\global\edefcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_set_dis#1{\global\edefcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_set_aut#1{\global\edefcsname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! - -\def\tabl_ntb_let_wid#1{\global\letcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_hei#1{\global\letcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_dis#1{\global\letcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_aut#1{\global\letcsname\??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_let_bck#1#2{\global\expandafter\chardef\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname} - -\def\tabl_ntb_get_bck#1#2{\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\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} - -%D If we ever run into memory issues we can do: -% -% \def\tabl_ntb_let_tag#1#2#3% -% {\ifx#3\c_tabl_ntb_none\else -% \letcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname#3% -% \fi} -% -% \def\tabl_ntb_get_tag#1#2% -% {\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname -% \lastnamedcs -% \else -% \c_tabl_ntb_none -% \fi} - -\def\tabl_ntb_let_ref #1#2{\global\letcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\def\tabl_ntb_set_ref #1#2{\global\edefcsname\??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{\letcsname\??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} - -\protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% - {\defcsname\??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 - -\newconditional \c_tabl_ntb_trace_widths - -\installtextracker - {tables.natural.widths} - {\settrue \c_tabl_ntb_trace_widths} - {\setfalse\c_tabl_ntb_trace_widths} - -% so far - -\protected\def\tabl_ntb_cell_process#1#2[#3]{} - -\permanent\protected\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax -\permanent\protected\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax -\permanent\protected\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax - -\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal - -\permanent\tolerant\protected\def\setupTABLE[#1]#*[#2]#*[#3]% - {\ifarguments - \expandafter\gobblethreeoptionals - \or - \expandafter\tabl_ntb_setup_one - \or - \expandafter\tabl_ntb_setup_two - \or - \expandafter\tabl_ntb_setup_three - \fi[#1][#2][#3]} - -\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]{\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 - \enforced\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 - \enforced\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 - -\protected\def\tabl_ntb_setup_cell#1#2% cell over col over row - {\tabl_ntb_setup_section % already forgotten - \edef\m_tabl_ntb_positive_row{\number#1}% - \edef\m_tabl_ntb_positive_col{\number#2}% - \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 - -\protected\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} - -\protected\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}% - % - \ifempty\m_tabl_ntb_n - \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax - \orelse\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else - \tabl_ntb_td_pass_n{#1}% - \fi - \ifempty\m_tabl_ntb_m \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 added -%D 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 as well as -%D the columndistance (although i changed the names -). Here 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 foot, dus state var - -\let\eTABLEhead\relax -\let\eTABLEnext\relax -\let\eTABLEbody\relax -\let\eTABLEfoot\relax - -\permanent\tolerant\protected\def\bTABLEhead[#1]#:#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} -\permanent\tolerant\protected\def\bTABLEnext[#1]#:#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} -\permanent\tolerant\protected\def\bTABLEbody[#1]#:#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} -\permanent\tolerant\protected\def\bTABLEfoot[#1]#:#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} - -\def\tabl_ntb_section[#1]#2% also used in tabl-nte - {\protected\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} - -\permanent\tolerant\protected\def\bTABLE[#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 - \enforced\let\bTR\tabl_ntb_bTR - \enforced\let\bTD\tabl_ntb_bTD - \enforced\let\bTH\tabl_ntb_bTH - \enforced\let\bTN\tabl_ntb_bTN} - -\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 - -% there is no gain in a \doifelsenextoptionalcs variant - -% todo with tolerant: - -\permanent\protected\def\tabl_ntb_bTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte -\permanent\protected\def\tabl_ntb_bTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte -\permanent\protected\def\tabl_ntb_bTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte -\permanent\protected\def\tabl_ntb_bTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte - -% permits \expanded{\bTD ... \eTD} - -\permanent\let\bTR\relax \permanent\protected\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows -\permanent\let\bTD\relax \permanent\protected\def\eTD{\ignorespaces} -\permanent\let\bTH\relax \permanent\protected\def\eTH{\ignorespaces} -\permanent\let\bTN\relax \permanent\protected\def\eTN{\ignorespaces} - -\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode - {% tricky and dirty order -) - \setfalse\c_tabl_ntb_okay - % head - \doifelsesometoks\t_tabl_ntb_head % slow, better a flag - {\c_tabl_ntb_head\numexpr\c_tabl_ntb_maximum_row+\plusone\relax - \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_head\zerocount - \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}% - % body - \c_tabl_ntb_body\numexpr\c_tabl_ntb_maximum_row+\plusone\relax - \the\t_tabl_ntb_body - % foot - \doifelsesometoks\t_tabl_ntb_foot - {\c_tabl_ntb_foot\numexpr\c_tabl_ntb_maximum_row+\plusone\relax - \the\t_tabl_ntb_foot}% - {\c_tabl_ntb_foot\zerocount}% - % done - \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 - \etoksapp\t_tabl_ntb - {% no need for init - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}} - -\def\tabl_ntb_row_stop_split - {\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname - \tabl_ntb_row_stop_split_yes - \else - \tabl_ntb_row_stop_split_nop - \fi} - -\def\tabl_ntb_row_stop_split_nop - {\etoksapp\t_tabl_ntb - {\tabl_ntb_row_align_reset - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}} - -\def\tabl_ntb_row_stop_split_yes - {\begingroup - \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 - \etoksapp\t_tabl_ntb - {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}% - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}} - -\protected\def\tabl_ntb_row_align_set#1#2#3% - {\xdef\m_tabl_ntb_before_split{#1}% - \xdef\m_tabl_ntb_after_split {#2}% - \xdef\m_tabl_ntb_same_page {#3}} - -\protected\def\tabl_ntb_row_align_reset - {\glet\m_tabl_ntb_before_split\empty - \glet\m_tabl_ntb_after_split \empty - \glet\m_tabl_ntb_same_page \empty} - -\def\tabl_ntb_prelocate_error - {\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}} - -% \prelocateTBLrows{1000} % may speed up large tables - -\permanent\protected\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway - {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone - {\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}% - \def\tabl_ntb_row_start - {\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 - {\etoksapp\t_tabl_ntb - {\tabl_ntb_row_align_start - \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname - \tabl_ntb_row_align_stop}}% - \global\c_tabl_prelocated_rows#1\relax} - -\def\tabl_ntb_prelocate_okay - {\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks} - -%D We use aligments to handle the empty (skipped) columns, so that we don't have to -%D (re|)|calculate these. - -\let\m_tabl_ntb_saved_row\!!zerocount -\let\m_tabl_ntb_saved_col\!!zerocount - -\def\tabl_ntb_start_tagged - {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax - \ifnum\scratchcounter=\c_tabl_ntb_head - \ifconditional\c_tabl_ntb_okay - \dostoptagged - \else - \settrue\c_tabl_ntb_okay - \fi - \dostarttagged\t!tablehead\empty - \orelse\ifnum\scratchcounter=\c_tabl_ntb_body - \ifconditional\c_tabl_ntb_okay - \dostoptagged - \else - \settrue\c_tabl_ntb_okay - \fi - \dostarttagged\t!tablebody\empty - \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot - \ifconditional\c_tabl_ntb_okay - \dostoptagged - \else - \settrue\c_tabl_ntb_okay - \fi - \dostarttagged\t!tablefoot\empty - \fi - \dostarttagged\t!tablerow\empty} - -\def\tabl_ntb_stop_tagged - {\dostoptagged - \ifconditional\c_tabl_ntb_okay - \scratchcounter\numexpr\c_tabl_ntb_row+\plustwo\relax - \ifnum\scratchcounter=\c_tabl_ntb_body - \dostoptagged - \setfalse\c_tabl_ntb_okay - \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot - \dostoptagged - \setfalse\c_tabl_ntb_okay - \orelse\ifnum\scratchcounter>\c_tabl_ntb_maximum_row - \dostoptagged - \setfalse\c_tabl_ntb_okay - \fi - \fi} - -\protected\def\tabl_ntb_row_align_start - {\global\advance\c_tabl_ntb_row\plusone - \global\c_tabl_ntb_col\plusone - \global\c_tabl_ntb_spn\zerocount - \tabl_ntb_row_align_start_inject - \ifconditional\c_strc_tags_enabled - \tabl_ntb_start_tagged - \fi - \hbox\bgroup - \kern\dimexpr\d_tabl_ntb_leftmargindistance\relax} - -\protected\def\tabl_ntb_row_align_stop - {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax - \egroup - \ifconditional\c_strc_tags_enabled - \tabl_ntb_stop_tagged - \fi - \tabl_ntb_row_align_stop_inject} - -\protected\def\tabl_ntb_before_page - {\ifx\m_tabl_ntb_same_page\v!before - % \blank[\v!samepage,\v!strong]% - \unpenalty - \nobreak - \orelse\ifx\m_tabl_ntb_same_page\v!both - % \blank[\v!samepage,\v!strong]% - \unpenalty - \nobreak - \fi} - -\protected\def\tabl_ntb_after_page - {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines - \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount - \unpenalty - \ifx\m_tabl_ntb_same_page\v!after - % \blank[\v!samepage,\v!strong]% - \nobreak - \orelse\ifx\m_tabl_ntb_same_page\v!both - % \blank[\v!samepage,\v!strong]% - \nobreak - \else - % \blank[\v!preference,\v!weak]% - \allowbreak - \fi - \fi - \else - % \blank[\v!preference,\v!weak]% - \allowbreak % else no proper head split off - \fi} - -\protected\def\tabl_ntb_inbetween - {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax - \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax - \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax - \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}% - \ifempty\p_spaceinbetween\else - \blank[\p_spaceinbetween]% - \fi - \fi - \fi} - -\protected\def\tabl_ntb_row_align_start_inject - {\bgroup % protect local vars - \m_tabl_ntb_before_split - \egroup - \ifenableTBLbreak - \tabl_ntb_before_page - \fi} - -\protected\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} - -\protected\def\tabl_ntb_span#1% - {\hskip\tabl_ntb_get_dis\c_tabl_ntb_col - \dorecurse{#1} - {\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax - \global\advance\c_tabl_ntb_col\plusone}} - -\protected\def\tabl_ntb_skip#1% - {\global\advance\c_tabl_ntb_col#1\relax} - -\protected\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 - \etoksapp\t_tabl_ntb_row - {\tabl_ntb_span{\the\scratchcounter}}% - \fi} - -\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2% - {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens - \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax - \ifnum\scratchcounter>\zerocount - \etoksapp\t_tabl_ntb_row - {\ifnum\scratchcounter=\plusone - \tabl_ntb_plus - \else - \tabl_ntb_skip{\the\scratchcounter}% - \fi}% - \fi} - -\protected\def\tabl_ntb_cell#1#2% - {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}} - -\protected\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 - \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax - \ifcase\scratchcounterone\or - \advance\d_tabl_ntb_width\dimexpr - \tabl_ntb_get_wid\scratchcounter - \relax - \advance\scratchcounter\plusone - \else - \dorecurse\scratchcounterone - {\advance\d_tabl_ntb_width\dimexpr - \tabl_ntb_get_wid\scratchcounter - \ifnum\recurselevel<\scratchcounterone - +\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 - \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax - \scratchcountertwo\tabl_ntb_get_row{#1}{#2}\relax - \scratchheight\tabl_ntb_get_ht {#1}{#2}\relax - \tablecellcolumns\scratchcounterone % used later so don't adapt these - \tablecellrows \scratchcountertwo % used later so don't adapt these - \d_tabl_ntb_height\zeropoint - \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax - % case: nc=maxcolumns - \else - \scratchcounter#1\relax - \dorecurse\scratchcountertwo - {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter - \advance\scratchcounter\plusone}% - \ifdim\d_tabl_ntb_height<\scratchheight\relax - \d_tabl_ntb_height\scratchheight - \fi - \fi - % width - \d_tabl_ntb_width\zeropoint - \scratchcounter\c_tabl_ntb_col - \ifcase\scratchcounterone\or - \advance\d_tabl_ntb_width\dimexpr - \tabl_ntb_get_wid\scratchcounter - \relax - \advance\scratchcounter\plusone - \else - \dorecurse\scratchcounterone - {\advance\d_tabl_ntb_width\dimexpr - \tabl_ntb_get_wid\scratchcounter - \ifnum\recurselevel<\scratchcounterone - +\d_tabl_ntb_columndistance - +\tabl_ntb_get_dis\scratchcounter - \fi - \relax - \advance\scratchcounter\plusone}% - \fi - % cell - \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged \bgroup - \dotagTABLEsignal % maybe we need to add some packaging in this case - \tabl_ntb_get_txt{#1}{#2}% - \egroup - \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax - % case: nc=maxcolumns - \else - \scratchdimen\tabl_ntb_get_hei{#1}% - \setbox\scratchbox\hpack - {\lower\ht\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}}% - \ht\scratchbox\scratchdimen - \fi - \dp\scratchbox\zeropoint - \edef\scratchmacro{\tabl_ntb_get_ref{#1}{#2}}% - \ifempty\scratchmacro - \box\scratchbox - \else - \normalexpanded{\directgotobox{\box\scratchbox}[\scratchmacro]}% to be checked - \fi - \dostoptagged} % right spot - -\def\tabl_ntb_cell_finalize - {\ifx\localwidth\v!fit - % nothing - \orelse\ifx\localwidth\v!broad - % nothing - \orelse\ifempty\localwidth - % nothing (safeguard) - \else - \tabl_ntb_cell_finalize_indeed - \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_get_max_width - {\scratchdimen\wd\scratchbox\relax} - -% enable dper 2018-02-22 - -\def\tabl_ntb_table_get_max_width_step - {\advance\scratchdimen\tabl_ntb_get_wid\fastloopindex - \advance\scratchdimen\tabl_ntb_get_dis\fastloopindex} - -\def\tabl_ntb_table_get_max_width - {\scratchdimen\zeropoint - \dofastloopcs\c_tabl_ntb_maximum_col\tabl_ntb_table_get_max_width_step - \ifdim\scratchdimen<\wd\scratchbox\relax - \scratchdimen\wd\scratchbox\relax - \fi} - -\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 - % - \tabl_ntb_table_get_max_width % \scratchdimen\scratchbox - % - \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}% - % \orelse\ifdim\wd\scratchbox>\hsize - \orelse\ifdim\scratchdimen>\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 - \orelse\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 - \hsize\scratchdimen\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 - \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_ntb_split_nop - \orelse\ifenableTBLbreak - \tabl_ntb_split_yes - \else - \tabl_ntb_split_nop - \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 - \scratchdimenfour\zeropoint - \scratchdimenfive\dimexpr - \hsize - -\d_tabl_ntb_leftmargindistance - -\d_tabl_ntb_rightmargindistance - +\d_tabl_ntb_columndistance - \relax - \dorecurse\c_tabl_ntb_maximum_col - {\advance\scratchdimenfour\dimexpr - \tabl_ntb_get_wid\recurselevel - \relax - \advance\scratchdimenfive\dimexpr - -\tabl_ntb_get_dis\recurselevel - -\d_tabl_ntb_columndistance - \relax}% - \relax - % distribute width (stretch) - \ifdim\scratchdimenfour<\scratchdimenfive - \advance\scratchdimenfour-\scratchdimenfive - \divide\scratchdimenfour\c_tabl_ntb_maximum_col - \dorecurse\c_tabl_ntb_maximum_col - {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel-\scratchdimenfour\relax}}% - \fi - \fi} - -\def\tabl_ntb_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 - % no \dontleavehmode else too wide, otherwise we get a \hsized box - \else - \registerparoptions % (*) better here (also does a \dontleavehmode) - \ifhmode\else\dontleavehmode\fi - \fi - \box\b_tabl_ntb_final - \afterTABLEbox} - -\def\tabl_ntb_split_yes - {\ifinsidesplitfloat - \donetrue - \orelse\ifinsidefloat - \donefalse - \else - \donetrue - \fi - \ifdone - \expandafter\tabl_ntb_split_box - \else - \expandafter\tabl_ntb_split_nop - \fi} - -\newbox\TABLEsplitbox % public, don't change - -\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox - -\def\tabl_ntb_split_box - {\resettsplit - \c_split_minimum_free_lines\plustwo - \d_split_minimum_free_space\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax - \t_split_before_result{\beforeTABLEsplitbox}% - \t_split_after_result{\afterTABLEsplitbox}% - \t_split_after{\m_tabl_ntb_after_split}% - \t_split_before{\m_tabl_ntb_before_split}% not used (yet) - \setbox\b_split_content\vbox{\tabl_ntb_flush_content}% - \ifmultipleTBLheads - \dorecurse\c_tabl_ntb_n_of_head_lines - {\setbox\scratchbox\vsplit\b_split_content to \lineheight - \setbox\b_split_head\vbox{\unvcopy\b_split_head\unvcopy\scratchbox}}% \vpack ? - \dorecurse\c_tabl_ntb_n_of_next_lines - {\setbox\scratchbox\vsplit\b_split_content to \lineheight - \setbox\b_split_next\vbox{\unvcopy\b_split_next\unvcopy\scratchbox}}% \vpack ? - \fi - \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}% - \ifempty\p_spaceinbetween\else - \blank[\p_spaceinbetween]% - \fi - \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\b_split_result}}% - \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_indeed\zerocount} % 0 = trial run -\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone } % 1 = real run - -\def\tabl_ntb_check_widths_indeed#1% - {\ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths B#1\fi - \scratchcounterone\zerocount - \scratchdimenone\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\scratchdimenone\dimexpr - -\tabl_ntb_get_dis\recurselevel - -\d_tabl_ntb_columndistance - \relax - \ifdim\scratchdimen>\zeropoint\relax - \advance\scratchdimenone -\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\scratchcounterone \plusone - \orelse\ifdim\scratchdimen>\zeropoint\relax - \advance\scratchdimenone -\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\scratchcounterone \plusone % setting maxwidth to a large value also works - \fi - \fi - \fi}% - \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths M#1\fi - \ifcase\scratchcounterone \else \divide\scratchdimenone \scratchcounterone \fi - \dorecurse\c_tabl_ntb_maximum_col - {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax - \ifcase#1\relax - \ifdim\scratchdimen<\scratchdimenone % take natural width - \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}% - \fi - \else - \ifzeropt\scratchdimen % auto set width - \tabl_ntb_set_wid\recurselevel{\the\scratchdimenone}% - \fi - \fi}% - \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths E#1\fi} - -% todo: use scratchcounters, not !! ones - -\def\tabl_ntb_check_heights_one_indeed - {\scratchcountertwo\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax - % check row span - \ifnum\scratchcountertwo>\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 - \scratchcounterthree\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax - \ifnum\scratchcounterthree=\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 - \scratchcounterthree\c_tabl_ntb_current_row_three - \advance\scratchcounterthree\minusone - \dorecurse\scratchcountertwo - {\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=\scratchcountertwo\else - \tabl_ntb_set_nob\scratchcounterthree - \advance\scratchcounterthree\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 \scratchcountertwo - \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\scratchcountertwo - {\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}% - \orelse\ifdim\dimen4>\dimen0 - \iftightTBLrowspan - \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}% - \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#2% - {\begingroup - \scratchdimen\zeropoint - \dorecurse\c_tabl_ntb_maximum_col - {\advance\scratchdimen\tabl_ntb_get_wid\recurselevel\relax}% - \writestatus\m!TABLE{#1 \ifcase#2trial\else real\fi: hsize: \the\hsize, total: \the\scratchdimen}% - \dorecurse\c_tabl_ntb_maximum_col - {\writestatus\m!TABLE{\space\space\recurselevel: \the\dimexpr\tabl_ntb_get_wid\recurselevel}}% - \endgroup} - -\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}} - -\protected\def\tabl_ntb_cell_process_a_extra#1#2% - {\ifcase\tabl_ntb_get_tal{#2}\relax - \expandafter\tabl_ntb_cell_process_x - \else - \expandafter\tabl_ntb_cell_process_a - \fi{#1}{#2}} - -\protected\def\tabl_ntb_cell_process_x#1#2[#3]#4% - {} - -% problem: when span doesn't break we can have a span that is the sum of cells but -% 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}% - \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} - -\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} - -\protected\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 - \anch_backgrounds_text_level_start - \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}% - \anch_backgrounds_text_level_stop - \ifcase\c_anch_backgrounds_text_count\else - \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state - \fi - }% - \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 - \ifzeropt\scratchdimen - % 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}% - \orelse\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 - \setbox\scratchboxone\emptyhbox - \wd\scratchboxone\wd\scratchbox - \ht\scratchboxone\ht\scratchbox - \dp\scratchboxone\dp\scratchbox - \box\scratchboxone - \egroup} - -\protected\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5% - {\setbox\scratchbox\hbox - {\tabl_ntb_setup_cell{#2}{#3}% - \setupcurrentnaturaltablelocal[#4,#1]% - \letnaturaltablelocalparameter\c!background\empty - \letnaturaltablelocalparameter\c!frame\v!off - \inheritednaturaltablelocalframed{\tabl_ntb_cell_start#5\tabl_ntb_cell_stop}}% - \setbox2\emptyhbox % todo: \scratchboxtwo - \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 } - -\protected\def\tabl_ntb_cell_process_b#1#2[#3]#4% - {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax - \ifdim\scratchdimen>\zeropoint\relax - \else - \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}} - -\protected\def\tabl_ntb_cell_process_c - {\tabl_ntb_cell_process_b_c{}} - -\protected\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} - -\protected\def\tabl_ntb_cell_process_e#1#2[#3]#4% - {\tabl_ntb_setup_cell{#1}{#2}% - \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we - \color % handle color here prevents interference due to whatsit nodes - [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence - {\letnaturaltablelocalparameter\c!color\empty - \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}% - \ifzeropt\d_tabl_ntb_height % case: nc=maxcolumns - \else - \setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}% - \fi - \ifcase\c_anch_backgrounds_text_count\else - \edef\p_region{\naturaltablelocalparameter\c!region}% - \ifempty\p_region\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount - \letnaturaltablelocalparameter\c!region\v!yes - \fi\fi - \fi - \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}% - \hskip\tabl_ntb_get_dis{#2}} - -\newtoks\everyresetTABLEyes -\newtoks\everyresetTABLEnop - -\appendtoks - \setupTABLE [% - % - % framed defaults - % - \c!width=\v!fit,% - \c!height=\v!fit,% - \c!lines=,% - \c!offset=.25\exheight,% - \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=\v!frame,% - \c!framecolor=,% - \c!frameoffset=.5\linewidth,% - % \c!backgroundcorner=\framedparameter\c!corner,% - % \c!backgrounddepth=\framedparameter\c!depth,% - % \c!backgroundradius=\framedparameter\c!radius,% - % \c!framecorner=\framedparameter\c!corner,% - % \c!framedepth=\framedparameter\c!depth,% - % \c!frameradius=\framedparameter\c!radius,% - \c!component=,% - \c!region=,% - \c!align=,% - \c!bottom=\vss,% - \c!top=,% - \c!strut=\v!yes,% - \c!autostrut=\v!no,% - \c!location=\v!normal,% - \c!orientation=,% - \c!autowidth=\v!yes,% - \c!setups=,% - \c!loffset=\zeropoint,% - \c!roffset=\zeropoint,% - \c!toffset=\zeropoint,% - \c!boffset=\zeropoint,% - % - % table specific - % - \c!aligncharacter=\v!no,% - \c!alignmentcharacter={,},% - \c!color=,% - \c!columndistance=\zeropoint,% each column (whole table) - \c!distance=\zeropoint,% individual column - \c!headcolor=,% - \c!header=,% - \c!headstyle=\v!bold,% - \c!left=,% - \c!leftmargindistance=\zeropoint,% whole table - \c!maxwidth=8\emwidth,% - \c!option=,% \v!stretch - \c!right=,% - \c!rightmargindistance=\zeropoint,% whole table - \c!spaceinbetween=,% - \c!split=\v!auto,% - \c!splitoffset=\zeropoint,% - \c!style=,% - \c!textwidth=\v!local,% was \hsize - ]% -\to \everyresetTABLEyes - -\appendtoks - \setupTABLE [% - \c!width=\v!fit,% - \c!height=\v!fit% - ]% -\to \everyresetTABLEnop - -\the\everyresetTABLEyes - -% \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 - \the\everyresetTABLEyes - \else - \the\everyresetTABLEnop - \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} - -\permanent\tolerant\protected\def\defineTABLEsetup[#1]#*[#2]% - {\ifarguments\else\setvalue{\??naturaltablesetup#1}{#2}\fi} - -\permanent\let\eTDs\relax -\permanent\let\eTRs\relax - -\permanent\protected\def\bTDs[#1]#2\eTDs - {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD} - -\permanent\protected\def\bTRs[#1]#2\eTRs - {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR} - -\protect \endinput - -% todo: mode: first|next (of niets) diff --git a/tex/context/base/mkiv/tabl-nte.mkxl b/tex/context/base/mkiv/tabl-nte.mkxl deleted file mode 100644 index e79e2a004..000000000 --- a/tex/context/base/mkiv/tabl-nte.mkxl +++ /dev/null @@ -1,107 +0,0 @@ -%D \module -%D [ file=core-nte, -%D version=2009.03.08, -%D title=\CONTEXT\ Table Macros, -%D subtitle=Natural Tables Extensions, -%D author=Hans Hagen \& Wolfgang Schuster, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Table Module / Natural Tables Extensions} - -\unprotect - -%D This module is suggested by Wolfgang Schuster who also prototyped -%D it and came up with the rationale: -%D -%D This module provides an easy way to use natural in a similiar -%D way as the older table module (based on the \TABLE\ macros) and -%D the newer tabulate module. -%D -%D You can see the advantage in the following table, once created -%D with the new macros and once with the normal macros provided -%D with the natural table module. -%D -%D Let us start with the original macros: -%D -%D \startbuffer -%D \bTABLE -%D \bTR -%D \bTD Text 1 \eTD -%D \bTD Text 2 \eTD -%D \eTR -%D \bTR -%D \bTD Text 3 \eTD -%D \bTD Text 4 \eTD -%D \eTR -%D \eTABLE -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D Watch how the new macros use less code: -%D -%D \startbuffer -%D \startTABLE -%D \NC Text 1 \NC Text 2 \NC\NR -%D \NC Text 3 \NC Text 4 \NC\NR -%D \stopTABLE -%D \stopbuffer -%D -%D \typebuffer \getbuffer -%D -%D The actual code differs from the prototype that it does not need -%D to collect whole rows and parse them but looks ahead instead. - -\newconditional\c_tabl_nte_in_nc - -\permanent\tolerant\protected\def\startTABLE[#1]% - {\bgroup - \bTABLE[#1]% - \enforced\let\NC\tabl_nte_start_nc - \enforced\let\NR\tabl_nte_start_nr - \enforced\let\bTR\relax - \enforced\let\bTD\relax - \enforced\let\bTH\relax - \enforced\let\bTN\relax} - -\permanent\protected\def\stopTABLE - {\eTABLE - \egroup} - -\permanent\protected\def\tabl_nte_start_nr - {\eTR - \setfalse\c_tabl_nte_in_nc} - -\permanent\protected\def\tabl_nte_start_nc - {\futurelet\nexttoken\tabl_nte_start_nc_indeed} - -\def\tabl_nte_start_nc_indeed - {\ifx\nexttoken\tabl_nte_start_nr \else - \expandafter\tabl_nte_start_nc_finish - \fi} - -\def\tabl_nte_start_nc_finish#1\NC - {\ifconditional\c_tabl_nte_in_nc \else - \settrue\c_tabl_nte_in_nc - \tabl_ntb_bTR[]% - \fi - \tabl_ntb_bTD#1\eTD\NC} - -%D The related structure commands are also available: - -\permanent\let\stopTABLEhead\relax -\permanent\let\stopTABLEnext\relax -\permanent\let\stopTABLEbody\relax -\permanent\let\stopTABLEfoot\relax - -\permanent\tolerant\protected\def\startTABLEhead[#1]#:#2\stopTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} -\permanent\tolerant\protected\def\startTABLEnext[#1]#:#2\stopTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} -\permanent\tolerant\protected\def\startTABLEbody[#1]#:#2\stopTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} -\permanent\tolerant\protected\def\startTABLEfoot[#1]#:#2\stopTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} - -\protect \endinput diff --git a/tex/context/base/mkiv/tabl-tab.mkxl b/tex/context/base/mkiv/tabl-tab.mkxl deleted file mode 100644 index e6449396c..000000000 --- a/tex/context/base/mkiv/tabl-tab.mkxl +++ /dev/null @@ -1,2230 +0,0 @@ -%D \module -%D [ file=core-tab, -%D version=1997.10.10, -%D title=\CONTEXT\ Table Macros, -%D subtitle=\TABLE\ Embedding, -%D author=Hans Hagen with copied and patched code from MJ Wichura, -%D date=\currentdate] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Table Macros / TaBlE Embedding} - -% Todo: just for the fun of it ... use lmtx features. - -% Todo: a bitmore namespace protection ... although we want to keep some of the -% original flavour. -% -% In \MKIV\ the old table macros are sort of obsolete. The color extensions have -% been removed and some code is stripped. For practical reasons the \TABLE\ macros -% that are used are embedded in this file. -% -% The following code is based on TABLE 1.0 by Michael J. Wichura (August 1988. We -% used a patched version with many overloads and extensions. The documented (and -% larger) source can be found in \type {thrd-tab.tex}. -% -% Some code has been stripped. Some color has been added. Some macros have been -% renamed. Registers have been replaces. And probably much more can be cleaned up. -% We also need to use \tabl_tab_ prefixes here. - -\unprotect - -\newconditional\c_tabl_table_spacing_left -\newconditional\c_tabl_table_spacing_right - -\newdimen \d_tabl_table_line_thickness_unit -\newdimen \d_tabl_table_strut_unit -\newskip \s_tabl_table_inter_column_space_unit -\newdimen \d_tabl_table_column_width_unit -\newdimen \d_tabl_table_kern_unit - -\def\tablestrutheightfactor {8} -\def\tablestrutdepthfactor {3} -\def\tableintercolumnspacefactor {3} -\def\tablecolumnwidthfactor {10} -\def\tablevspacefactor {2} -\def\tablekernfactor {1} -\def\tablelinethicknessfactor {4} - -\newtoks\everytable -\newtoks\everytableparbox - -\protected\def\tabl_table_begin_par_box#1% - {\setbox\scratchbox\vtop\bgroup % \setbox added - \hsize#1\relax - \dontcomplain - \tabl_table_restore_lineskips - \normalbaselines - \enforced\let~\fixedspace - \inhibitblank % \blank[\v!disable]% % added - \the\everytableparbox} - -\protected\def\tabl_table_end_par_box - {\removelastskip % itemize or so - \endgraf - \ifnum\prevgraf>\zerocount % we want at least - \verticalstrut \nowhitespace \vskip-\struttotal % one line of text - \egroup - \ifdim\dp\scratchbox>\lineheight % see (*) for an - \getnoflines{\dp\scratchbox}% % example of where - \dp\scratchbox\zeropoint % saving can go - \setbox\scratchbox % terrible wrong - \vtop to \noflines\lineheight{\box\scratchbox}% - \fi % esp between rows - \else % of paragraphs - \egroup - \fi - \box\scratchbox} - -\appendtoks - \parindent\zeropoint - \raggedright - \rightskip\zeropoint \s!plus 4em \relax -\to \everytableparbox - -\newskip \tablelefttabskip -\newskip \tablerighttabskip - -\newcount\!taColumnNumber -\newcount\!taRecursionLevel % (Initially 0) - -\newdimen\!taDimenA % used by \Enlarge -\newdimen\!taDimenB % used by \Enlarge -\newdimen\!taDimenC % used by numeric.tex -\newdimen\!taMinimumColumnWidth - -\newtoks \!taTableSpread -\newtoks \!taPreamble -\newtoks \!taDataColumnTemplate -\newtoks \!taRuleColumnTemplate -\newtoks \!taOldRuleColumnTemplate -\newtoks \!taLeftGlue -\newtoks \!taRightGlue - -\newskip \!taLastRegularTabskip - -\newif \if!taBeginFormat -\newif \if!taOnceOnlyTabskip - -\def\!thToksEdef#1#2% - {\edef\tempstring{#2}% - #1\expandafter{\tempstring}% - \ignorespaces} - -\def\!thLoop#1\repeat - {\def\!thIterate{#1\expandafter\!thIterate\fi}% - \!thIterate - \let\!thIterate\relax} - -\def\tabl_table_begin_format - {\!taPreamble\emptytoks - \!taColumnNumber\zerocount - \scratchskip\s_tabl_table_inter_column_space_unit - \multiply\scratchskip\tableintercolumnspacefactor - \divide\scratchskip\plustwo - \!taRuleColumnTemplate\expandafter{\expandafter\tabskip\the\scratchskip}% - \!taLastRegularTabskip\scratchskip - \!taOnceOnlyTabskipfalse - \!taBeginFormattrue - \let\!tfRowOfWidths\empty - \doreadtableformatkeys} - -\def\!tfSetWidth - {\ifempty\!tfRowOfWidths % true if no prior "w" keys - \ifnum\!taColumnNumber>\zerocount % true if "w" key is to right of first "|" - \begingroup % RowOfWidths={\aligntab\omit || n copies of \aligntab\omit\aligntab#\omit}, where n = number of column to the left of this one - \scratchcounter\plusone - \aftergroup\edef - \aftergroup\!tfRowOfWidths - \aftergroup{% - \aftergroup\aligntab - \aftergroup\omit - \!thLoop - \ifnum \scratchcounter<\!taColumnNumber - \advance\scratchcounter\plusone - \aftergroup\!tfAOAO - \repeat - \aftergroup}% - \endgroup - \fi - \fi - \ifx[\tempstring % \!tgGetValue sets \tempstring = token after w - \expandafter\!tfSetWidthText - \else - \expandafter\!tfSetWidthValue - \fi} - -\def\!tfAOAO{\aligntab\omit\aligntab\omit} - -\def\!tfSetWidthText[#1]% - {\def\!tfWidthText{#1}% - \doreadtableformatkeys} - -\def\!tfSetWidthValue - {\!taMinimumColumnWidth - \ifnum\!tgCode=\plusone - \ifempty\!tgValue \tablecolumnwidthfactor \else \!tgValue \fi \d_tabl_table_column_width_unit - \else - \!tgValue - \fi - \let\!tfWidthText\empty % Override possible prior `w[sample entry]' - \doreadtableformatkeys} - -\def\!tfSetTabskip - {\ifnum\!tgCode=\plusone - \scratchskip\s_tabl_table_inter_column_space_unit - \multiply\scratchskip \ifempty\!tgValue\tableintercolumnspacefactor\else\!tgValue\fi - \else - \scratchskip\!tgValue - \fi - \divide\scratchskip\plustwo - \ifnum\!taColumnNumber=\zerocount - %\!thToksEdef\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}% - \normalexpanded{\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}}% - \else - %\!thToksEdef\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}% - \normalexpanded{\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}}% - \fi - \if!taOnceOnlyTabskip\else - \!taLastRegularTabskip\scratchskip % Remember this Tabskip, for possible - \fi % restoration after a subsequent"OnceOnly" - \doreadtableformatkeys} - -\def\!tfSetVrule - {\!thToksEdef\!taRuleColumnTemplate - {\hfil - \vrule - \noexpand\s!width - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \c_tabl_table_vrule_thickness_factor - \else - \!tgValue - \fi - \d_tabl_table_line_thickness_unit - \else - \!tgValue - \fi - \alignmark\alignmark\alignmark\alignmark - \hfil - \the\!taRuleColumnTemplate}% - \!tfAdjoinPriorColumn} - -\def\!tfSetAlternateVrule - {\afterassignment\!tfSetAlternateA\scratchtoks} - -\def\!tfSetAlternateA - {\!thToksEdef\!taRuleColumnTemplate{\the\scratchtoks\the\!taRuleColumnTemplate}% - \!tfAdjoinPriorColumn} - -\def\!tfAdjoinPriorColumn - {\ifnum\!taColumnNumber=\zerocount - \!taPreamble=\!taRuleColumnTemplate % New \tabskip may have been added - \else - \ifempty\!tfRowOfWidths\else % no "w" keys specified yet, not even this col - \!tfUpdateRowOfWidths - \fi - \!thToksEdef\!taDataColumnTemplate{\the\!taLeftGlue\the\!taDataColumnTemplate\the\!taRightGlue}% - \!thToksEdef\!taPreamble{\the\!taPreamble\aligntab\the\!taDataColumnTemplate\aligntab\the\!taRuleColumnTemplate}% - \fi - \advance\!taColumnNumber\plusone - \if!taOnceOnlyTabskip - \!thToksEdef\!taDataColumnTemplate{\alignmark\alignmark\alignmark\alignmark\tabskip\the\!taLastRegularTabskip}% - \else - \!taDataColumnTemplate{\alignmark\alignmark}% - \fi - \!taRuleColumnTemplate\emptytoks - \!taLeftGlue{\hfil}% - \!taRightGlue{\hfil}% - \!taMinimumColumnWidth\zeropoint - \let\!tfWidthText\empty - \!taOnceOnlyTabskipfalse - \doreadtableformatkeys} - -\def\!tfUpdateRowOfWidths - {\ifempty\!tfWidthText\else - \!tfComputeMinColWidth - \fi - \edef\!tfRowOfWidths - {\!tfRowOfWidths - \aligntab - \omit - \ifdim \!taMinimumColumnWidth>\zeropoint - \hskip \the\!taMinimumColumnWidth - \fi - \aligntab - \omit}} - -\def\!tfComputeMinColWidth - {\setbox\scratchbox\vbox - {\ialign{% Plain's initialized \halign; \tabskip=0pt \everycr={} - \span\the\!taDataColumnTemplate\cr - \!tfWidthText\cr}}% - \!taMinimumColumnWidth\wd\scratchbox} - -\def\!tfFinishFormat - {\!thToksEdef\!taPreamble{% - \alignmark\alignmark\alignmark\alignmark\tabskip\tablelefttabskip - \aligntab - \the\!taPreamble\tabskip\tablerighttabskip - \aligntab - \alignmark\alignmark\alignmark\alignmark\tabskip\zeropoint\cr} - \!taBeginFormatfalse - \!ttDoHalign} - -\def\tabl_table_reformat[#1]% will become local - {\omit - \!taDataColumnTemplate{\alignmark\alignmark}% - \!taLeftGlue\emptytoks - \!taRightGlue\emptytoks - \begingroup - \tabl_table_use_bar - \expanded{\endgroup\noexpand\doreadtableformatkeys#1]}}% appear in a \tabl_table_reformat cmd; this is here as a safeguard. - -\appendtoks - \enforced\let\ReFormat\tabl_table_reformat -\to \everytable - -\def\!tfEndReFormat - {\!tfReFormat} - -\appendtoks \tabl_table_paralignment \to \everytableparbox - -\def\!tfReFormat#1% - {\the \!taLeftGlue - \vbox{\forgetall\ialign{\span\the\!taDataColumnTemplate\cr#1\cr}}% - \the \!taRightGlue - \kern\zeropoint} % prevents \unskip / really needed - -\def\!tgGetValue#1% - {\def\!tgReturn{#1}% - \futurelet\tempstring\!tgCheckForParen} - -\def\!tgCheckForParen% - {\ifx\tempstring (% - \expandafter \!tgDoParen - \else - \expandafter \!tgCheckForSpace - \fi} - -\def\!tgDoParen(#1)% - {\def\!tgCode{2}% will be expanded - \def\!tgValue{#1}% - \!tgReturn} - -\def\!tgCheckForSpace - {\def\!tgCode{1}% - \let\!tgValue\empty - \ifx\tempstring\!thSpaceToken - \expandafter\!tgReturn - \else - \expandafter\!tgCheckForDigit - \fi} - -\def\!tgCheckForDigit % less tokens: (could be an ifcsname) - {\donetrue - \ifx 0\tempstring \orelse \ifx 1\tempstring \orelse - \ifx 2\tempstring \orelse \ifx 3\tempstring \orelse - \ifx 4\tempstring \orelse \ifx 5\tempstring \orelse - \ifx 6\tempstring \orelse \ifx 7\tempstring \orelse - \ifx 8\tempstring \orelse \ifx 9\tempstring \else - \donefalse - \fi - \ifdone - \expandafter\!tgGetNumber - \else - \expandafter\!tgReturn - \fi} - -% \def\!tgCheckForDigit % does not work -% {\relax\doifnumberelse\tempstring\!tgGetNumber\!tgReturn} - -\def\!tgGetNumber {\afterassignment\!tgGetNumberA\scratchcounter=} -\def\!tgGetNumberA{\edef\!tgValue{\the\scratchcounter}\!tgReturn} - -\def\!tgSetUpParBox - {\normalexpanded - {\noexpand \doreadtableformatkeys - b{\tabl_table_begin_par_box - {\ifnum\!tgCode=\plusone - \ifempty\!tgValue - \tablecolumnwidthfactor - \else - \!tgValue - \fi - \d_tabl_table_column_width_unit - \else - \!tgValue - \fi}}% - a{\tabl_table_end_par_box}}} - -\def\!tgInsertKern - {\edef\tempstring - {\kern - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \tablekernfactor - \else - \!tgValue - \fi - \d_tabl_table_kern_unit - \else - \!tgValue - \fi}% - \edef\tempstring - {\noexpand\doreadtableformatkeys - \ifconditional\c_tabl_table_spacing_left - b{\tempstring} - \fi - \ifconditional\c_tabl_table_spacing_right - a{\tempstring} - \fi}% - \tempstring} - -\def\newtableformatkey #1{\setvalue{!tk<\string#1>}} -\def\doreadtableformatkeys#1{\getvalue{!tk<\string#1>}} - -% Key "b": b{TOKENS} adds TOKENS to the left of (before) the template - -\newtableformatkey b#1% - {\expandafter\!tkJoin\expandafter{\the\!taDataColumnTemplate}{#1}% - \doreadtableformatkeys} - -\def\!tkJoin#1#2% - {\!taDataColumnTemplate{#2#1}}% - -% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template - -\newtableformatkey a#1% - {\toksapp\!taDataColumnTemplate{#1}% - \doreadtableformatkeys} - -% Key "\{": Enclose template in braces. - -\newtableformatkey \{% - {\!taDataColumnTemplate=\expandafter{\expandafter{\the\!taDataColumnTemplate}}% - \doreadtableformatkeys} - -% Key "*": "*{N}{KEY LETTERS}" is equivalent to specifying -% N times. -% KEY LETTERS may contain further * specifications - -\newtableformatkey *#1#2% - {\scratchcounter=#1\relax - \scratchtoks\emptytoks - \!thLoop - \ifnum\scratchcounter>\zerocount - \toksapp\scratchtoks{#2}% - \advance\scratchcounter\minusone - \repeat - \expandafter\doreadtableformatkeys\the\scratchtoks} - -% Key "\LeftGlue": Specifies the glue (usually \hfil, or nothing) to be -% added to extreme left of the template to position a column - -\newtableformatkey \LeftGlue#1% - {\!taLeftGlue{#1}% - \doreadtableformatkeys} - -\newtableformatkey \RightGlue#1% - {\!taRightGlue{#1}% - \doreadtableformatkeys} - -\newtableformatkey c% - {\prependtoks\raggedcenter\to\!taDataColumnTemplate - \doreadtableformatkeys \LeftGlue\hfil \RightGlue\hfil} - -\newtableformatkey l% - {\prependtoks\raggedright\to\!taDataColumnTemplate - \doreadtableformatkeys \LeftGlue\empty \RightGlue\hfil} - -\newtableformatkey r% - {\prependtoks\raggedleft\to\!taDataColumnTemplate - \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} - -\newtableformatkey x% - {\prependtoks\notragged\to\!taDataColumnTemplate - \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} - -% Key "k": Adds kerns to left and right of "#" This key and the two below use Plain -% TeX's \if@h as if it were \if@left, and \if@v as if it were \if@right. Table -% making goes on in a group, so even in the unlikely circumstance that a \phantom -% is currently under construction, there's no problem. - -\newtableformatkey k% - {\settrue\c_tabl_table_spacing_left - \settrue\c_tabl_table_spacing_right - \!tgGetValue{\!tgInsertKern}} - -% Key "i": Adds a kern to the left of "#" - -\newtableformatkey i% - {\settrue\c_tabl_table_spacing_left - \setfalse\c_tabl_table_spacing_right - \!tgGetValue{\!tgInsertKern}} - -% Key "j": Adds a kern to the right of "#" - -\newtableformatkey j% - {\setfalse\c_tabl_table_spacing_left - \settrue\c_tabl_table_spacing_right - \!tgGetValue{\!tgInsertKern}} - -% Key "n": numeric item , non-math mode. - -\newtableformatkey n% - {\def\!tnStyle{}% - \futurelet\!tnext\!tnTestForBracket} - -% Key "N": numeric item, math mode. - -\newtableformatkey N% - {\def\!tnStyle{$}% - \futurelet\!tnext\!tnTestForBracket} - -% Key "m": Math mode. - -\newtableformatkey m% - {\doreadtableformatkeys b{\normalstartimath} a{\normalstopimath}} - -% Key "M": Displaymath mode. - -\newtableformatkey M% - {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}} - -% Key "\m": Template ${}#\hfil$ - -\newtableformatkey \m% - {\doreadtableformatkeys l b{{}} m} - -% Key "\M": Template $\displaystyle{{}#\hfil}$ - -\newtableformatkey \M% - {\doreadtableformatkeys l b{{}} M} - -% Key "f": Set font (E.g., f\it sets up italic font (assuming \it -% has its usual meaning) - -\newtableformatkey f#1% - {\doreadtableformatkeys b{#1}} - -\newtableformatkey B{\doreadtableformatkeys f\bf} % Key "B": abbreviation for f\bf -\newtableformatkey I{\doreadtableformatkeys f\it} % Key "I": abbreviation for f\it -\newtableformatkey S{\doreadtableformatkeys f\sl} % Key "S": abbreviation for f\sl -\newtableformatkey R{\doreadtableformatkeys f\rm} % Key "R": abbreviation for f\rm -\newtableformatkey T{\doreadtableformatkeys f\tt} % Key "T": abbreviation for f\tt - -% Key "p": ParBox - -\newtableformatkey p% - {\!tgGetValue{\!tgSetUpParBox}} - -% Key "w": minimum column width - -\newtableformatkey w% - {\!tkTestForBeginFormat w{\!tgGetValue{\!tfSetWidth}}} - -% Key "s": Set tabskip for the inter-column space to the right of the current -% column, and all subsequent spaces, until overriden by a new "s" or "o" key. - -\newtableformatkey s% - {\!taOnceOnlyTabskipfalse % in case same column has a prior "o" key - \!tkTestForBeginFormat t{\!tgGetValue{\!tfSetTabskip}}} - -% Key "o": Apply the \tabskip stated for this column ONLY to the inter-column space -% just to the right of this column; restore the the previous \tabskip for -% subsequent columns. - -\newtableformatkey o% - {\!taOnceOnlyTabskiptrue - \!tkTestForBeginFormat o{\!tgGetValue{\!tfSetTabskip}}} - -% Key "|": Standard rule column designator - -\newtableformatkey |% - {\!tkTestForBeginFormat |{\!tgGetValue{\!tfSetVrule}}} - -% Key "\|": Non-standard rule column designator - -\newtableformatkey \|% - {\!tkTestForBeginFormat \|{\!tfSetAlternateVrule}} - -% Key ".": PERIOD -- end of \tabl_table_begin_format section. - -\newtableformatkey .% - {\!tkTestForBeginFormat.{\!tfFinishFormat}} - -% Key "\doendtableformat": Equivalent to "." - -\newtableformatkey \doendtableformat - {\!tkTestForBeginFormat\doendtableformat{\!tfFinishFormat}} - -% Key "]": End of \tabl_table_reformat section - -\newtableformatkey ]% - {\!tkTestForReFormat ] \!tfEndReFormat} - -% TEST FOR BEGIN FORMAT{}{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{}{Intended Action}: This test is run on the key "]", -% which can only be used by \tabl_table_reformat. - -\def\!tkTestForReFormat#1#2% - {\if!taBeginFormat - \toks0={#1}% - \toks2=\expandafter{\string\tabl_table_begin_format}% - \expandafter\!tkImproperUse - \else - \def\tempstring{#2}% - \expandafter\tempstring - \fi} - -% NOTE: THE SPACE BETWEEN A NUMERIC ENTRY AND THE FOLLOWING '|', '"', OR '\|' IS -% MANDATORY. EMPTY NUMERIC ENTRIES ARE NOT ALLOWED: USE '{}' OR '\omit' INSTEAD. - -\def\!tnTestForBracket - {\ifx[\!tnext - \expandafter\!tnGetArgument - \else - \expandafter\!tnGetCode - \fi} - -% GET CODE: E.g. "4", or "4.0", "0.4", or "10.2" - -\def\!tnGetCode#1 % - {\!tnConvertCode #1..!} - -% CONVERT CODE: E.g. converts above to [0000], [0000.], [.0000], [0000000000.00] - -\def\!tnConvertCode #1.#2.#3!% - {\begingroup - \aftergroup\edef \aftergroup\tempstring \aftergroup{% - \aftergroup[% - \scratchcounter#1\relax - \!thLoop - \ifnum \scratchcounter>\zerocount - \advance\scratchcounter\minusone - \aftergroup0 - \repeat - \def\tempstring{#3}% - \ifempty\tempstring\else - \aftergroup. - \scratchcounter#2\relax - \!thLoop - \ifnum \scratchcounter>\zerocount - \advance\scratchcounter\minusone - \aftergroup0 - \repeat - \fi - \aftergroup]\aftergroup}% - \endgroup\relax - \expandafter\!tnGetArgument\tempstring} - -% GET ARGUMENT: [ > - -\def\!tnGetArgument[#1]% - {\!tnMakeNumericTemplate\!tnStyle#1..!} - -% MAKE NUMERIC TEMPLATE - -\def\!tnMakeNumericTemplate#1#2.#3.#4!% #1= or $ - {\def\tempstring{#4}% - \ifempty\tempstring - \!taDimenC\zeropoint - \else - \setbox\scratchbox\hbox{\mathsurround\zeropoint #1.#3#1}% - \!taDimenC\wd\scratchbox - \fi - \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% - \!thToksEdef\!taDataColumnTemplate - {\noexpand\!tnSetNumericItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% - \the\!taDataColumnTemplate}% Might have tabskip glue in here - \doreadtableformatkeys} - -% SET NUMERIC ITEM - -\def\!tnSetNumericItem #1#2#3#4 % - {\!tnSetNumericItemA {#1}{#2}{#3}#4..!} - -\def\!tnSetNumericItemA #1#2#3#4.#5.#6!% - {\def\tempstring{#6}% - \hbox to #1{\hss \mathsurround\zeropoint #3#4#3}% - \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint #3.#5#3\fi\hss}} - -% extensions - -\newtableformatkey q% - {\let\!tqStyle\empty - \futurelet\!tnext\!tqTestForBracket} - -\newtableformatkey Q% - {\def\!tqStyle{$}% - \futurelet\!tnext\!tqTestForBracket} - -\def\!tqTestForBracket - {\ifx[\!tnext - \!thx\!tqGetArgument - \else - \!thx\!tqGetCode - \fi} - -\def\!tqGetCode#1 % note the blank - {\!tqConvertCode #1,,!} - -\def\!tqConvertCode #1,#2,#3!% - {\begingroup - \aftergroup\edef - \aftergroup\tempstring - \aftergroup{% - \aftergroup[% - \scratchcounter#1\relax - \!thLoop - \ifnum \scratchcounter>\zerocount - \advance\scratchcounter\minusone - \aftergroup0 - \repeat - \def\tempstring{#3}% - \ifempty\tempstring\else - \aftergroup, - \scratchcounter#2\relax - \!thLoop - \ifnum\scratchcounter>\zerocount - \advance\scratchcounter\minusone - \aftergroup0 - \repeat - \fi - \aftergroup]\aftergroup}% - \endgroup\relax - \!thx\!tqGetArgument\tempstring} - -\def\!tqGetArgument[#1]% - {\!tqMakeQuantityTemplate\!tqStyle#1,,!} - -\def\!tqMakeQuantityTemplate#1#2,#3,#4!% #1= or $ - {\def\tempstring{#4}% - \ifempty\tempstring - \!taDimenC\zeropoint - \else - \setbox\scratchbox\hbox{\mathsurround\zeropoint #1,#3#1}% - \!taDimenC\wd\scratchbox - \fi - \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% - \!thToksEdef\!taDataColumnTemplate - {\noexpand\!tqSetQuantityItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% - \the\!taDataColumnTemplate}% - \doreadtableformatkeys} - -\def\!tqSetQuantityItem #1#2#3#4 % - {\!tqSetQuantityItemA{#1}{#2}{#3}#4,,!} - -\def\!tqSetQuantityItemA #1#2#3#4,#5,#6!% - {\def\tempstring{#6}% - \hbox to #1{\hss\mathsurround\zeropoint#3#4#3}% - \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint#3,#5#3\fi\hss}} - -% \Enlarge -% \enlarge - -\def\tabl_table_Enlarge#1#2% - {% 3rd argument is picked up later - % #1=extra height - % #2=extra depth - \!taDimenA=#1\relax - \!taDimenB=#2\relax - \let\!TsSpaceFactor\empty - \ifmmode - \expandafter\mathpalette - \expandafter\!TsEnlargeMath - \else - \expandafter\!TsEnlargeOther - \fi} - -\def\!TsEnlargeOther#1% - {\ifhmode - \setbox\scratchbox\hbox{#1\xdef\!TsSpaceFactor{\spacefactor\the\spacefactor}}% - \else - \setbox\scratchbox\hbox{#1}% - \fi - \!TsFinishEnlarge} - -\def\!TsEnlargeMath#1#2% - {\setbox\scratchbox\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% - \!TsFinishEnlarge} - -\def\!TsFinishEnlarge - {\ht\scratchbox\dimexpr\ht\scratchbox+\!taDimenA\relax - \dp\scratchbox\dimexpr\dp\scratchbox+\!taDimenB\relax - \box\scratchbox - \!TsSpaceFactor\relax} - -\def\tabl_table_enlarge#1#2% 3rd argument is picked up later - {\tabl_table_Enlarge{#1\d_tabl_table_strut_unit}{#2\d_tabl_table_strut_unit}} - -\appendtoks - \enforced\let\enlarge\tabl_table_enlarge - \enforced\let\Enlarge\tabl_table_Enlarge -\to \everytable - -% BEGIN TABLE - -\let\tabl_table_standard_end\relax - -\def\tabl_table_standard_begin[#1]% \!ttBeginTable (always argument) - {\if#1u% unboxed table - \ifmmode - \let\tabl_table_standard_end\relax % user had better be in display math mode and have only one table at the outer level - \else % user had better be in vertical mode - \bgroup - \let\tabl_table_standard_end\egroup - \fi - \else - \hbox\bgroup - \def\tabl_table_standard_end{\egroup\egroup}% - \if#1t% - \vtop - \orelse\if#1b% - \vbox - \else - \def\tabl_table_standard_end{\egroup\normalstopimath\egroup}% - \scratchtoks\everymath - \everymath\emptytoks - \normalstartimath - \everymath\scratchtoks - \vcenter - \fi - \bgroup % for the \vtop, \vbox, or \vcenter - \fi - \advance\!taRecursionLevel\plusone - \let\!ttRightGlue\relax - \everycr\emptytoks - \ifnum\!taRecursionLevel=\plusone - \the\everytable - \fi} - -\bgroup \catcode\tildeasciicode\activecatcode - - \appendtoks - \catcode\barasciicode\activecatcode - \enforced\protected\def ~{\kern.5em}% - \enforced\protected\def\\{\ifhmode\space\else\par\fi}% - \to \everytable - -\egroup - -\let\!ttRightGlue\relax % This may be changed, in a group, by \JustCenter, etc - -% DO HALIGN: Invoked by END FORMAT (or the key ".") - -\let\tabl_table_restore_lineskips\relax - -\def\!ttDoHalign - {\edef\tabl_table_restore_lineskips - {\baselineskip \the\baselineskip - \lineskiplimit\the\lineskiplimit - \lineskip \the\lineskip - \tabskip \the\tabskip - \relax}% - \baselineskip \zeropoint - \lineskiplimit\zeropoint - \lineskip \zeropoint - \tabskip \zeropoint - \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}% - % we are not in sync so: - \synchronizedisplaydirection - \synchronizeinlinedirection - \halign - \usedirectionparameterreverse\directtablesparameter - \ifempty\p_tabl_table_textwidth \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi - %\the\!taTableSpread - \bgroup - \span - \the\!taPreamble - \ifempty\!tfRowOfWidths\else - \!tfRowOfWidths\cr - \fi} - -% END TABLE - -\def\tabl_table_normal_end - {\egroup % finishes the \halign - \tabl_table_standard_end} % closes off the table envirnoment set up by \tablestandardbegin - -\def\tabl_table_normal_line_ending - {\cr} - -\def\tabl_table_normal_line_format#1#2% - {\vrule - \s!width \zeropoint - \s!height\dimexpr\tablestrutheightfactor\d_tabl_table_strut_unit+#1\d_tabl_table_strut_unit\relax - \s!depth \dimexpr\tablestrutdepthfactor \d_tabl_table_strut_unit+#2\d_tabl_table_strut_unit\relax - \relax - \cr} - -% INSERT VRULE - -\newcount\c_tabl_table_n_of_vrules \c_tabl_table_n_of_vrules\plusone - -\let\m_tabl_table_vrule_color\empty -\let\m_tabl_table_hrule_color\empty - -\def\do!ttInsertVrule - {\vrule\s!width - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \c_tabl_table_vrule_thickness_factor - \else - \!tgValue - \fi - \d_tabl_table_line_thickness_unit - \else - \!tgValue - \fi - \hskip.125\emwidth\relax} - -\def\tabl_table_normal_line_simple_bar - {\unskip\!ttRightGlue\aligntab\aligntab} - -\def\tabl_table_normal_line_complex_bar - {\unskip\!ttRightGlue\aligntab\omit - \hfil - \ifempty\m_tabl_table_vrule_color\else - \switchtocolor[\m_tabl_table_vrule_color]% - \fi - \ifcase\c_tabl_table_n_of_vrules\or - \do!ttInsertVrule - \unskip - \else - \dorecurse\c_tabl_table_n_of_vrules\do!ttInsertVrule - \global\c_tabl_table_n_of_vrules\plusone - \unskip - \fi - \glet\m_tabl_table_vrule_color\empty - \hfil - \aligntab} - -\def\tabl_table_normal_no_bar - {\unskip\!ttRightGlue\aligntab\omit\aligntab} - -\def\tabl_table_normal_single_rule - {\aligntab\tabl_table_normal_long_rule\aligntab} - -\def\tabl_table_normal_multi_rule - {\aligntab\tabl_table_use\c_tabl_table_drule_span\tabl_table_normal_long_rule\aligntab} - -% USE - -\def\tabl_table_use#1% - {\ifnum#1>\plusone - \omit - \global\setfalse\c_tabl_table_is_division % added - \scratchcounter\currenttablecolumn % added - \advance\scratchcounter #1% % added - \advance\scratchcounter \minusone % added - \def\next % added - {\global\advance\currenttablecolumn #1% % added - \global\advance\currenttablecolumn \minusone % added - \scratchcounter#1% - \advance\scratchcounter \minusone - \advance\scratchcounter \scratchcounter - \!thLoop - \ifnum\scratchcounter>\plusone - \spanomit \advance\scratchcounter\minusone - \repeat - \span}% - \else % added - \def\next % conflicts with possible next \omit % added - {\global\advance\currenttablecolumn \plusone}%% added - \fi - \next} % added - -\def\tabl_table_Use#1[% - {\tabl_table_use{#1}% - \tabl_table_reformat[} - -\appendtoks - \enforced\let\use\tabl_table_use - \enforced\let\Use\tabl_table_Use -\to \everytable - -% rules - -\def\tabl_table_normal_full_rule - {\noalign\bgroup - \!ttGetHalfRuleThickness - \scratchdistance\directtablesparameter\c!openup - \ifzeropt\scratchdistance\else\kern\scratchdistance\fi - \hrule\s!height\scratchdimen\s!depth\scratchdimen - \ifzeropt\scratchdistance\else\kern\scratchdistance\fi - \egroup} - -\def\tabl_table_normal_short_rule % was: \!ttShortHrule - {\omit - \!ttGetHalfRuleThickness - \ifempty\m_tabl_table_hrule_color\else - \switchtocolor[\m_tabl_table_hrule_color]% see *DL* - \fi - \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill - \emptyhbox - \ignorespaces} - -\def\tabl_table_normal_long_rule % was: \!ttLongHrule - {\omit\span - \omit\span - \tabl_table_normal_short_rule} - -\def\!ttGetHalfRuleThickness - {\scratchdimen\dimexpr - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \c_tabl_table_hrule_thickness_factor - \else - \!tgValue % user-specified integer - \fi - \d_tabl_table_line_thickness_unit - \else - \!tgValue % user-specified dimension - \fi - \divide\scratchdimen\plustwo} - -% \emptyhbox prevents \unskip - -\def\tabl_table_Left #1{#1\hfill\emptyhbox} -\def\tabl_table_Center#1{\hfill#1\hfill\emptyhbox} -\def\tabl_table_Right #1{\hfill#1} - -\def\tabl_table_OpenUp#1#2% - {\edef\tablestrutheightfactor{\withoutpt\the\dimexpr\tablestrutheightfactor\points+#1\points}% - \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr\tablestrutdepthfactor \points+#2\points}} - -% SetTableToWidth -> textwidth=dimension [to dimension] -% Expand -> textwidth=max [to \hsize] -% WidenTableBy -> [spread #1] -% \tablelefttabskip\zeropoint\s!plus1\s!fill -% \tablerighttabskip\tablelefttabskip -% LongLines -> [spread \hsize] - -\def\tabl_table_JustLeft {\omit\let\!ttRightGlue\hfill} -\def\tabl_table_JustCenter{\omit\hfill\emptyhbox\let\!ttRightGlue\hfill} -\def\tabl_table_JustRight {\omit\hfill\emptyhbox} - -\def\tabl_table_Smash - {\relax - \ifmmode - \expandafter\mathpalette - \expandafter\!thDoMathVCS - \else - \expandafter\!thDoVCS - \fi} - -\def\!thDoVCS#1% - {\setbox\zerocount\hbox{#1}% - \!thFinishVCS} - -\def\!thDoMathVCS#1#2% - {\setbox\zerocount\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% - \!thFinishVCS} - -\def\!thFinishVCS - {\vpack to\zeropoint{\vss\box\zerocount\vss}} - -\def\tabl_table_Raise - {\def\!thSign{+}% - \!tgGetValue\!thSetDimen} - -\def\tabl_table_Lower - {\def\!thSign{-}% - \!tgGetValue\!thSetDimen} - -\def\!thSetDimen - {\ifnum\!tgCode=\plusone - \ifempty\!tgValue - \!taDimenA\tablestrutheightfactor\d_tabl_table_strut_unit - \advance\!taDimenA\tablestrutdepthfactor\d_tabl_table_strut_unit - \divide\!taDimenA\plustwo - \else - \!taDimenA\!tgValue\d_tabl_table_strut_unit - \fi - \else - \!taDimenA\!tgValue - \fi - \!taDimenA\!thSign\!taDimenA\relax - \ifmmode - \expandafter\mathpalette - \expandafter\!thDoMathRaise - \else - \expandafter\!thDoSimpleRaise - \fi} - -\def\!thDoSimpleRaise#1% - {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{#1}}% - \!thFinishRaise} % From Plain TeX: \ht0=0pt \dp0=0pt \box0 - -\def\!thDoMathRaise#1#2% - {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}}% - \!thFinishRaise} - -\def\!thFinishRaise - {\ht\zerocount\zeropoint - \dp\zerocount\zeropoint - \box\zerocount} - -\def\tabl_table_BackSpace - {\!tgGetValue\!thKernBack} - -\def\!thKernBack - {\kern - - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \tablekernfactor - \else - \!tgValue % user-specified integer - \fi - \d_tabl_table_kern_unit - \else - \!tgValue % user-specified dimension - \fi - \ignorespaces} - -\def\tabl_table_Vspace - {\noalign - \bgroup - \!tgGetValue\!thVspace} - -\def\!thVspace - {\vskip - \ifnum\!tgCode=\plusone - \ifempty\!tgValue - \tablevspacefactor - \else - \!tgValue % user-specified integer - \fi - \d_tabl_table_strut_unit - \else - \!tgValue % user-specified skip - \fi - \egroup} % Ends the \noalign - -\appendtoks - \enforced\let\JustLeft \tabl_table_JustLeft - \enforced\let\JustCenter \tabl_table_JustCenter - \enforced\let\JustRight \tabl_table_JustRight - \enforced\let\Smash \tabl_table_Smash - \enforced\let\Raise \tabl_table_Raise - \enforced\let\Lower \tabl_table_Lower - \enforced\let\BackSpace \tabl_table_BackSpace - \enforced\let\Vspace \tabl_table_Vspace - \enforced\let\OpenUp \tabl_table_OpenUp - \enforced\let\TableLeft \tabl_table_Left - \enforced\let\TableCenter\tabl_table_Center - \enforced\let\TableRight \tabl_table_Right -\to \everytable - -%D \macros -%D {inintable, ifsplittables} -%D -%D First we declare some variables. These show a bit what we are dealing with. First -%D we introdoce some booleans that enable us, inside as well as outside this module, -%D to determine in what mode we are. - -\newif\ifintable -\newif\ifsplittables - -%D We show this feature in an example that also shows some of the basic table -%D typesetting commands. -%D -%D \startbuffer -%D \starttable[|||] -%D \HL -%D \VL first \VL second \VL\AR -%D \HL -%D \VL alfa \VL 1 \VL\AR -%D \VL beta \VL 2 \VL\AR -%D \VL gamma \VL 3 \VL\AR -%D \HL -%D \stoptable -%D \stopbuffer -%D -%D \startlinecorrection -%D \getbuffer -%D \stoplinecorrection -%D -%D This table is specified as: -%D -%D \typebuffer -%D -%D This examples shows about the minimum of commands needed to typeset such a table. -%D In this table, the \type {\AR} is automatically translated into the more -%D primitive (but more verbose) commands \type {\SR}, \type {\FR}, \type {\MR} and -%D \type {\LR} commands. -%D -%D \startbuffer -%D \starttables[|||] -%D \HL -%D \VL first \VL second \VL\AR -%D \HL -%D \VL alfa \VL 1 \VL\AR -%D \VL beta \VL 2 \VL\AR -%D \VL gamma \VL 3 \VL\AR -%D \HL -%D \stoptables -%D \stopbuffer -%D -%D \getbuffer -%D -%D Some simple color support is provided: -%D -%D \startbuffer -%D \starttable[|c|c|] -%D \HL -%D \VL test \VL test \VL \SR -%D \HL[green,5] -%D \VL[red] test \VL test \VL \FR -%D \VL test \VL[10,red] test \VL \MR -%D \VL test \VL test \VL[10] \LR -%D \HL -%D \stoptable -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\installcorenamespace{tabletemplate} - -\immutable\def\m!TABLE{TABLE} - -%D We already saw that the table macros report errors and provide automatic spacing. -%D These features can only be implemented by keeping track of the state, often the -%D last command on a row. - -\newconstant\tableforcestate -\newconstant\tableactionstate - -\setnewconstant\tableunknownstate 0 - -\setnewconstant\tableseparaterowstate 1 -\setnewconstant\tablefirstrowstate 2 -\setnewconstant\tablemidrowstate 3 -\setnewconstant\tablelastrowstate 4 -\setnewconstant\tablerulestate 5 -%setnewconstant\tableskipstate 6 -%setnewconstant\tableautorowstate 7 - -\setnewconstant\tableforcefirstrowstate 1 -\setnewconstant\tableforcelastrowstate 2 - -\newconstant\tablerowfactor -\newconstant\TABLEendofrowdepth -\newconstant\TABLEendofrowheight -\newconstant\TABLEcr -\newconstant\tablerowzero -\newconstant\TABLEn - -%D We store these states using \type {constants}'s and like most variables, these -%D are global ones. When needed, especially when we flush the backgrounds, we can -%D temporary disable the assignment. - -\newconditional\tableactionstatepermitted - -\def\tabl_table_set_action#1{\ifconditional\tableactionstatepermitted\global\tableactionstate#1\fi} -\def\tabl_table_set_force #1{\ifconditional\tableactionstatepermitted\global\tableforcestate #1\fi} - -%D To give an impression of what the (well documented) source of \TABLE\ looks like, -%D we first implement an alternative for the numeric keys. The quantity keys -%D (\type{q} and \type{Q}) support the more european way of writing numbers: -%D -%D \startnarrower -%D 100.000.000,00 instead of 100,000,000.00 -%D \stopnarrower -%D -%D The next table shows how to use these keys. We use braces instead of brackets because -%D we need brackets to specify the format. -%D -%D \starttyping -%D \starttable{|q[00,000]|Q[00,00]|} -%D \HL -%D \VL -1,2 \VL 12,35 \VL\FR -%D \VL 11,203 \VL 2,4 \VL\LR -%D \HL -%D \stoptable -%D \stoptyping -%D -%D Although a more efficient implementation is possible |<|we can for instance share -%D common macros|>| we just adapt a copy of the numeric ones. To permit double -%D loading of this module, we check for the existence of one of the macros. -%D -%D To be compatible with the tabulate environment, we also support the \type {l}, -%D \type {c} and \type {r} keys for paragraph entries. -%D -%D All commands that are executed between rows are to be put in \type {\noalign}. We -%D can however not verify if we (that is \TABLE) does or did not enter this mode. A -%D moderate dirty but useful trick is using our own alternative:\footnote{Once one -%D has entered the stage of redefining \TEX\ primitives, such hacks become a second -%D nature. However, redefining \type {\omit} and \type{\span} is not that easy.} - -%D We no longer need this in \LUAMETATEX: -%D -%D \starttyping -%D \aliased\let\tablenoalign \noalign -%D \def\starttablenoalign{\noalign\bgroup} -%D \let\stoptablenoalign \egroup -%D \stoptyping - -%D \macros -%D {starttable} -%D -%D The rest of this module is not easy to comprehend, mainly because we have to take -%D care of: -%D -%D \startitemize[packed] -%D \item \type{\startitemize[template]} -%D \item \type{\startitemize{template}} -%D \item \type{\startitemize[predefined]} -%D \stopitemize -%D -%D as well as: -%D -%D \startitemize[continue] -%D \item restart after table break -%D \stopitemize -%D -%D The official specification of the start command is: -%D -%D \showsetup{starttable} - -\newconditional\c_tabl_table_repeat_head -\newconditional\c_tabl_table_repeat_tail - -\permanent\tolerant\protected\def\starttable[#1]#*[#2]% preamble optional-settings - {\bgroup - \ifarguments\or\or - \setupcurrenttables[#2]% - \fi - \edef\p_tabl_table_split{\directtablesparameter\c!split}% - \edef\p_tabl_table_frame{\directtablesparameter\c!frame}% - \ifx\p_tabl_table_split\v!auto - \ifinsidesplitfloat - \let\p_tabl_table_split\v!yes - \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode - \fi - \fi - \ifx\p_tabl_table_split\v!yes - \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead - \expandafter\starttables - \orelse\ifx\p_tabl_table_split\v!repeat - \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead - \expandafter\starttables - \else - \enforced\let\stoptable\table_table_stop - \ifempty\p_tabl_table_frame - \ifinsidefloat\else\startbaselinecorrection\fi - \else - \startframedcontent[\p_tabl_table_frame]% - \fi - \postponenotes - \expandafter\tabl_table_first_stage - \fi[#1]} - -% We cannot define the stopper as \type {\protected} because lookahead in -% alignments fail then, so we relax it and define it locally. Actually we -% now can. - -\permanent\let\stoptable\relax - -\permanent\def\table_table_stop - {\tabl_tables_chuck_auto_row % before the tail, else noalign problem - \tabl_table_insert_tail - \noalign\bgroup - \glet\tabl_table_head\empty - \glet\tabl_table_tail\empty - \egroup - \tabl_table_finish - \ifempty\p_tabl_table_frame - \ifinsidefloat\else - \stopbaselinecorrection - \goodbreak % compensates all the nobreaks - \fi - \else - \stopframedcontent - \fi - \egroup} - -\permanent\def\table_table_stop_g - {\table_table_stop_s\egroup} - -%D Before we can grab the argument, we have to make sure that the \CATCODES\ are -%D set. The first stage takes care of that. - -\def\tabl_table_first_stage - {\bgroup - \global\intabletrue - \tabl_table_second_stage} - -%D \macros -%D {definetabletemplate} -%D -%D The complex (and main) start macro first takes care of the predefined case. Such -%D a predefined setup looks like: -%D -%D \starttyping -%D \definetabletemplate[test][|||] -%D -%D \starttable[test] -%D \VL test \VL test \VL\AR -%D \VL test \VL test \VL\AR -%D \VL test \VL test \VL\AR -%D \stoptable -%D \stoptyping -%D -%D The implementation of the definition macro is not that complicated: - -\installcorenamespace{tablehead} -\installcorenamespace{tabletail} - -\permanent\protected\def\definetabletemplate % to be redone - {\bgroup - \catcode\barasciicode\othercatcode - \tabl_table_define_template} - -\tolerant\def\tabl_table_define_template[#1]#*[#2]#*[#3]#*[#4]% - {\ifarguments\or\else - \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}% - \fi - \egroup} - -\def\tabl_table_use_template#1#2#3% - {\gdef\tabl_table_head{\begincsname\??tablehead#2\endcsname}% - \gdef\tabl_table_tail{\begincsname\??tabletail#3\endcsname}% - \tabl_table_second_stage[#1]} - -%D The optional third and fourth arguments define which table head and tail to use. -%D -%D \starttyping -%D \definetabletemplate[test][|||][before][after] -%D \stoptyping -%D -%D This also means that one can define table heads and tails by name! -%D -%D \starttyping -%D \starttablehead[before] -%D \HL \VL first \VL second \VL \SR \HL -%D \stoptablehead -%D \stoptyping -%D -%D Templates defined this way get protected names, that cannot conflict with -%D existing commands. -%D -%D \showsetup{definetabletemplate} -%D -%D The second half of the next macro prepares table -%D splitting. - -\def\tabl_table_insert_head - {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometablehead}% - \tabl_table_head - \noalign{\global\setfalse\preventtablebreak}} - -\def\tabl_table_insert_tail - {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometabletail}% - \tabl_table_tail - \noalign{\global\setfalse\preventtablebreak}} - -% \def\doverysimpletableHL % todo -% {\noalign{\normalexpanded{\noexpand\tabl_table_normal_full_rule\m_tabl_table_HLheight}} - -\def\tabl_table_restart_indeed#1% - {\gdef\tabl_table_restart{#1}% - \tabl_table_restart -% \noalign{\globalpushmacro\simpletableHL\glet\simpletableHL\doverysimpletableHL}% - \tabl_table_insert_head - \ifsplittables \ifconditional \c_tabl_table_repeat_tail - \noalign{\goodbreak}% - \tabl_table_insert_tail - \noalign{\goodbreak}% - \fi \fi -% \noalign{\globalpopmacro\simpletableHL}% - } - -\bgroup \catcode\barasciicode\othercatcode - -\gdef\tabl_table_second_stage[#1]% brr nested mess - {\bgroup - \tabl_table_use_bar - \global\setfalse\tableactionstatepermitted - \global\setfalse\hassometablehead - \global\setfalse\hassometabletail - \expanded{\doifelseinstring{|}{#1}} - {\xdef\tabl_table_restart{\noexpand\tabl_table_restart_indeed{\noexpand\tabl_table_third_stage{#1}}}} - {\doifelsedefined{\??tabletemplate#1} - {\gdef\tabl_table_restart{\getvalue{\??tabletemplate#1}}} - {\gdef\tabl_table_restart{\tabl_table_restart_indeed{\getvalue{#1}}}}}% - \egroup - \tabl_table_restart} - -\egroup - -%D The third stage involves a lot of (re)sets, which we will explain later. - -\appendtoks - \fixedspaces - \enforced\let\_\normalunderscore -\to \everytable - -%D Now we can start the table. - -\newtoks\localtabledefinitions - -\def\tabl_table_third_stage#1% - {\global\settrue\tableactionstatepermitted - \tabl_table_set_action\tableunknownstate - \tabl_table_set_force\tableunknownstate - \tabl_table_resetVLvalues - \appendtoks\tabl_table_local_setups\to\everytable - \tabl_table_standard_begin[\ifsplittables u\else b\fi]% - \the\localtabledefinitions - \forgetall % added - \edef\currenttableformat{#1}% - \doifsomething\currenttableformat - {\dogettablenofcolumns\currenttableformat - % more modern is to use catcode tables - \expandafter\tabl_table_begin_format\currenttableformat\doendtableformat}} - -\def\tabl_table_finish - {\tabl_tables_chuck_auto_row - \unskip\crcr - \tabl_table_normal_end - \global\intablefalse - \egroup} - -%D \macros -%D {starttables} -%D -%D Split tables are specified using the plural form of the start and stop commands. -%D -%D \showsetup{starttables} -%D -%D For example: -%D -%D \starttyping -%D \starttables[|||] -%D \HL -%D \VL element \VL atom weight \VL\AR -%D \HL -%D \VL ....... \VL ........... \VL\AR -%D \VL ....... \VL ........... \VL\AR -%D \HL -%D \stoptables -%D \stoptyping - -\newbox\tablecontentbox - -\permanent\protected\def\starttables - {\bgroup - \enforced\let\stoptables\table_table_stop_s - \splittablestrue - \edef\p_tabl_table_split{\directtablesparameter\c!split}% - \ifx\p_tabl_table_split\v!repeat - \settrue\c_tabl_table_repeat_head - \settrue\c_tabl_table_repeat_tail - \else - \setfalse\c_tabl_table_repeat_head - \setfalse\c_tabl_table_repeat_tail - \fi - \flushnotes - \setbox\tablecontentbox\vbox\bgroup - \forgetall - \tabl_table_first_stage} - -\permanent\let\stoptables\relax % needed for \noalign - -\def\table_table_stop_s % not \protected as we need the lookahead (brrr) - {\tabl_tables_chuck_auto_row % AM: before the tail, else noalign problem - \ifconditional\c_tabl_table_repeat_tail\else\tabl_table_insert_tail\fi - \tabl_table_finish - \egroup - \dontcomplain - \tabl_table_split_box\tablecontentbox - \glet\tabl_table_head\empty % new here - \glet\tabl_table_tail\empty % new here - \flushnotes - \egroup} - -\def\tabl_table_split_box#1% - {\resettsplit - \c_split_minimum_free_lines\plustwo - \d_split_minimum_free_space\zeropoint - \setbox\b_split_content\box#1% - \ifconditional\c_tabl_table_repeat_head \ifconditional\hassometablehead - \setbox\b_split_head\vsplit\b_split_content to \lineheight - \setbox\b_split_head\vbox{\unvbox\b_split_head}% \vpack ? - \fi \fi - \ifconditional\c_tabl_table_repeat_tail \ifconditional\hassometabletail - \setbox\b_split_tail\vsplit\b_split_content to \lineheight - \setbox\b_split_tail\vbox{\unvbox\b_split_tail}% \vpack ? - \fi \fi - \ifinsidefloat\else - \t_split_before_result{\startbaselinecorrection}% - \t_split_after_result {\stopbaselinecorrection}% - \fi - \handletsplit} - -%D When the table in the previous example is split across pages, only the first gets -%D a head. We could have said something like: -%D -%D \starttyping -%D \starttablehead -%D \HL -%D \VL element \VL atom weight \VL\AR -%D \HL -%D \stoptablehead -%D -%D \starttabletail -%D \HL -%D \stoptabletail -%D -%D \starttables[|||] -%D \VL ....... \VL ........... \VL\AR -%D \VL ....... \VL ........... \VL\AR -%D \stoptables -%D \stoptyping -%D -%D This time each split table gets a head line and ends with a rule. Keep in mind -%D that such heads also apply to the unbroken ones and should be defined local -%D (grouped) if needed. The rather complicated definition below is due to the fact -%D that the stopcondition is interface language dependant. - -\let\tabl_table_head\empty % needs checking -\let\tabl_table_tail\empty % needs checking - -\letvalue{\e!start\v!tablehead}\relax % todo: frozen, but we use a grabber -\letvalue{\e!stop \v!tablehead}\relax % todo: frozen, but we use a grabber -\letvalue{\e!start\v!tabletail}\relax % todo: frozen, but we use a grabber -\letvalue{\e!stop \v!tabletail}\relax % todo: frozen, but we use a grabber - -%D The second argument is a dummy one, by scanning for it, we get rid of -%D interfering spaces. - -\newconditional\preventtablebreak -\newconditional\hassometablehead -\newconditional\hassometabletail - -% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} -% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} - -\permanent\protected\def\settablehead{\dodoubleempty\tabl_table_set_head} % todo: use pickup -\permanent\protected\def\settabletail{\dodoubleempty\tabl_table_set_tail} % todo: use pickup - -\def\tabl_table_set_head[#1][#2]#3\end - {\gdef\tabl_table_head{\begincsname\??tablehead#1\endcsname}% new - \setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} - -\def\tabl_table_set_tail[#1][#2]#3\end - {\gdef\tabl_table_tail{\begincsname\??tabletail#1\endcsname}% new - \setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} - -\normalexpanded - {\def\csname\e!start\v!tablehead\endcsname#1\csname\e!stop\v!tablehead\endcsname% - {\settablehead#1\noexpand\end}} - -\normalexpanded - {\def\csname\e!start\v!tabletail\endcsname#1\csname\e!stop\v!tabletail\endcsname% - {\settabletail#1\noexpand\end}} - -%D Redundant \type{\HL}'s are removed automatically, so mid||lines can be used -%D without problems. -%D -%D The order of the next macros is more or less random. First we implement error -%D recovery. Errors are reported to the screen and log file as well as visualized in -%D the table in teletype. - -\def\tabl_table_finish_row - {\crcr - \noalign\bgroup - \nobreak - \tabl_table_set_action\tableunknownstate - \glet\tabl_tables_check_auto_row\empty - \glet\tabl_tables_chuck_auto_row\empty - \global\currenttablecolumn\zerocount - \egroup} - -%D Next we enter the more complicated area of column and row switching. I won't go -%D into much detail from now on, but just mention the general principles. -%D -%D \startitemize[3*ruim] -%D \sym{\type{\SR}} end a separate row (between rules) -%D \sym{\type{\FR}} end a first row (after a rule) -%D \sym{\type{\MR}} end a mid row (between text lines) -%D \sym{\type{\LR}} end a last row (before a rule) -%D \stopitemize -%D -%D and best of all: -%D -%D \startitemize[continue] -%D \sym{\type{\AR}} end a row with automatic spacing -%D \stopitemize -%D -%D As far as possible, we report confusing situations. In most cases one can use -%D \type{\AR}, which transfigurates itself into one of the other types. -%D -%D \starttyping -%D \starttable[||] -%D \HL -%D \VL a separate row \VL\SR -%D \HL -%D \VL a first row \VL\FR -%D \VL a mid row \VL\MR -%D \VL a last row \VL\LR -%D \HL -%D \stoptable -%D \stoptyping -%D -%D In this example we could have used \type{\AR} without problems. -%D -%D Color or gray scale backgrounds precede the content. They are passed over -%D horizontal (division) lines when needed. Errors in the color template are traced -%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\ -%D handles alignments, we cannot automate spacing for colored rows and columns. - -\tablerowzero\zerocount - -\appendtoks - \enforced\let\SR\tabl_table_SR - \enforced\let\FR\tabl_table_FR - \enforced\let\MR\tabl_table_MR - \enforced\let\LR\tabl_table_LR - \enforced\let\AR\tabl_table_AR -\to \localtabledefinitions - -\protected\def\tabl_table_SR - {\ifnum\tableactionstate=\tablefirstrowstate - \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% - \orelse\ifnum\tableactionstate=\tablemidrowstate - \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% - \orelse\ifnum\tableactionstate=\tablemidrowstate - \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% - \fi - \tabl_table_end_row_indeed\tableseparaterowstate\tablerowfactor\tablerowfactor} - -\protected\def\tabl_table_FR - {\ifnum\tableactionstate=\tablemidrowstate - \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% - \orelse\ifnum\tableactionstate=\tablelastrowstate - \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% - \fi - \tabl_table_end_row_indeed\tablefirstrowstate\tablerowfactor\tablerowzero} - -\protected\def\tabl_table_MR - {\ifnum\tableactionstate=\tablerulestate - \writestatus\m!TABLE{change \string\MR\space into \string\FR/\string\SR}% - \orelse\ifnum\tableactionstate=\tablelastrowstate - \writestatus\m!TABLE{change \string\MR\space into \string\FR}% - \fi - \tabl_table_end_row_indeed\tablemidrowstate00} - -\protected\def\tabl_table_LR - {\ifnum\tableactionstate=\tablerulestate - \writestatus\m!TABLE{change \string\LR\space into \string\FR/\string\SR}% - \fi - \tabl_table_end_row_indeed\tablelastrowstate\tablerowzero\tablerowfactor} - -%D \macros -%D {ifcheckTABLEcolums} -%D -%D The next macros handle the actual row ending. This macro also take care of space -%D corrections due to table splitting when \type{\MR} and collegues are used. When -%D tracing is enabled, the corrections as well as the values used to determine the -%D available space are shown (in color). By default checking is off. - -\def\tabl_table_end_row_indeed#1#2#3% - {\tabl_table_set_action#1% - \ifcase#1\relax - % unknown - \or - \tabl_tables_end_line\SR\SR\tablerowfactor\tablerowfactor - \or - \tabl_tables_end_line\FR\FR\tablerowfactor\tablerowzero - \or - \ifnum\tableforcestate=\tableforcelastrowstate - \tabl_tables_end_line\MR\LR\tablerowzero\tablerowfactor - \orelse\ifnum\tableforcestate=\tableforcefirstrowstate - \tabl_tables_end_line\MR\FR\tablerowfactor\tablerowzero - \else - \tabl_tables_end_line\MR\MR\tablerowzero\tablerowzero - \fi - \or - \tabl_tables_end_line\LR\LR\tablerowzero\tablerowfactor - \fi - \noalign\bgroup - \tabl_table_set_force\tableunknownstate - \global\currenttablecolumn\zerocount - \ifconditional\preventtablebreak - \nobreak - \else - \goodbreak - \fi - \egroup} - -%D Handling \type{\AR} is postponed till the next row. The check takes care of -%D the first and mid rows, the chuck macro |<|how about that name|>| handles -%D the last row. - -\protected\def\tabl_table_AR - {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed - \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} - -\let\tabl_tables_check_auto_row\empty -\let\tabl_tables_chuck_auto_row\empty - -\def\tabl_tables_check_auto_row_indeed - {\glet\tabl_tables_check_auto_row\empty - \ifnum\tableactionstate=\tablerulestate \FR\orelse - \ifnum\tableactionstate=\tableunknownstate\FR\else - \MR\fi} - -\def\tabl_tables_chuck_auto_row_indeed - {\glet\tabl_tables_check_auto_row\empty - \glet\tabl_tables_chuck_auto_row\empty - \ifnum\tableactionstate=\tablerulestate \SR\orelse - \ifnum\tableactionstate=\tableunknownstate\SR\else - \LR\fi} - -%D When a table is split, we also add a tail and when present we repeat the table -%D head. If a gets split indeed, the spacing before and after a horizontal rule is -%D corrected according to what we expect. - -\def\tabl_tables_end_line#1#2#3#4% - {\ifx#1#2\else - \writestatus\m!TABLE{\string#1\space changed into \string#2}% - \fi - \expandafter\tabl_table_normal_line_format#3#4\crcr % \crcr nodig ? - \noalign{\nobreak\global\settrue\tableactionstatepermitted}} - -%D In order to prevent (as good as possible) alignment overflow and therefore \TEX\ -%D error messages, we check the maximum number of columns. We keep track of the -%D current column and maximum column by means of two \COUNTERS. Keep in mind that -%D the number of \type{|}'s and \type{\VL}'s or alike is always one more than the -%D number of columns. - -\newcount\currenttablecolumn - -% DWhile defining this macro we change the \CATCODE\ of \type{|}. When counting the -% Dbars, we use a non active representation of the bar, simply because we cannot be -% Dsure if the bar is active or not.\footnote{Normally it is, but \TABLE\ changes -% Dthe catcode when needed.} - -\bgroup - \catcode\barasciicode\othercatcode \permanent\gdef\tabl_table_bar{|} - \catcode\barasciicode\activecatcode\gdef\tabl_table_use_bar{\enforced\let|\tabl_table_bar} -\egroup - -\bgroup \catcode\barasciicode\othercatcode - -\gdef\dogettablenofcolumns#1% todo: also divert this to lua as with tabulate - {\bgroup - \cleanupfeatures % needed ! - \tabl_table_use_bar - \egroup} - -\egroup - -%D \startitemize[3*ruim] -%D \sym{\type{\VL}} a vertical line -%D \sym{\type{\VC}} a vertical colored line -%D \sym{\type{\HL}} a horizontal line -%D \sym{\type{\HC}} a horizontal colored line -%D \stopitemize - -\newcount\c_tabl_table_vrule_thickness_factor -\newcount\c_tabl_table_hrule_thickness_factor -\newcount\c_tabl_table_drule_span - -\let\m_tabl_table_vrule_color\empty -\let\m_tabl_table_hrule_color\empty - -\appendtoks - \enforced\let\VL\tabl_table_VL - \enforced\let\VC\tabl_table_VC - \enforced\let\HL\tabl_table_HL - \enforced\let\HC\tabl_table_HC - \enforced\let\VS\tabl_table_VS - \enforced\let\VD\tabl_table_VD - \enforced\let\VT\tabl_table_VT - \enforced\let\VN\tabl_table_VN -\to \localtabledefinitions - -\def\tabl_table_resetVLvalues - {\global\currenttablecolumn\zerocount} - -\def\tabl_table_vrulecommand#1% global assignments - {\doifelsenumber{#1} - {\global\c_tabl_table_vrule_thickness_factor#1\relax - \global\multiply\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax} - {\xdef\m_tabl_table_vrule_color{#1}}} - -\permanent\tolerant\protected\def\tabl_table_VL[#1]% - {\tabl_tables_check_auto_row - \global\advance\currenttablecolumn\plusone - \glet\m_tabl_table_vrule_color\empty - \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax - \iftok{#1}\emptytoks\else - \rawprocesscommalist[#1]\tabl_table_vrulecommand - \fi - \tabl_table_normal_line_complex_bar}% \relax breaks \use - -\permanent\let\tabl_table_VC\tabl_table_VL % for mojca - -% \starttable[|||] -% \HL -% \VL test \VS test \VL \FR -% \VL test \VD test \VL \MR -% \VL test \VT test \VL \LR -% \HL -% \stoptable - -\permanent\protected\def\tabl_table_VS {\VN1} -\permanent\protected\def\tabl_table_VD {\VN2} -\permanent\protected\def\tabl_table_VT {\VN3} -\permanent\protected\def\tabl_table_VN#1{\global\c_tabl_table_n_of_vrules#1\relax\VL} - -\def\tabl_table_hrulecommand#1% global assignments - {\doifelsenumber{#1} - {\global\c_tabl_table_hrule_thickness_factor#1\relax - \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax} - {\xdef\m_tabl_table_hrule_color{#1}}} - -\permanent\tolerant\protected\def\tabl_table_HL[#1]% - {\tabl_tables_chuck_auto_row - \tabl_table_finish_row - \noalign\bgroup - \nobreak - \ifnum\tableactionstate=\tablerulestate - \writestatus\m!TABLE{skipping \string\HL}% \statusmessage - \else - \ifnum\tableactionstate=\tablemidrowstate - \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% - \orelse\ifnum\tableactionstate=\tablefirstrowstate - \writestatus\m!TABLE{change \string\MR\space into \string\SR}% - \fi - \bgroup - \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax - \ifparameter#1\or - \glet\m_tabl_table_hrule_color\empty - \rawprocesscommalist[#1]\tabl_table_hrulecommand - \ifempty\m_tabl_table_hrule_color\else - \switchtocolor[\m_tabl_table_hrule_color]% - \fi - \fi - \tabl_table_normal_full_rule - \egroup - \tabl_table_account_width - \fi - \tabl_table_set_action\tablerulestate - \nobreak - \egroup} - -\aliased\let\tabl_table_HC\tabl_table_HL % for mojca - -%D \startitemize[3*ruim] -%D \sym{\type{\NL}} a vertical skip -%D \sym{\type{\NR}} goto the next row -%D \sym{\type{\NC}} goto the next column -%D \sym{\type{\FC}} a first column -%D \sym{\type{\MC}} a mid column -%D \sym{\type{\LC}} a last column -%D \stopitemize - -% \starttable[|||] -% \VL text \VL text \VL \AR -% \TB[small] -% \VL text \VL text \VL \AR -% \TB[4*big] -% \VL text \VL text \VL \AR -% \stoptable - -% n+1 uitleggen - -\appendtoks - \enforced\let\TB\tabl_table_TB - \enforced\let\NL\tabl_table_NL % old - \enforced\let\NR\tabl_table_NR - \enforced\let\NC\tabl_table_NC - \enforced\let\FC\tabl_table_NC - \enforced\let\MC\tabl_table_NC - \enforced\let\LC\tabl_table_NC -\to \localtabledefinitions - -\permanent\tolerant\protected\def\tabl_table_TB[#1]% - {\tabl_tables_chuck_auto_row - \tabl_table_finish_row - \noalign\bgroup - \blank[\iftok{#1}\emptytoks\directtablesparameter\c!NL\else#1\fi]% - \nobreak - \egroup} - -\aliased\let\tabl_table_NL\tabl_table_TB - -\protected\def\tabl_table_NR - {\global\currenttablecolumn\zerocount - \tabl_table_normal_line_ending - \noalign\bgroup - \nobreak - \tabl_table_set_action\tableunknownstate - \egroup} - -\protected\def\tabl_table_NC - {\tabl_tables_check_auto_row - \global\advance\currenttablecolumn \plusone - \tabl_table_normal_no_bar} - -%D \startitemize[3*broad] -%D \sym{\type{\DL}} -%D \sym{\type{\DV}} (\type{\VD}) -%D \sym{\type{\DC}} -%D \sym{\type{\DR}} -%D \stopitemize - -\newconditional\c_tabl_table_is_division - -\appendtoks - \global\setfalse\c_tabl_table_is_division - \enforced\let\DL\tabl_table_DL - \enforced\let\DC\tabl_table_DC - \enforced\let\DV\tabl_table_DV - \enforced\let\DR\tabl_table_DR -\to \localtabledefinitions - -\def\tabl_table_check_division - {\ifconditional\c_tabl_table_is_division\else - \tabl_tables_chuck_auto_row - \global\currenttablecolumn\zerocount - \global\settrue\c_tabl_table_is_division - \fi} - -\def\tabl_table_drulecommand#1% global assignments - {\doifelsenumber{#1} - {\ifcase\c_tabl_table_drule_span - \global\c_tabl_table_drule_span#1\relax - \else - \global\c_tabl_table_hrule_thickness_factor#1\relax - \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_VLwidth\relax - \fi} - {\xdef\m_tabl_table_hrule_color{#1}}} - -\permanent\tolerant\protected\def\tabl_table_DL[#1]% - {\tabl_table_check_division - \ifnum\tableactionstate=\tablerulestate - \writestatus\m!TABLE{skipping \string\DL}% - \else - \ifnum\tableactionstate=\tablemidrowstate - \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% - \orelse\ifnum\tableactionstate=\tablefirstrowstate - \writestatus\m!TABLE{change \string\MR\space into \string\SR}% - \fi - \tabl_table_set_action\tableunknownstate - \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax - \global\c_tabl_table_drule_span\zerocount - \iftok{#1}\emptytoks\else - \glet\m_tabl_table_hrule_color\empty - \rawprocesscommalist[#1]\tabl_table_drulecommand - % \ifempty\m_tabl_table_hrule_color\else - % \switchtocolor[\m_tabl_table_hrule_color]% see *DL* - % \fi - \fi - \ifcase\c_tabl_table_drule_span - \global\advance\currenttablecolumn \plusone - \tabl_table_normal_single_rule - \or - \global\advance\currenttablecolumn \plustwo - \tabl_table_normal_single_rule - \else - \global\advance\currenttablecolumn \plusone - \tabl_table_normal_multi_rule - \fi - \fi} - -\permanent\protected\def\tabl_table_DV - {\tabl_table_DCV\tabl_table_normal_line_simple_bar} - -\permanent\protected\def\tabl_table_DC - {\tabl_table_DCV\tabl_table_normal_no_bar} - -\permanent\protected\def\tabl_table_DCV#1% - {\tabl_table_check_division - \tabl_tables_check_auto_row - \global\advance\currenttablecolumn \plusone - #1} - -\permanent\protected\def\tabl_table_DR - {\global\currenttablecolumn\zerocount % nog check - \tabl_table_normal_line_ending - \noalign\bgroup - \nobreak - \global\setfalse\c_tabl_table_is_division - \tabl_table_account_width % temporary solution - \tabl_table_set_action\tablerulestate - \egroup} - -\def\tabl_table_account_width - {\scratchdimen\d_tabl_table_line_thickness_unit} - -\permanent\def\tabl_table_TWO {\use\plustwo} -\permanent\def\tabl_table_THREE{\use\plusthree} -\permanent\def\tabl_table_FOUR {\use\plusfour} -\permanent\def\tabl_table_FIVE {\use\plusfive} -\permanent\def\tabl_table_SIX {\use\plussix} - -\appendtoks - \enforced\let\TWO \tabl_table_TWO - \enforced\let\THREE\tabl_table_THREE - \enforced\let\FOUR \tabl_table_FOUR - \enforced\let\FIVE \tabl_table_FIVE - \enforced\let\SIX \tabl_table_SIX - \enforced\let\SPAN \use - \enforced\let\REF \tabl_table_reformat -\to \localtabledefinitions - -\installcorenamespace{tables} -\installcorenamespace{tabledistance} -\installcorenamespace{tablealign} - -\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables - -\setvalue{\??tabledistance\v!none }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} -\setvalue{\??tabledistance\v!small }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} % == baseline -\setvalue{\??tabledistance\v!medium}{\tabl_table_OpenUp11\def\LOW{\Lower7 }} -\setvalue{\??tabledistance\v!big }{\tabl_table_OpenUp22\def\LOW{\Lower8 }} - -\appendtoks - \expandnamespaceparameter\??tabledistance\directtablesparameter\c!distance\v!medium -\to \localtabledefinitions - -\setvalue{\??tablealign\v!right }{\def\tabl_table_paralignment{\raggedright}} -\setvalue{\??tablealign\v!left }{\def\tabl_table_paralignment{\raggedleft}} -\setvalue{\??tablealign\v!middle }{\def\tabl_table_paralignment{\raggedcenter}} -\setvalue{\??tablealign\s!unknown}{\def\tabl_table_paralignment{\notragged}} - -\appendtoks - \doifelse{\directtablesparameter\c!distance}\v!none - {\tablerowfactor\zerocount} - {\tablerowfactor\plustwo }% -\to \localtabledefinitions - -\def\dohandlebar % here ? - {\ifmmode - \expandafter\domathmodebar - \orelse\ifintable - \expandafter\domathmodebar - \else - \expandafter\dotextmodebar - \fi} - -\appendtoks - \expandnamespaceparameter\??tablealign\directtablesparameter\c!align\s!unknown - \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246% - \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246% -\to \everysetuptables - -\def\tabl_table_local_setups - {\directtablesparameter\c!commands\relax - \usebodyfontparameter\directtablesparameter - \d_tabl_table_line_thickness_unit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax - \edef\p_tabl_table_height{\directtablesparameter\c!height}% - \edef\p_tabl_table_depth{\directtablesparameter\c!depth}% - \ifx\p_tabl_table_height\v!strut - \let\tablestrutheightfactor\tablestrutheightfactor - \else - \let\tablestrutheightfactor\p_tabl_table_height - \fi - \ifx\p_tabl_table_depth\v!strut - \let\tablestrutdepthfactor\tablestrutdepthfactor - \else - \let\tablestrutdepthfactor\p_tabl_table_depth - \fi - \edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}% - \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}% - \d_tabl_table_strut_unit \dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont - \d_tabl_table_kern_unit .5em\relax - \s_tabl_table_inter_column_space_unit.5em plus 1fil minus .25em\relax - \d_tabl_table_column_width_unit \d_tabl_table_kern_unit - \d_tabl_table_kern_unit \d_tabl_table_kern_unit} - -%D As one can see, we didn't only add color, but also more control over spacing. -%D -%D \startbuffer[a] -%D \starttable[|c|] -%D \HL -%D \VL \strut test \VL \FR -%D \VL \strut test \VL \MR -%D \VL \strut test \VL \MR -%D \VL \strut test \VL \LR -%D \HL -%D \stoptable -%D \stopbuffer -%D -%D \startbuffer[b] -%D \starttabulate[|c|] -%D \HL -%D \NC test \NC \NR -%D \NC test \NC \NR -%D \NC test \NC \NR -%D \NC test \NC \NR -%D \HL -%D \stoptabulate -%D \stopbuffer -%D -%D In the next example, the first table is defined as: -%D -%D \typebuffer[a] -%D -%D and the second one as: -%D -%D \typebuffer[b] -%D -%D The first table is typeset using the default height and depth factors .8 and .4. -%D The second table has both factors set to \type {strut}, and the third table shows -%D what happens when we set the values to zero. The rightmost table is typeset using -%D the tabulate environment. -%D -%D \startcombination[4*1] -%D {$\vcenter{\getbuffer[a]}$} -%D {\hbox{h=.8 d=.4}} -%D {\setuptables[height=strut,depth=strut]$\vcenter{\getbuffer[a]}$} -%D {\hbox{h=d=\type{strut}}} -%D {\setuptables[height=0,depth=0]$\vcenter{\getbuffer[a]}$} -%D {\hbox{h=d=0}} -%D {$\vcenter{\getbuffer[b]}$} -%D {\hbox{tabulate}} -%D \stopcombination - -\setuptables - [\c!HL=\v!medium, - \c!VL=\v!medium, - \c!NL=\v!small, - \c!frame=, - \c!align=\v!right, - \c!depth=.40, % \v!strut - \c!height=.80, % \v!strut - \c!textwidth=, - \c!rulethickness=\linewidth, - \c!rulecolor=, - \c!distance=\v!medium, - \c!bodyfont=, - \c!commands=, - \c!background=, - \c!backgroundcolor=, - \c!split=\v!auto, - \c!openup=\zeropoint] - -\protect \endinput diff --git a/tex/context/base/mkiv/tabl-tbl.mkxl b/tex/context/base/mkiv/tabl-tbl.mkxl deleted file mode 100644 index 723758fb8..000000000 --- a/tex/context/base/mkiv/tabl-tbl.mkxl +++ /dev/null @@ -1,2929 +0,0 @@ -%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}{} % experiment - -%D I can probably reimplement this using a \LUATEX\ combination but it does not pay -%D of in development time. If I need something else I will write it from scratch -%D anyway. This module looks a bit complex which is a consequence of it dealing with -%D paragraphs being split over pages and that there are several passes over the data -%D set. We can probably do some cleanup (combine/split). -%D -%D Caching the preamble does not save much (compared to other bits and pieces of -%D \CONTEXT). There are not that many ways to deal with preambles and this is just -%D one of them. The keys are 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 skip left of column -% j i skip right of column -% k i 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_every_real_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_max_vrulecolumn -\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_nofrealrows -\newcount \c_tabl_tabulate_autocolor - -\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser -\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count) -\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_kind % 1=strong 2=equals -\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 - -\newtoks \everytabulatepar % where used ? -\newtoks \everytabulate % public ? - -\protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles ! -\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated - -\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty - -\installcorenamespace{tabulatebox} -\installcorenamespace{tabulatesetup} -\installcorenamespace{tabulatehook} -\installcorenamespace{tabulatesplit} -\installcorenamespace{tabulateseparator} -\installcorenamespace{tabulatecolor} -\installcorenamespace{tabulateheader} -\installcorenamespace{tabulatealigning} -\installcorenamespace{tabulatepreamble} -\installcorenamespace{tabulatevrule} - -\installcorenamespace{tabulatehead} -\installcorenamespace{tabulatefoot} -\installcorenamespace{tabulatenext} - -\prependtoks - \global\c_tabl_tabulate_nofrealrows\zerocount -\to \t_tabl_tabulate_initializers_first - -\prependtoks - \global\c_tabl_tabulate_nofrealrows\zerocount -\to \t_tabl_tabulate_initializers_second - -\prependtoks - \global\advance\c_tabl_tabulate_nofrealrows\plusone -\to \t_tabl_tabulate_every_real_row - -\def\b_tabl_tabulate_current#1% - {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym - -\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 - \else - \tabl_tabulate_initialize_box_nop#1% - \fi} - -\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 - -% [|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} - -\installtextracker - {tables.tabulate.breaks} - {\let\tabl_tabulate_break_no_tracer\tabl_tabulate_nobreak_inject_tracer} - {\let\tabl_tabulate_break_no_tracer\donothing} - -\let\tabl_tabulate_break_no_tracer\donothing - -\def\tabl_tabulate_nobreak_inject_indeed - {\tabl_tabulate_break_no - \tabl_tabulate_break_no_tracer} - -\def\tabl_tabulate_nobreak_inject - {\noalign{\tabl_tabulate_nobreak_inject_indeed}} - -\protected\def\tabl_tabulate_hook_check - {\ifnum\c_tabl_tabulate_type<\plustwo - \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop - \else - \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes - \fi} - -\protected\def\tabl_tabulate_setups_check - {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname} - -\protected\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook} -\protected\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi} - -\protected\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 - -\protected\def\tabl_tabulate_check_local_color_first#1#2% - {\relax} - -\protected\def\tabl_tabulate_check_local_color_second#1#2% - {\relax - \ifempty\m_tabl_tabulate_color_local - \xdef\m_tabl_tabulate_color{#1}% - \else - \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local - \glet\m_tabl_tabulate_color_local\empty - \fi - \ifcase\c_tabl_tabulate_localcolorspan - \global\c_tabl_tabulate_colorspan#2\relax - \else - \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan - \global\c_tabl_tabulate_localcolorspan\zerocount - \fi} - -\protected\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} - -\protected\def\tabl_tabulate_check_local_vrule_color_first#1% - {\relax} - -\protected\def\tabl_tabulate_check_local_vrule_color_second#1% - {\relax - \ifempty\m_tabl_tabulate_vrule_color_local - \xdef\m_tabl_tabulate_vrule_color{#1}% - \else - \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local - \glet\m_tabl_tabulate_vrule_color_local\empty - \fi} - -\let\tabl_tabulate_check_local_color \gobbletwoarguments -\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 - -% \protected % we can expand this one -\def\tabl_tabulate_inject_pre_skip#1% - {\ifdim#1>\zeropoint - \kern#1\relax % was \hskip - \orelse\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} - -% \protected % we can expand this one -\def\tabl_tabulate_inject_post_skip#1% - {\ifdim#1>\zeropoint - \kern#1\relax % was \hskip - \orelse\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} - -\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 - \ifempty\m_tabl_tabulate_alignment \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 - \ifempty\m_tabl_tabulate_text_color - \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} - -\protected\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}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}% - \tabl_tabulate_set_preamble} -\installtabulatepreambleoption{g}{\tabl_tabulate_set_align} -\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.} -\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,} -\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span} -\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}% - \tabl_tabulate_set_preamble} -\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble} -\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment} - -%D We no longer deal with \type {~} here but map it onto \type {d} instead. Of -%D course we could prefix a key with \type {\meaning} instead, which works ok (and -%D is needed in order to pseudo expand \type {\next}, but is ugly at the same time. -%D The type {d} stands for digitspace. - -%D \starttyping -%D \installtabulatepreambleoption{~}{...} % see 'd' -%D \stoptyping -%D -%D Also, as there is always a key, we no longer do some after assigment or future -%D let but just pick up the key. - -% \installtabulatepreambleoption \s!unknown % -% {\writestatus{tabulate}{unknown preamble key [\normalmeaning\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} - -% faster but seldom used -% -% \installcorenamespace{tabulatewidth} -% -% \setvalue{\??tabulatewidth\v!fit }{\c_tabl_tabulate_modus\plusthree} -% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak} -% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape} -% -% \def\tabl_tabulate_set_width_step#1% -% {\ifcsname\??tabulatewidth#1\endcsname -% \lastnamedcs -% \else -% \d_tabl_tabulate_width#1\relax -% \fi} -% -% \def\tabl_tabulate_set_width_indeed(#1)% -% {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step -% \ifconditional\c_tabl_tabulate_pwidth_set -% \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth -% \fi -% \tabl_tabulate_set_preamble} -% -\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi} -\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi} -\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi} -\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\orelse\if#1M\plustwo\orelse\if#1R\plusthree\else\zerocount\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 - \glet\m_tabl_tabulate_alignment\empty - \glet\m_tabl_tabulate_color\empty - \glet\m_tabl_tabulate_text_color\empty - \glet\m_tabl_tabulate_vrule_color\empty - \global\c_tabl_tabulate_colorspan\zerocount - \global\setfalse\c_tabl_auto_align_mode - \global\advance\c_tabl_tabulate_columns\plusone - \letcsname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ? - \edef\currenttabulationtrulespec{#1}% - \ifempty\currenttabulationtrulespec - \global\d_tabl_tabulate_vrulethickness\zeropoint - \else - \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default - % the lmtx raw processor handles {} like the normal one so we need to prune - \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command - \fi - \tabl_tabulate_set_preamble#2\relax\relax % permits i without n - \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 - {\glet\m_tabl_tabulate_color\empty - \glet\m_tabl_tabulate_vrule_color\empty - \edef\currenttabulationtrulespec{#1}% - \ifempty\currenttabulationtrulespec - \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} - -\protected\def\tabl_tabulate_hook_nop - {} - -\let\tabl_tabulate_hook\tabl_tabulate_hook_nop - -\def\tabl_tabulate_hook_yes{\begincsname\??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 - \orelse\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} - -\def\tabl_tabulate_pbreak_check - {\noalign\bgroup - \tabl_tabulate_pbreak_inject - \ifconditional\c_tabl_tabulate_splitoff_whitespace - \tabl_tabulate_whitespace - \fi - \egroup} - -%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 Because we want to be compatible we use an indirect way to implement the -%D definers. The next examples demonstrate 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] - -\permanent\tolerant\protected\def\definetabulate[#1]#*[#2]#*[#3]% - {\ifarguments - % ignore - \or - % [tag] - \definetabulation[#1][\c!format={|l|p|},\s!check=]% - \or - % [tag] [template] - \definetabulation[#1][\c!format={#2},\s!check=]% - \or - % [tag] [sub] [template] - \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else - \definetabulation[#1][\c!format={#3},\s!check=]% - \fi - \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]% - \fi} - -\permanent\tolerant\protected\def\setuptabulate[#1]#*[#2]#*[#3]% - {\ifarguments - % ignore - \or - % [tag] - \setuptabulation[#1]% - \or - % [tag] [settings] - \setuptabulation[#1][#2]% - \or - % [tag] [sub] [settings] - \setuptabulation[#1:#2][#3]% - \fi} - -\appendtoks - \enforced\edefcsname\e!start \currenttabulation\endcsname{\tabl_start_defined[\currenttabulation]}% - \enforced\letcsname \e!stop \currenttabulation\endcsname\relax - \enforced\letcsname \??tabulatehead\currenttabulation\endcsname\empty - \enforced\letcsname \??tabulatefoot\currenttabulation\endcsname\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 - {\noalign{\global\settrue\c_tabl_tabulate_someamble}% - \begincsname\??tabulatehead\currenttabulation\endcsname - \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% - -\def\tabl_tabulate_insert_foot_content - {\noalign{\global\settrue\c_tabl_tabulate_someamble}% - \begincsname\??tabulatefoot\currenttabulation\endcsname - \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% - -\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header - {\ifcsname\??tabulatehead\currenttabulation\endcsname - %\expandafter\ifempty\csname\??tabulatehead\currenttabulation\endcsname - \expandafter\ifempty\lastnamedcs - \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\ifempty\csname\??tabulatefoot\currenttabulation\endcsname - %\expandafter\ifempty\lastnamedcs - \let\tabl_tabulate_insert_foot\empty - \else - \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_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 - \noalign{\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 - \noalign{\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]} - -\protected\def\tabl_start_defined[#1]% - {\bgroup - \edef\currenttabulationparent{#1}% - \let\currenttabulation\currenttabulationparent - \iftok{\tabulationparameter\c!format}{\v!none}% - % this is special case: we need to define the generic english - % \starttabulate in other interfaces as well - \lettabulationparameter\c!format\tabl_default_format - \expandafter\tabl_start_regular - \else - \expandafter\tabl_start_defined_indeed - \fi} - -\tolerant\def\tabl_start_defined_indeed[#1]#*[#2]% - {\ifarguments\or - \ifhastok={#1}% - \setuptabulation[\currenttabulation][#1]% - \else - \edef\currenttabulation{\currenttabulation:#1}% - \fi - \else - \edef\currenttabulation{\currenttabulation:#1}% - \setuptabulation[\currenttabulation][#2]% - \fi - \tabl_tabulate_start_building} - -% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one - -\def\tabl_default_format{|l|p|} % actually format is always set - -\permanent\protected\setuvalue{\e!start\v!tabulate}% - {\bgroup % whole thing - \let\currenttabulationparent\empty - \tabl_start_regular} - -\tolerant\protected\def\tabl_start_regular[#1]#*[#2]% [format] | [settings] | [format] [settings] | [settings] [format] - {\let\currenttabulation\currenttabulationparent - \iftok{#1}\emptytoks - \ifhastok={#2}\relax - \setupcurrenttabulation[#2]% - \fi - \orelse\ifhastok={#1} - \ifhastok{#2}\relax - \settabulationparameter\c!format{#2}% - \fi - \setupcurrenttabulation[#1]% - \else - \settabulationparameter\c!format{#1}% - \ifhastok={#2}\relax - \setupcurrenttabulation[#2]% - \fi - \fi - \tabl_tabulate_start_building} - -\letvalue{\e!stop\v!tabulate }\relax -\letvalue{\e!stop\v!tabulatehead}\relax -\letvalue{\e!stop\v!tabulatetail}\relax - -\permanent\protected\def\tabl_tabulate_start_ignore % todo when we go frozen - {\em Nested tabulate is not (yet) supported.\relax - \expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname} - -\appendtoks - \enforced\letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one -\to \everytabulate - -\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split} -\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 - -% \let\tabl_tabulate_inside_before \relax -% \let\tabl_tabulate_inside_after \relax -% \let\tabl_tabulate_inside_inbetween\relax -% -% \def\tabl_tabulate_outside_before -% {\whitespace -% \tabulationparameter\c!before} -% -% \def\tabl_tabulate_outside_after -% {\tabulationparameter\c!after} - -% \showboxes -% -% \startcombination -% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} -% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} -% \stopcombination -% -% \startcombination -% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {} -% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {} -% \stopcombination -% -% \startcombination -% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} -% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} -% \stopcombination - -\let\tabl_tabulate_inside_after \relax -\let\tabl_tabulate_outside_after \relax -\let\tabl_tabulate_inside_inbetween \relax -\let\tabl_tabulate_outside_inbetween\relax - -\protected\def\tabl_tabulate_inside_before - {\ifhmode\par\fi - \ifhmode - \ifinsidesplitfloat - \let\tabl_tabulate_inside_after\relax - \else - \vbox\bgroup - \let\tabl_tabulate_inside_after\egroup - \fi - \else - \let\tabl_tabulate_inside_after\relax - \fi} - -\protected\def\tabl_tabulate_outside_before - {\ifhmode\par\fi - \ifhmode - \vbox\bgroup - \let\tabl_tabulate_outside_after \egroup - \let\tabl_tabulate_outside_inbetween\relax - \orelse\ifinner - \let\tabl_tabulate_outside_after \relax - \let\tabl_tabulate_outside_inbetween\relax - \else - \whitespace - \tabulationparameter\c!before - \relax - \let\tabl_tabulate_outside_after \tabl_tabulate_outside_after_indeed - \let\tabl_tabulate_outside_inbetween\tabl_tabulate_outside_inbetween_indeed - \fi} - -\def\tabl_tabulate_outside_after_indeed - {\tabulationparameter\c!after} - -\def\tabl_tabulate_outside_inbetween_indeed - {\doifempty{\tabulationparameter\c!after} - {\vskip\strutdp - \verticalstrut - \vskip-\struttotal}} - -\def\tabl_tabulate_inside_inbetween % needs checking - {\doifempty{\tabulationparameter\c!after} - {\vskip\strutdp - \verticalstrut - \vskip-\struttotal}} - -\protected\def\tabl_tabulate_start_building - {\ifinsidefloat - \tabl_tabulate_inside_before - \else - \tabl_tabulate_outside_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}% - \edef\p_keeptogether {\tabulationparameter\c!keeptogether}% - \edef\p_blank {\tabulationparameter\c!blank}% - % - \ifx\p_keeptogether\v!no - \settrue \c_tabl_tabulate_tolerant_break - %\setfalse\c_tabl_tabulate_handlepbreak - \else - \setfalse\c_tabl_tabulate_tolerant_break - %\settrue \c_tabl_tabulate_handlepbreak - \fi - % - \settrue\c_tabl_tabulate_split - \begincsname\??tabulatesplit\tabulationparameter\c!split\endcsname - % - \let\m_tabl_tabulate_blank_default\p_blank - % - \d_tabl_tabulate_unit\tabulationparameter\c!unit - \d_tabl_tabulate_margin\tabulationparameter\c!margin - \let\m_tabl_tabulate_vrule_color_default\p_rulecolor - \let\m_tabl_tabulate_hrule_color_default\p_rulecolor - \d_tabl_tabulate_vrulethickness_default\p_rulethickness - \d_tabl_tabulate_hrulethickness_default\p_rulethickness - \ifempty\p_bodyfont\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 % stoptabulate needs to match the frozen one - {\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifempty\currenttabulationparent\v!tabulate\else\currenttabulationparent\fi\fi} - \tabl_tabulate_insert_body - \tabl_tabulate_process} - -\def\tabulateEQ - {\ifconditional\c_tabl_tabulate_firstflushed\else - \dostarttaggedchained\t!ignore\empty\empty - \dostarttagged\t!ignore\empty - \tabulationparameter{EQ}% - \dostoptagged - \dostoptagged - \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 -\let\m_tabl_tabulate_blank_default \empty - -\appendtoks - \glet\m_tabl_tabulate_color_previous \empty - \glet\m_tabl_tabulate_color \empty - \glet\m_tabl_tabulate_text_color \empty - \glet\m_tabl_tabulate_color_local \empty - \glet\m_tabl_tabulate_vrule_color \empty - \glet\m_tabl_tabulate_vrule_color_local \empty - \global \d_tabl_tabulate_vrulethickness_local\zeropoint -\to \t_tabl_tabulate_every_row - -\protected\def\tabl_tabulate_color_side_right_second - {\ifempty\m_tabl_tabulate_color_previous \else - \tabl_tabulate_color_set\m_tabl_tabulate_color_previous - \glet\m_tabl_tabulate_color_previous\empty - \fi} - -\protected\def\tabl_tabulate_color_side_left_second - {\ifempty\m_tabl_tabulate_color \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} - -\protected\def\tabl_tabulate_color_side_both_second - {\ifempty\m_tabl_tabulate_color \else - \tabl_tabulate_color_set\m_tabl_tabulate_color - \ifcase\c_tabl_tabulate_colorspan - %\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 / todo - {\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\zerocount} - -\def\tabl_tabulate_set_color_column_yes#1[#2]% - {\xdef\m_tabl_tabulate_color_local{#2}% - \tabl_tabulate_column_normal\zerocount#1} - -% normal columns: - -\def\tabl_tabulate_column_normal#1#2% - {\unskip - \aligntab - \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi - \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn\else - \tabl_tabulate_column_vrule_setup - \fi - \aligntab - \global\c_tabl_tabulate_kind#1% - \global\c_tabl_tabulate_type#2% - \aligntab} - -% equal columns - -\def\tabl_tabulate_column_equal#1#2% - {\unskip - \aligntab - \tabulateequalpos - \aligntab - \global\c_tabl_tabulate_kind#1% - \global\c_tabl_tabulate_type#2% - \aligntab} - -% ruled columns - -\def\tabl_tabulate_column_vruled_preset - {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default - \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default} - -\def\tabl_tabulate_column_vruled#1#2% - {\unskip % 0-n - %\ifnum\c_tabl_tabulate_column=\plusone - % \global\c_tabl_tabulate_has_rule_spec_first\plusone - %\orelse\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns - % \global\c_tabl_tabulate_has_rule_spec_last\plusone - %\fi - \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn - \global\c_tabl_tabulate_max_vrulecolumn\c_tabl_tabulate_column - \fi - \doifelsefastoptionalcheck{\tabl_tabulate_column_vruled_yes#1#2}{\tabl_tabulate_column_vruled_nop#1#2}} - -\def\tabl_tabulate_column_vrule_setup - {\begincsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname} - -\def\tabl_tabulate_column_vruled_nop - {\global\letcsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname\tabl_tabulate_column_vruled_preset - \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[#3]% - {\global\defcsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname - {\tabl_tabulate_column_vruled_preset - \rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step}% - \tabl_tabulate_column_normal#1#2} - -\def\tabl_tabulate_vrule_reset - {\ifcase\c_tabl_tabulate_max_vrulecolumn\else - \tabl_tabulate_vrule_reset_indeed - \fi} - -\def\tabl_tabulate_vrule_reset_indeed - {\dofastloopcs\c_tabl_tabulate_max_vrulecolumn\tabl_tabulate_vrule_reset_step - \global\c_tabl_tabulate_max_vrulecolumn\zerocount} - -\def\tabl_tabulate_vrule_reset_step % undefined or relax - {\global\letcsname\??tabulatevrule\the\fastloopindex\endcsname\undefined} - -\appendtoks - \tabl_tabulate_vrule_reset -\to \t_tabl_tabulate_every_after_row - -\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} - -\protected\def\tabl_tabulate_column_vrule_inject_first - {\ifcase\d_tabl_tabulate_vrulethickness\else - \tabl_tabulate_column_vruled_normal % could be a skip instead - \fi - \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one - -\protected\def\tabl_tabulate_column_vrule_inject_second - {\ifcase\d_tabl_tabulate_vrulethickness\else - \ifempty\m_tabl_tabulate_vrule_color - \tabl_tabulate_column_vruled_normal - \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\zerocount - \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax - \expandafter\NR - \else - \expandafter\ignorespaces % interferes with the more tricky hooks - \fi} - -\protected\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public) - {\enforced\let#1\tabl_tabulate_column_inject_auto - \enforced\let\\\tabl_tabulate_column_inject_auto} % brrr, will go - -\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount} -\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp} -\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 - \ifempty\p_distance\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_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]% - {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default - \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default - \iftok{#1}\emptytoks\else\rawprocesscommalist[#1]\tabl_tabulate_hrule_preset_step\fi} - -\def\tabl_tabulate_hrule_inject_normal - {\autorule - \s!height.5\d_tabl_tabulate_hrulethickness_local - \s!depth .5\d_tabl_tabulate_hrulethickness_local - \s!left \d_tabl_tabulate_indent - \relax} - -\def\tabl_tabulate_hrule_inject_colored - {\dousecolorparameter\currenttabulationlocalhrulecolor - \tabl_tabulate_hrule_inject_normal} - -\protected\def\tabl_tabulate_hrule_inject_first - {\ifcase\d_tabl_tabulate_hrulethickness_local\else - \tabl_tabulate_hrule_inject_normal - \fi} - -\protected\def\tabl_tabulate_hrule_inject_second - {\ifcase\d_tabl_tabulate_hrulethickness_local\else - \ifempty\currenttabulationlocalhrulecolor - \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 - -\protected\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call - {\begingroup - \clf_enablebackgroundalign % was \node_backgrounds_align_initialize - \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second - \global\settrue\c_tabl_tabulate_has_colors - \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn - \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column - \fi - \global\edefcsname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}% - \hpack \thealignbackgroundcolorattr{#1}{}% pack ? - \endgroup} - -\def\tabl_tabulate_color_repeat_second % for split off lines - {\begingroup - \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly ! - \ifcsname\??tabulatecolor\the\scratchcounter\endcsname - % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ? - \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\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\letcsname\??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_indeed - {\hbox to \d_tabl_tabulate_indent % pack ? - {% we now have a local hsize, and since we want to - % register positional info (i.e. real hsizes) we - % need to reconstitute the original hsize - \advance\hsize\d_tabl_tabulate_indent - % this is indeed rather messy and took a few hours - % to dis/uncover - \the\t_tabl_tabulate_every_row - \hss}} - -\def\tabl_tabulate_flush_indent - {\ifnum\c_tabl_tabulate_column=\zerocount - \tabl_tabulate_flush_indent_indeed - \fi} - -\def\tabl_tabulate_digits{\digits} - -%D Beware, we cannot use \type {\protected} on \type {\HL} cum suis, since \TEX's -%D hard coded noalign lookahead fails on it! I mistakenly added this for a while. - -\setvalue{\??tabulatealigning\v!normal}{0} -\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} - -\protected\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} -\protected\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} -\protected\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} -\protected\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} - -\let\tabl_tabulate_bbskip\relax -\let\tabl_tabulate_eeskip\relax -\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_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 - -\permanent\protected\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount} -\permanent\protected\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount} -\permanent\protected\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone} -\permanent\protected\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo} -\permanent\protected\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount} -\permanent\protected\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone} -\permanent\protected\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo} - -\permanent\protected\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount} -\permanent\protected\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first -\permanent\protected\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake - -\permanent\protected\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row -\permanent\protected\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break - -\permanent\protected\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row -\permanent\protected\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break - -\permanent\protected\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount} -\permanent\protected\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount} -\permanent\protected\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount} -\permanent\protected\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount} - -%D Sort of special: -%D -%D \startbuffer -%D \startitemize[n] -%D \starttabulate[|||||] -%D \NC p \NC \itemtag \NC q \NC r \NC \NR -%D \NC p \NC \itemtag \NC q \NC r \NC \NR -%D \NC p \NC \itemtag \NC q \NC r \NC \NR -%D \NC p \NC \itemtag \NC q \NC r \NC \NR -%D \stoptabulate -%D \stopitemize -%D -%D \startitemize[n] -%D \starttabulate[|||||] -%D \NI b \NC c \NC d \NC \NR -%D \NC a \NI c \NC d \NC \NR -%D \NC a \NC b \NI d \NC \NR -%D \NC a \NC b \NC c \NI \NR -%D \stoptabulate -%D \stopitemize -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\permanent\tolerant\protected\def\tabl_tabulate_NI_first[#1]{\NC\itemtag[#1]\NC} - -%D The following shortcut is handy for tables where one needs bold headers: - -\permanent\protected\def\tabl_tabulate_BC_first - {\tabl_tabulate_column_normal\plusone\zerocount - \let\fontstyle\globalfontstyle - \bf} - -\appendtoks - \enforced\let\VL\tabl_tabulate_VL_first - \enforced\let\NC\tabl_tabulate_NC_first - \enforced\let\BC\tabl_tabulate_BC_first - \enforced\let\RC\tabl_tabulate_RC_first - \enforced\let\HC\tabl_tabulate_HC_first - \enforced\let\EQ\tabl_tabulate_EQ_first - \enforced\let\RQ\tabl_tabulate_RQ_first - \enforced\let\HQ\tabl_tabulate_HQ_first - \enforced\let\NG\tabl_tabulate_NG_first - \enforced\let\NN\tabl_tabulate_NN_first - \enforced\let\ND\tabl_tabulate_ND_first - \enforced\let\NR\tabl_tabulate_NR_first - \enforced\let\NB\tabl_tabulate_NB_first - \enforced\let\CC\tabl_tabulate_CC_first - \enforced\let\CL\tabl_tabulate_CL_first - \enforced\let\CM\tabl_tabulate_CM_first - \enforced\let\CR\tabl_tabulate_CR_first - \enforced\let\NI\tabl_tabulate_NI_first -\to \t_tabl_tabulate_initializers_first - -\appendtoks - \enforced\let\NR\tabl_tabulate_NR_second - \enforced\let\NB\tabl_tabulate_NB_second -\to \t_tabl_tabulate_initializers_second - -\appendtoks - \enforced\let\SR\NR - \enforced\let\FR\NR - \enforced\let\MR\NR - \enforced\let\LR\NR - \enforced\let\AR\NR -\to \t_tabl_tabulate_initializers_first - -\permanent\protected\def\tabl_tabulate_NR_common#1#2% - {\global\advance\c_tabl_tabulate_noflines\plusone - \global\setfalse\c_tabl_tabulate_firstflushed - \global\setfalse\c_tabl_tabulate_equal - \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 - \noalign{\the\t_tabl_tabulate_every_after_row#2}} - -\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 - \orelse\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 - \global\setfalse\c_tabl_tabulate_firstflushed} - -\protected\def\tabl_tabulate_bbskip_second_split_yes - {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column - \ifempty\tabl_tabulate_flush_collected_indeed\else - \setbox0\hbox - \fi - \fi} - -\protected\def\tabl_tabulate_eskip_second - {\par\egroup - \tabl_tabulate_pheight_set - \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes - \tabl_tabulate_splitoff_box} - -\protected\def\tabl_tabulate_bskip_second_split_yes - {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column - % first line - \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox - \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} - -\protected\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip} -\protected\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip} - -\protected\def\tabl_tabulate_flush_second_indeed - {\glet\tabl_tabulate_flush_collected_indeed\empty - \global\c_tabl_tabulate_column\zerocount - \tabl_tabulate_pbreak_check - \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step - \global\settrue\c_tabl_tabulate_firstflushed} - -\protected\def\tabl_tabulate_flush_second_step - {\ifvoid\b_tabl_tabulate_current\fastloopindex\else - \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}% - \fi} - -\def\tabl_tabulate_flush_second - {\noalign{\tabl_tabulate_flush_second_indeed}% - \tabl_tabulate_flush_collected_indeed} - -\protected\def\tabl_tabulate_bskip_second_split_nop - {\vtop\bgroup - \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi - % \begstrut % interferes with pre-\pars - % evt: \appendtoks\begstrut\to\everypar - \ignorespaces} - -\protected\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 - -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_XX_none [#1]{\noalign{\tabl_tabulate_break_state_set}} - -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_FL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_FL_second_indeed}} -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_ML_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_ML_second_indeed}} -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_LL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_LL_second_indeed}} -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_TL_second_indeed}} -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_BL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_BL_second_indeed}} - -\protected\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} - -\def\spac_vspacing_no_topskip % use grouped - {\c_attr_skipcategory\plusten} - -\protected\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} - -\protected\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 - \tabl_tabulate_inside_inbetween - \else - \tabl_tabulate_outside_inbetween - \fi} - -\protected\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} - -\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed - -\permanent\def\tabl_tabulate_HL_second - {\csname - \ifnum\c_tabl_tabulate_noflines=\zerocount F\orelse - \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else - M\fi - L\endcsname} - -\appendtoks - \enforced\let\FL\tabl_tabulate_XX_none - \enforced\let\ML\tabl_tabulate_XX_none - \enforced\let\LL\tabl_tabulate_XX_none - \enforced\let\TL\tabl_tabulate_XX_none - \enforced\let\BL\tabl_tabulate_XX_none - \enforced\let\HL\tabl_tabulate_XX_none - \enforced\let\HR\tabl_tabulate_XX_none -\to \t_tabl_tabulate_initializers_first - -\appendtoks - \enforced\let\FL\tabl_tabulate_FL_second - \enforced\let\ML\tabl_tabulate_ML_second - \enforced\let\LL\tabl_tabulate_LL_second - \enforced\let\TL\tabl_tabulate_TL_second - \enforced\let\BL\tabl_tabulate_BL_second - \enforced\let\HL\tabl_tabulate_HL_second - \enforced\let\HR\tabl_tabulate_HL_second -\to \t_tabl_tabulate_initializers_second - -% \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) - -%D When support for vertical rules we needed a way to pick up the specification for -%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to -%D become more complex and I was not in the mood for messing up the code too much. -%D Therefore from now on the preamble is split by \LUA. There are definitely more -%D places where we can use \LUA\ code (for instance in alignment of numbers. The -%D 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_check_side_float % new per 29-07-2016 - {\ifdefined\page_sides_check_floats_indeed - \page_sides_check_floats_indeed - \ifdim\hangindent>\zeropoint - \advance\d_tabl_tabulate_indent\hangindent - \fi - \fi} - -\def\tabl_tabulate_set_local_hsize - {\setlocalhsize - \hsize\localhsize} - -% test case for pre/post spacing: -% -% \ruledvbox{\starttabulate[|l|] \FL\NC xxx \NC \NR\LL\stoptabulate} -% \ruledvbox{\starttabulate[|l|l|]\FL\NC xxx \NC xxx \NC \NR\LL\stoptabulate} -% \ruledvbox{\starttabulate[|l|] \NC xxx \NC \NR \stoptabulate} -% \ruledvbox{\starttabulate[|lj8|] \NC xxx \NC \NR \stoptabulate} -% \ruledvbox{\starttabulate[|k8|] \NC xxx \NC \NR \stoptabulate} -% \ruledvbox{\starttabulate[|l|l|] \NC xxx \NC xxx \NC \NR \stoptabulate} - -\def\tabl_tabulate_process - {\c_tabl_tabulate_pass\plusone - \tabl_tabulate_check_full_content - \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}% - \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\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 - \orelse\ifinsidefloat - \donefalse - \else - \donetrue - \fi - \global\c_tabl_tabulate_repeathead - \ifdone - \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname - \lastnamedcs - \else - \zerocount - \fi - \else - \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_check_side_float - \tabl_tabulate_set_local_hsize - \fi - \dontcomplain - \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved - \everypar\everytabulatepar - \setbox\scratchbox\vbox % outside \if because of line counting - {\notesenabledfalse - \d_tabl_tabulate_indent\zeropoint - \settrialtypesetting % very important - \anch_backgrounds_text_level_start - \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}% - \anch_backgrounds_text_level_stop - \ifcase\c_anch_backgrounds_text_state\else - \global\settrue\tablehaspositions - \fi - \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-\wd\scratchbox-\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 - \setbox\scratchbox\emptybox % free memory - \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 - \enforced\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\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}% -% \toksapp\everycr{\noalign{\the\t_tabl_tabulate_every_real_row\dostoptagged\dostarttagged\t!tabulaterow\empty}}% - \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}% - \dostoptagged - \dostoptagged - \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 - \tabl_tabulate_inside_after - \else - \tabl_tabulate_outside_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% - \orelse\ifinsidefloat - \unvbox#1% - \else - \tabl_split_box_indeed#1% - \fi} - -\def\tabl_split_box_indeed#1% - {\resettsplit - \c_split_minimum_free_lines\plustwo - \d_split_minimum_free_space\zeropoint - \setbox\b_split_content\box#1% - \ifcase\c_tabl_tabulate_repeathead\or - \setbox\b_split_head\vsplit\b_split_content to \lineheight - \setbox\b_split_head\vbox{\unvbox\b_split_head}% - \or - \setbox\b_split_head\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 - -\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TB[#1]% - {\noalign\bgroup - \unless\iftok{#1}\emptytoks - \blank[#1] - \orelse\ifempty\m_tabl_tabulate_blank_default - \blank - \else - \blank[\m_tabl_tabulate_blank_default]% - \fi - \egroup} - -\appendtoks - \enforced\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 sometimes use the english command in tracing macros. In -%D fact, most detailed tracing macros that are done with \LUA\ only work in the -%D english interface anyway. - -% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here - -\newconditional\c_tabl_generic - -\pushoverloadmode - -\permanent\protected\setuvalue{starttabulate}% - {\bgroup % whole thing - \settrue\c_tabl_generic - \let\currenttabulationparent\empty - \tabl_start_regular} - -\permanent\letvalue{stoptabulate}\relax % testcase cvs-002.tex - -\popoverloadmode - -%D The following helpers are just there because we also have them at the \LUA\ end: -%D -%D \startbuffer -%D \starttabulate[|l|c|r|] -%D \tabulaterow {a,b,c} -%D \tabulaterowbold{aa,bb,cc} -%D \tabulaterowtype{aaa,bbb,ccc} -%D \tabulaterowtyp {aaaa,bbbb,cccc} -%D \stoptabulate -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\def\tabl_tabulate_compact_row#1#2% - {\NC\tabl_tabulate_compact_step#1#2,\end,} - -\def\tabl_tabulate_compact_step#1#2#3,% - {\ifx#2\end - \NR - \expandafter\gobbleoneargument - \else - #1{#2#3}\NC - \expandafter\tabl_tabulate_compact_step - \fi#1} - -\permanent\protected\def\tabulaterow {\tabl_tabulate_compact_row\relax} -\permanent\protected\def\tabulaterowbold{\tabl_tabulate_compact_row\bold} -\permanent\protected\def\tabulaterowtype{\tabl_tabulate_compact_row\type} -\permanent\protected\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ} - -%D Here we plug in a row background feature. As we only have support for -%D \type {frame=name} we can use these variables. -%D -%D \starttyping -%D \startuseMPgraphic{foo} -%D fill unitsquare -%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) -%D randomized ExHeight -%D shifted (-ExHeight/8,ExHeight/16) -%D withcolor RuleColor ; -%D \stopuseMPgraphic -%D -%D \setuptabulate % wel only have frame=name so we can use these: -%D [background=foo, -%D backgroundcolor=darkred, -%D foregroundcolor=white] -%D -%D \definelinefiller[foo][mp=foo,color=darkgreen] -%D \definelinefiller[bar][mp=foo,color=darkred] -%D -%D \starttabulate[|||] -%D \DB foo \BC bar \BC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \stoptabulate -%D -%D \starttabulate[|||] -%D \PB foo \BC bar \BC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \stoptabulate -%D -%D \starttabulate[|||] -%D \FB[bar] foo \BC bar \BC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \stoptabulate -%D -%D \startnarrower -%D \starttabulate[|||] -%D \DB foo \DB bar \BC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \stoptabulate -%D \stopnarrower -%D -%D \starttabulate[|||] -%D \BC foo \BC bar \BC \NR -%D \NL[magenta] foo \NC bar \NC \NR -%D \NL[yellow] foo \NC bar \NC \NR -%D \NL[cyan] foo \NC bar \NC \NR -%D \NL[gray] foo \NC bar \NC \NR -%D \stoptabulate -%D -%D \starttabulate -%D \NL[red] foo \NC bar \NC \NR -%D \NL[green] foo \NL[red] bar \NC \NR -%D \NC foo \NC bar \NC \NR -%D \NL[blue] foo \NC \input tufte \NC \NR -%D \NL[gray] foo \NC bar \NC \NR -%D \NL[yellow] foo \NC bar \NC \NR -%D \stoptabulate -%D \stoptyping - -% \setuptabulate -% [\c!background=, -% \c!backgroundcolor=, -% \c!foregroundcolor=, -% \c!foregroundstyle=] - -\let\m_table_current_row_background \empty -\let\m_table_current_row_background_default \empty -\let\m_table_current_row_background_filler \empty -\let\m_table_current_row_background_defaultfiller\empty -\let\m_table_current_row_background_auto \empty - -\protected\def\tabl_register_row_background#1% - {\xdef\m_table_current_row_background{#1}} - -\protected\def\tabl_register_row_background_filler#1% - {\xdef\m_table_current_row_background_filler{#1}} - -\protected\def\tabl_synchronize_row_background - {\iftrialtypesetting\else - \ifempty\m_table_current_row_background_filler - \ifempty\m_table_current_row_background - % nothing - \tabl_synchronize_row_background_dummy - \else - \tabl_synchronize_row_background_indeed\m_table_current_row_background - \fi - \else - \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler - \fi - \fi} - -\protected\def\tabl_synchronize_row_background_dummy - {\iftrialtypesetting\else - \begingroup - %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint - \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint - \endgroup - \fi} - -\protected\def\tabl_synchronize_row_background_indeed#1% - {\iftrialtypesetting\else - \begingroup - \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata - \dousecolorparameter{#1}% - \setbox\scratchbox\hpack{}% - %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent - \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent - \endgroup - \fi} - -\protected\def\tabl_synchronize_row_background_filler_indeed#1% - {\iftrialtypesetting\else - \begingroup - \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata - \node_linefiller_set{#1}% - \setbox\scratchbox\hpack{}% - %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent - \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent - \endgroup - \fi} - -\appendtoks - \glet\m_table_current_row_background\empty - \glet\m_table_current_row_background_filler\empty - \global\c_tabl_tabulate_nofrealrows\zerocount - \global\c_tabl_tabulate_autocolor\zerocount - \clf_resetbackgroundrowdata -\to \t_tabl_tabulate_initializers_first - -\appendtoks - \glet\m_table_current_row_background\empty - \glet\m_table_current_row_background_filler\empty - \global\c_tabl_tabulate_nofrealrows\zerocount - \global\c_tabl_tabulate_autocolor\zerocount - \clf_resetbackgroundrowdata -\to \t_tabl_tabulate_initializers_second - -\appendtoks - \tabl_synchronize_row_background -\to \t_tabl_tabulate_every_real_row - -\appendtoks - \glet\m_table_current_row_background\empty - \glet\m_table_current_row_background_filler\empty -\to \t_tabl_tabulate_every_after_row - -\permanent\protected\def\tabl_tabulate_NL_first[#1]% - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background{#1}% - \fi - \ignorespaces} - -\pushoverloadmode - - % redefinition needs checking - - \permanent\overloaded\protected\def\tabl_tabulate_ND_first - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background\m_table_current_row_background_default - \fi - \ignorespaces} - -\popoverloadmode - -\permanent\protected\def\tabl_tabulate_LB_first[#1]% - {\tabl_tabulate_column_normal\plusone\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background{#1}% - \fi - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_DB_first - {\tabl_tabulate_column_normal\plusone\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background\m_table_current_row_background_default - \fi - \enforced\let\fontstyle\globalfontstyle - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_NF_first[#1]% - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background_filler{#1}% - \fi - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_NP_first - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background_filler\m_table_current_row_background_default_filler - \fi - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_FB_first[#1]% - {\tabl_tabulate_column_normal\plusone\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background_filler{#1}% - \fi - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_PB_first - {\tabl_tabulate_column_normal\plusone\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background_filler\m_table_current_row_background_default_filler - \fi - \enforced\let\fontstyle\globalfontstyle - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \ignorespaces} - -\pushoverloadmode - - \permanent\overloaded\protected\def\tabl_tabulate_BC_first - {\tabl_tabulate_column_normal\plusone\zerocount - \enforced\let\fontstyle\globalfontstyle - \ifempty\m_table_current_row_background - \ifempty\m_table_current_row_background_filler - \usetabulationstyleandcolor\c!headstyle\c!headcolor - \else - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \fi - \else - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \fi} - -\popoverloadmode - -\permanent\protected\def\tabl_tabulate_A_first - {\global\advance\c_tabl_tabulate_autocolor\plusone - \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% - \ifempty\m_table_current_row_background_auto - \global\c_tabl_tabulate_autocolor\plusone - \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% - \fi - \ifempty\m_table_current_row_background_auto - \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default - \fi - \tabl_register_row_background{\m_table_current_row_background_auto}} - -\permanent\protected\def\tabl_tabulate_NA_first - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \iftrialtypesetting\else - \ifcase\c_tabl_tabulate_column\or - \tabl_tabulate_A_first - \fi - \fi - \ignorespaces} - -\permanent\protected\def\tabl_tabulate_BA_first - {\tabl_tabulate_column_normal\plusone\zerocount\relax - \iftrialtypesetting\else - \ifcase\c_tabl_tabulate_column\or - \tabl_tabulate_A_first - \fi - \fi - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \ignorespaces} - -\appendtoks - \enforced\let\NL\tabl_tabulate_NL_first % NC with Line - \enforced\let\ND\tabl_tabulate_ND_first % NC with Default Line - \enforced\let\LB\tabl_tabulate_LB_first % BC with Line - \enforced\let\DB\tabl_tabulate_DB_first % BC with Default Line - \enforced\let\NF\tabl_tabulate_NF_first % NC with Filler - \enforced\let\NP\tabl_tabulate_NP_first % NC with Predefined Filler - \enforced\let\FB\tabl_tabulate_FB_first % BC with Filler - \enforced\let\PB\tabl_tabulate_PB_first % BC with Predefined Filler - \enforced\let\NA\tabl_tabulate_NA_first % NC with Auto Line - \enforced\let\BA\tabl_tabulate_BA_first % NC with Auto Line -\to \t_tabl_tabulate_initializers_first - -\appendtoks - \edef\m_table_current_row_background_default {\tabulateparameter\c!backgroundcolor}% - \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}% - \let \m_table_current_row_background_auto \empty -\to \everytabulate - -\setuptabulate - [\c!headcolor=, - \c!headstyle=\bf, - \c!backgroundcolor=\tabulationparameter\c!rulecolor, - \c!foregroundcolor=, - \c!foregroundstyle=\tabulationparameter\c!headstyle] - -\protect \endinput diff --git a/tex/context/base/mkiv/tabl-tsp.mkxl b/tex/context/base/mkiv/tabl-tsp.mkxl deleted file mode 100644 index f09a5d9d8..000000000 --- a/tex/context/base/mkiv/tabl-tsp.mkxl +++ /dev/null @@ -1,575 +0,0 @@ -%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 a mkiv cleanup. -%D As it mostly targets at tables the code lives in the tabl and page namespaces. - -% work in progress - -\unprotect - -%D Although the name resembles floats, and therefore this should be a page module, -%D we decided to make it core functionality because the table code depends on it. -%D Othrwise there would be too much overloading afterwards involved. Actually, the -%D float part is rather generic and not that related to floats. - -% \splitfloat [settings] {\placetable[optional args]{test}} {content} - -%D When \type {inbetween} is made empty instead of the default \type {\page}, we -%D will get delayed flushing 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 - -\mutable\let \floatcaptionsuffix \empty - -\permanent\tolerant\protected\def\splitfloat[#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 - -\protected\def\page_split_float_suffix - {\begingroup - \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix - \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits - \endgroup} - -\protected\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}% - \ifempty\p_inbetween - \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=]% - % This controls samepage resetting too but it also messes up the numbering - % so I need another fix. -% \settrialtypesetting - \splitfloatcommand{\hbox to #1{\strut}}% dummy line -% \resettrialtypesetting - \setbox\scratchbox\vbox{\flushlocalfloats}% \vpack ? - \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} - -\permanent\protected\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\b_split_content -\newbox\b_split_result -\newbox\b_split_head -\newbox\b_split_next -\newbox\b_split_tail - -\newtoks\t_split_before_result -\newtoks\t_split_after_result -\newtoks\t_split_before -\newtoks\t_split_inbetween -\newtoks\t_split_after - -\newtoks\everyresettsplit - -\newcount\c_split_minimum_free_lines - -\newdimen\d_split_minimum_free_space -\newdimen\d_split_available_height -\newdimen\d_split_inbetween_height - -\newconditional\c_tabl_split_done -\newconditional\c_tabl_split_head -\newconditional\c_tabl_split_full - -\newconditional\tabl_split_forced_page - -\appendtoks - \c_split_minimum_free_lines\zerocount - \d_split_minimum_free_space\zeropoint - \setbox\b_split_content \emptyvbox - \setbox\b_split_result \emptyvbox - \setbox\b_split_head \emptyvbox - \setbox\b_split_next \emptyvbox - \setbox\b_split_tail \emptyvbox - \t_split_before_result \emptytoks - \t_split_after_result \emptytoks - \t_split_inbetween \emptytoks - \t_split_before \emptytoks - \t_split_after \emptytoks - \let\postprocesstsplit \donothing -\to \everyresettsplit - -\permanent\protected\def\resettsplit - {\the\everyresettsplit} - -\resettsplit - -\def\tsplitdirectwidth{\hsize} - -\protected\def\handletsplit - {\page_split_float_check_caption{\wd\b_split_content}% - \global\setfalse\splitfloatfirstdone - \testpagesync % new, sync, but still tricky - [\number\c_split_minimum_free_lines] - [\dimexpr\d_split_minimum_free_space+\extrasplitfloatlines\lineheight\relax]% - \setbox\scratchbox\vbox{\the\t_split_inbetween}% - \d_split_inbetween_height\htdp\scratchbox - \setfalse\c_tabl_split_done - \doloop\tabl_split_loop_body - \global\setfalse\usesamefloatnumber % new, prevent next increment - \global\setfalse\splitfloatfirstdone} % we can use this one for tests - -\def\tabl_split_loop_body - {\ifinsidecolumns - % brrr, assumes empty columns - \global\setfalse\splitfloatfirstdone - \d_split_available_height\textheight - \settrue\c_tabl_split_full - \else - \ifconditional\splitfloatfirstdone - \d_split_available_height\textheight - \settrue\c_tabl_split_full - \orelse\ifdim\pagegoal<\maxdimen - \d_split_available_height\dimexpr\pagegoal-\pagetotal\relax - \setfalse\c_tabl_split_full - \else - \d_split_available_height\textheight - \settrue\c_tabl_split_full - \fi - \fi - \d_split_available_height \dimexpr - \d_split_available_height - -\d_split_inbetween_height - -\d_split_minimum_free_space - -\extrasplitfloatlines\lineheight - \relax - \ifdim\htdp\b_split_tail>\zeropoint - \advance\d_split_available_height-\htdp\b_split_tail - \fi - \setbox\b_split_result\vbox - {\ifdim\ht\b_split_head>\zeropoint - \unvcopy\b_split_head - \the\t_split_inbetween - \fi}% - \ifconditional\c_tabl_split_done \else - \ifdim\ht\b_split_next>\zeropoint - \setbox\b_split_head\box\b_split_next - \fi - \fi - \settrue\c_tabl_split_done - \ifdim\ht\b_split_result>\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\b_split_content to \onepoint % \lineheight - \setbox\scratchbox\vbox % \vpack - {\unvbox\scratchbox - \setbox\scratchbox\vbox % \vpack - {\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\b_split_result\vbox - {\unvbox\b_split_result - \the\t_split_inbetween - \unvbox\scratchbox}% - \exitloop - \orelse\ifdim\dimexpr\d_split_available_height-\htdp\scratchbox-\htdp\b_split_result\relax>\zeropoint - \setbox\b_split_result\vbox - {\unvbox\b_split_result - \the\t_split_inbetween - \unvbox\scratchbox}% - \ifvoid\b_split_content \exitloop \fi - \orelse\ifconditional\c_tabl_split_head - % we only have a tablehead so far - \setbox\b_split_result\vbox{\unvbox\b_split_result\unvbox\scratchbox}% \vpack - \exitloop - \orelse\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\b_split_result\vbox - {\unvbox\b_split_result - \the\t_split_inbetween - \unvbox\scratchbox}% - \exitloop - \else - \setbox\b_split_content\vbox - {\unvbox\scratchbox - \the\t_split_inbetween - \ifvoid\b_split_content\else\unvbox\b_split_content\fi}% - \exitloop - \fi - \setfalse\c_tabl_split_head - \setfalse\c_tabl_split_full}% - \postprocesstsplit - \page_split_float_check_content\b_split_content - \ifvoid\b_split_content - \setbox\b_split_result\vbox - {\unvbox\b_split_result - \the\t_split_inbetween - \unvcopy\b_split_tail}% - \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% - \doifnotinsidesplitfloat{\the\t_split_after}% - \endgraf - \exitloop - \else - % hack - \ifdim\pagegoal<\maxdimen - \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex - \fi - % brrr - \ifdim\ht\b_split_result>\zeropoint - \setbox\b_split_result\vbox - {\unvbox\b_split_result - \the\t_split_inbetween - \unvcopy\b_split_tail}% - \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% - \doifnotinsidesplitfloat{\the\t_split_after}% - \endgraf - \global\settrue\usesamefloatnumber % new, prevent next increment - \fi - \ifinsidecolumns - \goodbreak % was \doifnotinsidesplitfloat\goodbreak - \else - \page % was \doifnotinsidesplitfloat\page - \fi - \fi} - -%D The next one assumes that the split takes place elsewhere. This is used in -%D xtables. - -\aliased\let\resetdirecttsplit\resettsplit - -\permanent\protected\def\handledirecttsplit - {\page_split_float_check_caption{\tsplitdirectwidth}% - \global\setfalse\splitfloatfirstdone - \testpagesync % new, sync, but still tricky - [\number\c_split_minimum_free_lines] - [\dimexpr\d_split_minimum_free_space+\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_split_available_height\textheight - \orelse\ifconditional\splitfloatfirstdone - \d_split_available_height\textheight - \orelse\ifdim\pagegoal<\maxdimen - \d_split_available_height\dimexpr\pagegoal-\pagetotal\relax - \else - \d_split_available_height\textheight - \fi - \d_split_available_height\dimexpr - \d_split_available_height - -\d_split_minimum_free_space - -\extrasplitfloatlines\lineheight - \relax - \tsplitdirectsplitter\d_split_available_height % also sets state - \ifdim\ht\b_split_result>\zeropoint - \ifconditional\somenextsplitofffloat - \global\setfalse\onlyonesplitofffloat - \fi - \ifdim\pagegoal<\maxdimen - \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex - \fi - \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% - \global\settrue\usesamefloatnumber % new, prevent next increment - \endgraf - \ifconditional\somenextsplitofffloat - \ifinsidecolumns - \goodbreak - \else - \page - \fi - \fi - \global\settrue\splitfloatfirstdone - \orelse\ifconditional\somenextsplitofffloat - \ifinsidecolumns - \goodbreak - \else - \page % no room - \fi - \else - \exitloop - \fi} - -%D Maybe handy: -%D -%D \starttyping -%D \splitfloat -%D {\placefigure{some caption}} -%D {\startsplittext -%D \typefile[option=TEX,before=,after=]{oeps.tex} -%D \stopsplittext} -%D \stoptyping - -\permanent\def\handlesplittext#1% - {\setbox\b_split_result\vbox - {\vsplit\b_split_content to \dimexpr#1-\lineheight\relax}} - -\permanent\protected\def\startsplittext - {\begingroup - \resettsplit - \c_split_minimum_free_lines\zerocount - \d_split_minimum_free_space\zeropoint - \let\extrasplitfloatlines \!!plusone - \let\tsplitdirectsplitter \handlesplittext - \setbox\b_split_content\vbox\bgroup - \insidefloattrue} - -\permanent\protected\def\stopsplittext - {\egroup - \handledirecttsplit - \endgroup} - -\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/tex/context/base/mkiv/tabl-xnt.mklx b/tex/context/base/mkiv/tabl-xnt.mklx deleted file mode 100644 index f2a41c500..000000000 --- a/tex/context/base/mkiv/tabl-xnt.mklx +++ /dev/null @@ -1,142 +0,0 @@ -% macros=mkvi - -%D \module -%D [ file=tabl-xtb, -%D version=2011.10.28, -%D title=\CONTEXT\ Table Macros, -%D subtitle=Natural to Xtreme Tables, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Table Macros / Natural to Xtreme Tables} - -\unprotect - -%D Don't expect wonders but it might come in handy: -%D -%D \starttyping -%D \mapTABLEtoxtable -%D \restoreTABLEfromxtable -%D \stoptyping -%D -%D We stick to a simple example: -%D -%D \startbuffer -%D \bTABLE -%D \bTR -%D \bTD[width=1cm,background=color,backgroundcolor=red] one \eTD -%D \bTD[width=2cm] two \eTD -%D \eTR -%D \bTR -%D \bTD alpha \eTD -%D \bTD beta \eTD -%D \eTR -%D \eTABLE -%D \stopbuffer -%D -%D \typebuffer -%D -%D \startbuffer -%D \startlinecorrection -%D \getbuffer -%D \stoplinecorrection -%D -%D \startlinecorrection -%D \mapTABLEtoxtable \getbuffer -%D \stoplinecorrection -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\pushoverloadmode % this file is runtime loaded - -\overloaded\permanent\let\tabl_x_normal_bTABLEhead\bTABLEhead -\overloaded\permanent\let\tabl_x_normal_eTABLEhead\eTABLEhead -\overloaded\permanent\let\tabl_x_normal_bTABLEnext\bTABLEnext -\overloaded\permanent\let\tabl_x_normal_eTABLEnext\eTABLEnext -\overloaded\permanent\let\tabl_x_normal_bTABLEfoot\bTABLEfoot -\overloaded\permanent\let\tabl_x_normal_eTABLEfoot\eTABLEfoot -\overloaded\permanent\let\tabl_x_normal_bTABLEbody\bTABLEbody -\overloaded\permanent\let\tabl_x_normal_eTABLEbody\eTABLEbody -\overloaded\permanent\let\tabl_x_normal_bTR \bTR -\overloaded\permanent\let\tabl_x_normal_eTR \eTR -\overloaded\permanent\let\tabl_x_normal_bTD \bTD -\overloaded\permanent\let\tabl_x_normal_eTD \eTD -\overloaded\permanent\let\tabl_x_normal_bTH \bTH -\overloaded\permanent\let\tabl_x_normal_eTH \eTH -\overloaded\permanent\let\tabl_x_normal_setupTABLE\setupTABLE -\overloaded\permanent\let\tabl_x_normal_bTABLE \bTABLE -\overloaded\permanent\let\tabl_x_normal_eTABLE \eTABLE - -\permanent\protected\def\restoreTABLEfromxtable - {\enforced\let\bTABLEhead\tabl_x_normal_bTABLEhead - \enforced\let\eTABLEhead\tabl_x_normal_eTABLEhead - \enforced\let\bTABLEnext\tabl_x_normal_bTABLEnext - \enforced\let\eTABLEnext\tabl_x_normal_eTABLEnext - \enforced\let\bTABLEfoot\tabl_x_normal_bTABLEfoot - \enforced\let\eTABLEfoot\tabl_x_normal_eTABLEfoot - \enforced\let\bTABLEbody\tabl_x_normal_bTABLEbody - \enforced\let\eTABLEbody\tabl_x_normal_eTABLEbody - \enforced\let\bTR \tabl_x_normal_bTR - \enforced\let\eTR \tabl_x_normal_eTR - \enforced\let\bTD \tabl_x_normal_bTD - \enforced\let\eTD \tabl_x_normal_eTD - \enforced\let\bTH \tabl_x_normal_bTH - \enforced\let\eTH \tabl_x_normal_eTH - \enforced\let\setupTABLE\tabl_x_normal_setupTABLE - \enforced\let\bTABLE \tabl_x_normal_bTABLE - \enforced\let\eTABLE \tabl_x_normal_eTABLE} - -\permanent\protected\def\mapTABLEtoxtable - {\enforced\let\bTABLEhead\startxtablehead - \enforced\let\eTABLEhead\stopxtablehead - \enforced\let\bTABLEnext\startxtablefoot - \enforced\let\eTABLEnext\stopxtablefoot - \enforced\let\bTABLEfoot\startxtablefoot - \enforced\let\eTABLEfoot\stopxtablefoot - \enforced\let\bTABLEbody\startxtablebody - \enforced\let\eTABLEbody\stopxtablebody - \enforced\let\bTR \startxrow - \enforced\let\eTR \stopxrow - \enforced\let\bTD \startxcell - \enforced\let\eTD \stopxcell - \enforced\let\bTH \tabl_x_TABLE_TH_start_cell - \enforced\let\eTH \tabl_x_TABLE_TH_stop_cell - \enforced\let\setupTABLE\tabl_x_TABLE_setup - \enforced\let\bTABLE \tabl_x_TABLE_start - \enforced\let\eTABLE \tabl_x_TABLE_stop} - -\popoverloadmode - -\permanent\protected\def\tabl_x_TABLE_TH_start_cell - {\startxcellgroup[\c!foregroundstyle=\v!bold]% - \startxcell} - -\permanent\protected\def\tabl_x_TABLE_TH_stop_cell - {\stopxcell - \stopxcellgroup} - -\permanent\protected\tolerant\def\tabl_x_TABLE_setup[#settings]% - {\ifarguments\or - %\ifparameter#1\or - \setupxtable[#settings]% - \fi} - -\permanent\protected\tolerant\def\tabl_x_TABLE_start[#settings]% - {\bgroup - \ifarguments\or - %\ifparameter#1\or - \tabl_x_prepare{#settings}% - \fi - \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% - \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process\zerocount} - -\permanent\protected\def\tabl_x_TABLE_stop - {\stopxtable} - -\protect \endinput diff --git a/tex/context/base/mkiv/tabl-xtb.mklx b/tex/context/base/mkiv/tabl-xtb.mklx deleted file mode 100644 index 906355d42..000000000 --- a/tex/context/base/mkiv/tabl-xtb.mklx +++ /dev/null @@ -1,976 +0,0 @@ -% macros=mkvi - -%D \module -%D [ file=tabl-xtb, -%D version=2011.10.26, -%D title=\CONTEXT\ Table Macros, -%D subtitle=Xtreme, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Table Macros / Xtreme} - -\registerctxluafile{tabl-xtb}{} - -% todo: -% -% - yes or no: foregroundstyle/color <- style/color -% - template alignment -% - maybe split horizontal (a la linetables) -% - before/after and wrapping (linecorrection) -% - maybe also some before/after commands -% - maybe correction when non float usage -% - tagging needs to be checked -% - maybe only tag the box -% - scale to fit -% -% - buffers permit verbatim but are not always handy - -%D This module started as an afternoon experiment and surprisingly could be -%D mostly finished the same evening. Of course it builds upon existing -%D functionality. The main reason for writing it is that we occasionally -%D run into pretty large tables that take tens of pages and need to be split -%D into floats. Speed is one issue there, avoiding to use vsplit is another. -%D -%D \starttyping -%D \definextable [tag] | [tag][parent] -%D \setupxtable [settings] | [tag][settings] -%D -%D \startxtable[tag|settings] -%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot -%D \startxrowgroup[tag|settings] -%D \startxrow[settings] -%D \startxcellgroup[tag|settings] -%D \startxcell[settings] ... \stopxcell -%D \stopxcellgroup -%D \stopxrow -%D \startxrowgroup -%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot -%D \stopxtable -%D \stoptyping -%D -%D See xtables-001.tex etc for some examples. - -% We can avoid some checking by using the fastoptionalcheckcs helpers -% instead of dosingleempty but the speed gain is neglectable. - -\unprotect - -% option=stretch : equal distribution -% option={stretch,width} : proportional distribution -% option={max} : prefer max over forced width/height -% -% cells: option=fixed : nils autostretch (not yet complete) - -% \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged {...} - -\aliased\let\dotagxtablecell \relax % names will change -\aliased\let\dotagxtablesignal\relax % names will change - -\appendtoks - \enforced\permanent\protected\def\dotagxtablecell - {\clf_settagtablecell - \numexpr\tablecellrows\relax - \numexpr\tablecellcolumns\relax - \numexpr\raggedstatus\relax}% - \enforced\permanent\protected\def\dotagxtablesignal - {\signalcharacter}% not used -\to \everyenableelements - -\newdimen\d_tabl_x_width -\newdimen\d_tabl_x_height -\newdimen\d_tabl_x_depth % not used -\newdimen\d_tabl_x_distance -\newcount\c_tabl_x_nx -\newcount\c_tabl_x_ny -\newcount\c_tabl_x_mode -\newbox \b_tabl_x -\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft -\newdimen\d_tabl_x_final_width -\newcount\c_tabl_x_nesting -\newcount\c_tabl_x_skip_mode % 1 = skip -\newdimen\d_tabl_x_textwidth -\newcount\c_tabl_x_swapped -\newcount\c_tabl_x_swapped_max - -\let\m_tabl_x_swapped_settings\empty - -\aliased\let\currentxtablerow \clf_x_table_r -\aliased\let\currentxtablecolumn\clf_x_table_c - -% \setupxtable[one][parent][a=b,c=d] -% \setupxtable[one] [a=b,c=d] -% \setupxtable [a=b,c=d] - -\installcorenamespace{xtable} -\installcorenamespace{xtablecheck} -\installcorenamespace{xtableswap} - -\installframedautocommandhandler \??xtable {xtable} \??xtable - -\appendtoks - \checkxtableparent % so we can deal with undefined settings, not that it's efficient -\to \everysetupxtable - -\setupxtable[% - \c!nr=\plusone, - \c!nc=\plusone, - \c!nx=\plusone, % slow - \c!ny=\plusone, % slow - \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE - \c!frameoffset=.5\linewidth, - \c!backgroundoffset=\v!frame, - % \c!framecolor=\s!black, - % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere - % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere - % \c!bodyfont=, - \c!width=\v!fit, - \c!height=\v!fit, - \c!maxwidth=8\emwidth, - \c!autowidth=\v!yes, % controls framed - \c!rulethickness=\linewidth, - \c!strut=\v!yes, - \c!autostrut=\v!no, - \c!split=\v!auto, % a number will take that many lines - \c!splitoffset=\zeropoint, % extra space taken - \c!aligncharacter=\v!no, - \c!alignmentcharacter={,}, - \c!alignmentleftsample=, - \c!alignmentrightsample=, - \c!alignmentleftwidth=\zeropoint, - \c!alignmentrightwidth=\zeropoint, - % \c!option=, % \v!stretch {\v!stretch,\v!width} - % \c!footer=, - % \c!header=, - \c!spaceinbetween=, - \c!textwidth=\v!local, % was \hsize, - \c!textheight=\vsize, % used for vertical spread - \c!distance=\zeropoint, % individual column - \c!columndistance=\zeropoint, % each column (whole table) - \c!leftmargindistance=\zeropoint, % whole table - \c!rightmargindistance=\zeropoint,% whole table -] - -\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting} -\let\tabl_x_current_buffer\empty - -\permanent\protected\def\startxtable{\tabl_x_start_table} - -\protected\tolerant\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings] - {\bgroup - \tabl_x_prepare{#settings}% - \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% - \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process\zerocount} - -% \permanent\protected\aliased\startxtable\tabl_x_start_table - -\aliased\permanent\let\stopxtable\relax - -% These direct buffers can be somewhat faster but it's probably neglectable. -% Anyway, no nesting is supported as we then need to catch (e.g.) rows and keep -% track of nesting and have a more complex redefinition of nested instanced -% \unknown\ it's not worth the trouble. Only use them when you really need them and -% use the embeddedxtable command when nesting them. Implementing nesting would be -% slower than not using direct buffers. - -\permanent\tolerant\protected\def\processxtablebuffer[#name]% - {\bgroup - \let\tabl_x_start_table\tabl_x_process_buffer - \edef\tabl_x_current_buffer{#name}% - \tabl_x_get_buffer % settings - \tabl_x_process} - -\protected\tolerant\def\tabl_x_start_ignore[#settings]% - {} - -\protected\tolerant\def\tabl_x_process_buffer[#settings]% - {\tabl_x_prepare{#settings}% - \let\tabl_x_start_table\tabl_x_start_ignore - \gobbleuntil\stopxtable} % nested xtables are not supported, - -%D A bonus: you have to use the following construct inside a macro or -%D direct buffer. - -\permanent\tolerant\protected\def\startembeddedxtable[#settings]#:#content\stopembeddedxtable - {\tabl_x_prepare{#settings}% - \clf_assignbuffer{embedded_x_table}{\detokenize{#content}}\catcodetable\relax - \bgroup - \let\tabl_x_start_table\tabl_x_process_buffer - \edef\tabl_x_current_buffer{embedded_x_table}% - \tabl_x_process} - -\aliased\permanent\let\stopembeddedxtable\relax - -%D We can also define xtables. - -\appendtoks - \permanent\setuevalue{\e!start\currentxtable}{\tabl_x_start_named[\currentxtable]}% - \permanent\setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}% -\to \everydefinextable - -\protected\def\tabl_x_start_named[#tag]#spacer[#settings]% - {\bgroup - \edef\currentxtable{#tag}% - \advance\c_tabl_x_nesting\plusone - \dostarttaggedchained\t!table\empty\??xtable - \setupcurrentxtable[#settings]% - \tabl_x_check_textwidth - %\forgetall % else whitespace mess - \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% - \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process\zerocount}} - -\protected\def\tabl_x_stop_named - {} - -%D Now we come to processing: - -\protected\def\tabl_x_check_textwidth - {\edef\p_textwidth{\xtableparameter\c!textwidth}% - \ifx\p_textwidth\v!local - \d_tabl_x_textwidth\availablehsize - \else - \d_tabl_x_textwidth\p_textwidth - \fi} - -\newtoks\everypreparextable - -\protected\def\tabl_x_prepare#settings% - {\advance\c_tabl_x_nesting\plusone - \dostarttaggedchained\t!table\empty\??xtable - \tabl_x_set_checked{#settings}% - \tabl_x_check_textwidth - \the\everypreparextable - }% else whitespace mess - -\def\tabl_x_get_buffer - {\clf_gettexbuffer{\tabl_x_current_buffer}} - -\let\tabl_x_start_row_yes \relax -\let\tabl_x_start_row_nop \relax -\let\tabl_x_stop_row \relax -\let\tabl_x_start_cell_yes\relax -\let\tabl_x_start_cell_nop\relax -\let\tabl_x_stop_cell \relax - -\newtoks\t_table_x_cleanup - -\protected\def\tabl_x_process - {\begingroup % * - \forgetall % moved here - \dontcomplain % for the moment here till we figure out where we get the overflow - \usebodyfontparameter\xtableparameter - \setbox\scratchbox\vbox - {\doifsomething{\xtableparameter\c!spaceinbetween}{\blank[\xtableparameter\c!spaceinbetween]}}% - \clf_x_table_create - option {\xtableparameter\c!option}% - textwidth \d_tabl_x_textwidth - textheight \dimexpr\xtableparameter\c!textheight\relax - maxwidth \dimexpr\xtableparameter\c!maxwidth\relax - lineheight \openlineheight - columndistance \dimexpr\xtableparameter\c!columndistance\relax - leftmargindistance \dimexpr\xtableparameter\c!leftmargindistance\relax - rightmargindistance \dimexpr\xtableparameter\c!rightmargindistance\relax - rowdistance \ht\scratchbox - header {\xtableparameter\c!header}% - footer {\xtableparameter\c!footer}% - \relax - % - \letxtableparameter\c!option\empty - % not so nice but needed as we use this in the setup - \linewidth\xtableparameter\c!rulethickness\relax - % so we freeze it - \c_tabl_x_swapped_max\zerocount - \begingroup - \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes - \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop - \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width - \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes - \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop - \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width - \settrialtypesetting - \tabl_x_get_buffer - \ifcase\c_tabl_x_swapped_max - \else - \tabl_x_flush_swapped - \fi - \clf_x_table_reflow_width - \endgroup - \begingroup - \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes - \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop - \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height - \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes - \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop - \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height - \settrialtypesetting - \ifcase\c_tabl_x_swapped_max - \tabl_x_get_buffer - \else - \tabl_x_flush_swapped - \fi - \clf_x_table_reflow_height - \endgroup - \begingroup - \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes - \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop - \let\tabl_x_stop_row \tabl_x_stop_row_construct - \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes - \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop - \let\tabl_x_stop_cell \tabl_x_stop_cell_construct - \ifcase\c_tabl_x_swapped_max - \tabl_x_get_buffer - \else - \tabl_x_flush_swapped - \fi - \clf_x_table_construct - \endgroup - \endgroup % * - \ifinsidesplitfloat - \tabl_x_flush_float_split - \orelse\ifinsidefloat - \tabl_x_flush_float_normal - \else - \tabl_x_flush_text_checked - \fi - \clf_x_table_cleanup - \dostoptagged - \resetbuffer[\tabl_x_current_buffer]% - \resetcharacteralign - \the\t_table_x_cleanup - \egroup} - -% text flow split modes - -\installcorenamespace{xtableflushsplit} - -\protected\def\tabl_x_flush_text_checked - {\expandnamespaceparameter\??xtableflushsplit\xtableparameter\c!split\v!no} - -% in text flow: headers and footers only once - -\setvalue{\??xtableflushsplit\v!yes}% - {\clf_x_table_flush - method {\v!split}% - \relax} - -% in text flow: headers and footers only once - -\setvalue{\??xtableflushsplit\v!no}% - {% \noindent % gives extra line after table - % \noindentation % messes up the next indentation - % \dontleavehmode % no leftskip - \kern\zeropoint % yet another guess - \ignorespaces - \clf_x_table_flush - method {\v!normal}% - \relax - \removeunwantedspaces} - -% in text flow: headers and footers get repeated - -\setvalue{\??xtableflushsplit\v!repeat}% - {\doloop - {\clf_x_table_flush - method {\v!split}% - height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi - \relax - \ifcase\c_tabl_x_state - \exitloop - \else - \page - \fi}} - -% \setvalue{\??xtableflushsplit\v!setups}% -% {\directsetup{xtable:split:user}} -% -% \startsetups[xtable:split:user] -% \doloop { -% \xtablesplitflush % uses \xtablesplitvsize (a macro) -% \ifcase\xtablesplitstate -% \exitloop -% \else -% \page -% \fi -% } -% \stopsetups -% -% \protected\def\xtablesplitflush -% {\clf_x_table_flush -% method {\v!split}% -% height \dimexpr\xtablesplitvsize\relax -% \relax} -% -% \def\xtablesplitvsize -% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi} -% -% \let\xtablesplitstate\c_tabl_x_state - -\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it - -\protected\def\tabl_x_flush_float_normal - {\clf_x_table_flush - method {\v!normal}% - \relax} - -\protected\def\tabl_x_flush_float_split - {\resetdirecttsplit - \edef\extrasplitfloatlines{\xtableparameter\c!split}% - \d_split_minimum_free_space\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax - %\c_split_minimum_free_lines\plustwo % not needed here as we're precise enough - \let\tsplitdirectsplitter\tabl_x_split_splitter - \let\tsplitdirectwidth \d_tabl_x_final_width - \handledirecttsplit} - -\protected\def\tabl_x_split_splitter#height% - {\setbox\b_split_result\vbox - {\clf_x_table_flush - method {\v!split}% - height \dimexpr#height\relax - \relax}% - \ifcase\c_tabl_x_state - \global\setfalse\somenextsplitofffloat - \else - \global\settrue \somenextsplitofffloat - \fi} - -% \permanent\protected\def\startxrow -% {\begingroup -% \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} - -% \permanent\protected\def\stopxrow -% {\tabl_x_stop_row -% \endgroup} - -\protected\def\tabl_x_start_row_reflow_width_yes[#settings]% - {\setupcurrentxtable[#settings]% - \clf_x_table_next_row} - -\protected\def\tabl_x_start_row_reflow_width_nop - {\clf_x_table_next_row} - -\protected\def\tabl_x_stop_row_reflow_width - {} - -\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes -\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop -\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width - -\protected\def\tabl_x_start_row_construct_yes[#settings]% - {\setupcurrentxtable[#settings]% - \dostarttagged\t!tablerow\empty - \clf_x_table_next_row_option{\xtableparameter\c!samepage}} - -\protected\def\tabl_x_start_row_construct_nop - {\dostarttagged\t!tablerow\empty - \clf_x_table_next_row} - -\protected\def\tabl_x_stop_row_construct - {\clf_x_table_finish_row - \dostoptagged} - -\permanent\protected\def\dummyxcell - {\begingroup - \enforced\let\inheritedxtableframed\relax - \tabl_x_start_cell_nop - \tabl_x_stop_cell - \endgroup} - -\def\tabl_x_setup_character_align - {\edef\p_left {\directxtableparameter\c!alignmentleftsample}% - \edef\p_right{\directxtableparameter\c!alignmentrightsample}% - \ifempty\p_left - \scratchdimenone\dimexpr\directxtableparameter\c!alignmentleftwidth\relax - \else - \setbox\scratchbox\hbox{\p_left}% - \scratchdimenone\wd\scratchbox - \fi - \ifempty\p_right - \scratchdimentwo\dimexpr\directxtableparameter\c!alignmentrightwidth\relax - \else - \setbox\scratchbox\hbox{\p_right}% - \scratchdimentwo\wd\scratchbox - \fi - \clf_setcharacteraligndetail - \clf_x_table_c - {\directxtableparameter\c!alignmentcharacter}% - \scratchdimenone - \scratchdimentwo - \relax} - -\newtoks\t_tabl_x_every_cell - -% \appendtoks -% \inhibitblank % already in framed -% \to \t_tabl_x_every_cell - -\appendtoks - \edef\p_characteralign{\directxtableparameter\c!aligncharacter}% - \ifx\p_characteralign\v!yes - \ifcase\clf_x_table_r\or - \tabl_x_setup_character_align - \fi - \signalcharacteralign\clf_x_table_c\clf_x_table_r - \fi -\to \t_tabl_x_every_cell - -\protected\def\tabl_x_begin_of_cell - {\the\t_tabl_x_every_cell - \everypar{\delayedbegstrut}} - -\protected\def\tabl_x_end_of_cell - {\ifhmode - \delayedendstrut - \par - \else - \par - \ifdim\prevdepth<\zeropoint % =-1000pt ? - \vskip-\strutdp - \else - \removebottomthings - \fi - \fi} - -% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes -% obsolete some day. The let as well as the direct speed things up a bit. We -% could also consider a \defaultxtableparameter. -% -% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone} -% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone} -% -% Although this becomes kind of messy. It saves already time that we only check -% for it when we have settings. - -% \def\tabl_x_set_hsize -% {\hsize.25\maxdimen} % let's be reasonable - -% \def\tabl_x_set_hsize -% {\edef\p_width{\xtableparameter\c!width}% -% \ifempty\p_width -% \hsize.25\maxdimen % is this really needed -% \fi} - -\let\tabl_x_set_hsize\relax - -\protected\def\tabl_x_start_cell_reflow_width_yes[#settings]% - {\setbox\b_tabl_x\hpack\bgroup - \ifnum\c_tabl_x_nesting>\plusone - \letxtableparameter\c!width \v!fit % overloads given width - \letxtableparameter\c!height\v!fit % overloads given height - \fi - % - \letxtableparameter\c!nx\plusone - \letxtableparameter\c!ny\plusone - \letxtableparameter\c!nc\plusone - \letxtableparameter\c!nr\plusone - % - \setupcurrentxtable[#settings]% - % - \c_tabl_x_nx\directxtableparameter\c!nc\relax - \c_tabl_x_ny\directxtableparameter\c!nr\relax - \ifnum\c_tabl_x_nx=\plusone - \c_tabl_x_nx\directxtableparameter\c!nx\relax - \fi - \ifnum\c_tabl_x_ny=\plusone - \c_tabl_x_ny\directxtableparameter\c!ny\relax - \fi - % - \d_tabl_x_distance\xtableparameter\c!distance\relax - \clf_x_table_init_reflow_width_option{\xtableparameter\c!option}% - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \tabl_x_set_hsize} - -\protected\def\tabl_x_start_cell_reflow_width_nop - {\setbox\b_tabl_x\hpack\bgroup - \ifnum\c_tabl_x_nesting>\plusone - \letxtableparameter\c!width \v!fit % overloads given width - \letxtableparameter\c!height\v!fit % overloads given height - \fi - \c_tabl_x_nx\plusone - \c_tabl_x_ny\plusone - \d_tabl_x_distance\xtableparameter\c!distance\relax - \clf_x_table_init_reflow_width - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \tabl_x_set_hsize} - -\protected\def\tabl_x_stop_cell_reflow_width - {\tabl_x_end_of_cell - \egroup - \egroup - \clf_x_table_set_reflow_width} - -\protected\def\tabl_x_start_cell_reflow_height_yes[#settings]% - {\setbox\b_tabl_x\hpack\bgroup - \clf_x_table_init_reflow_height - \ifcase\c_tabl_x_skip_mode % can be sped up - \ifnum\c_tabl_x_nesting>\plusone - \letxtableparameter\c!height\v!fit % overloads given height - \fi - \setupcurrentxtable[#settings]% - \relax - \letxtableparameter\c!width\d_tabl_x_width % overloads given width - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \fi} - -\protected\def\tabl_x_start_cell_reflow_height_nop - {\setbox\b_tabl_x\hpack\bgroup - \clf_x_table_init_reflow_height - \ifcase\c_tabl_x_skip_mode % can be sped up - \ifnum\c_tabl_x_nesting>\plusone - \letxtableparameter\c!height\v!fit % overloads given height - \fi - \relax - \letxtableparameter\c!width\d_tabl_x_width % overloads given width - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \fi} - -\protected\def\tabl_x_stop_cell_reflow_height - {\ifcase\c_tabl_x_skip_mode - \tabl_x_end_of_cell - \egroup - \fi - \egroup - \clf_x_table_set_reflow_height} - -\protected\def\tabl_x_start_cell_construct_yes[#settings]% - {\dostarttagged\t!tablecell\empty % can't we just tag the box - \setbox\b_tabl_x\hpack\bgroup - \setupcurrentxtable[#settings]% - \letxtableparameter\c!width \d_tabl_x_width % overloads given width - \letxtableparameter\c!height\d_tabl_x_height % overloads given height - \clf_x_table_init_construct - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \dotagxtablecell} - -\protected\def\tabl_x_start_cell_construct_nop - {\dostarttagged\t!tablecell\empty % can't we just tag the box - \setbox\b_tabl_x\hpack\bgroup - \letxtableparameter\c!width \d_tabl_x_width % overloads given width - \letxtableparameter\c!height\d_tabl_x_height % overloads given height (commenting it ... nice option) - \clf_x_table_init_construct - \inheritedxtableframed\bgroup - \tabl_x_begin_of_cell - \dotagxtablecell} - -\protected\def\tabl_x_stop_cell_construct - {\tabl_x_end_of_cell - \egroup - \dotagxtablesignal % harmless spot - \egroup - \clf_x_table_set_construct - \dostoptagged} - -% \permanent\tolerant\protected\def\startxcellgroup[#settings]% -% {\begingroup -% \ifarguments\or -% \tabl_x_set_checked{#settings}% -% \fi} -% -% \permanent\protected\def\stopxcellgroup -% {\endgroup} -% -% \permanent\tolerant\protected\def\startxrowgroup[#settings]% -% {\begingroup -% \ifarguments\or -% \tabl_x_set_checked{#settings}% -% \fi} -% -% \permanent\protected\def\stopxrowgroup -% {\dostoptagged -% \endgroup} - -\protected\def\tabl_x_set_checked#settings% - {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname - \edef\currentxtable{#settings}% - \else - \setupcurrentxtable[#settings]% - \fi} - -\permanent\protected\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \tabl_x_start_partition} -\permanent\protected\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \tabl_x_start_partition} -\permanent\protected\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\tabl_x_start_partition} -\permanent\protected\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \tabl_x_start_partition} - -\permanent\tolerant\protected\def\tabl_x_start_partition[#settings]% - {\ifarguments\or - \tabl_x_set_checked{#settings}% - \fi} - -\protected\def\tabl_x_stop_partition - {\endgroup} - -\permanent\aliased\let\stopxtablehead\tabl_x_stop_partition -\permanent\aliased\let\stopxtablefoot\tabl_x_stop_partition -\permanent\aliased\let\stopxtablenext\tabl_x_stop_partition -\permanent\aliased\let\stopxtablebody\tabl_x_stop_partition - -%D This is an experiment! Beware: you can create loops by using nested -%D references to already chained settings. -%D -%D \startbuffer -%D \setupxtable[suffix][align=middle,foregroundcolor=red] -%D \setupxtable[blabla][foregroundstyle=slanted] -%D \setupxtable[crap] [foregroundcolor=blue] -%D \setupxtable[bold] [crap][foregroundstyle=bold] -%D -%D \startxtable[frame=off] -%D \startxtablehead -%D \startxrow[bold] -%D \startxcell[suffix] a 0 \stopxcell -%D \startxcell[blabla] a 1 \stopxcell -%D \startxcell a 2 \stopxcell -%D \stopxrow -%D \stopxtablehead -%D \startxtablebody -%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow -%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow -%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow -%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow -%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow -%D \stopxtablebody -%D \stopxtable -%D \stopbuffer -%D -%D \typebuffer \placetable{}{\getbuffer} - -\appendtoks - \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent -\to \everysetupxtable - -% \definefontfamily[newtimes][serif][TeX Gyre Termes] -% \setupxtable[newtimes][foregroundstyle=\newtimes] -% \startxcell[newtimes] ...\stopxcell -% \startxcell[foregroundstyle=\newtimes] ...\stopxcell - -% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname -% % \ifcsname\??xtablecheck#tag\endcsname -% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords -% \expandafter\whatever % but more tolerant for tricky key=value -% \else -% \expandafter\whatever -% \fi[#tag] - -% groups - -\permanent\protected\def\startxgroup - {\begingroup - \doifelsenextoptionalcs\tabl_x_start_group_delayed_one\relax} - -\permanent\protected\def\stopxgroup - {\endgroup} - -\protected\def\tabl_x_start_group_delayed_one[#tag]% - {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname - \expandafter\tabl_x_start_group_delayed_two - \else - \expandafter\setupcurrentxtable - \fi[#tag]} - -\protected\def\tabl_x_start_group_delayed_two[#tag]% - {\ifempty\currentxtable \else - \chaintocurrentxtable{#tag}% - \fi - \edef\currentxtable{#tag}% - \doifelsenextoptionalcs\setupcurrentxtable\relax} - -\aliased\let\startxrowgroup \startxgroup -\aliased\let\stopxrowgroup \stopxgroup -\aliased\let\startxcellgroup\startxgroup -\aliased\let\stopxcellgroup \stopxgroup - -% cells (maybe also check for 1 etc but it becomes messy) - -\permanent\protected\def\startxcell - {\begingroup - \doifelsenextoptionalcs\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop} - -\protected\def\tabl_x_start_cell_delayed_one[#tag]% - {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname - \expandafter\tabl_x_start_cell_delayed_two - \else - \expandafter\tabl_x_start_cell_yes - \fi[#tag]} - -\protected\def\tabl_x_start_cell_delayed_two[#tag]% - {\ifempty\currentxtable \else - \chaintocurrentxtable{#tag}% - \fi - \edef\currentxtable{#tag}% - \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} - -\permanent\protected\def\stopxcell - {\tabl_x_stop_cell - \endgroup} - -% rows - -\permanent\protected\def\startxrow - {\begingroup - \doifelsenextoptionalcs\tabl_x_start_row_delayed_one\tabl_x_start_row_nop} - -\protected\def\tabl_x_start_row_delayed_one[#tag]% - {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname - \expandafter\tabl_x_start_row_delayed_two - \else - \expandafter\tabl_x_start_row_yes - \fi[#tag]} - -\permanent\protected\def\tabl_x_start_row_delayed_two[#tag]% - {\ifempty\currentxtable \else - \chaintocurrentxtable{#tag}% - \fi - \edef\currentxtable{#tag}% - \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} - -\permanent\protected\def\stopxrow - {\tabl_x_stop_row - \endgroup} - -%D A bonus, not advertised but some like it this way: - -\protected\def\tabl_x_nc - {\startxrow - \enforced\let\NC\tabl_x_nc_next - \enforced\let\NR\tabl_x_nr - \startxcell} - -\protected\def\tabl_x_nc_next - {\stopxcell - \startxcell} - -\protected\def\tabl_x_nr - {\stopxcell - \stopxrow - \enforced\let\NC\tabl_x_nc} - -\appendtoks - \enforced\let\NC\tabl_x_nc - \enforced\let\NR\tabl_x_nr -\to \everypreparextable - -%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting. - -\protected\def\tabl_x_c_cell_start#settings% - {\begingroup - \tabl_x_set_checked{#settings}% - \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} - -\protected\def\tabl_x_c_cell_stop - {\tabl_x_stop_cell - \endgroup} - -% \protected\def\dummyxcell -% {\tabl_x_start_cell_nop -% \tabl_x_stop_cell} - -\mutable\let\t_tabl_x_swapped\relax - -\def\tabl_x_flush_swapped - {\dorecurse\c_tabl_x_swapped_max - {\expandafter - \startxrow - \the\csname\??xtableswap##1\endcsname\relax - \stopxrow}} - -\def\tabl_x_collect_allocate - {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname - \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname} - -\def\tabl_x_collect_advance - {\global\advance\c_tabl_x_swapped\plusone - \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max - \global\c_tabl_x_swapped_max\c_tabl_x_swapped - \fi - \mutable\expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname - \ifx\t_tabl_x_swapped\relax - \tabl_x_collect_allocate - \fi} - -\protected\def\tabl_x_collect_cell_start - {\doifelsenextoptionalcs - \tabl_x_collect_cell_start_yes - \tabl_x_collect_cell_start_nop} - -\def\tabl_x_collect_cell_start_nop#content\stopxcell - {\tabl_x_collect_advance - \ifempty\m_tabl_x_swapped_settings - \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}% - \else - \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}% - \fi} - -\def\tabl_x_collect_cell_start_yes[#settings]#content\stopxcell - {\tabl_x_collect_advance - \ifempty\m_tabl_x_swapped_settings - \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}% - \else - \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}% - \fi - \getdummyparameters[\c!ny=1,#settings]% - \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax - \ifcase\scratchcounter\else - \dorecurse\scratchcounter\tabl_x_collect_advance - \fi} - -\permanent\tolerant\protected\def\startxcolumn[#1]% - {\begingroup - \global\c_tabl_x_swapped\zerocount - \enforced\let\startxcell\tabl_x_collect_cell_start - \enforced\let\stopxcell \relax - \xdef\m_tabl_x_swapped_settings{#1}} - -\permanent\protected\def\stopxcolumn - {\endgroup} - -\appendtoks - \dorecurse\c_tabl_x_swapped_max - {\global\csname\??xtableswap\number#1\endcsname\emptytoks}% -\to \t_table_x_cleanup - -%D \startbuffer -%D \setupxtable[one][foregroundcolor=red] -%D \setupxtable[two][foregroundcolor=blue] -%D -%D \startlinecorrection -%D \startxtable -%D \startxrow[one] -%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell -%D \startxcell Row 1, Column 2 \stopxcell -%D \startxcell Row 1, Column 3 \stopxcell -%D \stopxrow -%D \startxrow[two] -%D \startxcell Row 2, Column 1 \stopxcell -%D \startxcell Row 2, Column 2 \stopxcell -%D \startxcell Row 2, Column 3 \stopxcell -%D \stopxrow -%D \stopxtable -%D \stoplinecorrection -%D -%D \startlinecorrection -%D \startxtable -%D \startxcolumn[one] -%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell -%D \startxcell Row 1, Column 2 \stopxcell -%D \startxcell Row 1, Column 3 \stopxcell -%D \stopxcolumn -%D \startxcolumn[two] -%D \startxcell Row 2, Column 1 \stopxcell -%D \startxcell Row 2, Column 2 \stopxcell -%D \startxcell Row 2, Column 3 \stopxcell -%D \stopxcolumn -%D \stopxtable -%D \stoplinecorrection -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -\protect \endinput diff --git a/tex/context/base/mkiv/task-ini.mkxl b/tex/context/base/mkiv/task-ini.mkxl deleted file mode 100644 index 77e4fa985..000000000 --- a/tex/context/base/mkiv/task-ini.mkxl +++ /dev/null @@ -1,22 +0,0 @@ -%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}{} - -\protect \endinput diff --git a/tex/context/base/mkiv/toks-aux.lmt b/tex/context/base/mkiv/toks-aux.lmt deleted file mode 100644 index 03f4dc2c1..000000000 --- a/tex/context/base/mkiv/toks-aux.lmt +++ /dev/null @@ -1,183 +0,0 @@ -if not modules then modules = { } end modules ['toks-aux'] = { - version = 1.001, - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, tostring = type, tostring -local max = math.max -local formatters, gsub, char = string.formatters, string.gsub, string.char -local concat = table.concat - -local function flags(t) - if type(t) == "string" then - t = token.create(t) - end - local r = { } - if t.frozen then r[#r+1] = "frozen" end - if t.permanent then r[#r+1] = "permanent" end - if t.immutable then r[#r+1] = "immutable" end - if t.primitive then r[#r+1] = "primitive" end - if t.mutable then r[#r+1] = "mutable" end - if t.noaligned then r[#r+1] = "noaligned" end - if t.instance then r[#r+1] = "instance" end - if t.tolerant then r[#r+1] = "tolerant" end - if t.protected then r[#r+1] = "protected" end - return r -end - -tokens.flags= flags - -interfaces.implement { - name = "showluatokens", - public = true, - protected = true, - actions = function() - local f0 = formatters["%s: %s"] - local nl = logs.newline - local wr = logs.writer - local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) - local n = "" - local w = "" - local c = t.cmdname - if c == "left_brace" then - w = "given token list" - t = token.scan_toks(false) - elseif c == "register_toks" then - token.scan_next() - w = "token register" - n = t.csname or t.index - t = tex.gettoks(n,true) - elseif c == "internal_toks" then - token.scan_next() - w = "internal token variable" - n = t.csname or t.index - t = tex.gettoks(n,true) - else - n = token.scan_csname() - local r = flags(t) - local m = token.get_meaning(n,true) - r[#r+1] = "control sequence" - if type(m) == "table" then - t = m - else - t = { t } - end - w = concat(r, " ") - end - wr(f0(w,n)) - nl() - if type(t) == "table" then - local w1 = 4 - local w2 = 1 - local w3 = 3 - local w4 = 3 - for i=1,#t do - local ti = t[i] - w1 = max(w1,#tostring(ti.id)) - w2 = max(w2,#tostring(ti.command)) - w3 = max(w3,#tostring(ti.index)) - w4 = max(w4,#ti.cmdname) - end - local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] - local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] - local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] - for i=1,#t do - local ti = t[i] - local cs = ti.csname - local id = ti.id - local ix = ti.index - local cd = ti.command - local cn = ti.cmdname - if cn == "prefix" and not cs then - cs = "always enforced" - end - cn = gsub(cn,"_"," ") - if cs then - wr(f1(id,cd,ix,cn,cs)) - elseif cn == "letter" or cn == "other char" then - wr(f3(id,cd,ix,cn,ix)) - elseif cn == "match" then - local s - if ix == 32 then s = "optional spacer" -- space - elseif ix == 42 then s = "skip spaces" -- * - elseif ix == 43 then s = "keep braces" -- + - elseif ix == 45 then s = "thrash" -- - - elseif ix == 47 then s = "prune" -- / - elseif ix == 58 then s = "continue" -- : - elseif ix == 59 then s = "quit" -- ; - elseif ix == 61 then s = "mandate braces" -- = - elseif ix == 94 then s = "keep spaces" -- ^ - elseif ix == 95 then s = "keep mandate braces" -- _ - else s = "argument " .. char(ix) - end - wr(f1(id,cd,ix,cn,s)) - else - wr(f2(id,cd,ix,cn)) - if cn == "end match" then - wr("--------------") - end - end - end - nl() - end - end -} - --- For the moment here, will move to initex only (also see node-ini.lua); we need --- to actually store these. - -local groupcodes = { } -local glyphoptioncodes = { } -local hyphenationcodes = { } -local frozenparcodes = { } -local flagcodes = { } -local normalizecodes = { } - -for k, v in next, tex.getgroupvalues() do - groupcodes[k] = gsub(v,"[_ ]","") -end -for k, v in next, tex.gethyphenationvalues() do - hyphenationcodes[k] = gsub(v,"[_ ]","") -end -for k, v in next, tex.getglyphoptionvalues() do - glyphoptioncodes[k] = gsub(v,"[_ ]","") -end -for k, v in next, tex.getfrozenparvalues() do - frozenparcodes[k] = gsub(v,"[_ ]","") -end -for k, v in next, tex.getflagvalues() do - flagcodes[k] = gsub(v,"[_ ]","") -end -for k, v in next, tex.getnormalizevalues() do - normalizecodes[k] = gsub(v,"[_ ]","") -end - - -if environment.initex then - - local texintegerdef = tex.integerdef - - for k, v in next, groupcodes do texintegerdef(v .. "groupcode", k,"immutable") end - for k, v in next, glyphoptioncodes do texintegerdef(v .. "code", k,"immutable") end - for k, v in next, hyphenationcodes do texintegerdef(v .. "hyphenationmodecode",k,"immutable") end - for k, v in next, frozenparcodes do texintegerdef("frozen" .. v .. "code", k,"immutable") end - for k, v in next, flagcodes do texintegerdef(v .. "flagcode", k,"immutable") end - for k, v in next, normalizecodes do texintegerdef(v .. "code", k,"immutable") end - -end - -groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes)) -glyphoptioncodes = utilities.storage.allocate(table.swapped(glyphoptioncodes,glyphoptioncodes)) -hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodes)) -frozenparcodes = utilities.storage.allocate(table.swapped(frozenparcodes, frozenparcodes)) -flagcodes = utilities.storage.allocate(table.swapped(flagcodes, flagcodes)) -normalizecodes = utilities.storage.allocate(table.swapped(normalizecodes, normalizecodes)) - -tex.groupcodes = groupcodes -tex.glyphoptioncodes = glyphoptioncodes -tex.hyphenationcodes = hyphenationcodes -tex.frozenparcodes = frozenparcodes -tex.flagcodes = flagcodes -tex.normalizecodes = normalizecodes diff --git a/tex/context/base/mkiv/toks-aux.mkiv b/tex/context/base/mkiv/toks-aux.mkiv index f66b51ec5..5b43de596 100644 --- a/tex/context/base/mkiv/toks-aux.mkiv +++ b/tex/context/base/mkiv/toks-aux.mkiv @@ -15,23 +15,6 @@ \unprotect -% The older \type {\scantokens} overload has been replace by a more modern -% one (in \LMTX): -% -% \protected\def\whatever#1[#2](#3)\relax{oeps #1 and #2 and #3 done ## error} -% \scratchtoks{foo \framed{\red 123}456} -% -% \showluatokens{123\what} -% \showluatokens\whatever -% \showluatokens\framed -% -% \showluatokens\scratchtoks -% \showluatokens\everypar - -\ifcase\contextlmtxmode \or - \registerctxluafile{toks-aux}{autosuffix} -\fi - \installcorenamespace {tokenlist} \unexpanded\def\definetokenlist[#1]% diff --git a/tex/context/base/mkiv/toks-ini.lmt b/tex/context/base/mkiv/toks-ini.lmt deleted file mode 100644 index 4b2d1facc..000000000 --- a/tex/context/base/mkiv/toks-ini.lmt +++ /dev/null @@ -1,332 +0,0 @@ -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 next = next -local tonumber = tonumber -local tostring = tostring -local utfchar = utf.char -local char = string.char -local printtable = table.print -local concat = table.concat -local format = string.format - -local commands = token.getcommandvalues() -local values = token.getfunctionvalues() -values.dimen = values.dimension -values.count = values.integer -tokens.values = utilities.storage.allocate(table.swapped(values, values)) -tokens.commands = utilities.storage.allocate(table.swapped(commands,commands)) - -local scan_toks = token.scan_toks -local scan_string = token.scan_string -local scan_argument = token.scan_argument -local scan_delimited = token.scan_delimited -local scan_tokenlist = token.scan_tokenlist or scan_string -local scan_integer = token.scan_integer or token.scan_int -local scan_cardinal = token.scan_cardinal -local scan_code = token.scan_code -local scan_token_code = token.scan_token_code -local scan_dimen = token.scan_dimen -local scan_glue = token.scan_glue -local scan_skip = token.scan_skip -local scan_keyword = token.scan_keyword -local scan_keyword_cs = token.scan_keyword_cs or scan_keyword -local scan_token = token.scan_token -local scan_box = token.scan_box -local scan_word = token.scan_word -local scan_letters = token.scan_letters or scan_word -- lmtx -local scan_key = token.scan_key -local scan_value = token.scan_value -local scan_char = token.scan_char -local scan_number = token.scan_number -- not defined -local scan_csname = token.scan_csname -local scan_real = token.scan_real -local scan_float = token.scan_float -local scan_luanumber = token.scan_luanumber or scan_float -- only lmtx -local scan_luainteger = token.scan_luainteger or scan_integer -- only lmtx -local scan_luacardinal = token.scan_luacardinal or scan_cardinal -- only lmtx - -local scan_integer_argument = token.scan_integer_argument -local scan_dimen_argument = token.scan_dimen_argument - --- todo: gobble_integer -- might go away --- todo: gobble_dimension -- might go away - -local set_macro = token.set_macro -local set_char = token.set_char -local set_lua = token.set_lua - -local create_token = token.create -local new_token = token.new -local is_defined = token.is_defined -local is_token = token.is_token - -tokens.new = new_token -tokens.create = create_token -tokens.istoken = is_token -tokens.isdefined = is_defined -tokens.defined = is_defined - -tokens.getinteger = token.get_integer -tokens.setinteger = token.set_integer - -local bits = { - escape = 0x00000001, -- 2^00 - begingroup = 0x00000002, -- 2^01 - endgroup = 0x00000004, -- 2^02 - mathshift = 0x00000008, -- 2^03 - alignment = 0x00000010, -- 2^04 - endofline = 0x00000020, -- 2^05 - parameter = 0x00000040, -- 2^06 - superscript = 0x00000080, -- 2^07 - subscript = 0x00000100, -- 2^08 - ignore = 0x00000200, -- 2^09 - space = 0x00000400, -- 2^10 -- 1024 - letter = 0x00000800, -- 2^11 - other = 0x00001000, -- 2^12 - active = 0x00002000, -- 2^13 - comment = 0x00004000, -- 2^14 - invalid = 0x00008000, -- 2^15 - -- - character = 0x00001800, -- 2^11 + 2^12 - whitespace = 0x00002400, -- 2^13 + 2^10 -- / needs more checking - -- - open = 0x00000402, -- 2^10 + 2^01 -- space + begingroup - close = 0x00000404, -- 2^10 + 2^02 -- space + endgroup -} - --- for k, v in next, bits do bits[v] = k end - -tokens.bits = bits - --- words are space or \relax terminated and the trailing space is gobbled; a word --- can contain any non-space letter/other (see archive for implementation in lua) - -if not scan_number 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 - -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 - -local function scan_verbatim() - return scan_argument(false) -end - -if not scan_box then - - local scan_list = token.scan_list - local put_next = token.put_next - - scan_box = function(s) - if s == "hbox" or s == "vbox" or s == "vtop" then - put_next(create_token(s)) - end - return scan_list() - end - - token.scan_box = scan_box - -end - -tokens.scanners = { -- these expand - token = scan_token, - toks = scan_toks, - tokens = scan_toks, - box = scan_box, - hbox = function() return scan_box("hbox") end, - vbox = function() return scan_box("vbox") end, - vtop = function() return scan_box("vtop") end, - dimen = scan_dimen, - dimension = scan_dimen, - glue = scan_glue, - gluevalues = function() return scan_glue(false,false,true) end, - gluespec = scan_skip, - integer = scan_integer, - cardinal = scan_cardinal, - real = scan_real, - float = scan_float, - luanumber = scan_luanumber, - luainteger = scan_luainteger, - luacardinal = scan_luacardinal, - count = scan_integer, - string = scan_string, - argument = scan_argument, - delimited = scan_delimited, - tokenlist = scan_tokenlist, - verbatim = scan_verbatim, -- detokenize - code = scan_code, - tokencode = scan_token_code, - word = scan_word, - letters = scan_letters, - key = scan_key, - value = scan_value, - char = scan_char, - number = scan_number, - boolean = scan_boolean, - keyword = scan_keyword, - keywordcs = scan_keyword_cs, - csname = scan_csname, - - next = token.scan_next, - nextexpanded = token.scan_next_expanded, - - peek = token.peek_next, - peekexpanded = token.peek_next_expanded, - peekchar = token.peek_next_char, - - skip = token.skip_next, - skipexpanded = token.skip_next_expanded, - - cmdchr = token.scan_cmdchr, - cmdchrexpanded = token.scan_cmdchr_expanded, - - ischar = token.is_next_char, - - integerargument = scan_integer_argument, - dimenargument = scan_dimen_argument, -} - -tokens.getters = { -- these don't expand - meaning = token.get_meaning, - macro = token.get_macro, - token = token.scan_next or token.get_next, -- not here, use scanners.next or token - cstoken = token.get_cstoken, - 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, - char = set_char, - lua = set_lua, - count = tex.setcount, - dimen = tex.setdimen, - skip = tex.setglue, - glue = tex.setglue, - skip = tex.setmuglue, - glue = tex.setmuglue, - box = tex.setbox, -} - -token.accessors = { - command = token.get_command, - cmd = token.get_command, - cmdname = token.get_cmdname, - name = token.get_cmdname, - csname = token.get_csname, - index = token.get_index, - active = token.get_active, - frozen = token.get_frozen, - protected = token.get_protected, - expandable = token.get_protected, - user = token.get_user, - cmdchrcs = token.get_cmdchrcs, - active = token.get_active, - range = token.get_range, -} - --- 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; --- } - -if setinspector then - - local simple = { letter = "letter", other_char = "other" } - - local astable = function(t) - if t and is_token(t) then - local cmdname = t.cmdname - local simple = simple[cmdname] - if simple then - return { - id = t.id, - category = simple, - character = utfchar(t.index) or nil, - } - else - return { - id = t.id, - command = t.command, - index = t.index, - csname = t.csname, - cmdname = cmdname, - active = t.active, - expandable = t.expandable, - frozen = t.frozen, - tolerant = t.tolerant, - protected = t.protected, - primitive = t.primitive, - permanent = t.permanent, - noaligned = t.noaligned, - instance = t.instance, - immutable = t.imutable, - user = t.user, - } - end - end - end - - tokens.astable = astable - - setinspector("token",function(v) local t = astable(v) if t then printtable(t,tostring(v)) return true end end) - -end - -tokens.cache = table.setmetatableindex(function(t,k) - if not is_defined(k) then - set_macro(k,"","global") - end - local v = create_token(k) - t[k] = v - return v -end) diff --git a/tex/context/base/mkiv/toks-ini.mkxl b/tex/context/base/mkiv/toks-ini.mkxl deleted file mode 100644 index c7d7bceb3..000000000 --- a/tex/context/base/mkiv/toks-ini.mkxl +++ /dev/null @@ -1,20 +0,0 @@ -%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} - -\unprotect - -\registerctxluafile{toks-ini}{autosuffix} - -\protect \endinput diff --git a/tex/context/base/mkiv/toks-scn.lmt b/tex/context/base/mkiv/toks-scn.lmt deleted file mode 100644 index 93e0af09a..000000000 --- a/tex/context/base/mkiv/toks-scn.lmt +++ /dev/null @@ -1,592 +0,0 @@ -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 scanargument = scanners.argument -local scandelimited = scanners.delimited -- lmtx -local scanverbatim = scanners.verbatim -local scantokenlist = scanners.tokenlist -local scantoks = scanners.toks -local scaninteger = scanners.integer -local scancardinal = scanners.cardinal -local scannumber = scanners.number -local scankeyword = scanners.keyword -local scankeywordcs = scanners.keywordcs -local scanword = scanners.word -local scanletters = scanners.letters -local scankey = scanners.key -local scancode = scanners.code -local scanboolean = scanners.boolean -local scandimen = scanners.dimen -local scanglue = scanners.glue -local scangluevalues = scanners.gluevalues -local scangluespec = scanners.gluespec -local scancsname = scanners.csname -local scanintegerargument = scanners.integerargument -local scandimenargument = scanners.dimenargument - -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 - -local function scantable(t,data) - if not data then - data = { } - end - if t then - local wrapped = scanopen() - while true do - local key = scanword(true) - 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 - end - return data -end - -function tokens.constant(s) - if type(s) == "string" then - return "'" .. s .. "'" - else - return s - end -end - -scanners.list = scanlist -scanners.table = scantable -scanners.conditional = scanconditional - -function scanners.whd() - local width, height, depth - while true do - if scankeyword("width") then - width = scandimen() - elseif scankeyword("height") then - height = scandimen() - elseif scankeyword("depth") then - depth = scandimen() - else - break - end - end - if width or height or depth then - return width or 0, height or 0, depth or 0 - else - -- we inherit - end -end - --- begin lmtx - -local l = utf.byte("[") -local r = utf.byte("]") - -local function scanbracketed() - local s = scandelimited(l, r) - if s then - return s - else - local readstate = status.getreadstate() - report_scan("missing argument in line %i of %a", readstate.linenumber, readstate.filename) - return "" - end -end - -local function scanoptional() - return scandelimited(l, r) or "" -end - -local function scanbracketedasis() - return scandelimited(l, r, false) -end - -local function scanargumentasis() - return scanargument(false) -end - -scanners.bracketed = scanbracketed -scanners.optional = scanoptional -scanners.bracketedasis = scanbracketedasis -scanners.argumentasis = scanargumentasis - --- end lmtx - -local shortcuts = { - tokens = tokens, - bits = tokenbits, - open = open, - close = close, - scanners = scanners, - scanstring = scanstring, - scanargument = scanargument, - scanverbatim = scanverbatim, - scantokenlist = scantokenlist, - scantoks = scantoks, - scaninteger = scaninteger, - scancardinal = scancardinal, - scannumber = scannumber, - scantable = scantable, -- not directly useable - scankeyword = scankeyword, - scankeywordcs = scankeywordcs, - scanword = scanword, - scanletters = scanletters, - -- scankey = scankey, - scancode = scancode, - scanboolean = scanboolean, - scanglue = scanglue, -- list - scangluespec = scangluespec, - scangluevalues = scangluevalues, - scandimen = scandimen, - scandimension = scandimen, - scanbox = scanners.box, - scanhbox = scanners.hbox, - scanvbox = scanners.vbox, - scanvtop = scanners.vtop, - scanconditional = scanconditional, - scanopen = scanopen, - scanclose = scanclose, - scanlist = scanlist, - scancsname = scancsname, - todimen = todimen, - tonumber = tonumber, - tostring = tostring, - toboolean = toboolean, - inspect = inspect, - report = report_scan, - -- lmtx - scandelimited = scandelimited, -- not directly useable - scanbracketed = scanbracketed, - scanoptional = scanoptional, - scanbracketedasis = scanbracketedasis, - scanargumentasis = scanargumentasis, - -- - scanintegerargument = scanintegerargument, - scandimenargument = scandimenargument, -} - -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", -} - --- We could just pickup a keyword but then we really need to make sure that no number --- follows it when that is the assignment and adding an optional = defeats the gain --- in speed. Currently we have sources with no spaces (\startcontextdefinitioncode --- ...) so it fails there. --- --- Another drawback is that we then need to use { } instead of ending with \relax (as --- we can do now) but that is no big deal. It's just that I then need to check the TeX --- end. More pain than gain and a bit risky too. Using scanletters works better, but --- the gain is only some 10 percent but if we don't have keywords with numbers it might --- make sense in the end, some day. - -local f_if = formatters[ " if scankeywordcs('%s') then data['%s'] = scan%s()"] -local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = scan%s()"] - ------ f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] ------ f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] - --- if CONTEXTLMTXMODE > 0 then --- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"] --- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"] --- end - -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 scankeywordcs('%s') then data['%s'] = %s(scan%s())"] -local f_elseif_c = formatters[" elseif scankeywordcs('%s') then data['%s'] = %s(scan%s())"] -local f_scan_c = formatters["%s(scan%s())"] - --- see above - --- if CONTEXTLMTXMODE > 0 then --- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"] --- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"] --- end - -local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"] -local f_any_c = formatters[" else local key = scanword(true) 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(true) if key then data[key] = scan%s() else break end"] -local f_any_all_c= formatters[" local key = scanword(true) 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_singular = formatters["%\nt\n%\nt\n\nreturn function(%s)\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 = scanopen() - while true do - ]] .. "%\nt\n" .. [[ - %s - end - if wrapped then - scanclose() - end -]] ] - --- using these shortcuts saves temporary small tables (okay, it looks uglier) - -local presets = { - ["1 string" ] = { "string" }, - ["2 strings"] = { "string", "string" }, - ["3 strings"] = { "string", "string", "string" }, - ["4 strings"] = { "string", "string", "string", "string" }, - ["5 strings"] = { "string", "string", "string", "string", "string" }, - ["6 strings"] = { "string", "string", "string", "string", "string", "string" }, - ["7 strings"] = { "string", "string", "string", "string", "string", "string", "string" }, - ["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" }, - - ["1 argument" ] = { "argument" }, - ["2 arguments"] = { "argument", "argument" }, - ["3 arguments"] = { "argument", "argument", "argument" }, - ["4 arguments"] = { "argument", "argument", "argument", "argument" }, -} - -tokens.presets = presets - -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 args - 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) - -- r[m] = (m > 1 and f_elseif_x or f_if_x)(t1,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 p = t and presets[t] -- already done in implement - if p then - t = p - 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) - n = n + 1 - f[n] = 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) - n = n + 1 - f[n] = 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) - n = n + 1 - f[n] = f_action_s(i,i) - end - code = f_simple(f,code) - else - return scanners[ti] - end - elseif #t == 0 then - if specification.usage == "value" then - code = "b" - args = "_,b" - else - code = "" - args = "" - end - if a then - tokens._action = a - for i=1,#a do - code = f_action_f(i,code) - n = n + 1 - f[n] = f_action_s(i,i) - end - end - code = f_singular(c,f,args,code) - 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) - n = n + 1 - f[n] = 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() diff --git a/tex/context/base/mkiv/toks-scn.mkxl b/tex/context/base/mkiv/toks-scn.mkxl deleted file mode 100644 index 12abf0cb8..000000000 --- a/tex/context/base/mkiv/toks-scn.mkxl +++ /dev/null @@ -1,26 +0,0 @@ -%D \module -%D [ file=toks-ini, -%D version=2007.03.03, -%D title=\CONTEXT\ Token Support, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Token Support / Scanners} - -\unprotect - -\registerctxluafile{toks-scn}{} -\registerctxluafile{cldf-scn}{} -\registerctxluafile{cldf-stp}{} - -\ifcase \contextlmtxmode \else - \registerctxluafile{cldf-lmt}{} -\fi - -\protect \endinput diff --git a/tex/context/base/mkiv/trac-ctx.mkxl b/tex/context/base/mkiv/trac-ctx.mkxl deleted file mode 100644 index 656a7a9aa..000000000 --- a/tex/context/base/mkiv/trac-ctx.mkxl +++ /dev/null @@ -1,58 +0,0 @@ -%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}{} - -\unprotect - -\permanent\protected\def\installtextracker #1#2#3{\clf_installtextracker {#1}{\detokenize{#2}}{\detokenize{#3}}} -\permanent\protected\def\installtexdirective #1#2#3{\clf_installtexdirective {#1}{\detokenize{#2}}{\detokenize{#3}}} -\permanent\protected\def\installtexexperiment#1#2#3{\clf_installtexexperiment{#1}{\detokenize{#2}}{\detokenize{#3}}} - -\appendtoks - \clf_initializetextrackers - \clf_initializetexdirectives - \clf_initializetexexperiments -\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/tex/context/base/mkiv/trac-deb.lmt b/tex/context/base/mkiv/trac-deb.lmt deleted file mode 100644 index b9827c3a9..000000000 --- a/tex/context/base/mkiv/trac-deb.lmt +++ /dev/null @@ -1,419 +0,0 @@ -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" -} - --- This is an old mechanism, a result of some experiments in the early days of --- luatex and mkiv, but still nice anyway. I will clean it up in lmtx. - -local status = status - -local tonumber, tostring, type = tonumber, tostring, type -local format, concat, match, find, gsub = string.format, table.concat, string.match, string.find, string.gsub - -local report_nl = logs.newline -local report_str = logs.writer - -tracers = tracers or { } -local tracers = tracers - -local implement = interfaces.implement - -local ioflush = io.flush -local ioread = io.read -local writenl = texio.write_nl -local write = texio.write - -local runlocal = tex.runlocal -local terminaldata = false -local context = context - -interfaces.implement { - name = "fetchterminaldata", - actions = function() - context(terminaldata) - end, -} - -function texio.terminal() - writenl("\n" .. "entering interactive mode, use \\quit to abort reading" .."\n\n") - while true do - write(">") - ioflush() - terminaldata = ioread() - if terminaldata == "\\quit" then - terminaldata = false - break - else - runlocal("t_syst_terminal_data",nil,nil,true) -- obeymode - end - end -end - -interfaces.implement { - name = "readfromterminal", - public = true, - protected = true, - actions = texio.terminal, -} - -local savedluaerror = nil -local usescitelexer = nil -local quitonerror = true - -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 scite = usescitelexer and require("util-sci") - if scite then - return utilities.scite.tohtml(data,"tex",linenumber or true,false) - else - 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 "" - 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 "" - end - end -end - --- 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,errortype) - local readstate = status.readstate - local filename = readstate.filename - local linenumber = readstate.linenumber - local skiplinenumber = readstate.skiplinenumber - local errorstate = status.errorstate - local lastcontext = errorstate.errorcontext - local lasttexerror = errorstate.error or "?" - local lastluaerror = errorstate.luaerror or "?" -- lasttexerror - local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0) - local lastmpserror = match(lasttexerror,[[^.-mp%serror:%s*(.*)$]]) - resetmessages() - lastluaerror = gsub(lastluaerror,"%[\\directlua%]","[ctxlua]") - tracers.printerror { - filename = filename, - linenumber = linenumber, - skiplinenumber = skiplinenumber, - offset = tonumber(offset) or 10, - lasttexerror = lasttexerror, - lastmpserror = lastmpserror, - lastluaerror = lastluaerror, -- can be the same as lasttexerror - luaerrorline = luaerrorline, - lastcontext = lastcontext, - lasttexhelp = tex.gethelptext and tex.gethelptext() or nil, - errortype = errortype, - } - if job and type(job.disablesave) == "function" then - job.disablesave() - end -end - -directives.register("system.quitonerror",function(v) - quitonerror = toboolean(v) -end) - -directives.register("system.usescitelexer",function(v) - usescitelexer = toboolean(v) -end) - -local busy = false - -function tracers.printerror(specification) - if not busy then - busy = true - local errorvalues = table.swapped(tex.geterrorvalues()) - local filename = specification.filename - local linenumber = specification.linenumber - local lasttexerror = specification.lasttexerror - local lastmpserror = specification.lastmpserror - local lastluaerror = specification.lastluaerror - local lastcontext = specification.lastcontext - local luaerrorline = specification.luaerrorline - local errortype = specification.errortype - local offset = specification.offset - local endoffile = specification.endoffile - local report = errorreporter(luaerrorline) - if errortype == errorvalues.warning then - report("warning error: %s",lasttexerror or "-") - busy = false; - return; - elseif errortype == errorvalues.eof then - report("runaway error: %s",lasttexerror or "-") - if not quitonerror and texio.terminal then - texio.terminal() -- not well tested - end - elseif errortype == errorvalues.condition then - linenumber = specification.skiplinenumber - if linenumber > 0 then - report("condition error on line %s in file %s: %s",linenumber,filename,lasttexerror) - report_nl() - report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline))) - report_nl() - else - report("runaway condition error: %s",lasttexerror or "-") - end - quitonerror = true - elseif not filename then - report("fuzzy error:") - report(" tex: %s",lasttexerror or "-") - report(" lua: %s",lastluaerror or "-") - report(" mps: %s",lastmpserror or "-") - elseif type(filename) == "number" then - report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror) - else - report_nl() - if luaerrorline then - if linenumber == 0 or not filename or filename == "" then - print("\nfatal lua error:\n\n",lastluaerror,"\n") - luatex.abort() - return - else - report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror) - end - elseif lastmpserror then - report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror) - else - report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror) - if lastcontext then - report_nl() - report_str(lastcontext) - report_nl() - else - report_nl() - -- tex.showcontext() - end - if lastluaerror and not match(lastluaerror,"^%s*[%?]*%s*$") then - print("\nlua error:\n\n",lastluaerror,"\n") - quitonerror = true - end - end - report_nl() - report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline))) - report_nl() - end - local errname = file.addsuffix(tex.jobname .. "-error","log") - if quitonerror then - table.save(errname,specification) - local help = specification.lasttexhelp - if help and #help > 0 then - report_nl() - report_str(help) - report_nl() - report_nl() - end - luatex.abort() - end - busy = false - end -end - -luatex.wrapup(function() os.remove(file.addsuffix(tex.jobname .. "-error","log")) end) - -local function processwarning(offset) - local warningstate = status.warningstate - local lastwarning = warningstate.warning or "?" - local lastlocation = warningstate.warningtag or "?" - resetmessages() - tracers.printwarning { - 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('intercept_lua_error', function() processerror(v) end) - register('intercept_tex_error', function(mode,eof) processerror(v,eof) return mode end) - else - register('show_error_message', nil) - register('show_warning_message', nil) - register('intercept_lua_error', nil) - register('intercept_tex_error', 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 - -local function reportback(lmxname,default,variables) - if lmxname == false then - return variables - else - local name = lmx.show(type(lmxname) == "string" and lmxname or default,variables) - if name then - logs.report("context report","file: %s",name) - end - end -end - -local function showerror(lmxname) - local readstate = status.readstate() - local filename = readstate.filename - local linenumber = tonumber(readstate.linenumber) or 0 - local errorcontext = "" - if not filename then - filename = status.iocodes[readstate.iocode] - errorcontext = 'error in filename' - else - errorcontext = tracers.showlines(filename,linenumber,offset) - end - local variables = { - ['title'] = 'ConTeXt Error Information', - ['errormessage'] = status.errorstatus.error or "?", - ['linenumber'] = linenumber, - ['color-background-one'] = lmx.get('color-background-yellow'), - ['color-background-two'] = lmx.get('color-background-purple'), - ['filename'] = filename, - ['errorcontext'] = errorcontext, - } - reportback(lmxname,"context-error.lmx",variables) - luatex.abort() -end - -lmx.showerror = showerror - -function lmx.overloaderror(v) - if v == "scite" then - usescitelexer = true - end - callback.register('show_error_message', function() showerror() end) - callback.register('intercept_lua_error', function() showerror() end) - callback.register('intercept_tex_error', function() showerror() end) -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 - --- Obsolete ... not that usefull as normally one runs from an editor and --- when run unattended it makes no sense either. - --- local editor = [[scite "-open:%filename%" -goto:%linenumber%]] --- --- directives.register("system.editor",function(v) --- editor = v --- end) --- --- callback.register("call_edit",function(filename,linenumber) --- if editor then --- editor = gsub(editor,"%%s",filename) --- editor = gsub(editor,"%%d",linenumber) --- editor = gsub(editor,"%%filename%%",filename) --- editor = gsub(editor,"%%linenumber%%",linenumber) --- logs.report("system","starting editor: %s",editor) --- os.execute(editor) --- end --- end) - -local implement = interfaces.implement - -implement { name = "showtrackers", public = true, protected = true, actions = trackers.show } -implement { name = "enabletrackers", public = true, protected = true, actions = trackers.enable, arguments = "optional" } -implement { name = "disabletrackers", public = true, protected = true, actions = trackers.disable, arguments = "optional" } -implement { name = "resettrackers", public = true, protected = true, actions = trackers.reset } - -implement { name = "showdirectives", public = true, protected = true, actions = directives.show } -implement { name = "enabledirectives", public = true, protected = true, actions = directives.enable, arguments = "optional" } -implement { name = "disabledirectives", public = true, protected = true, actions = directives.disable, arguments = "optional" } - -implement { name = "showexperiments", public = true, protected = true, actions = experiments.show } -implement { name = "enableexperiments", public = true, protected = true, actions = experiments.enable, arguments = "optional" } -implement { name = "disableexperiments", public = true, protected = true, actions = experiments.disable, arguments = "optional" } - -implement { name = "overloaderror", public = true, protected = true, actions = lmx.overloaderror } -implement { name = "showlogcategories", public = true, protected = true, actions = logs.show } - -local debugger = utilities.debugger - -directives.register("system.profile",function(n) - luatex.registerstopactions(function() - debugger.disable() - debugger.savestats("luatex-profile.log",tonumber(n) or 0) - report_nl() - logs.report("system","profiler stopped, log saved in %a","luatex-profile.log") - report_nl() - end) - logs.report("system","profiler started") - debugger.enable() -end) diff --git a/tex/context/base/mkiv/trac-deb.mkxl b/tex/context/base/mkiv/trac-deb.mkxl deleted file mode 100644 index 37a901aa3..000000000 --- a/tex/context/base/mkiv/trac-deb.mkxl +++ /dev/null @@ -1,48 +0,0 @@ -%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} - -%registerctxluafile{trac-lmx}{} -\registerctxluafile{trac-deb}{autosuffix} - -\unprotect - -\permanent\protected\def\breakpoint{\showdebuginfo\wait} - -% \showtrackers % defined at the lua end -% \enabletrackers [#1] % defined at the lua end -% \disabletrackers [#1] % defined at the lua end -% \resettrackers % defined at the lua end -% -% \showdirectives % defined at the lua end -% \enabledirectives [#1] % defined at the lua end -% \disabledirectives [#1] % defined at the lua end -% -% \showexperiments % defined at the lua end -% \enableexperiments [#1] % defined at the lua end -% \disableexperiments[#1] % defined at the lua end -% -% \showdebuginfo % defined at the lua end -% \overloaderror % defined at the lua end -% -% \showlogcategories % defined at the lua end - -% \enabledirectives[system.showerror] - -\newtoks \t_syst_terminal_data - -%t_syst_terminal_data {\beginlocalcontrol\clf_fetchterminaldata\endlocalcontrol} -\t_syst_terminal_data {\clf_fetchterminaldata} - -\protect \endinput diff --git a/tex/context/base/mkiv/trac-inf.lmt b/tex/context/base/mkiv/trac-inf.lmt deleted file mode 100644 index 9207d5b45..000000000 --- a/tex/context/base/mkiv/trac-inf.lmt +++ /dev/null @@ -1,425 +0,0 @@ -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, gsub, rep = string.format, string.lower, string.find, string.gsub, string.rep -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, offset = 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, offset = 0 } -end - -local ticks = clock -local seconds = function(n) return n or 0 end - -ticks = lua.getpreciseticks -seconds = lua.getpreciseseconds - -local function starttiming(instance,reset) - local timer = timers[instance or "notimer"] - local it = timer.timing - if reset then - it = 0 - timer.loadtime = 0 - end - if it == 0 then - timer.starttime = ticks() - if not timer.loadtime then - 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 and starttime > 0 then - local stoptime = ticks() - local loadtime = stoptime - starttime - timer.stoptime = stoptime - timer.loadtime = timer.loadtime + loadtime - timer.timing = 0 - timer.starttime = 0 - return loadtime - end - end - return 0 -end - -local function benchmarktimer(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 and starttime > 0 then - timer.offset = ticks() - starttime - else - timer.offset = 0 - end - end -end - -local function elapsed(instance) - if type(instance) == "number" then - return instance - else - local timer = timers[instance or "notimer"] - return timer and seconds(timer.loadtime - 2*(timer.offset or 0)) or 0 - end -end - -local function currenttime(instance) - if type(instance) == "number" then - return instance - else - local timer = timers[instance or "notimer"] - local it = timer.timing - if it > 1 then - -- whatever - else - local starttime = timer.starttime - if starttime and starttime > 0 then - return seconds(timer.loadtime + ticks() - starttime - 2*(timer.offset or 0)) - end - end - return 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.currenttime = currenttime -statistics.elapsed = elapsed -statistics.elapsedtime = elapsedtime -statistics.elapsedindeed = elapsedindeed -statistics.elapsedseconds = elapsedseconds -statistics.benchmarktimer = benchmarktimer - --- general function .. we might split this module - -function statistics.register(tag,fnc) - if statistics.enable and type(fnc) == "function" then - -- second load can overload: - 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("used engine", function() - return format("%s version: %s, functionality level: %s, format id: %s, compiler: %s", - LUATEXENGINE, LUATEXVERSION, LUATEXFUNCTIONALITY, LUATEXFORMATID, status.used_compiler) - end) - register("tex properties", function() - local t = status.gethashstate() - local m = status.gettexstate() - return format("%s hash slots used of %s, approximate memory usage: %i MB", - t.top, t.max, m.approximate // (1024 * 1024)) - end) - register("callbacks", statistics.callbacks) - -- so far - register("lua properties",function() - local hash = lua.gethashchars() - local mask = load([[τεχ = 1]]) and "utf" or "ascii" - return format("engine: %s %s, used memory: %s, hash chars: min(%i,40), symbol mask: %s (%s)", - "lua", LUAVERSION, statistics.memused(), hash, 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 - local luastate = status.getluastate() - return format("%s MB, ctx: %s MB, max: %s MB", - round(collectgarbage("count")//1024), - round(luastate.state_bytes//1048576), - luastate.state_bytes_max and round(luastate.state_bytes_max//1048576) or "unknown" - ) -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) - -- stoptiming(statistics) -- somehow we can start the timer twice, but where - local runtime = lua.getruntime and lua.getruntime() or elapsedtime(statistics) - return statistics.formatruntime(runtime) -end - -local report = logs.reporter("system") - -function statistics.timed(action,all) - starttiming("run") - action() - stoptiming("run") - local runtime = tonumber(elapsedtime("run")) - if all then - local alltime = tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics)) - if alltime and alltime > 0 then - report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime) - return - end - end - report("total runtime: %0.3f seconds",runtime) -end - --- goodie - -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 - --- now here - -status.iocodes = setmetatableindex(tex.getiovalues(), function() return "unknown" end) - -local report = logs.reporter("system") - -function statistics.showusage(when) - local s = status.list() - local c = status.getcallbackstate() -- status.callbacks - local m = mplib.getcallbackstate() - local b = backends.getcallbackstate() - -- - local estatus = s.expandstate - local tstatus = s.texstate - local lstatus = s.luastate - local rstatus = s.readstate - -- - local pstatus = logs.private.getpagetiming() - -- - local iocode = status.iocodes[rstatus.iocode] - -- - local mpinstances, mpmemory = metapost.getstatistics(true) - -- - report("") - if when == "finish" then - report("status after finishing run") - else - report("status after shipping out page %s",tex.getcount("realpageno")) - end - report("") - local list = { - "stringstate", "poolstate", "hashstate", "lookupstate", - "nodestate", "extrastate", "tokenstate", - "bufferstate", "inputstate", "filestate", - "neststate", "parameterstate", "savestate", - "fontstate", "languagestate", "markstate", "sparsestate", - } - local fields = { "max", "min", "set", "stp", false, "mem", "all", false, "ini", "ptr", "top" } - local line = rep("-",190) - do - local t = { } - for i=1,#list do - t[i] = gsub(list[i],"state","") - end - report("%w%s",2,line) - report("%w%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",5,unpack(t)) - report("%w%s",2,line) - end - for i=1,#fields do - local f = fields[i] - if f then - local t = { } - for i=1,#list do - local n = s[list[i]][f] - t[i] = n < 0 and formatters["%w"](11) or formatters["%11i"](n) - end - report(" %3s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",f,unpack(t)) - else - report("") - end - end - report("%w%s",2,line) - report("") - report(" current input type : %s", iocode) - if iocode == "file" then - report(" current file name : %s", rstatus.filename or "") - report(" current line number : %s", rstatus.linenumber) - end - report("") - report(" approximate memory : %s (%s MB)", tstatus.approximate, tstatus.approximate // 1048576) - report("") - report(" expansion depth : min: %s, max: %s, set: %s, top: %s", estatus.min, estatus.max, estatus.set, estatus.top) - report("") - report(" luabytecode registers : %s", lstatus.bytecodes) - report(" luabytecode bytes : %s (%s MB)", lstatus.bytecode_bytes, lstatus.bytecode_bytes // 1048576) - report(" luastate bytes now : %s (%s MB)", lstatus.state_bytes, lstatus.state_bytes // 1048576) - report(" luastate bytes max : %s (%s MB)", lstatus.state_bytes_max, lstatus.state_bytes_max // 1048576) - report("") - report(" file callbacks : %s", c.file) - report(" saved callbacks : %s", c.saved) - report(" direct callbacks : %s", c.direct) - report(" function callbacks : %s", c["function"]) - report(" value callbacks : %s", c.value) - report(" message callbacks : %s", c.message) - report(" bytecode callbacks : %s", c.bytecode) - report("") - report(" mp instances : %s", mpinstances) - report(" mp estimated memory : %s (%s MB)", mpmemory, mpmemory // 1048576) - report(" mp file callbacks : %s", m.file) - report(" mp text callbacks : %s", m.text) - report(" mp script callbacks : %s", m.script) - report(" mp log callbacks : %s", m.log) - report("") - report(" total callbacks : %s", c.count) - report(" mp total callbacks : %s", m.count) - report(" backend callbacks : %s", b.count) - report("") - report(" page numbers : realpage %s, userpage %s, subpage %s",pstatus.page.real,pstatus.page.user,pstatus.page.sub) - report(" page timing : total %0.03f, page %0.03f, average %0.03f",pstatus.time.elapsed,pstatus.time.page,pstatus.time.average) - report("") -end - -function statistics.showmemory(when) - local s = status.list() - -- - report("") - report("memory configuration") - report("") - local list = { - "stringstate", "poolstate", "hashstate", "lookupstate", - "nodestate", "tokenstate", - "bufferstate", "inputstate", "filestate", - "neststate", "parameterstate", "savestate", - "fontstate", "languagestate", "markstate", - } - local fields = { "max", "min", "set", "stp" } - local line = rep("-",168) - do - local t = { } - for i=1,#list do - t[i] = gsub(list[i],"state","") - end - report("%w%s",2,line) - report("%w%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",5,unpack(t)) - report("%w%s",2,line) - end - for i=1,#fields do - local f = fields[i] - if f then - local t = { } - for i=1,#list do - local n = s[list[i]][f] - t[i] = n < 0 and formatters["%w"](11) or formatters["%11i"](n) - end - report(" %3s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",f,unpack(t)) - else - report("") - end - end - report("%w%s",2,line) - report("") -end - -local registered = false -local enabled = false - -trackers.register("system.usage", function(v) - if v and not registered then - logs.private.enablepagetiming() - if v ~= "summary" then - luatex.registerpageactions(function() - if enabled then - statistics.showusage("page") - end - end) - end - luatex.registerstopactions(function() - if enabled then - statistics.showusage("finish") - end - end) - registered = true - end - enabled = v -end) diff --git a/tex/context/base/mkiv/trac-jus.mkxl b/tex/context/base/mkiv/trac-jus.mkxl deleted file mode 100644 index 0eacc886d..000000000 --- a/tex/context/base/mkiv/trac-jus.mkxl +++ /dev/null @@ -1,24 +0,0 @@ -%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}{} - -\unprotect - -\definesystemattribute [justification] [public] - -\protected\def\showjustification{\clf_showjustification} % currently no argument (default 1), todo: public implementor - -\protect \endinput diff --git a/tex/context/base/mkiv/trac-tex.mkxl b/tex/context/base/mkiv/trac-tex.mkxl deleted file mode 100644 index f9c763c4f..000000000 --- a/tex/context/base/mkiv/trac-tex.mkxl +++ /dev/null @@ -1,69 +0,0 @@ -%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}{} - -%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{...} - -\mutable\let\alltextracers\empty % so that we can report available tracers - -\permanent\protected\def\installtextracer#1% - {\addtocommalist{#1}\alltextracers} - -\permanent\protected\def\enabletextracers [#1]{\processcommalist[#1]\syst_textracers_enable } -\permanent\protected\def\disabletextracers[#1]{\processcommalist[#1]\syst_textracers_disable} - -\def\syst_textracers_enable #1{\begincsname enabletracer#1\endcsname} -\def\syst_textracers_disable#1{\begincsname disabletracer#1\endcsname} - -% The next one is for Taco, although we can use directives as well: - -\protected\def\nomkivstatistics{\enabledirectives[system.nostatistics]} - -%D This is not really a tracker but for decades it lived in my \type {cont-loc} -%D file. I moved it here because I wanted someone else to use it. This macro is not -%D really useful for users. I kept the \LUA\ variant in \type {cont-loc.mkiv}. - -\installcorenamespace{profilemacrocount} -\installcorenamespace{profilemacromacro} - -\newtoks\t_syst_profile - -\appendtoks - \the\t_syst_profile -\to \everystoptext - -\permanent\protected\def\profilemacro#1% an oldie, but modernized a bit - {\edef\p_name{\csstring#1}% - \ifcsname\??profilemacrocount\p_name\endcsname \else - \expandafter\newcount\csname\??profilemacrocount\p_name\endcsname - \letcsname\??profilemacromacro\p_name\endcsname#1% - \xtoksapp\t_syst_profile - {\writestatus - {profile}% - {\string#1: \noexpand\the\csname\??profilemacrocount\p_name\endcsname}}% - \enforced\protected\xdef#1% - {\global\advance\csname\??profilemacrocount\p_name\endcsname\plusone - \expandafter\noexpand\csname\??profilemacromacro\p_name\endcsname}% - \fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/trac-tim.lmt b/tex/context/base/mkiv/trac-tim.lmt deleted file mode 100644 index fcba7f132..000000000 --- a/tex/context/base/mkiv/trac-tim.lmt +++ /dev/null @@ -1,178 +0,0 @@ -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.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 function convert(name) - name = name ~= "" and name or progress.defaultfilename - if not processed[name] then - local pages = 0 - local names = { } - local top = { } - local bot = { } - local siz = { } - local paths = { } - local data = table.load(name .. ".lut") - if data then - pages = #data - if pages > 1 then - - local factor = 100 - - local function path(tag,subtag,tagname) - local tagname = tag .. ": " .. subtag - local b, t, s = nil, nil, { } - for k=1,#data do - local v = data[k][tag] - v = v and v[subtag] - if v then - if type(v) == "table" then - set[tagname] = tonumber(v.set) - v = tonumber(v.top) - else - v = tonumber(v) - end - if v then - if b then - if v > t then t = v end - if v < b then b = v end - else - t = v - b = v - end - else - v = 0 - end - else - v = 0 - end - s[k] = v - end - if not b then - -- safeguard against updates - b = 0 - t = 0 - end - 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,"--") - return tagname - end - - local function collect(category) - if data[1][category] then - local keys = { } - for k=1,#data do - for k, v in next, data[k][category] do - keys[k] = true - end - end - for k=1,#data do - local m = data[k][category] - for k, v in next, keys do - if not m[k] then m[k] = 0 end - end - end - for k in next, keys do - names[#names+1] = path(category,k) - end - end - end - - collect("nodes") - collect("stock") - collect("memories") - collect("variables") - collect("texvariables") - collect("luavariables") - collect("texcallbacks") - collect("mpcallbacks") - collect("backendcallbacks") - - pages = pages - 1 -- hm - end - end - - sort(names) - - processed[name] = { - names = names, - top = top, - bot = bot, - set = set, - pages = pages, - paths = paths, - } - end - return processed[name] -end - -progress.convert = convert - -function progress.set(name,tag) - return convert(name).set[tag] or 0 -end - -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.names(name) - return convert(name).names or { } -end - diff --git a/tex/context/base/mkiv/trac-vis.lmt b/tex/context/base/mkiv/trac-vis.lmt deleted file mode 100644 index 7ac5964da..000000000 --- a/tex/context/base/mkiv/trac-vis.lmt +++ /dev/null @@ -1,1700 +0,0 @@ -if not modules then modules = { } end modules ['trac-vis'] = { - version = 1.001, - optimize = true, - comment = "companion to trac-vis.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local node, nodes, attributes, tex = node, nodes, attributes, tex -local type, tonumber, next, rawget = type, tonumber, next, rawget -local gmatch = string.gmatch -local formatters = string.formatters -local round = math.round - --- This module started out in the early days of mkiv and luatex with visualizing --- kerns related to fonts. In the process of cleaning up the visual debugger code it --- made sense to integrate some other code that I had laying around and replace the --- old supp-vis debugging code. As only a subset of the old visual debugger makes --- sense it has become a different implementation. Soms of the m-visual --- functionality will also be ported. The code is rather trivial. The caching is not --- really needed but saves upto 50% of the time needed to add visualization. Of --- course the overall runtime is larger because of color and layer processing in the --- backend (can be times as much) so the runtime is somewhat larger with full --- visualization enabled. In practice this will never happen unless one is demoing. - --- todo: global switch (so no attributes) --- todo: maybe also xoffset, yoffset of glyph --- todo: inline concat (more efficient) --- todo: tags can also be numbers (just add to hash) --- todo: make a lmtx variant (a few more efficient fetchers) - -local nodecodes = nodes.nodecodes - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local setboth = nuts.setboth -local setlink = nuts.setlink -local setdisc = nuts.setdisc -local setlist = nuts.setlist -local setleader = nuts.setleader -local setsubtype = nuts.setsubtype -local setattr = nuts.setattr -local setwidth = nuts.setwidth -local setshift = nuts.setshift - -local getid = nuts.getid -local getfont = nuts.getfont -local getattr = nuts.getattr -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox -local getlist = nuts.getlist -local getleader = nuts.getleader -local getnext = nuts.getnext -local getboth = nuts.getboth -local getdisc = nuts.getdisc -local getwhd = nuts.getwhd -local getkern = nuts.getkern -local getpenalty = nuts.getpenalty -local getwidth = nuts.getwidth -local getdepth = nuts.getdepth -local getshift = nuts.getshift -local getexpansion = nuts.getexpansion -local getdirection = nuts.getdirection -local getstate = nuts.getstate - -local isglyph = nuts.isglyph - -local hpack_nodes = nuts.hpack -local vpack_nodes = nuts.vpack -local copy_list = nuts.copy_list -local copy_node = nuts.copy_node -local flush_node_list = nuts.flush_list -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local apply_to_nodes = nuts.apply -local effectiveglue = nuts.effective_glue - -local hpack_string = nuts.typesetters.tohpack - -local texgetattribute = tex.getattribute -local texsetattribute = tex.setattribute - -local setmetatableindex = table.setmetatableindex - -local unsetvalue = attributes.unsetvalue - -local current_font = font.current - -local fonthashes = fonts.hashes -local chardata = fonthashes.characters -local exheights = fonthashes.exheights -local emwidths = fonthashes.emwidths -local pt_factor = number.dimenfactors.pt - -local nodepool = nuts.pool -local new_rule = nodepool.rule -local new_kern = nodepool.kern -local new_glue = nodepool.glue -local new_hlist = nodepool.hlist -local new_vlist = nodepool.vlist - -local tracers = nodes.tracers -local visualizers = nodes.visualizers - -local setcolor = tracers.colors.set -local setlistcolor = tracers.colors.setlist -local settransparency = tracers.transparencies.set -local setlisttransparency = tracers.transparencies.setlist - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local a_visual = attributes.private("visual") -local a_layer = attributes.private("viewerlayer") - -local band = bit32.band -local bor = bit32.bor - -local enableaction = nodes.tasks.enableaction - --- local trace_hbox --- local trace_vbox --- local trace_vtop --- local trace_kern --- local trace_glue --- local trace_penalty --- local trace_fontkern --- local trace_strut --- local trace_whatsit --- local trace_user --- local trace_math --- local trace_italic --- local trace_discretionary --- local trace_expansion --- local trace_line --- local trace_space - -local report_visualize = logs.reporter("visualize") - -local modes = { - hbox = 0x000001, - vbox = 0x000002, - vtop = 0x000004, - kern = 0x000008, - glue = 0x000010, - penalty = 0x000020, - fontkern = 0x000040, - strut = 0x000080, - whatsit = 0x000100, - glyph = 0x000200, - simple = 0x000400, - simplehbox = 0x000401, - simplevbox = 0x000402, - simplevtop = 0x000404, - user = 0x000800, - math = 0x001000, - italic = 0x002000, - origin = 0x004000, - discretionary = 0x008000, - expansion = 0x010000, - line = 0x020000, - space = 0x040000, - depth = 0x080000, - marginkern = 0x100000, - mathlistkern = 0x200000, - dir = 0x400000, - par = 0x800000, -} - -local usedfont, exheight, emwidth -local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_marginkern, l_mathlistkern, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth, - l_dir, l_whatsit - -local enabled = false -local layers = { } - -local preset_boxes = modes.hbox + modes.vbox + modes.vtop + modes.origin -local preset_makeup = preset_boxes - + modes.kern + modes.glue + modes.penalty -local preset_all = preset_makeup - + modes.fontkern + modes.marginkern + modes.mathlistkern - + modes.whatsit + modes.glyph + modes.user + modes.math - + modes.dir + modes.whatsit - -function visualizers.setfont(id) - usedfont = id or current_font() - exheight = exheights[usedfont] - emwidth = emwidths[usedfont] -end - --- we can preset a bunch of bits - -local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") -local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") - -local function initialize() - -- - if not usedfont then - -- we use a narrow monospaced font -- infofont ? - visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") }) - end - -- - for mode, value in next, modes do - local tag = formatters["v_%s"](mode) - attributes.viewerlayers.define { - tag = tag, - title = formatters["visualizer %s"](mode), - visible = "start", - editable = "yes", - printable = "yes" - } - layers[mode] = attributes.viewerlayers.register(tag,true) - end - l_hbox = layers.hbox - l_vbox = layers.vbox - l_vtop = layers.vtop - l_glue = layers.glue - l_kern = layers.kern - l_penalty = layers.penalty - l_fontkern = layers.fontkern - l_strut = layers.strut - l_whatsit = layers.whatsit - l_glyph = layers.glyph - l_user = layers.user - l_math = layers.math - l_italic = layers.italic - l_marginkern = layers.marginkern - l_mathlistkern = layers.mathlistkern - l_origin = layers.origin - l_discretionary = layers.discretionary - l_expansion = layers.expansion - l_line = layers.line - l_space = layers.space - l_depth = layers.depth - l_dir = layers.dir - l_par = layers.par - -- - if not userrule then - userrule = nuts.rules.userrule - end - -- - if not outlinerule then - outlinerule = nuts.pool.outlinerule - end - initialize = false -end - -local function enable() - if initialize then - initialize() - end - enableaction("shipouts","nodes.visualizers.handler") - report_visualize("enabled") - enabled = true - tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end -end - -local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in - if not n or n == "reset" then - return unsetvalue - elseif n == true or n == "makeup" then - if not a or a == 0 or a == unsetvalue then - a = preset_makeup - else - a = bor(a,preset_makeup) - end - elseif n == "boxes" then - if not a or a == 0 or a == unsetvalue then - a = preset_boxes - else - a = bor(a,preset_boxes) - end - elseif n == "all" then - if what == false then - return unsetvalue - elseif not a or a == 0 or a == unsetvalue then - a = preset_all - else - a = bor(a,preset_all) - end - else - for s in gmatch(n,"[a-z]+") do - local m = modes[s] - if not m then - -- go on - elseif not a or a == 0 or a == unsetvalue then - a = m - else - a = bor(a,m) - end - end - end - if not a or a == 0 or a == unsetvalue then - return unsetvalue - elseif not enabled then -- must happen at runtime (as we don't store layers yet) - enable() - end - return a -end - -function nuts.setvisual(n,mode) - setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true)) -end - -function nuts.setvisuals(n,mode) -- currently the same - setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true,true)) -end - --- fast setters - -do - - local cached = setmetatableindex(function(t,k) - if k == true then - return texgetattribute(a_visual) - elseif not k then - t[k] = unsetvalue - return unsetvalue - else - local v = setvisual(k) - t[k] = v - return v - end - end) - - -- local function applyvisuals(n,mode) - -- local a = cached[mode] - -- apply_to_nodes(n,function(n) setattr(n,a_visual,a) end) - -- end - - local a = unsetvalue - - local f = function(n) setattr(n,a_visual,a) end - - local function applyvisuals(n,mode) - a = cached[mode] - apply_to_nodes(n,f) - end - - nuts.applyvisuals = applyvisuals - - function nodes.applyvisuals(n,mode) - applyvisuals(tonut(n),mode) - end - - function visualizers.attribute(mode) - return cached[mode] - end - - visualizers.attributes = cached - -end - -function nuts.copyvisual(n,m) - setattr(n,a_visual,getattr(m,a_visual)) -end - -function visualizers.setvisual(n) - texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual))) -end - -function visualizers.setlayer(n) - texsetattribute(a_layer,layers[n] or unsetvalue) -end - -local function set(mode,v) - texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v)) -end - -for mode, value in next, modes do - trackers.register(formatters["visualizers.%s"](mode), function(v) set(mode,v) end) -end - -local fraction = 10 - -trackers .register("visualizers.reset", function(v) set("reset", v) end) -trackers .register("visualizers.all", function(v) set("all", v) end) -trackers .register("visualizers.makeup", function(v) set("makeup",v) end) -trackers .register("visualizers.boxes", function(v) set("boxes", v) end) -directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end) - -local c_positive = "trace:b" -local c_negative = "trace:r" -local c_zero = "trace:g" -local c_text = "trace:s" -local c_space = "trace:y" -local c_space_x = "trace:m" -local c_skip_a = "trace:c" -local c_skip_b = "trace:m" -local c_glyph = "trace:o" -local c_ligature = "trace:s" -local c_white = "trace:w" ------ c_math = "trace:s" ------ c_origin = "trace:o" ------ c_discretionary = "trace:d" ------ c_expansion = "trace:o" -local c_depth = "trace:o" -local c_indent = "trace:s" - -local c_positive_d = "trace:db" -local c_negative_d = "trace:dr" -local c_zero_d = "trace:dg" -local c_text_d = "trace:ds" -local c_space_d = "trace:dy" -local c_space_x_d = "trace:dm" -local c_skip_a_d = "trace:dc" -local c_skip_b_d = "trace:dm" -local c_glyph_d = "trace:do" -local c_ligature_d = "trace:ds" -local c_white_d = "trace:dw" -local c_math_d = "trace:dr" -local c_origin_d = "trace:do" -local c_discretionary_d = "trace:dd" ------ c_expansion_d = "trace:do" ------ c_depth_d = "trace:do" ------ c_indent_d = "trace:ds" - -local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed - local text = hpack_string(str,usedfont) - local size = getwidth(text) - local rule = new_rule(size,2*exheight,exheight/2) - local kern = new_kern(-size) - if color then - setcolor(rule,color) - end - if textcolor then - setlistcolor(getlist(text),textcolor) - end - local info = setlink(rule,kern,text) - setlisttransparency(info,c_zero) - info = hpack_nodes(info) - local width = getwidth(info) - if lap then - info = new_hlist(setlink(new_kern(-width),info)) - else - info = new_hlist(info) -- a bit overkill: double wrapped - end - if layer then - setattr(info,a_layer,layer) - end - return info, width -end - -local function someblob(str,layer,color,textcolor,width) - local text = hpack_string(str,usedfont) - local size = getwidth(text) - local rule = new_rule(width,2*exheight,exheight/2) - local kern = new_kern(-width + (width-size)/2) - if color then - setcolor(rule,color) - end - if textcolor then - setlistcolor(getlist(text),textcolor) - end - local info = setlink(rule,kern,text) - setlisttransparency(info,c_zero) - info = hpack_nodes(info) - local width = getwidth(info) - info = new_hlist(info) - if layer then - setattr(info,a_layer,layer) - end - return info, width -end - -local caches = setmetatableindex("table") - -local fontkern, italickern, marginkern, mathlistkern do - - local f_cache = caches["fontkern"] - local i_cache = caches["italickern"] - local m_cache = caches["marginkern"] - local l_cache = caches["mathlistkern"] - - local function somekern(head,current,cache,color,layer) - local width = getkern(current) - local extra = getexpansion(current) - local kern = width + extra - local info = cache[kern] - if not info then - local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont) - local rule = new_rule(emwidth/fraction,6*exheight,2*exheight) - local list = getlist(text) - if kern > 0 then - setlistcolor(list,c_positive_d) - elseif kern < 0 then - setlistcolor(list,c_negative_d) - else - setlistcolor(list,c_zero_d) - end - setlisttransparency(list,color) - setcolor(rule,color) - settransparency(rule,color) - setshift(text,-5 * exheight) - info = new_hlist(setlink(rule,text)) - setattr(info,a_layer,layer) - f_cache[kern] = info - end - head = insert_node_before(head,current,copy_list(info)) - return head, current - end - - fontkern = function(head,current) - return somekern(head,current,f_cache,c_text_d,l_fontkern) - end - - italickern = function(head,current) - return somekern(head,current,i_cache,c_glyph_d,l_italic) - end - - marginkern = function(head,current) - return somekern(head,current,m_cache,c_glyph_d,l_marginkern) - end - - mathlistkern = function(head,current) - return somekern(head,current,l_cache,c_glyph_d,l_mathlistkern) - end - -end - -local glyphexpansion do - - local f_cache = caches["glyphexpansion"] - - glyphexpansion = function(head,current) - local extra = getexpansion(current) - if extra and extra ~= 0 then - extra = extra / 1000 - local info = f_cache[extra] - if not info then - local text = hpack_string(round(extra),usedfont) - local rule = new_rule(emwidth/fraction,exheight,2*exheight) - local list = getlist(text) - if extra > 0 then - setlistcolor(list,c_positive_d) - elseif extra < 0 then - setlistcolor(list,c_negative_d) - end - setlisttransparency(list,c_text_d) - setcolor(rule,c_text_d) - settransparency(rule,c_text_d) - setshift(text,1.5 * exheight) - info = new_hlist(setlink(rule,text)) - setattr(info,a_layer,l_expansion) - f_cache[extra] = info - end - head = insert_node_before(head,current,copy_list(info)) - return head, current - end - return head, current - end - -end - -local kernexpansion do - - local f_cache = caches["kernexpansion"] - - -- in mkiv we actually need to reconstruct but let's not do that now - - kernexpansion = function(head,current) - local extra = getexpansion(current) - if extra ~= 0 then - extra = extra / 1000 - local info = f_cache[extra] - if not info then - local text = hpack_string(round(extra),usedfont) - local rule = new_rule(emwidth/fraction,exheight,4*exheight) - local list = getlist(text) - if extra > 0 then - setlistcolor(list,c_positive_d) - elseif extra < 0 then - setlistcolor(list,c_negative_d) - end - setlisttransparency(list,c_text_d) - setcolor(rule,c_text_d) - settransparency(rule,c_text_d) - setshift(text,3.5 * exheight) - info = new_hlist(setlink(rule,text)) - setattr(info,a_layer,l_expansion) - f_cache[extra] = info - end - head = insert_node_before(head,current,copy_list(info)) - return head, current - end - return head, current - end - -end - -local whatsit do - - local whatsitcodes = nodes.whatsitcodes - local w_cache = caches["whatsit"] - - local tags = { - open = "OPN", - write = "WRI", - close = "CLS", - special = "SPE", - latelua = "LUA", - savepos = "POS", - userdefined = "USR", - literal = "LIT", - setmatrix = "MAT", - save = "SAV", - restore = "RES", - } - - whatsit = function(head,current) - local what = getsubtype(current) - local info = w_cache[what] - if info then - -- print("hit whatsit") - else - info = sometext(formatters["W:%s"](what),usedfont,nil,c_white) - setattr(info,a_layer,l_whatsit) - w_cache[what] = info - end - head, current = insert_node_after(head,current,copy_list(info)) - return head, current - end - -end - -local dir, par do - - local dircodes = nodes.dircodes - local dirvalues = nodes.dirvalues - - local cancel_code = dircodes.cancel - local l2r_code = dirvalues.l2r - local r2l_code = dirvalues.r2l - - local d_cache = caches["dir"] - - local tags = { - l2r = "L2R", - r2l = "R2L", - cancel = "CAN", - par = "PAR", - } - - par = function(head,current) - local what = "par" -- getsubtype(current) - local info = d_cache[what] - if info then - -- print("hit par") - else - info = sometext(formatters["L:%s"](what),usedfont,nil,c_white) - setattr(info,a_layer,l_dir) - d_cache[what] = info - end - return head, current - end - - dir = function(head,current) - local what = getsubtype(current) - if what == cancelcode then - what = "cancel" - elseif getdirection(current) == r2l_code then - what = "r2l" - else - what = "l2r" - end - local info = d_cache[what] - if info then - -- print("hit dir") - else - info = sometext(formatters["D:%s"](what),usedfont,nil,c_white) - setattr(info,a_layer,l_dir) - d_cache[what] = info - end - return head, current - end - -end - -local user do - - local u_cache = caches["user"] - - user = function(head,current) - local what = getsubtype(current) - local info = u_cache[what] - if info then - -- print("hit user") - else - info = sometext(formatters["U:%s"](what),usedfont) - setattr(info,a_layer,l_user) - u_cache[what] = info - end - head, current = insert_node_after(head,current,copy_list(info)) - return head, current - end - -end - -local math do - - local mathcodes = nodes.mathcodes - local m_cache = { - beginmath = caches["bmath"], - endmath = caches["emath"], - } - local tags = { - beginmath = "B", - endmath = "E", - } - - math = function(head,current) - local what = getsubtype(current) - local tag = mathcodes[what] - local skip = getkern(current) + getwidth(current) -- surround - local info = m_cache[tag][skip] - if info then - -- print("hit math") - else - local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d) - local rule = new_rule(skip,-655360/fraction,2*655360/fraction) - setcolor(rule,c_math_d) - settransparency(rule,c_math_d) - setattr(rule,a_layer,l_math) - if tag == "beginmath" then - info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text)) - else - info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text)) - end - setattr(info,a_layer,l_math) - m_cache[tag][skip] = info - end - head, current = insert_node_after(head,current,copy_list(info)) - return head, current - end - -end - -local ruleddepth do - - ruleddepth = function(current,wd,ht,dp) - local wd, ht, dp = getwhd(current) - if dp ~= 0 then - local rule = new_rule(wd,0,dp) - setcolor(rule,c_depth) - settransparency(rule,c_zero) - setattr(rule,a_layer,l_depth) - setlist(current,setlink(rule,new_kern(-wd),getlist(current))) - end - end - -end - -local ruledbox do - - local b_cache = caches["box"] - local o_cache = caches["origin"] - - setmetatableindex(o_cache,function(t,size) - local rule = new_rule(2*size,size,size) - local origin = hpack_nodes(rule) - setcolor(rule,c_origin_d) - settransparency(rule,c_origin_d) - setattr(rule,a_layer,l_origin) - t[size] = origin - return origin - end) - - ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent) - local wd, ht, dp = getwhd(current) - if wd ~= 0 then - local shift = getshift(current) - local next = getnext(current) - local prev = previous - setboth(current) - local linewidth = emwidth/fraction - local size = 2*linewidth - local this - if not simple then - this = b_cache[what] - if not this then - local text = hpack_string(what,usedfont) - this = setlink(new_kern(-getwidth(text)),text) - setlisttransparency(this,c_text) - this = new_hlist(this) - b_cache[what] = this - end - end - -- we need to trigger the right mode (else sometimes no whatits) - local info = setlink( - this and copy_list(this) or nil, - (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { - width = wd, - height = ht, - depth = dp, - line = linewidth, - type = "box", - dashed = 3*size, - } - ) - -- - setlisttransparency(info,c_text) - info = new_hlist(info) -- important - -- - setattr(info,a_layer,layer) - if vertical then - if shift == 0 then - info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) - elseif trace_origin then - local size = 2*size - local origin = o_cache[size] - origin = copy_list(origin) - if getid(parent) == vlist_code then - setshift(origin,-shift) - info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info) - else - -- todo .. i need an example - info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) - end - setshift(current,0) - else - info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info) - setshift(current,0) - end - info = new_vlist(info,wd,ht,dp,shift) - else - if shift == 0 then - info = setlink(current,new_kern(-wd),info) - elseif trace_origin then - local size = 2*size - local origin = o_cache[size] - origin = copy_list(origin) - if getid(parent) == vlist_code then - info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info) - else - setshift(origin,-shift) - info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info) - end - setshift(current,0) - else - info = setlink(current,new_kern(-wd),info) - setshift(current,0) - end - info = new_hlist(info,wd,ht,dp,shift) - end - if next then - setlink(info,next) - end - if prev and prev > 0 then - setlink(prev,info) - end - if head == current then - return info, info - else - return head, info - end - else - return head, current - end - end - -end - -local ruledglyph do - - -- see boundingbox feature .. maybe a pdf stream is more efficient, after all we - -- have a frozen color anyway or i need a more detailed cache .. below is a more - -- texie approach - - ruledglyph = function(head,current,previous) -- wrong for vertical glyphs - local wd = getwidth(current) - if wd ~= 0 then - local wd, ht, dp = getwhd(current) - local next = getnext(current) - local prev = previous - setboth(current) - local linewidth = emwidth/(2*fraction) - local info - -- - info = setlink( - (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { - width = wd, - height = ht, - depth = dp, - line = linewidth, - type = "box", - }, - new_kern(-wd) - ) - -- - local c, f = isglyph(current) - local char = chardata[f][c] - if char and type(char.unicode) == "table" then -- hackery test - setlistcolor(info,c_ligature) - setlisttransparency(info,c_ligature_d) - else - setlistcolor(info,c_glyph) - setlisttransparency(info,c_glyph_d) - end - info = new_hlist(info) - setattr(info,a_layer,l_glyph) - local info = setlink(current,new_kern(-wd),info) - info = hpack_nodes(info) - setwidth(info,wd) - if next then - setlink(info,next) - end - if prev then - setlink(prev,info) - end - if head == current then - return info, info - else - return head, info - end - else - return head, current - end - end - - function visualizers.setruledglyph(f) - ruledglyph = f or ruledglyph - end - -end - -local ruledglue do - - local gluecodes = nodes.gluecodes - - local userskip_code = gluecodes.userskip - local spaceskip_code = gluecodes.spaceskip - local xspaceskip_code = gluecodes.xspaceskip - local zerospaceskip_code = gluecodes.zerospaceskip or gluecodes.userskip - -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip - local leftskip_code = gluecodes.leftskip - local rightskip_code = gluecodes.rightskip - local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code - local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code - local indentskip_code = gluecodes.indentskip - local correctionskip_code = gluecodes.correctionskip - - local g_cache_v = caches["vglue"] - local g_cache_h = caches["hglue"] - - local tags = { - -- [userskip_code] = "US", - [gluecodes.lineskip] = "LI", - [gluecodes.baselineskip] = "BS", - [gluecodes.parskip] = "PS", - [gluecodes.abovedisplayskip] = "DA", - [gluecodes.belowdisplayskip] = "DB", - [gluecodes.abovedisplayshortskip] = "SA", - [gluecodes.belowdisplayshortskip] = "SB", - [gluecodes.topskip] = "TS", - [gluecodes.splittopskip] = "ST", - [gluecodes.tabskip] = "AS", - [gluecodes.lefthangskip] = "LH", - [gluecodes.righthangskip] = "RH", - [gluecodes.thinmuskip] = "MS", - [gluecodes.medmuskip] = "MM", - [gluecodes.thickmuskip] = "ML", - [gluecodes.intermathskip] = "IM", - [gluecodes.keepskip or 99] = "KS", - [gluecodes.mathskip] = "MT", - [gluecodes.leaders] = "NL", - [gluecodes.cleaders] = "CL", - [gluecodes.xleaders] = "XL", - [gluecodes.gleaders] = "GL", - -- true = "VS", - -- false = "HS", - [leftskip_code] = "LS", - [rightskip_code] = "RS", - [spaceskip_code] = "SP", - [xspaceskip_code] = "XS", - [zerospaceskip_code] = "ZS", - [parfillleftskip_code] = "PL", - [parfillrightskip_code] = "PR", - [indentskip_code] = "IN", - [correctionskip_code] = "CS", - } - - -- we sometimes pass previous as we can have issues in math (not watertight for all) - - ruledglue = function(head,current,vertical,parent) - local subtype = getsubtype(current) - local width = effectiveglue(current,parent) - local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) - local info = (vertical and g_cache_v or g_cache_h)[amount] - if info then - -- print("glue hit") - else - if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then - info = sometext(amount,l_glue,c_space) - elseif subtype == leftskip_code or subtype == rightskip_code then - info = sometext(amount,l_glue,c_skip_a) - elseif subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then - info = sometext(amount,l_glue,c_indent) - elseif subtype == userskip_code then - if width > 0 then - info = sometext(amount,l_glue,c_positive) - elseif width < 0 then - info = sometext(amount,l_glue,c_negative) - else - info = sometext(amount,l_glue,c_zero) - end - else - info = sometext(amount,l_glue,c_skip_b) - end - (vertical and g_cache_v or g_cache_h)[amount] = info - end - info = copy_list(info) - if vertical then - info = vpack_nodes(info) - end - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - - -- ruledspace = function(head,current,parent) - -- local subtype = getsubtype(current) - -- if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then - -- local width = effectiveglue(current,parent) - -- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor) - -- local info = g_cache_h[amount] - -- if info then - -- -- print("space hit") - -- else - -- info = sometext(amount,l_glue,c_space) - -- g_cache_h[amount] = info - -- end - -- info = copy_list(info) - -- head, current = insert_node_before(head,current,info) - -- return head, getnext(current) - -- else - -- return head, current - -- end - -- end - - local g_cache_s = caches["space"] - local g_cache_x = caches["xspace"] - - ruledspace = function(head,current,parent) - local subtype = getsubtype(current) - if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then -- not yet all space - local width = effectiveglue(current,parent) - local info - if subtype == spaceskip_code then - info = g_cache_s[width] - if not info then - info = someblob("SP",l_glue,c_space,nil,width) - g_cache_s[width] = info - end - else - info = g_cache_x[width] - if not info then - info = someblob("XS",l_glue,c_space_x,nil,width) - g_cache_x[width] = info - end - end - info = copy_list(info) - head, current = insert_node_before(head,current,info) - return head, getnext(current) - else - return head, current - end - end - -end - -local ruledkern do - - local k_cache_v = caches["vkern"] - local k_cache_h = caches["hkern"] - - ruledkern = function(head,current,vertical,mk) - local kern = getkern(current) - local cache = vertical and k_cache_v or k_cache_h - local info = cache[kern] - if not info then - local amount = formatters["%s:%0.3f"](vertical and "VK" or (mk and "MK") or "HK",kern*pt_factor) - if kern > 0 then - info = sometext(amount,l_kern,c_positive) - elseif kern < 0 then - info = sometext(amount,l_kern,c_negative) - else - info = sometext(amount,l_kern,c_zero) - end - cache[kern] = info - end - info = copy_list(info) - if vertical then - info = vpack_nodes(info) - end - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - -end - -local ruleditalic do - - local i_cache = caches["italic"] - - ruleditalic = function(head,current) - local kern = getkern(current) - local info = i_cache[kern] - if not info then - local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor) - if kern > 0 then - info = sometext(amount,l_kern,c_positive) - elseif kern < 0 then - info = sometext(amount,l_kern,c_negative) - else - info = sometext(amount,l_kern,c_zero) - end - i_cache[kern] = info - end - info = copy_list(info) - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - -end - -local ruledmarginkern do - - local m_cache = caches["marginkern"] - - ruledmarginkern = function(head,current) - local kern = getkern(current) - local info = m_cache[kern] - if not info then - local amount = formatters["%s:%0.3f"]("MK",kern*pt_factor) - if kern > 0 then - info = sometext(amount,l_marginkern,c_positive) - elseif kern < 0 then - info = sometext(amount,l_marginkern,c_negative) - else - info = sometext(amount,l_marginkern,c_zero) - end - m_cache[kern] = info - end - info = copy_list(info) - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - -end - -local ruledmathlistkern do - - local l_cache = caches["mathlistkern"] - - ruledmathlistkern = function(head,current) - local kern = getkern(current) - local info = l_cache[kern] - if not info then - local amount = formatters["%s:%0.3f"]("LK",kern*pt_factor) - if kern > 0 then - info = sometext(amount,l_mathlistkern,c_positive) - elseif kern < 0 then - info = sometext(amount,l_mathlistkern,c_negative) - else - info = sometext(amount,l_mathlistkern,c_zero) - end - l_cache[kern] = info - end - info = copy_list(info) - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - -end - -local ruleddiscretionary do - - local d_cache = caches["discretionary"] - - ruleddiscretionary = function(head,current) - local d = d_cache[true] - if not the_discretionary then - local rule = new_rule(4*emwidth/fraction,4*exheight,exheight) - local kern = new_kern(-2*emwidth/fraction) - setlink(kern,rule) - setcolor(rule,c_discretionary_d) - settransparency(rule,c_discretionary_d) - setattr(rule,a_layer,l_discretionary) - d = new_hlist(kern) - d_cache[true] = d - end - insert_node_after(head,current,copy_list(d)) - return head, current - end - -end - -local ruledpenalty do - - local p_cache_v = caches["vpenalty"] - local p_cache_h = caches["hpenalty"] - - local raisepenalties = false - - directives.register("visualizers.raisepenalties",function(v) raisepenalties = v end) - - ruledpenalty = function(head,current,vertical) - local penalty = getpenalty(current) - local info = (vertical and p_cache_v or p_cache_h)[penalty] - if info then - -- print("penalty hit") - else - local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty) - if penalty > 0 then - info = sometext(amount,l_penalty,c_positive) - elseif penalty < 0 then - info = sometext(amount,l_penalty,c_negative) - else - info = sometext(amount,l_penalty,c_zero) - end - (vertical and p_cache_v or p_cache_h)[penalty] = info - end - info = copy_list(info) - if vertical then - info = vpack_nodes(info) - elseif raisepenalties then - setshift(info,-65536*4) - end - head, current = insert_node_before(head,current,info) - return head, getnext(current) - end - -end - -do - - local disc_code = nodecodes.disc - local kern_code = nodecodes.kern - local glyph_code = nodecodes.glyph - local glue_code = nodecodes.glue - local penalty_code = nodecodes.penalty - local whatsit_code = nodecodes.whatsit - local user_code = nodecodes.user - local math_code = nodecodes.math - local hlist_code = nodecodes.hlist - local vlist_code = nodecodes.vlist - local marginkern_code = nodecodes.marginkern - local mathlistkern_code = nodecodes.mathlistkern - local dir_code = nodecodes.dir - local par_code = nodecodes.par - - local kerncodes = nodes.kerncodes - local fontkern_code = kerncodes.fontkern - local italickern_code = kerncodes.italiccorrection - local leftmarginkern_code = kerncodes.leftmarginkern - local rightmarginkern_code = kerncodes.rightmarginkern - local mathlistkern_code = kerncodes.mathlistkern - ----- userkern_code = kerncodes.userkern - - local listcodes = nodes.listcodes - local linelist_code = listcodes.line - - local vtop_package_state = 3 -- todo: symbolic - - local cache - - local function visualize(head,vertical,forced,parent) - local trace_hbox = false - local trace_vbox = false - local trace_vtop = false - local trace_kern = false - local trace_glue = false - local trace_penalty = false - local trace_fontkern = false - local trace_strut = false - local trace_whatsit = false - local trace_glyph = false - local trace_simple = false - local trace_user = false - local trace_math = false - local trace_italic = false - local trace_origin = false - local trace_discretionary = false - local trace_expansion = false - local trace_line = false - local trace_space = false - local trace_depth = false - local trace_dir = false - local trace_par = false - local current = head - local previous = nil - local attr = unsetvalue - local prev_trace_fontkern = nil - local prev_trace_italic = nil - local prev_trace_marginkern = nil --- local prev_trace_mathlist = nil - local prev_trace_expansion = nil - - while current do - local id = getid(current) - local a = forced or getattr(current,a_visual) or unsetvalue - local subtype - if a ~= attr then - prev_trace_fontkern = trace_fontkern - prev_trace_italic = trace_italic - prev_trace_marginkern = trace_marginkern --- prev_trace_mathlistkern = trace_mathlistkern - prev_trace_expansion = trace_expansion - attr = a - if a == unsetvalue then - trace_hbox = false - trace_vbox = false - trace_vtop = false - trace_kern = false - trace_glue = false - trace_penalty = false - trace_fontkern = false - trace_strut = false - trace_whatsit = false - trace_glyph = false - trace_simple = false - trace_user = false - trace_math = false - trace_italic = false - trace_origin = false - trace_discretionary = false - trace_expansion = false - trace_line = false - trace_space = false - trace_depth = false - trace_marginkern = false - trace_mathlistkern = false - trace_dir = false - trace_par = false - if id == kern_code then - goto kern - else - goto list - end - else -- dead slow: - -- cache[a]() - trace_hbox = band(a,0x000001) ~= 0 - trace_vbox = band(a,0x000002) ~= 0 - trace_vtop = band(a,0x000004) ~= 0 - trace_kern = band(a,0x000008) ~= 0 - trace_glue = band(a,0x000010) ~= 0 - trace_penalty = band(a,0x000020) ~= 0 - trace_fontkern = band(a,0x000040) ~= 0 - trace_strut = band(a,0x000080) ~= 0 - trace_whatsit = band(a,0x000100) ~= 0 - trace_glyph = band(a,0x000200) ~= 0 - trace_simple = band(a,0x000400) ~= 0 - trace_user = band(a,0x000800) ~= 0 - trace_math = band(a,0x001000) ~= 0 - trace_italic = band(a,0x002000) ~= 0 - trace_origin = band(a,0x004000) ~= 0 - trace_discretionary = band(a,0x008000) ~= 0 - trace_expansion = band(a,0x010000) ~= 0 - trace_line = band(a,0x020000) ~= 0 - trace_space = band(a,0x040000) ~= 0 - trace_depth = band(a,0x080000) ~= 0 - trace_marginkern = band(a,0x100000) ~= 0 - trace_mathlistkern = band(a,0x200000) ~= 0 - trace_dir = band(a,0x400000) ~= 0 - trace_whatsit = band(a,0x800000) ~= 0 - end - elseif a == unsetvalue then - goto list - end - if trace_strut then - setattr(current,a_layer,l_strut) - elseif id == glyph_code then - if trace_glyph then - head, current = ruledglyph(head,current,previous) - end - if trace_expansion then - head, current = glyphexpansion(head,current) - end - elseif id == disc_code then - if trace_discretionary then - head, current = ruleddiscretionary(head,current) - end - local pre, post, replace = getdisc(current) - if pre then - pre = visualize(pre,false,a,parent) - end - if post then - post = visualize(post,false,a,parent) - end - if replace then - replace = visualize(replace,false,a,parent) - end - setdisc(current,pre,post,replace) - elseif id == kern_code then - goto kern - elseif id == glue_code then - local content = getleader(current) - if content then - setleader(current,visualize(content,false,nil,parent)) - elseif trace_glue then - head, current = ruledglue(head,current,vertical,parent) - elseif trace_space then - head, current = ruledspace(head,current,parent) - end - elseif id == penalty_code then - if trace_penalty then - head, current = ruledpenalty(head,current,vertical) - end - elseif id == hlist_code or id == vlist_code then - goto list - elseif id == whatsit_code then - if trace_whatsit then - head, current = whatsit(head,current) - end - elseif id == user_code then - if trace_user then - head, current = user(head,current) - end - elseif id == math_code then - if trace_math then - head, current = math(head,current) - end - elseif id == marginkern_code then - if trace_kern then - head, current = ruledkern(head,current,vertical,true) - end - elseif id == dir_code then - if trace_dir then - head, current = dir(head,current) - end - elseif id == par_code then - if trace_par then - head, current = par(head,current) - end - end - goto next - ::kern:: - subtype = getsubtype(current) - if subtype == fontkern_code then - if trace_fontkern or prev_trace_fontkern then - head, current = fontkern(head,current) - end - if trace_expansion or prev_trace_expansion then - head, current = kernexpansion(head,current) - end - elseif subtype == italickern_code then - if trace_italic or prev_trace_italic then - head, current = italickern(head,current) - elseif trace_kern then - head, current = ruleditalic(head,current) - end - elseif subtype == leftmarginkern_code or subtype == rightmarginkern_code then - if trace_marginkern or prev_trace_marginkern then - head, current = marginkern(head,current) - elseif trace_kern then - head, current = ruledmarginkern(head,current) - end - elseif subtype == mathlistkern_code then - if trace_mathlist then -- or prev_trace_mathlist then - head, current = mathlistkern(head,current) - elseif trace_kern then - head, current = ruledmathlistkern(head,current) - end - else - if trace_kern then - head, current = ruledkern(head,current,vertical) - end - end - goto next; - ::list:: - if id == hlist_code then - local content = getlist(current) - if content then - setlist(current,visualize(content,false,nil,current)) - end - if trace_depth then - ruleddepth(current) - end - if trace_line and getsubtype(current) == linelist_code then - head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent) - elseif trace_hbox then - head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent) - end - elseif id == vlist_code then - local content = getlist(current) - local isvtop = getstate(current) == vtop_package_state - local tag = nil - local layer = nil - if content then - setlist(current,visualize(content,true,nil,current)) - end - if trace_vtop then - if isvtop then - tag = "_T_" - layer = l_vtop - elseif trace_vbox then - tag = "__V" - layer = l_vbox - end - elseif trace_vbox then - if not isvtop then - tag = "__V" - layer = l_vbox - end - end - if tag then - head, current = ruledbox(head,current,true,layer,tag,trace_simple,previous,trace_origin,parent) - end - end - ::next:: - previous = current - current = getnext(current) - end - return head - end - - local function cleanup() - for tag, cache in next, caches do - for k, v in next, cache do - flush_node_list(v) - end - end - cleanup = function() - report_visualize("error, duplicate cleanup") - end - end - - luatex.registerstopactions(cleanup) - - function visualizers.handler(head) - if usedfont then - starttiming(visualizers) - head = visualize(head,true) - stoptiming(visualizers) - return head, true - else - return head, false - end - end - - function visualizers.box(n) - if usedfont then - starttiming(visualizers) - local box = getbox(n) - if box then - setlist(box,visualize(getlist(box),getid(box) == vlist_code)) - end - stoptiming(visualizers) - return head, true - else - return head, false - end - end - -end - -do - - local hlist_code = nodecodes.hlist - local vlist_code = nodecodes.vlist - local nextnode = nuts.traversers.node - - local last = nil - local used = nil - - local mark = { - "trace:1", "trace:2", "trace:3", - "trace:4", "trace:5", "trace:6", - "trace:7", - } - - local function markfonts(list) - for n, id in nextnode, list do - if id == glyph_code then - local font = getfont(n) - local okay = used[font] - if not okay then - last = last + 1 - okay = mark[last] - used[font] = okay - end - setcolor(n,okay) - elseif id == hlist_code or id == vlist_code then - markfonts(getlist(n)) - end - end - end - - function visualizers.markfonts(list) - last, used = 0, { } - markfonts(type(n) == "number" and getlist(getbox(n)) or n) - end - -end - -statistics.register("visualization time",function() - if enabled then - -- cleanup() -- in case we don't don't do it each time - return formatters["%s seconds"](statistics.elapsedtime(visualizers)) - end -end) - --- interface - -do - - local implement = interfaces.implement - - implement { - name = "setvisual", - arguments = "string", - actions = visualizers.setvisual - } - - implement { - name = "setvisuals", - arguments = "string", - actions = visualizers.setvisual - } - - implement { - name = "getvisual", - arguments = "string", - actions = { setvisual, context } - } - - implement { - name = "setvisuallayer", - arguments = "string", - actions = visualizers.setlayer - } - - implement { - name = "markvisualfonts", - arguments = "integer", - actions = visualizers.markfonts - } - - implement { - name = "setvisualfont", - arguments = "integer", - actions = visualizers.setfont - } - -end - --- Here for now: - -do - - local function make(str,forecolor,rulecolor,layer) - if initialize then - initialize() - end - local rule = new_rule(emwidth/fraction,exheight,4*exheight) - setcolor(rule,rulecolor) - settransparency(rule,rulecolor) - local info - if str == "" then - info = new_hlist(rule) - else - local text = hpack_string(str,usedfont) - local list = getlist(text) - setlistcolor(list,textcolor) - setlisttransparency(list,textcolor) - setshift(text,3.5 * exheight) - info = new_hlist(setlink(rule,text)) - end - setattr(info,a_layer,layer) - return info - end - - function visualizers.register(name,textcolor,rulecolor) - if rawget(layers,name) then - -- message - return - end - local cache = caches[name] - local layer = layers[name] - if not textcolor then - textcolor = c_text_d - end - if not rulecolor then - rulecolor = c_origin_d - end - return function(str) - if not str then - str = "" - end - local info = cache[str] - if not info then - info = make(str,textcolor,rulecolor,layer) - cache[str] = info - end - return copy_node(info) - end - end - -end diff --git a/tex/context/base/mkiv/trac-vis.mkxl b/tex/context/base/mkiv/trac-vis.mkxl deleted file mode 100644 index dd69e0bb8..000000000 --- a/tex/context/base/mkiv/trac-vis.mkxl +++ /dev/null @@ -1,219 +0,0 @@ -%D \module -%D [ file=trac-vis, % replaces supp-vis plus some s-* modules -%D version=2012.06.23, % 1996.10.21, -%D title=\CONTEXT\ Tracing Macros, -%D subtitle=Visualization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D The old visual debugger dates from 1996 and started out as joke. In practice -%D it's not used that often although the \type {\ruledhbox} cum suis macros come -%D in handy when writing code. In the process of luafication some additional -%D tracing options were tested, for instance showing font kerns. As part of the -%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider -%D all these features. The old code is gone and the new code will get extended -%D when needed. We still provide placeholders for some old visualization commands -%D but they might go away. -%D -%D Control over what gets visualized happens with the tracker command: -%D -%D \enabletrackers[visualizers.*] -%D -%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type -%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type -%D {makeup}, \type {whatsit}, \type{glyph}. -%D -%D In due time some special visualzation of math will move here as well. - -\writestatus{loading}{ConTeXt Tracing Macros / Visualization} - -\registerctxluafile{trac-vis}{autosuffix,optimize} - -\unprotect - -\newconstant\c_syst_visualizers_state -\newtoks \t_syst_visualizers_optimize - -% \definesystemattribute[visual][public,global] % already defined - -% no, but can become an option: -% -% \appendtoks -% \c_attr_visual\attributeunsetvalue -% \to \everybeforepagebody - -%D We only provide box visualizers as they can come in handy for testing -%D macros. In due time we will move some of the m-visual code here too. - -\aliased\let\syst_visualizers_hbox \hbox -\aliased\let\syst_visualizers_vbox \vbox -\aliased\let\syst_visualizers_vtop \vtop -\aliased\let\syst_visualizers_vcenter\vcenter -\aliased\let\syst_visualizers_hpack \hpack -\aliased\let\syst_visualizers_vpack \vpack -\aliased\let\syst_visualizers_tpack \tpack - -\permanent\protected\def\ruledhbox {\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} } -\permanent\protected\def\ruledhpack {\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} } -\permanent\protected\def\ruledvbox {\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} } -\permanent\protected\def\ruledvpack {\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} } -\permanent\protected\def\ruledvtop {\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} } -\permanent\protected\def\ruledtpack {\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} } -\permanent\protected\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual{simplevbox} } -\permanent\protected\def\ruledmbox #1{\ruledhbox{\startimath#1\stopimath}} - -\appendtoks - \ifcase\c_syst_visualizers_state\else - \syst_visualizers_speedup - \fi -\to \everyshipout - -\appendtoks - \glet\syst_visualizers_speedup\relax - \global\t_syst_visualizers_optimize\emptytoks -\to \t_syst_visualizers_optimize - -\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize} - -\appendtoks -% \enforced\global\protected\edef\ruledhbox {\syst_visualizers_hbox attr \visualattribute \number\clf_getvisual{simplehbox} } -% \enforced\global\protected\edef\ruledhpack {\syst_visualizers_hpack attr \visualattribute \number\clf_getvisual{simplehbox} } -% \enforced\global\protected\edef\ruledvbox {\syst_visualizers_vbox attr \visualattribute \number\clf_getvisual{simplevbox} } -% \enforced\global\protected\edef\ruledvpack {\syst_visualizers_vpack attr \visualattribute \number\clf_getvisual{simplevbox} } -% \enforced\global\protected\edef\ruledvtop {\syst_visualizers_vtop attr \visualattribute \number\clf_getvisual{simplevtop} } -% \enforced\global\protected\edef\ruledtpack {\syst_visualizers_tpack attr \visualattribute \number\clf_getvisual{simplevtop} } -% \enforced\global\protected\edef\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \number\clf_getvisual{simplevbox} } -\to \t_syst_visualizers_optimize - -\permanent\tolerant\protected\def\showmakeup[#1]% - {\ifarguments - \clf_setvisual{makeup}% - \else - \clf_setvisual{#1}% - \fi} - -\permanent\protected\def\showallmakeup {\clf_setvisual{all}\showstruts} -\permanent\protected\def\showboxes {\clf_setvisual{boxes}} -\permanent\protected\def\showglyphs {\clf_setvisual{glyph}} -\permanent\protected\def\showfontkerns {\clf_setvisual{fontkern}} -\permanent\protected\def\showfontitalics {\clf_setvisual{italic}} -\permanent\protected\def\showglyphdata {\showglyphs\showfontkerns\showfontitalics} -\permanent\protected\def\showfontexpansion{\clf_setvisual{expansion}} - -\permanent\tolerant\protected\def\setvisualizerfont[#1]% somename at 4pt - {\begingroup - \iftok{#1}\emptytoks - \definedfont[Mono at 4pt]% - \else - \definedfont[#1]% - \fi - \clf_setvisualfont\fontid\font - \endgroup} - -\permanent\protected\def\resetvisualizers - {\c_attr_visual\attributeunsetvalue} - -%D New (these might also be a visualizers): - -% \definecolor[f:r:t][a=1,t=.25,r=1] -% \definecolor[f:g:t][a=1,t=.25,g=1] -% \definecolor[f:b:t][a=1,t=.25,b=1] -% \definecolor[f:c:t][a=1,t=.25,c=1] -% \definecolor[f:m:t][a=1,t=.25,m=1] -% \definecolor[f:y:t][a=1,t=.25,y=1] -% \definecolor[f:k:t][a=1,t=.25,s=0] - -\permanent\protected\def\filledhboxr{\node_backgrounds_boxes_add\hbox[f:r:t]} -\permanent\protected\def\filledhboxg{\node_backgrounds_boxes_add\hbox[f:g:t]} -\permanent\protected\def\filledhboxb{\node_backgrounds_boxes_add\hbox[f:b:t]} -\permanent\protected\def\filledhboxc{\node_backgrounds_boxes_add\hbox[f:c:t]} -\permanent\protected\def\filledhboxm{\node_backgrounds_boxes_add\hbox[f:m:t]} -\permanent\protected\def\filledhboxy{\node_backgrounds_boxes_add\hbox[f:y:t]} -\permanent\protected\def\filledhboxk{\node_backgrounds_boxes_add\hbox[f:k:t]} - -%D Overload: - -\protected\def\spac_struts_vide_hbox - {\hbox attr \visualattribute \clf_getvisual{strut} } - -\appendtoks - \normalexpanded{\protected\xdef\spac_struts_vide_hbox\expandafter{\spac_struts_vide_hbox}}% -\to \t_syst_visualizers_optimize - -%D For manuals: - -\permanent\protected\def\markfonts#1% - {\dontleavehmode - \begingroup - \setbox\scratchbox\hbox{\getbuffer}% - \clf_markvisualfonts\scratchbox - \unhbox\scratchbox - \endgroup} - -% As demo: -% -% \startbuffer -% \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}} -% \blank -% \moveleft1cm\hbox{left} -% \blank -% \hbox{normal} -% \blank -% \moveright1cm\hbox{right} -% \blank -% \stopbuffer -% -% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer -% -% \startbuffer -% \moveleft1cm\vbox{left} -% \blank -% \vbox{normal} -% \blank -% \moveright1cm\vbox{right} -% \blank -% \stopbuffer -% -% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer - -%D We keep this one: - -\permanent\protected\def\dontinterfere - {\reseteverypar - \parindent\zeropoint - \parskip \zeropoint - \leftskip \zeropoint - \rightskip\zeropoint - \relax} - -%D We keep these for a while: - -% \aliased\let\ruledhss \hss -% \aliased\let\ruledhfil \hfil -% \aliased\let\ruledhfill \hfill -% \aliased\let\ruledhfilll \hfilll -% \aliased\let\ruledhfilneg \hfilneg -% \aliased\let\ruledhfillneg \hfillneg -% \aliased\let\ruledhfilllneg \hfilllneg -% \aliased\let\ruledvss \vss -% \aliased\let\ruledvfil \vfil -% \aliased\let\ruledvfill \vfill -% \aliased\let\ruledvfilll \vfilll -% \aliased\let\ruledvfilneg \vfilneg -% \aliased\let\ruledvfillneg \vfillneg -% \aliased\let\ruledvfilllneg \vfilllneg -% \aliased\let\ruledhskip \hskip -% \aliased\let\ruledvskip \vskip -% \aliased\let\ruledkern \kern -% \aliased\let\ruledhglue \hglue -% \aliased\let\ruledvglue \vglue -% \aliased\let\ruledmkern \mkern -% \aliased\let\ruledmskip \mskip -% \aliased\let\ruledpenalty \penalty - -\protect \endinput diff --git a/tex/context/base/mkiv/type-ini.mklx b/tex/context/base/mkiv/type-ini.mklx deleted file mode 100644 index afbbfea47..000000000 --- a/tex/context/base/mkiv/type-ini.mklx +++ /dev/null @@ -1,708 +0,0 @@ -%D \module -%D [ file=type-ini, -%D version=2001.03.05, -%D title=\CONTEXT\ Typescript Macros, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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}{} - -%D The default fontclass is empty. We could demand always using fontclasses, and -%D then make the calling macros simplier (always assume fontclass) but apart from -%D downward compatibility issues, it would make global, class spanning definitions a -%D 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 mutual -%D dependencies. -%D -%D At some point we will only store in memory so some code can go away. - -\unprotect - -\newcount \c_font_typescripts_n_of_preloaded -\newconditional\c_font_typescripts_quit -\newtoks \c_font_typescripts_document -\newconditional\c_font_typescripts_preload -\newconditional\c_font_typescripts_first_pass \settrue\c_font_typescripts_first_pass - -\newif \iftypescriptfound % will become a mode -\newif \iftracetypescripts - -\newtoks \everybeforedefinetypeface -\newtoks \everyafterdefinetypeface - -\let\typescriptfiles \empty -\let\currenttypescripts\empty -\let\currenttypefile \empty - -\installmacrostack\currenttypefile - -\let\typescriptone \empty % public, used in typescripts -\let\typescripttwo \empty % public, used in typescripts -\let\typescriptthree\empty % public, used in typescripts - -\installmacrostack\typescriptone -\installmacrostack\typescripttwo -\installmacrostack\typescriptthree - -\let\fontclassstyle \empty - -\installmacrostack\fontclassstyle - -\let\m_font_typescripts_one \empty -\let\m_font_typescripts_two \empty -\let\m_font_typescripts_three\empty -\let\m_font_typescripts_check\empty -\let\m_font_typescripts_match\empty - -\installmacrostack\m_font_typescripts_one -\installmacrostack\m_font_typescripts_two -\installmacrostack\m_font_typescripts_three - -\mutable\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 - -\installmacrostack\typescriptmethod -\installmacrostack\typescriptstate - -%D When these are loaded it is possible to get spaces but the whole idea is to do -%D that loading in vertical mode. Adding \type {\pushendofline} and \type -%D {\popendofline} is an option but not watertight as it can still interfere, for -%D instance work comments and leading spaces. Also, in horizontal mode it is likely -%D that one is also grouped and loading bodyfonts grouped is a real bad idea. -%D Ignoring all spaces is also not a solution. So, our verdict is: no catch. - -\permanent\protected\def\starttypescriptcollection % redefined on the fly - {\dosingleempty\font_typescripts_collection_start} - -\def\font_typescripts_collection_start[#tag]% - {} - -\permanent\let\stoptypescriptcollection\relax - -\permanent\protected\def\usetypescriptfile[#filename]% - {\iftok{#filename}{\v!reset}% - \let\typescriptfiles\empty - \else - \splitfilename{#filename}% - \addtocommalist\splitoffbase\typescriptfiles - \fi} - -\installmacrostack\stoptypescript - -% \permanent\protected\def\usetypescript {\dotripleempty\font_typescripts_use_one} -% \permanent\protected\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two} -% -% \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} -% \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} -% -% \protected\def\font_typescripts_use[#one][#two][#three]% - -% todo: just pass the method ... also further on then .. first test - -\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} -\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} - -\permanent\protected\def\usetypescript {\font_typescripts_use_one} -\permanent\protected\def\usetypescriptexact{\font_typescripts_use_two} - -\tolerant\protected\def\font_typescripts_use[#one]#spacer[#two]#spacer[#three]% - {\push_macro_m_font_typescripts_one - \push_macro_m_font_typescripts_two - \push_macro_m_font_typescripts_three - \edef\m_font_typescripts_one {\truetypescript{#one}}% - \edef\m_font_typescripts_two {\truetypescript{#two}}% - \edef\m_font_typescripts_three{\truetypescript{#three}}% - \push_macro_typescriptone - \push_macro_typescripttwo - \push_macro_typescriptthree - \push_macro_typescriptmethod - \push_macro_typescriptstate - \push_macro_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 - \pop_macro_stoptypescript - \pop_macro_typescriptstate - \pop_macro_typescriptmethod - \pop_macro_typescriptthree - \pop_macro_typescripttwo - \pop_macro_typescriptone - \pop_macro_m_font_typescripts_three - \pop_macro_m_font_typescripts_two - \pop_macro_m_font_typescripts_one} - -\def\font_typescripts_use_display - {\processcommacommand[\typescriptfiles]\font_typescripts_load_file - \the\c_font_typescripts_document} - -\let\font_typescripts_use_inline\font_typescripts_use_display - -\permanent\protected\def\preloadtypescripts - {\ifproductionrun\settrue\c_font_typescripts_preload\fi} - -\prependtoks - \preloadtypescripts -\to \everyjob - -\permanent\protected\def\loadtypescriptfile[#1]% - {\push_macro_typescriptstate - \let\typescriptstate\plustwo % assumes 2 at the outer level - \clf_loadtypescriptfile{#1}% - \pop_macro_typescriptstate} - -\permanent\protected\def\loadfoundtypescriptfile#1#2% name foundname / not a user command - {\startreadingfile - \unprotect - \pushendofline - \input{#2}% - \popendofline - \protect - \stopreadingfile} - -\permanent\protected\def\quittypescriptscanning - {\settrue\c_font_typescripts_quit} % public - -\permanent\protected\def\font_typescripts_start_store#definitions\stoptypescript - {\global\advance\c_font_typescripts_n_of_preloaded\plusone - \global\defcsname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname - {\starttypescript#definitions\stoptypescript}% - \gtoksapp\t_font_typescripts\expandafter - {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} - -\permanent\protected\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection - {\global\advance\c_font_typescripts_n_of_preloaded\plusone - \global\defcsname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname - {\starttypescriptcollection#definitions\stoptypescriptcollection}% - \gtoksapp\t_font_typescripts\expandafter - {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} - -\def\font_typescripts_load_file#filename% - {\setfalse\c_font_typescripts_quit - \push_macro_currenttypefile - \def\currenttypefile{#filename}% - \ifconditional\c_font_typescripts_preload - \font_typescript_process_typescript_file_and_store - \else - \font_typescript_process_typescript_file - \fi - \pop_macro_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 -% {\aliased\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 - \enforced\let\starttypescript \font_typescripts_start_store - \enforced\let\starttypescriptcollection\font_typescripts_collection_start_store - \font_typescript_process_typescript_file - \endgroup - \letcsname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts} - -\def\font_typescript_process_typescript_file - {\clf_doprocesstypescriptfile{\currenttypefile}} - -\permanent\tolerant\protected\def\usetypescriptonce[#one]#spacer[#two]#spacer[#three]% - {\ifcsname\??typescriptonce#one:#two:#three\endcsname - \writestatus\m!fonts{once (#one) (#two) (#three)}% - \else - \letcsname\??typescriptonce#one:#two:#three\endcsname\relax - \font_typescripts_use[#one][#two][#three]% - \fi} - -% \definetypescriptsynonym[lbr][cmr] - -\permanent\tolerant\protected\def\definetypescriptsynonym[#name]#spacer[#synonym]% - {\ifarguments\or\or\setevalue{\??typescriptsynonyms#name}{#synonym}\fi} - -\permanent\def\truetypescript#name% recursive 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 - -\permanent\protected\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#ignore\stoptypescript{} - -\def\font_typescripts_start_document#definitions\stoptypescript - {\toksapp\c_font_typescripts_document{\starttypescript#definitions\stoptypescript}} - -\def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed - {\let\typescriptone \m_font_typescripts_one - \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 - {\push_macro_fontclass} - -\permanent\protected\def\stoptypescript - {\pop_macro_fontclass} - -\def\font_typescripts_check#asked#target#followup[#value]% script use value next - {\donefalse - \edef\m_font_typescripts_check{#value}% - \ifempty\m_font_typescripts_check % no longer needed / met - \ifcase\typescriptmethod\or\donetrue\fi - \orelse\ifx#asked\s!all - \donetrue - \orelse\ifx\m_font_typescripts_check\s!all - \donetrue - \orelse\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 - \ifdone - \iftracetypescripts\extendtypescriptmatch\fi - \expandafter#followup% - \else - \expandafter\font_typescripts_start_gobble - \fi} - -\permanent\protected\def\extendtypescriptmatch - {\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}} - -%D Map files will go away in \LUATEX, but till that happens we use stripped down -%D support for loading them. - -\permanent\tolerant\protected\def\loadmapfile [#filename]{\clf_loadmapfile{#filename}} -\permanent\tolerant\protected\def\loadmapline [#kind]#spacer[#data]{\clf_loadmapline{#kind}{#data}} -\permanent \protected\def\forgetmapfiles {\clf_resetmapfiles} - -% \prependtoks -% \loadmapfile[mkiv-base.map]% can't we preload this one? -% \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 - -% \protected\def\definetypescriptprefix -% {\dodoubleargument\font_typescripts_define_prefix} -% -% \def\font_typescripts_define_prefix[#name][#prefix]% -% {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global - -\permanent\tolerant\protected\def\definetypescriptprefix[#name]#spacer[#prefix]% - {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global - -\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] - -\appendtoks - \font_helpers_reset_fontclass_math_families\fontclass -\to \everybeforedefinetypeface - -%D This hooks into the font switcher: - -\settrue\autotypescripts - -\protected\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: - -\permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]% - {\ifarguments - \expandafter\font_typefaces_define_e - \or - \expandafter\font_typefaces_define_d - \or - \expandafter\font_typefaces_define_d - \or - \expandafter\font_typefaces_define_c - \or - \expandafter\font_typefaces_define_b - \or - \expandafter\font_typefaces_define_a - \or - \expandafter\font_typefaces_define_a - \fi[#name][#style][#fontshape][#fontname][#fontsize][#settings]} - -\def\font_typefaces_define_e[#name][#style][#fontshape][#fontname][#fontsize][#settings]% - {} - -\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]% - {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi - \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 - \orelse\ifconditional\autotypescripts - \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi - \usetypescriptfile[#fontname]% - \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% - \fi - \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% - \font_typefaces_defining_stop} - -\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#discard][#discard]% - {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#discard]} - -\def\font_typefaces_define_c[#name][#style][#discard][#discard][#discard][#discard]% - {\font_typefaces_define_indeed[#name][#style]} - -\def\font_typefaces_define_d[#name][#specification][#discard][#discard][#discard][#discard]% use definitions in lfg file - {\clf_definetypeface{#name}{#specification}} - -\def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition - {\doifsomething{#name} - {\ifcsname\??typescriptdefaultstyles#name\endcsname \else - \registerfontclass{#name}% - \setxvalue{\??typescriptdefaultstyles#name}{#style}% - \fi - \ifcsname#name\endcsname \else - \setugvalue{#name}{\switchtotypeface[#name][#style]}% - \fi}} - -% needs testing first ... let'd do it stepwise - -% \permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]% -% {\ifarguments -% \or -% \clf_definetypeface{#name}{#specification}% -% \or -% \clf_definetypeface{#name}{#specification}% -% \or -% \font_typefaces_define_simplex[#name][#style]% -% \or -% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][\s!default][#discard]% -% \else -% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]% -% \fi} -% -% \def\font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]% -% {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi -% \font_typefaces_define_simplex[#name][#style]% -% \font_typefaces_defining_start{#name}{#style}{#settings}% -% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% -% \iftypescriptfound -% % we're okay -% \orelse\ifconditional\autotypescripts -% \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi -% \usetypescriptfile[#fontname]% -% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% -% \fi -% \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% -% \font_typefaces_defining_stop} -% -% \def\font_typefaces_define_simplex[#name][#style]% saveguard against redefinition -% {\doifsomething{#name} -% {\ifcsname\??typescriptdefaultstyles#name\endcsname \else -% \registerfontclass{#name}% -% \setxvalue{\??typescriptdefaultstyles#name}{#style}% -% \fi -% \ifcsname#name\endcsname \else -% \setugvalue{#name}{\switchtotypeface[#name][#style]}% -% \fi}} - -\def\font_typefaces_defining_start#name#style#settings% - {\let\m_ts_rscale \!!plusone % as we push/pop - \let\m_ts_features \empty - \let\m_ts_fallbacks \empty - \let\m_ts_goodies \empty - \let\m_ts_direction \empty - \let\m_ts_designsize\empty - \geteparameters[m_ts_][#settings]% todo raw ... no need for key interpretation - \push_macro_fontclass - \push_macro_fontclassstyle - \setcurrentfontclass{#name}% - \savefontclassparameters{#style}\m_ts_rscale\m_ts_features\m_ts_fallbacks\m_ts_goodies\m_ts_designsize\m_ts_direction - \the\everybeforedefinetypeface} - -\permanent\def\tsvar#key#default% undocumented and unofficial - {\expandafter\ifempty\csname\??ts#key\endcsname - #default% - \else - \csname\??ts#key\endcsname - \fi} - -\def\font_typefaces_defining_stop - {\the\everyafterdefinetypeface - \pop_macro_fontclassstyle - \pop_macro_fontclass} - -\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d) - {\font_typefaces_define_indeed[#name][#style]% - \font_typefaces_defining_start{#name}{#style}{#settings}% - \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% - \font_typefaces_defining_stop} - -% \protected\def\setuptypeface% [class] [settings] -% {\dodoubleempty\font_typefaces_setup} -% -% \protected\def\switchtotypeface% [class] [settings] -% {\dodoubleempty\font_typefaces_switch} -% -% \def\font_typefaces_setup[#class][#settings]% -% {\setcurrentfontclass{#class}% -% \let\globalfontclass\fontclass -% \ifsecondargument -% \setupbodyfont[#settings]% -% \orelse\ifempty\fontclass -% \setupbodyfont[\s!rm]% -% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname -% %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% -% \expandafter\setupbodyfont\expandafter[\lastnamedcs]% -% \else -% \setupbodyfont[\s!rm]% -% \fi -% \ifmmode\mr\else\tf\fi} % needed ? -% -% \def\font_typefaces_switch[#class]#spacer[#settings]% -% {\setcurrentfontclass{#class}% -% \let\globalfontclass\globalfontclass -% \ifsecondargument -% \switchtobodyfont[#settings]% -% \orelse\ifempty\fontclass -% \switchtobodyfont[\s!rm]% -% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname -% %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% -% \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% -% \else -% \switchtobodyfont[\s!rm]% -% \fi -% \ifmmode\mr\else\tf\fi} % needed ? - -\permanent\tolerant\protected\def\setuptypeface[#class]#spacer[#settings]% - {\ifarguments - \or - \setcurrentfontclass{#class}% - \let\globalfontclass\fontclass - \ifempty\fontclass - \setupbodyfont[\s!rm]% - \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname - \expandafter\setupbodyfont\expandafter[\lastnamedcs]% - \else - \setupbodyfont[\s!rm]% - \fi - \or - \setcurrentfontclass{#class}% - \let\globalfontclass\fontclass - \setupbodyfont[#settings]% - \fi - \ifmmode\mr\else\tf\fi} % needed ? - -\permanent\tolerant\protected\def\switchtotypeface[#class]#spacer[#settings]% - {\ifarguments - \or - \setcurrentfontclass{#class}% - \let\globalfontclass\globalfontclass - \ifempty\fontclass - \switchtobodyfont[\s!rm]% - \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname - \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% - \else - \switchtobodyfont[\s!rm]% - \fi - \or - \setcurrentfontclass{#class}% - \let\globalfontclass\globalfontclass - \switchtobodyfont[#settings]% - \fi - \ifmmode\mr\else\tf\fi} % needed ? - -%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 - -\permanent\tolerant\protected\def\inherittypeface[#name]#spacer[#styles]#spacer[#parentclass]% - {\iftok{#styles}\emptytoks - \font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]% - \orelse\iftok{#name}{#parentclass}\else - \glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed - \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}% - \processcommalist[#styles]\font_typescripts_inherit_check_step - \fi} - -\let\font_typescripts_inherit_check_step\relax - -%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 % no \orelse ! - \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!ss \s!Sans \else % no \orelse ! - \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else % no \orelse ! - \s!Serif \fi\fi\fi} - -\protected\def\font_helpers_set_fontstyle_of_fontclass - {\ifempty\fontclass - \let\fontstyle\s!rm - \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname - %\edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}% - \edef\fontstyle{\lastnamedcs}% - \else - \let\fontstyle\s!rm - \fi} - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-brk.mkxl b/tex/context/base/mkiv/typo-brk.mkxl deleted file mode 100644 index 51abc1034..000000000 --- a/tex/context/base/mkiv/typo-brk.mkxl +++ /dev/null @@ -1,94 +0,0 @@ -%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}{} - -\definesystemattribute[breakpoint][public,global] - -% see below: \exhyphenchar \minusone % we use a different order than base tex, so we really need this - -\permanent\tolerant\protected\def\definebreakpoints[#1]% - {\clf_definebreakpoints{#1}} % todo: public implementor - -\permanent\tolerant\protected\def\definebreakpoint[#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} - -\permanent\protected\def\setbreakpoints[#1]% - {\exhyphenchar\minusone % we use a different order than base tex, so we really need this - \clf_setbreakpoints{#1}} - -\permanent\protected\def\resetbreakpoints - {\exhyphenchar\hyphenasciicode % 2020.03.05 - \c_attr_breakpoint\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=-) - -\aliased\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/tex/context/base/mkiv/typo-cap.mkxl b/tex/context/base/mkiv/typo-cap.mkxl deleted file mode 100644 index 587ab62ef..000000000 --- a/tex/context/base/mkiv/typo-cap.mkxl +++ /dev/null @@ -1,269 +0,0 @@ -%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}{optimize} - -% \definesystemattribute[case][public] % already predefined - -%D \macros -%D {setupcapitals} -%D -%D By default we use pseudo small caps in titles. This can be 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] % 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 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 - -\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}\fontid\font} % can be public implementor - -\protected\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font} -\protected\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font} -\protected\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font} -\protected\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font} -\protected\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font} - -\pushoverloadmode - -\permanent\protected\def\WORD {\triggergroupedcommandcs\typo_capitale_WORD } -\permanent\protected\def\word {\triggergroupedcommandcs\typo_capitale_word } -\permanent\protected\def\Word {\triggergroupedcommandcs\typo_capitale_Word } -\permanent\protected\def\Words{\triggergroupedcommandcs\typo_capitale_Words} -\permanent\protected\def\camel{\triggergroupedcommandcs\typo_capitale_camel} - -\aliased\let\WORDS\WORD -\aliased\let\words\word - -\popoverloadmode - -%D \macros -%D {kap,KAP,Kap,Kaps,nokap,userealcaps,usepseudocaps} -%D -%D We already introduced \type {\cap} as way to capitalize words. This command comes -%D 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 \type {\cap}. -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D These macros show te main reason why we introduced the smaller \type {\tx} and -%D \type {\txx}. -%D -%D \starttyping -%D \cap\romannumerals{1995} -%D \stoptyping -%D -%D This at first sight unusual capitilization is completely 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 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 \type {\groupedcommand}. - -\newconditional\c_typo_capitals_pseudo - -\permanent\protected\def\usepseudocaps{\settrue \c_typo_capitals_pseudo} -\permanent\protected\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} - -\permanent\protected\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped} -\permanent\protected\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped} -\permanent\protected\def\pseudoSmallCapped{\triggergroupedcommandcs\font_style_pseudoSmallCapped} -\permanent\protected\def\pseudoMixedCapped{\triggergroupedcommandcs\font_style_pseudoMixedCapped} - -\permanent\protected\def\realsmallcapped {\triggergroupedcommandcs\font_style_realsmallcapped} -\permanent\protected\def\realSmallcapped {\triggergroupedcommandcs\font_style_realSmallcapped} -\permanent\protected\def\realSmallCapped {\triggergroupedcommandcs\font_style_realSmallCapped} - -\permanent\protected\def\notsmallcapped {\triggergroupedcommandcs\font_style_notsmallcapped} - -\protected\def\font_style_pseudosmallcapped{\typo_capitals_set_fake\v!WORD } % all upper -\protected\def\font_style_pseudoSmallcapped{\typo_capitals_set_fake\v!capital} % one upper + font -\protected\def\font_style_pseudoSmallCapped{\typo_capitals_set_fake\v!Capital} % some upper + font -\protected\def\font_style_pseudoMixedCapped{\typo_capitals_set_fake\v!mixed } - -\protected\def\font_style_realsmallcapped {\typo_capitals_set_real\v!WORD } % all lower -\protected\def\font_style_realSmallcapped {\typo_capitals_set_real\v!Word } % one upper + font -\protected\def\font_style_realSmallCapped {\typo_capitals_set_real\v!Words } % some upper - -\protected\def\font_style_notsmallcapped {\typo_capitals_set_fake\v!word } - -\protected\def\typo_capitals_smallcaps - {\ifconditional\c_typo_capitals_pseudo - \expandafter\firstoftwoarguments - \else - \expandafter\secondoftwoarguments - \fi} - -\permanent\protected\def\smallcapped{\typo_capitals_smallcaps\pseudosmallcapped\realsmallcapped} -\permanent\protected\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped} -\permanent\protected\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped} - -\permanent\protected\def\font_style_smallcapped{\typo_capitals_smallcaps\font_style_pseudosmallcapped\font_style_realsmallcapped} -\permanent\protected\def\font_style_Smallcapped{\typo_capitals_smallcaps\font_style_pseudoSmallcapped\font_style_realSmallcapped} -\permanent\protected\def\font_style_SmallCapped{\typo_capitals_smallcaps\font_style_pseudoSmallCapped\font_style_realSmallCapped} - -\permanent\protected\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi} - -\prependtoks - \enforced\let\normalcap\cap % mathmode cap -\to \everydump - -\appendtoks - \enforced\let\cap\autocap -\to \everydump - -\aliased\let\kap\cap % for old times sake -\aliased\let\Caps\SmallCapped % for old times sake - -\aliased\let\mixedcaps\pseudoMixedCapped - -\aliased\let\normalsmallcapped\smallcapped -\aliased\let\normalWORD \WORD -\aliased\let\normalword \word - -\aliased\let\font_style_normalsmallcapped\font_style_smallcapped -\aliased\let\font_style_normalWORD \WORD -\aliased\let\font_style_normalword \word - -\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 - -\aliased\let\uppercased\normalWORD -\aliased\let\lowercased\normalword - -\setupcapitals - [\c!title=\v!yes, - \c!style=\tx, - \s!sc=\v!no] % no \c!sc any longer - -\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=] - -% \protected\def\randomizetext{\groupedcommand{\c_attr_case\pluseight}{}} - -\permanent\protected\def\randomizetext{\triggergroupedcommand{\c_attr_case\pluseight}} - -\definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=] - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-cln.mkxl b/tex/context/base/mkiv/typo-cln.mkxl deleted file mode 100644 index 84fc1d235..000000000 --- a/tex/context/base/mkiv/typo-cln.mkxl +++ /dev/null @@ -1,32 +0,0 @@ -%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}{} - -\definesystemattribute[cleaner][public] - -%D Currently there is no interface. -%D -%D 1: Autocap first character of a line - -\permanent\protected\def\setcharactercleaning[#1]{\clf_setcharactercleaning{#1}} % also accepts reset, todo: public implementor - -% \appendtoks -% \c_attr_cleaner\attributeunsetvalue -% \to \everyforgetall - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-del.mkxl b/tex/context/base/mkiv/typo-del.mkxl deleted file mode 100644 index 3550626aa..000000000 --- a/tex/context/base/mkiv/typo-del.mkxl +++ /dev/null @@ -1,927 +0,0 @@ -%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) - -\permanent\permanent\protected\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] - -\permanent\protected\def\normalhyphen - {\hbox{\directsymbol\empty\c!hyphen}} - -\permanent\protected\def\composedhyphen - {\hbox{\directsymbol\empty\c!compoundhyphen}} - -\permanent\protected\def\normalhyphendiscretionary - {\discretionary - {\hbox{\directsymbol\empty\c!righthyphen}} - {\hbox{\directsymbol\empty\c!lefthyphen}} - {\hbox{\directsymbol\empty\c!hyphen}}} - -\permanent\protected\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 - -% old: skip symbol skip -% new: bound skip symbol skip bound - -\permanent\protected\def\midboundarycharacter#1#2% - {\ifcase\boundarycharactermode - \or - \removeunwantedspaces - \wordboundary - \hskip\hspaceamount\currentusedlanguage{#2}% - \usedlanguageparameter#1% - \hskip\hspaceamount\currentusedlanguage{#2}% - \wordboundary - \ignorespaces - \or - \usedlanguageparameter#1% - \fi - \boundarycharactermode\plusone} - -% old: symbol nobreak skip -% new: symbol nobreak skip wordboundary - -\permanent\protected\def\leftboundarycharacter#1#2% - {\ifcase\boundarycharactermode - \or - \usedlanguageparameter#1% - \nobreak - \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern - \wordboundary - \or - \usedlanguageparameter#1% - \fi - \boundarycharactermode\plusone} - -% old: preword skip symbol -% new: bound nobreak skip symbol - -\permanent\protected\def\rightboundarycharacter#1#2% - {\ifcase\boundarycharactermode - \or - \wordboundary - \nobreak - \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern - \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} - -\newconditional\c_typo_subsentence_cleanup \settrue\c_typo_subsentence_cleanup - -\def\typo_subsentence_cleanup_start - {\ifconditional\c_typo_subsentence_cleanup - \expandafter\ignorespaces - \fi} - -\def\typo_subsentence_cleanup_stop - {\ifconditional\c_typo_subsentence_cleanup - \removeunwantedspaces - \fi} - -\permanent\protected\def\midsentence - {\dostarttagged\t!subsentencesymbol\empty - \dotagsetsubsentencesymbol\s!middle - \symbol[\c!midsentence]% - \dostoptagged} - -\permanent\protected\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 - \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 - \typo_subsentence_cleanup_start} - -\permanent\protected\def\endofsubsentence % relax prevents space gobbling - {\typo_subsentence_cleanup_stop - \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} - -\permanent\protected\def\beginofsubsentencespacing % relax prevents space gobbling - {\kern\d_typo_subsentence_signal\relax}% \ignorespaces} - -\permanent\protected\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\typo_subsentence_cleanup_start} -%unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\endofsubsentencespacing\prewordbreak\endofsubsentence} -%unexpanded\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence} -%unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\prewordbreak\midsentence\prewordbreak\typo_subsentence_cleanup_stop} - -\permanent\protected\def\startsubsentence{\beginofsubsentence\wordboundary\beginofsubsentencespacing\wordboundary\typo_subsentence_cleanup_start} -\permanent\protected\def\stopsubsentence {\typo_subsentence_cleanup_stop\wordboundary\endofsubsentencespacing\wordboundary\endofsubsentence} -\permanent\protected\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence} -\permanent\protected\def\midsubsentence {\typo_subsentence_cleanup_start\wordboundary\midsentence\wordboundary\typo_subsentence_cleanup_stop} - -\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 - \enforced\permanent\def\quotation#1{"#1"}% - \enforced\permanent\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 - -\installglobalmacrostack\currentdelimitedtext - -\let\delimitedtextlevel\!!zerocount - -\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname} - -% the \setlanguageparameter macro sets but we are ungrouped .. only used here -% -% \currentusedlanguage -% \usedlanguageparameter - -%D The optional argument can be a language, a narrower spec, or a outer:inner language -%D specification. -%D -%D \starttabulate -%D \NC [en] \NC {\tttf en} \quotation[en] {{\tttf } something french} \NC \NR -%D \NC [fr] \NC {\tttf en} \quotation[fr] {{\tttf } something french} \NC \NR -%D \NC [fr:] \NC {\tttf fr} \quotation[fr:] {{\tttf } something french} \NC \NR -%D \NC [:fr] \NC {\tttf en} \quotation[:fr] {{\tttf } something french} \NC \NR -%D \NC [fr:fr] \NC {\tttf fr} \quotation[fr:fr]{{\tttf } something french} \NC \NR -%D \NC [en:fr] \NC {\tttf en} \quotation[en:fr]{{\tttf } something french} \NC \NR -%D \NC [fr:en] \NC {\tttf fr} \quotation[fr:en]{{\tttf } something french} \NC \NR -%D \stoptabulate - -\let\currentdelimitedlanguage\empty - -\installglobalmacrostack\currentdelimitedlanguage - -\def\typo_delimited_set_language_nop - {\setusedlanguage{\delimitedtextparameter\c!language}} - -\def\typo_delimited_set_language_yes - {\doiflanguageelse\m_delimited_argument - \typo_delimited_set_language_yes_a - {\doifelseinstring:\m_delimited_argument - \typo_delimited_set_language_yes_b - \typo_delimited_set_language_nop}} - -\def\typo_delimited_set_language_yes_b - {\splitatcolon\m_delimited_argument\outerdelimitedlanguage\innerdelimitedlanguage - \ifempty\outerdelimitedlanguage - \typo_delimited_set_language_nop - \else - \doiflanguageelse\outerdelimitedlanguage - {\setusedlanguage\outerdelimitedlanguage}% - \typo_delimited_set_language_nop - \fi - \ifempty\innerdelimitedlanguage\else - \doiflanguageelse\innerdelimitedlanguage - {\let\currentdelimitedlanguage\innerdelimitedlanguage}% - \donothing - \fi - \let\m_delimited_argument\empty} - -\def\typo_delimited_set_language_yes_a - {\let\currentdelimitedlanguage\m_delimited_argument - \let\m_delimited_argument\empty} - -\def\typo_delimited_push#1#2% - {\push_macro_currentdelimitedtext % can we combine these two - \push_macro_currentdelimitedlanguage % the language used for hyphenation - \edef\currentdelimitedtext{#1}% - \edef\m_delimited_argument{#2}% - \ifempty\m_delimited_argument - \typo_delimited_set_language_nop - \else - \typo_delimited_set_language_yes - \fi - \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 - \pop_macro_currentdelimitedlanguage - \pop_macro_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!language=\v!local, - \c!repeat=\v!no] - -\def\typo_delimited_repeat_indeed - {\relax\ifcase\delimitedtextlevel\else - \typo_delimited_handle_middle\c!middle - \fi} - -\let\typo_delimited_repeat\relax - -\permanent\tolerant\protected\def\startdelimitedtext[#1]#*[#2]% - {\begingroup - \typo_delimited_push{#1}{#2}% - \dostarttaggedchained\t!delimitedblock\currentdelimitedtext\??delimitedtext - \edef\p_delimited_method{\delimitedtextparameter\c!method}% - \ifx\p_delimited_method\v!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} - -\newconditional\c_typo_delimited_repeating - -\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 - \setfalse\c_typo_delimited_repeating - \edef\p_delimited_location{\delimitedtextparameter\c!location}% - \ifx\p_delimited_location\v!paragraph - \expandafter\typo_delimited_start_par - \orelse\ifx\p_delimited_location\v!margin - \expandafter\typo_delimited_start_par - \else - \expandafter\typo_delimited_start_txt - \fi} - -\def\typo_delimitedtexts_finish_font - {\removeunwantedspaces % again ? - \dostarttagged\t!delimitedsymbol\empty - \dotagsetdelimitedsymbol\s!right - \delimitedtextparameter\c!right - \dostoptagged} - -\def\typo_delimited_show_language_indeed#1#2% - {\begingroup - \infofont - \setbox\scratchbox\hpack{\lower\strutht\hbox to \zeropoint{\darkred#1\currentlanguage:\currentdelimitedlanguage#2}}% - \vsmashbox\scratchbox - \box\scratchbox - \endgroup} - -\let\typo_delimited_show_language\gobbletwoarguments - -\installtextracker{delimited.language} - {\let\typo_delimited_show_language\typo_delimited_show_language_indeed} - {\let\typo_delimited_show_language\gobbletwoarguments} - -\def\typo_delimited_start_content - {\dostarttagged\t!delimitedcontent\empty - \begingroup - \douselanguageparameter\currentdelimitedlanguage - \typo_delimited_show_language<\hss - \ignorespaces} - -\def\typo_delimited_stop_content - {\removeunwantedspaces - \removelastskip % redundant - \typo_delimited_show_language\hss<% - \endgroup - \dostoptagged} - -\tolerant\def\typo_delimited_start_par[#1]% - {\let\typo_delimited_stop\typo_delimited_stop_par - \edef\p_delimited_spacebefore{\delimitedtextparameter\c!spacebefore}% - \ifempty\p_delimited_spacebefore \else - \blank[\p_delimited_spacebefore]% - \fi - \delimitedtextparameter\c!before - \edef\m_delimited_argument{#1}% - \ifempty\m_delimited_argument - \let\m_delimited_argument\m_delimited_argument - \fi - \ifempty\m_delimited_argument - \endgraf - \doadaptleftskip {\delimitedtextparameter\c!leftmargin}% - \doadaptrightskip{\delimitedtextparameter\c!rightmargin}% - \let\typo_delimited_stop_par_indeed\endgraf - \else % backward compatible direct directive - \startnarrower[\m_delimited_argument]% - \let\typo_delimited_stop_par_indeed\stopnarrower - \fi - % so far - \push_macro_checkindentation - \useindentingparameter\delimitedtextparameter - % - \begingroup - \usedelimitedtextstyleandcolor\c!style\c!color - % - \begingroup - \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 - % - \typo_delimited_start_content} - -\let\typo_delimited_stop_par_indeed\endgraf - -\def\typo_delimited_stop_par - {\typo_delimited_stop_content - \rightdelimitedtextmark - \rightdelimitedtextmark - \carryoverpar\endgroup - \endgraf - \endgroup - \pop_macro_checkindentation - \typo_delimited_stop_par_indeed - \delimitedtextparameter\c!after - \edef\p_delimited_spaceafter{\delimitedtextparameter\c!spaceafter}% - \ifempty\p_delimited_spaceafter \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 - \typo_delimited_start_content} - -\def\typo_delimited_stop_txt - {\typo_delimited_stop_content - \typo_delimited_handle_right\c!right - \endgroup} - -\permanent\protected\def\stopdelimitedtext - {\typo_delimited_stop - \dostoptagged - \typo_delimited_pop - \endgroup} - -\permanent\tolerant\protected\def\delimitedtext[#1]#*[#2]% - {\dontleavehmode % following ones can be omited - \typo_delimited_push{#1}{#2}% - \edef\p_delimited_method{\delimitedtextparameter\c!method}% - \ifx\p_delimited_method\v!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 - \expandafter\typo_delimited_par - \orelse\ifx\p_delimited_location\v!margin - \expandafter\typo_delimited_par - \else - \expandafter\typo_delimited_txt - \fi} - -% shortcuts - -\permanent\protected\def\startdelimited{\startdelimitedtext} -\permanent\protected\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned -\permanent \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 - -\permanent\protected\def\setnextleftdelimitedtextmark - {\ifempty\p_delimited_nextleft - % nothing - \orelse\ifx\p_delimited_nextleft\v!left - \typo_delimited_nextleft_symbol\p_delimited_left - \orelse\ifx\p_delimited_nextleft\v!right - \typo_delimited_nextleft_symbol\p_delimited_right - \else - \typo_delimited_nextleft_symbol\p_delimited_nextleft - \fi} - -\permanent\protected\def\setnextrightdelimitedtextmark - {\ifempty\p_delimited_nextright - % nothing - \orelse\ifx\p_delimited_nextright\v!right - \typo_delimited_nextright_symbol\p_delimited_right - \orelse\ifx\p_delimited_nextright\v!left - \typo_delimited_nextright_symbol\p_delimited_left - \else - \typo_delimited_nextright_symbol\p_delimited_nextright - \fi} - -\permanent\protected\def\leftdelimitedtextmark - {\ifempty\p_delimited_left - % nothing - \else - \typo_delimited_left_symbol\p_delimited_left - \fi} - -\permanent\protected\def\rightdelimitedtextmark - {\ifempty\p_delimited_right - % 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% - {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed - \localleftbox\bgroup - \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter - \boundarycharactermode\plusone - \typo_delimited_left_symbol#1% - \egroup} - -\def\typo_delimited_nextright_symbol#1% - {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed - \localrightbox\bgroup - \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter - \boundarycharactermode\plusone - \typo_delimited_right_symbol#1% - \egroup} - -\protected\def\typo_delimited_reset_next_symbol_indeed - {\localleftbox {}% - \localrightbox{}}% - -\let\typo_delimited_reset_next_symbol\relax - -\appendtoks - \typo_delimited_reset_next_symbol -\to \everyforgetall - -% \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 - -% We have no real test case for this and it's broken already for a while, -% even in \MKII. Maybe we should to this in \LUA. Only Italian has the -% middlespeech parameter set. - -\def\typo_delimited_handle_middle#1% special case - {\ifconditional\c_typo_delimited_repeating - \begingroup - \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor - \setbox\scratchbox\hbox{\delimitedtextparameter#1}% - \ifdim\wd\scratchbox>\zeropoint - \ifdim\lastkern=\d_typo_delimited_signal - \unkern - \hskip\hspaceamount\currentusedlanguage{interquotation}% - \else % maybe an option: - %\edef\p_delimited_margin{\delimitedtextparameter\c!location}% - %\ifx\p_delimited_margin\v!margin - % \hskip-\wd\scratchbox - %\fi - \fi - \strut % new, needed below - \dostarttagged\t!delimitedsymbol\empty - \dotagsetdelimitedsymbol\s!middle - \delimitedtextparameter#1% unhbox\scratchbox - \dostoptagged - % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods - \kern\d_typo_delimited_signal % +- \prewordbreak - \fi - \endgroup - \else - \settrue\c_typo_delimited_repeating - \fi} - -\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}% - \orelse\ifdim\lastskip=\d_typo_delimited_signal - \unskip - \hskip\hspaceamount\currentusedlanguage{interquotation}% - \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}% - \orelse\ifdim\lastskip=\d_typo_delimited_signal - \unskip - \penalty\plustenthousand - \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!right - \delimitedtextparameter#1% unhbox\scratchbox - \dostoptagged - \kern\d_typo_delimited_signal % +- \prewordbreak - \fi - \endgroup} - -\protected\def\typo_delimited_par - {\groupedcommand - {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext % block? - \usedelimitedtextstyleandcolor\c!style\c!color - \typo_delimited_handle_left\c!left - \typo_delimited_start_content} - {\typo_delimited_stop_content - \typo_delimited_handle_right\c!right - \removelastskip % hm - \dostoptagged - \typo_delimited_pop}} - -\protected\def\typo_delimited_txt - {\edef\p_left_right{\delimitedtextparameter\c!left\delimitedtextparameter\c!right}% - \ifempty\p_left_right - \expandafter\typo_delimited_attributed - \else - \expandafter\typo_delimited_quoted - \fi} - -\def\typo_delimited_quoted - {\dontleavehmode - \begingroup - \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext - \typo_delimited_handle_left\c!left - \usedelimitedtextstyleandcolor\c!style\c!color - \typo_delimited_start_content - \bgroup - \aftergroup\typo_delimited_quoted_e - \let\next=} - -\def\typo_delimited_quoted_e - {\typo_delimited_stop_content - \typo_delimited_handle_right\c!right - \removelastskip % ? - \dostoptagged - \typo_delimited_pop - \endgroup} - -\def\typo_delimited_attributed - {\dontleavehmode - \begingroup - \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext - \usedelimitedtextstyleandcolor\c!style\c!color - \typo_delimited_start_content - \bgroup - \aftergroup\typo_delimited_attributed_e - \let\next=} - -\def\typo_delimited_attributed_e - {\typo_delimited_stop_content - \dostoptagged - \typo_delimited_pop - \endgroup} - -\def\typo_delimited_fontdriven - {\dontleavehmode - \begingroup - \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext - \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext - \usedelimitedtextstyleandcolor\c!style\c!color - \typo_delimited_start_content - \bgroup - \aftergroup\typo_delimited_fontdriven_e - \let\next=} - -\def\typo_delimited_fontdriven_e - {\typo_delimited_stop_content - \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext - \dostoptagged - \typo_delimited_pop - \endgroup} - -% 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] - -\permanent\protected\def\setupquotation{\setupdelimitedtext[\v!quotation]} -\permanent\protected\def\setupquote {\setupdelimitedtext[\v!quote]} - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-dir.mkxl b/tex/context/base/mkiv/typo-dir.mkxl deleted file mode 100644 index 55fabffc0..000000000 --- a/tex/context/base/mkiv/typo-dir.mkxl +++ /dev/null @@ -1,207 +0,0 @@ -%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}{optimize} -\registerctxluafile{typo-dha}{} -%registerctxluafile{typo-dua}{} -%registerctxluafile{typo-dub}{} -\registerctxluafile{typo-duc}{} - -\definesystemattribute[directions][public,pickup] - -\installcorenamespace{directions} -\installcorenamespace{directionsbidimode} - -% plural as we can have a combination but maybe better singular - -\installsimplecommandhandler \??directions {directions} \??directions % no \define... yet - -\permanent\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark % expandable -\permanent\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark % expandable - -\permanent\protected\def\setdirection[#1]% todo: symbolic names - {\clf_setdirection#1\relax} - -% \protected\def\resetdirection -% {\clf_setdirection\zerocount} -% -% is in fact: - -\protected\def\resetdirection - {\c_attr_directions\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}% - }% - \global\letcsname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode} - -\appendtoks - \edef\p_bidi{\directionsparameter\c!bidi}% - \edef\currentbidistamp - {\p_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 - \ifx\p_bidi\v!global - \pickupdirectionsattribute - \else - \forgetdirectionsattribute - \fi -\to \everysetupdirections - -\appendtoks - \edef\p_option{\directionsparameter\c!break}% name can change - \bitwiseflip\normalizelinemode\ifx\p_option\v!both\else-\fi\breakafterdircode -\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!break=\v!both, % experimental value, maybe \v!no will be default (bad name too) - \c!fences=\v!yes] - -\permanent\protected\edef\bidilre{\normalUchar"202A} -\permanent\protected\edef\bidirle{\normalUchar"202B} -\permanent\protected\edef\bidipop{\normalUchar"202C} -\permanent\protected\edef\bidilro{\normalUchar"202D} -\permanent\protected\edef\bidirlo{\normalUchar"202E} - -\permanent\protected\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi} -\permanent\protected\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi} -\permanent\protected\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi} -\permanent\protected\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi} - -% for the moment: \setdirection[\plusone] - -\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 -% -% \protected\def\biditest#1#2#3% font text raw -% {\dontleavehmode\hbox -% {\framed[offset=overlay]{\tttf#2}\quad -% \enabletrackers[typesetters.directions]% -% \framed[offset=overlay]{#1#3}\quad -% \disabletrackers[typesetters.directions]% -% \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}} -% -% \startbuffer[bidi-sample] -% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par -% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par -% \biditest\Arabic{LATIN ARAB}{\lefttoright{\bidilro \LATIN\ \ARAB}}\par % right -> left -% \biditest\Arabic{LATIN ARAB}{\righttoleft{\bidilro \LATIN\ \ARAB}}\par % right -> left -% \biditest\Arabic{BARA NITAL}{\lefttoright{\bidirlo \LATIN\ \ARAB}}\par % left -> right -% \biditest\Arabic{BARA NITAL}{\righttoleft{\bidirlo \LATIN\ \ARAB}}\par % left -> right -% \stopbuffer -% -% \startbuffer[bidi-sample] -% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par -% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par -% \biditest\Arabic{LATIN ARAB}{\lefttoright\bidilro \LATIN\ \ARAB}\par % right -> left -% \biditest\Arabic{LATIN ARAB}{\righttoleft\bidilro \LATIN\ \ARAB}\par % right -> left -% \biditest\Arabic{BARA NITAL}{\lefttoright\bidirlo \LATIN\ \ARAB}\par % left -> right -% \biditest\Arabic{BARA NITAL}{\righttoleft\bidirlo \LATIN\ \ARAB}\par % left -> right -% \stopbuffer -% -% \startbuffer[bidi-setup] -% \setupdirections[bidi=off] -% \stopbuffer -% -% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} -% -% \startbuffer[bidi-setup] -% \setupdirections[bidi=global] -% \stopbuffer -% -% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} -% -% \startbuffer[bidi-setup] -% \setupdirections[bidi=local] -% \stopbuffer -% -% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} -% -% \startbuffer[bidi-sample] -% \setupdirections[bidi=global] -% -% \hbox{\righttoleft\arabicfont (0001)}\par -% \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par -% {\righttoleft\arabicfont (0003)\par} -% {\righttoleft\arabicfont (0004)}\par -% \dontleavehmode{\righttoleft\arabicfont (0005)\par} -% \dontleavehmode{\righttoleft\arabicfont (0006)}\par -% \rtlhbox{\arabicfont (0007)}\par -% \ltrhbox{\arabicfont (0008)}\par -% \dontleavehmode\rtlhbox{\arabicfont (0009)}\par -% \dontleavehmode\ltrhbox{\arabicfont (0010)}\par -% \stopsetups -% -% {\typebuffer[bidi-sample] \getbuffer[bidi-sample]} -% -% \stoptext diff --git a/tex/context/base/mkiv/typo-ini.mkxl b/tex/context/base/mkiv/typo-ini.mkxl deleted file mode 100644 index 3e0790af0..000000000 --- a/tex/context/base/mkiv/typo-ini.mkxl +++ /dev/null @@ -1,49 +0,0 @@ -%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}{} - -\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/tex/context/base/mkiv/typo-inj.mkxl b/tex/context/base/mkiv/typo-inj.mkxl deleted file mode 100644 index 7bd01aac0..000000000 --- a/tex/context/base/mkiv/typo-inj.mkxl +++ /dev/null @@ -1,75 +0,0 @@ -%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}{} - -% 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 - -\permanent \protected\def\resetinjector [#1]{\clf_resetinjector{#1}} -\permanent \protected\def\markinjector [#1]{\dontleavehmode\clf_markinjector{#1}} -\permanent\tolerant\protected\def\checkinjector [#1]#*[#2]{\clf_checkinjector{#1}{#2}} -\permanent \protected\def\checknextinjector [#1]{\clf_checkinjector{#1}{\v!next}} -\permanent \protected\def\checkpreviousinjector [#1]{\clf_checkinjector{#1}{\v!previous}} -%permanent \protected\def\checknextinjector [#1]{\clf_checknextinjector{#1}} -%permanent \protected\def\checkpreviousinjector [#1]{\clf_checkpreviousinjector{#1}} -\permanent\tolerant\protected\def\setinjector [#1]#*[#2]#*[#3]{\clf_setinjector{#1}{#2}{#3}} -\permanent\tolerant\protected\def\showinjector [#1]{\clf_showinjector{#1}} - -\permanent\protected\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 - -\permanent\protected\def\doinstallinjector#1% - {\letvalue{typo_injectors_mark_#1}\donothing - \letvalue{typo_injectors_check_#1}\donothing} - -\permanent\protected\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}}} - -\permanent\protected\def\dotestinjector#1% only for testing outside unprotect - {\begincsname typo_injectors_check_#1\endcsname - \begincsname typo_injectors_mark_#1\endcsname} - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-itc.mklx b/tex/context/base/mkiv/typo-itc.mklx deleted file mode 100644 index f979261c8..000000000 --- a/tex/context/base/mkiv/typo-itc.mklx +++ /dev/null @@ -1,60 +0,0 @@ -%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}{} - -\definesystemattribute[italics] [public] -\definesystemattribute[mathitalics][public] - -% \let\/=/ -% \let\emphasiscorrection\donothing - -\ifdefined \normalitaliccorrection \else - \aliased\let\normalitaliccorrection\italiccorrection -\fi - -\permanent\protected\def\italiccorrection - {\ifnum\c_attr_italics<\plusone\normalitaliccorrection\fi} - -\pushoverloadmode - \aliased\let\/\italiccorrection -\popoverloadmode - -% 1 = end of word -% 2 = end of word and end of a list - -\permanent\protected\def\setitaliccorrection [#code]{\clf_setitaliccorrection#code\relax} % todo: public implementor -\permanent\protected\def\resetitaliccorrection {\clf_resetitaliccorrection} % todo: public implementor -\permanent\protected\def\setupitaliccorrection[#settings]{\clf_setupitaliccorrection{#settings}} % todo: public implementor - -% global : no attributes, just always (faster and less memory) -% text : only text -% always : text and boxes -% none : - - -\appendtoks - \c_attr_italics\attributeunsetvalue -\to \everymathematics - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-krn.mkxl b/tex/context/base/mkiv/typo-krn.mkxl deleted file mode 100644 index 5573fc529..000000000 --- a/tex/context/base/mkiv/typo-krn.mkxl +++ /dev/null @@ -1,143 +0,0 @@ -%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}{} - -\definesystemattribute[kern][public] - -% more -% -% {\setcharacterkerning[extrakerning]\input davis\relax} - -\installcorenamespace{characterkerning} - -\installcommandhandler \??characterkerning {characterkerning} \??characterkerning - -\permanent\protected\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}} - -\permanent\protected\def\resetcharacterkerning % fast one - {\c_attr_kern\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) \unknown\ this -%D 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 then we always -%D would get a command defined which is not beforehand a good idea. -%D -%D Here we need to keep the groupedcommand solution as it is used as modifier. - -\appendtoks - \frozen\instance\setuevalue{\currentcharacterkerning}% - {\doifelsenextoptional - {\typo_kerning_apply_yes{\currentcharacterkerning}}% - {\typo_kerning_apply_nop{\currentcharacterkerning}}}% -\to \everydefinecharacterkerning - -\protected\def\typo_kerning_apply_yes#1[#2]% - {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}{#2}}\donothing} - -\protected\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 murder. Nevertheless -%D we support this manipulation for use in 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] - -\permanent\protected\def\setupstretched - {\setupcharacterkerning[\v!stretched]} - -\pushoverloadmode - -\enforced\permanent\tolerant\protected\def\stretched[#1]#:#2% - {\begingroup - \let\currentcharacterkerning\v!stretched - \ifparameter#1\or - \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} - -\popoverloadmode - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-lan.mkxl b/tex/context/base/mkiv/typo-lan.mkxl deleted file mode 100644 index 9d137f5a5..000000000 --- a/tex/context/base/mkiv/typo-lan.mkxl +++ /dev/null @@ -1,64 +0,0 @@ -%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}{} - -%D \macros -%D {averagecharwidth, charwidthlanguage} -%D -%D This is a more \MKIV-ish variant of lang-frq.mkiv. The methods are gone as one -%D doesn't need the tables for them. The main macro is \type {\averagecharwidth} -%D which behaves like a dimension register. -%D -%D I finally decided to reimplement this as I needed it for a manual (which is often -%D a reason for such a rewrite). With some inspiring Porcupine Tree in the -%D background it's not the worst thing to do. - -\mutable\def\charwidthlanguage{\currentmainlanguage} - -\permanent\def\averagecharwidth {\dimexpr\clf_averagecharwidth{\charwidthlanguage}\scaledpoint\relax} -\permanent\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/tex/context/base/mkiv/typo-lig.mkxl b/tex/context/base/mkiv/typo-lig.mkxl deleted file mode 100644 index e30774d8e..000000000 --- a/tex/context/base/mkiv/typo-lig.mkxl +++ /dev/null @@ -1,23 +0,0 @@ -%D \module -%D [ file=typo-lig, -%D version=2014.12.01, -%D title=\CONTEXT\ Typesetting Macros, -%D subtitle=Ligatures, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Typesetting Macros / Ligatures} - -%D The original macro was mostly used for testing an attribute that blocks ligatures -%D in the nodemode handler. In \LMTX\ things are done differently. - -\unprotect - -\permanent\protected\def\noligature{\dontleavehmode\groupedcommandcs\noligaturing\donothing} - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-lin.lmt b/tex/context/base/mkiv/typo-lin.lmt deleted file mode 100644 index e49f13b60..000000000 --- a/tex/context/base/mkiv/typo-lin.lmt +++ /dev/null @@ -1,475 +0,0 @@ -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 par node is no longer of any use so we remove it (each line has the --- direction attached). We might at some point also strip the disc nodes as they no longer serve --- a purpose but that can better be a helper. Anchoring left has advantage of keeping page --- stream. --- --- 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 linelist_code = listcodes.line ------ par_code = nodecodes.par -local leftskip_code = gluecodes.leftskip -local rightskip_code = gluecodes.rightskip -local parfillskip_code = gluecodes.parfillskip - -local tonut = nodes.tonut -local tonode = nodes.tonode - -local nexthlist = nuts.traversers.hlist -local insert_before = nuts.insert_before -local insert_after = nuts.insert_after -local find_tail = nuts.tail -local rehpack = nuts.rehpack ------ 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 setlink = nuts.setlink -local setkern = nuts.setkern -local getkern = nuts.getkern -local getdirection = nuts.getdirection -local getshift = nuts.getshift -local setshift = nuts.setshift -local getwidth = nuts.getwidth -local setwidth = nuts.setwidth - -local setprop = nuts.setprop -local getprop = nuts.rawprop -- getprop - -local effectiveglue = nuts.effective_glue - -local nodepool = nuts.pool -local new_kern = nodepool.kern -local new_leftskip = nodepool.leftskip -local new_rightskip = nodepool.rightskip -local new_hlist = nodepool.hlist -local new_rule = nodepool.rule -local new_glue = nodepool.glue - -local righttoleft_code = nodes.dirvalues.righttoleft - -local texgetcount = tex.getcount -local texgetglue = tex.getglue -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters - -local jobpositions = job.positions -local getposition = jobpositions.get -local getreserved = jobpositions.getreserved - -local paragraphs = { } -typesetters.paragraphs = paragraphs - -local addskips = false -- todo: use engine normalizer -local noflines = 0 - --- This is the third version, a mix between immediate (prestine lines) and delayed --- as we don't want anchors that are not used. - --- I will make a better variant once lmtx is stable i.e. less clutter. - -local function finalize(prop,key) -- delayed calculations - local line = prop.line - local hsize = prop.hsize - local width = prop.width - local shift = getshift(line) -- dangerous as it can be vertical as well - local reverse = getdirection(line) == righttoleft_code 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 = getwidth(line) - 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 = getwidth(head) or 0 - end - current = getnext(head) - id = getid(current) - end - -- no: - -- if id == par_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 = getwidth(current) 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 - --- do we still need this: - -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 - -- normalizer : todo, get the data, no need to normalize - for line, subtype in nexthlist, head do - if subtype == linelist_code and not getprop(line,"line") then - normalize(line) - end - end - return head, true -- true is obsolete -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 - anchor = new_hlist(setlink( - anchor, - new_kern(-65536/4), - new_rule(65536/2,4*65536,4*65536), - new_kern(-65536/4-4*65536), - new_rule(8*65536,65536/4,65536/4) - )) - setwidth(anchor,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 - setkern(prev,getkern(prev) + dx) - end - if next and getid(next) == kern_code then - setkern(next,getkern(next) - dx) - end - end - if dy ~= 0 then - if getid(blob) == hlist_code then - setshift(blob,getshift(blob) + dy) - end - end - else --- report("no line") - end - end -end - -local latelua = nodepool.latelua -local setposition = jobpositions.setspec - -local function setanchor(h_anchor) - return latelua { - action = setposition, - name = "md:h", - index = h_anchor, - value = { x = true, c = true }, - } -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/tex/context/base/mkiv/typo-lin.mkxl b/tex/context/base/mkiv/typo-lin.mkxl deleted file mode 100644 index 6b142b32d..000000000 --- a/tex/context/base/mkiv/typo-lin.mkxl +++ /dev/null @@ -1,25 +0,0 @@ -%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}{autosuffix} - -\unprotect - -% nothing yet / experimental - -\protect \endinput - diff --git a/tex/context/base/mkiv/typo-mar.mkxl b/tex/context/base/mkiv/typo-mar.mkxl deleted file mode 100644 index 5d6f15f21..000000000 --- a/tex/context/base/mkiv/typo-mar.mkxl +++ /dev/null @@ -1,471 +0,0 @@ -% 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 one of the things -%D that I really need myself, for instance when rendering rather unpredictable -%D (educational) tests encoded in XML. This module permits anchoring for instance -%D item numbers and also overload them when they have subnumbers. In the future it -%D might replace the current maginal note mechanism (that then will be just an -%D instance). -%D -%D In spite of what might be expected, the more advanced \LUA\ based variant is upto -%D twice as fast on simple entries. Also, we no longer need an extra pass to get -%D inner and outer alignments in sync with the pagebuilder. - -\registerctxluafile{typo-mar}{} - -%definesystemattribute[margindata] % only at the lua end - -%D In \MKII\ we have three categories and their historically meaning is as follows: -%D -%D marginlines: These are flushed relative to the start of a line and need to be -%D invoked there. -%D -%D marginwords: These can be issued in the text flow and will migrate sidewards; in -%D spite of the name, it can be a paragraph of text as well, but normally it's -%D words. -%D -%D margintexts: These can be set beforehand and are flushed at the next paragraph of -%D 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. It can be -%D anchored in the text or given beforehand in which case it gets flushed at the -%D first occasion. -%D -%D margintext: This runs on top of margindata and the only difference is that it -%D uses the framed mechanism for packaging. -%D -%D Stacking is done differently as is inner and outer alignment (in most cases more -%D efficient). The functionality is mostly the same as in \MKII, but there are a few -%D additions, like names entries, where later ones overload preceding not yet -%D flushed ones. Data can get catagorized and is then treated as a group (e.g. when -%D stacking is needed). -%D -%D The amount of \TEX\ code is less than in \MKII\ because we do all trickery in at -%D the \LUA\ end. At the end of this file we define several commands, like \type -%D {\inleftmargin} and \type {\inleft}. You can configure them individually or as a -%D group. There is an 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 on -%D 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!stackname=, - % \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, % so by default we scale the strut to the font ! - \c!offset=\v!overlay, - \c!fr!analyze=\v!yes, - \c!frame=\v!off, - \c!width=\margindataparameter\c!width, - \c!align=\margindataparameter\c!align] - -\appendtoks - \frozen\instance\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 - \pickupattributes -\to \everymargindatacontent - -% trialtypesetting: no need for margin stuff while trialing as -% is has no dimensions - -\newcount\nofmargintexts -\newcount\c_typo_margins_n - -\ifdefined\dotagmarginanchor \else \let\dotagmarginanchor\gobbleoneargument \fi -\ifdefined\dotagmargintext \else \let\dotagmargintext \gobbleoneargument \fi - -\definepagestate[\s!margintext] - -\protected\def\typo_margins_data_synchronize - {\doforcedtrackpagestate\s!margintext\nofmargintexts % includes increment - \docheckpagestate\s!margintext\nofmargintexts - %\doifelserightpagestate\s!margintext\nofmargintexts\relax\relax - \realpageno\realpagestateno - \swapmargins} - -\permanent\protected\def\margindata - {\iftrialtypesetting - \expandafter\typo_margins_data_nop - \else - \expandafter\typo_margins_data_yes - \fi} - -\permanent\tolerant\protected\def\typo_margins_data_nop[#name]#spacer[#dataparameters]#spacer[#textparameters]#:#content% - {} - -\permanent\tolerant\protected\def\typo_margins_data_yes[#name]#spacer[#dataparameters]#spacer[#textparameters]#:#content% - {\setfalse\inhibitmargindata % flushing afterwards - \begingroup - %\settrue\inhibitmargindata % no flushing in here - \def\currentmargindata{#name}% - \let\currentmarginframed\currentmargindata - \ifparameter#dataparameters\or - \setupcurrentmargindata[#dataparameters]% - \fi - \doifelsenothing{#content}\donefalse\donetrue - \global\advance\c_typo_margins_n\plusone - \ifdone - \edef\currentmarginreference{\margindataparameter\c!reference}% - \ifempty\currentmarginreference \else - \strc_references_set_page_only_destination_box_attribute\currentmarginreference\currentmarginreference - \fi - \edef\currentmargindatastrut{\margindataparameter\c!strut}% - \dostarttaggedchained\t!margintext\currentmargindata\??margindata - \dotagmargintext\c_typo_margins_n - \ifcsname\currentmarginframedhash\s!parent\endcsname - \setbox\nextbox\naturalhbox \currentmarginreference \bgroup - \the\everymargindatacontent - \usemargindatastyleandcolor\c!style\c!color - \setupcurrentmarginframed[\c!location=\v!normal,#textparameters]% - \typo_margins_data_synchronize - \inheritedmarginframedframed\bgroup - \ifempty\currentmargindatastrut \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}% - \ifempty\currentmargindatawidth - \setbox\nextbox\naturalhbox \currentmarginreference \bgroup - \typo_margins_data_synchronize - \the\everymargindatacontent - \usemargindatastyleandcolor\c!style\c!color - \ifempty\currentmargindatastrut \else - \synchronizestrut\currentmargindatastrut - \fi - \begstrut - \strc_references_flush_destination_nodes - \margindataparameter\c!command{#content}% - \endstrut - \egroup - \let\currentmarginfirstheight\empty - \else - \setbox\nextbox\naturalhbox \currentmarginreference \bgroup - \typo_margins_data_synchronize - \dosetraggedcommand{\margindataparameter\c!align}% - \vtop \bgroup - \the\everymargindatacontent - \usemargindatastyleandcolor\c!style\c!color - \hsize\currentmargindatawidth - \raggedcommand - \ifempty\currentmargindatastrut \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 - \dostarttagged\t!marginanchor\empty - \dotagmarginanchor\c_typo_margins_n - \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 - \ifempty\currentmarginfirstheight \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 - stackname {\margindataparameter\c!stackname}% - stack {\margindataparameter\c!stack}% - index \c_typo_margins_n - \relax - \dostoptagged - \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: - -\appendtoks - \enforced\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] - -\aliased\let\marginword \margintext -\aliased\let\margintitle \margintext -\aliased\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 ... it will disappear from lmtx: - -\permanent\tolerant\protected\def\defineinmargin[#name]#spacer[#location]#spacer[#align]#spacer[#settings]% not completely compatible - {\ifarguments\else - \definemargindata[#name][\c!location=#location,\c!align=#align,#settings]% - \definemarginframed[#name][#location][\c!align=#align,#settings]% - \fi} - -\aliased\let\definemarginline\definemargindata % for old times sake -\aliased\let\setupinmargin \setupmargindata % only partial (no framed), for old times sake - -% 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 - -%D Here because in strc-ren we are too early: - -% % \definemargindata -% % [margintext:chapter] -% % [margintext:section] -% % -% % \defineheadalternative -% % [margintext:chapter] -% % [margintext] -% % [margintext=margintext:chapter] -% % -% % \setuphead -% % [chapter] -% % [alternative=margintext:chapter] -% -% \setuphead -% [chapter] -% [alternative=margintext] - -\definemargindata - [\v!margintext:\v!section] - [\v!left] - [\c!margin=\v!margin, - \c!width=\leftmarginwidth, - \c!align=\v!flushright] - -\defineheadalternative - [\v!margintext] - [\c!alternative=\v!somewhere, - \c!margintext=\v!margintext:\v!section, - \c!renderingsetup=\??headrenderings:\v!margintext] - -\startsetups[\??headrenderings:\v!margintext] - \executeifdefined{\headalternativeparameter\c!margintext}\margintext { - \ifconditional\headshownumber - \headnumbercontent - \hskip\headnumberdistance - \fi - \headtextcontent - } -\stopsetups - -\protect \endinput diff --git a/tex/context/base/mkiv/typo-pnc.mkxl b/tex/context/base/mkiv/typo-pnc.mkxl deleted file mode 100644 index b5b1a17d6..000000000 --- a/tex/context/base/mkiv/typo-pnc.mkxl +++ /dev/null @@ -1,55 +0,0 @@ -%D \module -%D [ file=typo-pnc, -%D version=2017.06.23, % experiment in project -%D title=\CONTEXT\ Typesetting Macros, -%D subtitle=Punctuation, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This 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 / Punctuation} - -\unprotect - -% In manuals we often have "foo e.g. bar" where we then have to compensate spaces -% with "foo e.g.\ bar" so let's see if we can automate that and at the same time -% inject spaces between the snippets. It gets boring writing this kind of code. - -\registerctxluafile{typo-pnc}{} - -\definesystemattribute[periodkern][public,global] - -\installcorenamespace{periodkerning} - -\installcommandhandler \??periodkerning {periodkerning} \??periodkerning - -\permanent\protected\def\setperiodkerning[#1]% - {\edef\currentperiodkerning{#1}% - \ifx\currentperiodkerning\s!reset - \resetperiodkerning - \else - \typo_periodkerning_set - \fi} - -\def\typo_periodkerning_set - {\clf_setperiodkerning{\periodkerningparameter\c!factor}} - -\permanent\protected\def\resetperiodkerning % fast one - {\c_attr_periodkern\attributeunsetvalue} - -\appendtoks - \resetperiodkerning -\to \everyresettypesetting - -\defineperiodkerning [zerospaceperiods] [\c!factor=0] -\defineperiodkerning [smallspaceperiods] [\c!factor=.25] -\defineperiodkerning [halfspaceperiods] [\c!factor=.5] - -% If we ever need a command, see typo-krn.mkiv but it doesn't make much sense -% to have it. - -\protect diff --git a/tex/context/base/mkiv/typo-scr.mkxl b/tex/context/base/mkiv/typo-scr.mkxl deleted file mode 100644 index 36e2997e2..000000000 --- a/tex/context/base/mkiv/typo-scr.mkxl +++ /dev/null @@ -1,266 +0,0 @@ -%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 - -\protected\def\typo_scripts_low[#1]#2% - {\dontleavehmode - \begingroup - \edef\currentlow{#1}% - \kern\lowparameter\c!distance\relax - \setbox\scratchbox\runninghbox\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} - -\protected\def\typo_scripts_high[#1]#2% - {\dontleavehmode - \begingroup - \edef\currenthigh{#1}% - \kern\highparameter\c!distance\relax - \setbox\scratchbox\runninghbox\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} - -\permanent\protected\def\low {\typo_scripts_low []} -\permanent\protected\def\high{\typo_scripts_high[]} - -%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 - \frozen\setuevalue\currentlowhigh{\typo_scripts_lowhigh[\currentlowhigh]}% -\to \everydefinelowhigh - -\tolerant\protected\def\typo_scripts_lowhigh[#1]#*[#2]#:#3#4% todo: align .. [#1] is compatible hack - {\dontleavehmode - \runninghbox\bgroup - \edef\currentlowhigh{#1}% - \dostarttagged\t!subsup\currentlowhigh - \scratchdimen\lowhighparameter\c!distance\relax - \setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#3}}% - \setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#4}}% - \edef\p_align{#2}% - \ifx\p_align\v!left - \ifdim\wd\plusfour<\wd\plussix - \setbox\plusfour\hpack to \wd\plussix {\hss\box\plusfour}% - \else - \setbox\plussix \hpack to \wd\plusfour{\hss\box\plussix }% - \fi - \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% - {\kern\scratchdimen - \setbox\scratchbox\hpack\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} - -\permanent\tolerant\protected\def\typo_scripts_highlow[#1]#*[#2]#:#3#4% - {\typo_scripts_lowhigh[#1][#2]{#4}{#3}} - -\permanent\protected\def\lohi{\typo_scripts_lowhigh[]} -\permanent\protected\def\hilo{\typo_scripts_highlow[]} - -%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 - \frozen\setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh[\currentlowmidhigh]}% -\to \everydefinelowmidhigh - -\protected\def\typo_scripts_lowmidhigh[#1]#2#3#4% - {\dontleavehmode - \runninghbox\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 \hpack to \scratchdimen{\hss\lower\lowmidhighparameter\c!down\box\plustwo \hss}% - \setbox\plusfour\hpack to \scratchdimen{\hss \box\plusfour\hss}% - \setbox\plussix \hpack to \scratchdimen{\hss\raise\lowmidhighparameter\c!up \box\plussix \hss}% - \wd\plustwo \zeropoint - \wd\plusfour\zeropoint - \box\plusfour - \box\plustwo - \box\plussix - \dostoptagged - \egroup} - -\permanent\protected\def\lomihi {\typo_scripts_lowmidhigh[]} -\permanent\protected\def\himilo#1#2#3{\typo_scripts_lowmidhigh[]{#3}{#2}{#1}} - -\protect \endinput diff --git a/tex/context/base/mkiv/unic-ini.mkxl b/tex/context/base/mkiv/unic-ini.mkxl deleted file mode 100644 index 3fccd2feb..000000000 --- a/tex/context/base/mkiv/unic-ini.mkxl +++ /dev/null @@ -1,36 +0,0 @@ -%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}{} - -\unprotect - -\permanent\def\unicodenumber #1{\the\numexpr#1\relax} % no lookahead -\permanent\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 - -\permanent\def\unicodechar#1{\clf_unicodechar{#1}} - -\permanent\protected\def\unknownchar - {\dontleavehmode\hpack{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}} - -\ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace - -\protect \endinput diff --git a/tex/context/base/mkxl/anch-bar.mkxl b/tex/context/base/mkxl/anch-bar.mkxl new file mode 100644 index 000000000..3587eb8a0 --- /dev/null +++ b/tex/context/base/mkxl/anch-bar.mkxl @@ -0,0 +1,220 @@ +%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 This can be done better now ... + +%D We will implement a sidebar mechanism using the functionality from +%D \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] + +\aliased\let\setupsidebars\setupsidebar + +\permanent\tolerant\protected\def\startsidebar[#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 + \ifhastok={#1}% + \edef\currentsidebar{\the\c_anch_sidebars_level}% + \checksidebarparent + \setupcurrentsidebar[#1]% + \else + \def\currentsidebar{#1}% + \setupcurrentsidebar[#2]% + \fi + \scratchdistance\sidebarparameter\c!distance\relax + \scratchdimen\sidebarparameter\c!leftmargindistance\relax + \edef\m_level{\sidebarparameter\c!level}% + \ifempty\m_level + \ifnum\c_anch_sidebars_level=\plusone + \ifzeropt\scratchdimen + \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 + \ifzeropt\scratchdimen + \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} + +\permanent\protected\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}% + 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 + +\permanent\tolerant\protected\def\setupmarginrule[#1]#*[#2]% + {\ifarguments\or + \setupsidebar[\v!margin][#1]% + \or + \setupsidebar[\v!margin:#1][#2]% + \fi} + +\aliased\let\setupmarginrules\setupmarginrule + +\permanent\tolerant\protected\def\startmarginrule[#1]% pretty inefficient checking + {\edef\m_anch_marginrules_kind{#1}% + \ifempty\m_anch_marginrules_kind + \startsidebar[\v!margin][]% + \orelse\ifhastok={\m_anch_marginrules_kind}% + \startsidebar[\v!margin][#1]% + \else + \anch_marginrules_check{#1}% + \startsidebar[\v!margin:#1][\c!level=#1]% + \fi} + +\def\anch_marginrules_check#1% + {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}} + +\aliased\let\stopmarginrule\stopsidebar + +\protect \endinput diff --git a/tex/context/base/mkxl/anch-bck.mklx b/tex/context/base/mkxl/anch-bck.mklx new file mode 100644 index 000000000..3f0504c4b --- /dev/null +++ b/tex/context/base/mkxl/anch-bck.mklx @@ -0,0 +1,754 @@ +%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 that use +%D attributes although not too much is to be expected, apart from better anchoring. +%D In fact better anchoring can be 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 + +\protected\def\anch_backgrounds_text_initialize + {\doifelsepositionsused\enableparpositions\donothing + \glet\anch_backgrounds_text_initialize\relax} + +\appendtoks + \anch_backgrounds_text_initialize +\to \everystarttext + +%D Some MP + +\newcount\MPparcounter + +\permanent\def\MPself {\MPvar{self}} +\permanent\def\MPbself {b:\MPvar{self}} +\permanent\def\MPeself {e:\MPvar{self}} +\permanent\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 + \frozen\instance\setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}% + \frozen\instance\setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}% + \frozen\instance\setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}% +\to \everydefinetextbackground + +\newconstant \c_anch_backgrounds_pos_state +\newconditional\c_anch_backgrounds_pos_no_shape + +\def\anch_backgrounds_bpos + {\ifconditional\c_anch_backgrounds_pos_no_shape + \bposkind\v_anch_backgrounds_text_current\plusthree + \else + \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state + \fi} + +\def\anch_backgrounds_epos + {\ifconditional\c_anch_backgrounds_pos_no_shape + \eposkind\v_anch_backgrounds_text_current\plusthree + \else + \eposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state + \fi} + +% \permanent\tolerant\protected\def\starttextbackground[#tag]#spacer[#settings]% +% {\begingroup +% \advance\c_anch_backgrounds_text_level\plusone +% \def\currenttextbackground{#tag}% +% \anch_backgrounds_text_initialize_next +% \ifparameter#settings\or +% \setupcurrenttextbackground[#settings]% +% \fi +% \doifelse{\textbackgroundparameter\c!state}\v!start +% \anch_backgrounds_text_preset_yes +% \anch_backgrounds_text_preset_nop +% \anch_backgrounds_text_start_indeed} + +% ugly hack to register usage + +\newcount \c_anch_backgrounds_text_count +\newcount \c_anch_backgrounds_text_check +\newconstant\c_anch_backgrounds_text_state + +\permanent\tolerant\protected\def\starttextbackground[#tag]#spacer[#settings]% + {\begingroup + \global\advance\c_anch_backgrounds_text_count\plusone + \advance\c_anch_backgrounds_text_level\plusone + \def\currenttextbackground{#tag}% + \anch_backgrounds_text_initialize_next + \ifparameter#settings\or + \setupcurrenttextbackground[#settings]% + \fi + \doifelse{\textbackgroundparameter\c!state}\v!start + \anch_backgrounds_text_preset_yes + \anch_backgrounds_text_preset_nop + \anch_backgrounds_text_start_indeed} + +\def\anch_backgrounds_text_level_start + {\c_anch_backgrounds_text_check\c_anch_backgrounds_text_count} + +\def\anch_backgrounds_text_level_stop + {\c_anch_backgrounds_text_state + \ifnum\c_anch_backgrounds_text_count>\c_anch_backgrounds_text_check + \plusone + \else + \zerocount + \fi} + +% todo \backgroundvariable\c!variant + +% criterium determines when we fall back on text +% always is always forcing paragraphs + +\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>\textbackgroundparameter\c!criterium\relax + \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!always}% + {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par + \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par} + +\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}}} + +\permanent\protected\def\stoptextbackground + {\anch_backgrounds_text_stop_indeed + \carryoverpar\endgroup} % why doesn't this work ? + +\permanent\protected\def\starttextbackgroundmanual + {\begingroup + \c_anch_backgrounds_pos_state\plusone + \usetextbackgroundstyleandcolor\c!style\c!color + \anch_backgrounds_bpos} + +\permanent\protected\def\stoptextbackgroundmanual + {\anch_backgrounds_epos + \carryoverpar\endgroup} + +\def\anch_backgrounds_text_start_txt + {\ifvmode \dontleavehmode \fi + \begingroup + \c_anch_backgrounds_pos_state\plusone + \usetextbackgroundstyleandcolor\c!style\c!color + \anch_backgrounds_bpos} + +\def\anch_backgrounds_text_stop_txt + {\anch_backgrounds_epos + \carryoverpar\endgroup} + +\newskip\textbackgroundskip + +% maybe we should have a resetter for such compensation struts + +\def\anch_backgrounds_reset_attributes + {\scratchcounter\c_attr_snapmethod + \resetallattributes % \c_attr_linenumber\attributeunsetvalue + \c_attr_snapmethod\scratchcounter} + +\def\anch_backgrounds_text_start_par % beware .. background shapes + {\endgraf % new + \textbackgroundparameter\c!before + \begingroup + \c_anch_backgrounds_pos_state\plustwo + \begingroup + \anch_backgrounds_reset_attributes + \noindent + \ifgridsnapping + \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}% + \ifdim\textbackgroundskip>\zeropoint + \struttedbox % not always ok (e.g. setups) + {\hpack{\raise\textbackgroundskip\hpack{\anch_backgrounds_bpos}}}% + \else + \anch_backgrounds_bpos + \fi + \else + \anch_backgrounds_bpos + \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 + \orelse\ifdim\textbackgroundskip>\zeropoint + \kern\textbackgroundskip\nobreak + \fi + \nobreak + \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent + \nobreak + \endgroup + \begingroup + \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM + \anch_backgrounds_reset_attributes + \nobreak \noindent \strut \hfill \kern\zeropoint + % so far + \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}% + \ifgridsnapping % experimental, pascal (todo: topoffset in same way) + \ifdim\textbackgroundskip>\zeropoint + \struttedbox % not always ok (e.g. setups) + {\hpack{\lower\textbackgroundskip\hpack{\anch_backgrounds_epos}}}% + \else + \anch_backgrounds_epos + \fi + \else + \anch_backgrounds_epos + \fi + \endgraf + \carryoverpar\endgroup + \endgraf % new + \textbackgroundparameter\c!after} + +\permanent\protected\def\checkpositionoverlays % overloads \relax in anch-pgr + {\ifproductionrun + \enabletextarearegistration + \enablehiddenbackground + \enforced\glet\checkpositionoverlays\relax + \fi} + +% shape handling + +\definesystemattribute[textbackground][public] + +% \def\page_prepare_backgrounds#1% +% {\clf_collectbackgrounds\realpageno#1\relax} + +\def\anch_backgrounds_bpos + {\ifconditional\c_anch_backgrounds_pos_no_shape + \c_attr_textbackground\attributeunsetvalue + \bposkind\v_anch_backgrounds_text_current\plusthree + \orelse\ifnum\c_anch_backgrounds_pos_state=\plusone + \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state + \clf_registerbackground{\v_anch_backgrounds_text_current}% + \else + \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state + \c_attr_textbackground\attributeunsetvalue + \fi} + +% plugs into other code + +\def\strc_floats_wrap_free_region + {\global\setbox\floatbox\hpack % we always need to wrap + {\ifconditional\c_strc_floats_trace_free + \strc_floats_show_free_region + \fi + \box\floatbox}} + +\startuseMPgraphic{floatfree} + draw_free_region( + \the\wd\floatbox, + \the\ht\floatbox, + \the\dp\floatbox, + \the\d_free_offset_left, + \the\d_free_offset_right, + \the\d_free_offset_top, + \the\d_free_offset_bottom + ) ; +\stopuseMPgraphic + +\def\strc_floats_show_free_region + {\lower\dp\floatbox\hpack to \zeropoint {\useMPgraphic{floatfree}}} + +\newconditional\c_strc_floats_mark_as_free +\newconditional\c_strc_floats_trace_free +\newconstant \c_free_offset_kind +\newdimen \d_free_offset_left +\newdimen \d_free_offset_right +\newdimen \d_free_offset_top +\newdimen \d_free_offset_bottom + +\installtextracker{floats.freeregion} + {\settrue \c_strc_floats_trace_free} + {\setfalse\c_strc_floats_trace_free} + +\def\strc_floats_mark_as_free#1#2#3#4#5% + {\c_free_offset_kind #1% + \d_free_offset_left #2% + \d_free_offset_right #3% + \d_free_offset_top #4% + \d_free_offset_bottom#5% + \strc_floats_wrap_free_region + \anch_mark_tagged_box_free + \floatbox + \c_free_offset_kind + \d_free_offset_left + \d_free_offset_right + \d_free_offset_top + \d_free_offset_bottom} + +\ifx\strc_floats_mark_pag_as_free\relax \else + \writestatus{error}{wrong place for pag_as_free}\wait +\fi + +\ifx\strc_floats_mark_par_as_free\relax \else + \writestatus{error}{wrong place for par_as_free}\wait +\fi + +\def\strc_floats_mark_pag_as_free + {\ifpositioning + \ifconditional\c_strc_floats_mark_as_free + \strc_floats_mark_as_free + \plusone + \zeropoint + \zeropoint + \d_strc_floats_top + \d_strc_floats_bottom + \fi + \fi} + +\def\strc_floats_mark_par_as_free + {\ifpositioning + \ifconditional\c_strc_floats_mark_as_free + \ifcase\c_page_sides_float_type + \or % backspace + \strc_floats_mark_as_free + \plustwo + \zeropoint + \d_page_sides_rightoffset + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % leftedge + \strc_floats_mark_as_free + \plustwo + \zeropoint + \d_page_sides_rightoffset + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % leftmargin + \strc_floats_mark_as_free + \plustwo + \zeropoint + \d_page_sides_rightoffset + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % leftside + \strc_floats_mark_as_free + \plustwo + \d_page_sides_leftskip % maybe too + \d_page_sides_margin + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % rightside + \strc_floats_mark_as_free + \plusthree + \d_page_sides_margin + \d_page_sides_rightskip % maybe too + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % rightmargin + \strc_floats_mark_as_free + \plusthree + \d_page_sides_leftoffset + \zeropoint + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % rightedge + \strc_floats_mark_as_free + \plusthree + \d_page_sides_leftoffset + \zeropoint + \d_page_sides_topskip + \d_page_sides_bottomskip + \or % cutspace + \strc_floats_mark_as_free + \plusthree + \d_page_sides_leftoffset + \zeropoint + \d_page_sides_topskip + \d_page_sides_bottomskip + \fi + \fi + \fi} + +% so far + +\setuptextbackground + [\c!mp=mpos:region:draw, + \c!method=mpos:region, + \c!state=\v!start, + \c!location=\v!text, + \c!leftoffset=\!!zeropoint, % 1em, + \c!rightoffset=\textbackgroundparameter\c!leftoffset, + \c!topoffset=\!!zeropoint, % \v!medium, + \c!bottomoffset=\textbackgroundparameter\c!topoffset, + \c!criterium=\plusone, + \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} + 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 boxgridcolor = \MPvar{gridcolor} enddef ; + def boxlinecolor = \MPvar{linecolor} enddef ; + def boxfillcolor = \MPvar{fillcolor} enddef ; + % + def boxgridoptions = withcolor boxgridcolor enddef ; + def boxlineoptions = withcolor boxlinecolor enddef ; + def boxfilloptions = withcolor boxfillcolor enddef ; +\stopuseMPgraphic + +\startuseMPgraphic{mpos:region:extra} + % user stuff +\stopuseMPgraphic + +\startuseMPgraphic{mpos:region:anchor} + setbounds currentpicture to multibox ; +\stopuseMPgraphic + +\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 + +%D For old times sake: + +\startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth} + string tag; tag := "\MPvar{self}" ; + path box ; box := positionbox(tag) ; + + box := box enlarged \MPvar{filloffset} ; + fill box withcolor \MPvar{fillcolor} ; + draw box withcolor \MPvar{linecolor} withpen pencircle scaled \MPvar{linewidth} ; + + positioninregion; +\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: + +\pushoverloadmode + +\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 + \aliased\letcsname\v!grid\endcsname\basegrid +\fi + +\popoverloadmode + +%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} + \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} + 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/tex/context/base/mkxl/anch-pgr.mkxl b/tex/context/base/mkxl/anch-pgr.mkxl new file mode 100644 index 000000000..62dfe02d5 --- /dev/null +++ b/tex/context/base/mkxl/anch-pgr.mkxl @@ -0,0 +1,460 @@ +%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 the reference point +%D on the page. The next macros do so and are hooked into the page building routine. + +\registerctxluafile{anch-pgr}{} + +\unprotect + +%D A few more low level macros take care of defining and recalling actions. Actions +%D are saved globally! The lists can become quite long because there can be lots of +%D parameters passed on so we clean up the list afterwards. + +\newtoks\everypositionaction +\newtoks\everyinsertpositionaction +\newtoks\everycleanpositionaction + +\installcorenamespace{positionaction} +\installcorenamespace{positioncleanup} + +\protected\def\anch_positions_set_action#1% + {\gdefcsname\??positionaction#1\endcsname} % nicely gobbles spaces + +\permanent\protected\def\doifpositionaction#1% + {\ifcsname\??positionaction#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifelsepositionaction#1% + {\ifcsname\??positionaction#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifpositionactionelse\doifelsepositionaction + +\permanent\protected\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 % \hpack + {\anch_positions_trace_action_yes + \the\everyinsertpositionaction + \the\everypositionaction + \begincsname\??positionaction\currentpositionaction\endcsname + \anch_positions_cleanup_action}% + \smashedbox\scratchbox % smashing is really needed else we get problems with too big overlays + \endgroup} + +\protected\def\anch_positions_trace_action_nop_indeed + {\anch_positions_trace\clap\darkred{<\currentpositionaction>}} + +\protected\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 for later execution. This +%D collection is especially handy when we want to move actions to a specific layer. +%D Such series of actions are stored in a macro that is cleaned up after each +%D invocation. + +\def\anch_positions_cleanup_action % not in trialtypesetting + {\ifcsname\??positioncleanup\currentpositionaction\endcsname + \the\everycleanpositionaction + \xdefcsname\??positioncleanup\currentpositionaction\endcsname + {\csname\??positioncleanup\currentpositionaction\endcsname}% + \fi} + +\permanent\protected\def\handlepositionaction#1\with#2\on#3% ugly, will change + {\begingroup + \edef\currentpositionanchor + {\ifempty\currentpositionoverlay#3\else\currentpositionoverlay::\MPanchoridentifier\fi}% + \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}% + \let#1\relax + \ifcsname\??positioncleanup\currentpositionanchor\endcsname + \xdefcsname\??positioncleanup\currentpositionanchor\endcsname + {\csname\??positioncleanup\currentpositionanchor\endcsname#1#2}% + \else + \xdefcsname\??positioncleanup\currentpositionanchor\endcsname + {#1#2}% + \fi + \endgroup} + +%D The first version of this module implemented head and tail anchors. Currently we +%D stick to just one anchor and derive the head and tail anchors from this one. We +%D set these anchors before and after each page. + +\newdimen\c_anch_page_width +\newdimen\c_anch_page_height + +\protected\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\hpack{\box#1}\fi + \fi + \else + \c_anch_page_width \paperwidth + \c_anch_page_height\paperheight + \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi + \fi + \fi\fi} + +\protected\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 % redundant + \wd\scratchbox\makeupwidth + \anch_mark_text_box\scratchbox + \box\scratchbox + \endgroup} + +\def\anch_positions_place_anchors_nop + {\vkern\textheight} + +%D \macros +%D {positionoverlay,startpositionoverlay} +%D +%D As long as we're dealing with graphics it makes much sense to use the available +%D overlay mechanism. For this purpose, we 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 macros defined in an +%D auxiliary \METAPOST\ module that is preloaded. +%D +%D \typebuffer[graphic] + +\immutable\def\MPanchoridentifier{mpa} % {mp-anchor} +\mutable \def\MPanchornumber {\the\realpageno} +\mutable \let\MPanchorid \empty + +%D The rest of the definitions concerning such overlays may look complicated, + +\mutable\let\currentpositionoverlay\empty + +%D Position actions are automatically executed when a position is set. + +\immutable\def\textbackgroundoverlay#1{\v!text#1} + +\permanent\protected\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} + +\permanent\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}% + \enforced\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used + \the\everyinsertpositionaction + \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid + \setbox\scratchbox\hbox to \d_overlay_width % \hpack + {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% + \ht\scratchbox\d_overlay_height + \dp\scratchbox\zeropoint + \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox + \box\scratchbox + \vfill}} + +\permanent\protected\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 + \enforced\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used + \the\everyinsertpositionaction + \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid + \setbox\scratchbox\hbox to \d_overlay_width % \hpack + {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% + \ht\scratchbox\d_overlay_height + \dp\scratchbox\zeropoint + \box\scratchbox + \vfill}} + +% \let\anch_positions_overlay_nop\gobbleoneargument + +\permanent\protected\def\startpositionoverlay + {\iftrialtypesetting + \expandafter\anch_positions_overlay_start_nop + \else + \expandafter\anch_positions_overlay_start_yes + \fi} + +\def\anch_positions_overlay_start_nop#1\stoppositionoverlay + {} + +\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi + +\mutable\let\currentpositionoverlay\empty + +\def\anch_positions_overlay_start_yes#1% + {\checkpositionoverlays + \edef\currentpositionoverlay{#1}} + +\permanent\protected\def\stoppositionoverlay + {\let\currentpositionoverlay\empty} + +%D A position graphic is a normal (non||reused) \METAPOST\ graphic, used +%D immediately, with zero dimensions, so that a sequence of them does not harm. + +\installcorenamespace{positiongraphic} +\installcorenamespace{positionmethod} +%installcorenamespace{graphicvariable} + +\newbox\b_anch_positions_graphic + +\permanent\tolerant\protected\def\startMPpositiongraphic#=#*#=#:#3\stopMPpositiongraphic % tag list mpcode + {\setgvalue{\??positiongraphic#1}{\anch_positions_meta_graphic_use{#1}{#2}{#3}}} + +\aliased\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} + +\permanent\tolerant\protected\def\MPpositiongraphic#=#*#=% + {\ifcsname\??positionmethod#1\endcsname % method + \expandafter\anch_positions_meta_graphic_direct_method + \orelse\ifcsname\??positiongraphic#1\endcsname + \expandafter\anch_positions_meta_graphic_direct_normal + \else + \expandafter\gobbletwoarguments + \fi{#1}{#2}} + +% \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}} + +\def\anch_positions_meta_graphic_direct_method{\anch_positions_meta_graphic_direct\??positionmethod } +\def\anch_positions_meta_graphic_direct_normal{\anch_positions_meta_graphic_direct\??positiongraphic} + +\def\anch_positions_meta_graphic_direct#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 + \enforced\tolerant\protected\def\MPpositiongraphic##=##*##={\anch_positions_meta_graphic_nested{#3}{##1}{##2}}% takes two extra arguments +% \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments + \setbox\b_anch_positions_graphic\hbox % \hpack + {\ignorespaces\begincsname#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 + \begincsname\??positiongraphic#2\endcsname + \endgroup}% + +\permanent\def\startMPpositionmethod#1#2\stopMPpositionmethod + {\gdefcsname\??positionmethod#1\endcsname{#2}} % todo: var list here + +\aliased\let\stopMPpositionmethod\relax + +%D Simple one position graphics. + +\permanent\tolerant\protected\def\setMPpositiongraphic#=#*#=#*#=% + {\ifempty\currentpositionoverlay + \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). + +\permanent\tolerant\protected\def\setMPpositiongraphicrange#=#*#=#*#=#*#=% + {\ifempty\currentpositionoverlay + \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: + +\permanent\def\MPgetposboxes #1#2{\clf_fetchposboxes{#1}{#2}\realpageno} +\permanent\def\MPgetmultipars#1#2{\clf_fetchmultipar{#1}{#2}\realpageno} + +\protect \endinput diff --git a/tex/context/base/mkxl/anch-pos.lmt b/tex/context/base/mkxl/anch-pos.lmt new file mode 100644 index 000000000..e1d9bd752 --- /dev/null +++ b/tex/context/base/mkxl/anch-pos.lmt @@ -0,0 +1,1633 @@ +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-- +

We save positional information in the main utility table. Not only +can we store much more information in but it's also +more efficient.

+--ldx]]-- + +-- plus (extra) is obsolete but we will keep it for a while +-- +-- maybe replace texsp by our own converter (stay at the lua end) +-- eventually mp will have large numbers so we can use sp there too +-- +-- this is one of the first modules using scanners and we need to replace it by +-- implement and friends +-- +-- we could have namespaces, like p, page, region, columnarea, textarea but then +-- we need virtual table accessors as well as have tag/id accessors ... we don't +-- save much here (at least not now) +-- +-- This was the last module that got rid of directly setting scanners, with a little +-- performance degradation but not that noticeable. + +local tostring, next, setmetatable, tonumber = tostring, next, setmetatable, tonumber +local sort = table.sort +local format, gmatch = string.format, string.gmatch +local lpegmatch = lpeg.match +local insert, remove = table.insert, table.remove +local allocate = utilities.storage.allocate + +local report = logs.reporter("positions") + +local scanners = tokens.scanners +local scanstring = scanners.string +local scaninteger = scanners.integer +local scandimen = scanners.dimen + +local implement = interfaces.implement + +local commands = commands +local context = context + +local ctx_latelua = context.latelua + +local tex = tex +local texgetcount = tex.getcount +local texgetinteger = tex.getintegervalue or tex.getcount +local texsetcount = tex.setcount +local texget = tex.get +local texsp = tex.sp +----- texsp = string.todimen -- because we cache this is much faster but no rounding + +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex + +local nuts = nodes.nuts + +local setlink = nuts.setlink +local getlist = nuts.getlist +local setlist = nuts.setlist +local getbox = nuts.getbox +local getid = nuts.getid +local getwhd = nuts.getwhd + +local hlist_code = nodes.nodecodes.hlist + +local find_tail = nuts.tail +----- hpack = nuts.hpack + +local new_latelua = nuts.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 + +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 + dir = 0, + } +} + +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_region = formatters["region:%s"] + +local f_tag_three = formatters["%s:%s:%s"] +local f_tag_two = formatters["%s:%s"] + +local nofregular = 0 +local nofspecial = 0 +local splitter = lpeg.splitat(":",true) + +local pagedata = { } +local columndata = setmetatableindex("table") -- per page +local freedata = setmetatableindex("table") -- per page + +local function initializer() + tobesaved = jobpositions.tobesaved + collected = jobpositions.collected + for tag, data in next, collected do + local prefix, rest = lpegmatch(splitter,tag) + if prefix == "p" then + nofregular = nofregular + 1 + elseif prefix == "page" then + nofregular = nofregular + 1 + pagedata[tonumber(rest) or 0] = data + elseif prefix == "free" then + nofspecial = nofspecial + 1 + local t = freedata[data.p or 0] + t[#t+1] = data + elseif prefix == "columnarea" then + columndata[data.p or 0][data.c or 0] = data + end + setmetatable(data,default) + end + -- + local pages = structures.pages.collected + if pages then + local last = nil + for p=1,#pages do + local region = "page:" .. p + local data = pagedata[p] + local free = freedata[p] + if free then + sort(free,function(a,b) return b.y < a.y end) -- order matters ! + end + if data then + last = data + last.free = free + elseif last then + local t = setmetatableindex({ free = free, p = p },last) + if not collected[region] then + collected[region] = t + else + -- something is wrong + end + pagedata[p] = t + end + end + end + jobpositions.pagedata = pagedata +end + +function jobpositions.used() + return next(collected) -- we can safe it +end + +function jobpositions.getfree(page) + return freedata[page] +end + +-- we can gain a little when we group positions but then we still have to +-- deal with regions and cells so we either end up with lots of extra small +-- tables pointing to them and/or assembling/disassembling so in the end +-- it makes no sense to do it (now) and still have such a mix +-- +-- proof of concept code removed ... see archive + +local function finalizer() + -- We make the (possible extensive) shape lists sparse working + -- from the end. We could also drop entries here that have l and + -- r the same which saves testing later on. + for k, v in next, tobesaved do + local s = v.s + if s then + for p, data in next, s do + local n = #data + if n > 1 then + local ph = data[1][2] + local pd = data[1][3] + local xl = data[1][4] + local xr = data[1][5] + for i=2,n do + local di = data[i] + local h = di[2] + local d = di[3] + local l = di[4] + local r = di[5] + if r == xr then + di[5] = nil + if l == xl then + di[4] = nil + if d == pd then + di[3] = nil + if h == ph then + di[2] = nil + else + ph = h + end + else + pd, ph = d, h + end + else + ph, pd, xl = h, d, l + end + else + ph, pd, xl, xr = h, d, l, r + end + end + end + end + end + end +end + +job.register('job.positions.collected', tobesaved, initializer, finalizer) + +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, gethpos, getvpos + +function jobpositions.registerhandlers(t) + getpos = t and t.getpos or function() return 0, 0 end + getrpos = t and t.getrpos or function() return 0, 0, 0 end + gethpos = t and t.gethpos or function() return 0 end + getvpos = t and t.getvpos or function() return 0 end +end + +function jobpositions.getpos () return getpos () end +function jobpositions.getrpos() return getrpos() end +function jobpositions.gethpos() return gethpos() end +function jobpositions.getvpos() return getvpos() end + +-------- jobpositions.getcolumn() return column end + +jobpositions.registerhandlers() + +local function setall(name,p,x,y,w,h,d,extra) + tobesaved[name] = { + p = p, + x = x ~= 0 and x or nil, + y = y ~= 0 and y or nil, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + e = extra ~= "" and extra or nil, + r = region, + c = column, + r2l = texgetinteger("inlinelefttoright") == 1 and true or nil, + } +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 + local x, y = getpos() + data.x = x ~= 0 and x or nil + data.y = y ~= 0 and y or nil + else + local x = gethpos() + data.x = x ~= 0 and x or nil + end + elseif data.y == true then + local y = getvpos() + data.y = y ~= 0 and y or nil + end + if data.p == true then + data.p = texgetcount("realpageno") -- we should use a variable set in otr + 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,value) -- ,key + -- officially there should have been a settobesaved + local data = enhance(value or {}) + if value then + container = tobesaved[name] + if not container then + tobesaved[name] = { + [index] = data + } + else + container[index] = data + end + else + tobesaved[name] = data + end +end + +local function setspec(specification) + local name = specification.name + local index = specification.index + local value = specification.value + local data = enhance(value or {}) + if value then + container = tobesaved[name] + if not container then + tobesaved[name] = { + [index] = data + } + else + container[index] = data + end + else + tobesaved[name] = data + end +end + +local function get(id,index) + if index then + local container = collected[id] + return container and container[index] + else + return collected[id] + end +end + +------------.setdim = setdim +jobpositions.setall = setall +jobpositions.set = set +jobpositions.setspec = setspec +jobpositions.get = get + +implement { + name = "dosaveposition", + public = true, + protected = true, + arguments = { "argument", "integerargument", "dimenargument", "dimenargument" }, + actions = setall, -- name p x y +} + +implement { + name = "dosavepositionwhd", + public = true, + protected = true, + arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument" }, + actions = setall, -- name p x y w h d +} + +implement { + name = "dosavepositionplus", + public = true, + protected = true, + arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "argument" }, + actions = setall, -- name p x y w h d extra +} + +-- 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) + +local function b_column(specification) + local tag = specification.tag + local x = gethpos() + tobesaved[tag] = { + r = true, + x = x ~= 0 and x or nil, + -- w = 0, + } + insert(columns,tag) + column = tag +end + +local function e_column() + local t = tobesaved[column] + if not t then + -- something's wrong + else + local x = gethpos() - t.x + t.w = x ~= 0 and x or nil + t.r = region + end + remove(columns) + column = columns[#columns] +end + +jobpositions.b_column = b_column +jobpositions.e_column = e_column + +implement { + name = "bposcolumn", + arguments = "string", + actions = function(tag) + insert(columns,tag) + column = tag + end +} + +implement { + name = "bposcolumnregistered", + arguments = "string", + actions = function(tag) + insert(columns,tag) + column = tag + ctx_latelua { action = b_column, tag = tag } + end +} + +implement { + name = "eposcolumn", + actions = function() + remove(columns) + column = columns[#columns] + end +} + +implement { + name = "eposcolumnregistered", + actions = function() + ctx_latelua { action = e_column } + remove(columns) + column = columns[#columns] + end +} + +-- regions + +local function b_region(specification) + local tag = specification.tag or specification + local last = tobesaved[tag] + local x, y = getpos() + last.x = x ~= 0 and x or nil + last.y = y ~= 0 and y or nil + last.p = texgetcount("realpageno") + insert(regions,tag) -- todo: fast stack + region = tag +end + +local function e_region(specification) + local last = tobesaved[region] + local y = getvpos() + local x, y = getpos() + if specification.correct then + local h = (last.y or 0) - y + last.h = h ~= 0 and h or nil + end + last.y = y ~= 0 and y or nil + remove(regions) -- todo: fast stack + region = regions[#regions] +end + +jobpositions.b_region = b_region +jobpositions.e_region = e_region + +local lastregion + +local function setregionbox(n,tag,k,lo,ro,to,bo,column) -- kind + if not tag or tag == "" then + nofregions = nofregions + 1 + tag = f_region(nofregions) + end + local box = getbox(n) + local w, h, d = getwhd(box) + tobesaved[tag] = { + -- p = texgetcount("realpageno"), -- we copy them + x = 0, + y = 0, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + k = k ~= 0 and k or nil, + lo = lo ~= 0 and lo or nil, + ro = ro ~= 0 and ro or nil, + to = to ~= 0 and to or nil, + bo = bo ~= 0 and bo or nil, + c = column or nil, + } + lastregion = tag + return tag, box +end + +local function markregionbox(n,tag,correct,...) -- correct needs checking + local tag, box = setregionbox(n,tag,...) + -- todo: check if tostring is needed with formatter + local push = new_latelua { action = b_region, tag = tag } + local pop = new_latelua { action = e_region, correct = correct } + -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end + local head = getlist(box) + -- no, this fails with \framed[region=...] .. needs thinking + -- if getid(box) ~= hlist_code then + -- -- report("mark region box assumes a hlist, fix this for %a",tag) + -- head = hpack(head) + -- end + 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 + +function jobpositions.gettobesaved(name,tag) + local t = tobesaved[name] + if t and tag then + return t[tag] + else + return t + end +end + +function jobpositions.settobesaved(name,tag,data) + local t = tobesaved[name] + if t and tag and data then + t[tag] = data + end +end + +local nofparagraphs = 0 + +implement { + name = "parpos", + actions = function() + nofparagraphs = nofparagraphs + 1 + texsetcount("global","c_anch_positions_paragraph",nofparagraphs) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local t = { + p = true, + c = true, + r = true, + x = true, + y = true, + h = h, + d = d, + hs = texget("hsize"), -- never 0 + } + local leftskip = texget("leftskip",false) + local rightskip = texget("rightskip",false) + 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 name = f_p_tag(nofparagraphs) + tobesaved[name] = t + ctx_latelua { action = enhance, specification = t } + end +} + +implement { + name = "dosetposition", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} + +implement { + name = "dosetpositionwhd", + arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, + public = true, + protected = true, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} + +implement { + name = "dosetpositionbox", + arguments = { "argument", "integerargument" }, + public = true, + protected = true, + actions = function(name,n) + local box = getbox(n) + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} + +implement { + name = "dosetpositionplus", + arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, + public = true, + protected = true, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + e = scanstring(), + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} + +implement { + name = "dosetpositionstrut", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} + +implement { + name = "dosetpositionstrutkind", + arguments = { "argument", "integerargument" }, + public = true, + protected = true, + actions = function(name,kind) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + k = kind, + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + 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 + +local function getpage(id) + local jpi = collected[id] + return jpi and jpi.p +end + +local function getcolumn(id) + local jpi = collected[id] + return jpi and jpi.c or false +end + +local function getparagraph(id) + local jpi = collected[id] + return jpi and jpi.n +end + +local function getregion(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 + +jobpositions.page = getpage +jobpositions.column = getcolumn +jobpositions.paragraph = getparagraph +jobpositions.region = getregion + +jobpositions.p = getpage -- not used, kind of obsolete +jobpositions.c = getcolumn -- idem +jobpositions.n = getparagraph -- idem +jobpositions.r = getregion -- idem + +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.whd(id) + local jpi = collected[id] + if jpi then + return jpi.h, jpi.h, jpi.d + end +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 + +local splitter = lpeg.splitat(",") + +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 + +local function columnofpos(realpage,xposition) + local p = columndata[realpage] + if p then + for i=1,#p do + local c = p[i] + local x = c.x or 0 + local w = c.w or 0 + if xposition >= x and xposition <= (x + w) then + return i + end + end + end + return 1 +end + +jobpositions.overlapping = overlapping +jobpositions.onsamepage = onsamepage +jobpositions.columnofpos = columnofpos + +-- interface + +implement { + name = "replacepospxywhd", + arguments = { "argument", "integerargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument", "dimenargument" }, + public = true, + protected = true, + actions = function(name,page,x,y,w,h,d) + collected[name] = { + p = page, + x = x, + y = y, + w = w, + h = h, + d = d, + } + end +} + +implement { + name = "copyposition", + arguments = "2 arguments", + public = true, + protected = true, + actions = function(target,source) + collected[target] = collected[source] + end +} + +implement { + name = "MPp", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local p = jpi.p + if p and p ~= true then + context(p) + return + end + end + context('0') + end +} + +implement { + name = "MPx", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 +} + +implement { + name = "MPy", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 +} + +implement { + name = "MPw", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local w = jpi.w + if w and w ~= 0 then + context("%.5Fpt",w*pt) + return + end + end + context('0pt') + end +} + +implement { + name = "MPh", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local h = jpi.h + if h and h ~= 0 then + context("%.5Fpt",h*pt) + return + end + end + context('0pt') + end +} + +implement { + name = "MPd", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local d = jpi.d + if d and d ~= 0 then + context("%.5Fpt",d*pt) + return + end + end + context('0pt') + end +} + +implement { + name = "MPxy", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + jpi.x*pt, + jpi.y*pt + ) + else + context('(0,0)') + end + end +} + +implement { + name = "MPwhd", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local w = jpi.w or 0 + local h = jpi.h or 0 + local d = jpi.d or 0 + if w ~= 0 or h ~= 0 or d ~= 0 then + context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt) + return + end + end + context('0pt,0pt,0pt') + end +} + +implement { + name = "MPll", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + jpi.x *pt, + (jpi.y-jpi.d)*pt + ) + else + context('(0,0)') -- for mp only + end + end +} + +implement { + name = "MPlr", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 +} + +implement { + name = "MPur", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 +} + +implement { + name = "MPul", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 + +implement { + name = "MPpos", + arguments = "argument", + public = true, + actions = MPpos +} + +implement { + name = "MPn", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local n = jpi.n + if n then + context(n) + return + end + end + context(0) + end +} + +implement { + name = "MPc", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local c = jpi.c + if c and c ~= true then + context(c) + return + end + end + context('0') -- okay ? + end +} + +implement { + name = "MPr", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + local r = jpi.r + if r and r ~= true then + context(r) + return + end + local p = jpi.p + if p and p ~= true then + context("page:" .. p) + end + end + end +} + +local function MPpardata(id) + local t = collected[id] + if not t then + local tag = f_p_tag(id) + 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 + +implement { + name = "MPpardata", + arguments = "argument", + public = true, + actions = MPpardata +} + +implement { + name = "MPposset", + arguments = "argument", + public = true, + actions = function(name) + local b = f_b_tag(name) + local e = f_e_tag(name) + local w = f_w_tag(name) + local p = f_p_tag(getparagraph(b)) + MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) + end +} + +implement { + name = "MPls", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + context("%.5Fpt",jpi.ls*pt) + else + context("0pt") + end + end +} + +implement { + name = "MPrs", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + if jpi then + context("%.5Fpt",jpi.rs*pt) + else + context("0pt") + end + end +} + +local splitter = lpeg.tsplitat(",") + +implement { + name = "MPplus", + arguments = { "argument", "integerargument", "argument" }, + public = true, + actions = function(name,n,default) + local jpi = collected[name] + 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 +} + +implement { + name = "MPrest", + arguments = { "argument", "argument" }, + public = true, + actions = function(name,default) + local jpi = collected[name] + context(jpi and jpi.e or default) + end +} + +implement { + name = "MPxywhd", + arguments = "argument", + public = true, + actions = function(name) + local jpi = collected[name] + 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 + +implement { + name = "doifelseposition", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + doifelse(collected[name]) + end +} + +implement { + name = "doifposition", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + doif(collected[name]) + end +} + +implement { + name = "doifelsepositiononpage", + arguments = { "string", "integerargument" }, + public = true, + protected = true, + actions = function(name,p) + local c = collected[name] + doifelse(c and c.p == p) + end +} + +implement { + name = "doifelseoverlapping", + arguments = { "argument", "argument" }, + public = true, + protected = true, + actions = function(one,two) + doifelse(overlapping(one,two)) + end +} + +implement { + name = "doifelsepositionsonsamepage", + arguments = "argument", -- string + public = true, + protected = true, + actions = function(list) + doifelse(onsamepage(list)) + end +} + +implement { + name = "doifelsepositionsonthispage", + arguments = "argument", -- string + public = true, + protected = true, + actions = function(list) + doifelse(onsamepage(list,tostring(texgetcount("realpageno")))) + end +} + +implement { + name = "doifelsepositionsused", + public = true, + protected = true, + actions = function() + doifelse(next(collected)) + end +} + +implement { + name = "markregionbox", + arguments = "integer", + actions = markregionbox +} + +implement { + name = "setregionbox", + arguments = "integer", + actions = setregionbox +} + +implement { + name = "markregionboxtagged", + arguments = { "integer", "string" }, + actions = markregionbox +} + +implement { + name = "markregionboxtaggedn", + arguments = { "integer", "string", "integer" }, + actions = function(box,tag,n) + markregionbox(box,tag,nil,nil,nil,nil,nil,nil,n) + end +} + +implement { + name = "setregionboxtagged", + arguments = { "integer", "string" }, + actions = setregionbox +} + +implement { + name = "markregionboxcorrected", + arguments = { "integer", "string", true }, + actions = markregionbox +} + +implement { + name = "markregionboxtaggedkind", + arguments = { "integer", "string", "integer", "dimen", "dimen", "dimen", "dimen" }, + actions = function(box,tag,n,d1,d2,d3,d4) + markregionbox(box,tag,nil,n,d1,d2,d3,d4) + end +} + +implement { + name = "reservedautoregiontag", + public = true, + actions = function() + nofregions = nofregions + 1 + context(f_region(nofregions)) + 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) + +statistics.register("positions", function() + local total = nofregular + nofspecial + if total > 0 then + return format("%s collected, %s regular, %s special",total,nofregular,nofspecial) + else + return nil + end +end) + +-- We support the low level positional commands too: + +local newsavepos = nodes.pool.savepos + +implement { name = "savepos", actions = function() context(newsavepos()) end } +implement { name = "lastxpos", actions = function() context(gethpos()) end } +implement { name = "lastypos", actions = function() context(getvpos()) end } diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl new file mode 100644 index 000000000..53544fedc --- /dev/null +++ b/tex/context/base/mkxl/anch-pos.mkxl @@ -0,0 +1,503 @@ +%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}{autosuffix} + +\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 + +% \dosaveposition #1#2#3#4 % defined at lua end +% \dosavepositionwhd #1#2#3#4#5#6#7 % defined at lua end +% \dosavepositionplus #1#2#3#4#5#6#7#8 % defined at lua end + +% \dosetposition #1 % defined at lua end +% \dosetpositionwhd #1#2#3#4 % defined at lua end +% \dosetpositionplus #1#2#3#4#5 % defined at lua end +% \dosetpositionbox #1#2 % defined at lua end +% \dosetpositionstrut #1 % defined at lua end +% \dosetpositionstrutkind #1#2 % defined at lua end + +\newbox\b_anch_position +\newif \ifpositioning % sort of public + +%D Sometimes we want to trick the position handler a bit: + +% \replacepospxywhd #1#2#3#4#5#6#7 % defined at lua end + +%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. + +% \MPp : defined at lua end +% \MPr : defined at lua end +% \MPc : defined at lua end +% \MPn : defined at lua end +% \MPx : defined at lua end +% \MPy : defined at lua end +% \MPw : defined at lua end +% \MPh : defined at lua end +% \MPd : defined at lua end +% \MPxy : defined at lua end +% \MPwhd : defined at lua end +% \MPll : defined at lua end +% \MPlr : defined at lua end +% \MPur : defined at lua end +% \MPul : defined at lua end +% \MPpos : defined at lua end +% \MPls : defined at lua end +% \MPrs : defined at lua end +% \MPpardata : defined at lua end +% \MPxywhd : defined at lua end +% \MPposset : defined at lua end + +\aliased\let\MPpage \MPp +\aliased\let\MPregion \MPr +\aliased\let\MPcolumn \MPc +\aliased\let\MPparagraph\MPn +\aliased\let\MPanchor \MPpos % overloaded locally when needed (todo: LMTX) + +\aliased\let\MPleftskip \MPls % compatible feature +\aliased\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. + +% \MPplus #1#2#3 % defined at lua end +% \MPrest #1 % defined at lua end + +\aliased\let\MPv \MPplus +\aliased\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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 % \hpack + {\edef\currentposition{#1}% + \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr + \anch_positions_trace_left + \dopositionaction\currentposition + \hss}} + +\permanent\protected\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 % \hpack + {\edef\currentposition{#1}% + \dosetpositionbox\currentposition\nextbox + \anch_positions_trace_left + \setbox\b_anch_position\box\nextbox + \dopositionaction\currentposition + \box\b_anch_position + \hss}} + +\permanent\protected\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 % \hpack + {\edef\currentposition{#1}% + \dosetpositionstrut\currentposition + \anch_positions_trace_left + \dopositionaction\currentposition + \strut + \hss}} + +\permanent\protected\def\setpositionstrutkind + {\iftrialtypesetting + \expandafter\anch_positions_set_strut_kind_nop + \else + \expandafter\anch_positions_set_strut_kind_yes + \fi} + +\def\anch_positions_set_strut_kind_yes#1#2% + {\anch_positions_initialize + \hbox to \zeropoint % \hpack + {\edef\currentposition{#1}% + \dosetpositionstrutkind\currentposition{#2}% + \anch_positions_trace_left + \dopositionaction\currentposition + \strut + \hss}} + +\def\anch_positions_set_strut_kind_nop#1#2% + {\strut} + +\permanent\protected\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 % \hpack + {\edef\currentposition{#1}% + \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr + \anch_positions_trace_right + \dopositionaction\currentposition + \hss}} + +\permanent\protected\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 % \hpack + {\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 { } + +\protected\def\anch_mark_column_box#1#2% box n + {\global\advance\c_anch_column\plusone + \clf_markregionboxtaggedn#1{columnarea:\the\c_anch_column}#2\relax} % extra height + +\protected\def\anch_mark_region_box + {\iftrialtypesetting + \expandafter\gobbleoneargument + \orelse\ifpositioning + \expandafter\anch_mark_region_box_indeed + \else + \expandafter\gobbleoneargument + \fi} + +\protected\def\anch_mark_region_box_indeed#1% + {\clf_markregionbox#1\relax} + +\protected\def\anch_mark_flow_box#1% will be extended / renamed + {\hpack\bgroup + \global\advance\c_anch_text\plusone + \clf_markregionboxtagged#1{textarea:\the\c_anch_text}% + \box#1% + \egroup} + +\protected\def\anch_mark_tagged_box#1#2% + {\clf_markregionboxtagged#1{#2}} + +\protected\def\anch_mark_flow_only#1% will be extended / renamed + {\global\advance\c_anch_text\plusone + \clf_markregionboxcorrected#1{textarea:\the\c_anch_text}} + +\protected\def\anch_make_page_box#1% maybe like text + {\clf_setregionboxtagged#1{page:\the\realpageno}} + +\protected\def\anch_mark_text_box#1% + {\clf_markregionboxtagged#1{text:\the\realpageno}} % needs an hbox + +\newcount\c_anch_free + +\protected\def\anch_mark_tagged_box_free#1#2#3#4#5#6% only needed when positions + {\ifpositioning + \global\advance\c_anch_free\plusone % could be done at the lua end + \clf_markregionboxtaggedkind + #1% + {free:\number\c_anch_free}% + #2\space % kind + #3\space % leftoffset + #4\space % rightoffset + #5\space % topoffset + #6\relax % bottomoffset + \fi} + +% \reservedautoregiontag % define at lua end + +%D We can copy a position with: +%D +%D \starttyping +%D \copyposition {to} {from} +%D \stoptyping +%D +%D Again, this is a global operation. + +% \copyposition #1#2 % defined at lua end + +%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 + +% \doifposition #1 % defined at lua end +% \doifelseposition #1#2 % defined at lua end +% \doifelsepositiononpage #1#2 % defined at lua end + +\aliased\let\doifpositionelse \doifelseposition +\aliased\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. + +\aliased\let\xypos\setpositiononly + +\permanent\protected\def\hpos #1{\dontleavehmode\setpositionbox{#1}\hbox} +\permanent\protected\def\vpos #1{\setpositionbox{#1}\vbox} +\permanent\protected\def\bpos #1{\dontleavehmode\setpositionstrut{b:#1}\ignorespaces} +\permanent\protected\def\epos #1{\removeunwantedspaces\setpositionstrut{e:#1}} +\permanent\protected\def\bposkind#1#2{\dontleavehmode\setpositionstrutkind{b:#1}{#2}\ignorespaces} % not public, used in backgrounds +\permanent\protected\def\eposkind#1#2{\removeunwantedspaces\setpositionstrutkind{e:#1}{#2}} % not public, used in backgrounds + +%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 + +\permanent\protected\def\tracepositions + {\the\t_anch_positions_tracers} + +\permanent\protected\def\enableparpositions % global + {\glet\registerparoptions\doregisterparoptions + \global\positioningtrue} + +\permanent\let\disableparpositions\relax + +\let\registerparoptions\relax + +\protected\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 + +\protected\def\anch_positions_trace#1#2#3% + {\smashedhbox + {#1{\infofont#2#3}% + \kern-\onepoint + \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}} + +\protected\def\anch_positions_trace_left_indeed + {\anch_positions_trace\llap\darkmagenta{\currentposition>}} + +\protected\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 boxes do +%D overlap: +%D +%D \starttyping +%D \doifoverlappingelse{point a}{point b} +%D {action when overlapping} +%D {action when not overlapping} +%D \stoptyping + +% \doifelseoverlapping #1#2#3#4 % defined at lua end + +\aliased\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 + +% \doifelsepositionsonsamepage #1 % defined at lua end +% \doifelsepositionsonthispage #1 % defined at lua end +% \doifelsepositionsused % defined at lua end + +\aliased\let\doifpositionsonsamepageelse\doifelsepositionsonsamepage +\aliased\let\doifpositionsonthispageelse\doifelsepositionsonthispage +\aliased\let\doifpositionsusedelse \doifelsepositionsused + +%D Moved here: + +\permanent\protected\def\savepos {\clf_savepos} +\permanent\protected\def\lastxpos{\numexpr\clf_lastxpos\relax} +\permanent\protected\def\lastypos{\numexpr\clf_lastypos\relax} + +\protect \endinput diff --git a/tex/context/base/mkxl/anch-snc.mkxl b/tex/context/base/mkxl/anch-snc.mkxl new file mode 100644 index 000000000..51fb02d7c --- /dev/null +++ b/tex/context/base/mkxl/anch-snc.mkxl @@ -0,0 +1,157 @@ +%D \module +%D [ file=anch-snc, +%D version=2003.12.01, % actually 1999 so real old +%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. + +%D The original is in the mkii file. It does more at the \TEX\ end and +%D has some more magic. If we really need that I'll add it. After all, +%D in mkiv we can do things different. + +%D TODO: bleed : + left , minus right oro check if it touches page ... autobleed + +\writestatus{loading}{ConTeXt Anchoring Macros / Synchronization} + +\registerctxluafile{anch-snc}{} + +\unprotect + +\ifx\??syncposcounter\undefined \installcorenamespace{syncposcounter} \fi +\ifx\s!syncpos \undefined \def\s!syncpos {syncpos} \fi + +\let\c_sync_n\relax + +\permanent\protected\def\definesyncpositions[#1]% + {\ifcsname\??syncposcounter:#1\endcsname \else + \expandafter\newcount\csname\??syncposcounter:#1\endcsname + \fi} + +\permanent\tolerant\protected\def\syncposition[#1]#*[#2]% we could actually use par positions + {\dontleavehmode + \ifcsname\??syncposcounter:#1\endcsname + \let\c_sync_n\lastnamedcs + \global\advance\c_sync_n\plusone + \enabletextarearegistration + \setpositionplus{\s!syncpos:#1:\the\c_sync_n}{#2}\hpack{\strut}% + \else + \strut + \fi + \ignorespaces} + +\protect + +\continueifinputfile{anch-snc.mkiv} + +\starttext + +% \setuppapersize[A4][A3] + +\setuplayout[location=middle] + +\setupbodyfont[dejavu] + +\definesyncpositions[1] +\definesyncpositions[2] + +% \enabletrackers[metapost.lua] + +\startMPdefinitions + input "mp-asnc.mpiv" ; + + SetSyncColor(1,0,"magenta") ; + SetSyncColor(1,1,"red") ; + SetSyncColor(1,2,"green") ; + SetSyncColor(1,3,"blue") ; + SetSyncColor(1,4,"yellow") ; + + SetSyncColor(2,0,"magenta") ; + SetSyncColor(2,1,"red") ; + SetSyncColor(2,2,"green") ; + SetSyncColor(2,3,"blue") ; + SetSyncColor(2,4,"yellow") ; +\stopMPdefinitions + +\startuseMPgraphic{sync1} + StartPage ; + StartSync(1) ; + SyncHOffset := 0 ; + SyncWidth := BackSpace - LeftMarginDistance; + CollectSyncDataPage ; + % ExtendSyncPaths ; % to top of text area + PruneSyncPaths ; % clip top / bottom + CollapseSyncPaths ; + MakeSyncPaths ; + % DrawSyncPaths ; + FillSyncPaths ; + StopSync ; + clip currentpicture to Page ; + setbounds currentpicture to Page ; + StopPage ; +\stopuseMPgraphic + +\startuseMPgraphic{sync2} + StartSync(2) ; + SyncHOffset := -1cm ; + SyncWidth := 1cm ; + CollectSyncDataRegion(OverlayRegion) ; + ExtendSyncPaths ; % to top of text area + MakeSyncPaths ; + FillSyncPaths ; + StopSync ; + clip currentpicture to OverlayBox leftenlarged 1cm; + setbounds currentpicture to OverlayBox ; +\stopuseMPgraphic + +\defineoverlay[tempoverlay1][\useMPgraphic{sync1}] +\defineoverlay[tempoverlay2][\useMPgraphic{sync2}] + +\setupbackgrounds[page][background=tempoverlay1] + +\framed[region=yes,background=tempoverlay2,width=14cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} + + +\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=16cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} + +\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=10cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} + + +\dorecurse {100} { +% \dorecurse {1} { + \startchapter[title={Test #1}] + \syncposition[1][1,reset]\dorecurse{20}{\samplefile{ward}\endgraf} + \syncposition[1][2]\dorecurse {4}{\samplefile{ward}\endgraf} + \syncposition[1][3]\dorecurse {7}{\samplefile{ward}\endgraf} + \syncposition[1][4]\dorecurse {3}{\samplefile{ward}\endgraf} + \stopchapter +} + +\dorecurse {100} { +% \dorecurse {1} { + \startchapter[title={Test #1}] + \syncposition[1][1]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][2]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][3]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][4]\dorecurse{1}{\samplefile{ward}\endgraf} + \stopchapter +} + +\stoptext diff --git a/tex/context/base/mkxl/anch-tab.mkxl b/tex/context/base/mkxl/anch-tab.mkxl new file mode 100644 index 000000000..8f4bb0b5b --- /dev/null +++ b/tex/context/base/mkxl/anch-tab.mkxl @@ -0,0 +1,382 @@ +%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 dissappear in +%D favour of better solutions. Anyway, it now has been aroudn too long to bother. + +\unprotect + +\newcount\c_anch_tabs + +\protected\def\tabl_tabulate_hook_b + {\iftrialtypesetting\else + \ifpositioning + \ifconditional\tablehaspositions + \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 + \fi} + +\protected\def\tabl_tabulate_hook_e + {\iftrialtypesetting\else + \ifpositioning + \ifconditional\tablehaspositions + \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 + \fi} + +\protected\def\tabl_tabulate_hook_b_first{\clf_bposcolumnregistered{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}} +\protected\def\tabl_tabulate_hook_b_next {\clf_bposcolumn{tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column}} +\protected\def\tabl_tabulate_hook_e_first{\clf_eposcolumnregistered} +\protected\def\tabl_tabulate_hook_e_next {\clf_eposcolumn} + +% \appendtoks \registerparoptions \to \everypar + +\appendtoks + \global\advance\c_anch_tabs\plusone +\to \everytabulate + +% for text backgrounds + +\appendtoks + \settrue\c_anch_backgrounds_pos_no_shape +\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 + +\protected\def\anch_tabulate_bpos{\bpos} +\protected\def\anch_tabulate_epos{\epos} + +\installcorenamespace{positiontables} + +\permanent\def\tbPOSprefix{\??positiontables\number\noftabpositions:} + +\protected\def\tablepos + {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}} + +\permanent\protected\def\tbXC {\anch_table_checked\anch_tables_indeed_XC } +\permanent\protected\def\tbGSC{\anch_table_checked\anch_tables_indeed_GSC} +\permanent\protected\def\tbGFC{\anch_table_checked\anch_tables_indeed_GFC} +\permanent\protected\def\tbGTC{\anch_table_checked\anch_tables_indeed_GTC} + +\tolerant\def\anch_table_checked#1[#2]% + {\iftrialtypesetting + \global\settrue\tablehaspositions + \expandafter\anch_tables_indeed_NC + \orelse\ifparameter#2\or + \expandafter#1% + \else + \expandafter\anch_tables_indeed_NC + \fi[#2]} + +\def\anch_tables_indeed_NC[#1]% + {\NC} + +\def\anch_tables_indeed_XC[#1]% + {{\enforced\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]\orelse + \if#1+\anch_tables_indeed_GFC[#2:#2]\orelse + \if#1<\anch_tables_indeed_GTC[#2:#2]\orelse + \if#1-\anch_tables_indeed_GTC[#2:#2]\orelse + \if#1=\anch_tables_indeed_GSC[#2:#2]\orelse + \anch_tables_indeed_GSC[#1#2:#1#2]\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} + {\gtoksapp\posXCtoks{\anch_tables_process_GSC[#1:#2]}\NC} + +\def\anch_tables_process_GSC[#1:#2]% + {\remappositionframed{#2}{\tbPOSprefix#1}% + \anch_tabulate_bpos{\tbPOSprefix#1}% + \doglobal\appendtoks\expandafter\anch_tabulate_epos\expandafter{\tbPOSprefix#1}\to\posXCtoks} +% \xtoksapp\posXCtoks{\anch_tabulate_epos{\tbPOSprefix#1}}} + +\def\anch_tables_indeed_GFC[#1]% + {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC} +% {\gtoksapp\posXCtoks{\anch_tables_delayed_GFC[#1]}\NC} + +\def\anch_tables_delayed_GFC[#1]% + {\processcommalist[#1]\anch_tables_step_GFC} + +\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} +% {\gtoksapp\posXCtoks{\anch_tables_delayed_GTC[#1]}\NC} + +\def\anch_tables_delayed_GTC[#1]% + {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks} +% {\gtoksapp\posXCtoks{\anch_tables_process_GTC[#1]}\NC} + +\def\anch_tables_process_GTC[#1]% + {\processcommalist[#1]\anch_tables_step_GTC} + +\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 minimalistic. + +\aliased\let\tabulatepos\tablepos + +\def\tabulatenormalpos + {\iftrialtypesetting + % nothing + \orelse\ifconditional\tablehaspositions + \hss\tabulatepos\hss + \else + % nothing + \fi} + +\def\tabulateequalpos + {\iftrialtypesetting + \tabulateEQ + \orelse\ifconditional\tablehaspositions + \tabulateEQpos + \else + \tabulateEQ + \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 + +\protected\def\anch_tabulate_bpos_indeed + {\bpos} + +\protected\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} + +\permanent\def\flushtabulatesplitbox + {\box\b_tabl_tabulate + \iftrialtypesetting\orelse\ifconditional\tablehaspositions\anch_tabulate_flush_epos\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 + \enforced\let\GSC\tbGSC + \enforced\let\GFC\tbGFC + \enforced\let\GTC\tbGTC + \enforced\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: + +\permanent\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&} % | +\permanent\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \| +\permanent\def\normalTABLEquote {\unskip\!ttRightGlue&\omit\tablepos&} % " + +\appendtoks + \global\advance\noftabpositions\plusone + \global\setfalse\tablehaspositions +\to \everytable + +%D Since we don't want nameclashes: + +\appendtoks + \enforced\let\GSC\tbGSC + \enforced\let\GFC\tbGFC + \enforced\let\GTC\tbGTC + \enforced\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] + +\permanent\protected\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}}} + +\permanent\tolerant\protected\def\definepositionframed[#1]#*[#2]% + {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}} + +\protected\def\anch_framed_handle + {\bgroup + \anch_framed_indeed} + +\permanent\tolerant\protected\def\positionframed[#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/tex/context/base/mkxl/attr-col.mkxl b/tex/context/base/mkxl/attr-col.mkxl new file mode 100644 index 000000000..c75f448e9 --- /dev/null +++ b/tex/context/base/mkxl/attr-col.mkxl @@ -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}{} + +\unprotect + +% We implement this elsewhere but some code might end up here. + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-eff.mkxl b/tex/context/base/mkxl/attr-eff.mkxl new file mode 100644 index 000000000..04a0c55ce --- /dev/null +++ b/tex/context/base/mkxl/attr-eff.mkxl @@ -0,0 +1,60 @@ +%D \module +%D [ file=attr-eff, +%D version=2007.06.06, +%D title=\CONTEXT\ Attribute Macros, +%D subtitle=Effects, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Attribute Macros / Effects} + +\registerctxluafile{attr-eff}{} + +\unprotect + +\installcorenamespace{effect} + +\installcommandhandler \??effect {effect} \??effect + +\setupeffect + [\c!method=\v!none, + \c!stretch=\zerocount, + \c!rulethickness=\zeropoint, + \c!alternative=\v!normal] + +\appendtoks + \edef\p_method{\effectparameter\c!method}% + \ifx\p_method\v!command + \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}% + \setuxvalue{\e!stop \currenteffect}{\stopeffect}% + \fi +\to \everydefineeffect + +\permanent\protected\def\starteffect[#1]% + {\clf_seteffect + alternative {\namedeffectparameter{#1}\c!alternative} + stretch \numexpr\namedeffectparameter{#1}\c!stretch\relax + rulethickness \dimexpr\namedeffectparameter{#1}\c!rulethickness\relax + \relax} + +\permanent\protected\def\stopeffect % can be special + {\clf_reseteffect} % v!normal 0 0 + +\permanent\protected\def\effect[#1]% + {\groupedcommand{\starteffect[#1]}{\stopeffect}} + +% yes or no grouped + +\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt] +\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt] +\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt] +\defineeffect [\v!normal] [\c!alternative=\v!normal] +\defineeffect [\v!hidden] [\c!alternative=\v!hidden] +\defineeffect [\v!stretch] [\c!alternative=\v!stretch,\c!stretch=1] + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-ini.mkxl b/tex/context/base/mkxl/attr-ini.mkxl new file mode 100644 index 000000000..de22cd6e2 --- /dev/null +++ b/tex/context/base/mkxl/attr-ini.mkxl @@ -0,0 +1,143 @@ +%D \module +%D [ file=attr-ini, +%D version=2007.06.06, +%D title=\CONTEXT\ Attribute Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Attribute Macros / Initialization} + +%D Although it's still somewhat experimental, here we introduce code +%D related to attributes. Housekeeping will move completely to \LUA\ +%D and \type {\newattribute} will go away. + +\unprotect + +\registerctxluafile{attr-ini}{} + +\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd) +\installcorenamespace{attributeid} % the internal number +\installcorenamespace{attributestack} % the attribute specific stack +\installcorenamespace{attributepickup} + +\permanent\protected\def\pushattribute#1% + {\global\advance\csname\??attributestack\string#1\endcsname\plusone + \gdefcsname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}} + +\permanent\protected\def\popattribute#1% + {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax + \global\advance\csname\??attributestack\string#1\endcsname\minusone} + +\permanent\protected\def\installattributestack#1% + {\ifcsname\??attributestack\string#1\endcsname \else + \expandafter\newcount\csname\??attributestack\string#1\endcsname + \fi} + +\newtoks \t_attr_list_global +\newtoks \t_attr_list_local +\newtoks \t_attr_list_pickup +\newtoks \t_attr_list_nomath + +\ifdefined \s!global \else \immutable\def\s!global {global} \fi % for metatex % or hard check later +\ifdefined \s!public \else \immutable\def\s!public {public} \fi % for metatex % or hard check later +\ifdefined \s!private \else \immutable\def\s!private {private} \fi % for metatex % or hard check later +\ifdefined \s!attribute \else \immutable\def\s!attribute{attribute} \fi % for metatex % or hard check later +\ifdefined \s!pickup \else \immutable\def\s!pickup {pickup} \fi % for metatex % or hard check later +\ifdefined \s!forget \else \immutable\def\s!forget {forget} \fi % for metatex % or hard check later + +\immutable\def\??attributeprefix{c_attr_} + +\permanent\protected\def\defineattribute {\attr_basics_define_indeed[\s!public ]} +\permanent\protected\def\definesystemattribute{\attr_basics_define_indeed[\s!private]} + +\tolerant\def\attr_basics_define_indeed[#1]#*[#2]#*[#3]% + {\ifcsname\??attributeprefix#2\endcsname\else + \scratchcounter\clf_defineattribute{#2}{#1}\relax + %\writestatus\m!system{defining #1 attribute #2 with number \number\scratchcounter}% + \global\permanent\expandafter\attributedef\csname\??attributeprefix#2\endcsname\scratchcounter % \foo = 123 + \global\permanent\expandafter\integerdef \csname\??attributeid #2\endcsname\scratchcounter % \attribute\foo = 123 + % some attributes are always global + \doifelseinset\s!global{#3}% + {\xtoksapp\t_attr_list_global{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% \c_attr_foo + {\xtoksapp\t_attr_list_local {\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% + \doifinset\s!nomath{#3}% + {\xtoksapp\t_attr_list_nomath{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% + \doifinset\s!public{#3}% + {\aliased\gletcsname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}% \attribute\fooattribute + \doifinset\s!pickup{#3}% + {\global\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue + \xtoksapp\t_attr_list_pickup{\csname\??attributeprefix#2\endcsname\csname\??attributepickup#2\endcsname}% + \ifcsname#2\s!attribute\endcsname + \xdefcsname\s!pickup#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\csname\??attributeprefix#2\endcsname}% + \xdefcsname\s!forget#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue}% + \fi}% + \fi} + +\permanent\protected\def\pickupattributes + {\the\t_attr_list_pickup\relax} + +\permanent\protected\def\newattribute#1% + {\attr_basics_define_indeed\s!public[\csstring#1][]% + \expandafter\glet\expandafter#1\csname\??attributeid\csstring#1\endcsname} + +% expandable so we can \edef them for speed + +\permanent\def\dosetattribute#1#2{\csname\??attributeprefix#1\endcsname#2\relax} +\permanent\def\doresetattribute#1{\csname\??attributeprefix#1\endcsname\attributeunsetvalue} +\permanent\def\dogetattribute #1{\number\csname\??attributeprefix#1\endcsname} +\permanent\def\dogetattributeid#1{\number\csname\??attributeid #1\endcsname} + +\aliased\let\dompattribute\gobbletwoarguments + +\permanent\protected\def\resetglobalattributes{\the\t_attr_list_global\glyphdatafield\zerocount\glyphscriptfield\zerocount} +\permanent\protected\def\resetlocalattributes {\the\t_attr_list_local \glyphdatafield\zerocount\glyphscriptfield\zerocount} + +\aliased\let\resetallattributes\resetlocalattributes + +%D Rather special. + +\permanent\protected\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}} +\permanent\protected\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}} + +%D For the moment we put this here. The order of definition matters a bit because +%D performance is better when we put frequently accessed attributes at the front. +%D So, we might move more here. + +%definesystemattribute [state] % nomath +\definesystemattribute [color] [public] % global +\definesystemattribute [colormodel] [public,global] +%definesystemattribute [skip] +%definesystemattribute [penalty] +\definesystemattribute [transparency] [public] +\definesystemattribute [reference] [public] +\definesystemattribute [destination] [public] +\definesystemattribute [case] [public] +\definesystemattribute [visual] [public,global] +\definesystemattribute [viewerlayer] [public] +\definesystemattribute [background] [public] +\definesystemattribute [alignbackground] [public] +\definesystemattribute [colorintent] [public] +\definesystemattribute [negative] [public] +\definesystemattribute [effect] [public] +\definesystemattribute [layoutcomponent] [public] +\definesystemattribute [internal] [public] +\definesystemattribute [ruled] [public] +\definesystemattribute [shifted] [public] +\definesystemattribute [checkedbreak] [public] +\definesystemattribute [vboxtohboxseparator] [public] + +\permanent\protected\let\showattributes\clf_showattributes % maybe at lua end + +%D Todo: + +% \appendtoks +% \clf_cleanupattributes +% \to \everyafterpagebreak + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-lay.lmt b/tex/context/base/mkxl/attr-lay.lmt new file mode 100644 index 000000000..d0febb9ee --- /dev/null +++ b/tex/context/base/mkxl/attr-lay.lmt @@ -0,0 +1,311 @@ +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 enableaction = nodes.tasks.enableaction +local disableaction = nodes.tasks.disableaction +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 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 + disableaction("shipouts","attributes.viewerlayers.handler") + end + enabled = false + else + if not enabled then + 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 + -- or macro + 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", + public = true, + protected = true, + actions = viewerlayers.start, + arguments = "optional", +} + +implement { + name = "stopviewerlayer", + public = true, + protected = true, + actions = viewerlayers.stop +} + +implement { + name = "registeredviewerlayer", + actions = { register, context }, + arguments = { "string", true } -- true forces a use +} diff --git a/tex/context/base/mkxl/attr-lay.mkxl b/tex/context/base/mkxl/attr-lay.mkxl new file mode 100644 index 000000000..6cb1387ca --- /dev/null +++ b/tex/context/base/mkxl/attr-lay.mkxl @@ -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}{autosuffix} + +% 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 + {\frozen\instance\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}% + \frozen\instance\setuxvalue{\e!stop #1}{\stopviewerlayer}}% +\to \everydefineviewerlayer + +% \startviewerlayer[#1] % defined at lua end +% \stopviewerlayer % defined at lua end + +\permanent\protected\def\viewerlayer[#1]% + {\groupedcommand{\startviewerlayer[#1]}{\stopviewerlayer}} + +% 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} + +\permanent\def\attr_layoutcomponent_initialize#1% + {\edef\layoutcomponentboxattribute{\clf_definedlayoutcomponent{#1}}% + \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}% + \gletcsname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute} + +\permanent\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} + +\permanent\def\attr_layoutcomponent_reset + {\let\layoutcomponentboxattribute\empty} + +\permanent\let\setlayoutcomponentattribute \gobbleoneargument +\permanent\let\resetlayoutcomponentattribute\relax + \let\layoutcomponentboxattribute \empty + +\permanent\protected\def\showlayoutcomponents + {\enforced\let\setlayoutcomponentattribute \attr_layoutcomponent_set + \enforced\let\resetlayoutcomponentattribute\attr_layoutcomponent_reset} + +\protected\def\attr_layoutcomponent_cleanup + {\clf_cleanuplayers} + +\appendtoks + \attr_layoutcomponent_cleanup +\to \everyshipout + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-mkr.mkxl b/tex/context/base/mkxl/attr-mkr.mkxl new file mode 100644 index 000000000..2209af241 --- /dev/null +++ b/tex/context/base/mkxl/attr-mkr.mkxl @@ -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}{} + +\permanent \protected\def\definemarker [#1]{\defineattribute[\s!marker:#1]} +\permanent\tolerant\protected\def\setmarker [#1]#*[#2]{\dosetattribute{\s!marker:#1}{#2}} +\permanent \protected\def\resetmarker [#1]{\dogetattribute{\s!marker:#1}} +\permanent \def\boxmarker #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax} + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-neg.mkxl b/tex/context/base/mkxl/attr-neg.mkxl new file mode 100644 index 000000000..c849e6bf6 --- /dev/null +++ b/tex/context/base/mkxl/attr-neg.mkxl @@ -0,0 +1,28 @@ +%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}{} + +\unprotect + +% positive and negative are preregistered + +\permanent\protected\def\startnegative{\clf_setnegative{\v!negative}} +\permanent\protected\def\stopnegative {\clf_setnegative{\v!positive}} + +\permanent\protected\def\startpositive{\clf_setnegative{\v!positive}} +\permanent\protected\def\stoppositive {\clf_setnegative{\v!negative}} + +\protect \endinput diff --git a/tex/context/base/mkxl/back-exp.mkxl b/tex/context/base/mkxl/back-exp.mkxl new file mode 100644 index 000000000..f248ca214 --- /dev/null +++ b/tex/context/base/mkxl/back-exp.mkxl @@ -0,0 +1,356 @@ +%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}{} + +%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 because otherwise rendering information would get lost. In +%D general we assume that when the \XML\ is converted to \HTML\ some stylesheet +%D is applied anyway. + +\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] + +\permanent\tolerant\protected\def\setelementexporttag[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \clf_settagproperty{#1}{export}{#2}% + \or + \clf_settagproperty{#1}{#2}{#3}% + \fi} + +% todo: no need for calls when trialtypesetting + +\permanent\def\taggedctxcommand + {\iftrialtypesetting + \expandafter\gobbleoneargument + \else + \expandafter\ctxcommand + \fi} + +\newcount\tagparcounter + +\aliased\let\dotagsetparcounter\relax +\aliased\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 + \enforced\permanent\protected\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) + \enforced\permanent\protected\def\dotagTABLEsignal + {\signalcharacter}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagtabulatecell + {\iftrialtypesetting\else + \clf_settagtabulatecell\c_tabl_tabulate_align\c_tabl_tabulate_kind + \fi}% + \enforced\permanent\protected\def\dotagtabulatesignal + {\dontleavehmode\signalcharacter\ignorespaces}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsynonym + {\iftrialtypesetting\else\clf_settagsynonym{\currentsynonymtag}\fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsorting + {\iftrialtypesetting\else\clf_settagsorting{\currentsortingtag}\fi}% +\to \everyenableelements + +\appendtoks % frozen and assumed global per highlight class + \enforced\permanent\protected\def\dotagconstruct + {\iftrialtypesetting\else + \clf_settagconstruct + {\currentstartstop}% + {\startstopparameter\c!style}% + \c_attr_color + \ifvmode\plusone\else\zerocount\fi + \relax + \fi}% +\to \everyenableelements + +\appendtoks % frozen and assumed global per highlight class + \enforced\permanent\protected\def\dotaghighlight + {\iftrialtypesetting\else + \clf_settaghighlight + {\currenthighlight}% + {\highlightparameter\c!style} + \c_attr_color + \ifvmode\plusone\else\zerocount\fi + \relax + \fi}% +\to \everyenableelements + +\appendtoks % we can have differently scaled images + \enforced\permanent\protected\def\dotagfigure + {\iftrialtypesetting\else + \clf_settagfigure + {\figurefileoriginal}% + {\figurefullname}% + {\figurefilepage}% + \dimexpr\figurewidth\relax + \dimexpr\figureheight\relax + {\figurelabel}% + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagcombination + {\iftrialtypesetting\else + \clf_settagcombination + \numexpr\combinationparameter\c!nx\relax + \numexpr\combinationparameter\c!ny\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetparcounter + {\global\advance\tagparcounter\plusone\c_attr_taggedpar\tagparcounter}% + \enforced\permanent\protected\def\doresetparcounter + {\c_attr_taggedpar\attributeunsetvalue}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetitemgroup + {\iftrialtypesetting\else + \clf_settagitemgroup + \ifconditional\c_strc_itemgroups_pack true\else false\fi\space + \numexpr\currentitemlevel\relax + {\currentitemgroupsymbol}% + \fi}% + \enforced\permanent\protected\def\dotagsetitem#1% + {\iftrialtypesetting\else + \clf_settagitem{#1}% + \fi}% +\to \everyenableelements + +% \appendtoks +% \enforced\permanent\protected\def\dotagsetdescription +% {\iftrialtypesetting\else +% \clf_settagdescription{\currentdescription}\currentdescriptionnumberentry\relax +% \fi}% +% \to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetnotation + {\iftrialtypesetting\else + \clf_settagnotation{\currentnote}\currentnotenumber\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetnotesymbol + {\iftrialtypesetting\else + \clf_settagnotationsymbol{\currentnote}\currentnotenumber\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagregisterlocation + {\iftrialtypesetting\else + \clf_settagregister{\currentregister}\currentregisternumber\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotaglistlocation + {\iftrialtypesetting\else + \clf_settaglist\currentlistindex\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetdelimitedsymbol#1% + {\iftrialtypesetting\else + \clf_settagdelimitedsymbol{#1}\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagsetsubsentencesymbol#1% + {\iftrialtypesetting\else + \clf_settagsubsentencesymbol{#1}\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagregisterfloat#1#2% + {\iftrialtypesetting\else + \clf_settagfloat{#1}{#2}\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\let\specialfixedspace \explicitfixedspace + \enforced\let\specialobeyedspace \explicitobeyedspace + \enforced\let\specialstretchedspace\explicitstretchedspace + \enforced\let\specialcontrolspace \explicitcontrolspace +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagregisterformula#1% + {\iftrialtypesetting\else + \clf_settagformulacontent#1\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagmarginanchor#1% + {\iftrialtypesetting\else\clf_settagmarginanchor#1\relax\fi}% + \enforced\permanent\protected\def\dotagmargintext#1% + {\iftrialtypesetting\else\clf_settagmargintext#1\relax\fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagpublication#1#2% + {\iftrialtypesetting\else + \clf_settagpublication{#1}{#2}\relax + \fi}% +\to \everyenableelements + +\appendtoks + \enforced\permanent\protected\def\dotagparagraph#1% + {\iftrialtypesetting\else + \clf_settagparagraph{#1}\relax + \fi}% +\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!properties=\v!no, % no: ignore, yes: as attribute, otherwise: use as prefix + \c!hyphen=\v!no, + \c!svgstyle=, + \c!cssfile=, + \c!file=] + +\resetsystemmode\v!export + +\permanent\protected\def\doinitializeexport + {\edef\p_export{\backendparameter\c!export}% + \ifx\p_export\empty \else + % yes | xml + \setuptagging[\c!state=\v!start]% + \clf_initializeexport + \setsystemmode\v!export + \exportingtrue + \writestatus\m!backend\empty % so messages will stand out a bit + \the\everyinitializeexport + \writestatus\m!backend\empty % so messages will stand out a bit + \enforced\glet\doinitializeexport\relax + \fi} + +\permanent\protected\def\dostartexport + {%\glet\dostartexport\relax + \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}% + file {\exportparameter\c!file}% + export {\backendparameter\c!export}% + \relax} + +\permanent\protected\def\dostopexport + {\enforced\glet\dostopexport\relax + \clf_finishexport} + +\appendtoks + \doinitializeexport +\to \everysetupbackend + +\appendtoks + \ifexporting + \dostartexport + \fi +\to \everystarttext + +% better (before pdf gets closed, so we can embed), but it needs testing: + +\appendtoks + \ifexporting + \dostopexport + \fi +\to \everystoptext + +\appendtoks + \ifexporting + \dostartexport % in case it is done inside \starttext + \fi +\to \everystartdocument + +\protect \endinput diff --git a/tex/context/base/mkxl/back-ini.mkxl b/tex/context/base/mkxl/back-ini.mkxl new file mode 100644 index 000000000..00bfeb188 --- /dev/null +++ b/tex/context/base/mkxl/back-ini.mkxl @@ -0,0 +1,80 @@ +%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. + +\writestatus{loading}{ConTeXt Backend Macros / Initialization} + +\registerctxluafile{back-ini}{} + +\unprotect + +%D Right from the start \CONTEXT\ had a backend system based on runtime pluggable +%D code. As most backend issues involved specials and since postprocessors had not +%D that much in common, we ended up with a system where we could switch backend as +%D well as output code for multiple backends at the same time. +%D +%D Because \LUATEX\ has the backend built in, and since some backend issues have +%D been moved to the frontend I decided to provide new backend code for \MKIV, +%D starting with what was actually used. +%D +%D At this moment \DVI\ is no longer used for advanced document output and we +%D therefore dropped support for this format. Future versions might support more +%D backends again, but this has a low priority. + +%D The exact page model depends on the backend so we just define some variables that +%D are used. A helper at the \LUA\ end will synchronize with the internal variables. +%D We store these in the format. + +\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi +\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi +\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi + +\installcorenamespace{backend} + +\installsetuponlycommandhandler \??backend {backend} + +%D \starttyping +%D \setupbackend[space=yes] +%D \stoptyping + +\appendtoks + \clf_setrealspaces{\backendparameter\c!space}% +\to \everysetupbackend + +\appendtoks + \ifdefined\clf_resetmapfile + \clf_resetmapfile + \fi +\to \everysetupbackend + +%D For the moment this is an experiment (defauls is pdf, but we also +%D have lua, json and mps). +%D +%D \starttyping +%D % \setupoutput[lua] +%D % \setupoutput[json] +%D % \setupoutput[mps] +%D % \setupoutput[none] % for testing only +%D % \setupoutput[empty] % for testing only +%D +%D \starttext +%D \dorecurse{1000}{ +%D {\tf \red \samplefile{tufte}} \par +%D {\bf \green \samplefile {ward}} \par +%D {\sl \blue \samplefile{davis}} \par +%D } +%D \stoptext +%D \stoptyping + +\permanent\protected\def\setupoutput[#1]{\clf_enabledriver{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/back-lua.lmt b/tex/context/base/mkxl/back-lua.lmt new file mode 100644 index 000000000..dc836f12b --- /dev/null +++ b/tex/context/base/mkxl/back-lua.lmt @@ -0,0 +1,366 @@ +if not modules then modules = { } end modules ['back-lua'] = { + version = 1.001, + optimize = true, + 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" +} + +-- we can remap fonts + +local fontproperties = fonts.hashes.properties +local fontparameters = fonts.hashes.parameters +local fontshapes = fonts.hashes.shapes + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local bpfactor = number.dimenfactors.bp +local texgetbox = tex.getbox + +local rulecodes = nodes.rulecodes +local normalrule_code = rulecodes.normal +----- boxrule_code = rulecodes.box +----- imagerule_code = rulecodes.image +----- emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +local outlinerule_code = rulecodes.outline + +-- todo : per instance + +local pages = { } +local fonts = { } +local names = { } +local mapping = { } +local used = { } +local shapes = { } +local glyphs = { } +local buffer = { } +local b = 0 +local converter = nil + +local compact = false -- true +local shapestoo = true + +local x, y, d, f, c, w, h, t, r, o + +local function reset() + buffer = { } + b = 0 + t = nil + x = nil + y = nil + d = nil + f = nil + c = nil + w = nil + h = nil + r = nil + o = nil +end + +local function result() + -- todo: we're now still in the pdf backend but need different codeinjections + local codeinjections = backends.pdf.codeinjections + local getvariable = codeinjections.getidentityvariable or function() end + local jobname = environment.jobname or tex.jobname or "unknown" + return { + metadata = { + unit = "bp", + jobname = jobname, + title = getvariable("title") or jobname, + subject = getvariable("subject"), + author = getvariable("author"), + keywords = getvariable("keywords"), + time = os.date("%Y-%m-%d %H:%M"), + engine = environment.luatexengine .. " " .. environment.luatexversion, + context = environment.version, + }, + fonts = fonts, + pages = pages, + shapes = shapes, + } +end + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.lua" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + io.savedata(filename,table.serialize(data)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +local function initialize(driver,details) + reset() +end + +local function finalize(driver,details) + local n = details.pagenumber + local b = details.boundingbox + pages[n] = { + number = n, + content = buffer, + boundingbox = { + b[1] * bpfactor, + b[2] * bpfactor, + b[3] * bpfactor, + b[4] * bpfactor, + }, + } +end + +local function wrapup(driver) +end + +local function cleanup(driver) + reset() +end + +local function convert(driver,boxnumber,pagenumber) + converter(driver,texgetbox(boxnumber),"page",pagenumber) +end + +-- flushers + +local function updatefontstate(id) + if not mapping[id] then + local fn = #fonts + 1 + mapping[id] = fn + local properties = fontproperties[id] + local parameters = fontparameters[id] + local filename = file.basename(properties.filename) + local fontname = properties.fullname or properties.fontname + if shapestoo then + if not names[fontname] then + local sn = #shapes+1 + names[fontname] = sn + shapes[sn] = { } + glyphs[sn] = fontshapes[id].glyphs + end + end + fonts[fn] = { + filename = filename, + name = fontname, + size = parameters.size * bpfactor, + shapes = shapestoo and names[fontname] or nil, + } + end +end + +local function flushcharacter(current, pos_h, pos_v, pos_r, font, char) + local fnt = mapping[font] + b = b + 1 + buffer[b] = { + t = "glyph" ~= t and "glyph" or nil, + f = font ~= f and fnt or nil, + c = char ~= c and char or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "glyph" + f = font + c = char + x = pos_h + y = pos_v + d = pos_r + if shapestoo then + -- can be sped up if needed + local sn = fonts[fnt].shapes + local shp = shapes[sn] + if not shp[char] then + shp[char] = glyphs[sn][char] + end + end +end + +local function rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) + b = b + 1 + buffer[b] = { + t = "rule" ~= t and "rule" or nil, + r = rule_s ~= r and rule_s or nil, + o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil, + w = size_h ~= w and (size_h * bpfactor) or nil, + h = size_v ~= h and (size_v * bpfactor) or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "rule" + w = size_h + h = size_v + x = pos_h + y = pos_v + d = pos_r +end + +local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype) + local rule_s, rule_o + if subtype == normalrule_code then + rule_s = "normal" + elseif subtype == outlinerule_code then + rule_s = "outline" + rule_o = getdata(current) + else + return + end + return rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) +end + +local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v) + return rule(pos_h, pos_v, pos_r, size_h, size_v, "normal", nil) +end + +local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline) + -- no l support yet + return rule(pos_h, pos_v - d, pos_r, w, h + d, outline and "outline" or "normal") +end + +-- file stuff too +-- todo: default flushers +-- also color (via hash) + +-- installer + +drivers.install { + name = "lua", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.json" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename,utilities.json.tostring(data,not compact)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "json", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.js" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename, + "const JSON_CONTEXT = JSON.parse ( `" .. + utilities.json.tostring(data,not compact) .. + "` ) ;\n" + ) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "js", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} diff --git a/tex/context/base/mkxl/back-lua.mkxl b/tex/context/base/mkxl/back-lua.mkxl new file mode 100644 index 000000000..0fb1bcc88 --- /dev/null +++ b/tex/context/base/mkxl/back-lua.mkxl @@ -0,0 +1,16 @@ +%D \module +%D [ file=back-lua, +%D version=2018.07.26, +%D title=\CONTEXT\ Backend 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{back-lua}{autosuffix,optimize} + +\endinput diff --git a/tex/context/base/mkxl/back-mps.lmt b/tex/context/base/mkxl/back-mps.lmt new file mode 100644 index 000000000..4a2a573c4 --- /dev/null +++ b/tex/context/base/mkxl/back-mps.lmt @@ -0,0 +1,210 @@ +if not modules then modules = { } end modules ['back-mps'] = { + version = 1.001, + optimize = true, + 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 fontproperties = fonts.hashes.properties +local fontparameters = fonts.hashes.parameters + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local bpfactor = number.dimenfactors.bp +local texgetbox = tex.getbox +local formatters = string.formatters + +local rulecodes = nodes.rulecodes +local normalrule_code = rulecodes.normal +----- boxrule_code = rulecodes.box +----- imagerule_code = rulecodes.image +----- emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +local outlinerule_code = rulecodes.outline + +local fonts = { } +local pages = { } +local buffer = { } +local b = 0 +local converter = nil + +local function reset() + buffer = { } + b = 0 +end + +local f_font = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ] + +local f_glyph = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ] +local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] +local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.tex" +end + +local function save() -- might become a driver function that already is plugged into stopactions + starttiming(drivers) + if #pages > 0 then + local filename = outputfilename() + drivers.report("saving result in %a",filename) + reset() + b = b + 1 + buffer[b] = "\\starttext\n" + for k, v in table.sortedhash(fonts) do + b = b + 1 + buffer[b] = f_font(v.name,v.filename,v.size) + end + for i=1,#pages do + b = b + 1 + buffer[b] = pages[i] + end + b = b + 1 + buffer[b] = "\\stoptext\n" + io.savedata(filename,table.concat(buffer,"",1,b)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +local function initialize(driver,details) + reset() + b = b + 1 + buffer[b] = "\n\\startMPpage" +end + +local function finalize(driver,details) + b = b + 1 + buffer[b] = "\\stopMPpage\n" + pages[details.pagenumber] = table.concat(buffer,"\n",1,b) +end + +local function wrapup(driver) +end + +local function cleanup(driver) + reset() +end + +local function convert(driver,boxnumber,pagenumber) + converter(driver,texgetbox(boxnumber),"page",pagenumber) +end + +-- flushers + +local last + +local function updatefontstate(id) + if fonts[id] then + last = fonts[id].name + else + last = "MPSfont" .. converters.Characters(id) + fonts[id] = { + filename = file.basename(fontproperties[id].filename), + size = fontparameters[id].size * bpfactor, + name = last, + } + end +end + +local function flushcharacter(current, pos_h, pos_v, pod_r, font, char) + b = b + 1 + buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor) +end + +local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v, subtype) + if subtype == normalrule_code then + b = b + 1 + buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) + elseif subtype == outlinerule_code then + b = b + 1 + buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) + end +end + +local function flushsimplerule(pos_h, pos_v, pod_r, size_h, size_v) + flush_rule(false,pos_h,pos_v,pod_r,size_h,size_v,normalrule_code) +end + +local function flushspecialrule(pos_h, pos_v, pod_r, w, h, d, l, outline) + flush_rule(false,pos_h,pos_v-d,pod_r,w,h+d,outline and outlinerule_code or normalrule_code) +end + +-- installer + +drivers.install { + name = "mps", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- extras + +-- if not mp then +-- return +-- end +-- +-- local mpprint = mp.print +-- local formatters = string.formatters +-- +-- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ] +-- local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] +-- +-- local current = nil +-- local size = 0 +-- +-- function mp.place_buffermake(box) +-- drivers.convert("mps",box) +-- current = drivers.action("mps","fetch") +-- size = #current +-- end +-- +-- function mp.place_buffersize() +-- mpprint(size) +-- end +-- +-- function mp.place_bufferslot(i) +-- if i > 0 and i <= size then +-- local b = buffer[i] +-- local t = b[1] +-- if t == "glyph" then +-- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor)) +-- elseif t == "rule" then +-- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor)) +-- end +-- end +-- end +-- +-- function mp.place_bufferwipe() +-- current = nil +-- size = 0 +-- end diff --git a/tex/context/base/mkxl/back-mps.mkxl b/tex/context/base/mkxl/back-mps.mkxl new file mode 100644 index 000000000..d4d428d42 --- /dev/null +++ b/tex/context/base/mkxl/back-mps.mkxl @@ -0,0 +1,16 @@ +%D \module +%D [ file=back-mps, +%D version=2018.07.26, +%D title=\CONTEXT\ Backend 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{back-mps}{autosuffix,optimize} + +\endinput diff --git a/tex/context/base/mkxl/back-out.lmt b/tex/context/base/mkxl/back-out.lmt new file mode 100644 index 000000000..1f33da557 --- /dev/null +++ b/tex/context/base/mkxl/back-out.lmt @@ -0,0 +1,255 @@ +if not modules then modules = { } end modules ['back-out'] = { + 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" +} + +local type = type +local loadstring = loadstring + +local context = context + +-- tokens.scanners..... + +local get = token.get_index +local scanners = tokens.scanners +local scaninteger = scanners.integer +local scanstring = scanners.string +local scankeyword = scanners.keyword +local scantokenlist = scanners.tokenlist + +local serialize = token.serialize + +local logwriter = logs.writer +local openfile = io.open +local flushio = io.flush + +local nuts = nodes.nuts +local tonode = nuts.tonode +local copynode = nuts.copy +local nodepool = nuts.pool + +local getdata = nuts.getdata + +local whatsit_code = nodes.nodecodes.whatsit + +local whatsitcodes = nodes.whatsitcodes + +local literalvalues = nodes.literalvalues +local originliteral_code = literalvalues.origin +local pageliteral_code = literalvalues.page +local directliteral_code = literalvalues.direct +local rawliteral_code = literalvalues.raw + +local immediate_code = tex.flagcodes.immediate + +local nodeproperties = nodes.properties.data + +local channels = { } + +local register = nodepool.register +local newnut = nuts.new + +local opennode = register(newnut(whatsit_code,whatsitcodes.open)) +local writenode = register(newnut(whatsit_code,whatsitcodes.write)) +local closenode = register(newnut(whatsit_code,whatsitcodes.close)) +local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua)) +local literalnode = register(newnut(whatsit_code,whatsitcodes.literal)) +local savenode = register(newnut(whatsit_code,whatsitcodes.save)) +local restorenode = register(newnut(whatsit_code,whatsitcodes.restore)) +local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix)) + +local tomatrix = drivers.helpers.tomatrix + +local open_command, write_command, close_command + +backends = backends or { } + +local function immediately(prefix) + return prefix and (prefix & immediate_code) ~= 0 +end + +local function openout(prefix) + local channel = scaninteger() + scankeyword("=") -- hack + local filename = scanstring() + if not immediately(prefix) then + local n = copynode(opennode) + nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" + return context(tonode(n)) + elseif not channels[channel] then + local handle = openfile(filename,"wb") or false + if handle then + channels[channel] = handle + else + -- error + end + end +end + +function backends.openout(n) + local p = nodeproperties[n] + if p then + local handle = openfile(p.filename,"wb") or false + if handle then + channels[p.channel] = handle + else + -- error + end + end +end + +local function write(prefix) + local channel = scaninteger() + if not immediately(prefix) then + local t = scantokenlist() + local n = copynode(writenode) + nodeproperties[n] = { channel = channel, data = t } -- action = "write" + return context(tonode(n)) + else + local content = scanstring() + local handle = channels[channel] + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end +end + +function backends.writeout(n) + local p = nodeproperties[n] + if p then + local handle = channels[p.channel] + local content = serialize(p.data) + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end +end + +local function closeout(prefix) + local channel = scaninteger() + if not immediately(prefix) then + local n = copynode(closenode) + nodeproperties[n] = { channel = channel } -- action = "close" + return context(tonode(n)) + else + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end +end + +function backends.closeout(n) + local p = nodeproperties[n] + if p then + local channel = p.channel + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end +end + +local noflatelua = 0 + +local function latelua() + local node = copynode(lateluanode) + local name = "latelua" + if scankeyword("name") then + name = scanstring() + end + local data = scantokenlist() + nodeproperties[node] = { name = name, data = data } + return context(tonode(node)) +end + +function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) + local p = nodeproperties[current] + if p then + data = p.data + else + data = getdata(current) + end + noflatelua = noflatelua + 1 + local kind = type(data) + if kind == "table" then + data.action(data.specification or data) + elseif kind == "function" then + data() + else + if kind ~= "string" then + data = serialize(data) + end + if #data ~= "" then + local code = loadstring(data) + if code then + code() + end + end + end +end + +function backends.getcallbackstate() + return { count = noflatelua } +end + +function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end +function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end +function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end +function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end + +local pdfliterals = { + [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, + [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, + [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, + [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, +} + +function nodepool.literal(mode,str) + local t = copynode(literalnode) + if str then + nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } + else + nodeproperties[t] = { data = mode, mode = pageliteral_code } + end + return t +end + +function nodepool.save() + return copynode(savenode) +end + +function nodepool.restore() + return copynode(restorenode) +end + +function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) + local t = copynode(setmatrixnode) + nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) } + return t +end + +interfaces.implement { name = "openout", actions = openout, public = true, usage = "value" } +interfaces.implement { name = "write", actions = write, public = true, usage = "value" } +interfaces.implement { name = "closeout", actions = closeout, public = true, usage = "value" } +interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true } +interfaces.implement { name = "special", actions = scanstring, public = true, protected = true } + +open_command = get(token.create("openout")) +write_command = get(token.create("write")) +close_command = get(token.create("closeout")) diff --git a/tex/context/base/mkxl/back-out.mkxl b/tex/context/base/mkxl/back-out.mkxl new file mode 100644 index 000000000..5cf79b2ea --- /dev/null +++ b/tex/context/base/mkxl/back-out.mkxl @@ -0,0 +1,22 @@ +%D \module +%D [ file=back-out, +%D version=2019.02.08, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=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. + +\registerctxluafile{back-out}{autosuffix} + +% \let\normalopenout \openout +% \let\normalwrite \write +% \let\normalcloseout\closeout +% \let\normallatelua \latelua +% \let\normalspecial \special + +\endinput diff --git a/tex/context/base/mkxl/back-pdf.mkxl b/tex/context/base/mkxl/back-pdf.mkxl new file mode 100644 index 000000000..1ce97cede --- /dev/null +++ b/tex/context/base/mkxl/back-pdf.mkxl @@ -0,0 +1,157 @@ +%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. + +%D The less there is here, the better. After a decade it is time to remove the \type +%D {\pdf*} ones completely. For the moment I keep them commented but even that will +%D go away. + +\writestatus{loading}{ConTeXt Backend Macros / PDF} + +\registerctxluafile{lpdf-ini}{optimize} +\registerctxluafile{lpdf-lmt}{autosuffix,optimize} +\registerctxluafile{lpdf-col}{} +\registerctxluafile{lpdf-vfc}{autosuffix} +\registerctxluafile{lpdf-xmp}{} +\registerctxluafile{lpdf-ano}{} +\registerctxluafile{lpdf-res}{} +\registerctxluafile{lpdf-mis}{} +\registerctxluafile{lpdf-ren}{} +\registerctxluafile{lpdf-grp}{} +\registerctxluafile{lpdf-wid}{} +\registerctxluafile{lpdf-fld}{} +\registerctxluafile{lpdf-mov}{} +\registerctxluafile{lpdf-u3d}{} % this will become a module +%registerctxluafile{lpdf-swf}{} % this will become a module +\registerctxluafile{lpdf-tag}{} +\registerctxluafile{lpdf-fmt}{} +\registerctxluafile{lpdf-pde}{} +\registerctxluafile{lpdf-img}{autosuffix,optimize} +\registerctxluafile{lpdf-epa}{} +\registerctxluafile{lpdf-emb}{autosuffix,optimize} +\registerctxluafile{lpdf-fnt}{} + +\registerctxluafile{back-pdp}{} +\registerctxluafile{back-pdf}{} % some code will move to lpdf-* + +\loadmkxlfile{back-u3d} % this will become a module +%loadmkxlfile{back-swf} % this will become a module + +\unprotect + +%D We will minimize the number of calls to \PDF\ specific primitives and delegate +%D all management and injection of code to the backend. +%D +%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. + +\permanent\protected\def\pdfextension{\clf_pdfextension} +\permanent \def\pdffeedback {\clf_pdffeedback} +\permanent \def\pdfvariable {\clf_pdfvariable} + +%D For the moment we keep this for tikz but hopefully it will at some point use +%D the proper ones. Consider them obsolete: + +\permanent\protected\def\pdfliteral {\clf_pdfliteral} +\permanent\protected\def\pdfobj {\clf_pdfobj}% +\permanent\protected\def\pdflastobj {\numexpr\clf_pdflastobj\relax} +\permanent\protected\def\pdfrefobj {\clf_pdfrefobj} + +\permanent\protected\def\pdfrestore {\pdfextension restore} +\permanent\protected\def\pdfsave {\pdfextension save} +\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix} + +\permanent\let\pdfxform \saveboxresource +\permanent\let\pdflastxform\lastsavedboxresourceindex +\permanent\let\pdfrefxform \useboxresource + +%D Here are quick and dirty compression flippers, mostly used when testing something +%D as one can best stick to the defaults that also adapt to specific standards. + +\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} +\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} +\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } +\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} + +%D PDF/X (maybe combine the two lua calls) + +\setupbackend + [xmpfile=] + +\appendtoks + \edef\p_file{\backendparameter{xmpfile}}% + \ifempty\p_file\else + \clf_setxmpfile{\p_file}% + \fi +\to \everysetupbackend + +%D This will change: + +\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 These are the only official methods to add stuff to the resources. If more is +%D needed for third party low level code, it can be added. + +\permanent\protected\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} +\permanent\protected\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} +\permanent\protected\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} + +\permanent\protected\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} +\permanent\protected\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} +\permanent\protected\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} + +\permanent\protected\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} +\permanent\protected\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} +\permanent\protected\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} +\permanent\protected\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} + +\permanent \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} +\permanent \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} + +%D This is a temporary hack mthat will be removed, improved or somehow can become +%D default. + +\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} + +%D Just in case one needs this \unknown: +%D +%D \starttyping +%D text \pdfbackendactualtext{Meier}{Müller} text +%D \stoptyping + +\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced + {\clf_startactualtext{#2}% + #1% + \clf_stopactualtext} + +\aliased\let\pdfactualtext\pdfbackendactualtext + +%D Bah, this is also needed for tikz: + +\ifdefined\pdfsavepos\else + \permanent\let\pdfsavepos \savepos + \permanent\let\pdflastxpos\lastxpos + \permanent\let\pdflastypos\lastypos +\fi + +\protect \endinput diff --git a/tex/context/base/mkxl/back-res.mkxl b/tex/context/base/mkxl/back-res.mkxl new file mode 100644 index 000000000..52317b946 --- /dev/null +++ b/tex/context/base/mkxl/back-res.mkxl @@ -0,0 +1,34 @@ +%D \module +%D [ file=back-res, +%D version=2019.05.23, % 2009.04.15, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=Resources, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Resources} + +\registerctxluafile{back-res}{} + +\unprotect + +%D We overload the primitives with our own but use a bit of indirection for the +%D purpose of tracing. Some of these are needed for packages like tikz. + +% todo: public implementors (we can update the lua code anyway) + +\permanent\protected\def\saveboxresource {\clf_saveboxresource} +\permanent\protected\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax} +\permanent\protected\def\useboxresource {\clf_useboxresource} + +\permanent\protected\def\saveimageresource {\clf_saveimageresource} +\permanent\protected\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax} +\permanent\protected\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax} +\permanent\protected\def\useimageresource {\clf_useimageresource} + +\protect \endinput diff --git a/tex/context/base/mkxl/back-trf.mkxl b/tex/context/base/mkxl/back-trf.mkxl new file mode 100644 index 000000000..96479614d --- /dev/null +++ b/tex/context/base/mkxl/back-trf.mkxl @@ -0,0 +1,81 @@ +%D \module +%D [ file=back-trf, +%D version=2019.02.08, % 2009.04.15, +%D title=\CONTEXT\ Backend 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. + +\unprotect + +\registerctxluafile{back-trf}{} + +% rotation + +\permanent\protected\def\dostartrotation#1% + {\forcecolorhack + \clf_startrotation#1\relax} % todo: implement without Q q + +\permanent\protected\def\dostoprotation + {\clf_stoprotation + \forcecolorhack} + +% scaling + +\permanent\protected\def\dostartscaling#1#2% + {\forcecolorhack + \clf_startscaling rx #1 ry #2\relax} + +\permanent\protected\def\dostopscaling + {\clf_stopscaling + \forcecolorhack} + +% mirroring + +\permanent\protected\def\dostartmirroring + {\clf_startmirroring} + +\permanent\protected\def\dostopmirroring + {\clf_stopmirroring} + +% transform + +\permanent\protected\def\dotransformnextbox#1#2#3#4#5#6% + {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} + +\permanent\protected\def\dodotransformnextbox#1#2#3#4#5#6% + {\hpack + {\kern #5\onebasepoint + \raise#6\onebasepoint + \hpack + {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax + \box\nextbox + \clf_stopmatrix}}} + +%D \macros +%D {dostartclipping,dostopclipping} +%D +%D Clipping is implemented in such a way that an arbitrary code can be fed. +%D +%D \starttyping +%D \dostartclipping {pathname} {width} {height} +%D \dostopclipping +%D \stoptyping + +\mutable\let\MPclippath\empty + +\permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here + {\forcecolorhack + \meta_grab_clip_path{#1}{#2}{#3}% + \clf_startclipping{\MPclippath}% + \glet\MPclippath\empty} + +\permanent\protected\def\dostopclipping + {\clf_stopclipping} + +\protect \endinput diff --git a/tex/context/base/mkxl/back-u3d.mkxl b/tex/context/base/mkxl/back-u3d.mkxl new file mode 100644 index 000000000..297dd5545 --- /dev/null +++ b/tex/context/base/mkxl/back-u3d.mkxl @@ -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/tex/context/base/mkxl/bibl-bib.mkxl b/tex/context/base/mkxl/bibl-bib.mkxl new file mode 100644 index 000000000..6d35d8de0 --- /dev/null +++ b/tex/context/base/mkxl/bibl-bib.mkxl @@ -0,0 +1,982 @@ +%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. + +%D This is really obsolete in \LMTX. For now I keep it but it will either go +%D away. The code is not upgraded, we only deal with macro protection. + +\writestatus{loading}{ConTeXt Bibliography Support / Experimental BibTeX} + +\registerctxluafile{bibl-bib}{} + +\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 some +%D motivation to spend time on it, and an occasional question on the list can be a +%D reason. A few examples. As \BIBTEX\ databases can be poluted by local commands, +%D 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 strip +%D 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 familiar with +%D \XML\ processing in \MKIV. +%D +%D Here we regular setups. Three elements are mapped but only one is actually used +%D 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 element +%D 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 + +\protected\def\definebibtexsession {\dosingleargument\dodefinebibtexsession} + \def\preparebibtexsession{\dodoubleempty \dopreparebibtexsession} +\protected\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]{\xmlprocess{bibtex:#1}{#2}{#2}} + +\protected\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] + +% \protected\def\startpublication#1\stoppublication +% {\blank +% todo +% \blank} + +% \let\stoppublication\relax + +\protected\def\bibtexspace {\removeunwantedspaces\space} +\protected\def\bibtexperiod {\removeunwantedspaces.\space} +\protected\def\bibtexcomma {\removeunwantedspaces,\space} +\protected\def\bibtexlparent {\removeunwantedspaces\space(} +\protected\def\bibtexrparent {\removeunwantedspaces)\space} +\protected\def\bibtexlbracket{\removeunwantedspaces\space[} +\protected\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% + \orelse\ifcsname\??pb:\currentbibtexvariant#1\endcsname + \??pb:\currentbibtexvariant#1% + \orelse\ifcsname\??pb\currentbibtexsession#1\endcsname + \??pb\currentbibtexsession#1% + \orelse\ifcsname\??pb#1\endcsname + \??pb#1% + \else + \s!empty + \fi + \endcsname} + +\def\bibtexcitationparameter#1% + {\csname + \ifcsname\??pv\currentbibtexsession:\currentbibtexvariant#1\endcsname + \??pv\currentbibtexsession:\currentbibtexvariant#1% + \orelse\ifcsname\??pv:\currentbibtexvariant#1\endcsname + \??pv:\currentbibtexvariant#1% + \orelse\ifcsname\??pv\currentbibtexsession#1\endcsname + \??pv\currentbibtexsession#1% + \orelse\ifcsname\??pv#1\endcsname + \??pv#1% + \else + \s!empty + \fi + \endcsname} + +% setup commands + +\protected\def\setupbibtexpublications + {\let\currentpublicationclass\??pb + \let\everysetupbibtexwhatever\everysetupbibtexpublications + \dosetupbibtexwhatever} + +\protected\def\setupbibtexcitations + {\let\currentpublicationclass\??pv + \let\everysetupbibtexwhatever\everysetupbibtexcitations + \dosetupbibtexwhatever} + +\protected\def\setupbibtexpublicationvariants + {\let\currentpublicationclass\??pb + \let\everysetupbibtexwhatever\everysetupbibtexpublications + \dosetupbibtexwhatevervariant} + +\protected\def\setupbibtexcitationvariants + {\let\currentpublicationclass\??pv + \let\everysetupbibtexwhatever\everysetupbibtexcitations + \dosetupbibtexwhatevervariant} + +\tolerant\def\dosetupbibtexwhatever[#1]#*[#2]% [sessionlist] [setup] + {\ifarguments\or + % setups + \getparameters[\currentpublicationclass][#1]% + \the\everysetupbibtexwhatever + \or + % sessions setups + \def\dobtxcommand##1{\getparameters[\currentpublicationclass##1][#2]}% + \processcommalist[#1]\dobtxcommand + \fi} + +\tolerant\def\dosetupbibtexwhatevervariant[#1]#*[#2]#*[#3]% [sessionlist] [variantlist] [setup] + {\ifarguments\or + % setups + \getparameters[\currentpublicationclass][#1]% + \the\everysetupbibtexwhatever + \or + % variants setups + \def\dobtxcommand##1{\getparameters[\currentpublicationclass:##1][#2]}% + \processcommalist[#1]\dobtxcommand + \or + % sessions variants setups + \def\dobtxcommand##1% + {\def\dodobtxcommand####1{\getparameters[\currentpublicationclass##1:####1][#3]}% + \processcommalist[#2]\dodobtxcommand}% + \processcommalist[#1]\docbtxommand + \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} +\protected\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} + +\protected\def\typesetbibtexpublication#1% + {\edef\currentbibtexsessiontag{#1}% + \ifx\currentbibtexsessiontag\empty + % can't really happen + \orelse\ifx\currentbibtexcriterium\v!all + \dotypesetbibtexpublication % was \doplacepublicationindeed + \else + \ctxlua{bibtex.hacks.doifalreadyplaced("\currentbibtexsessiontag")} + \donothing + \dotypesetbibtexpublication + \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 + +\protected\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 + +\protected\def\doifelsebibtexinteraction + {\iflocation + \edef\temp{\bibtexcitationparameter\c!interaction}% + \ifx\temp\v!stop + \doubleexpandafter\secondoftwoarguments + \else + \doubleexpandafter\firstoftwoarguments + \fi + \else + \expandafter\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 + +\protected\def\bibtexdataref {\dodoubleargument\dobibtexdataref} +\protected\def\bibtextyperef {\dodoubleargument\dobibtextyperef} +\protected\def\bibtexkeyref {\dodoubleargument\dobibtexkeyref} +\protected\def\bibtexserialref {\dodoubleargument\dobibtexserialref} +\protected\def\bibtexurlref {\dodoubleargument\dobibtexurlref} +\protected\def\bibtexdoiref {\dodoubleargument\dobibtexdoiref} +\protected\def\bibtexpageref {\dodoubleargument\dobibtexpageref} +\protected\def\bibtexnoneref {\dodoubleargument\dobibtexnoneref} +\protected\def\bibtexshortref {\dodoubleargument\dobibtexshortref} +\protected\def\bibtexyearref {\dodoubleargument\dobibtexyearref} +\protected\def\bibtexauthorref {\dodoubleargument\dobibtexauthorref} +\protected\def\bibtexauthoryearref {\dodoubleargument\dobibtexauthoryearref} +\protected\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")}} + +\protected\def\bibtexsingularplural#1#2{\ctxlua{bibtex.singularorplural(\!!bs#1\!!es,\!!bs#2\!!es)}} + +\protect \endinput + diff --git a/tex/context/base/mkxl/bibl-tra.mkxl b/tex/context/base/mkxl/bibl-tra.mkxl new file mode 100644 index 000000000..2fecf9cd8 --- /dev/null +++ b/tex/context/base/mkxl/bibl-tra.mkxl @@ -0,0 +1,1504 @@ +%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. + +%D This is really obsolete in \LMTX. For now I keep it but it will either go +%D away. The code is not upgraded, we only deal with macro protection. + +% % % % 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, he is +%D to blame. The changes concern references and lists but teh rendering itself is +%D unchanged. Future versions might provide variants as we have plans for an +%D upgrade. +%D +%D We use a still somewhat experimental extension to the list mechanism. Eventually +%D the bibtex module will use the bibl loader and access the data by means of lpath +%D expressions. In that case we don't need to process the bibliography but still +%D need to track usage as done here. +%D +%D A bit ongoing: make more local macros prefixed with bib, i.e. the bib namespace +%D is reserved. + +%D Todo: commandhandler + +\writestatus{loading}{ConTeXt Bibliography Support / BibTeX} + +\definefilesynonym[bib][obsolete] + +\registerctxluafile{bibl-tra}{} + +%D The original was developed independantly by Taco Hoekwater while still working +%D for Kluwer Academic publishers (it still used the dutch interface then). +%D Development continued after he left Kluwer, and in Januari 2005, the then already +%D internationalized file was merged with the core distribution by Hans Hagen. The +%D 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{}} (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{}} +%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. + +\protected\def\bibdoifelse#1% + {\expandafter\def\expandafter\!!stringa\expandafter{#1}% + \ifx\!!stringa\empty + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\protected\def\bibdoifnot#1% + {\expandafter\def\expandafter\!!stringa\expandafter{#1}% + \ifx\!!stringa\empty + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\protected\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 around. The names of +%D the commands it parses as well as the \type {.aux} extension to the file name are +%D both hardwired. +%D +%D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk! The good +%D news is that it can be rather short. We'll just ask \BIBTEX\ to output the entire +%D database(s) into the \type {bbl} file. +%D +%D The \type {\bibstyle} command controls how the \type {bbl} file will be sorted. +%D 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 + +\protected\def\setupbibtex + {\dosingleempty\dosetupbibtex} + +\protected\def\dosetupbibtex[#1]% + {\let\@@pbdatabase\empty + \getparameters[\??pb][#1]% + \the\everysetupbibtex} + +\protected\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 + +\protected\def\setuppublications + {\dosingleargument\dosetuppublications} + +\protected\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 lists each time +%D (\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 + +\protected\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 because +%D similar numbers can be confusing. So, for the moment this is not supported in +%D \MKIV. (So no: see reference [3-5,9] in "some other document") + +\protected\def\usepublications[#1]% + {\processcommalist[#1]\dousepublications} + +\protected\def\dousepublications#1% + {\doonlyonce{#1.\f!bibextension}{\dodousepublications{#1}}} + +\protected\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} files. \quote +%D {samplesize} is a sample value (in case of \BIBTEX|-|generated files, this will +%D be the longest \quote {short} key). Here \quote {totalnumber} is the total number +%D of entries that will follow in this file. +%D +%D Both values are only needed for the label calculation if \quote {autohang} is +%D \quote {true}, so by default the command is not even needed, and therefore I saw +%D no need to give it it's own system variable and it just re-uses \type {pb}. + +\def\publicationlistparameter#1{\csname\??pv:l:#1\endcsname} + +\protected\def\setuppublicationlist + {\dosingleempty\dosetuppublicationlist} + +\protected\def\dosetuppublicationlist[#1]% + {\getparameters[\??pv:l:][#1]% + \setuplist[pubs][\c!samplesize={AA99},\c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1,\c!command=]} + +\protected\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 key in the weird +%D \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 use one argument +%D that is stored in \type {@@pb@#1}. +%D +%D \type {\simplebibdef} also defines \type {bibinsert#1}, which can be used in the +%D argument of \type {\setuppublicationlayout} to fetch one of the \type {@@pb@} +%D data entries. \type {bibinsert#1} then has three arguments: \type {#1} are +%D commands to be executed before the data, \type {#2} are commands to be executed +%D after the data, and \type {#3} are commands to be executed if the data is not +%D found. +%D +%D \type {\bibcommandlist} is the list of commands that is affected by this +%D approach. Later on, it will be used to do a series of assignments from \type {#1} +%D to \type {bib@#1}: e.g \type {\title} becomes \type {\bib@title} when used within +%D a publication. + +\newtoks\initializebibdefinitions % we need to prevent clashes + +\protected\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\protected\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 + +\protected\def\bibinsertdoi#1#2#3% let's see how this fails + {\bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}} + +\protected\def\bibinsertbiburl#1#2#3% let's see how this fails + {\bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}} + +\protected\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 + +\protected\def\newbibfield[#1]% + {\simplebibdef{#1}% + \edef\bibcommandlist{\bibcommandlist,#1}} + +%D \macros{complexbibdef,specialbibinsert} +%D +%D The commands \type {\artauthor}, \type {\author} and \type {\editor} are more +%D complex than the other commands. 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 these +%D commands. This is why a special command is needed to insert them, as well as one +%D 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 look far +%D more complex than it really is. For example, the argument \type {author} defines +%D the macro \type {\bib@author} to do two things: increment the counter \type +%D {\author@num} (let's say to 2) and next store it's arguments in the macro \type +%D {\@@pb@author2}. And it defines \type {\bibinsertauthors} to expand into +%D +%D \starttyping +%D \specialbibinsert{author}{\author@num}{}{}{} +%D \stoptyping + +\protected\def\docomplexbibdef#1% + {\dodoubleempty\dodocomplexbibdef[#1]} + +\protected\def\dodocomplexbibdef[#1][#2]#3% + {\doquadrupleempty\dododocomplexbibdef[#1][#2][#3]} + +\protected\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} + +\protected\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 typesetting of all of these +%D arguments. + +\newcount\etallimitcounter +\newcount\etaldisplaycounter +\newcount\todocounter + +\protected\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 output, with +%D proper regard of all the inbetween strings that can arise depending on length of +%D the list of people. + +%D \#1 = type +%D \#2 = number of items to be typeset +%D \#3 = commacommand containing authors + +\protected\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 + \orelse\ifnum\numexpr\scratchcounter+\plusone\relax=#2\relax + \ifnum\commalistsize>\plustwo + \bibalternative\c!finalnamesep + \else + \bibalternative\c!lastnamesep + \fi + \else + \bibalternative\c!namesep + \fi + \fi} + +\protected\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 as well define +%D some of these commands yourself. +%D +%D The argument list has been reordered here, and the meanings 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 + +\protected\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}} + +\protected\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}} + +\protected\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}} + +\protected\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 initializations and +%D cleanups. + +\protected\def\clearbibitem#1{\setvalue{\??pb @#1}{}}% + +\protected\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} + +\protected\def\bibitemdefs#1% + {\expandafter\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname} + +\protected\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 do typesetting and +%D read the \type {bbl} file. +%D +%D Just a \type {\dosingleempty} is the most friendly of doing this: there need not +%D even be an argument to \type {\startpublication}. Of course, then there is no key +%D either, and it had better be an article (otherwise the layout will be all screwed +%D up). +%D +%D Only specifying the key in the argument is also legal. In storing this stuff into +%D macros, some trickery with token registers is needed to fix the expansion +%D problems. Even so, 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 the primitive \type +%D {\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 + +\pushoverloadmode + +\overloaded \protected\def\startpublication + {\dosingleempty\dostartpublication} + +\overloaded\let\stoppublication\relax + +\popoverloadmode + +%D This is rather memory hungry; some day i will rewrite this so that we use the +%D database instead. + +%D \macros{doifbibreferencefoundelse} +%D +%D Some macros to fetch the information provided by \type {\startpublication}. +%D +%D We can consider a faster variant in the bbl file; we can also consider storing +%D 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 ... + +\protected\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} + +\protected\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 } + +\protected\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 entry. Because of +%D this special situation, it has to be defined separately. Since this command will +%D not be seen until at \type {\placepublications}, it may force extra runs. The +%D same is true for \type {\cite} commands inside of publications. + +% used in bib self + +\protected\def\bib@crossref#1% called via \csname \endcsname + {\setvalue{\??pb @crossref}{#1}\ignorespaces} + +\protected\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 publist sometimes +%D needs to fetch something from the current item (like the 'short' key). For this, +%D the ID of the current item is passed in the implict parameter \type +%D {\currentpublicationkey}. + +\protected\def\doprocessbibtexentry#1{\typesetapublication{#1}} + +\protected\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 + +\protected\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}}}% + \orelse\ifx\@@pbnumbering\v!bib + \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}% + \else + \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}% + \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}}}% + \orelse\ifx\@@pbnumbering\v!bib + \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}% + \else + \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}% + \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} + +%D The full list of publications + +\protected\def\completepublications + {\dosingleempty\docompletepublications} + +\protected\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:} + +\protected\def\placepublications + {\dosingleempty\doplacepublications} + +\protected\def\doplacepublications[#1]% + {\begingroup + \setuplist[pubs][#1]% + \dodoplacepublications + \endgroup} + +\protected\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 text when you want +%D text only. + +\protected\def\typesetapublication#1% + {\doifsomething{#1} + {\doifelse{\namedlistparameter{pubs}\c!criterium}\v!all + {\doplacepublicationindeed{#1}}% + {\ctxlua{bibtex.hacks.doifalreadyplaced("#1")} + {} + {\doplacepublicationindeed{#1}}}% + }} + +%D For the moment we don't access the data directly but we will do that later when +%D we get away from storing the data and only deal with references. + +% we'll define proper handlers later + +\protected\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 + +\protected\def\bibtexpubtext + {\expanded{\reference[\bibrefprefix\currentpublicationkey]{\number\bibtexcounter}}% + \strut\dotypesetapublication\currentpublicationkey\strut} + +\protected\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. + +\protected\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}} + +\protected\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 \type {\cite} +%D commands with a braced argument (these might appear in included data from the +%D \type {.bib} file). + +\pushoverloadmode + +\protected\def\cite + {\strictdoifelsenextoptional\dodocite\dobibref} + +\popoverloadmode + +\protected\def\dobibref#1% + {\docite[#1][]} + +\protected\def\dodocite[#1]% + {\strictdoifelsenextoptional{\docite[#1]}{\docite[#1][]}} + +\protected\def\docite[#1][#2]% + {\begingroup + \doifelsesomething{#2} + {\dowhatevercite{#1}{#2}}% + {\donumberedcite{#1}}% + \endgroup} + +\protected\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]} + +\protected\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} + +\pushoverloadmode + +\protected\def\nocite[#1]% + {\processcommalist[#1]\docitation} + +\popoverloadmode + +%D \macros{setupcite} + +\permanent\tolerant\protected\def\setupcite[#1]#*[#2]% + {\ifparameter#2\or + \def\dodosetupcite##1{\getparameters[\??pv##1][#2]}% + \processcommalist[#1]\dodosetupcite + \else % default case + \getparameters[\??pv\@@citedefault][#1]% + \fi} + +%D Low-level stuff + +\protected\def\getcitedata#1[#2]#*[#3]#*to#4% + {\bgroup + \dofetchapublication{#3}% + \doifelsedefined{\??pb @bib#2}% + {\xdef#4{\getvalue{\??pb @bib#2}}}% + {\xdef#4{\getvalue{\??pb @#2}}}% + \egroup} + +\protected\def\dofetchapublication#1% + {\def\currentpublicationkey{#1}% + \presetbibvariables + \ignorespaces\bibgetvard{#1}} + +\protected\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, the macros that deal +%D with authors and years call this internal command to do the actual typesetting. +%D +%D Two entries with same author but with different years may be condensed into +%D ``Author (year1,year2)''. This is about the only optimization that makes sense +%D for the (author,year) style of citations (years within one author have to be +%D unique 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, the macro \type {\thebibauthors} holds the names of the +%D alternative author info fields for the current list. This is a commalist, and +%D \type {\thebibyears} holds the (collection of) year(s) that go with this author +%D (possibly as a nested commalist). +%D +%D There had better be an author for all cases, but there does not have to be year +%D info always. \type{\thebibyears} is pre|-|initialized because this makes the +%D 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 + +\protected\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 \type {\thebibauthors} and \type +%D {\thebibyears} are printed. + +\protected\def\dobibauthoryear + {\scratchcounter\zerocount + \getcommacommandsize[\thebibauthors]% + \edef\authorcount{\commalistsize}% + \expandafter\processcommalist\expandafter[\thebibauthors]\dodobibauthoryear} + +\protected\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 + \orelse\ifnum \scratchcounter=\authorcount\relax + \ixlastcommand + \else + \ixsecondcommand + \fi} + +\protected\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 + +\protected\def\handlemultiplebibauthors#1#2% + {\citescratchcounter\zerocount + \let\currentbibauthor\empty + \protected\def\bibprocessauthoritem##1% + {\advance\citescratchcounter\plusone + \ifnum \citescratchcounter=#1\relax + \edef\currentbibauthor{\currentbibauthor##1}% + \orelse\ifnum\numexpr\citescratchcounter+\plusone\relax=#1\relax + \edef\currentbibauthor{\currentbibauthor##1\bibalternative{andtext}}% + \else + \edef\currentbibauthor{\currentbibauthor##1\bibalternative{namesep}}% + \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. + +\protected\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}. + +\pushoverloadmode + + \protected\def\robustaddtocommalist#1#2% {item} \cs + {\robustdoifelseinset{#1}#2\resetglobal + {\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}} + +\popoverloadmode + +%D \macros{donormalbibauthoryear} +%D +%D Now we get to the macros that fill the two lists. The \quote {simple} one really +%D is quite simple. + +\protected\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 the reference is not +%D found or the reference does not contain author data. No questions marks o.s.s. +%D (to be fixed later). + +\protected\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 by \type +%D {\scratchcounter}. + +\newcount\bibitemcounter +\newcount\bibitemwanted + +%D The first portion is simple enough: if this is the very first author it is quite +%D straightforward to add it. \type {\bibitemcounter} and \type {\bibitemwanted} are +%D needed later to insert the year information in the correct item of \type +%D {\thebibyears}. + +\protected\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 a new author to \type +%D {\thebibauthors}. The messing about with the two counters is again to make sure +%D that \type {\thebibyears} will be updated correctly.If the author {\it was} +%D found, the counters will stay at their present values and everything will be +%D setup properly to insert the year info. + +\protected\def\docomparemyauthor#1% + {\global\advance\bibitemwanted \plusone + \def\mytempc{#1}% + \ifx\mytempc\myauthor + \quitcommalist + \orelse\ifnum\bibitemwanted=\bibitemcounter\relax + \global\advance\bibitemwanted \plusone + \global\bibitemcounter\bibitemwanted\relax + \expandafter\doglobal\expandafter\robustaddtocommalist\expandafter{{\myauthor}}\thebibauthors + \fi} + +%D This macro should be clear now. + +\protected\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. + +\protected\def\gotobiblink#1[#2]{\doifelsereferencefound{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}} +\protected\def\atbiblink [#1]{\doifelsereferencefound{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}} +\protected\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. \type +%D {\ixbibauthoryearref} stores the data in the macros \type {\currentbibauthor} and +%D \type {\currentbibyear}. + +\protected\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 + +\protected\def\bibmaybeinteractive#1#2% + {\doifelsebibinteraction{\gotobiblink{#2}[#1]}{#2}} + +\protected\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}}} + +\protected\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} + +\protected\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} + +\protected\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 thing that needs +%D to be done is making sure that the separations are inserted correctly. And that +%D is what \type {\bibinsertrefsep} does. + +\newconditional\firstbibrefsep + +\protected\def\bibresetrefsep + {\settrue\firstbibrefsep} + +\protected\def\bibinsertrefsep + {\ifconditional\firstbibrefsep + \setfalse\firstbibrefsep + \else + \bibalternative\c!pubsep + \fi} + +\protected\def\bibshortref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibshortref + \bibalternative\v!right} + +\protected\def\dobibshortref#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\gotobiblink{\bibgetvars{#1}}[#1]} + {}} + +\protected\def\bibserialref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibserialref + \bibalternative\v!right} + +\protected\def\dobibserialref#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\gotobiblink{\bibgetvarn{#1}}[#1]} + {}} + +\protected\def\bibkeyref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibkeyref + \bibalternative\v!right} + +\protected\def\dobibkeyref#1% + {\bibinsertrefsep + \gotobiblink{#1}[#1]} + +\protected\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}}} + +\protected\def\bibdoiref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibdoiref + \bibalternative\v!right} + +\protected\def\dobibdoiref#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\expanded{\bibgotoDOI{#1}{\bibgetvaro{#1}}}} + {}} + +\protected\def\biburlref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobiburlref + \bibalternative\v!right} + +\protected\def\bibgotoURL#1#2% + {\doifelsebibinteraction + {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]} + {\hyphenatedurl{#2}}} + +\protected\def\dobiburlref#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\expanded{\bibgotoURL{#1}{\bibgetvaru{#1}}}} + {}} + +\protected\def\bibtyperef[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibtyperef + \bibalternative\v!right} + +\protected\def\dobibtyperef#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\gotobiblink{\bibgetvart{#1}}[#1]} + {}} + +\protected\def\bibpageref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibpageref + \bibalternative\v!right} + +\protected\def\dobibpageref#1% + {\bibinsertrefsep + \doifelsebibinteraction + {\atbiblink[#1]} + {{\referencingfalse\at[#1]}}} + +\protected\def\bibdataref[#1]% + {\bibalternative\v!left + \bibresetrefsep\processcommalist[#1]\dobibdata + \bibalternative\v!right} + +\protected\def\dobibdata#1% + {\bibinsertrefsep + \doifelsebibreferencefound{#1} + {\dotypesetapublication{#1}} + {}} + +\let\bibnoneref\nocite + +%D \macros{bibnumref} + +\protected\def\bibnumref[#1]% + {\begingroup + \bibalternative\v!left + \penalty\plustenthousand + \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}% + \bibalternative\v!right + \endgroup} + +\protected\def\dowithbibtexnumrefconnector#1#2% + {\ifnum#1>\plusone + \ifnum#2>\plusone + \ifnum#2=#1\relax + \bibalternative{lastpubsep}% + \else + \bibalternative{pubsep}% + \fi + \fi + \fi} + +\protected\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref + {\dowithbibtexnumrefconnector{#1}{#2}% + \def\bibrefprefix{#4:}% + \inbiblink[#5]} + +\protected\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 \type {\citeasnoun}. + +\protected\def\bibauthornumref[#1]% + {\getcommalistsize[#1]% + \global\bibitemcounter\commalistsize + \bibresetrefsep + \processcommalist[#1]\dobibauthornumref} + +\protected\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] + +\protected\def\preloadbiblist + {\glet\preloadbiblist\relax + \dousepublications\jobname} + +% \appendtoks \preloadbiblist \to \everysetuppublications +% \appendtoks \preloadbiblist \to \everystarttext + +\let\ifbibinteractionelse\doifbibinteractionelse + +\protect \endinput diff --git a/tex/context/base/mkxl/blob-ini.lmt b/tex/context/base/mkxl/blob-ini.lmt new file mode 100644 index 000000000..42a18fddd --- /dev/null +++ b/tex/context/base/mkxl/blob-ini.lmt @@ -0,0 +1,210 @@ +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 +----- 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 + +-- upgraded + +local dimension_code = tokens.values.dimension +local scan_hbox = tokens.scanners.hbox + +local function action(field,what) + local l = scan_hbox() + local d = l[field] + flush_node_list(l) + if what == "value" then + return dimension_code, d + else + context("%p",d) + end +end + +implement { name = "widthofstring", public = true, usage = "value", actions = function(w) return action("width", w) end } +implement { name = "heightofstring", public = true, usage = "value", actions = function(w) return action("height",w) end } +implement { name = "depthofstring", public = true, usage = "value", actions = function(w) return action("depth", w) end } +implement { name = "totalofstring", public = true, usage = "value", actions = function(w) return action("total", w) end } diff --git a/tex/context/base/mkxl/blob-ini.mkxl b/tex/context/base/mkxl/blob-ini.mkxl new file mode 100644 index 000000000..3443836b7 --- /dev/null +++ b/tex/context/base/mkxl/blob-ini.mkxl @@ -0,0 +1,56 @@ +%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}{} % experimental +\registerctxluafile{blob-ini}{autosuffix} + +\unprotect + +% \widthofstring % defined in lua +% \heightofstring % defined in lua +% \depthofstring % defined in lua +% \heightanddepthofstring % defined in lua + +\permanent\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen +\permanent\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen +\permanent\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen +\permanent\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen + +\aliased\let\heightanddepthofstring\totalofstring +\aliased\let\htdpofstring \hdofstring + +\let\hd\htdp % if yes then move this + +% This one takes anything that can be typeset + +\permanent\protected\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}} + +\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/tex/context/base/mkxl/buff-ini.mkxl b/tex/context/base/mkxl/buff-ini.mkxl new file mode 100644 index 000000000..815107851 --- /dev/null +++ b/tex/context/base/mkxl/buff-ini.mkxl @@ -0,0 +1,232 @@ +%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}{} + +\unprotect + +%D There have been several iterations in \MKIV\ but here we only show the currently +%D used one. One can always look back (and maybe learn some). It will never look +%D pretty and never be efficient but it has served us for ages (conceptually it's +%D as in \MKII). + +\mutable\let\currentbuffer\empty + +\permanent\def\doifelsebuffer#1{\clf_doifelsebuffer{#1}} % expandable, todo: use public implementor + +\aliased\let\doifbufferelse\doifelsebuffer + +\permanent\tolerant\protected\def\resetbuffer[#1]{\clf_erasebuffer{#1}} % todo: use public implementor + +\permanent\setuvalue{\e!start\v!buffer}% + {\begingroup % (3) + \obeylines + \buff_start} + +\tolerant\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% + {\edef\p_strip{\namedbufferparameter{#1}\c!strip}% for aditya + \normalexpanded{\buff_pickup + {#2}% + {#3}% + {#4}% + {}% + {\buff_stop{#4}}% + \ifx\p_strip\v!no\zerocount\else\plusone\fi}} + +\permanent\protected\def\grabbufferdatadirect % name start stop + {\begingroup % (6) + \buff_start_indeed\empty} + +\permanent\protected\def\grabbufferdata % was: \dostartbuffer + {\begingroup % (4) + \obeylines + \buff_grab_direct} + +\tolerant\def\buff_grab_direct[#1]#*[#2]#*[#3]#*[#4]% [category] [name] [start] [stop] + {\ifnum\lastarguments=\plusfour + \expandafter\buff_start_indeed + \else + \expandafter\buff_start_indeed_default + \fi{#1}{#2}{#3}{#4}} + +\def\buff_start_indeed_default#1#2#3#4{\buff_start_indeed\empty{#1}{#2}{#3}} + +% \let\buff_finish\relax +% \let\buff_gobble\relax + +\protected\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 + \protected\def\dofinishpickupbuffer + {\endgroup % (1) + \endgroup % (2) + #5}% + % todo: we need to skip the first lineending which is an 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 + +\protected\def\buff_stop#1% + {\endgroup % (3 & 4 & 5 & 6) + \begincsname#1\endcsname} + +\aliased\let\endbuffer\relax + +\permanent\tolerant\protected\def\setbuffer[#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 + +\mutable\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}% + \frozen\instance\setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}% + \frozen\instance\setuevalue{\e!get \currentbuffer}{\buff_get_stored {\currentbuffer}{\currentdefinedbuffer}}% +\to \everydefinebuffer + +\protected\def\buff_start_defined + {\begingroup % (5) + \buff_start_indeed} + +\permanent\def\thebuffernumber #1{\namedbufferparameter{#1}\c!number} +\permanent\def\thedefinedbuffer#1{def-\namedbufferparameter{#1}\c!number} + +\permanent\tolerant\protected\def\getbuffer[#1]% [name] + {\namedbufferparameter\empty\c!before\relax + \doifelsenothing{#1} + {\buff_get_stored_indeed\empty} + {\processcommalist[#1]\buff_get_stored_indeed}% + \namedbufferparameter\empty\c!after\relax} + +\protected\def\buff_get_stored#1#2% + {\namedbufferparameter{#1}\c!before\relax + \buff_get_stored_indeed{#2}% + \namedbufferparameter{#1}\c!after\relax} + +\protected\def\buff_get_stored_indeed#1% + {\clf_getbuffer{#1}} + +\permanent\protected\def\getdefinedbuffer[#1]% + {\buff_get_stored{#1}{\thedefinedbuffer{#1}}}% + +\permanent\tolerant\protected\def\inlinebuffer[#1]% [name] + {\doifelsenothing{#1} + {\buff_get_stored_inline_indeed\empty} + {\processcommalist[#1]\buff_get_stored_inline_indeed}} + +\protected\def\buff_get_stored_inline_indeed#1% + {\ignorespaces\clf_getbuffer{#1}\removeunwantedspaces} + +\permanent\def\rawbuffer#1% expandable + {\clf_getbuffer{#1}} + +\definebuffer + [\v!hiding] + +\setupbuffer + [\v!hiding] + [\c!before=, + \c!after=] + +\permanent\protected\protected\def\processTEXbuffer[#1]% keep case, maybe also lower + {\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] + +\permanent\tolerant\protected\def\savebuffer[#1]#*[#2]% + {\begingroup + \ifhastok={#1}% + \setupcurrentsavebuffer[#1]% + \else + \setupcurrentsavebuffer[\c!list={#1},\c!file=#2]% + \fi + \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 + +\permanent\tolerant\protected\def\ctxluabuffer[#1]{\clf_getbufferctxlua{#1}} % todo: use public implementor +\permanent\tolerant\protected\def\mkvibuffer [#1]{\clf_getbuffermkvi {#1}} % todo: use public implementor + +% maybe still used elsewhere + +\permanent\protected\def\doprocesstexbuffer#1{\buff_process_tex[#1]} % still used? if not ... it will go away + +\aliased\let\dostartbuffer\grabbufferdata % for old times sake, this will go away + +% new (expandable): + +\permanent\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/buff-par.mklx b/tex/context/base/mkxl/buff-par.mklx new file mode 100644 index 000000000..663ea7254 --- /dev/null +++ b/tex/context/base/mkxl/buff-par.mklx @@ -0,0 +1,180 @@ +%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}{} + +%D This module is made for Thomas Schmitz as part of a project. There is +%D no documentation yet. Also, this code is unfinished and not tested well. +%D +%D \starttyping +%D \defineparallel[main][one,two] +%D +%D \startmain +%D \startone +%D first 0 +%D [reference] first 1 +%D first 2 +%D first 3 +%D \stopone +%D \starttwo +%D second 1 +%D second 2 +%D \stoptwo +%D \stopmain +%D +%D \startmain +%D \startone +%D first 4 +%D first 4 +%D \stopone +%D \starttwo +%D second 3 +%D second 4 +%D \stoptwo +%D \stopmain +%D +%D \placeparallel[main][one][criterium=all] +%D +%D \placeparallel[main][two][criterium=all] +%D \stoptyping + +%D criterium=all start= n= + +\unprotect + +\installcorenamespace{parallel} +\installcorenamespace{parallelhandler} + +\installcommandhandler \??parallel {parallel} \??parallel + +\setupparallel + [\c!setups=parallel:place:default] + +\pushoverloadmode + +\let\buff_parallel_define_saved \defineparallel +\let\buff_process_parallel_instance\relax + +\permanent\tolerant\protected\overloaded\def\defineparallel[#name]#spacer[#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}}% + \frozen\instance\setuevalue{\e!start#name}{\buff_parallel_start{#name}}% + \frozen\instance\setuevalue{\e!stop #name}{\buff_parallel_stop}} + +\popoverloadmode + +\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 + \toksapp\t_buff_parallel{\edef\currentparallelinstance{#instance}\buff_process_parallel_instance\relax}% + \setuevalue{\e!stop#instance}{\buff_parallel_save{#instance}}} + +\pushoverloadmode + +\let\buff_parallel_setup_saved \setupparallel + +\permanent\tolerant\protected\def\setupparallel[#name]#spacer[#instances]#spacer[#setups]% + {\processcommalist[#instances]{\buff_parallel_setup_instance{#name}{#setups}}} + +\popoverloadmode + +\def\buff_parallel_setup_instance#name#setups#instance% + {\buff_parallel_setup_saved[#name:#instance][#setups]} + +\protected\def\buff_parallel_start#name% + {\pushmacro\currentparallel + \edef\currentparallel{#name}% + \clf_nextparallel{\currentparallel}} + +\protected\def\buff_parallel_stop + {\popmacro\currentparallel} + +\protected\def\buff_parallel_save#instance% defined moet ook aan de lua kant kunnen + {\clf_saveparallel + {\currentparallel}% + {#instance}% + {\thedefinedbuffer{#instance}}% + \relax} + +\permanent\tolerant\protected\def\placeparallel[#name]#spacer[#instance]#spacer[#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}} + {\directsetup{\namedparallelparameter{\currentparallelinstance}\c!setups}} + +\permanent\protected\def\doifelseparallel#name#instance% + {\clf_doifelseparallel{#name}{#instance}} + +\aliased\let\doifparallelelse\doifelseparallel + +\permanent\tolerant\protected\def\resetparallel[#name]#spacer[#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/tex/context/base/mkxl/buff-ver.mkxl b/tex/context/base/mkxl/buff-ver.mkxl new file mode 100644 index 000000000..8ca44a956 --- /dev/null +++ b/tex/context/base/mkxl/buff-ver.mkxl @@ -0,0 +1,998 @@ +%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}{} + +\unprotect + +\startcontextdefinitioncode + +\definesystemattribute[verbatimline][public] + +\appendtoksonce + \c_attr_verbatimline\attributeunsetvalue +\to \everyforgetall + +%D Initializations. + +\installcorenamespace{typinglines} +\installcorenamespace{typingspace} +\installcorenamespace{typingblank} % needs checking ... used? + +\newtoks\everyinitializeverbatim + +\appendtoks + \the\everyresettypesetting + \resetfontfeature + \resetcharacterspacing + \resetbreakpoints +\to \everyinitializeverbatim + +\permanent\protected\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 }{\enforced\let\obeyedspace\specialcontrolspace} +\setvalue{\??typingspace\v!stretch }{\enforced\let\obeyedspace\specialstretchedspace} +\setvalue{\??typingspace\v!normal }{} +\setvalue{\??typingspace\v!fixed }{\enforced\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} + +\protected\def\buff_verbatim_obey_hyphens + {} + +\protected\def\buff_verbatim_obey_breakpoints + {\nohyphens + \veryraggedright} + +\protected\def\buff_verbatim_ignore_hyphens + {\nohyphens} + +\def\buff_verbatim_initialize_type_one + {\enforced\let\obeylines\ignorelines + \edef\p_buff_option{\typeparameter\c!option}% + \ifx\p_buff_option\v!none + \usetypestyleandcolor\c!style\c!color + \orelse\ifempty\p_buff_option + \usetypestyleandcolor\c!style\c!color + \else + \usetypestyleparameter\c!style % no color + \fi + \setcatcodetable\vrbcatcodes} + +\def\buff_verbatim_initialize_type_two + {\spaceskip.5\emwidth\relax + \enforced\let\obeyedspace\specialobeyedspace + \enforced\let\controlspace\specialcontrolspace + \edef\p_buff_lines{\typeparameter\c!lines}% + \begincsname\??typinglines\p_buff_lines\endcsname + \edef\p_buff_space{\typeparameter\c!space}% + \begincsname\??typingspace\p_buff_space\endcsname + \relax\the\everyinitializeverbatim\relax} + +\protected\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 + \orelse\ifempty\p_buff_option + \usetypingstyleandcolor\c!style\c!color + \else + \usetypingstyleparameter\c!style % no color ! + \fi + \usealignparameter\typingparameter} + +\def\buff_verbatim_initialize_typing_two + {\spaceskip.5\emwidth\relax + \enforced\let\obeyedspace\specialobeyedspace + \enforced\let\controlspace\specialcontrolspace + \edef\p_buff_lines{\typingparameter\c!lines}% + \begincsname\??typinglines\p_buff_lines\endcsname + \edef\p_buff_space{\typingparameter\c!space}% + \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 following command. + +\installcorenamespace{type} + +\installcommandhandler \??type {type} \??type + +\appendtoks + \frozen\instance\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 will suffice, but +%D for documentation purposes the next 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 + \frozen\instance\setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}% + \frozen\instance\setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}% + \ifempty\currenttypingparent + \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} + +\permanent\protected\def\doifelsevisualizer#1% + {\clf_doifelsevisualizer{#1}} + +\aliased\let\doifvisualizerelse\doifelsevisualizer + +%D Verbatim command are very sensitive to argument processing, which is a direct +%D result of the \CATCODES\ being fixed at reading time. +%D +%D Typesetting inline verbatim can be accomplished by \type {\type}, which in this +%D sentence was typeset by saying just \type {\type {\type}}, which in turn was +%D typeset by \unknown. Using the normal grouping characters \type {{}} is the most +%D natural way of using this command. +%D +%D A second, more or less redundant, alternative is delimiting the argument with an +%D own character. This method was implemented in the context of a publication in the +%D \MAPS, where this way of delimiting is recognized by \LATEX\ users. +%D +%D The third, more original alternative, is the one using \type {<<} and \type {>>} +%D as delimiters. This alternative can be used in situations where slanted +%D typeseting is needed. +%D +%D \macros +%D {type} +%D +%D We define \type {\type} as a protected command. This command has several +%D invocations: grouped, wirt boundary characters, and with font switches. +%D +%D \starttyping +%D normal: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par +%D normal: \par \type{xx<..xx.. >..>xx} \par \type{<....>} \par \type{<....>} +%D \setuptype[option=slanted] +%D slanted: \par \type{xx<<..sl..<> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<>..>> \par +%D slanted: \par \type{xx<<..sl.. xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<....>> \par +%D \setuptype[option=none] +%D none: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par +%D \stoptyping +%D +%D When writing the manual to \CONTEXT\ and documenting this source we needed to +%D typeset \type {<<} and \type {>>}. Because we wanted to do this in the natural +%D way, we've adapted the original definition a bit. This implementation went +%D through several live cycles. The final implementation looks a bit further and +%D treats the lone \type {<<} and \type {>>} a bit different. The \type {\null} +%D prevents ligatures, which unfortunately turn up in Lucida fonts. +%D +%D The following lines show what happens when we set \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} + +\permanent\protected\def\type{\buff_verbatim_type\empty} +\permanent\protected\def\typ {\buff_verbatim_typ \empty} + +\protected\def\buff_verbatim_type#1% + {\dontleavehmode + \bgroup + \edef\currenttype{#1}% + \buff_verbatim_type_indeed} + +\def\buff_verbatim_typ#1% + {\dontleavehmode + \bgroup + \edef\currenttype{#1}% + \lettypeparameter\c!lines\v!hyphenated + \enforced\let\specialobeyedspace\specialstretchedspace + \buff_verbatim_type_indeed} + +\tolerant\def\buff_verbatim_type_indeed[#1]% + {\ifarguments\or\setupcurrenttype[#1]\fi + \buff_verbatim_left_of_type + \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one} + +\def\buff_verbatim_type_one + {\catcode`<=\othercatcode % old precaution + \catcode`>=\othercatcode % old precaution + \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c} + +\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 trait of this macros, +%D which are build on top of the support module, is that they don't hyphenate. We +%D therefore offer the alternative \type{\typ}. The current implementation works all +%D right, but a decent hyphenation support of \type{\tt} text will be implemented +%D soon. + +\permanent\protected\def\specialfixedspace {\kern\interwordspace\relax} +\permanent\protected\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip +\permanent\protected\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero +\permanent\protected\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback + +\permanent\protected\def\explicitfixedspace {\asciispacechar} +\permanent\protected\def\explicitobeyedspace {\asciispacechar\allowbreak} +\permanent\protected\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}% +\permanent\protected\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace + +\appendtoks + \enforced\protected\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}% +\to \everyenableelements + +\permanent\protected\def\obeyhyphens + {\enforced\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace + \enforced\let\controlspace\specialcontrolspace + \spaceskip.25\emwidth\relax} % hm a bit of stretch ! + +\permanent\protected\def\obeybreakpoints + {\ignorehyphens + \veryraggedright} + +\permanent\protected\def\ignorehyphens + {\nohyphens + \enforced\let\obeyedspace \specialobeyedspace + \enforced\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 argument, the fixed +%D \CATCODES\ interfere with our wishes. An experimental implementation of character +%D by character processing of verbatim text did overcome this limitation, but we've +%D decided not to use that slow and sometimes troublesome solution. Instead we stick +%D to some 'old' \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} + +\protected\def\tex{\buff_verbatim_special_type\texescape \relax} +\protected\def\arg{\buff_verbatim_special_type\leftargument \rightargument} +\protected\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker} +\protected\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker} + +\let\normaltexttex\tex +\let\normaltextarg\arg +\let\normaltextmat\mat +\let\normaltextdis\dis + +\permanent\protected\def\astype + {\dontleavehmode + \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken} + +\permanent\protected\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 + +\protected\def\buff_verbatim_typing_start#1% tricky non standard lookahead + {\begingroup + \edef\currenttyping{#1}% + \obeylines + \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop} + +\def\buff_verbatim_typing_start_nop + {\typingparameter\c!before\relax + \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\relax + \startpacked[\v!blank]% + \ifcondition\validassignment{#1}% + \setupcurrenttyping[#1]% + \else + \doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}% + \fi + \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}}} + +% \startnamedtyping[#1] + +\protected\def\buff_verbatim_setup_keep_together + {\edef\p_keeptogether{\typingparameter\c!keeptogether}% + \ifx\p_keeptogether\v!yes + \settrue \c_buff_optimize_linebreaks + \else + \setfalse\c_buff_optimize_linebreaks + \fi} + +\protected\def\buff_verbatim_type_block#1#2% + {\edef\p_strip{\typingparameter\c!strip}% + \normalexpanded{\buff_pickup + {_typing_}% + {#1}% + {#2}% + {}% + {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}% + \ifx\p_strip\v!no\zerocount\else\plusone\fi}} + +\protected\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 + \begincsname#2\endcsname} + +\protected\def\buff_verbatim_typing_stop#1% hm, currenttyping + {\stoppacked + \typingparameter\c!after\relax + \useindentnextparameter\typingparameter + \endgroup + \dorechecknextindentation} + +%D Line numbering for files is combined with filtering, while display verbatim has +%D 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 colorization of \TEX\ +%D sources as valid option. The other setup values are inherited from display +%D verbatim. The implementation of \type {\typefile} is straightforward: + +% [category] [settings] {name} % for historic reasons, all filenames are {} + +\appendtoks + \frozen\instance\setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}% +\to \everydefinetyping + +\permanent\tolerant\protected\def\typefile[#1]#*[#2]#:#3% + {\begingroup + \ifparameter#2\or + \setuptyping[#1][#2]% + \buff_verbatim_type_file_checked{#1}{#3}% + \orelse\ifparameter#1\or + \ifhastok={#1}% + \setuptyping[\v!file][#1]% + \buff_verbatim_type_file_checked\v!file{#3}% + \else + \buff_verbatim_type_file_checked{#1}{#3}% + \fi + \else + \buff_verbatim_type_file_checked\v!file{#3}% + \fi + \useindentnextparameter\typingparameter % needs checking + \endgroup + \dorechecknextindentation} % needs checking + +\def\buff_verbatim_type_file_checked#1#2% + {\doifelsetypingfile{#2} + {\buff_verbatim_type_file_indeed{#1}\askedtypingfile} + {\showmessage\m!verbatims1{#2}}} + +\permanent\protected\def\doifelsetypingfile#1% + {\edef\askedtypingfile{\locfilename{#1}}% + \ifempty\askedtypingfile + \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible + \fi + \ifempty\askedtypingfile + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doiftypingfileelse\doifelsetypingfile + +\def\buff_verbatim_type_file_indeed#1#2% category name + {\edef\currenttyping{#1}% + \typingparameter\c!before\relax + \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\relax} + +%D Line numbering: + +\newconditional\verbatimnumberinglines + +\permanent\protected\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]} + +\overloaded\protected\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 + \orelse\ifx\currenttypingnumbering\v!line + \settrue\verbatimnumberinglines + \else + \setfalse\verbatimnumberinglines + \fi + \ifconditional\verbatimnumberinglines + \enforced\let\beginofverbatimlines\beginofverbatimlinenumbering + \enforced\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. + +\permanent\protected\def\filename#1{{\tttf\hyphenatedfilename{#1}}} + +%D \macros +%D {verbatim} +%d +%D And a bonus macro, an unexpanded detokenize: + +\permanent\protected\def\verbatim#1{\detokenize{#1}} + +%D The setups for display verbatim and file verbatim are shared. One can adapt the +%D extra defined typing environments, but they also default to the values below. +%D Watch the 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] + +% the \zeropoint forces the number to the margin but also works ok in text + +\setuplinenumbering[\v!typing][\c!location=\v!left,\c!width=\zeropoint] + +\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] + +\permanent\protected\def\typebuffer + {\begingroup + \let\currenttyping\v!buffer + \buff_verbatim_type_buffer} + +\permanent\protected\def\typedefinedbuffer[#1]% + {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}% + +\appendtoks + \frozen\instance\setuevalue{\e!type\currentbuffer}{\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}% +\to \everydefinebuffer + +\appendtoks % \e!buffer + \frozen\instance\setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}% +\to \everydefinetyping + +\tolerant\protected\def\buff_verbatim_type_buffer[#1]#*[#2]% + {\ifarguments + \buff_verbatim_type_buffer_indeed\currenttyping\empty% [] + \or + \ifhastok={#1}% + \setupcurrenttyping[#1]% + \buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings] + \else + \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] + \fi + \or + \setupcurrenttyping[#2]% + \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings] + \fi + \useindentnextparameter\typingparameter + \endgroup + \dorechecknextindentation} + +\protected\def\buff_verbatim_type_buffer_class#1% + {\begingroup + \edef\currenttyping{#1}% + \buff_verbatim_type_buffer} + +\tolerant\protected\def\buff_verbatim_type_defined_buffer[#1]#*[#2]#*[#3]% category name settings + {\begingroup + \ifarguments\or\or\or + \setuptyping[#1][#3]% + \fi + \buff_verbatim_type_buffer_indeed{#1}{#2}% + \useindentnextparameter\typingparameter + \endgroup + \dorechecknextindentation} + +\protected\def\buff_verbatim_type_buffer_indeed#1#2% category name + {\edef\currenttyping{#1}% + \typingparameter\c!before\relax + \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\relax} + +\permanent\protected\def\typeinlinebuffer + {\dontleavehmode + \begingroup + \let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline + \let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code + \let\currenttype\empty + \buff_verbatim_type_buffer} + +\protected\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name + {\edef\currenttype{#1}% + \buff_verbatim_initialize_type_one + \dostarttaggedchained\t!verbatim\currenttype\??type + \clf_typebuffer + name {#2}% + strip {\v!yes}% + regime {\currentregime}% + method {\p_buff_option}% + nature {inline}% is default anyway + \relax + \dostoptagged} + +% 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 + +\permanent\tolerant\protected\def\processbuffer[#1]#*[#2]% + {\writestatus{nota bene}{\string\processbuffer\space is obsolete}% + \begingroup + \ifarguments + \buff_verbatim_process_indeed\v!buffer\empty% [] + \or + %\ifcondition\validassignment{#1}% + \ifhastok={#1}% + \setuptyping[\v!buffer][#1]% + \buff_verbatim_process_indeed\v!buffer\empty% [settings] + \else + \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] + \fi + \or + \setuptyping[\v!buffer][#2]% + \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings] + \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 + +\protected\def\buff_verbatim_begin_of_line + {\ifconditional\verbatimnumberinglines + \global\advance\nofverbatimlines\plusone + \c_attr_verbatimline\nofverbatimlines + \fi + \noindent + \buff_verbatim_set_line_margin + \the\everyline % maybe also after starttagged + \strut % after starttagged, else break ! + \dostarttagged\t!verbatimline\empty} + +\protected\def\buff_verbatim_end_of_line + {\dostoptagged + \obeyedline % still needed? + \par + \ifconditional\verbatimnumberinglines + \c_attr_verbatimline\attributeunsetvalue + \fi} + +\protected\def\buff_verbatim_empty_line + {\dostoptagged + \ifconditional\verbatimnumberinglines + \par\strut\par % this will be an option where we use a signal instead of a strut + \else + \blank[\typingparameter\c!blank]% + \fi + \dostarttagged\t!verbatimlines\empty} + +% hooks (todo: frozen): + +\newcount \c_buff_verbatim_noflines +\newcount \c_buff_verbatim_current +\newconditional\c_buff_optimize_linebreaks + + \def\doverbatimspace {\obeyedspace} + +\protected\def\doinlineverbatimstart {} +\protected\def\doinlineverbatimstop {} +\protected\def\doinlineverbatimbeginline {} +\protected\def\doinlineverbatimnewline {\obeyedspace} +\protected\def\doinlineverbatimemptyline {\obeyedspace} + +\protected\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone + \buff_verbatim_begin_of_line} +\protected\def\dodisplayverbatimstop {\buff_verbatim_end_of_line} +\protected\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone + \buff_verbatim_begin_of_line} +\protected\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line + \par + \ifconditional\c_buff_optimize_linebreaks + \buff_verbatim_inject_breaks + \fi} +\protected\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line} + +\protected\def\buff_verbatim_inject_breaks + {\ifnum\c_buff_verbatim_current=\plusone + \nobreak + \orelse\ifnum\c_buff_verbatim_noflines=\plusthree + \nobreak + \orelse\ifnum\c_buff_verbatim_current=\numexpr\c_buff_verbatim_noflines-\plusone\relax + \nobreak + \fi} + +\protected\def\dodisplayverbatiminitialize#1% + {\forgetparindent % maybe more + \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 +% \frozen\instance\setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}% +% \to \everydefinevisualizer +% +% \protected\def\buff_verbatim_visualize#1% +% {\bgroup +% \def\currentvisualizer{#1}% +% \usevisualizerstyleandcolor\c!style\c!color +% \let\next} + +\appendtoks + \enforced\def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize + \enforced\def\tex #1{\letterbackslash#1}% +\to \everysimplifycommands + +\stopcontextdefinitioncode + +%D This is \type {\asciimode} without the double comment hackery: + +\protected\def\literalmode{\setcatcodetable\txtcatcodes} + +\protect \endinput diff --git a/tex/context/base/mkxl/catc-act.mkxl b/tex/context/base/mkxl/catc-act.mkxl new file mode 100644 index 000000000..4ccf22a7f --- /dev/null +++ b/tex/context/base/mkxl/catc-act.mkxl @@ -0,0 +1,51 @@ +%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. + +\unprotect + +%D \macros +%D {installactivecharacter, defineactivecharacter} +%D +%D This module deals with some active character handling and I still need to +%D update it to use \typ {\letcharcode = \something}. This module +%D will be simplified stepwise. Look into the \MKIV\ variant for originals. +%D +%D There was a time when we had active double quotes and such but we no longer +%D do that. In fact, only the tilde and bar can be active in \CONTEXT. +%D +%D For those who love the more obscure features of \TEX: whenever you see +%D uppercase magic with active characters, keep in mind that this is something +%D deep down in the engine: handling of that specific case. The code here is +%D not used and not really tested. + +\permanent\protected\def\installactivecharacter#1 % + {\ifchknum#1\or + \scratchcounter #1\edef\scratchmacro{\expandtoken\othercatcode\scratchcounter}% + \else + \scratchcounter`#1\let \scratchmacro #1% + \fi + \normalexpanded{\startextendcatcodetable\ctxcatcodes\catcode\the\scratchcounter\activecatcode\stopextendcatcodetable}% + \letcatcodecommand \ctxcatcodes \scratchcounter \scratchmacro + \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi} + +\permanent\protected\def\defineactivecharacter #1 #2% + {\ifchknum#1\or\letcharcode#1=#2\relax\else\letcharcode`#1=#2\relax\fi} + +\permanent\protected\def\makecharacteractive #1 % + {\catcode`#1\activecatcode} + +\permanent\protected\def\installanddefineactivecharacter #1 #2% + {\normalexpanded{\installactivecharacter \utfchar{#1} }% + \defineactivecharacter #1 #2} + +\protect \endinput diff --git a/tex/context/base/mkxl/catc-ctx.mkxl b/tex/context/base/mkxl/catc-ctx.mkxl new file mode 100644 index 000000000..fcaec65d0 --- /dev/null +++ b/tex/context/base/mkxl/catc-ctx.mkxl @@ -0,0 +1,162 @@ +%D \module +%D [ file=catc-cys, +%D version=2006.09.18, +%D title=\CONTEXT\ Catcode Macros, +%D subtitle=Extra Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D We prefer to define relevant catcode tables in this file instead +%D of everywhere around. + +\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi +\ifdefined \prtcatcodes \else \newcatcodetable \prtcatcodes \fi +\ifdefined \txtcatcodes \else \newcatcodetable \txtcatcodes \fi +%ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky +\ifdefined \tpacatcodes \else \newcatcodetable \tpacatcodes \fi % { } +\ifdefined \tpbcatcodes \else \newcatcodetable \tpbcatcodes \fi % < > + +\setnewconstant \doublecommentsignal "10FF25 %% < 110000 (last valid range) + +\startcatcodetable \ctxcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + % \catcode\circumflexasciicode\superscriptcatcode + % \catcode\underscoreasciicode\subscriptcatcode + % \catcode\ampersandasciicode \alignmentcatcode + \catcode\underscoreasciicode\othercatcode + \catcode\circumflexasciicode\othercatcode + \catcode\ampersandasciicode \othercatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\startcatcodetable \prtcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\circumflexasciicode \superscriptcatcode % candidate + \catcode\underscoreasciicode \lettercatcode + \catcode\ampersandasciicode \alignmentcatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode \endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\startcatcodetable \tpacatcodes + \catcode\tabasciicode \othercatcode + \catcode\endoflineasciicode \othercatcode + \catcode\formfeedasciicode \othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\endoffileasciicode \othercatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode +\stopcatcodetable + +\startcatcodetable \tpbcatcodes + \catcode\tabasciicode \othercatcode + \catcode\endoflineasciicode \othercatcode + \catcode\formfeedasciicode \othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\endoffileasciicode \othercatcode + \catcode\lessthanasciicode \begingroupcatcode + \catcode\morethanasciicode \endgroupcatcode +\stopcatcodetable + +\startcatcodetable \txtcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode + \catcode\doublecommentsignal\commentcatcode +\stopcatcodetable + +\letcatcodecommand \ctxcatcodes \barasciicode \relax +\letcatcodecommand \ctxcatcodes \tildeasciicode \relax + +\pushoverloadmode + + \catcodetable \ctxcatcodes +\let \defaultcatcodetable \ctxcatcodes + +\popoverloadmode + +% for the moment here: + +\permanent\protected\def\starttexcode + {\pushcatcodetable + \catcodetable\prtcatcodes} + +\permanent\protected\def\stoptexcode + {\popcatcodetable} + +\permanent\protected\def\startcontextcode + {\pushcatcodetable + \catcodetable\ctxcatcodes} + +\permanent\protected\def\stopcontextcode + {\popcatcodetable} + +% not visible, only for special cases + +\newcatcodetable \ctdcatcodes % context definitions + +\startcatcodetable \ctdcatcodes + \catcode\tabasciicode \ignorecatcode + \catcode\endoflineasciicode \ignorecatcode + \catcode\formfeedasciicode \ignorecatcode + \catcode\spaceasciicode \ignorecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\circumflexasciicode \superscriptcatcode % candidate + \catcode\underscoreasciicode \lettercatcode + \catcode\ampersandasciicode \alignmentcatcode +% \catcode\colonasciicode \lettercatcode % candidate + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode \endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\permanent\protected\def\startcontextdefinitioncode + {\pushcatcodetable + \catcodetable\ctdcatcodes} + +\permanent\protected\def\stopcontextdefinitioncode + {\popcatcodetable} + +\endinput diff --git a/tex/context/base/mkxl/catc-def.mkxl b/tex/context/base/mkxl/catc-def.mkxl new file mode 100644 index 000000000..e93345e1c --- /dev/null +++ b/tex/context/base/mkxl/catc-def.mkxl @@ -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 shortcuts to their +%D character representation. Some will be overloaded (which might change). + +\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. + +\permanent\protected\def\unprotect{\pushcatcodetable\setcatcodetable\prtcatcodes} +\permanent\protected\def\protect {\popcatcodetable} + +% \prependtoks \catcodetable\ctxcatcodes \to \everyjob + +\endinput diff --git a/tex/context/base/mkxl/catc-ini.mkxl b/tex/context/base/mkxl/catc-ini.mkxl new file mode 100644 index 000000000..84d58b977 --- /dev/null +++ b/tex/context/base/mkxl/catc-ini.mkxl @@ -0,0 +1,329 @@ +%D \module +%D [ file=catc-ini, +%D version=2006.09.18, +%D title=\CONTEXT\ System Macros, +%D subtitle=Catcode Handling, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D We've split the functionality of syst-cat.* over more files +%D now so that we can load more selectively. + +\registerctxluafile{catc-ini}{} + +\unprotect + +%D A long standing wish has been the availability of catcode arrays. Because +%D traditional \TEX\ does not provide this we implement a fake method in the +%D \MKII\ file. There is some overlap in code with \MKII\ but we take that +%D for granted. Also, in \MKIV\ less active characters are used. + +% \begingroup +% +% \catcode\tabasciicode \activecatcode +% \catcode\formfeedasciicode \activecatcode +% \catcode\endoflineasciicode\activecatcode +% +% \letcharcode\tabasciicode \relax +% \letcharcode\newlineasciicode \relax +% \letcharcode\formfeedasciicode \relax +% \letcharcode\endoflineasciicode\relax +% +% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I} +% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J} +% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L} +% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M} +% +% \endgroup + +\begingroup + \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode} +\endgroup + +% \endlinechar = \endoflineasciicode % appended to input lines +% \newlinechar = \newlineasciicode % can be used in write + +% rather special and used in writing to file: \let\par\outputnewlinechar + +% \protected\def\initializenewlinechar % operating system dependent +% {\begingroup +% \newlinechar\newlineasciicode +% \xdef\outputnewlinechar{^^J}% +% \endgroup} + +\permanent\protected\def\initializenewlinechar % operating system dependent + {\begingroup + \letcharcode\newlineasciicode\relax + \newlinechar\newlineasciicode + \xdef\outputnewlinechar{\Uchar\newlineasciicode}% + \endgroup} + +%D We predefine some prefixes ahead of syst-aux and mult-sys. + +% We reserve 8 slots for catcodes. +% +% \def\??catcodelet {1>>} % let : \let +% \def\??catcodedef {2>>} % def : \def +% \def\??catcodeued {3>>} % ued : \protected\def +% \def\??catcodeget {4>>} % \meaning +% +% \def\??catcodetablet{5>>} +% \def\??catcodetablen{6>>} + +\installsystemnamespace {catcodelet} % let : \let +\installsystemnamespace {catcodedef} % def : \def +\installsystemnamespace {catcodeued} % ued : \protected\def +\installsystemnamespace {catcodeget} % \meaning + +\installsystemnamespace {catcodetablet} +\installsystemnamespace {catcodetablen} + +\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate +\newcount\c_syst_catcodes_a +\newcount\c_syst_catcodes_b +\newcount\c_syst_catcodes_c + +\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua + {\global\advance\c_syst_catcodes_n\plusone + \gdefcsname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging + %\setnewconstant#1\c_syst_catcodes_n + \immutable\integerdef#1\c_syst_catcodes_n + \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}} + +\newtoks \everysetdefaultcatcodes + +\everysetdefaultcatcodes % this might get dropped + {\catcode\backslashasciicode\othercatcode + \catcode\endoflineasciicode\othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\commentasciicode \othercatcode + \catcode\delasciicode \othercatcode} + +\permanent\protected\def\startcatcodetable#1#2\stopcatcodetable + {\begingroup + \catcodetable\inicatcodes + \the\everysetdefaultcatcodes + #2% + \savecatcodetable#1\relax + \endgroup} + +\permanent\let\stopcatcodetable\relax + +\permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable + {\begingroup + \catcodetable#1\relax + \globaldefs\plusone + #2% + \globaldefs\zerocount + \endgroup} + +\permanent\let\stopextendcatcodetable\relax + +\permanent\protected\def\permitcircumflexescape % to be used grouped + {\catcode\circumflexasciicode\superscriptcatcode} + +\aliased\let\permitcaretescape\permitcircumflexescape + +% == +% +% \protected\def\startextendcatcodetable#1#2\stopextendcatcodetable +% {\bgroup +% \scratchcounter\the\catcodetable +% \catcodetable #1 #2 +% \catcodetable\scratchcounter +% \egroup} + +%D The next command can be defined in a cleaner way in the MkIV way but we want +%D to have a fast one with a minimal chance for interference. Do we still need +%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use +%D active characters for very special cases. + +\setnewconstant\c_syst_catcodes_hack\tildeasciicode + +%D Once a catcode is assigned, the next assignments will happen faster. However, +%D redefinitions probably happen seldom so it's sort of overkill. + +\permanent\protected\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a} +\permanent\protected\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a} +\permanent\protected\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a} + +\def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b} +\def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b} +\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b} + +\def\syst_catcodes_let_b % each time + {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_let_c + \fi} + +\def\syst_catcodes_def_b % each time + {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_def_c + \fi} + +\def\syst_catcodes_ued_b % each time + {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_ued_c + \fi} + +\def\syst_catcodes_let_c % only first time + {\frozen\enforced\gdefcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter + {\enforced\letcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}% + \syst_catcodes_reinstate_unexpanded + \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here) + {\frozen\enforced\gdefcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + \expandafter##\expandafter1\expandafter + {\frozen\enforced\defcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + \syst_catcodes_reinstate_normal + \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\def\syst_catcodes_ued_c % only first time + {\frozen\enforced\gdefcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + \expandafter##\expandafter1\expandafter + {\frozen\enforced\protected\defcsname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + \syst_catcodes_reinstate_unexpanded + \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\permanent\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b} + +% \def\syst_catcodes_reinstate_normal % can be used when a direct definition has been done +% {\begingroup % and the selector has been lost +% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b +% \catcode\uccode\c_syst_catcodes_hack\activecatcode +% \uppercase{\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% +% \endgroup} + +% \def\syst_catcodes_reinstate_unexpanded % can be used when a direct definition has been done +% {\begingroup % and the selector has been lost +% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b +% \catcode\uccode\c_syst_catcodes_hack\activecatcode +% \uppercase{\protected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% +% \endgroup} + +%D This can be used when a direct definition has been done and the selector has been +%D lost. + +% problem: \next needs to be unique (as it gets bound) + +\def\syst_catcodes_reinstate_normal + {\begingroup + \edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% + \global\letcharcode\c_syst_catcodes_b\c_syst_char_code + \endgroup} + +\def\syst_catcodes_reinstate_unexpanded + {\begingroup + \protected\edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% + \global\letcharcode\c_syst_catcodes_b\c_syst_char_code + \endgroup} + +\newconstant\defaultcatcodetable + +\permanent\def\catcodecommand#1% + {\csname\??catcodeget\number + \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname + \currentcatcodetable \else \defaultcatcodetable + \fi + :\number#1\endcsname} + +%D \macros +%D {restorecatcodes,pushcatcodetable,popcatcodetable} +%D +%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary +%D file, which deals with tables of contents, registers, two pass tracking, references +%D etc. This file, as well as files concerning graphics, is processed when needed, +%D which can be in the mid of typesetting verbatim. However, when reading in data in +%D verbatim mode, we should temporary restore the normal \CATCODES, and that's exactly +%D what the next macros do. Saving the catcodes can be disabled by saying \type +%D {\localcatcodestrue}. In \MKIV\ instead we can push and pop catcode tables and as +%D we keep track of used tables users seldom need to deal with this themselves. + +\newcount\c_syst_catcodes_level + +\permanent\protected\def\pushcatcodetable + {\advance\c_syst_catcodes_level\plusone + \syst_catcodes_trace_push + \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable} + +\permanent\protected\def\popcatcodetable + {\ifcase\c_syst_catcodes_level + \syst_catcodes_trace_nesting_error + \else + \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname + \syst_catcodes_trace_pop + \advance\c_syst_catcodes_level\minusone + \fi} + +\protected\def\syst_catcodes_trace_nesting_error + {\immediate\write\statuswrite{}% + \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end + \immediate\write\statuswrite{}} + +\permanent\protected\def\restorecatcodes % takes previous level + {\ifnum\c_syst_catcodes_level>\plusone + \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname + \fi} + +% \newtoks\everycatcodetable + +\permanent\protected\def\setcatcodetable#1% + {\catcodetable#1% +% \the\everycatcodetable + \syst_catcodes_trace_set} + +%D Handy for debugging: +%D +%D \starttyping +%D \tracecatcodetables +%D \stoptyping + +\permanent\protected\def\tracecatcodetables + {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \number\c_syst_catcodes_level}}% + \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}% + \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}} + +\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}} + +\def\syst_catcodes_prev + {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount + \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname + \else + -% + \fi} + +\def\catcodetablename + {\ifnum\currentcatcodetable>\zerocount + \csname\??catcodetablen\number\currentcatcodetable\endcsname + \else + -% + \fi} + +\let\syst_catcodes_trace_set \empty +\let\syst_catcodes_trace_push\empty +\let\syst_catcodes_trace_pop \empty + +% \tracecatcodetables + +\protect + +%D We still have to define these so let's do that now: + +\newcatcodetable \inicatcodes +\initcatcodetable\inicatcodes + +\let\currentcatcodetable\catcodetable + +\endinput diff --git a/tex/context/base/mkxl/catc-sym.mkxl b/tex/context/base/mkxl/catc-sym.mkxl new file mode 100644 index 000000000..f60537da8 --- /dev/null +++ b/tex/context/base/mkxl/catc-sym.mkxl @@ -0,0 +1,96 @@ +%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 The following definitions can be used for mapping special characters onto +%D letters, although we cheat a bit: they actually are of category other but +%D for users that distinction doesn't matter here. The definitions in \MKII\ +%D and \MKIV\ look more impressive but here we use a \LUAMETATEX\ feature +%D that permits a more direct definition (that also looks nice with the +%D \CONTEXT\ syntax highlighting): + +\immutable\edef\letterleftbrace {\expandtoken \othercatcode \leftbraceasciicode} +\immutable\edef\letterrightbrace {\expandtoken \othercatcode \rightbraceasciicode} +\immutable\edef\letterampersand {\expandtoken \othercatcode \ampersandasciicode} +\immutable\edef\letterless {\expandtoken \othercatcode \lessthanasciicode} +\immutable\edef\lettermore {\expandtoken \othercatcode \morethanasciicode} +\immutable\edef\letterhash {\expandtoken \othercatcode \hashasciicode} +\immutable\edef\letterdoublequote {\expandtoken \othercatcode \doublequoteasciicode} +\immutable\edef\lettersinglequote {\expandtoken \othercatcode \singlequoteasciicode} +\immutable\edef\letterdollar {\expandtoken \othercatcode \dollarasciicode} +\immutable\edef\letterpercent {\expandtoken \othercatcode \percentasciicode} +\immutable\edef\letterhat {\expandtoken \othercatcode \circumflexasciicode} +\immutable\edef\letterunderscore {\expandtoken \othercatcode \underscoreasciicode} +\immutable\edef\letterbar {\expandtoken \othercatcode \barasciicode} +\immutable\edef\lettertilde {\expandtoken \othercatcode \tildeasciicode} +\immutable\edef\letterbackslash {\expandtoken \othercatcode \backslashasciicode} +\immutable\edef\letterslash {\expandtoken \othercatcode \forwardslashasciicode} +\immutable\edef\letterquestionmark {\expandtoken \othercatcode \questionmarkasciicode} +\immutable\edef\letterexclamationmark {\expandtoken \othercatcode \exclamationmarkasciicode} +\immutable\edef\letterat {\expandtoken \othercatcode \atsignasciicode} +\immutable\edef\lettercolon {\expandtoken \othercatcode \colonasciicode} +\immutable\edef\letterhyphen {\expandtoken \othercatcode \hyphenasciicode} + +\immutable\edef\letterleftparenthesis {\expandtoken \othercatcode \leftparentasciicode} +\immutable\edef\letterrightparenthesis {\expandtoken \othercatcode \rightparentasciicode} +\immutable\edef\letterleftbracket {\expandtoken \othercatcode \leftbracketasciicode} +\immutable\edef\letterrightbracket {\expandtoken \othercatcode \rightbracketasciicode} + +\aliased\let\letterescape \letterbackslash +\aliased\let\letterbgroup \letterleftbrace +\aliased\let\letteregroup \letterrightbrace +\aliased\let\letteropenbrace \letterleftbrace +\aliased\let\letterclosebrace\letterrightbrace + +\unprotect + +%immutable\edef\_n_u_l_{\expandtoken \othercatcode \zerocount} % nul(l) +%immutable\edef\_s_o_h_{\expandtoken \othercatcode \plusone } % start of header ^^^^0001 +\immutable\edef\_s_t_x_{\expandtoken \othercatcode \plustwo } % start of text ^^^^0002 +\immutable\edef\_e_t_x_{\expandtoken \othercatcode \plusthree} % end of text ^^^^0003 +\immutable\edef\_e_o_t_{\expandtoken \othercatcode \plusfour } % end of transmission ^^^^0004 +%immutable\edef\_e_n_q_{\expandtoken \othercatcode \plusfive } % enquiry +%immutable\edef\_a_c_k_{\expandtoken \othercatcode \plussix } % aknowledgement + +\protect + +%D \macros +%D {uncatcodespecials,setnaturalcatcodes,setnormalcatcodes, +%D uncatcodecharacters,uncatcodeallcharacters, +%D uncatcodespacetokens} +%D +%D The following macros are more or less replaced by switching to a catcode table +%D (which we simulate in \MKII) but we keep them for convenience and compatibility. +%D Some old engine code has been removed. A few ar still used a few times so I need +%D to clean that up. + +%permanent\protected\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens} +%permanent\protected\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes} +\permanent\protected\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes +%permanent\protected\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now +%permanent\protected\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore + +\permanent\protected\def\uncatcodespacetokens + {\catcode\spaceasciicode \spacecatcode + \catcode\tabasciicode \spacecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\endoflineasciicode\endoflinecatcode + \catcode\delasciicode \ignorecatcode} + +%D These two are probably no longer needed, but we keep them for a while. Some more +%D explanation can be foun din the mkiv variant of this module, where we also +%D discuss side effects. It's time to move on, so these might go away some day. + +\aliased \let\rescan \scantextokens +\permanent\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup} + +\endinput diff --git a/tex/context/base/mkxl/char-act.mkxl b/tex/context/base/mkxl/char-act.mkxl new file mode 100644 index 000000000..3fb4d2da6 --- /dev/null +++ b/tex/context/base/mkxl/char-act.mkxl @@ -0,0 +1,99 @@ +%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, \NEWLINE\ and \NEWPAGE\ +%D active and assigning them \type {\obeysomething}, but first we set some default +%D values. +%D +%D These are expandable: + +\permanent\def\obeyedspace{\space} +\permanent\def\obeyedtab {\obeyedspace} +\permanent\def\obeyedline {\par} +\permanent\def\obeyedpage {\page_otr_fill_and_eject_page} + +%D \macros +%D {controlspace,setcontrolspaces} +%D +%D First we define \type {\obeyspaces}. When we want visible spaces (control spaces) +%D we only have to adapt the definition of \type {\obeyedspace} to: + +\immutable\chardef\asciispacechar\spaceasciicode % a real space character + +\permanent\protected\def\naturalspace{\asciispacechar} +\permanent\protected\def\controlspace{\hbox{\asciispacechar}} % rather tex, we need the unicode value +\permanent\protected\def\normalspaces{\catcode\spaceasciicode\spacecatcode} + +% \bgroup +% \catcode\spaceasciicode\activecatcode +% \protected\gdef\obeyspaces {\catcode\spaceasciicode\activecatcode\def {\obeyedspace }} +% \protected\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}} +% \egroup + +%permanent\protected\def\obeyspaces {\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\obeyedspace } +%permanent\protected\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\controlspace} + +%D \macros +%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages} +%D +%D Next we take care of \NEWLINE\ and \NEWPAGE\ and because we want to be able to +%D typeset listings that contain \TAB, we have to handle those too. Because we have +%D to redefine the \NEWPAGE\ character locally, we redefine the meaning of this +%D (often already) active character. + +% \expandafter\def\activeformfeedtoken{\par} + +\letcharcode\formfeedasciicode\par + +%D The following indirect definitions enable us to implement all kind of \type +%D {\obeyed} handlers. + +% \protected\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }} +% \protected\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}} +% \protected\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}} + +% \protected\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}} +% \protected\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}} +% \protected\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} +% \protected\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} + +% but ... as we don't want to freeze to \obeyedspace etc which can be set after +% \obeyspaces, we use an idirectness + +\def\syst_obeyed_space{\obeyedspace} +\def\syst_obeyed_tab {\obeyedtab} +\def\syst_obeyed_line {\obeyedline} +\def\syst_obeyed_page {\obeyedpage} + +\permanent\protected\def\obeyspaces {\catcode\spaceasciicode \activecatcode\enforced\letcharcode\spaceasciicode \syst_obeyed_space} +\permanent\protected\def\obeytabs {\catcode\tabasciicode \activecatcode\enforced\letcharcode\tabasciicode \syst_obeyed_tab } +\permanent\protected\def\obeylines {\catcode\endoflineasciicode\activecatcode\enforced\letcharcode\endoflineasciicode\syst_obeyed_line } +\permanent\protected\def\obeypages {\catcode\formfeedasciicode \activecatcode\enforced\letcharcode\formfeedasciicode \syst_obeyed_page } + +\permanent\protected\def\ignoretabs {\catcode\tabasciicode \activecatcode\enforced\letcharcode\tabasciicode \syst_obeyed_space} +\permanent\protected\def\ignorelines{\catcode\endoflineasciicode\activecatcode\enforced\letcharcode\endoflineasciicode\syst_obeyed_space} +\permanent\protected\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} +\permanent\protected\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} + +\permanent\protected\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\enforced\letcharcode\spaceasciicode\controlspace} + +\endinput \protect diff --git a/tex/context/base/mkxl/char-enc.mkxl b/tex/context/base/mkxl/char-enc.mkxl new file mode 100644 index 000000000..d0dd3d20a --- /dev/null +++ b/tex/context/base/mkxl/char-enc.mkxl @@ -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}{} + +\endinput diff --git a/tex/context/base/mkxl/char-ini.mkxl b/tex/context/base/mkxl/char-ini.mkxl new file mode 100644 index 000000000..1df5d4b01 --- /dev/null +++ b/tex/context/base/mkxl/char-ini.mkxl @@ -0,0 +1,130 @@ +%D \module +%D [ file=char-ini, +%D version=2006.08.20, +%D title=\CONTEXT\ Character Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Character Support / Initialization} + +\registerctxluafile{char-fio}{} +\registerctxluafile{char-map}{} % maybe we will load this someplace else +\registerctxluafile{char-tex}{} +\registerctxluafile{char-ent}{} + +\unprotect + +% ¨äëïöüÿ +% ´áćéíĺńóŕśúýź +% ˙ċėġiż +% ¯āēīōū +% ˝őű +% ˆâĉêĝĥîĵôŝûŵŷ +% `àèìòùỳ +% ¸çķļņŗşţ +% ˛ąęįų +% ˚åů +% ˘ăĕğĭŏŭ +% ˇčďěľňřšťž +% ˜ãĩñõũ + +% \def\checkedchar#1% #2% +% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} +% +% impossible in math mode so there always fallback (till we have gyre): +% +% use \normalUchar when possible .. the next one is nice for documents and it also accepts +% 0x prefixed numbers + +\permanent\def\utfchar #1{\clf_utfchar {#1}} % todo: define public at lua end +\permanent\def\safechar#1{\clf_safechar{#1}} % todo: define public at lua end + +\permanent\protected\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) +\permanent \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) + +\permanent\def\expandUx{\enforced\let\Ux\eUx} + +\permanent \def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2 +\permanent \def\checkedmathchar#1#2{#2} +%permanent \def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} +\permanent\protected\def\checkedtextchar #1{\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2} + +\newconditional\prefermathovertextchar + +\permanent\protected\def\textormathchar#1% + {\begingroup + \scratchcounter#1\relax + \ifmmode + \char\scratchcounter + \else + \ifconditional\prefermathovertextchar + % dirty trick .. maybe let this adapt to bf too ? + \setfontid\fontid\textfont\c_font_fam_mr + \fi + \iffontchar\font\scratchcounter + \char\scratchcounter + \else + \normalstartimath\char\scratchcounter\normalstopimath + \fi + \fi + \endgroup} + +\permanent\protected\def\textormathchars#1% + {{\font_text_or_mathchars#1\relax}} + +\protected\def\font_text_or_mathchars#1#2\relax + {\relax\ifmmode + #1#2% + \orelse\iffontchar\font`#1\relax + #1#2\relax + \else + \normalstartimath#1#2\normalstopimath + \fi} + +%D The codes are stored in the format, so we don't need to reinitialize +%D them (unless of course we have adapted the table). It is on the agenda +%D to do this with \type {tex.lccode} cum suis once they're available. + +% \def\setcclcuc#1#2#3{\global\catcode#1=\lettercatcode\global\lccode#1=#2\global\uccode#1=#3\relax} +% \def\setcclcucself#1{\global\catcode#1=\lettercatcode\global\lccode#1=#1\global\uccode#1=#1\relax } + +% Is setting up vrb tpa and tpb needed? + +% move to lua side + +%clf_setcharactercodes + +\clf_setlettercatcodes\texcatcodes +\clf_setlettercatcodes\ctxcatcodes +\clf_setlettercatcodes\notcatcodes +%clf_setlettercatcodes\mthcatcodes +\clf_setlettercatcodes\vrbcatcodes +\clf_setlettercatcodes\prtcatcodes +\clf_setlettercatcodes\tpacatcodes +\clf_setlettercatcodes\tpbcatcodes +\clf_setlettercatcodes\txtcatcodes + +\clf_setactivecatcodes\ctxcatcodes +\clf_setactivecatcodes\notcatcodes +\clf_setactivecatcodes\prtcatcodes + +\clf_setcharacternames\ctxcatcodes + +\permanent\def\chardescription#1{\clf_chardescription#1\relax} + +% experiment (watch out: this is global and very font dependent when used with +% casing mechanisms) +% +% \overloaduppercase{0xDF}{0x1E9E}} +% \overloaduppercase{0xDF}{0x53,0x53} + +\permanent\protected\def\overloaduppercase{\clf_overloaduppercase} % todo: define public at lua end +\permanent\protected\def\overloadlowercase{\clf_overloadlowercase} % todo: define public at lua end + +\protect \endinput diff --git a/tex/context/base/mkxl/char-utf.mkxl b/tex/context/base/mkxl/char-utf.mkxl new file mode 100644 index 000000000..a7cbab345 --- /dev/null +++ b/tex/context/base/mkxl/char-utf.mkxl @@ -0,0 +1,44 @@ +%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\ 8, 16 and 32 +%D were supported as well as collapsing (combining sequences). Writing the code was +%D a relaxed experience, not in the last place because it was accompanied by +%D listening to those nice Vienna Teng cd's (who decided that making music was more +%D fun than programming, but then, she may not know \TEX\ and \LUA). + +\unprotect + +\registerctxluafile{char-def}{} +\registerctxluafile{char-ini}{} +\registerctxluafile{char-utf}{} +\registerctxluafile{char-cjk}{} + +%D We enable collapsing (combining characters) by default, but since the source +%D files are rather simple, we postpone the 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 + +\permanent\protected\def\definecomposedutf#1 #2 #3 {\clf_addgrapheme{#1}{#2}{#3}} + +\protect diff --git a/tex/context/base/mkxl/chem-ini.mkxl b/tex/context/base/mkxl/chem-ini.mkxl new file mode 100644 index 000000000..b88d4d834 --- /dev/null +++ b/tex/context/base/mkxl/chem-ini.mkxl @@ -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}{} + +\unprotect + +% todo: use \mathscriptsmode if needed + +%D \macros +%D {molecule} +%D +%D Quick and dirty: +%D +%D \starttyping +%D \permanent\protected\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 + +\permanent\protected\def\molecule#1% todo: can become a public implementor + {\clf_molecule{#1}} + +%D For old times sake: + +\permanent\protected\def\chem#1#2#3% + {\dontleavehmode\begingroup#1\lohi{#2}{#3}\endgroup} + +\protect \endinput + + diff --git a/tex/context/base/mkxl/chem-str.mkxl b/tex/context/base/mkxl/chem-str.mkxl new file mode 100644 index 000000000..2212ddfcb --- /dev/null +++ b/tex/context/base/mkxl/chem-str.mkxl @@ -0,0 +1,741 @@ +%D \module +%D [ file=chem-ini, +%D version=2009.05.13, +%D subtitle=Chemistry, +%D author=Hans Hagen \& Alan Braslau, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made +%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between +%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible +%D but better implementation, later versions might provide more, + +%D NOT YET LMTX'd + +\writestatus{loading}{ConTeXt Chemistry Macros / Structure} + +\registerctxluafile{chem-str}{} + +% We have a slightly different interface. This is unchanged: +% +% \startchemical[axis=on] +% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1] +% \stopchemical +% +% Here we use chemicalformula instead, so no longer a mix: +% +% \startchemicalformula +% \chemical{2H_2}{top}{bottom} +% \chemical{PLUS}{top}{bottom} +% \chemical{O_2}{top}{bottom} +% \chemical{GIVES}{top}{bottom} +% \chemical{2H_2O}{top}{bottom} +% \stopchemicalformula +% +% \startchemicalformula +% \chemical{2H_2} +% \chemical{PLUS} +% \chemical{O_2} +% \chemical{GIVES} +% \chemical{2H_2O} +% \stopchemicalformula +% +% The inline variant has only one argument: +% +% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O} + +\unprotect + +\installcorenamespace{chemical} +\installcorenamespace{chemicalsymbol} +\installcorenamespace{chemicalframed} +\installcorenamespace{chemicalsize} + +% \installsimplecommandhandler \??chemical {chemical} \??chemical % no \define... +\installcommandhandler \??chemical {chemical} \??chemical % no \define... + +\aliased\let\setupchemicals \setupchemical +\aliased\let\definechemicals\definechemical + +%D We use a dedicated framed macro instead of inheriting one. This is both +%D a historical and practical reason (like shared keys with different meaning +%D that could clash, e.g.\ align). + +\defineMPinstance % not really needed as we set in lua + [chemistry] + [\s!format=metafun, + %\s!extensions=\v!yes, % Should we add extensions and initializations? + %\s!initializations=\v!yes, % Would this give EmWidth, etc.? + \c!method=\s!double] + +\startMPdefinitions{chemistry} + loadmodule "chem" ; +\stopMPdefinitions + +\defineframed + [\??chemicalframed] + [\c!align=\v!normal, + \c!strut=\v!no] + +\permanent\protected\def\setupchemicalframed + {\setupframed[\??chemicalframed]} + +\permanent\protected\overloaded\def\definechemical % is global (so we don't use the commandhandler) + {\dosingleargument\chem_define} + +\def\chem_define[#1]#2% + {\startnointerference + \edef\currentdefinedchemical{#1}% + \enforced\let\chemical\chem_chemical_nested + \clf_undefinechemical{#1}% + #2% flush + \stopnointerference} + +\permanent\tolerant\protected\def\chem_chemical_nested[#1]#*[#2]% + {\clf_definechemical{\currentdefinedchemical}{#1}{\detokenize{#2}}} + +% chemical symbols + +\permanent\tolerant\protected\def\definechemicalsymbol[#1]#*[#2]% + {\ifarguments\else\setvalue{\??chemicalsymbol#1}{#2}\fi} + +\permanent\protected\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} + +\permanent\protected\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 + +\permanent\tolerant\protected\def\startchemical[#1]#*[#2]% + {\ifmmode\vcenter\else\vbox\fi % vpack ? + \bgroup + \synchronizestrut{\chemicalparameter\c!strut}% + \dontcomplain + %\settrue\indisplaychemical + \forgetall + \ifparameter#2\or + \ifhastok={#1}% + \setupcurrentchemical[#1]% same as \currentchemical + \else + \edef\currentchemical{#1}% + \setupcurrentchemical[#2]% + \fi + \orelse\ifparameter#1\or + \ifhastok={#1}% + \setupcurrentchemical[#1]% same as \currentchemical + \else + \edef\currentchemical{#1}% + \fi + \fi + \the\everystructurechemical + \setbox\b_chem_result\hpack\bgroup + \clf_startchemical + width {\chemicalparameter\c!width}% + height {\chemicalparameter\c!height}% + left {\chemicalparameter\c!left}% + right {\chemicalparameter\c!right}% + top {\chemicalparameter\c!top}% + bottom {\chemicalparameter\c!bottom}% + scale {\chemicalparameter\c!scale}% + rotation {\chemicalparameter\c!rotation}% + symalign {\chemicalparameter\c!symalign}% + axis {\chemicalparameter\c!axis}% was \MPcolor{...} + framecolor {\chemicalparameter\c!framecolor}% + rulethickness {\number\dimexpr\chemicalparameter\c!rulethickness}% + offset {\number\dimexpr\chemicalparameter\c!offset}% + unit {\number\dimexpr\chemicalparameter\c!unit}% + factor {\number\chemicalparameter\c!factor}% + \relax + \startnointerference} + +\permanent\protected\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} + +\protected\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 + +\protected\def\chem_framed_nop + {\directlocalframed + [\??chemicalframed]% + {\vpack{\box\b_chem_result\vss}}} % remove depth + +\aliased\let\startstructurechemical\startchemical +\aliased\let\stopstructurechemical \stopchemical + +\appendtoks + \enforced\let\chemical\structurechemical +\to\everystructurechemical + +\permanent\tolerant\protected\def\structurechemical[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \expandafter\strc_chem_indeed_three + \else + \expandafter\strc_chem_indeed_two + \fi[#1][#2][#3]} + +\def\strc_chem_indeed_three[#1][#2][#3]% + {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored + \clf_chemicalcomponent + {#2}% + {\detokenize{#3}}% + {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points + {\chemicalparameter\c!rulecolor}% + \relax + \ignorespaces} + +\def\strc_chem_indeed_two[#1][#2]% why no [#3] here + {\clf_chemicalcomponent + {#1}% + {\detokenize{#2}}% + {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points + {\chemicalparameter\c!rulecolor}% + \relax + \ignorespaces} + +\appendtoks + \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}% + \d_chem_width \wd\b_chem_result + \d_chem_height\ht\b_chem_result + \d_chem_depth \dp\b_chem_result +\to \t_chem_every_box + +% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize) + +\appendtoks + \edef\m_bodyfont{\chemicalparameter\c!bodyfont}% + \ifempty\m_bodyfont + \switchtobodyfont[\m_bodyfont]% + \fi + \getvalue{\??chemicalsize\chemicalparameter\c!size}% +% \to \everystructurechemical +\to \everychemical + +\permanent\protected\def\chemicaltoptext#1{\global\settrue\c_chem_some_text\gdef\m_chem_top_text{#1}\ignorespaces} +\permanent\protected\def\chemicalbottext#1{\global\settrue\c_chem_some_text\gdef\m_chem_bot_text{#1}\ignorespaces} +\permanent\protected\def\chemicalmidtext#1{\global\settrue\c_chem_some_text\gdef\m_chem_mid_text{#1}\ignorespaces} + +\appendtoks + \enforced\let\toptext\chemicaltoptext \glet\m_chem_top_text\empty + \enforced\let\bottext\chemicalbottext \glet\m_chem_bot_text\empty + \enforced\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\chemicaltop {\chem_top_construct \hss \hss } +\permanent\protected\def\chemicallefttop {\chem_top_construct \relax\hss } +\permanent\protected\def\chemicalrighttop {\chem_top_construct \hss \relax} +\permanent\protected\def\chemicalbottom {\chem_bottom_construct\hss \hss } +\permanent\protected\def\chemicalleftbottom {\chem_bottom_construct\relax\hss } +\permanent\protected\def\chemicalrightbottom{\chem_bottom_construct\hss \relax} + +\permanent\protected\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}} +\permanent\protected\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}} +\permanent\protected\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}} +\permanent\protected\def\chemicalbottomright#1{\chemicalright{\chemicalleftbottom {#1}{}}} + +% \protected\def\chemicalcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1\hss}} +% \protected\def\chemicalleftcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut #1\hss}} +% \protected\def\chemicalrightcentered#1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1}} + +% \let\chemicalsmashedmiddle\chemicalcentered +% \let\chemicalsmashedleft \chemicalleftcentered +% \let\chemicalsmashedright \chemicalrightcentered + +\permanent\protected\def\chemicalalignedtext + {\ifmmode + \expandafter\chem_aligned_text_math + \else + \expandafter\chem_aligned_text_text + \fi} + +\aliased\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} + +\permanent\protected\def\chemicalcentered {\chemicalalignedtext\hss \hss } +\permanent\protected\def\chemicalleftcentered {\chemicalalignedtext\relax\hss } +\permanent\protected\def\chemicalrightcentered{\chemicalalignedtext\hss \relax} + +\aliased\let\chemicalsmashedmiddle\chemicalcentered +\aliased\let\chemicalsmashedleft \chemicalleftcentered +\aliased\let\chemicalsmashedright \chemicalrightcentered + +\permanent\protected\def\chemicaloxidation#1#2#3% + {\chemicaltop{\txx\ifcase#2\relax0\else#1\convertnumber{I}{#2}\fi}{#3}} + +\permanent\protected\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed! +\permanent\protected\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed! +\permanent\protected\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed! +\permanent\protected\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed! +\permanent\protected\def\chemicaloxidationone {\chemicaloxidation\relax1} +\permanent\protected\def\chemicaloxidationtwo {\chemicaloxidation\relax2} +\permanent\protected\def\chemicaloxidationthree{\chemicaloxidation\relax3} +\permanent\protected\def\chemicaloxidationfour {\chemicaloxidation\relax4} +\permanent\protected\def\chemicaloxidationfive {\chemicaloxidation\relax5} +\permanent\protected\def\chemicaloxidationsix {\chemicaloxidation\relax6} +\permanent\protected\def\chemicaloxidationseven{\chemicaloxidation\relax7} + +\permanent\protected\def\chemicalbar + {\hpack \s!spread .5\emwidth \bgroup + \hss + \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight + \hss + \egroup} + +\appendtoks + \enforced\let |\chemicalbar % \SR{N|NH} + \enforced\let \+\chemicaloxidationplus + \enforced\let \-\chemicaloxidationminus + \enforced\let \[\chemicalforeveropen + \enforced\let \]\chemicalforeverclose + \enforced\let \1\chemicaloxidationone + \enforced\let \2\chemicaloxidationtwo + \enforced\let \3\chemicaloxidationthree + \enforced\let \4\chemicaloxidationfour + \enforced\let \5\chemicaloxidationfive + \enforced\let \6\chemicaloxidationsix + \enforced\let \7\chemicaloxidationseven + \enforced\let \X\chemicaltighttext + \enforced\let \T\chemicaltop + \enforced\let \B\chemicalbottom + \enforced\let \L\chemicalleft + \enforced\let\LC\chemicalleftcentered + \enforced\let \R\chemicalright + \enforced\let\RC\chemicalrightcentered + \enforced\let\TL\chemicaltopleft + \enforced\let\BL\chemicalbottomleft + \enforced\let\TR\chemicaltopright + \enforced\let\BR\chemicalbottomright + \enforced\let\LT\chemicallefttop + \enforced\let\LB\chemicalleftbottom + \enforced\let\RT\chemicalrighttop + \enforced\let\RB\chemicalrightbottom + \enforced\let\SL\chemicalsmashedleft + \enforced\let\SM\chemicalsmashedmiddle + \enforced\let\SR\chemicalsmashedright +\to \everychemical + +% Should these also be defined in lower case, so as to be case independent? + +\appendtoks + \the\everychemical +\to \everystructurechemical + +% inline + +\permanent\protected\def\chemical + {\ifinformula + \expandafter\indisplaychemical + \else + \expandafter\inlinechemical + \fi} + +\permanent\protected\def\indisplaychemical + {\mathstylecommand\displaychemical\inlinechemical\inlinechemical} + +% \permanent\protected\def\inlinechemical#1% +% {\dontleavehmode +% \begingroup +% \scratchcounter\normalmathstyle +% \usechemicalstyleandcolor\c!style\c!color +% \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\clf_inlinechemical{#1}}}% +% \endgroup} + +\permanent\tolerant\protected\def\displaychemical#=#=#=% + {\the\everychemical + \everychemical\emptytoks + \quad + \vcenter\bgroup + \usechemicalstyleandcolor\c!style\c!color + \ifparameter#3\or + \ifparameter#2\or + \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} + +\permanent\protected\def\inlinechemical#1% + {\dontleavehmode + \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}} + +\permanent\protected\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}] + +\permanent\protected\def\chemicalsinglebond {\chemicalsymbol[i:single]} +\permanent\protected\def\chemicaldoublebond {\chemicalsymbol[i:double]} +\permanent\protected\def\chemicaltriplebond {\chemicalsymbol[i:triple]} +\permanent\protected\def\chemicalgives {\chemicalsymbol[i:gives]} +\permanent\protected\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]} +\permanent\protected\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]} +\permanent\protected\def\chemicalplus {\chemicalsymbol[i:plus]} +\permanent\protected\def\chemicalminus {\chemicalsymbol[i:minus]} +\permanent\protected\def\chemicalequals {\chemicalsymbol[i:equals]} +\permanent\protected\def\chemicalspace {\chemicalsymbol[i:space]} +\permanent\protected\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 + +\permanent\protected\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 + \enforced\let\chemical\formulachemical + \setfalse\c_chem_has_top + \setfalse\c_chem_has_bot} + +\permanent\protected\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]}] + +\permanent\tolerant\protected\def\formulachemical#=#=#=% + {\relax + \ifarguments\or + \chem_formula_top_nop + \chem_formula_bot_nop + \or + \chem_formula_top_nop + \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}% + \or + \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}% + \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}% + \fi + \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname + \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}% + \else + \toksapp\t_chem_mid{\molecule{#1}\aligntab}% + \fi} + +\def\chem_formula_mid#1% + {\csname\??chemicalsymbol\detokenize{#1}\endcsname} + +\def\chem_formula_top_nop {\toksapp\t_chem_top{\aligntab}} +\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}} +\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} +\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot} + +\def\chem_formula_top_indeed#1{\strut#1} +\def\chem_formula_bot_indeed#1{\strut#1} + +% Experimental: defaults might change. + +\definefloat + [\v!chemical] + [\v!chemicals] + +\setuplabeltext + [\v!chemical=] + +\setupfloat + [\v!chemical] + [\c!location=\v!here, + \c!inner=\hsize.8\textwidth\dontleavehmode, % brr + \c!align={\v!flushleft,\v!lohi}] + +\setupcaption + [\v!chemical] + [\c!location=\v!right, + \c!distance=\zeropoint, + \c!width=.2\textwidth, + \c!align=\v!flushright] + +% Can be used as for displayed math: \startplaceformula... to display a chemical formula +% or a chemical structure: +% +% \startplacechemical +% \startchemicalformula +% \chemical{2H_2} +% \chemical{PLUS} +% \chemical{O_2} +% \chemical{GIVES} +% \chemical{2H_2O} +% \stopchemicalformula +% \stopplacechemical + +% gone: state option resolution offset (now frame offset) alternative + +\setupchemicalframed + [\c!align=\v!normal, + \c!strut=\v!no, + \c!offset=\v!overlay, + \c!frame=\v!off] + +\definecolor % private color + [chemicalframecolor] + [r=.75,g=.85,b=.95] + +\setupchemical + [\c!frame=, + \c!width=\v!fit, % or unitless number, multiplies scale*unit + \c!height=\v!fit, % or unitless number, multiplies scale*unit + \c!left=\v!fit, % or unitless number, multiplies scale*unit + \c!right=\v!fit, % or unitless number, multiplies scale*unit + \c!top=\v!fit, % or unitless number, multiplies scale*unit + \c!bottom=\v!fit, % or unitless number, multiplies scale*unit + \c!bodyfont=, + \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies unit) + \c!size=\v!medium, + \c!textsize=\v!big, % how is textsize used?? + \c!axis=\v!off, + \c!style=\rm, + \c!rotation=0, % unitless number (interpreted as degrees) + \c!symalign=\v!auto, + \c!location=, % not yet used (was interaction related in mkii) + \c!offset=.25\emwidth, + \c!unit=\emwidth, + \c!factor=3, + \c!color=, + \c!strut=\v!yes, + \c!framecolor=chemicalframecolor, + \c!rulethickness=0.6pt, %1.5\linewidth, + \c!rulecolor=] + +%D Compatibility: + +\definechemical[+R] {\chemical[RR]} +\definechemical[-R] {\chemical[LR]} + +\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]} +\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]} +\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]} +\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]} + +\definechemical[NEWMAN] {\chemical[]} +\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]} +\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]} +\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]} +\definechemical[SIX:FRONT] {\chemical[SIXFRONT]} +\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]} + +\protect \endinput diff --git a/tex/context/base/mkxl/cldf-bas.mkxl b/tex/context/base/mkxl/cldf-bas.mkxl new file mode 100644 index 000000000..962db5209 --- /dev/null +++ b/tex/context/base/mkxl/cldf-bas.mkxl @@ -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}{} +\registerctxluafile{cldf-prs}{} + +\endinput diff --git a/tex/context/base/mkxl/cldf-com.mkxl b/tex/context/base/mkxl/cldf-com.mkxl new file mode 100644 index 000000000..7a8f7bf5c --- /dev/null +++ b/tex/context/base/mkxl/cldf-com.mkxl @@ -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}{} +%registerctxluafile{cldf-ver}{} + +\endinput diff --git a/tex/context/base/mkxl/cldf-ini.mkxl b/tex/context/base/mkxl/cldf-ini.mkxl new file mode 100644 index 000000000..b393eb9b5 --- /dev/null +++ b/tex/context/base/mkxl/cldf-ini.mkxl @@ -0,0 +1,45 @@ +%D \module +%D [ file=cldf-int, +%D version=2019.01.01, +%D title=\CONTEXT\ Data Macros, +%D subtitle=Integer, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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} + +\newcount\trialtypesettingstate % gets aliased at the Lua end + +\registerctxluafile{cldf-ini}{autosuffix} + +%D With each new update of \MKIV\ we can join Within Temptation in 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: + +% \catcode`=\activecatcode \let\luafunction % saves 10% on the call + +% todo: these can become implementers + +\permanent\protected\def\cldprocessfile#1{\directlua{context.runfile("#1")}} +\permanent \def\cldloadfile #1{\directlua{context.loadfile("#1")}} +\permanent \def\cldloadviafile#1{\directlua{context.loadviafile("#1")}} +\permanent \def\cldcontext #1{\directlua{context(#1)}} +\permanent \def\cldcommand #1{\directlua{context.#1}} + +\endinput diff --git a/tex/context/base/mkxl/cldf-int.lmt b/tex/context/base/mkxl/cldf-int.lmt new file mode 100644 index 000000000..4f486221b --- /dev/null +++ b/tex/context/base/mkxl/cldf-int.lmt @@ -0,0 +1,252 @@ +if not modules then modules = { } end modules ['cldf-int'] = { + version = 1.001, + comment = "companion to cldf-int.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 byte = string.byte +local insert, remove, concat = table.insert, table.remove, table.concat +local unpack, type = unpack or table.unpack, type + +local ctxcatcodes = catcodes.numbers.ctxcatcodes +local context = context +local contextsprint = context.sprint + +local trace_define = false trackers.register("context.define", function(v) trace_define = v end) + +interfaces = interfaces or { } +local implement = interfaces.implement +local estart = interfaces.elements.start +local estop = interfaces.elements.stop + +local scanners = tokens.scanners +local shortcuts = tokens.shortcuts + +local peekchar = scanners.peekchar +local scankey = scanners.key +local scanvalue = scanners.value +local scanskip = scanners.skip + +local open = byte('[') +local close = byte(']') +local equal = byte('=') +local comma = byte(',') + +function scanhash(scanners) + if peekchar() == open then + local data = { } + scanskip() + while true do + local c = peekchar() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local key = scankey(equal) + if key then + if peekchar() == equal then + scanskip() + if scanners then + local scanner = scanners[key] + if scanner then + data[key] = scanner() + else + data[key] = scanvalue(comma,close) or "" + end + else + data[key] = scanvalue(comma,close) or "" + end + else + break + end + else + break + end + end + end + return data + end +end + +function scanarray() + if peekchar() == open then + local data = { } + local d = 0 + scanskip() + while true do + local c = peekchar() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local v = scanvalue(comma,close) or "" + d = d + 1 + data[d] = v + end + end + return data + end +end + +shortcuts.scanhash = scanhash +shortcuts.scanarray = scanarray + +scanners.hash = scanhash +scanners.array = scanarray + +local function remap(arguments) + -- backward compatibility + if type(arguments) == "table" then + for i=1,#arguments do + local a = arguments[i] + if type(a) == "table" then + local t = a[2] + arguments[i] = t == "list" and "array" or t + end + end + return arguments + end +end + +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 environment = specification.environment + local arguments = remap(specification.arguments) + if environment then + local starter = specification.starter + local stopper = specification.stopper + if starter and stopper then + implement { + name = estart .. name, + arguments = arguments, + public = true, + protected = true, + actions = starter, + } + implement { + name = estop .. name, + public = true, + protected = true, + actions = stopper, + } + else + -- message + end + end + if not environment or environment == "both" then + local macro = specification.macro + if macro then + implement { + name = name, + arguments = arguments, + public = true, + protected = true, + actions = macro, + } + else + -- message + end + end + else + -- message + end +end + +function interfaces.tolist(t) + if t then + 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,", ") + else + return "" + end +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() +-- context.stopnarrower() +-- context("stop more") +-- 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 +-- +-- More modern (no need for option or content): +-- +-- \startluacode +-- interfaces.definecommand { +-- name = "test", +-- arguments = { +-- "array", -- or list +-- "hash", +-- "string", +-- "number", +-- }, +-- macro = test, +-- } +-- \stopluacode +-- diff --git a/tex/context/base/mkxl/cldf-int.mkxl b/tex/context/base/mkxl/cldf-int.mkxl new file mode 100644 index 000000000..a564afc80 --- /dev/null +++ b/tex/context/base/mkxl/cldf-int.mkxl @@ -0,0 +1,34 @@ +%D \module +%D [ file=cldf-int, +%D version=2019.01.01, +%D title=\CONTEXT\ Data Macros, +%D subtitle=Integer, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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}{autosuffix} + +%D These are user commands so we don't add any protection against overloading +%D here. + +\unprotect + +\permanent\protected\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}} +\permanent\protected\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}} + +\installcorenamespace{datavalue} + +\permanent\protected\def\setdatavalue#1#2% #2 is a number (expression) + {\expandafter\integerdef\csname\??datavalue#1\endcsname\numexpr#2\relax} + +\permanent\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname} +\permanent\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname} + +\protect \endinput diff --git a/tex/context/base/mkxl/cldf-lmt.lmt b/tex/context/base/mkxl/cldf-lmt.lmt new file mode 100644 index 000000000..f3121eadc --- /dev/null +++ b/tex/context/base/mkxl/cldf-lmt.lmt @@ -0,0 +1,949 @@ +if not modules then modules = { } end modules ['cldf-lmt'] = { + version = 1.001, + comment = "companion to toks-scn.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local next, load = next, load +local gmatch, gsub, byte = string.gmatch, string.gsub, string.byte + +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local serialize = table.serialize +local concat = table.concat + +local random = math.random +local randomseed = math.randomseed +local round = math.round +local abs = math.abs + +local implement = interfaces.implement + +local scanners = tokens.scanners +local scanword = scanners.word +local scanstring = scanners.string +local scanboolean = scanners.boolean +local scandimen = scanners.dimen +local scanfloat = scanners.float +local scaninteger = scanners.integer +local scancardinal = scanners.cardinal +local scannumber = scanners.luanumber +local scanluainteger = scanners.luainteger +local scanluacardinal = scanners.luacardinal +local scanluanumber = scanners.luanumber +local scanargument = scanners.argument +local scantoken = scanners.token +local scancsname = scanners.csname +local scankeyword = scanners.keyword + +local peekchar = scanners.peekchar +local skipnext = scanners.skip + +local getindex = token.get_index + +local texsetdimen = tex.setdimen +local texsetcount = tex.setcount +local texgetcount = tex.getcount +local texget = tex.get + +local values = tokens.values +local none_code = values.none +local integer_code = values.integer +local cardinal_code = values.cardinal +local dimension_code = values.dimension +local skip_code = values.skip +local boolean_code = values.boolean +local float_code = values.float + +local global_code = tex.flagcodes.global + +local context = context + +-- variables -- + +local floats = { } +local integers = { } +local cardinals = { } +local numbers = { } + +implement { + name = "luafloat", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + context("%.99g",floats[n] or 0) + else + floats[n] = scanluanumber(true) + -- floats[n] = scanfloat(true) + end + end, +} + +implement { + name = "luainteger", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + context("%i",integers[n] or 0) + else + integers[n] = scanluainteger(true) + end + end, +} + +implement { + name = "luacount", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + return integer_code, integers[n] or 0 + else + integers[n] = scaninteger(true) + end + end, +} + +implement { + name = "luadimen", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + return dimension_code, integers[n] or 0 + else + integers[n] = scandimen(false,false,true) + end + end, +} + +implement { + name = "luacardinal", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + context("%1.0f",cardinals[n] or 0) + else + cardinals[n] = scanluacardinal(true) + end + end, +} + +implement { + name = "luanumber", + public = true, + usage = "value", + actions = function(b) + local n = scanword() + if b == "value" then + context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N + else + -- floats[n] = scanfloat(true) + floats[n] = scanluanumber(true) + end + end, +} + +implement { + name = "luarandom", + public = true, + usage = "value", + actions = function(b) + if b == "value" then + return integer_code, random(scanluainteger(),scanluainteger()) + else + randomseed(scanluainteger(true)) + end + end, +} + +interfaces.floats = floats +interfaces.integers = integers +interfaces.cardinals = cardinals + +interfaces.numbers = table.setmetatableindex(function(t,k) + return floats[k] or integers[k] or cardinals[k] +end) + +-- arrays -- + +local arrays = { } + +interfaces.arrays = arrays + +local newindex = lua.newindex + +implement { + name = "newarray", + public = true, + protected = true, + arguments = { { + { "name", "string" }, + { "nx", "integer" }, + { "ny", "integer" }, + { "type", "string" }, + } }, + actions = function(t) + local name = t.name + if t.name then + local nx = t.nx + local ny = t.ny + local ty = t.type or "integer" + local df = nil + if ty == "integer" or ty == "float" or ty == "dimension" then + df = 0 + elseif ty == "boolean" then + df = false + else + ty = nil + end + if nx and ty ~= nil then + local data + if ny then + data = newindex(t.ny) + for i=1,ny do + data[i] = newindex(nx,df) + end + else + data = newindex(nx,df) + end + arrays[name] = data + data.nx = nx + data.ny = ny + data.type = ty + if ty == "integer" then + data.scanner = scaninteger + elseif ty == "boolean" then + data.scanner = scanboolean + elseif ty == "dimension" then + data.scanner = scandimen + elseif ty == "float" then + data.scanner = scanfloat + end + if ty == "integer" then + data.code = integer_code + elseif ty == "boolean" then + data.code = boolean_code + elseif ty == "dimension" then + data.code = dimension_code + elseif ty == "float" then + data.code = float_code + end + end + end + end, +} + +implement { + name = "arrayvalue", + public = true, + usage = "value", + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + local code = a.code + if code == float_code then + context("%.99g",d[x]) + else + return code, d[x] + end + else + d[x] = a.scanner() + end + end + end + end, +} + +implement { + name = "arrayequals", + public = true, + usage = "value", + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + return boolean_code, a.scanner() == d[x] + end + end + end + end, +} + +implement { + name = "arraycompare", + public = true, + usage = "value", + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + local v = a.scanner() + local d = d[x] + if d < v then + return integer_code, 0 + elseif d == v then + return integer_code, 1 + else + return integer_code, 2 + end + end + end + end + end, +} + +implement { + name = "showarray", + public = true, + protected = true, + actions = function() + local name = scanstring() + if name then + inspect(arrays[name]) + end + end, +} + +-- expressions -- + +local cache = table.setmetatableindex(function(t,k) + local code = "return function() local n = interfaces.numbers local a = interfaces.arrays return " .. k .. " end" + code = loadstring(code) + if code then + code = code() + end + t[k] = code or false + return code +end) + +table.makeweak(cache) + +implement { + name = "luaexpression", + public = true, + actions = function() + local how = scanword() + local code = cache[scanargument()] + if code then + local result = code() + if result then + if not how then + context(tostring(code())) + elseif how == "float" then + context("%.99g",result) + elseif how == "integer" then + context("%i",round(result)) + elseif how == "cardinal" then + context("%d",abs(round(result))) + elseif how == "dimen" then + context("%p",result) + elseif how == "boolean" then + context("%d",result and 1 or 0) + elseif how == "lua" then + context("%q",result) + else + context(tostring(code())) + end + end + end + end +} + +local dimenfactors = number.dimenfactors + +implement { + name = "nodimen", + public = true, + usage = "value", + actions = function(b) + if b == "value" then + local how = scanword() + local what = scandimen() + if how then + local factor = dimenfactors[how] + if factor then + context("%.6N%s",factor*what,how) + else + return dimension_code, what + end + else + return dimension_code, what + end + else + local t = scantoken() + if t then + local i = getindex(t) + if i then + local d = scandimen(false,false,true) + texsetdimen(i,d) + end + end + end + end, +} + +-- experimental: + +local grouped = { } +local slots = { } +local nofslots = 0 +local nofgrouped = 0 + +local getinteger = tokens.getinteger +local setinteger = tokens.setinteger + +local report = logs.reporter("lua table") + +local ctxsprint = context.sprint + +-- we could have an extra one that collects all end of grouped actions +-- so that we dispose more in one go but it doesn's pay off + +local function newluatable(name,mt,dispose) + local g = { } + local t = slots[nofslots] + slots[nofslots] = false + nofslots = nofslots - 1 + if not t then + nofgrouped = nofgrouped + 1 + t = nofgrouped + end + if mt then + mt = getinteger(name) + if mt then + mt = grouped[mt] + if mt then + setmetatableindex(g,mt) + end + end + end + grouped[t] = g + setinteger(name,t) + -- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll + -- think of something that we can set it at the Lua end. + if dispose then + ctxsprint("\\atendofgrouped{\\disposeluatable\\" .. name .. "}") + end +end + +local function disposeluatable(name) + local t = getinteger(name) + local g = grouped[t] + if g then + grouped[t] = false + nofslots = nofslots + 1 + slots[nofslots] = t + end +end + +local function setluatable(name,kv) + local t = getinteger(name) + local g = grouped[t] + if g and kv then + for k, v in next, kv do + g[k] = v + end + end +end + +local function getfromluatable(name,k) + local t = getinteger(name) + local g = grouped[t] + if g then + local v = g[k] + if v then + context(v) + else + local n = tonumber(k) + if n then + local v = g[n] + if v then + context(v) + end + end + end + end +end + +local function idxfromluatable(name,k) + local t = getinteger(name) + local g = grouped[t] + if g then + local v = g[k] + if v then + context(v) + end + end +end + +local function getluatable(name,k) + local t = getinteger(name) + local g = grouped[t] + if g then + return g + end +end + +local function inspectluatable(name) + local t = getinteger(name) + local g = grouped[t] + if g then + report("%s", serialize(g,'[grouped slot ' .. t .. ']')) + end +end + +local function showluatables() + report("nofgrouped %i, nofslots %i",nofgrouped,nofslots) + for t=1,nofgrouped do + local g = grouped[t] + if g then + report("%s", serialize(g,'[grouped slot ' .. t .. ']')) + end + end +end + +implement { + name = "newluatable", + protected = true, + arguments = "csname", + actions = newluatable, +} + +implement { + name = "useluatable", + protected = true, + arguments = { "csname", true }, + actions = newluatable, +} + +implement { + name = "disposeluatable", + protected = true, + public = true, + arguments = "csname", + actions = disposeluatable, +} + +implement { + name = "inspectluatable", + protected = true, + public = true, + arguments = "csname", + actions = inspectluatable, +} + +implement { + name = "showluatables", + protected = true, + public = true, + actions = showluatables, +} + +implement { + name = "setluatable", + protected = true, + public = true, + arguments = { "csname", "argument" }, + actions = function(name,data) + data = load("return {" .. data .. "}") + if data then + data = data() + if data then + setluatable(name,data) + end + end + end +} + +implement { + name = "getfromluatable", + protected = false, + public = true, + arguments = { "csname", "argument" }, + actions = getfromluatable, +} + +implement { + name = "idxfromluatable", + protected = false, + public = true, + arguments = { "csname", "integer" }, + actions = idxfromluatable, +} + +context.luatables = { + new = function(name) newluatable(name,false,true) end, + use = function(name) useluatable(name,true, true) end, + dispose = disposeluatable, + set = setluatable, + get = getluatable, + getfrom = getfromluatable, + idxfrom = idxfromluatable, + inspect = inspectluatable, + show = showluatables, +} + +-- Here's another mechanism ... + +local tables = { } +local stack = setmetatableindex("table") + +interfaces.implement { + name = "droptablegroup", + public = true, + actions = function() + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + if s then + for t, data in next, s do + for k, v in next, data do + t[k] = v + end + end + stack[g] = { } + end + end, +} + +local ctx_atendofgroup = context.core.cs.atendofgroup +local ctx_droptablegroup = context.core.cs.droptablegroup + +local function handletable(t,b,array) + if b == "value" then + local k = array and scaninteger() or scanargument() + local v = t[k] + if v then + context(v) + end + else + local data = scanargument() + data = load("return {" .. data .. "}") + if data then + data = data() + if data then + local l = t.level + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + local d = s[t] + if not d then + d = { } + s[t] = d + ctx_atendofgroup() + ctx_droptablegroup() + end + for k, v in next, data do + if not d[k] then + d[k] = t[k] + end + t[k] = v + end + -- if b == "global" then + if b and (b & 0x04) ~= 0 then -- or just band(b,0x04) + for k, v in next, stack do + local t = s[t] + if t then + for k, v in next, data do + if t[k] then + t[k] = nil + end + end + end + end + end + end + end + end +end + +local function newtable(array) + local name = scancsname(true) + if not tables[name] then + local t = { } + tables[name] = t + interfaces.implement { + name = name, + public = true, + usage = "value", + actions = function(b) + handletable(t,b,array) + end, + } + else + -- already defined + end +end + +implement { + name = "newhashedtable", + protected = true, + public = true, + actions = newtable, +} + +implement { + name = "newindexedtable", + protected = true, + public = true, + actions = function() newtable(true) end, +} + +context.hashedtables = setmetatableindex(function(t,k) return tables[k] end) +context.indexedtables = context.hashedtables + +-- I played with adding bitwise operator to the expr scanners but in the end didn't +-- keep the code ... the problem is in what symbols ... so for now a more verbose +-- and/or/xor is okay. Extending the expression scanner would add a little overhead +-- to all expressions while an logical operator would gain less that 50% so for now +-- we don't bother. Providing \ifbitwiseand makes sense for performance reasons as +-- if a bit beter than testing the bitwise and with an \ifcase. + +local reporterror = logs.texerrormessage + +local function youcant(cmd) + reporterror("you can't use \\%s this way, it's an integer value", cmd) +end + +implement { + name = "bitwiseset", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + if what == "value" then + return cardinal_code, a + else + youcant("bitwiseset") + end + end +} + +implement { + name = "bitwiseand", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + scankeyword("with") + local b = scancardinal() + if what == "value" then + return cardinal_code, a & b + else + youcant("bitwiseand") + end + end +} + +implement { + name = "bitwiseor", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + scankeyword("with") + local b = scancardinal() + if what == "value" then + return cardinal_code, a | b + else + youcant("bitwiseor") + end + end +} + +implement { + name = "bitwisexor", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + scankeyword("with") + local b = scancardinal() + if what == "value" then + return cardinal_code, a ~ b + else + youcant("bitwisexor") + end + end +} + +implement { + name = "bitwisenot", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + if what == "value" then + return cardinal_code, ~a & 0xFFFFFFFF + else + youcant("bitwisenot") + end + end +} + +implement { + name = "bitwisenil", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + scankeyword("with") + local b = scancardinal() + if what == "value" then + return cardinal_code, a & (~b & 0xFFFFFFFF) + else + youcant("bitwisenil") + end + end +} + +implement { + name = "bitwiseshift", + public = true, + usage = "value", + actions = function(what) + local a = scancardinal() + scankeyword("by") + local b = scaninteger() + if what == "value" then + return cardinal_code, (b < 0) and (a << -b) or (a >> b) + else + youcant("bitwiseshift") + end + end +} + +implement { + name = "bitwiseflip", + public = true, + usage = "value", + actions = function(what) + local t = scancsname() + local b = scaninteger() + local c = texgetcount(t) + if c then + if b > 0 then + c = c | b + elseif b < 0 then + c = c & (~(-b) & 0xFFFFFFFF) + end + if what == "value" then + return cardinal_code, c + elseif what and (what & global_code) ~= 0 then + texsetcount("global",t,c) + else + texsetcount(t,c) + end + end + end +} + +implement { + name = "ifbitwiseand", + public = true, + usage = "condition", + actions = function(what) + local a = scancardinal() + local b = scancardinal() + return boolean_code, (a & b) ~= 0 + end +} + +interfaces.implement { + name = "bitwise", + public = true, + usage = "value", + actions = function(what) + if what == "value" then + local b = 0 + while true do + local c = peekchar() + if c == 48 or c == 49 then + skipnext() + b = (b << 1) + (c - 48) + if b == 0xFFFFFFFF then + break + end + else + break + end + end + return 1, b + else + local b = scancardinal() + local t = nil + local n = 0 + for i=1,32 do + if (b & (0x100000000 >> i)) == 0 then + if n > 0 then + n = n + 1 + t[n] = "0" + end + elseif t then + n = n + 1 + t[n] = "1" + else + n = 1 + t = { "1" } + end + end + context(n > 0 and table.concat(t) or "0") + end + end, +} + +-- something to play with, this might move to syst-aux.lmt when we have that + +local escape = function(s) return "\\" .. byte(s) end + +interfaces.implement { + name = "ctxluamatch", + public = true, + usage = "value", + actions = function() + local command = context[scancsname()] + local pattern = gsub(scanstring(),"\\.",escape) + local input = gsub(scanstring(),"\\.",escape) + for a, b, c, d, e, f, g, h, i in gmatch(input,pattern) do + command(a, b or "", c or "", d or "", e or "", f or "", g or "", h or "", i or "") + end + return none_code + end, +} diff --git a/tex/context/base/mkxl/cldf-ver.mkxl b/tex/context/base/mkxl/cldf-ver.mkxl new file mode 100644 index 000000000..0ff63810e --- /dev/null +++ b/tex/context/base/mkxl/cldf-ver.mkxl @@ -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}{} + +\endinput diff --git a/tex/context/base/mkxl/colo-ext.mkxl b/tex/context/base/mkxl/colo-ext.mkxl new file mode 100644 index 000000000..df2d9d768 --- /dev/null +++ b/tex/context/base/mkxl/colo-ext.mkxl @@ -0,0 +1,99 @@ +%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 devices, we want to reverse +%D the color scheme. Instead of recalculating all those colors, we use a quick and +%D dirty approach: +%D +%D \starttyping +%D \negativecolorbox0 +%D \stoptyping +%D +%D will negate the colors in box zero. + +\permanent\protected\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 or +%D independent. For the moment we only support independent overprint handling. Here +%D we deal with a per-document setting. + +%D We can move the stack and attribute setting to the \LUA\ end. + +\installcorenamespace{colorintent} + +\permanent\protected\def\registercolorintent#1#2% \relax is needed ! + {\setevalue{\??colorintent#1}{\c_attr_colorintent\clf_registercolorintent{#2}\relax}} + +\protected\def\colo_intents_set + {\clf_enablecolorintents + \protected\gdef\colo_intents_set##1{\csname\??colorintent##1\endcsname}% + \colo_intents_set} + +\registercolorintent{knockout} {knockout} +\registercolorintent{overprint}{overprint} + +\installattributestack\colorintentattribute + +\setevalue{\??colorintent\v!none}{\c_attr_colorintent\attributeunsetvalue} % or reset? used at all? + +\permanent\protected\def\startcolorintent[#1]% + {\pushattribute\colorintentattribute + \colo_intents_set{#1}} + +\permanent\protected\def\stopcolorintent + {\popattribute\colorintentattribute} + +\permanent\protected\def\startoverprint{\startcolorintent[\v!overprint]} +\permanent\protected\def\startknockout {\startcolorintent[\v!knockout ]} + +\aliased\let\stopoverprint\stopcolorintent +\aliased\let\stopknockout \stopcolorintent + +\aliased\let\starttextcolorintent\relax +\aliased\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 + \enforced\protected\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/tex/context/base/mkxl/colo-grp.mkxl b/tex/context/base/mkxl/colo-grp.mkxl new file mode 100644 index 000000000..82dd67959 --- /dev/null +++ b/tex/context/base/mkxl/colo-grp.mkxl @@ -0,0 +1,163 @@ +%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 which is why we +%D 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 ordening, which in turn is +%D 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 defining each color +%D separate, it also loads faster and takes less bytes. + +\installcorenamespace{colorgroup} +\installcorenamespace{colorgroupsetter} + +\newcount\c_colo_groups_n % scratch counter + +\permanent\tolerant\protected\def\definecolorgroup[#1]#*[#2]#*[#3]% % sort of obsolete, just use palets directly + {\ifarguments\or\or + \ifhastok:{#2}% + \colo_groups_define_normal[#1][\v!rgb][#2] + \else + \colo_groups_define_checked[#1][#2][]% + \fi + \else + \colo_groups_define_normal[#1][#2][#3]% + \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]% + {\doloop % inherited + {\ifcsname#2:##1\endcsname + \definecolor[#1:##1][#2:##1]% + \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!colo_run + +%D There are ten predefined color groups, like \color [green] {\em groen}, \color +%D [red] {\em rood}, \color [blue] {\em blauw}, \color [cyan] {\em cyaan}, \color +%D [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 zeta}. As long as we +%D don't use colors from the same row, we get ourselves distinctive palets. By +%D activating such a palet one gains access to its members {\em top} to {\em charm} +%D (of 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 components are shown too. +%D When printed in color, these 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!colo_run + +\protect \endinput diff --git a/tex/context/base/mkxl/colo-ini.mkxl b/tex/context/base/mkxl/colo-ini.mkxl new file mode 100644 index 000000000..15cedb51d --- /dev/null +++ b/tex/context/base/mkxl/colo-ini.mkxl @@ -0,0 +1,1383 @@ +%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. + +\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. + +\installcorenamespace{color} +\installcorenamespace{colorattribute} +\installcorenamespace{transparencyattribute} +\installcorenamespace{colorsetter} +\installcorenamespace{transparencysetter} +\installcorenamespace{colorpaletspecification} +\installcorenamespace{colorpalet} +\installcorenamespace{colorstack} +\installcorenamespace{colorconversions} +\installcorenamespace{colornumber} + +\registerctxluafile{colo-ini}{} +\registerctxluafile{colo-icc}{} + +\unprotect + +%D In \MKIV\ we have independent color, colorspace and transparency but I'm still +%D not sure if I keep it that way as it's probably more efficient to combine them +%D (less attributes and finalizing). If it becomes a bottleneck we can set up a more +%D complex system with one shared attribute for colorspace, color and transparency. +%D +%D When typesetting for paper, we prefer using the \CMYK\ color space, but for +%D on||screen viewing we prefer \RGB\ (the previous implementation supported only +%D this scheme). Independant of such specifications, we support some automatic +%D 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_convert_gray \settrue\c_colo_convert_gray +\newconditional\c_colo_enabled +\newconditional\c_colo_expanded + +\let\m_colo_weight_gray\v!yes + +\let\currentcolormodel \empty +\let\currentcolorname \empty +\let\currentcolorpalet \empty +\let\currentcolorprefix\empty % \currentcolorpalet: + +%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 + +\permanent\protected\def\loadfoundcolorsetfile#1#2% name foundname / not a user command + {\startreadingfile + \startcolorset[#1]% + \input{#2}% + \stopcolorset + \showmessage\m!colors4{#1}% + \stopreadingfile} + +%D \macros +%D {startcolor,stopcolor,color,graycolor} +%D +%D The local and global commands are here just for compatibility 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 + +\permanent\protected\def\switchtocolor[#1]{\begincsname#1\endcsname} + +% transparency + +\permanent\protected\def\transparent[#1]% + {\bgroup + \edef\currenttransparencyname{#1}% + % the \relax catches a non existent csname + \ifx\currenttransparencyname\v!reset + \c_attr_transparency\attributeunsetvalue + \else + \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax + \fi + \let\nexttoken} + +\permanent\protected\def\starttransparent[#1]%$ + {\begingroup + \edef\currenttransparencyname{#1}% + \ifx\currenttransparencyname\v!reset + \c_attr_transparency\attributeunsetvalue + \else + \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax + \fi} + +\permanent\protected\def\stoptransparent + {\endgroup} + +% color + +\permanent\protected\def\coloronly[#1]% + {\bgroup + \edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop_only + \else + \colo_helpers_activate_yes_only + \fi + \let\nexttoken} + +\permanent\protected\def\startcoloronly[#1]%$ + {\begingroup + \edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop_only + \else + \colo_helpers_activate_yes_only + \fi} + +\permanent\protected\def\stopcoloronly + {\endgroup} + +% color + transparency + +\permanent\protected\def\color[#1]% + {\bgroup + \edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop + \else + \colo_helpers_activate_yes + \fi + \let\nexttoken} + +\permanent\protected\def\graycolor[#1]% + {\bgroup + \colo_helpers_set_model\s!gray\colo_helpers_activate{#1}% + \let\nexttoken} + +\permanent\protected\def\startcolor[#1]%$ + {\begingroup + \edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop + \else + \colo_helpers_activate_yes + \fi} + +\permanent\protected\def\stopcolor + {\endgroup} + +\permanent\protected\def\colored[#1]% + {\bgroup + \colo_basics_defined_and_activated{#1}% + \let\nexttoken} + +\permanent\protected\def\fastcolored[#1]#2% + {\begingroup % is this command still needed? + \colo_basics_defined_and_activated{#1}% + #2% + \endgroup} + +\permanent\protected\def\directcolored[#1]% + {\colo_basics_defined_and_activated{#1}} + +\permanent\protected\def\fastcolor[#1]#2% + {\begingroup % is this command still needed? + \edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop + \else + \colo_helpers_activate_yes + \fi + #2% + \endgroup} + +\permanent\protected\def\directcolor[#1]% + {\edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + \colo_helpers_activate_nop + \else + \colo_helpers_activate_yes + \fi} + +%D The following command is obsolete: + +\permanent\protected\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} +\permanent\protected\def\stopcolorpage {\stopcolor} + +\permanent\protected\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ... + {\begingroup + \colo_helpers_activate{#1}% + \normalexpanded{\endgroup\edef\noexpand#2{\ifnum\c_attr_color=\attributeunsetvalue\else\number\c_attr_color\fi}}} + +\let\grey\graycolor % these macros are only used in tracing + +%D \macros +%D {startcurrentcolor,stopcurrentcolor} + +\permanent\protected\def\startcurrentcolor{\startcolor[\outercolorname]} +\permanent\protected\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}, which is loaded into +%D the format by default. +%D +%D Some demo palets and groups are defined in \type {colo-imp-dem} which can be +%D loaded with: +%D +%D \starttyping +%D \usecolors[dem] +%D \stoptyping + +\permanent\protected\def\startcolorset[#1]{\clf_startcolorset{#1}} +\permanent\protected\def\stopcolorset {\clf_stopcolorset} +\permanent\protected\def\usecolors [#1]{\clf_usecolors{#1}} + +\aliased\let\setupcolor\usecolors + +\installsetuponlycommandhandler \??color {colors} + +\let\colo_helpers_show_message\gobblethreearguments + +% \newtoks\everysetupcolors + +\let\v_colo_freeze_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!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 + % + \edef\m_colo_weight_gray{\directcolorsparameter\c!factor}% + % + \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 + +\permanent\protected\def\pushcolor[#1]% + {\global\advance\c_colo_nesting\plusone + \edefcsname\??colorstack\number\c_colo_nesting\endcsname + {\c_attr_colormodel \the\c_attr_colormodel + \c_attr_color \the\c_attr_color + \c_attr_transparency\the\c_attr_transparency + \relax}% stack + \colo_helpers_activate{#1}} + +\permanent\protected\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 + +\permanent\protected\def\savecolor + {\c_colo_saved_attribute_color \c_attr_color + \c_colo_saved_attribute_transparency\c_attr_transparency} + +\permanent\protected\def\restorecolor + {\c_attr_color \c_colo_saved_attribute_color + \c_attr_transparency\c_colo_saved_attribute_transparency} + +%D In this documentation we will not go into too much details on palets. Curious +%D users can find more information on this topic in \from[use of color]. +%D +%D At the moment we implemented color in \CONTEXT\ color printing was not yet on the +%D desktop. In spite of this lack our graphics designer made colorfull +%D illustrations. When printed on a black and white printer, distinctive colors can +%D come out equally gray. We therefore decided to use only colors that were +%D distinctive in colors as well as in black and white print. +%D +%D Although none of the graphic packages we used supported logical colors and global +%D color redefition, we build this support into \CONTEXT. This enabled us to +%D experiment and also prepared us for the future. + +%D \macros +%D {definepalet} +%D +%D Colors are grouped in palets. The colors in such a palet can have colorful names, +%D but best is to use names that specify their use, like {\em important} or {\em +%D danger}. As a sort of example \CONTEXT\ has some palets predefined, +%D like:\footnote{At the time I wrote the palet support, I was reading 'A hort +%D history of time' of S.~Hawkins, so that's 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 palet components (not +%D 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 deal with pretty +%D verbatim typesetting. + +\installcorenamespace{paletlist} +\installcorenamespace{paletsize} + +\let\m_colo_palet\relax +\let\c_colo_palet\relax + +\def\colo_palet_allocate#1% + {\letcsname\??paletlist#1\endcsname\empty + \ifcsname\??paletsize#1\endcsname\else + \expandafter\newcount\csname\??paletsize#1\endcsname + \fi} + +\def\colo_palet_prepare#1% + {\edef\colo_palet_name{#1}% + \ifcsname\??paletlist\colo_palet_name\endcsname + \csname\??paletsize\colo_palet_name\endcsname\zerocount + \else + \colo_palet_allocate\colo_palet_name + \fi + \enforced\expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname + \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}} + +\def\colo_palet_extend#1% + {\addtocommalist{#1}\m_colo_palet + \letcsname\??paletlist\colo_palet_name\endcsname\m_colo_palet + %\advance\csname\??paletsize\colo_palet_name\endcsname\plusone + \advance\c_colo_palet\plusone} + +\permanent\protected\def\doifelsecolorpalet#1% + {\ifcsname\??paletlist#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\mutable\let\paletlist\empty +\mutable\let\paletsize\!!zerocount + +\permanent\protected\def\getpaletlist[#1]% + {\edef\paletlist{\begincsname\??paletlist#1\endcsname}} + +\permanent\protected\def\getpaletsize[#1]% + {\ifcsname\??paletsize#1\endcsname + \edef\paletsize{\the\lastnamedcs}% + \else + \let\paletsize\!!zerocount + \fi} + +\permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreearguments + \or + \expandafter\gobblethreearguments + \or + \expandafter\colo_palets_define_a + \or + \expandafter\colo_palets_define_b + \fi{#1}{#2}{#3}} + +\protected\def\colo_palets_define_a#1#2#3% + {\colo_palet_prepare{#1}% + \ifcondition\validassignment{#2}% + \edefcsname\??colorpaletspecification#1\endcsname{#2}% + \processcommalist[#2]{\colo_palets_define_one{#1}}% + \orelse\ifcsname\??colorpaletspecification#2\endcsname + \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}\empty}% + \fi} + +\protected\def\colo_palets_define_b#1#2#3% + {\colo_palet_prepare{#1}% + \edefcsname\??colorpaletspecification#1\endcsname{#2}% + \colo_palet_extend{#2}% + \colo_palets_define_assign{#1}{#2}{#3}} + +% % or, it being not that critital, just this +% +% \permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% +% {\ifarguments +% \or +% \or +% \colo_palet_prepare{#1}% +% \ifcondition\validassignment{#2}% +% \setevalue{\??colorpaletspecification#1}{#2}% +% \processcommalist[#2]{\colo_palets_define_one{#1}}% +% \orelse\ifcsname\??colorpaletspecification#2\endcsname +% \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}{}}% +% \fi +% \or +% \colo_palet_prepare{#1}% +% \setevalue{\??colorpaletspecification#1}{#2}% +% \colo_palet_extend{#2}% +% \colo_palets_define_assign{#1}{#2}{#3}% +% \fi} + +\def\colo_palets_define_one#1#2% get rid of { } + {\ifcondition\validassignment{#2}% catch empty entries + \colo_palets_define_two{#1}[#2]% + \else + \colo_palets_define_three{#1}{#2}% + \fi} + +\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 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. Setting the current palet is +%D done by: +%D +%D \showsetup{setuppalet} + +\newtoks\everysetuppalet + +% \newtoks\t_colo_prefix % used in mp interface + +\permanent\tolerant\protected\def\setuppalet[#1]% + {\edef\currentcolorpalet{#1}% + \ifempty\currentcolorpalet + % seems to be a reset + \let\currentcolorprefix\empty + %\t_colo_prefix\emptytoks + \orelse\ifcsname\??paletlist\currentcolorpalet\endcsname + \edef\currentcolorprefix{#1:}% + %\t_colo_prefix\expandafter{\currentcolorprefix}% + \else + \colo_helpers_show_message\m!colors7\currentcolorpalet + \let\currentcolorpalet\empty + \let\currentcolorprefix\empty + %\t_colo_prefix\emptytoks + \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!colo_run + +%D \macros +%D {showcolorcomponents} +%D +%D \starttyping +%D \showcolorcomponents[color-1,color-2] +%D \stoptyping + +\fetchruntimecommand \showcolorcomponents \f!colo_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!colo_run + +%D \macros +%D {showcolor} +%D +%D But let's not forget that we also have the more traditional non||related colors. +%D 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!colo_run + +%D It would make sense to put the following code in \type {colo-mps}, but it it +%D rather low level. + +%D \macros +%D {negatecolorcomponent,negatedcolorcomponent} +%D +%D These speak for themselves. See \type {colo-ext} for usage. + +\permanent\protected\def\negatecolorcomponent#1% #1 = \macro + {\edef#1{\clf_negatecolorcomponent{#1}}} + +\permanent\def\negatedcolorcomponent#1% + {\clf_negatecolorcomponent{#1}} + +%D \macros +%D {MPcolor} +%D +%D A very special macro is \type{\MPcolor}. This one can be used to pass a \CONTEXT\ +%D 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 switch, i.e.\ expanded +%D colors. However, predefined colors and palets are no longer expanded (which is +%D what I wanted in the first place). +%D +%D In \MKIV\ we don't support color separation as we might now assume that printing +%D houses have the right programs to do it themselves. If it's ever needed in \MKIV\ +%D It is relatively 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 + +\permanent\protected\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is + {\colo_helpers_set_model{#1}} % only for local usage + +\def\colo_helpers_set_model#1% direct + {\edef\currentcolormodel{#1}% + \clf_setcolormodel{\currentcolormodel}{\m_colo_weight_gray}} % 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 + \orelse\ifconditional\c_colo_cmyk_supported + \colo_helpers_set_model\s!cmyk + \orelse\ifconditional\c_colo_convert_gray + \colo_helpers_set_model\s!gray + \else + \colo_helpers_set_model\s!none + \fi + \orelse\ifconditional\c_colo_convert_gray + \colo_helpers_set_model\s!gray + \else + \colo_helpers_set_model\s!none + \fi} + +%D Currently in mkiv transparency is implemented independent of color. This costs a +%D bit more processing time but gives the possibility to apply transparency +%D independently in the future. Is this useful? If not we may as well combine them +%D again in the future. By coupling we are downward compatible. When we decouple we +%D need to do more tricky housekeeping (e.g. persist color independent +%D 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{c_o_l_o_r} + +\letvalue{\??colorattribute \v_colo_dummy_name}\empty +\letvalue{\??transparencyattribute\v_colo_dummy_name}\empty +\letvalue{\??colorsetter \v_colo_dummy_name}\empty +\letvalue{\??transparencysetter \v_colo_dummy_name}\empty + +\letvalue{\??colorsetter -}\empty % used? +\letvalue{\??transparencysetter-}\empty % used? + +% new: expandable (see tbl) + +\def\colo_helpers_fast_activate + {\ifempty\currentcolorprefix + \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 + \begincsname\??transparencysetter\currentcolorprefix#1\endcsname + \orelse\ifcsname\??colorsetter#1\endcsname + \lastnamedcs + \begincsname\??transparencysetter#1\endcsname + \fi} + +\def\colo_helpers_fast_activate_nop#1% + {\ifcsname\??colorsetter#1\endcsname + \lastnamedcs + \begincsname\??transparencysetter#1\endcsname + \fi} + +\def\colo_helpers_activate_dummy + {\begincsname\??colorsetter \v_colo_dummy_name\endcsname + \begincsname\??transparencysetter\v_colo_dummy_name\endcsname} + +\let\dofastcoloractivation\colo_helpers_fast_activate + +% so far + +\def\colo_helpers_activate#1% two-step is not that much faster but less tracing + {\edef\currentcolorname{#1}% + \ifempty\currentcolorprefix + %\expandafter + \colo_helpers_activate_nop + \else + %\expandafter + \colo_helpers_activate_yes + \fi} + +\def\colo_helpers_activate_yes + {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname + \lastnamedcs + \begincsname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname + \orelse\ifcsname\??colorsetter\currentcolorname\endcsname + \lastnamedcs + \begincsname\??transparencysetter\currentcolorname\endcsname + \fi} + +\def\colo_helpers_activate_nop + {\ifcsname\??colorsetter\currentcolorname\endcsname + \lastnamedcs + \begincsname\??transparencysetter\currentcolorname\endcsname + \fi} + +\def\colo_helpers_activate_yes_only + {\ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname + \lastnamedcs + \orelse\ifcsname\??colorsetter\currentcolorname\endcsname + \lastnamedcs + \fi} + +\def\colo_helpers_activate_nop_only + {\ifcsname\??colorsetter\currentcolorname\endcsname + \lastnamedcs + \fi} + +\let\dousecolorparameter\colo_helpers_activate + +\permanent\protected\def\dousecolorhashparameter#1#2% + {\ifcsname#1#2\endcsname + \expandafter\dousecolorparameter\csname#1#2\endcsname + \fi} + +\permanent\protected\def\dousecurrentcolorparameter + {\let\currentcolorname\currentcolorparameter % maybe only when success + \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname + \lastnamedcs + \begincsname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname + \orelse\ifcsname\??colorsetter\currentcolorparameter\endcsname + \lastnamedcs + \begincsname\??transparencysetter\currentcolorparameter\endcsname + \fi} + +\let\dosetcolorattribute\dousecolorhashparameter % for a while + +\permanent\protected\def\deactivatecolor % sort of public but a bad name + {\let\currentcolorname\s!black + \c_attr_color \attributeunsetvalue + \c_attr_transparency\attributeunsetvalue} + +% todo: check if color is overloading a non-color command + +% \let\colo_basics_synchronize\gobbleoneargument % used in mp interface +% \let\colo_basics_inherit \gobbletwoarguments % used in mp interface + +\def\colo_basics_allocate#1% + {\expandafter\newcount\csname\??colornumber#1\endcsname + \clf_synccolorcount{#1}\c_syst_last_allocated_count} + +\def\colo_basics_synchronize#1% + {\ifcsname\??colornumber#1\endcsname\else + \colo_basics_allocate{#1}% + \fi + \clf_synccolor{#1}% + %\csname\??colornumber#1\endcsname\csname\??colorattribute#1\endcsname + \lastnamedcs\csname\??colorattribute#1\endcsname} + +\let\colo_basics_inherit\clf_synccolorclone + +\newcount\c_colo_protection + +\permanent\protected\def\startprotectedcolors{\advance\c_colo_protection\plusone } +\permanent\protected\def\stopprotectedcolors {\advance\c_colo_protection\minusone} + +\permanent\tolerant\protected\def\definecolor[#1]#*[#2]% + {\iftok{#1}{#2}% + % maybe a warning + \else + \clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax + \colo_basics_synchronize{#1}% + \ifcase\c_colo_protection + \protected\instance\defcsname#1\endcsname{\colo_helpers_activate{#1}}% + \fi + \fi} + +\permanent\tolerant\protected\def\defineglobalcolor[#1]#*[#2]% + {\iftok{#1}{#2}% + % maybe a warning + \else + \clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax + \colo_basics_synchronize{#1}% + \ifcase\c_colo_protection + \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% + \fi + \fi} + +\aliased\let\definenamedcolor\definecolor + +\def\colo_basics_defined_and_activated#1% + {\clf_defineprocesscolordummy{#1}% we could pass dummy here too + \colo_basics_synchronize{\v_colo_dummy_name}% + \colo_helpers_activate_dummy} + +\permanent\tolerant\protected\def\defineprocesscolor[#1]#*[#2]#*[#3]% + {\ifarguments\or + \colo_basics_define_process_wrapup{#1}\empty + \or + \colo_basics_define_process_wrapup{#1}{#2}% + \or % we could just pass #3 to clf_... also when it's empty ... todo after split + \colo_basics_define_process_wrapup{#1}{\processcolorcomponents{#2},#3}% + \fi} + +\def\colo_basics_define_process_wrapup#1#2% + {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax + \colo_basics_synchronize{#1}% + \ifcase\c_colo_protection + \protected\instance\defcsname#1\endcsname{\colo_helpers_activate{#1}}% + \fi} + +%D Spotcolors used setxvalue but that messes up currentcolor and probably no global +%D is needed either but they are global at the lua end (true argument) so we keep +%D that if only because spot colors often are a document wide property + +\permanent\tolerant\protected\def\definespotcolor[#1]#*[#2]#*[#3]% + {\clf_definespotcolorglobal{#1}{#2}{#3}% + \colo_basics_synchronize{#1}% + \ifcase\c_colo_protection + \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% + \fi} + +\permanent\tolerant\protected\def\definemultitonecolor[#1]#*[#2]#*[#3]#*[#4]% + {\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}% + \colo_basics_synchronize{#1}% + \ifcase\c_colo_protection + \protected\instance\setgvalue{#1}{\colo_helpers_activate{#1}}% + \fi} + +%D Transparencies (only): + +\permanent\tolerant\protected\def\definetransparency[#1]#*[#2]% + {\clf_definetransparency{#1}{#2}} + +\permanent\tolerant\protected\def\defineglobaltransparency[#1]#*[#2]% + {\clf_definetransparencyglobal{#1}{#2}} + +% 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. + +\permanent\tolerant\protected\def\defineintermediatecolor[#1]#*[#2]#*[#3] + {\colo_basics_define_intermediate_indeed[#1][#2][#3]} + +\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]% + {\clf_defineintermediatecolor % not global + {#1}% + {#2}% + \rawcolorattribute{#3} % + \rawcolorattribute{#4} % + \rawtransparencyattribute{#3} % + \rawtransparencyattribute{#4} % + {#5}% + \v_colo_freeze_state + \relax + \colo_basics_synchronize{#1}% + \protected\instance\defcsname#1\endcsname{\colo_helpers_activate{#1}}} + +%D Here is a more efficient helper for pgf: +%D +%D \starttyping +%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 + +\protected\def\pgf@context@registercolor#1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\zerocount\thecolorattribute{#1}}} +\protected\def\pgf@context@registergray #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plustwo \thecolorattribute{#1}}} +\protected\def\pgf@context@registerrgb #1{\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\clf_pgfxcolorspec\plusthree\thecolorattribute{#1}}} +\protected\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 command. Later on we will +%D explain the use of palets. We define ourselves a color conditional first. + +\permanent\def\doifelsecolor#1% + {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname + \expandafter\firstoftwoarguments + \orelse\ifcsname\??colorattribute#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifcolorelse\doifelsecolor + +\permanent\def\doifcolor#1% + {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname + \expandafter\firstofoneargument + \orelse\ifcsname\??colorattribute#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +%D \macros +%D {startregistercolor,stopregistercolor,permitcolormode} +%D +%D If you only want to register a color, the switch \type {\ifpermitcolormode} can +%D be used. That way the nested colors know where to go back to. +%D +%D We use these macros for implementing text colors (actually, the first application +%D was in foreground 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} + +\permanent\protected\def\inheritmaintextcolor + {\ifempty\maintextcolor\else\colo_helpers_activate\maintextcolor\fi} + +\permanent\protected\def\onlyinheritmaintextcolor + {\ifempty\maintextcolor + \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} + +\permanent\protected\def\starttextcolor[#1]% + {\doifsomething{#1}{\colo_helpers_switch_to_maintextcolor{#1}}} + +\aliased\let\stoptextcolor\relax + +\let\p_colo_textcolor\empty + +\def\colo_helpers_initialize_maintextcolor + {\edef\p_colo_textcolor{\directcolorsparameter\c!textcolor}% + \ifempty\p_colo_textcolor + \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{\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} + +\let\colo_defcsname\defcsname +\let\colo_endcsname\endcsname + +\appendtoks + \ifconditional\c_colo_expanded + \let\colo_defcsname\edefcsname + \else + \let\colo_defcsname\defcsname + \fi +\to \everysetupcolors + +\def\colo_palets_define_set#1#2#3% + {\ifcondition\validassignment{#3}% \definepalet[test][xx={y=.4}] + \expandafter\colo_palets_define_assign + \orelse\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_basics_inherit{#1:#2}{#3}% + \colo_defcsname\??colorsetter #1:#2\colo_endcsname{\colo_helpers_inherited_direct_cs{#3}}% + \colo_defcsname\??colorattribute #1:#2\colo_endcsname{\colo_helpers_inherited_direct_ca{#3}}% + \colo_defcsname\??transparencysetter #1:#2\colo_endcsname{\colo_helpers_inherited_direct_ts{#3}}% + \colo_defcsname\??transparencyattribute#1:#2\colo_endcsname{\colo_helpers_inherited_direct_ta{#3}}} + +\def\colo_palets_define_undefine#1#2#3% + {\letcsname\??colorsetter #1:#2\endcsname\undefined + \letcsname\??colorattribute #1:#2\endcsname\undefined + \letcsname\??transparencysetter #1:#2\endcsname\undefined + \letcsname\??transparencyattribute#1:#2\endcsname\undefined} + +\def\colo_palets_define_assign#1#2#3% + {\definecolor[\??colorpalet#1:#2][#3]% + \colo_defcsname\??colorsetter #1:#2\colo_endcsname{\colo_helpers_inherited_direct_cs{\??colorpalet#1:#2}}% + \colo_defcsname\??colorattribute #1:#2\colo_endcsname{\colo_helpers_inherited_direct_ca{\??colorpalet#1:#2}}% + \colo_defcsname\??transparencysetter #1:#2\colo_endcsname{\colo_helpers_inherited_direct_ts{\??colorpalet#1:#2}}% + \colo_defcsname\??transparencyattribute#1:#2\colo_endcsname{\colo_helpers_inherited_direct_ta{\??colorpalet#1:#2}}} + +\setvalue{\??colorattribute currentcolor}{\the\c_attr_color} % for mpcolor +\setvalue{\??transparencyattribute currentcolor}{\the\c_attr_transparency} % for mpcolor + +\def\colo_helpers_inherited_current_ca#1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi} +\def\colo_helpers_inherited_current_cs#1{\ifcsname\??colorsetter \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorsetter #1\endcsname\lastnamedcs\fi} +\def\colo_helpers_inherited_current_ta#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi} +\def\colo_helpers_inherited_current_ts#1{\ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi} + +%D Low level defs: + +\permanent\protected\def\colordefalc#1#2{\edefcsname\??colorattribute #1\endcsname{#2}% + \defcsname \??colorsetter #1\endcsname{\c_attr_color #2 }} +\permanent\protected\def\colordefagc#1#2{\xdefcsname\??colorattribute #1\endcsname{#2}% + \gdefcsname\??colorsetter #1\endcsname{\c_attr_color #2 }} % was not g +\permanent\protected\def\colordefalt#1#2{\edefcsname\??transparencyattribute#1\endcsname{#2}% + \gdefcsname\??transparencysetter #1\endcsname{\c_attr_transparency#2 }} +\permanent\protected\def\colordefagt#1#2{\xdefcsname\??transparencyattribute#1\endcsname{#2}% + \gdefcsname\??transparencysetter #1\endcsname{\c_attr_transparency#2 }} + +\permanent\protected\def\colordefflc#1#2{\defcsname \??colorattribute #1\endcsname{\colo_helpers_inherited_current_ca{#2}}% + \defcsname \??colorsetter #1\endcsname{\colo_helpers_inherited_current_cs{#2}}} +\permanent\protected\def\colordeffgc#1#2{\gdefcsname\??colorattribute #1\endcsname{\colo_helpers_inherited_current_ca{#2}}% + \defcsname \??colorsetter #1\endcsname{\colo_helpers_inherited_current_cs{#2}}} +\permanent\protected\def\colordefflt#1#2{\defcsname \??transparencyattribute#1\endcsname{\colo_helpers_inherited_current_ta{#2}}% + \defcsname \??transparencysetter #1\endcsname{\colo_helpers_inherited_current_ts{#2}}} +\permanent\protected\def\colordeffgt#1#2{\gdefcsname\??transparencyattribute#1\endcsname{\colo_helpers_inherited_current_ta{#2}}% + \defcsname \??transparencysetter #1\endcsname{\colo_helpers_inherited_current_ts{#2}}} + +\permanent\protected\def\colordefrlc #1{\letcsname \??colorattribute #1\endcsname\undefined + \letcsname \??colorsetter #1\endcsname\undefined} +\permanent\protected\def\colordefrgc #1{\gletcsname\??colorattribute #1\endcsname\undefined + \gletcsname\??colorsetter #1\endcsname\undefined} +\permanent\protected\def\colordefrlt #1{\letcsname \??transparencyattribute#1\endcsname\undefined + \letcsname \??transparencysetter #1\endcsname\undefined} +\permanent\protected\def\colordefrgt #1{\gletcsname\??transparencyattribute#1\endcsname\undefined + \gletcsname\??transparencysetter #1\endcsname\undefined} + +%D \macros +%D {colorvalue, grayvalue} +%D +%D We can typeset the color components using \type {\colorvalue} and \type +%D {\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 + +\permanent\def\MPcolor#1% + {\clf_mpcolor + \c_attr_colormodel + \colo_helpers_inherited_current_ca{#1} % + \colo_helpers_inherited_current_ta{#1} } + +\permanent\def\MPcoloronly#1% + {\clf_mpcolor + \c_attr_colormodel + \colo_helpers_inherited_current_ca{#1} % + \zerocount} + +\permanent\def\MPtransparency#1% + {\clf_mpcolor + \zerocount + \zerocount + \colo_helpers_inherited_current_ta{#1} } + +\permanent\def\MPoptions#1% + {\clf_mpoptions + \c_attr_colormodel + \colo_helpers_inherited_current_ca{#1} % + \colo_helpers_inherited_current_ta{#1} } + +\permanent\def\thecolormodelattribute {\the\c_attr_colormodel} + +\permanent\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} +\permanent\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} + +\permanent\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} +\permanent\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} + +\permanent\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}} +\permanent\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}} +\permanent\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}} + +\permanent\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}} +\permanent\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}} +\permanent\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}} + +\permanent\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}} +\permanent\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}} + +\permanent\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}} +\permanent\def\doifelsedrawingblack {\clf_doifelsedrawingblack} + +\aliased\let\doifblackelse \doifelseblack +\aliased\let\doifdrawingblackelse \doifelsedrawingblack + +%D \macros +%D {forcecolorhack} +%D +%D We can out this in front of (for instance) a special and so force color to be +%D 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) + +% \protected\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed ! +% +% I really need to sort this out! + +\permanent\protected\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! + +%D We default to the colors defined in \type {colo-imp-rgb} and support both \RGB\ +%D and \CMYK\ output. Transparencies are defined 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] + +%D Some common ones: + +\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[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:c][g=.75,b=.75,t=.5,a=1] +\definecolor[trace:m][r=.75,b=.75,t=.5,a=1] +\definecolor[trace:y][r=.75,g=.75,t=.5,a=1] +\definecolor[trace:s][s=.75,t=.5,a=1] +\definecolor[trace:d][s=.25,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:dc][g=.75,b=.75,t=.75,a=1] +\definecolor[trace:dm][r=.75,b=.75,t=.75,a=1] +\definecolor[trace:dy][r=.75,g=.75,t=.75,a=1] +\definecolor[trace:ds][s=.75,t=.75,a=1] +\definecolor[trace:dd][s=.25,t=.75,a=1] +\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1] + +\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/tex/context/base/mkxl/cont-cs.mkxl b/tex/context/base/mkxl/cont-cs.mkxl new file mode 100644 index 000000000..8e5ae567c --- /dev/null +++ b/tex/context/base/mkxl/cont-cs.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-de.mkxl b/tex/context/base/mkxl/cont-de.mkxl new file mode 100644 index 000000000..579cc88c3 --- /dev/null +++ b/tex/context/base/mkxl/cont-de.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-en.mkxl b/tex/context/base/mkxl/cont-en.mkxl new file mode 100644 index 000000000..bfb17ffb3 --- /dev/null +++ b/tex/context/base/mkxl/cont-en.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-fil.mkxl b/tex/context/base/mkxl/cont-fil.mkxl new file mode 100644 index 000000000..0ca3bb05a --- /dev/null +++ b/tex/context/base/mkxl/cont-fil.mkxl @@ -0,0 +1,152 @@ +%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. + +%D Todo: use full names and remove calls at the tex end (now integrated in \LUA\ +%D library code .. then we can load it at runtime when needed. We can also remove +%D some of the names that no longer make sense for \LMTX. + +\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] [present-original] +\definefilesynonym [pre-green] [present-green] +\definefilesynonym [pre-funny] [present-funny] +\definefilesynonym [pre-colorful] [present-colorful] +\definefilesynonym [pre-fuzzy] [present-fuzzy] +\definefilesynonym [pre-polish] [pre-06] +\definefilesynonym [pre-spider] [pre-07] +\definefilesynonym [pre-wonder] [pre-08] +\definefilesynonym [pre-windows] [present-windows] +\definefilesynonym [pre-grow] [present-grow] +\definefilesynonym [pre-stack] [present-stack] +\definefilesynonym [pre-split] [present-split] +\definefilesynonym [pre-balls] [present-balls] +\definefilesynonym [pre-weird] [present-weird] +\definefilesynonym [pre-stepwise] [present-stepwise] +\definefilesynonym [pre-stepper] [present-stepper] +\definefilesynonym [pre-punk] [present-punk] +\definefilesynonym [pre-random] [present-random] + +\definefilesynonym [pre-arrows] [pre-12] +\definefilesynonym [pre-writing] [pre-13] +\definefilesynonym [pre-knot] [pre-16] +\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-26] + +\definefilesynonym [pre-01] [present-original] +\definefilesynonym [pre-02] [present-green] +\definefilesynonym [pre-03] [present-funny] +\definefilesynonym [pre-04] [present-colorful] +\definefilesynonym [pre-05] [present-fuzzy] +\definefilesynonym [pre-09] [present-windows] +\definefilesynonym [pre-10] [present-grow] +\definefilesynonym [pre-11] [present-stack] +\definefilesynonym [pre-14] [present-split] +\definefilesynonym [pre-15] [present-balls] +\definefilesynonym [pre-17] [present-weird] +\definefilesynonym [pre-41] [present-tiles] +\definefilesynonym [pre-60] [present-stepwise] +\definefilesynonym [pre-61] [present-stepper] +\definefilesynonym [pre-62] [present-overlap] +\definefilesynonym [pre-69] [present-wobbling] +\definefilesynonym [pre-70] [present-punk] +\definefilesynonym [pre-71] [present-random] + +\definefilesynonym [abr-01] [abbreviations-pseudocaps] +\definefilesynonym [abr-02] [abbreviations-smallcaps] +\definefilesynonym [abr-03] [abbreviations-words] +\definefilesynonym [abr-04] [abbreviations-mixed] + +\definefilesynonym [art-01] [article-basic] +\definefilesynonym [article] [article-basic] +\definefilesynonym [mag-01] [magazine-basic] +\definefilesynonym [magazine] [magazine-basic] +\definefilesynonym [mod-01] [module-basic] +\definefilesynonym [module] [module-basic] + +\definefilesynonym [map-10] [maps] % for a while + +\definefilesynonym [mml] [mathml] +\definefilesynonym [cml] [chemml] + +\definefilesynonym [letter] [cor-01] +\definefilesynonym [memo] [cor-02] +\definefilesynonym [resume] [cor-03] + +\definefilesynonym [fnt-10] [fonts-complete] +\definefilesynonym [fnt-11] [fonts-system] +\definefilesynonym [fnt-20] [fonts-steps] +\definefilesynonym [fnt-21] [fonts-steps] +\definefilesynonym [fnt-22] [fonts-engines] +\definefilesynonym [fnt-23] [fonts-shapes] +\definefilesynonym [fnt-24] [fonts-cjk] +\definefilesynonym [fnt-25] [math-characters] +\definefilesynonym [fnt-28] [fonts-goodies] +\definefilesynonym [fnt-29] [fonts-shapes] +\definefilesynonym [fnt-31] [fonts-coverage] +\definefilesynonym [fnt-33] [math-coverage] + +\definefilesynonym [mat-10] [math-characters] +\definefilesynonym [mat-11] [math-characters] +\definefilesynonym [mat-12] [math-parameters] +\definefilesynonym [mat-20] [math-parameters] + +\definefilesynonym [syn-01] [syntax] + +\definefilesynonym [reg-01] [regimes-list] + +\definefilesynonym [set-11] [setups-basics] +\definefilesynonym [set-12] [setups-overview] +%definefilesynonym [set-13] [setups-proofing] +%definefilesynonym [set-15] [setups-generate] + +\definefilesynonym [ecmascript] [libs-imp-mujs] +\definefilesynonym [zint] [libs-imp-zint] + +\endinput diff --git a/tex/context/base/mkxl/cont-fr.mkxl b/tex/context/base/mkxl/cont-fr.mkxl new file mode 100644 index 000000000..bedae536b --- /dev/null +++ b/tex/context/base/mkxl/cont-fr.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-gb.mkxl b/tex/context/base/mkxl/cont-gb.mkxl new file mode 100644 index 000000000..464b237da --- /dev/null +++ b/tex/context/base/mkxl/cont-gb.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-it.mkxl b/tex/context/base/mkxl/cont-it.mkxl new file mode 100644 index 000000000..1702a872f --- /dev/null +++ b/tex/context/base/mkxl/cont-it.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-log.mkxl b/tex/context/base/mkxl/cont-log.mkxl new file mode 100644 index 000000000..3d110c648 --- /dev/null +++ b/tex/context/base/mkxl/cont-log.mkxl @@ -0,0 +1,298 @@ +%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. + +%D We define the uppercase logo commands as (unfrozen) instances because they can be +%D redefined in the synonyms modules. + +\unprotect + +\frozen\instance\protected\def\TeX + {\dontleavehmode + \begingroup + T% + \setbox\scratchbox\hbox{M}% + \kern-.1667\wd\scratchbox + \lower.5\exheight\hbox{E}% + \kern-.125\wd\scratchbox + X% + \endgroup} + +\frozen\instance\protected\def\TeXsuffix{\wordboundary\TeX} +\frozen\instance\protected\def\TeXprefix{\TeX\wordboundary} + +\frozen\instance\protected\def\ConTeXt + {\dontleavehmode + \begingroup + Con% + \wordboundary + \setbox\scratchboxone\hbox{T\kern\zeropoint e}% + \setbox\scratchboxtwo\hbox{Te}% + \discretionary{-}{}{\kern\dimexpr\wd\scratchboxtwo-\wd\scratchboxone\relax}% + \TeX t% + \endgroup} + +\frozen\instance\protected\def\PPCHTeX{ppch\TeX} + +\frozen\instance\protected\def\LaTeX % requested by erik frambach + {\dontleavehmode + \begingroup + \setbox\scratchbox\hbox{L}% + \scratchdimen\ht\scratchbox + \setbox\scratchbox\hbox{\doresetattribute{case}\txx A}% + L\kern-.55\wd\scratchbox + \raise\scratchdimen\hbox{\lower\ht\scratchbox\copy\scratchbox}% + \kern-.2\wd\scratchbox\TeX + \endgroup} + +\frozen\instance\protected\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} + +\frozen\instance\protected\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} + +\frozen\instance\protected\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} + +\frozen\instance\protected\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} + +%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: + +\frozen\instance\protected\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 + +\protected\def\setMFPfont% more sensitive for low level changes + {\font\logofont=logo% + \ifx\fontalternative\s!bf\s!bf\orelse + \ifx\fontalternative\s!it\s!sl\orelse + \ifx\fontalternative\s!sl\s!sl\orelse + \ifx\fontalternative\s!bi\s!bf\orelse + \ifx\fontalternative\s!bs\s!bf\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}{}{}} + +\frozen\instance\protected\def\MetaFont + {\dontleavehmode + \begingroup + \setMFPfont META\syst_logos_meta_hyphen FONT% + \endgroup} + +% \protected\def\MetaPost +% {\dontleavehmode +% \begingroup +% \setMFPfont META\syst_logos_meta_hyphen POST% +% \endgroup} +% +% As decided on the ConText Meeting 2013 the logo has been simplified: + +\instance\protected\def\MetaPost{MetaPost} +\instance\protected\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.) + +\instance\protected\def\METAFONT{\MetaFont} +\instance\protected\def\METAPOST{\MetaPost} +\instance\protected\def\PPCHTEX {\PPCHTeX} +\instance\protected\def\CONTEXT {\ConTeXt} +\instance\protected\def\METAFUN {\MetaFun} + +\instance\protected\def\TEX {\TeX} +\instance\protected\def\LATEX {\LaTeX} +\instance\protected\def\PICTEX {\PiCTeX} +\instance\protected\def\TABLE {\TaBlE} +\instance\protected\def\AMSTEX {\AmSTeX} +\instance\protected\def\LAMSTEX {\LamSTeX} +\instance\protected\def\INRSTEX {inrs\TeX} + +\instance\protected\def\PRAGMA {Pragma ADE} + +%D And this is how they show up: \TeX, \MetaFont, \MetaPost, \PiCTeX, \TaBlE, \ConTeXt, +%D \PPCHTeX, \AmSTeX, \LaTeX, \LamSTeX. + +%D Some placeholders: + +\frozen\instance\protected\def\eTeX {\mathematics{\varepsilon}-\TeX} +\frozen\instance\protected\def\pdfTeX {pdf\wordboundary\TeX} +\frozen\instance\protected\def\pdfeTeX {pdfe-\wordboundary\TeX} +\frozen\instance\protected\def\luaTeX {lua\wordboundary\TeX} +\frozen\instance\protected\def\Lua {Lua} +\frozen\instance\protected\def\luajitTeX {lua\wordboundary jit\wordboundary\TeX} +\frozen\instance\protected\def\luametaTeX{lua\wordboundary meta\wordboundary\TeX} +%frozen\instance\protected\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}}} + +\frozen\instance\protected\def\XeTeX + {X\lower.5\exheight + \hbox + {\kern-.15\emwidth + \iffontchar\font"018E\relax + \char"018E% + \else + \ifx\fontalternative\s!bf \mirror{E}\orelse + \ifx\fontalternative\s!it\syst_logos_xetex_e\orelse + \ifx\fontalternative\s!sl\syst_logos_xetex_e\orelse + \ifx\fontalternative\s!bi\syst_logos_xetex_e\orelse + \ifx\fontalternative\s!bs\syst_logos_xetex_e\orelse + \mirror{E}\fi + \fi}% + \kern-.1667\emwidth\TeX} + +\instance\protected\def\ETEX {\eTeX} +\instance\protected\def\PDFTEX {\pdfTeX} +\instance\protected\def\PDFETEX {\pdfeTeX} +\instance\protected\def\LUATEX {\luaTeX} +\instance\protected\def\LUAJITTEX {\luajitTeX} +\instance\protected\def\LuaTeX {\luaTeX} +\instance\protected\def\LuaMetaTeX{\luametaTeX} +\instance\protected\def\LUAMETATEX{\luametaTeX} +\instance\protected\def\XETEX {\XeTeX} + +\frozen\instance\protected\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} + +\frozen\instance\protected\def\LuajitTeX + {\dontleavehmode + \begingroup + % at this moment there is no real need for kerning tT + Luajit\kern\zeropoint\TeX + \endgroup} + +\frozen\instance\let\luaTeX \LuaTeX +\frozen\instance\let\luajitTeX\LuajitTeX + +\instance\protected\def\LUATEX {\LuaTeX} +\instance\protected\def\LUAJITTEX{\LuajitTeX} + +\instance\protected\def\MKII{MkII} % MarkTwo +\instance\protected\def\MKIV{MkIV} % MarkFour : MKIV +\instance\protected\def\MKVI{MkVI} % MarkSix : MKIV +\instance\protected\def\MKXL{MkXL} % MarkFourty : LMTX +\instance\protected\def\MKLX{MkLX} % MarkSixty : LMTX +\instance\protected\def\MKIX{MkIX} % : MKIV / LMTX +\instance\protected\def\MKXI{MkXI} % : MKIV / LMTX + +\instance\protected\def\MPII{MpII} % MarkTwo +\instance\protected\def\MPIV{MpIV} % MarkFour : MetaFun +\instance\protected\def\MPVI{MpVI} % MarkSix : MetaFun +\instance\protected\def\MPXL{MpXL} % MarkFourty : LuaMetaFun +\instance\protected\def\MPLX{MpLX} % MarkSixty : LuaMetaFun + +\instance\protected\def\LMTX{LMTX} % for LuaMetaTeX + +\appendtoks + \enforced\instance\def\ConTeXt {ConTeXt}% + \enforced\instance\def\MetaPost {MetaPost}% + \enforced\instance\def\MetaFont {MetaFont}% + \enforced\instance\def\MetaFun {MetaFun}% + \enforced\instance\def\TeX {TeX}% + \enforced\instance\let\TeXsuffix \TeX + \enforced\instance\let\TeXprefix \TeX + \enforced\instance\def\LuaTeX {LuaTeX}% + \enforced\instance\def\LuajitTeX {LuajitTeX}% + \enforced\instance\def\LuaMetaTeX{LuaMetaTeX}% + %\let\wordboundary\empty % primitive so we need to promote it to frozen (orjust preroll) +\to \everysimplifycommands + +\protect \endinput diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl new file mode 100644 index 000000000..e44f73f9d --- /dev/null +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -0,0 +1,50 @@ +%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. + +% \normalend % uncomment this to get the real base runtime + +\newcontextversion{2020.11.23 18:34} + +%D This file is loaded at runtime, thereby providing an excellent place for hacks, +%D patches, extensions and new features. There can be local overloads in cont-loc +%D (which has always been the case) and experimental code in cont-exp (which is also +%D so old that I need to remind myself to check it occasionally, so here is the +%D reminder). + +% \enabletrackers[pages.timing] +% \enabletrackers[system.usage=summary] + +\unprotect + +\writestatus\m!system{beware: some patches loaded from cont-new.mkiv} + +%D I need to verify if this indeed will make it into \type {math-ini.mkiv}, that is: +%D does Alan use it? + +\ifdefined\t \else \permanent\protected\def\t{\mathortext\text\mathtext} \fi +\ifdefined\w \else \permanent\protected\def\w{\mathortext\word\mathword} \fi + +\appendtoks + \enforced\aliased\let\t\mathtext + \enforced\aliased\let\w\mathword +\to \everymathematics + +\pushoverloadmode + % charts needs these + \overloaded\unletfrozen\name % for now + \overloaded\frozen\let\type\type +\popoverloadmode + +%D We're done. + +\protect \endinput diff --git a/tex/context/base/mkxl/cont-nl.mkxl b/tex/context/base/mkxl/cont-nl.mkxl new file mode 100644 index 000000000..1f00e7e89 --- /dev/null +++ b/tex/context/base/mkxl/cont-nl.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-pe.mkxl b/tex/context/base/mkxl/cont-pe.mkxl new file mode 100644 index 000000000..82bf73721 --- /dev/null +++ b/tex/context/base/mkxl/cont-pe.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-ro.mkxl b/tex/context/base/mkxl/cont-ro.mkxl new file mode 100644 index 000000000..6d636c7dc --- /dev/null +++ b/tex/context/base/mkxl/cont-ro.mkxl @@ -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.mkxl + +\endinput diff --git a/tex/context/base/mkxl/cont-run.mkxl b/tex/context/base/mkxl/cont-run.mkxl new file mode 100644 index 000000000..909c07204 --- /dev/null +++ b/tex/context/base/mkxl/cont-run.mkxl @@ -0,0 +1,59 @@ +%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} + +\registerctxluafile{cont-run}{} + +% \enabletrackers[system.synctex.visualize] +% \enabletrackers[system.synctex.xml] +% \enabledirectives[system.synctex.details] +% \setupsynctex[state=start] + +\unprotect + +\permanent\let\synctexsetfilename \clf_synctexsetfilename % can be public implementors +\permanent\let\synctexresetfilename\clf_synctexresetfilename % idem +\permanent\let\synctexblockfilename\clf_synctexblockfilename % idem + +\aliased\let\synctexpause \donothing +\aliased\let\synctexresume \donothing +\aliased\let\synctexpushline\donothing +\aliased\let\synctexpopline \donothing + +\appendtoks\synctexpause \to\everybeforeoutput +\appendtoks\synctexresume\to\everyafteroutput + +\permanent\protected\def\setupsynctex[#1]% + {\begingroup + \getdummyparameters[\c!state=\v!stop,\c!method=\v!max,#1]% + \edef\p_state{\dummyparameter\c!state}% + \clf_setupsynctex + state {\p_state}% + method {\dummyparameter\c!method}% + \relax + \ifx\p_state\v!start + % when public implementor, use conditional + \enforced\glet\synctexpause \clf_synctexpause + \enforced\glet\synctexresume \clf_synctexresume + \enforced\glet\synctexpushline\clf_synctexpushline + \enforced\glet\synctexpopline \clf_synctexpopline + \fi + \endgroup} + +\permanent\protected\def\blocksynctexfile[#1]% + {\processcommacommand{#1}\synctexblockfilename} + +\aliased\let\continuewhenlmtxmode\relax + +\protect \endinput diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl new file mode 100644 index 000000000..ca9c6be40 --- /dev/null +++ b/tex/context/base/mkxl/context.mkxl @@ -0,0 +1,615 @@ +%D \module +%D [ file=context, +%D version=2019.07.24, % 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. + +% http://build.contextgarden.net/waterfall?tag=c/lua(meta)tex + +%D 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 distribution) +%D later on we will calculate a number that can be used by use modules to identify +%D the feature level. Starting with version 2004.8.30 the low level interface is +%D english. Watch out and adapt 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 up and the +%D dependencies are more consistent. Beware, the version number has to match \type +%D {YYYY.MM.DD HH:MM} format. + +\edef\contextformat {\jobname} +\edef\contextversion{2020.11.23 18:34} + +%overloadmode 1 % check frozen / warning +%overloadmode 2 % check frozen / error +%overloadmode 3 % check frozen, primitive, permanent / warning +\overloadmode 4 % check frozen, primitive, permanent / error + +%D Kind of special: + +\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax + +%D For those who want to use this: + +\let\fmtname \contextformat +\let\fmtversion\contextversion + +%D Loading: + +\edef\mksuffix {mkiv} +\edef\contextmark{LMTX} + +\ifx\normalinput\undefined \let\normalinput\input \fi + +\def\loadmarkfile#1{\normalinput{#1.\mksuffix}} +\def\loadmkivfile#1{\normalinput{#1.mkiv}} +\def\loadmkvifile#1{\normalinput{#1.mkvi}} +\def\loadmkxlfile#1{\normalinput{#1.mkxl}} +\def\loadmklxfile#1{\normalinput{#1.mklx}} + +%D First we load the system modules. These implement a lot of manipulation macros. +%D We start with setting up some basic \TEX\ machinery. + +\loadmkxlfile{syst-ini} + +%D We just quit if new functionality is expected. + +\ifnum\luatexversion<200 % also change message + \writestatus{!!!!}{Your luametatex binary is too old, you need at least version 2.00!} + \expandafter\end +\fi + +%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 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} + +% \normaleverypar{\wait} % uncomment for test of funny injections + +%D Now the more fundamental code gets defined. + +\loadmkxlfile{norm-ctx} +\loadmkxlfile{syst-pln} +\loadmkxlfile{syst-mes} + +\loadmkxlfile{luat-cod} +\loadmkxlfile{luat-bas} +\loadmkxlfile{luat-lib} +\loadmkxlfile{luat-soc} + +\loadmkxlfile{catc-ini} +\loadmkxlfile{catc-act} +\loadmkxlfile{catc-def} +\loadmkxlfile{catc-ctx} +\loadmkxlfile{catc-sym} + +\loadmkxlfile{toks-ini} +\loadmkxlfile{cldf-ini} + +% \tracecatcodetables + +%D From here on we have \unexpanded being \normalprotected, as we already had +%D \type {\unexpanded} long before etex came around. + +\loadmkxlfile{luat-ini} +\loadmkxlfile{toks-scn} + +\loadmkxlfile{syst-aux} +\loadmkxlfile{syst-lua} +\loadmkxlfile{syst-con} + +\loadmkxlfile{syst-fnt} +\loadmkxlfile{syst-rtp} + +\loadmkxlfile{luat-usr} + +\loadmklxfile{file-ini} +\loadmklxfile{file-res} +\loadmkxlfile{file-lib} + +\loadmkxlfile{core-lmt} + +%D This needs more checking for clashes: +%D +%D \starttyping +%D \doifelsefileexists{l-macro-imp-codes-luametatex.lua}{\registerctxluafile{l-macro-imp-codes-luametatex}{}}{} +%D \stoptyping + +\loadmkxlfile{supp-dir} + +\loadmkxlfile{char-utf} +\loadmkxlfile{char-ini} +\loadmkxlfile{char-act} + +\loadmkxlfile{mult-ini} +\loadmkxlfile{mult-sys} +\loadmkxlfile{mult-aux} +\loadmkxlfile{mult-def} +%loadmarkfile{mult-chk} +\loadmklxfile{mult-dim} + +\loadmkxlfile{cldf-int} % interface + +\loadmkxlfile{trac-ctx} % maybe move up + +\loadmkxlfile{toks-aux} + +\loadmkxlfile{attr-ini} + +\loadmkxlfile{core-ini} +\loadmkxlfile{core-env} + +\loadmkxlfile{layo-ini} + +\loadmkxlfile{node-ini} + +\loadmkxlfile{cldf-bas} % basics / depends on nodes + +\loadmkxlfile{node-fin} +\loadmkxlfile{node-mig} +%loadmkxlfile{node-pag} + +\loadmkxlfile{driv-ini} + +\loadmkxlfile{back-ini} +\loadmkxlfile{back-res} +\loadmkxlfile{back-trf} +\loadmkxlfile{back-out} + +\loadmkxlfile{attr-col} +\loadmkxlfile{attr-lay} +\loadmkxlfile{attr-neg} +\loadmkxlfile{attr-eff} +\loadmkxlfile{attr-mkr} + +\loadmkxlfile{trac-tex} +\loadmkxlfile{trac-deb} % will move up + +\loadmkxlfile{supp-box} + +\loadmkxlfile{supp-ran} +\loadmkxlfile{supp-mat} + +\loadmkxlfile{core-uti} +\loadmklxfile{file-job} + +\loadmkxlfile{anch-pos} + +\loadmkxlfile{typo-ini} +\loadmkxlfile{typo-lin} +\loadmkxlfile{typo-bld} % par builders + +\loadmkxlfile{typo-inj} + +\loadmklxfile{file-syn} +\loadmklxfile{file-mod} + +\loadmkxlfile{core-sys} +\loadmkxlfile{core-con} + +\loadmkxlfile{cont-fil} + +\loadmkxlfile{regi-ini} +\loadmkxlfile{enco-ini} +\loadmkxlfile{hand-ini} + +\loadmkxlfile{lang-ini} +\loadmkxlfile{lang-hyp} % also loads dis +\loadmkxlfile{lang-lab} + +\loadmkxlfile{unic-ini} + +\loadmkxlfile{core-two} +\loadmkxlfile{core-dat} + +\loadmkxlfile{colo-ini} +\loadmkxlfile{colo-grp} % optional +\loadmkxlfile{colo-ext} + +\loadmkxlfile{node-bck} % overloads anch-pgr (experimental and undocumented) + +\loadmkxlfile{pack-cut} + +\loadmkxlfile{lang-mis} +\loadmkxlfile{lang-url} +\loadmkxlfile{lang-def} + +% \loadmkvifile{file-job} % why so late? + +\loadmkxlfile{symb-ini} % brrr depends on fonts + +\loadmkxlfile{sort-ini} + +\loadmklxfile{pack-mis} +\loadmkxlfile{pack-ori} +\loadmkxlfile{pack-rul} +\loadmkxlfile{pack-mrl} +\loadmklxfile{pack-bck} +\loadmkxlfile{pack-fen} + +\loadmkxlfile{lxml-ini} +\loadmkxlfile{lxml-sor} + +\loadmklxfile{typo-prc} +\loadmkxlfile{typo-plc} + +\loadmklxfile{strc-ini} +\loadmkxlfile{strc-tag} +\loadmkxlfile{strc-doc} +\loadmkxlfile{strc-num} +\loadmkxlfile{strc-mar} +\loadmkxlfile{strc-sbe} +\loadmklxfile{strc-lst} +\loadmkxlfile{strc-sec} +\loadmkxlfile{strc-pag} % hm, depends on core-num +\loadmkxlfile{strc-ren} +%loadmarkfile{strc-xml} +\loadmkxlfile{strc-def} % might happen later +\loadmklxfile{strc-ref} +%loadmarkfile{strc-reg} +\loadmklxfile{strc-lev} % experiment + +\loadmkxlfile{spac-hor} +\loadmkxlfile{spac-ali} +\loadmkxlfile{spac-flr} +\loadmkxlfile{spac-ver} % beware, hooks into strc-sec +\loadmkxlfile{spac-lin} +\loadmkxlfile{spac-pag} +\loadmkxlfile{spac-par} +\loadmkxlfile{spac-def} +\loadmklxfile{spac-prf} +\loadmkxlfile{spac-grd} + +\loadmklxfile{scrn-ini} +\loadmklxfile{scrn-ref} + +\loadmkxlfile{pack-obj} + +\loadmklxfile{strc-itm} + +\loadmklxfile{strc-con} +\loadmklxfile{strc-des} +\loadmklxfile{strc-enu} + +\loadmkxlfile{strc-ind} +\loadmkxlfile{strc-lab} +\loadmkxlfile{strc-syn} + +% \loadmarkfile{core-sys} + +\loadmkxlfile{page-var} +\loadmklxfile{page-otr} +\loadmkxlfile{page-ini} +\loadmkxlfile{page-ins} +\loadmkxlfile{page-fac} +\loadmkxlfile{page-brk} +\loadmkxlfile{page-col} +\loadmkxlfile{page-inf} +\loadmkxlfile{page-flt} +\loadmkxlfile{page-bck} +\loadmkxlfile{page-not} +\loadmkxlfile{page-one} +\loadmkxlfile{page-lay} +\loadmklxfile{page-box} +\loadmklxfile{page-txt} +\loadmkxlfile{page-sid} + +\loadmklxfile{strc-flt} + +\loadmkxlfile{page-pst} +\loadmklxfile{page-mbk} +%loadmarkfile{page-mul} % \usecolumns[old-multicolumns] +\loadmkxlfile{page-mix} +\loadmkxlfile{page-smp} +\loadmkxlfile{page-cst} +\loadmkxlfile{page-pcl} % new +\loadmkxlfile{pack-lyr} +\loadmkxlfile{pack-pos} +\loadmklxfile{page-mak} +\loadmkxlfile{page-mcl} + +\loadmkxlfile{strc-reg} % uses mixed columns + +\loadmklxfile{page-lin} +\loadmkxlfile{page-par} +\loadmkxlfile{typo-pag} +\loadmkxlfile{typo-mar} +\loadmkxlfile{typo-itm} + +\loadmkxlfile{buff-ini} +\loadmkxlfile{buff-ver} +\loadmklxfile{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 + +\loadmkxlfile{strc-blk} + +\loadmkxlfile{page-imp} +\loadmklxfile{page-sel} % optional +\loadmklxfile{page-inj} % optional + +\loadmklxfile{scrn-pag} +\loadmklxfile{scrn-wid} +\loadmklxfile{scrn-but} +\loadmklxfile{scrn-bar} + +\loadmkxlfile{page-com} % optional (after scrn-pag) + +\loadmkxlfile{strc-bkm} % bookmarks + +\loadmkxlfile{java-ini} + +\loadmklxfile{scrn-fld} +\loadmklxfile{scrn-hlp} + +\loadmkxlfile{char-enc} + +\loadmklxfile{font-lib} % way too late but after language +\loadmklxfile{font-fil} +\loadmklxfile{font-var} +\loadmklxfile{font-fea} +\loadmklxfile{font-mat} +\loadmklxfile{font-ini} +\loadmklxfile{font-sym} +\loadmklxfile{font-sty} +\loadmklxfile{font-set} +\loadmklxfile{font-emp} +\loadmkxlfile{font-pre} +\loadmkxlfile{font-unk} +\loadmkxlfile{font-tra} +\loadmkxlfile{font-chk} +\loadmkxlfile{font-uni} +\loadmklxfile{font-col} +\loadmklxfile{font-gds} +\loadmklxfile{font-aux} +\loadmklxfile{font-sel} + +\loadmkxlfile{typo-tal} +\loadmkxlfile{typo-par} % par builders (uses fonts) + +\loadmkxlfile{tabl-com} +%loadmarkfile{tabl-pln} + +\loadmkxlfile{tabl-tab} % thrd-tab stripped and merged + +\loadmkxlfile{tabl-tbl} +\loadmkxlfile{tabl-ntb} +\loadmkxlfile{tabl-nte} +\loadmkxlfile{tabl-ltb} +\loadmkxlfile{tabl-frm} +\loadmkxlfile{tabl-tsp} +\loadmklxfile{tabl-xtb} +\loadmkxlfile{tabl-mis} + +\loadmkxlfile{typo-lan} + +\loadmkxlfile{lxml-css} + +\loadmkxlfile{spac-chr} % depends on fonts + +\loadmkxlfile{blob-ini} + +\loadmkxlfile{trac-vis} +\loadmkxlfile{trac-jus} + +\loadmkxlfile{typo-cln} +\loadmkxlfile{typo-wrp} +\loadmkxlfile{typo-spa} +\loadmkxlfile{typo-krn} +\loadmklxfile{typo-itc} +\loadmkxlfile{typo-dir} +\loadmkxlfile{typo-brk} +\loadmkxlfile{typo-cap} +\loadmkxlfile{typo-dig} +\loadmkxlfile{typo-rep} +\loadmklxfile{typo-txt} +\loadmkxlfile{typo-drp} +\loadmkxlfile{typo-fln} +\loadmkxlfile{typo-sus} +\loadmkxlfile{typo-lig} +\loadmkxlfile{typo-chr} +\loadmkxlfile{typo-rub} +\loadmkxlfile{typo-fkr} +\loadmkxlfile{typo-pnc} + +\loadmklxfile{type-ini} +\loadmkxlfile{type-set} + +\loadmkxlfile{scrp-ini} + +\loadmkxlfile{symb-emj} + +\loadmkxlfile{lang-tra} % can be optional (discussion with mm sideeffect) +\loadmkxlfile{lang-wrd} % can be optional (discussion with mm sideeffect) +\loadmkxlfile{lang-rep} % can be optional (bt 2013 side effect) + +\loadmkxlfile{mlib-ctx} % messy order + +\loadmkxlfile{meta-ini} +\loadmkxlfile{meta-tex} +\loadmkxlfile{meta-fun} +\loadmkxlfile{meta-pag} +\loadmkxlfile{meta-grd} +\loadmkxlfile{meta-fnt} +\loadmkxlfile{meta-nod} +\loadmkxlfile{meta-lua} +\loadmkxlfile{meta-mac} + +\loadmkxlfile{page-mrk} % depends on mp + +\loadmkxlfile{page-flw} +\loadmkxlfile{page-spr} +\loadmkxlfile{page-plg} +\loadmkxlfile{page-str} + +\loadmkxlfile{anch-pgr} % can be moved up (nicer for dependencies) +\loadmklxfile{anch-bck} +\loadmkxlfile{anch-tab} % overloads tabl-tbl +\loadmkxlfile{anch-bar} +%loadmkxlfile{anch-snc} % when needed this one will be redone + +\loadmkxlfile{math-ini} % way after font-pre ! +\loadmkxlfile{math-pln} +\loadmkxlfile{math-for} +\loadmkxlfile{math-def} % also saves some meanings +\loadmkxlfile{math-ali} +\loadmklxfile{math-stc} +\loadmkxlfile{math-frc} +\loadmkxlfile{math-mis} +\loadmkxlfile{math-scr} +\loadmkxlfile{math-int} +\loadmkxlfile{math-del} +\loadmkxlfile{math-fen} +\loadmklxfile{math-acc} +\loadmklxfile{math-rad} +\loadmkxlfile{math-inl} +\loadmkxlfile{math-dis} +%loadmkxlfile{math-lan} +\loadmkxlfile{math-toy} + +\loadmkxlfile{strc-mat} + +\loadmkxlfile{chem-ini} +\loadmkxlfile{chem-str} + +\loadmkxlfile{typo-scr} +\loadmkxlfile{phys-dim} + +\loadmkxlfile{node-rul} % beware, defined \underbar so after math +\loadmklxfile{font-sol} % font solutions + +\loadmklxfile{strc-not} +\loadmklxfile{strc-lnt} +\loadmkxlfile{strc-tnt} +\loadmkxlfile{strc-usr} + +\loadmkxlfile{pack-com} +\loadmkxlfile{typo-del} + +\loadmkxlfile{grph-trf} +\loadmkxlfile{grph-inc} +\loadmkxlfile{grph-fig} +\loadmkxlfile{grph-raw} +\loadmkxlfile{grph-rul} +\loadmkxlfile{grph-pat} + +\loadmkxlfile{pack-box} +\loadmkxlfile{pack-bar} +\loadmkxlfile{page-app} +\loadmkxlfile{meta-fig} + +\loadmkxlfile{page-ffl} + +\loadmkxlfile{lang-spa} % will become obsolete + +\loadmkxlfile{typo-ovl} % fuzzy project (tracing) code + +% old bibtex support: (will be m-oldbibtex.mkiv) + +% \loadmarkfile{bibl-bib} +% \loadmarkfile{bibl-tra} + +% new bibtex support: + +\loadmkxlfile{publ-ini} +\loadmkxlfile{publ-tra} +\loadmkxlfile{publ-xml} +\loadmkxlfile{publ-old} + +%loadmarkfile{x-xtag} % no longer preloaded + +\loadmkxlfile{meta-xml} + +\loadmkxlfile{cont-log} + +\loadmkxlfile{cldf-ver} % verbatim, this can come late +\loadmkxlfile{cldf-com} % commands, this can come late + +\loadmkxlfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace + +\loadmkxlfile{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) + +\loadmkxlfile{driv-shp} + +\loadmkxlfile{back-exp} +\loadmkxlfile{back-pdf} +\loadmkxlfile{back-mps} +\loadmkxlfile{back-lua} + +\loadmkxlfile{mlib-pdf} +\loadmkxlfile{mlib-pps} +\loadmkxlfile{meta-pdf} +\loadmkxlfile{meta-blb} +\loadmkxlfile{grph-epd} + +\loadmkxlfile{math-inc} % an experiment +\loadmkxlfile{publ-inc} % an experiment + +\loadmkxlfile{task-ini} + +\loadmkxlfile{syst-cmp} % compatibility stuff moved here + +\loadmkxlfile{libs-ini} + +\loadmkxlfile{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{job.prepare()}% +% \to \everyjob + +% \appendtoks +% \enabletrackers[*]% +% \to \everyjob + +\appendtoks + \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkxl","\contextbanner")}% can become automatic +\to \everydump + +% some day: +% +% \prependtoks +% \overloadmode 255 +% \to \everyjob + +\overloadmode 0 % for now + +\errorstopmode \dump \endinput diff --git a/tex/context/base/mkxl/core-con.mkxl b/tex/context/base/mkxl/core-con.mkxl new file mode 100644 index 000000000..3601dc630 --- /dev/null +++ b/tex/context/base/mkxl/core-con.mkxl @@ -0,0 +1,1010 @@ +%D \module +%D [ file=core-con, +%D version=1997.26.08, +%D title=\CONTEXT\ Core Macros, +%D subtitle=Conversion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Core Macros / Conversion} + +\registerctxluafile{core-con}{} + +% todo: iso date ranges (from/to) + +\unprotect + +\ifdefined\currentlanguage \else \let\currentlanguage\empty \fi +\ifdefined\labeltext \else \let\labeltext \firstofoneargument \fi + +%D This module deals with all kind of conversions from numbers and dates. I +%D considered splitting this module in a support one and a core one, but to keep +%D things simple as well as preserve the overview, I decided against splitting. + +\let\spr\firstofoneargument % separator +\let\stp\firstofoneargument % stopper + +% needed for arab: + +\permanent\protected\def\isolateseparators % even works with list separator overloading + {\def\spr##1{{##1}}% % we can probably best mess around with zwj + \def\stp##1{{##1}}} % and friends + +%D \macros +%D {numbers} +%D +%D First we deal with the dummy conversion of numbers using the \TEX\ primitive +%D \type{\number}. The uppercase alternative is only there for compatibility with +%D the other conversion macros. We could do without \type{#1} but this way we get +%D rid of unwanted braces. For the savety we also define a non||sence uppercase +%D alternative. +%D +%D \showsetup{numbers} +%D +%D \starttyping +%D \def\numbers#1{\number#1} +%D \def\Numbers#1{\number#1} +%D \stoptyping +%D +%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear, +%D unless we use: + +\permanent\def\numbers#1{\purenumber{#1}} +\permanent\def\Numbers#1{\purenumber{#1}} + +%D \macros +%D {romannumerals,Romannumerals} +%D +%D \TEX\ the program uses a rather tricky conversion from numbers to their roman +%D counterparts. This conversion could of course be programmed in \TEX\ itself, but +%D I guess Knuth found the programming trick worth presenting. +%D +%D \showsetup{romannumerals} +%D \showsetup{Romannumerals} + +\permanent\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax} +\permanent\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax} + +%D Arabic etc: + +\permanent\def\abjadnumerals #1{\clf_abjadnumerals \numexpr#1\relax} +\permanent\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax} +\permanent\def\abjadnaivenumerals#1{\clf_alphabetic \numexpr#1\relax{arabic}} % okay? + +\permanent\def\hebrewnumerals #1{\clf_hebrewnumerals\numexpr#1\relax} +\aliased \let\yiddishnumerals \hebrewnumerals + +\permanent\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new +\permanent\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new + +\permanent\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}} +\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}} + +\permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}} +\permanent\def\devanagarinumerals#1{\clf_alphabetic\numexpr#1\relax{devanagari}} +\permanent\def\gurmurkhinumerals #1{\clf_alphabetic\numexpr#1\relax{gurmurkhi}} +\permanent\def\gujaratinumerals #1{\clf_alphabetic\numexpr#1\relax{gujarati}} +\permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}} +\permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}} +\permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}} +\permanent\def\arabicnumerals #1{\clf_alphabetic\numexpr#1\relax{arabic}} +\permanent\def\persiannumerals #1{\clf_alphabetic\numexpr#1\relax{persian}} +\permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}} +\permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}} + +\aliased \let\arabicexnumerals \persiannumerals + +\permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}} +\permanent\def\koreannumeralsp #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}} +\permanent\def\koreannumeralsc #1{\clf_alphabetic\numexpr#1\relax{korean-circle}} + +\aliased \let\koreanparentnumerals \koreannumeralsp +\aliased \let\koreanparenthesisnumerals\koreannumeralsp +\aliased \let\koreancirclenumerals \koreannumeralsc + +\permanent\def\chinesenumerals #1{\clf_chinesenumerals\numexpr#1\relax{normal}} +\permanent\def\chinesecapnumerals#1{\clf_chinesenumerals\numexpr#1\relax{cap}} +\permanent\def\chineseallnumerals#1{\clf_chinesenumerals\numexpr#1\relax{all}} + +%D \macros +%D {character,Character} +%D +%D Converting a number into a character can of course only be done with numbers +%D less or equal to~26. At the cost of much more macros a faster conversion is +%D possible, using: +%D +%D \starttyping +%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}} +%D \stoptyping +%D +%D But we prefer a simpel \type{\case}. +%D +%D \showsetup{character} +%D \showsetup{Character} + +\def\unknowncharacter{-} % else in lists \relax + +\permanent\def\character#1{\clf_character\numexpr#1\relax} +\permanent\def\Character#1{\clf_Character\numexpr#1\relax} + +%D \macros +%D {characters,Characters} +%D +%D Converting large numbers is supported by the next two macros. This time we +%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$. +%D +%D \showsetup{characters} +%D \showsetup{Characters} + +\permanent\def\characters#1{\clf_characters\numexpr#1\relax} +\permanent\def\Characters#1{\clf_Characters\numexpr#1\relax} + +%D \macros +%D {greeknumerals,Greeknumerals} +%D +%D Why should we only honour the romans, and not the greek? + +% \let\greeknumerals\gobbleoneargument +% \let\Greeknumerals\gobbleoneargument + +%D \macros +%D {oldstylenumerals,oldstyleromannumerals} +%D +%D These conversions are dedicated to Frans Goddijn. + +\permanent\protected\def\oldstylenumerals#1% + {\begingroup + \os\number#1% + \endgroup} + +\permanent\protected\def\oldstyleromannumerals#1% will become obsolete + {\dontleavehmode + \hbox\bgroup + \ss\txx + \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}% + \scratchwidth \wd\scratchbox + \scratchheight\ht\scratchbox + \scratchdimen .1\exheight + \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax + \hskip-\scratchwidth + \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen + \hskip-\scratchwidth + \box\scratchbox + \egroup} + +%D \macros +%D {protectconversion} +%D +%D The previous two commands are not robust enough to be passed to \type +%D {\write} en \type{\message}. That's why we introduce: + +\permanent\protected\def\protectconversion + {\let\doconvertcharacters\firstofoneargument} + +%D \macros +%D {normaltime,normalyear,normalmonth,normalday} +%D +%D The last part of this module is dedicated to converting dates. Because we want to +%D use as meaningful commands as possible, and because \TEX\ already uses up some of +%D those, we save the original meanings. + +% \savenormalmeaning\time +% \savenormalmeaning\year +% \savenormalmeaning\month +% \savenormalmeaning\day + +%D \macros +%D {month,MONTH} +%D +%D Converting the month number into a month name is done using a case statement, +%D abstact values and the label mechanism. This way users can easily redefine a +%D label from for instance german into austrian. +%D +%D \starttyping +%D \setuplabeltext [de] [january=J\"anner] +%D \stoptyping +%D +%D Anyhow, the conversion looks like: + +\permanent\protected\def\monthlong #1{\clf_monthname\numexpr#1\relax} +\permanent\protected\def\monthshort#1{\clf_monthmnem\numexpr#1\relax} +\permanent\protected\def\daylong #1{\clf_dayname\numexpr#1\relax} +\permanent\protected\def\dayshort #1{\clf_daymnem\numexpr#1\relax} +\aliased \let\convertmonth\monthlong % for old times sake + +%D We redefine the \TEX\ primitive \type{\month} as: +%D +%D \showsetup{month} +%D \showsetup{MONTH} + +\pushoverloadmode + +\aliased\let\month\monthlong + +\popoverloadmode + +\permanent\protected\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}} +\permanent\protected\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}} +\permanent\protected\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}} + +%D We never explicitly needed this, but Tobias Burnus pointed out that it would be +%D handy to convert to the day of the week. In doing so, we have to calculate the +%D total number of days, taking leapyears into account. For those who are curious: +%D +%D \startitemize[packed] +%D \item years that can be divided by 4 are leapyears +%D \item exept years that can be divided by 100 +%D \item unless years can be divided by 400 +%D \stopitemize + +%D \macros +%D {weekday,WEEKDAY} +%D +%D The first one is sort of redundant. It takes the day number argument. +%D +%D \showsetup{weekday} +%D \showsetup{WEEKDAY} + +\permanent\protected\def\weekday #1{\clf_dayname\numexpr#1\relax} +\permanent\protected\def\WEEKDAY #1{\WORD{\clf_dayname\numexpr#1\relax}} +\permanent\protected\def\DAYLONG #1{\WORD{\clf_dayname\numexpr#1\relax}} +\permanent\protected\def\DAYSHORT#1{\WORD{\clf_daymnem\numexpr#1\relax}} + +%D \macros +%D {getdayoftheweek, dayoftheweek} + +\newcount\normalweekday + +\permanent \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax} % name +\permanent\protected\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number + +%D Using this macro in +%D +%D \startbuffer +%D monday: \dayoftheweek {4} {5} {1992} +%D friday: \dayoftheweek {16} {6} {1995} +%D monday: \dayoftheweek {25} {8} {1997} +%D saturday: \dayoftheweek {30} {8} {1997} +%D tuesday: \dayoftheweek {2} {1} {1996} +%D tuesday: \dayoftheweek {7} {1} {1997} +%D tuesday: \dayoftheweek {13} {1} {1998} +%D friday: \dayoftheweek {1} {1} {2000} +%D \stopbuffer +%D +%D \typebuffer +%D +%D gives +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D The macro \type {\getdayoftheweek} can be used to calculate the number \type +%D {\normalweekday}. + +%D \macros +%D {doifleapyearelse, +%D getdayspermonth} +%D +%D Sometimes we need to know if we're dealing with a leapyear, so here is a +%D testmacro: +%D +%D \starttyping +%D \doifleapyearelse{year}{yes}{no} +%D \stoptyping +%D +%D An example of its use can be seen in the macro +%D +%D \starttyping +%D \getdayspermonth{year}{month} +%D \stoptyping +%D +%D The number of days is available in the macro \type {\numberofdays}. + +\permanent\def\doifelseleapyear#1% expandable check + {\clf_doifelseleapyear\numexpr#1\relax} + +\aliased\let\doifleapyearelse\doifelseleapyear + +\permanent\protected\def\getdayspermonth#1#2% + {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}} + +\permanent\def\dayspermonth#1#2% + {\clf_nofdays\numexpr#1\relax\numexpr#2\relax} + +% \dayoftheweek{2006}{9}{15} +% \doifleapyearelse{2000}{OK}{NOT OK} +% \doifleapyearelse{2100}{NOT OK}{OK} +% \doifleapyearelse{2004}{OK}{NOT OK} +% \doifleapyearelse{2003}{NOT OK}{OK} +% \dayspermonth{2000}{2} +% [\the\normaltime=\the\time] + +%D \macros +%D {currentdate, rawdate, date} +%D +%D We use these conversion macros in the date formatting macro: +%D +%D \showsetup{currentdate} +%D +%D This macro takes care of proper spacing and delivers for instance: +%D +%D \startbuffer +%D \currentdate[weekday,day,month,year] +%D \currentdate[WEEKDAY,day,MONTH,year] +%D \stopbuffer +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D depending of course on the keywords. Here we gave: +%D +%D \typebuffer +%D +%D If needed one can also add non||keywords, like in +%D +%D \startbuffer +%D \currentdate[dd,--,mm,--,yy] +%D \stopbuffer +%D +%D \typebuffer +%D +%D or typeset: \getbuffer. +%D +%D When no argument is passed, the current date is given as specified per +%D language (using \type{\installlanguage}). +%D +%D \showsetup{currentdate} +%D +%D \startbuffer +%D \date +%D \date[d=12,m=12,y=1998][weekday] +%D \date[d=12,m=12,y=1998] +%D \stopbuffer +%D +%D We can also typeset arbitrary dates, using the previous +%D command. +%D +%D \typebuffer +%D +%D The date is specified by one character keys. When no date is given, we get the +%D current date. +%D +%D \startlines +%D \getbuffer +%D \stoplines + +%D \starttabulate[|l|l|] +%D \HL +%D \NC year \NC (\currentdate[year]) \NC\NR +%D \NC yy \NC (\currentdate[yy]) \NC\NR +%D \NC y \NC (\currentdate[y]) \NC\NR +%D \NC Y \NC (\currentdate[Y]) \NC\NR +%D \HL +%D \NC month \NC (\currentdate[month]) \NC\NR +%D \NC mm \NC (\currentdate[mm]) \NC\NR +%D \NC m \NC (\currentdate[m]) \NC\NR +%D \NC M \NC (\currentdate[M]) \NC\NR +%D \HL +%D \NC day \NC (\currentdate[day]) \NC\NR +%D \NC dd \NC (\currentdate[dd]) \NC\NR +%D \NC d \NC (\currentdate[d]) \NC\NR +%D \NC D \NC (\currentdate[D]) \NC\NR +%D \HL +%D \NC weekday \NC (\currentdate[weekday]) \NC\NR +%D \NC w \NC (\currentdate[w]) \NC\NR +%D \NC W \NC (\currentdate[W]) \NC\NR +%D \HL +%D \NC referral \NC (\currentdate[referral]) \NC\NR +%D \HL +%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR +%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR +%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR +%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR +%D \HL +%D \stoptabulate +%D +%D \startbuffer +%D (\currentdate[D,.,M,.,Y]) +%D (\currentdate[day,month,year]) +%D (\currentdate[day,+,month,+,year]) +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Some indirectness and abstraction: +%D +%D \starttyping +%D \definedate[crap][year] +%D \currentdate[crap] +%D \stoptyping + +\installcorenamespace{date} + +\permanent\tolerant\protected\def\definedate[#1]#*[#2]% + {\ifarguments\else\setvalue{\??date#1}{#2}\fi} + +\def\syst_converters_check_date_specification#1% + {\ifcsname\??date#1\endcsname + \edef#1{\lastnamedcs}% + \fi} + +\newtoks\everycurrentdate + +\permanent\tolerant\protected\def\currentdate[#1]% + {\dontleavehmode + \begingroup + \the\everycurrentdate + \edef\forceddatespecification{#1}% + \syst_converters_check_date_specification\forceddatespecification + \syst_converters_check_date_specification\currentdatespecification + \clf_currentdate + {\forceddatespecification}{\currentdatespecification}{\labellanguage}% + \normalyear\normalmonth\normalday + \endgroup} + +\permanent\tolerant\protected\def\date[#1]#*[#2]% sets the date ! + {\dontleavehmode + \ifparameter#1\or + \begingroup + \letdummyparameter\c!d\normalday + \letdummyparameter\c!m\normalmonth + \letdummyparameter\c!y\normalyear + \getdummyparameters[#1]% + \normalexpanded + {\endgroup + \normalday \number\directdummyparameter\c!d\relax + \normalmonth\number\directdummyparameter\c!m\relax + \normalyear \number\directdummyparameter\c!y\relax}% + \fi + \begingroup + \the\everycurrentdate + \edef\forceddatespecification{#2}% + \syst_converters_check_date_specification\forceddatespecification + \syst_converters_check_date_specification\currentdatespecification + \clf_currentdate + {\forceddatespecification}{\currentdatespecification}{\labellanguage}% + \normalyear\normalmonth\normalday + \endgroup} + +\permanent\def\rawdate[#1]% expandable and no labels + {\clf_currentdate + {#1}{\currentdatespecification}{}% + \normalyear\normalmonth\normalday} + +%D \macros +%D {currenttime} +%D +%D The currenttime is actually the jobtime. You can specify a pattern similar +%D to the previous date macro using the keys \type {h}, \type {m} and a separator. + +\permanent\protected\def\calculatecurrenttime + {\edef\currenthour {\clf_hour }% + \edef\currentminute{\clf_minute}% + \edef\currentsecond{\clf_second}} + +\let\currenthour \!!plusone +\let\currentminute\!!plusone +\let\currentsecond\!!plusone + +% \def\currenttimespecification{h,:,m} + +\permanent\protected\def\currenttime + {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop} + +\protected\def\syst_converters_current_time_yes[#1]% + {\calculatecurrenttime + \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} + +\protected\def\syst_converters_current_time_nop + {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}} + +%D Because we're dealing with dates, we also introduce a few day loops: +%D +%D \starttyping +%D \processmonth{year}{month}{command} +%D \processyear{year}{command}{before}{after} +%D \stoptyping +%D +%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday} +%D can be used for for date manipulations. + +\permanent\protected\def\processmonth#1#2#3% year month command + {\begingroup + \getdayspermonth{#1}{#2}% + \dostepwiserecurse\plusone\numberofdays\plusone + {\normalyear #1\relax + \normalmonth#2\relax + \normalday \recurselevel\relax + #3}% + \endgroup} + +\def\lastmonth{12} % can be set to e.g. 1 when testing + +\permanent\protected\def\processyear#1#2#3#4% year command before after + {\begingroup + \dorecurse\lastmonth + {\normalyear #1\relax + \normalmonth\recurselevel\relax + #3\processmonth\normalyear\normalmonth{#2}#4}% + \endgroup} + +%D \macros +%D {defineconversion, convertnumber} +%D +%D Conversion involves the macros that we implemented earlier in this module. +%D +%D \showsetup{defineconversion} +%D \showsetup{convertnumber} +%D +%D We can feed this command with conversion macros as well as a set of conversion +%D symbols. Both need a bit different treatment. +%D +%D \starttyping +%D \defineconversion [roman] [\romannumerals] +%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$] +%D \stoptyping +%D +%D You can define a language dependent conversion with: +%D +%D \starttyping +%D \defineconversion [en] [whatever] [\something] +%D \stoptyping + +\installcorenamespace {conversion} +\installcorenamespace {conversionarguments} +\installcorenamespace {conversionwords} + +%D It might be better to move more to \LUA\ as we also need conversion there and +%D doublicating logic doesn't make things cleaner. It means that all conversions +%D will get a language argument too. However, we permit definitions at the \TEX\ end +%D so we have to provide some hybrid method. + +% checkedconversion(method,n,language) + +\permanent\tolerant\protected\def\defineconversion[#1]#*[#2]#*[#3]% from now on global (maybe local again some day) + {\ifparameter#3\or + \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}% + \else + \syst_converters_define_conversion_indeed{#1}{#1}{#2}% + \fi} + +\def\syst_converters_define_conversion_indeed#1#2#3% + {\doifelseinstring{,}{\detokenize{#3}} + {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols + \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}} + {\setgvalue{\??conversion#1}{#3}}} + +\def\syst_converters_checked_conversion#1#2% + {\clf_checkedconversion{#1}\numexpr#2\relax} + +%D If a conversion is just a font switch then we need to make sure that the number +%D is indeed ends up as number in the input, so we need to handle the second +%D argument. + +\permanent\def\convertnumber#1#2% expandable + {\csname\??conversionarguments + \ifcsname\??conversion\currentlanguage#1\endcsname1\else + \ifcsname\??conversion #1\endcsname2\else + 3\fi\fi + \endcsname{#1}{\number#2}} + +\permanent\protected\def\uconvertnumber % unexpandable + {\convertnumber} + +\setvalue{\??conversionarguments1}#1{\csname\??conversion\currentlanguage#1\endcsname} +\setvalue{\??conversionarguments2}#1{\csname\??conversion #1\endcsname} +\letvalue{\??conversionarguments3}\syst_converters_checked_conversion + +% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check +% if we have definitions that are not matched at the lua end .. eventually we might do +% that when more shows up + +\permanent\def\doifelseconversiondefined#1% expandable + {\ifcsname\??conversion\currentlanguage#1\endcsname + \expandafter\firstoftwoarguments + \orelse\ifcsname\??conversion#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\def\doifelseconversionnumber#1#2% expandable + {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doifconversiondefinedelse\doifelseconversiondefined +\aliased\let\doifconversionnumberelse \doifelseconversionnumber + +%D Handy. + +\setvalue{\??conversionwords\v!one }{1} +\setvalue{\??conversionwords\v!two }{2} +\setvalue{\??conversionwords\v!three}{3} +\setvalue{\??conversionwords\v!four }{4} +\setvalue{\??conversionwords\v!five }{5} + +%permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi} +\permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi} + +% \defineconversion[ctx][c,o,n,t,e,x,t] +% +% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}} + +%D \macros +%D {ordinalnumber, highordinalstr, ordinalstr} +%D +%D Efficient general ordinal number converters are sometimes difficult to +%D implement. Fortunately dates never exceed the number~31. + +\permanent\def\highordinalstr#1{\high{\notsmallcapped{#1}}} +\permanent\def\ordinalstr #1{\notsmallcapped{#1}} +\permanent\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}} +\permanent\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}} + +\permanent\def\verbosenumber#1{\clf_verbose\numexpr#1\relax{\currentlanguage}} +\permanent\def\VerboseNumber#1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}}} + +%D As longs as symbols are linked to levels or numbers, we can also use the +%D conversion mechanism, but in for instance the itemization macros, we prefer +%D symbols because they can more easier be (partially) redefined. Symbols are +%D implemented in another module. + +\permanent\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}} +\permanent\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}} + +\defineconversion [] [\numbers] % the default conversion +\defineconversion [\v!empty] [\gobbleoneargument] +\defineconversion [\v!none] [\numbers] +\defineconversion [\s!default] [\numbers] + +\defineconversion [month] [\monthlong] +\defineconversion [month:mnem] [\monthshort] + +\defineconversion [\v!character] [\character] +\defineconversion [\v!Character] [\Character] + +\defineconversion [\v!characters] [\characters] +\defineconversion [\v!Characters] [\Characters] + +\defineconversion [a] [\alphabeticnumerals] +\defineconversion [A] [\Alphabeticnumerals] +\defineconversion [AK] [\smallcappedcharacters] +\defineconversion [KA] [\smallcappedcharacters] + +\defineconversion [\v!alphabetic] [\alphabeticnumerals] +\defineconversion [\v!Alphabetic] [\Alphabeticnumerals] + +\defineconversion [\v!number] [\numbers] +\defineconversion [\v!numbers] [\numbers] +\defineconversion [\v!Numbers] [\Numbers] +\defineconversion [\v!mediaeval] [\mediaeval] + +\defineconversion [\v!word] [\verbosenumber] +\defineconversion [\v!words] [\verbosenumber] + +\defineconversion [\v!Word] [\VerboseNumber] +\defineconversion [\v!Words] [\VerboseNumber] + +\defineconversion[\v!ordinal] [\ordinalnumber] +\defineconversion[\v!Ordinal] [\Ordinalnumber] + +\defineconversion [n] [\numbers] +\defineconversion [N] [\Numbers] +\defineconversion [m] [\mediaeval] +\defineconversion [o] [\oldstylenumerals] +\defineconversion [O] [\oldstylenumerals] +\defineconversion [or] [\oldstyleromannumerals] + +\defineconversion [\v!romannumerals] [\romannumerals] +\defineconversion [\v!Romannumerals] [\Romannumerals] + +\defineconversion [i] [\romannumerals] +\defineconversion [I] [\Romannumerals] +\defineconversion [r] [\romannumerals] +\defineconversion [R] [\Romannumerals] + +\defineconversion [KR] [\smallcappedromannumerals] +\defineconversion [RK] [\smallcappedromannumerals] + +\defineconversion [\v!greek] [\greeknumerals] +\defineconversion [\v!Greek] [\Greeknumerals] + +\defineconversion [g] [\greeknumerals] +\defineconversion [G] [\Greeknumerals] + +%defineconversion [ñ] [\spanishnumerals] +%defineconversion [Ñ] [\Spanishnumerals] + +\defineconversion [abjadnumerals] [\abjadnumerals] +\defineconversion [abjadnodotnumerals] [\abjadnodotnumerals] +\defineconversion [abjadnaivenumerals] [\abjadnaivenumerals] + +\defineconversion [hebrewnumerals] [\hebrewnumerals] +\defineconversion [yiddishnumerals] [\yiddishnumerals] + +% users can do: \defineconversion [he] [\hebrewnumerals] +% users can do: \defineconversion [yi] [\hebrewnumerals] + +\defineconversion [thainumerals] [\thainumerals] +\defineconversion [devanagarinumerals] [\devanagarinumerals] +\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals] +\defineconversion [gujaratinumerals] [\gujaratinumerals] +\defineconversion [tibetannumerals] [\tibetannumerals] +\defineconversion [greeknumerals] [\greeknumerals] +\defineconversion [Greeknumerals] [\Greeknumerals] +\defineconversion [arabicnumerals] [\arabicnumerals] +\defineconversion [persiannumerals] [\persiannumerals] +\defineconversion [arabicexnumerals] [\arabicexnumerals] +\defineconversion [arabicdecimals] [\arabicdecimals] +\defineconversion [persiandecimals] [\persiandecimals] + +\defineconversion [koreannumerals] [\koreannumerals] +\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while) +\defineconversion [koreanparenthesisnumerals] + [\koreanparenthesisnumerals] +\defineconversion [koreancirclenumerals] [\koreancirclenumerals] + +\defineconversion [kr] [\koreannumerals] +\defineconversion [kr-p] [\koreanparentnumerals] +\defineconversion [kr-c] [\koreancirclenumerals] + +\defineconversion [chinesenumerals] [\chinesenumerals] +\defineconversion [chinesecapnumerals] [\chinesecapnumerals] +\defineconversion [chineseallnumerals] [\chineseallnumerals] + +\defineconversion [cn] [\chinesenumerals] +\defineconversion [cn-c] [\chinesecapnumerals] +\defineconversion [cn-a] [\chineseallnumerals] + +%D Moved from lang-def.mkiv: +%D +%D Define these as the general character enumeration when language is Slovenian. If +%D you feel uncomfortable with this, mail Mojca, since she promised to to take the +%D heat. Pablo was next to request this. We changed characters to numerals for this +%D feature. We do need these definitions for mechanisms like itemize that check +%D for converters. + +\permanent\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}} +\permanent\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}} + +\permanent\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}} +\permanent\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}} + +\permanent\def\russiannumerals #1{\clf_alphabetic\numexpr#1\relax{ru}} +\permanent\def\russianNumerals #1{\clf_Alphabetic\numexpr#1\relax{ru}} + +%defineconversion [\s!sl] [character] [\sloveniannumerals] +%defineconversion [\s!sl] [Character] [\slovenianNumerals] +%defineconversion [\s!sl] [characters] [\sloveniannumerals] +%defineconversion [\s!sl] [Characters] [\slovenianNumerals] + +\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals] +\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals] + +\defineconversion [\s!sl] [a] [\sloveniannumerals] +\defineconversion [\s!sl] [A] [\slovenianNumerals] +\defineconversion [\s!sl] [AK] [\smallcapped\sloveniannumerals] +\defineconversion [\s!sl] [KA] [\smallcapped\sloveniannumerals] + +%defineconversion [\s!es] [character] [\spanishnumerals] +%defineconversion [\s!es] [Character] [\spanishNumerals] +%defineconversion [\s!es] [characters] [\spanishnumerals] +%defineconversion [\s!es] [Characters] [\spanishNumerals] + +\defineconversion [\s!es] [alphabetic] [\spanishnumerals] +\defineconversion [\s!es] [Alphabetic] [\spanishNumerals] + +\defineconversion [\s!es] [a] [\spanishnumerals] +\defineconversion [\s!es] [A] [\spanishNumerals] +\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals] +\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals] + +%defineconversion [\s!ru] [character] [\russiannumerals] +%defineconversion [\s!ru] [Character] [\russianNumerals] +%defineconversion [\s!ru] [characters] [\russiannumerals] +%defineconversion [\s!ru] [Characters] [\russianNumerals] + +\defineconversion [\s!ru] [alphabetic] [\russiannumerals] +\defineconversion [\s!ru] [Alphabetic] [\russianNumerals] + +\defineconversion [\s!ru] [a] [\russiannumerals] +\defineconversion [\s!ru] [A] [\russianNumerals] +\defineconversion [\s!ru] [AK] [\smallcapped\russiannumerals] +\defineconversion [\s!ru] [KA] [\smallcapped\russiannumerals] + +\defineconversion [sloveniannumerals] [\sloveniannumerals] +\defineconversion [slovenianNumerals] [\slovenianNumerals] + +\defineconversion [spanishnumerals] [\spanishnumerals] +\defineconversion [spanishNumerals] [\spanishNumerals] + +\defineconversion [russiannumerals] [\russiannumerals] +\defineconversion [russianNumerals] [\russianNumerals] + +%D In case a font has no greek (WS): + +\defineconversion [mathgreek] + [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ}, + \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ}, + \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ}, + \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}] + +%D Handy too (expanded!): + +\permanent\def\unihex#1{\clf_unihex\numexpr#1\relax} + +%D Symbol sets: + +\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo + +% \defineconversion +% [set 0] +% [{\symbol[bullet]}, +% {\symbol[dash]}, +% {\symbol[star]}, +% {\symbol[triangle]}, +% {\symbol[circle]}, +% {\symbol[medcircle]}, +% {\symbol[bigcircle]}, +% {\symbol[square]}, +% {\symbol[checkmark]}] + +% \defineconversion +% [set 1] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] +% +% \defineconversion +% [set 2] +% [\mathematics{\ast}, +% \mathematics{\dag}, +% \mathematics{\ddag}, +% \mathematics{\ast\ast}, +% \mathematics{\dag\dag}, +% \mathematics{\ddag\ddag}, +% \mathematics{\ast\ast\ast}, +% \mathematics{\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag}, +% \mathematics{\ast\ast\ast\ast}, +% \mathematics{\dag\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag\ddag}] +% +% \defineconversion +% [set 3] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\P}, +% \mathematics{\P\P}, +% \mathematics{\P\P\P}, +% \mathematics{\S}, +% \mathematics{\S\S}, +% \mathematics{\S\S\S}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] + +\defineconversion + [set 0] + [\symbol{bullet}, + \symbol{dash}, + \symbol{star}, + \symbol{triangle}, + \symbol{circle}, + \symbol{medcircle}, + \symbol{bigcircle}, + \symbol{square}, + \symbol{checkmark}] + +\defineconversion + [set 1] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] + +\defineconversion + [set 2] + [\textormathchars{∗}, + \textormathchars{†}, + \textormathchars{‡}, + \textormathchars{∗∗}, + \textormathchars{††}, + \textormathchars{‡‡}, + \textormathchars{∗∗∗}, + \textormathchars{†††}, + \textormathchars{‡‡‡}, + \textormathchars{∗∗∗∗}, + \textormathchars{††††}, + \textormathchars{‡‡‡‡}] + +\defineconversion + [set 3] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{¶}, + \textormathchars{¶¶}, + \textormathchars{¶¶¶}, + \textormathchars{§}, + \textormathchars{§§}, + \textormathchars{§§§}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] + +%D Iteration of suggestion by WS on mailinglist 2010.12.22: +%D +%D \starttyping +%D \setupfloatsplitting[conversion=continued] +%D \stoptyping + +\permanent\protected\def\continuednumber#1% + {\labeltext{\ifcase#1\or\else\v!continued\fi}} + +\defineconversion + [\v!continued] + [\continuednumber] + +%D Taken from x-asciimath (see digits-001.tex for an example): + +\let\spaceddigitsmethod \empty % alternative methods : 1 default, 2 and 3 only when > 4 +\let\spaceddigitssymbol \empty % extra splitter symbol : {,} +\let\spaceddigitsseparator\empty % separator symbol : {\Uchar{"2008}} + +\permanent\protected\def\spaceddigits#1% + {\clf_spaceddigits + method {\spaceddigitsmethod}% + symbol {\spaceddigitssymbol}% + separator {\spaceddigitsseparator}% + data {#1}% + \relax} + +%D For those who sart counting at zero: +%D +%D \starttyping +%D \defineconversionset [zero] [n,zero] [n] +%D +%D \setuphead [sectionconversionset=zero] +%D +%D \starttext +%D \startchapter [title=Introduction] +%D \startsection [title=First topic] \stopsection +%D \startsection [title=Second topic] \stopsection +%D \stopchapter +%D \stoptext +%D \stoptyping + +\permanent\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax} + +\defineconversion [zero] [\zeronumberconversion] + +\protect \endinput diff --git a/tex/context/base/mkxl/core-ctx.mkxl b/tex/context/base/mkxl/core-ctx.mkxl new file mode 100644 index 000000000..8837640d4 --- /dev/null +++ b/tex/context/base/mkxl/core-ctx.mkxl @@ -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}{} + +\unprotect + +% called directly in core-def.mkiv +% +% \protected\def\job_options_get_commandline {\clf_setdocumentcommandline} +% \protected\def\job_options_get_ctxfile {\clf_setdocumentctxfile} +% \protected\def\job_options_set_modes {\clf_setdocumentmodes} +% \protected\def\job_options_set_modules {\clf_setdocumentmodules} +% \protected\def\job_options_set_environments{\clf_setdocumentenvironments} +% \protected\def\job_options_set_filenames {\clf_setdocumentfilenames} + +\protect \endinput diff --git a/tex/context/base/mkxl/core-dat.mkxl b/tex/context/base/mkxl/core-dat.mkxl new file mode 100644 index 000000000..7360a4e46 --- /dev/null +++ b/tex/context/base/mkxl/core-dat.mkxl @@ -0,0 +1,110 @@ +%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}{} + +\installcorenamespace{dataset} + +\installcommandhandler \??dataset {dataset} \??dataset + +\permanent\tolerant\protected\def\setdataset[#1]#*[#2]#*[#3]% + {\begingroup + \edef\currentdataset{#1}% + \ifparameters\or\or + \clf_setdataset + name {\currentdataset}% + delay {\datasetparameter\c!delay}% + data {#2}% + \relax + \or + \edef\currentdataset{#1}% + \clf_setdataset + name {\currentdataset}% + tag {#2}% + delay {\datasetparameter\c!delay}% + data {#3}% + \relax + \fi + \endgroup} + +\permanent\def\datasetvariable#1#2#3% + {\clf_datasetvariable{#1}{#2}{#3}} + +\installcorenamespace{pagestate} +\installcorenamespace{pagestatecounter} + +\installcommandhandler \??pagestate {pagestate} \??pagestate + +\def\syst_pagestates_allocate + {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname} + +\appendtoks + \syst_pagestates_allocate +\to \everydefinepagestate + +\setuppagestate + [\c!delay=\v!yes] + +\permanent\tolerant\protected\def\setpagestate[#1]#*[#2]% + {\begingroup + \edef\currentpagestate{#1}% + \ifcsname\??pagestatecounter\currentpagestate\endcsname + \scratchcounter\lastnamedcs + \advance\scratchcounter\plusone + \else + \scratchcounter\plusone + \syst_pagestates_allocate + \fi + \global\csname\??pagestatecounter\currentpagestate\endcsname\scratchcounter + \clf_setpagestate + name {\currentpagestate}% + tag {\ifparameter#2\or#2\else\number\scratchcounter\fi}% + delay {\pagestateparameter\c!delay}% + \relax + \endgroup} + +\permanent\protected\def\autosetpagestate#1% + {\syst_pagestates_set[#1]\relax} + +\permanent\def\autopagestatenumber#1{\begincsname\??pagestatecounter#1\endcsname} + +\permanent\def\pagestaterealpage #1#2{\clf_pagestaterealpage {#1}{#2}} +\permanent\def\setpagestaterealpageno#1#2{\clf_setpagestaterealpageno{#1}{#2}} +\permanent\def\pagestaterealpageorder#1#2{\clf_pagestaterealpageorder{#1}#2\relax} + +\permanent\def\autopagestaterealpage #1{\clf_pagestaterealpage {#1}{\number\autopagestatenumber{#1}}} +\permanent\def\setautopagestaterealpageno#1{\clf_setpagestaterealpageno{#1}{\number\autopagestatenumber{#1}}} +\permanent\def\autopagestaterealpageorder#1{\clf_pagestaterealpageorder{#1}\numexpr\autopagestatenumber{#1}\relax} + +\protect diff --git a/tex/context/base/mkxl/core-def.mkxl b/tex/context/base/mkxl/core-def.mkxl new file mode 100644 index 000000000..c7baf9ab1 --- /dev/null +++ b/tex/context/base/mkxl/core-def.mkxl @@ -0,0 +1,182 @@ +%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 + % + \spac_paragraph_wrap + \spac_paragraph_freeze +\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 + % for the moment here (before doc env) + \setupoutput[pdf]% + % + \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: + +\pushoverloadmode + \frozen\protected\def\arg{\mathortext\normalmatharg\normaltextarg} +\popoverloadmode + +% 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] + +%D Till we fixed all styles: + +\enforced\let\\\crlf % frozen or permanent? + +\protect \endinput diff --git a/tex/context/base/mkxl/core-env.lmt b/tex/context/base/mkxl/core-env.lmt new file mode 100644 index 000000000..388e96787 --- /dev/null +++ b/tex/context/base/mkxl/core-env.lmt @@ -0,0 +1,213 @@ +if not modules then modules = { } end modules ['core-env'] = { + version = 1.001, + comment = "companion to core-env.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- maybe this will move to the context name space although the +-- plurals are unlikely to clash with future tex primitives +-- +-- if tex.modes['xxxx'] then .... else .... end + +local rawset = rawset + +local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns + +local context = context +local ctxcore = context.core + +local texgetcount = tex.getcount +local texgetintegervalue = token.get_integer -- todo: in tex namespace + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local setmetatablecall = table.setmetatablecall + +local createtoken = token.create +local isdefined = tokens.isdefined + +texmodes = allocate { } tex.modes = texmodes +texsystemmodes = allocate { } tex.systemmodes = texsystemmodes +texconstants = allocate { } tex.constants = texconstants +texconditionals = allocate { } tex.conditionals = texconditionals +texifs = allocate { } tex.ifs = texifs +texisdefined = allocate { } tex.isdefined = texisdefined + +local modes = { } +local systemmodes = { } + +-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching +-- at the lua end is not that bad (and we need more anyway) + +local cache = tokens.cache + +-- we can have a modes cache too + +local commandcodes = tokens.commands +local iftrue = cache["iftrue"].index + +-- local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen +-- local countcode = cache["scratchcounter"].command -- tokens.commands.register_int +-- local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks +-- local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue +-- local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue +-- local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test + +-- local types = { +-- [dimencode] = "dimen", +-- [countcode] = "count", +-- [tokencode] = "token", +-- [skipcode] = "skip", +-- [muskipcode] = "muskip", +-- -- [attributecode] = "attribute", +-- [conditioncode] = "condition" +-- } + +local dimencode = commandcodes.register_dimen -- cache["scratchdimen"] .command -- tokens.commands.register_dimen +local countcode = commandcodes.register_int -- cache["scratchcounter"].command -- tokens.commands.register_int +local tokencode = commandcodes.register_toks -- ["scratchtoks"] .command -- tokens.commands.register_toks +local skipcode = commandcodes.register_glue -- cache["scratchskip"] .command -- tokens.commands.register_glue +local muskipcode = commandcodes.register_mu_glue -- cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue +local conditioncode = commandcodes.if_test -- cache["iftrue"] .command -- tokens.commands.if_test +local integercode = commandcodes.integer + +local types = { + [dimencode] = "dimen", + [countcode] = "count", + [tokencode] = "token", + [skipcode] = "skip", + [muskipcode] = "muskip", + -- [attributecode] = "attribute", + [conditioncode] = "condition", + [integercode] = "integer", +} + +setmetatableindex(texmodes, function(t,k) + local m = systemmodes[k] + if not m then + local n = "mode>" .. k + m = function() return texgetintegervalue(n) == 1 end + rawset(modes,k,m) + end + return m() +end) + +setmetatableindex(texsystemmodes, function(t,k) + local m = systemmodes[k] + if not m then + local n = "mode>*" .. k + m = function() return texgetintegervalue(n) == 1 end + rawset(modes,k,m) + end + return m() +end) + +-- also a call method + +context.settrialtypesettingmethod(function() return texsystemmodes.trialtypesetting end) + +setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end) +setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end) +setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end) +setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end) +setmetatablenewindex(texifs, function(t,k) end) + +-- if we really need performance we can have a dedicated cache for each +-- kind of variable ... maybe we no longer have to cache anyway (in lmtx) + +setmetatableindex(texconstants, function(t,k) + -- return cache[k].command == countcode and texgetcount(k) or 0 + return cache[k].command == integercode and texgetintegervalue(k) or 0 +end) + +setmetatableindex(texconditionals, function(t,k) -- 0 == true + -- return cache[k].command == countcode and texgetcount(k) == 0 + return cache[k].command == integercode and texgetintegervalue(k) == 0 +end) + +setmetatableindex(texifs, function(t,k) + local c = cache[k] + return c.command == conditioncode and c.index == iftrue +end) + +tex.isdefined = isdefined + +function tex.isdimen(name) + local hit = cache[name] + return hit.command == dimencode and hit.index or true +end + +function tex.iscount(name) + local hit = cache[name] + return hit.command == countcode and hit.index or true +end + +function tex.istoken(name) + local hit = cache[name] + return hit.command == tokencode and hit.index or true +end + +function tex.isskip(name) + local hit = cache[name] + return hit.command == skipcode and hit.index or true +end + +function tex.ismuskip(name) + local hit = cache[name] + return hit.command == muskipcode and hit.index or true +end + +function tex.type(name) + return types[cache[name].command] or "macro" +end + +function context.setconditional(name,value) + if value then + ctxcore.settruevalue(name) + else + ctxcore.setfalsevalue(name) + end +end + +function context.setmode(name,value) + if value then + ctxcore.setmode(name) + else + ctxcore.resetmode(name) + end +end + +function context.setsystemmode(name,value) + if value then + ctxcore.setsystemmode(name) + else + ctxcore.resetsystemmode(name) + end +end + +context.modes = texmodes +context.systemmodes = texsystemmodes +context.conditionals = texconditionals +-------.constants = texconstants +-------.ifs = texifs + +local sep = S("), ") +local str = C((1-sep)^1) +local tag = P("(") * C((1-S(")" ))^1) * P(")") +local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")") + +local pattern = ( + P("lua") * tag / ctxcore.luasetup + + P("xml") * arg / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments + + (P("tex") * tag + str) / ctxcore.texsetup + + sep^1 +)^1 + +interfaces.implement { + name = "autosetups", + actions = function(str) lpegmatch(pattern,str) end, + arguments = "string" +} diff --git a/tex/context/base/mkxl/core-env.mkxl b/tex/context/base/mkxl/core-env.mkxl new file mode 100644 index 000000000..ccb5b665e --- /dev/null +++ b/tex/context/base/mkxl/core-env.mkxl @@ -0,0 +1,770 @@ +%D \module +%D [ file=core-env, % was core-new +%D version=1995.01.01, % wrong +%D title=\CONTEXT\ Core Macros, +%D subtitle=New ones, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Core Macros / Environments} + +\registerctxluafile{core-env}{autosuffix} + +\unprotect + +%D Modes: +%D +%D \starttyping +%D \enablemode[screen,paper,bound] +%D +%D \doifmodeelse {paper} {this} {that} +%D \doifmode {paper,screen} {this} +%D \doifnotmode {paper,bound} {that} +%D +%D \startmode [list] +%D \stopmode +%D +%D \startnotmode [list] +%D \stopnotmode +%D \stoptyping +%D +%D system modes have a * as prefix +%D +%D Sometimes, we want to prevent a mode for being set. Think of situations where a +%D style enables a mode, but an outer level style does not want that. Preventing can +%D be considered a permanent disabling on forehand. + +\aliased\let\systemmodeprefix\wildcardsymbol + +% we will have \installcorenamespace{mode} but need some hackery at the lua end then + +% TODO: make them mutable, also at the lua end + +\installcorenamespace{modestack} + +\immutable\def\??mode{mode>} % special namespace, also used at lua end + +\permanent\protected\def\newmode #1{\ifcsname \??mode#1\endcsname\else\resetmode{#1}\fi} +\permanent\protected\def\setmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\plusone} +\permanent\protected\def\resetmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\zerocount} +\permanent\protected\def\globalsetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\plusone} +\permanent\protected\def\globalresetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\zerocount} + +\permanent\protected\def\newsystemmode #1{\ifcsname \??mode\systemmodeprefix#1\endcsname\else\resetsystemmode{#1}\fi} +\permanent\protected\def\setsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} +\permanent\protected\def\resetsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} +\permanent\protected\def\globalsetsystemmode #1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} +\permanent\protected\def\globalresetsystemmode#1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} + +\expandafter \appendtoks + \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\plusone + \luacopyinputnodes\plusone +\to \everysettrialtypesetting + +\expandafter \appendtoks + \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\zerocount + \luacopyinputnodes\zerocount +\to \everyresettrialtypesetting + +\pushoverloadmode \newsystemmode{trialtypesetting} \popoverloadmode + +\the\everyresettrialtypesetting + +% user ones + +\mutable\let\syst_mode_prefix\relax + +\permanent\protected\def\preventmode{\unprotect\syst_modes_prevent} +\permanent\protected\def\enablemode {\unprotect\syst_modes_enable } +\permanent\protected\def\disablemode{\unprotect\syst_modes_disable} + +\permanent\protected\def\globalpreventmode{\let\syst_mode_prefix\global\unprotect\syst_modes_prevent} +\permanent\protected\def\globalenablemode {\let\syst_mode_prefix\global\unprotect\syst_modes_enable } +\permanent\protected\def\globaldisablemode{\let\syst_mode_prefix\global\unprotect\syst_modes_disable} + +\def\syst_modes_prevent[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_prevent_indeed\let\syst_mode_prefix\relax} +\def\syst_modes_enable [#1]{\protect\fastprocesscommacommand[#1]\syst_modes_enable_indeed \let\syst_mode_prefix\relax} +\def\syst_modes_disable[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_disable_indeed\let\syst_mode_prefix\relax} + +\def\syst_modes_prevent_indeed#1% + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plustwo} + +\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \ifnum\lastnamedcs=\plustwo\else + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plusone + \fi} + +\def\syst_modes_disable_indeed#1% + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \ifnum\lastnamedcs=\plustwo\else + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\zerocount + \fi} + +%D If you do a lot of mode testing, it makes sense to define modes (or disable them +%D explicitly if unset. This makes testing twice as fast. Often one enables modes +%D beforehand, in which case \type {\definemode} would reset the mode. The optional +%D second argument \type {keep} will prevent changing the already set mode but defines +%D it when undefined. + +\permanent\protected\def\definemode + {\unprotect + \syst_modes_define} + +\tolerant\def\syst_modes_define[#1]#*[#2]% + {\protect + \edef\m_modes_asked{#2}% + \fastprocesscommacommand[#1]\syst_modes_define_indeed} + +\def\syst_modes_define_indeed#1% + {\ifcsname\??mode#1\endcsname + % already set + \else + \newmode{#1}% + \fi + \ifx\m_modes_asked\v!keep + % not changes, disabled when undefined + \orelse\ifx\m_modes_asked\v!yes + \setmode{#1}% + \else + \resetmode{#1}% + \fi} + +% handy for mp + +\permanent\def\booleanmodevalue#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs + \s!false + \or + \s!true + \else + \s!false + \fi + \else + \s!false + \fi} + +% check macros + +\newconditional\c_checked_mode + +% one + +\def\syst_modes_check_indeed#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs\else + \let\syst_modes_check_step\gobbleoneargument + \fi + \fi} + +\def\syst_modes_check_nop#1#2#3% + {\let\syst_modes_check_step\syst_modes_check_indeed + \fastprocesscommacommand[#3]\syst_modes_check_step + \ifx\syst_modes_check_step\gobbleoneargument + \expandafter#1% + \else + \expandafter#2% + \fi} + +\def\syst_modes_check_yes#1#2#3% + {\ifcase\lastnamedcs + \expandafter#2% + \or + \expandafter#1% + \else + \expandafter#2% + \fi} + +\def\syst_modes_check_lr#1#2#3% + {\ifcsname\??mode#3\endcsname + \expandafter\syst_modes_check_yes + \else + \expandafter\syst_modes_check_nop + \fi#1#2{#3}} + +\def\syst_modes_check_ss#1#2[#3]% + {\ifcsname\??mode#3\endcsname + \expandafter\syst_modes_check_yes + \else + \expandafter\syst_modes_check_nop + \fi#1#2{#3}} + +% all + +\def\syst_modes_check_all_indeed#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs + \let\syst_modes_check_all_step\gobbleoneargument + \or + % enabled + \else + \let\syst_modes_check_all_step\gobbleoneargument + \fi + \else + \let\syst_modes_check_all_step\gobbleoneargument + \fi} + +\def\syst_modes_check_all_lr#1#2#3% + {\let\syst_modes_check_all_step\syst_modes_check_all_indeed + \fastprocesscommacommand[#3]\syst_modes_check_all_step + \ifx\syst_modes_check_all_step\gobbleoneargument + \expandafter#2% + \else + \expandafter#1% + \fi} + +\def\syst_modes_check_all_ss#1#2[#3]% + {\let\syst_modes_check_all_step\syst_modes_check_all_indeed + \fastprocesscommacommand[#3]\syst_modes_check_all_step + \ifx\syst_modes_check_all_step\gobbleoneargument + \expandafter#2% + \else + \expandafter#1% + \fi} + +\permanent\protected\def\doifelsemode {\syst_modes_check_lr \firstoftwoarguments \secondoftwoarguments} +\permanent\protected\def\doifmode {\syst_modes_check_lr \firstofoneargument \gobbleoneargument} +\permanent\protected\def\doifnotmode {\syst_modes_check_lr \gobbleoneargument \firstofoneargument} +\permanent\protected\def\startmode {\syst_modes_check_ss \donothing \syst_modes_stop_yes} +\permanent\protected\def\startnotmode {\syst_modes_check_ss \syst_modes_stop_nop \donothing} +\permanent\protected\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments \secondoftwoarguments} +\permanent\protected\def\doifallmodes {\syst_modes_check_all_lr\firstofoneargument \gobbleoneargument} +\permanent\protected\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument \firstofoneargument} +\permanent\protected\def\startallmodes {\syst_modes_check_all_ss\donothing \syst_modes_stop_all_yes} +\permanent\protected\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing} + +\aliased\let\doifmodeelse \doifelsemode +\aliased\let\doifallmodeselse\doifelseallmodes + +\permanent\protected\def\stopmode {} % no relax +\permanent\protected\def\stopnotmode {} % no relax +\permanent\protected\def\stopallmodes {} % no relax +\permanent\protected\def\stopnotallmodes{} % no relax + +\def\syst_modes_stop_yes #1\stopmode {} +\def\syst_modes_stop_nop #1\stopnotmode {} +\def\syst_modes_stop_all_yes#1\stopallmodes {} +\def\syst_modes_stop_all_nop#1\stopnotallmodes{} + +%D Pushing/popping: + +\permanent\protected\def\pushmode[#1]{\expandafter\pushmacro\csname\??mode#1\endcsname} +\permanent\protected\def\popmode [#1]{\expandafter\popmacro \csname\??mode#1\endcsname} + +\permanent\protected\def\pushsystemmode#1{\expandafter\pushmacro\csname\??mode\systemmodeprefix#1\endcsname} +\permanent\protected\def\popsystemmode #1{\expandafter\popmacro \csname\??mode\systemmodeprefix#1\endcsname} + +%D Here is a relatively new variant of mode checking: +%D +%D \starttyping +%D \enablemode[two] +%D +%D \startmodeset +%D [one] {1} +%D [two] {2} +%D [two] {2} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D +%D \startmodeset +%D [one] {1} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D +%D \startmodeset +%D [one] { +%D \input tufte +%D } +%D [two] { +%D \startmodeset +%D [one] {1} +%D [two] {2} +%D [two] {2} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D } +%D [three] { +%D \input zapf +%D } +%D [default] { +%D \input ward +%D } +%D \stopmodeset +%D \stoptyping + +\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped + +\installmacrostack\c_syst_modes_set_done + +\permanent\protected\def\startmodeset + {\push_macro_c_syst_modes_set_done + \setfalse\c_syst_modes_set_done + \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\aliased\let\stopmodeset\relax + +\def\syst_modes_set_start[#1]% + {\edef\m_mode_case{#1}% + \unless\ifx\m_mode_case\s!default + \expandafter\syst_modes_set_check + \orelse\ifconditional\c_syst_modes_set_done + \expandafter\syst_modes_set_quit + \else + \expandafter\syst_modes_set_yes + \fi} + +\def\syst_modes_set_check + {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case} + +\def\syst_modes_set_yes#1% + {\settrue\c_syst_modes_set_done + #1% + \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\def\syst_modes_set_nop#1% + {\doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\def\syst_modes_set_quit#-\stopmodeset + {\pop_macro_c_syst_modes_set_done} + +%D Lets now set a mode: + +\enablemode[mkiv] \newsystemmode{mkiv} \setsystemmode{mkiv} + +%D Setups: + +\installcorenamespace{setup} % we can probably get rid of some :'s later on + +% \protected\def\startsetups{} % to please dep checker +% \protected\def\stopsetups {} % to please dep checker +% +% \protected\def\setups{\doifelsenextbgroup\syst_setups_a\syst_setups_b} % {..} or [..] +% \protected\def\setup {\doifelsenextbgroup\syst_setups \syst_setups_c} % {..} or [..] +% +% \def\syst_setups_a #1{\processcommacommand[#1]\syst_setups} % {..} +% \def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..] +% \def\syst_setups_c[#1]{\syst_setups{#1}} % [..] + +\permanent\protected\tolerant\def\setups[#1]#;#2{\processcommacommand[#1#2]\syst_setups} % {..} or [..] +\permanent\protected\tolerant\def\setup [#1]#;#2{\syst_setups{#1#2}} % {..} or [..] + +\letvalue{\??setup:\??empty}\gobbleoneargument + +\permanent\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: + +\permanent\def\fastsetup #1{\csname\??setup:#1\endcsname\empty} +\permanent\def\fastsetupwithargument #1{\csname\??setup:#1\endcsname} % swapped per 2015-08-30 +\permanent\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 + +\permanent\protected\def\doprocesslocalsetups#1% sort of public, fast local variant + {\edef\m_syst_setups_asked{#1}% + \ifempty\m_syst_setups_asked\else + \expandafter\syst_setups_process_local + \fi} + +\permanent\protected\def\usesetupsparameter#1% + {\edef\m_syst_setups_asked{#1\c!setups}% + \ifempty\m_syst_setups_asked\else + \expandafter\syst_setups_process_local + \fi} + +% setups=S1 +% setups=lua(S2) +% setups=S3 +% setups={S1,lua(S2),xml(test{123}),S3} + +\def\syst_setups_process_local + {\clf_autosetups{\m_syst_setups_asked}% + \relax} % let's prevent lookahead + +\permanent\def\autosetups#1{\clf_autosetups{#1}} % todo: public implementor + +\permanent\edef\setupwithargument#1% saves a few expansions + {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname} + +\permanent\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}} + +\aliased\let\directsetup\syst_setups +\aliased\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup + +\permanent\protected\def\doifelsesetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifsetupselse\doifelsesetups + +\permanent\protected\def\doifsetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotsetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +% maybe some day: +% +% \protected\def\fastsetupfallback#1#2% +% {\ifcsname\??setup:#1\endcsname +% \expandafter\lastnamedcs +% \else +% \csname\??setup:#2\expandafter\endcsname +% \fi} +% +% or +% +% \protected\def\fastsetupfallback#1#2#3% prefix preferred fallback +% {\ifcsname\??setup:#1#2\endcsname +% \expandafter\lastnamedcs +% \else +% \csname\??setup:#1#3\expandafter\endcsname +% \fi} + +% \startluasetups oeps +% context("DONE") +% a = 1 +% b = 1 +% \stopluasetups +% +% \luasetup{oeps} +% +% \startsetups xxx +% ziezo +% \stopsetups +% +% \directsetup{xxx} +% +% \startxmlsetups zzz +% [[#1]] +% \stopxmlsetups +% +% \xmlsetup{123}{zzz} +% +% \startbuffer[what] +% context("DONE") +% \stopbuffer +% +% \startbuffer +% context("MORE") +% \stopbuffer +% +% \ctxluabuffer[what] +% +% \ctxluabuffer + +\newtoks\t_syst_setups_tex \appendtoks + \catcode\endoflineasciicode \ignorecatcode +\to \t_syst_setups_tex + +\newtoks\t_syst_setups_loc \appendtoks + \catcode\endoflineasciicode \ignorecatcode +\to \t_syst_setups_loc + +\newtoks\t_syst_setups_raw \appendtoks + % nothing +\to \t_syst_setups_raw + +\newtoks\t_syst_setups_xml \appendtoks + \catcode\endoflineasciicode\ignorecatcode + \catcode\barasciicode \othercatcode +\to \t_syst_setups_xml + +\newtoks\t_syst_setups_lua \appendtoks + \obeylualines + \obeyluatokens +\to \t_syst_setups_lua + +% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete. + +\permanent\protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_yes\syst_setups_start_lua_nop} \aliased\let\stopluasetups \relax +\permanent\protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_yes\syst_setups_start_xml_nop} \aliased\let\stopxmlsetups \relax +\permanent\protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_yes\syst_setups_start_raw_nop} \aliased\let\stoprawsetups \relax +\permanent\protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_yes\syst_setups_start_loc_nop} \aliased\let\stoplocalsetups\relax +\permanent\protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_yes\syst_setups_start_tex_nop} \aliased\let\stopsetups \relax + +\def\syst_setups_start_lua_two#1#2#+\stopluasetups {\endgroup\dodoglobal\instance\defcsname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_xml_two#1#2#+\stopxmlsetups {\endgroup\dodoglobal\instance\defcsname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_raw_two#1#2#+\stoprawsetups {\endgroup\dodoglobal\instance\defcsname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_loc_two#1#2#+\stoplocalsetups{\endgroup\dodoglobal\instance\defcsname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_tex_two#1#2#+\stopsetups {\endgroup\dodoglobal\instance\defcsname\??setup#1:#2\endcsname##1{#3}} + +\tolerant\def\syst_setups_start_lua_yes[#1]#*[#2]% + {\the\t_syst_setups_lua + \ifarguments\expandafter\syst_setups_start_lua_one + \or \expandafter\syst_setups_start_lua_one + \else \expandafter\syst_setups_start_lua_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_xml_yes[#1]#*[#2]% + {\the\t_syst_setups_xml + \ifarguments\expandafter\syst_setups_start_xml_one + \or \expandafter\syst_setups_start_xml_one + \else \expandafter\syst_setups_start_xml_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_raw_yes[#1]#*[#2]% + {\the\t_syst_setups_raw + \ifarguments\expandafter\syst_setups_start_raw_one + \or \expandafter\syst_setups_start_raw_one + \else \expandafter\syst_setups_start_raw_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_loc_yes[#1]#*[#2]% + {\the\t_syst_setups_loc + \ifarguments\expandafter\syst_setups_start_loc_one + \or \expandafter\syst_setups_start_loc_one + \else \expandafter\syst_setups_start_loc_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_tex_yes[#1]#*[#2]% + {\the\t_syst_setups_tex + \ifarguments\expandafter\syst_setups_start_tex_one + \or \expandafter\syst_setups_start_tex_one + \else \expandafter\syst_setups_start_tex_two + \fi{#1}{#2}} + +\def\syst_setups_start_lua_nop#1 {\the\t_syst_setups_lua\syst_setups_start_lua_two{}{#1}} % space delimited +\def\syst_setups_start_xml_nop#1 {\the\t_syst_setups_xml\syst_setups_start_xml_two{}{#1}} % space delimited +\def\syst_setups_start_raw_nop#1 {\the\t_syst_setups_raw\syst_setups_start_raw_two{}{#1}} % space delimited +\def\syst_setups_start_loc_nop#1 {\the\t_syst_setups_loc\syst_setups_start_loc_two{}{#1}} % space delimited +\def\syst_setups_start_tex_nop#1 {\the\t_syst_setups_tex\syst_setups_start_tex_two{}{#1}} % space delimited + +\def\syst_setups_start_lua_one#1#2{\syst_setups_start_lua_two{}{#1}} % [..] +\def\syst_setups_start_xml_one#1#2{\syst_setups_start_xml_two{}{#1}} % [..] +\def\syst_setups_start_raw_one#1#2{\syst_setups_start_raw_two{}{#1}} % [..] +\def\syst_setups_start_loc_one#1#2{\syst_setups_start_loc_two{}{#1}} % [..] +\def\syst_setups_start_tex_one#1#2{\syst_setups_start_tex_two{}{#1}} % [..] + +\permanent\def\luasetup#1{\ctxlua{\syst_setups{#1}}} + +%D System setups: + +\aliased\let\systemsetupsprefix\wildcardsymbol + +\permanent\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}} + +\permanent\protected\def\resetsetups[#1]% see x-fo for usage + {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname + \dodoglobal\undefinevalue{\??setup\ifgridsnapping\v!grid\fi:#1}% + \else + \dodoglobal\undefinevalue{\??setup:#1}% + \fi} + +\permanent\tolerant\protected\def\copysetups[#1]#*[#2]% + {\ifcsname\??setup:#2\endcsname + \letcsname\??setup:#1\expandafter\endcsname\lastnamedcs + \fi} + +\permanent\protected\def\showsetupsdefinition[#1]% + {\showvalue{\??setup:#1}} % temp hack for debugging + +%D \macros +%D {setvariables,getvariable,getvariabledefault} +%D +%D \starttyping +%D \setvariables[xx][title=] +%D \setvariables[xx][title=test test] +%D \setvariables[xx][title=test $x=1$ test] % fatal error reported +%D \setvariables[xx][title=test {$x=1$} test] +%D \setvariables[xx][title] % fatal error reported +%D \setvariables[xx][titletitel=e] +%D \stoptyping + +\installcorenamespace{variables} + +\permanent\protected\def\setvariables {\syst_variables_set[\getrawparameters ]} +\permanent\protected\def\setevariables{\syst_variables_set[\getraweparameters]} +\permanent\protected\def\setgvariables{\syst_variables_set[\getrawgparameters]} +\permanent\protected\def\setxvariables{\syst_variables_set[\getrawxparameters]} + +\tolerant\def\syst_variables_set[#1]#*[#2]#*[#3]% tricky, test on s-pre-60 + {\doifelse{#2}\currentvariableclass + {#1[\??variables#2:][#3]}% + {\pushmacro\currentvariableclass + \def\currentvariableclass{#2}% + \getvariable{#2}\s!reset + #1[\??variables#2:][#3]% + \getvariable{#2}\s!set + \popmacro\currentvariableclass}} + +\permanent\protected\def\setvariable #1#2#3{\defcsname \??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setevariable#1#2#3{\edefcsname\??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setgvariable#1#2#3{\defcsname \??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setxvariable#1#2#3{\xdefcsname\??variables#1:#2\endcsname{#3}} + +\permanent \def\getvariable #1#2{\begincsname\??variables#1:#2\endcsname} +\permanent\protected\def\showvariable#1#2{\showvalue{\begincsname\??variables#1:#2\endcsname}} + +\let\currentvariableclass\empty + +%D \macros +%D {checkvariables} +%D +%D I'll probably forget that this on exists. + +\let\m_syst_variables_temp\empty + +\permanent\tolerant\def\checkvariables[#1]#*[#2]% + {\dogetparameters\syst_variables_check_value[#1][#2]} + +\def\syst_variables_check_value#1#2#3% + {\ifcsname\??variables#1:#2\endcsname + \edef\m_syst_variables_temp{\lastnamedcs}% + \ifempty\m_syst_variables_temp + \defcsname\??variables#1:#2\endcsname{#3}% + \fi + \else + \defcsname\??variables#1:#2\endcsname{#3}% + \fi} + +%D \macros +%D {doifelsevariable,doifvariable,doifnotvariable} +%D +%D A few trivial macros: + +\permanent\protected\def\doifelsevariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifvariableelse\doifelsevariable + +\permanent\protected\def\doifvariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotvariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +%D A few more (we could use a public test variable so that we only need to expand +%D once, assuming expandable variables): + +\letvalue{\??variables:}\empty + +\permanent\protected\def\doifelseemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifempty\m_syst_string_one + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifemptyvariableelse\doifelseemptyvariable + +\permanent\protected\def\doifemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifempty\m_syst_string_one + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifempty\m_syst_string_one + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\def\getvariabledefault#1#2% #3% can be command + {\ifcsname\??variables#1:#2\endcsname + \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\tolerant\protected\def\setupenv[#1]% + {\syst_variables_set[\getrawparameters][\s!environment][#1]} + +\permanent\protected\def\doifelseenv{\doifelsevariable \s!environment} +\permanent\protected\def\doifenv {\doifvariable \s!environment} +\permanent\protected\def\doifnotenv {\doifnotvariable \s!environment} +\permanent \def\env {\getvariable \s!environment} +\permanent \def\envvar {\getvariabledefault\s!environment} + +\aliased\let\doifenvelse\doifelseenv + +%D \macros +%D {defineselector,setupselector,select,directselect} +%D +%D \starttyping +%D \defineselector[caption][max=2,n=2] +%D +%D \start +%D \setupselector[caption][n=1] +%D \placelist[figure][criterium=all] +%D \stop +%D +%D \starttext +%D \placefigure +%D {\select{caption}{zapf}{\input zapf \relax}} +%D {} +%D \stoptext +%D \stoptyping + +\installcorenamespace{selector} + +\permanent\tolerant\protected\def\defineselector[#1]#*[#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]} +\permanent\tolerant\protected\def\setupselector [#1]#*[#2]{\getparameters[\??selector#1][#2]} + +\permanent\protected\let\select\directselect % we promote to protected + +% \def\directselect#1% expandable +% {\filterfromnext % maybe add an \expanded +% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}% +% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}} +% +% this is more efficient when the arguments are used a few times (or passed along): + +\permanent\def\directselect#1% expandable + {\expandafter\filterfromnext + \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname + \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname} + +\letvalue{\??selector\c!max}\plusone % \aliased ? +\letvalue{\??selector\c!n }\plusone % \aliased ? + +\protect \endinput diff --git a/tex/context/base/mkxl/core-ini.mkxl b/tex/context/base/mkxl/core-ini.mkxl new file mode 100644 index 000000000..94a0faeb9 --- /dev/null +++ b/tex/context/base/mkxl/core-ini.mkxl @@ -0,0 +1,224 @@ +%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 \everyendoftextbody + +\newtoks \everystarttext +\newtoks \everystoptext + +\newtoks \everystartdocument +\newtoks \everystopdocument + +%D Purity: + +\newtoks \everyforgetall +\newtoks \everycleanupfeatures +\newtoks \everysimplifycommands +\newtoks \everypreroll + +\aliased\let\simplifiedcommands\everysimplifycommands % backward compatible, will stay as it's used in styles + +\newconditional\simplifyingcommands % public + +\permanent\protected\def\forgetall {\the\everyforgetall} +\permanent\protected\def\cleanupfeatures {\the\everycleanupfeatures} +\permanent\protected\def\simplifycommands{\the\everysimplifycommands} + +\appendtoks + \settrue\simplifyingcommands +\to \everysimplifycommands + +\appendtoks + \everypar\emptytoks % pretty important +\to \everyforgetall + +%D Page building: + +\newtoks \everybeforepagebody +\newtoks \everyafterpagebody + +\aliased\let\everypagebody\everybeforepagebody % backward compatible, will become obsolete + +%D Floats: + +\newtoks \everyinsidefloat + +%D Exporting: + +\newtoks \everyinitializeexport + +%D Sectioning: + +%newtoks \everyheadstart + +%D Par building (experimental, used in xml

..

) + +\newtoks \everybeginofpar +\newtoks \everyendofpar +%newtoks \everyparflush + +\protected\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar +\protected\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 More generic (used to be pushcolor etc) + +\newtoks\everystarttextproperties +\newtoks\everystoptextproperties + +\permanent\protected\def\starttextproperties{\the\everystarttextproperties} +\permanent\protected\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 \ifinsidemulticolumns % simple mixed-in-text columns +\newif \ifdoublesided \doublesidedfalse +\newif \ifsinglesided \singlesidedtrue +\newif \ifinsidefloat +\newif \ifdoingblocks +\newif \ifgridsnapping +\newif \ifexporting + +\newconstant\pageduplexmode % 0 single 1 double 2 mix +\newconstant\pagebodymode % 0 not 1 normal pagebody 2 spread + +\newcount\nofcolumns \nofcolumns \plusone +\newcount\nofmulticolumns \nofmulticolumns\plusone + +%D \macros +%D {ifproductionrun} +%D +%D This boolean can be used to bypass certain initializations. + +% \newif\ifproductionrun % already defined + +\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 + +\permanent\protected\def\startboxedcontent{\bgroup\the\everyboxedcontent} + +\aliased\let\stopboxedcontent\egroup + +%D We store some original meanings, maybe in \type {math-ini}. + +\let\normalat \at +\let\normalin \in +\let\normalfrom \from +%let\normalover \over +\let\normalabout\about + +%D This will be implemented way later: + +\let\setlayoutcomponentattribute \gobbleoneargument +\let\resetlayoutcomponentattribute\relax +\let\layoutcomponentboxattribute \empty + +\protect \endinput diff --git a/tex/context/base/mkxl/core-lmt.lmt b/tex/context/base/mkxl/core-lmt.lmt new file mode 100644 index 000000000..ccbdcc0df --- /dev/null +++ b/tex/context/base/mkxl/core-lmt.lmt @@ -0,0 +1,95 @@ +if not modules then modules = { } end modules ['core-lmt'] = { + version = 1.001, + comment = "companion to core-lmt.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Kind of obsolete ... old school directions. + +local implement = interfaces.implement +local scankeyword = tokens.scanners.keyword +local scaninteger = tokens.scanners.integer + +local settextdir = tex.settextdir +local setlinedir = tex.setlinedir +local setpardir = tex.setpardir +local setboxdir = tex.setboxdir + +local gettextdir = tex.gettextdir +local getlinedir = tex.getlinedir +local getpardir = tex.getpardir +local getboxdir = tex.getboxdir + +local none_code = tokens.values.none + +local context = context + +local function scandir() + if scankeyword("tlt") then + return 0 + elseif scankeyword("trt") then + return 1 + else + return 0 + end +end + +local function showdir(d) + context(d == 1 and "TRT" or "LTL") + return none_code +end + +implement { + name = "textdir", + public = true, + usage = "value", + actions = function(what) + if what == "value" then + showdir(gettextdir()) + else + settextdir(scandir()) + end + end +} + +implement { + name = "linedir", + public = true, + usage = "value", + actions = function(what) + if what == "value" then + return showdir(getlinedir()) + else + setlinedir(scandir()) + end + end +} + +implement { + name = "pardir", + public = true, + usage = "value", + actions = function(what) + if what == "value" then + return showdir(getpardir()) + else + setpardir(scandir()) + end + end +} + +implement { + name = "boxdir", + public = true, + usage = "value", + actions = function(what) + local n = scaninteger() + if what == "value" then + return showdir(getboxdir(n)) + else + setboxdir(n,scandir()) + end + end +} diff --git a/tex/context/base/mkxl/core-lmt.mkxl b/tex/context/base/mkxl/core-lmt.mkxl new file mode 100644 index 000000000..77ef17966 --- /dev/null +++ b/tex/context/base/mkxl/core-lmt.mkxl @@ -0,0 +1,28 @@ +%D \module +%D [ file=core-lmt, +%D version=2018.08.2, +%D title=\CONTEXT\ System Macros, +%D subtitle=Primitives, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt System Macros / Primitives} + +\registerctxluafile{core-lmt}{autosuffix} + +\unprotect + +% nothing here + +\protect \endinput + +% \starttext +% abc{\textdir TRTdef}ghi +% abc{\textdir trtdef}ghi +% \boxdirection0=1 +% \stoptext diff --git a/tex/context/base/mkxl/core-sys.lmt b/tex/context/base/mkxl/core-sys.lmt new file mode 100644 index 000000000..12f001e37 --- /dev/null +++ b/tex/context/base/mkxl/core-sys.lmt @@ -0,0 +1,91 @@ +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.jobfilefullname = fulljobname + 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 + + -- if tex then + -- tex.jobname = jobfilename + -- end + + 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", public = true, actions = function() context(os.platform) end } +implement { name = "jobfilefullname", public = true, actions = function() context(environment.jobfilefullname) end } +implement { name = "jobfilename", public = true, actions = function() context(environment.jobfilename) end } +implement { name = "jobfilesuffix", public = true, actions = function() context(environment.jobfilesuffix) end } +implement { name = "inputfilebarename", public = true, actions = function() context(environment.inputfilebarename) end } +implement { name = "inputfilerealsuffix", public = true, actions = function() context(environment.inputfilerealsuffix) end } +implement { name = "inputfilesuffix", public = true, actions = function() context(environment.inputfilesuffix) end } +implement { name = "inputfilename", public = true, actions = function() context(environment.inputfilename) end } +implement { name = "outputfilename", public = true, 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 "" + return lpdf and format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf", + lpdf.getcompression() + ) or "error" +end) + +implement { + name = "systemlog", + arguments = "3 strings", + actions = function(whereto,category,text) + logs.system(whereto,"context",tex.jobname,category,text) + end, +} diff --git a/tex/context/base/mkxl/core-sys.mkxl b/tex/context/base/mkxl/core-sys.mkxl new file mode 100644 index 000000000..bcf216c0a --- /dev/null +++ b/tex/context/base/mkxl/core-sys.mkxl @@ -0,0 +1,445 @@ +%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}{autosuffix} + +\unprotect + +%D Version checking: + +\permanent\protected\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. + + +% \operatingsystem % defined at lua end + +%D The jobname is what gets loaded by the cont-yes stub file. This name also +%D determines the name of tuc etc files. + +% \jobfilefullname % defined at lua end +% \jobfilename % defined at lua end +% \jobfilesuffix % defined at lua end + +%D However, that one can itself load another file. + +% \inputfilebarename % defined at lua end +% \inputfilerealsuffix % defined at lua end +% \inputfilesuffix % defined at lua end +% \inputfilename % defined at lua end + +%D The output name is only used for some checking. + +% \outputfilename % defined at lua end + +\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 + +\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. + +\permanent\def\jobfullname{\jobfilename.\jobfilesuffix} + +\permanent\protected\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 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 + +\permanent\protected\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 is more +%D picky, so we default to the \type {cr}. I never understood why \type {crlf} was +%D not used in all systems, since it makes most sense. But anyway, in \MKIV\ we +%D avoid most of the complications anyway as we deal with much at the \LUA\ end. + +\permanent\tolerant\protected\def\start[#1]% + {\bgroup + \ifparameters + \expandafter\syst_start_nop + \else + \edef\m_syst_start_stop{#1}% + \expandafter\syst_start_yes + \fi} + +\def\syst_start_yes + {\ifempty\m_syst_start_stop + \let\syst_stop_indeed\donothing + \orelse\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} + +\def\syst_start_nop + {\let\syst_stop_indeed\donothing} + +\permanent\protected\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 + \frozen\setuevalue{\e!start\currentstartstop}{\syst_startstop_start {\currentstartstop}}% + \frozen\setuevalue{\e!stop \currentstartstop}{\syst_startstop_stop {\currentstartstop}}% + \frozen\setuevalue {\currentstartstop}{\syst_startstop_indeed{\currentstartstop}}% +\to \everydefinestartstop + +\ifdefined\dotagconstruct \else \let\dotagconstruct\relax \fi + +\protected\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 + \dotagconstruct} + +\protected\def\syst_startstop_stop#1% + {\dostoptagged + \egroup + \namedstartstopparameter{#1}\c!after\relax} + +\protected\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, not really needed + \startstopparameter\c!right\relax + \dostoptagged + \startstopparameter\c!inbetween\relax}} + +% \definestartstop[tracing][\c!style=\tt] + +% \protected\def\ignorestartstop[#1]% +% {\protected\defcsname\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!define=\v!yes] + +\appendtoks + \ifcstok{\highlightparameter\c!define}\v!yes + \frozen\instance\setuevalue\currenthighlight{\typo_highlights_indeed{\currenthighlight}}% + \fi +\to \everydefinehighlight + +\ifdefined\dotaghighlight \else \let\dotaghighlight\relax \fi + +\permanent\protected\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}} + +\permanent\protected\def\highlight[#1]% + {\typo_highlights_indeed{#1}} + +\permanent\protected\def\starthighlight[#1]% + {\begingroup + \def\currenthighlight{#1}% + \dostarttagged\t!highlight\currenthighlight + \usehighlightstyleandcolor\c!style\c!color + \dotaghighlight} + +\permanent\protected\def\stophighlight + {\dostoptagged + \endgroup} + +\aliased\let\directhighlight\typo_highlights_indeed + +\permanent\protected\def\defineexpandable + {\doifelsenextoptional + {\syst_basics_define_yes\def}% + {\syst_basics_define_nop\def}} + +\permanent\protected\def\define + {\doifelsenextoptional + {\syst_basics_define_yes{\protected\def}}% + {\syst_basics_define_nop{\protected\def}}} + +\protected\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} + +\protected\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} + +\permanent\protected\def\unique#1#2% + {\ifdefined#2% + \showmessage\m!system4{\string#2}% + \expandafter#1\expandafter\gobbleddefinition + \else + \expandafter#1% + \fi#2} + +\permanent\protected\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["\\protected\\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 +% +% \protected\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}. + +\permanent\protected\def\macroname#1% brrr + {\begincsname#1\endcsname} + +% %D A weird one that I probably needed once, so it might as well become +% %D obsolete. +% +% \protected\def\usecommands#1% +% {\begingroup +% \def\docommand##1{\setbox\scratchbox\hbox{\csname\string##1\endcsname##1}}% +% \processcommalist[#1]\docommand +% \endgroup} + +\permanent\protected\def\syst_log_indeed#1#2#3% + {\ctxcommand{systemlog("#1","#2",\!!bs#3\!!es)}} + +\aliased\let\systemlog\syst_log_indeed + +\permanent\protected\def\systemlogfirst + {\ifcase\directsystemparameter\c!n\relax + \expandafter\syst_log_indeed + \or + \expandafter\syst_log_indeed + \else + \expandafter\gobblethreearguments + \fi} + +\permanent\protected\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/tex/context/base/mkxl/core-two.mkxl b/tex/context/base/mkxl/core-two.mkxl new file mode 100644 index 000000000..0299e76f5 --- /dev/null +++ b/tex/context/base/mkxl/core-two.mkxl @@ -0,0 +1,109 @@ +%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 time, apart from +%D adding a few more selectors. This code used to be part of \type {core-uti}. The +%D following examples demonstrate 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}{} + +\permanent\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\clf_savetwopassdata{#1}{#3}}} +\permanent\def \lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata("#1","#3")}}} +\permanent\let \savetwopassdata \lazysavetwopassdata +\permanent\def \savetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}} +\permanent\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 + +\def\syst_twopass_check % can be delegated to lua once obsolete is gone + {\ifx\twopassdata\empty + \setfalse\twopassdatafound + \else + \settrue\twopassdatafound + \fi} + +\permanent\protected\def\definetwopasslist #1{\clf_definetwopasslist{#1}} +\permanent\protected\def\gettwopassdata #1{\edef\twopassdata {\clf_gettwopassdata {#1}}\syst_twopass_check} +\permanent\protected\def\checktwopassdata #1{\edef\twopassdata {\clf_checktwopassdata {#1}}\syst_twopass_check} +\permanent\protected\def\findtwopassdata #1#2{\edef\twopassdata {\clf_findtwopassdata {#1}{#2}}\syst_twopass_check} +\permanent\protected\def\getfirsttwopassdata #1{\edef\twopassdata {\clf_getfirsttwopassdata {#1}}\syst_twopass_check} +\permanent\protected\def\getlasttwopassdata #1{\edef\twopassdata {\clf_getlasttwopassdata {#1}}% + \edef\noftwopassitems{\clf_counttwopassdata {#1}}\syst_twopass_check} +\permanent\protected\def\getnamedtwopassdatalist#1#2{\edef #1{\clf_gettwopassdatalist {#2}}} +\permanent\protected\def\gettwopassdatalist #1{\edef\twopassdatalist{\clf_gettwopassdatalist {#1}}} + +\permanent\protected\def\doifelseintwopassdata #1#2{\clf_doifelseintwopassdata{#1}{#2}} + +\aliased\let\doifintwopassdataelse\doifelseintwopassdata +\aliased\let\getfromtwopassdata \findtwopassdata + +\protect \endinput diff --git a/tex/context/base/mkxl/core-uti.lua b/tex/context/base/mkxl/core-uti.lua new file mode 100644 index 000000000..60cf3d6a9 --- /dev/null +++ b/tex/context/base/mkxl/core-uti.lua @@ -0,0 +1,470 @@ +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-- +

A utility file has always been part of and with +the move to we also moved a lot of multi-pass info +to a table. Instead of loading a based +utility file under different setups, we now load a table once. This +saves much runtime but at the cost of more memory usage.

+--ldx]]-- + +local math = math +local format, match = string.format, string.match +local next, type, tostring, tonumber = next, type, tostring, tonumber +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 getrandom = utilities.randomizer.get +local setrandomseedi = utilities.randomizer.setseedi +local getrandomseed = utilities.randomizer.getseed + +local implement = interfaces.implement + +local texgetcount = tex.getcount + +local report_passes = logs.reporter("job","passes") + +job = job or { } +local job = job + +job.version = 1.31 +job.packversion = 1.02 + +-- some day we will implement loading of other jobs and then we need +-- job.jobs + +--[[ldx-- +

Variables are saved using in the previously defined table and passed +onto using the following method. Of course one can also +directly access the variable using a call.

+--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) + +function job.disablesave() + enabled = false -- for instance called when an error +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 then + 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 = getrandom("initialize") + setrandomseedi(rvalue) + rmethod = "initialized" + else + setrandomseedi(rvalue) + 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 + +function job.getrandomseed() + return tobesaved.randomseed or getrandomseed() +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", + "ownnumbers", + "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", + "positions", +} + +-- 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 function dofile(filename) + local result = loadstring(io.loaddata(filename)) + if result then + return result() + else + return nil + end + end + + 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 + local handlers = { } + for i=1,#savelist do + local list = savelist[i] + local target = list[1] + local initializer = list[3] + local result = accesstable(target,utilitydata) + if result then + local done = packers.unpack(result,jobpacker,true) + if done then + migratetable(target,mark(result)) + if type(initializer) == "function" then + handlers[#handlers+1] = { initializer, result } + end + else + report_passes("pack version mismatch") + end + end + end + -- so we have all tables available (unpacked) + for i=1,#handlers do + local handler = handlers[i] + handler[1](handler[2]) + 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 c_internal = status.callbacks or 0 + local c_file = status.indirect_callbacks or 0 + local c_direct = status.direct_callbacks or 0 + local c_late = backends.getcallbackstate().count + local c_function = status.function_callbacks or 0 + local c_total = c_internal + c_file + c_direct + c_late + c_function + local n_pages = structures.pages.nofpages or 0 + local c_average = n_pages > 0 and math.round(c_total/n_pages) or 0 + local result = format ( + "internal: %s, file: %s, direct: %s, late: %s, function %s, total: %s (%s per page)", + c_internal, c_file, c_direct, c_late, c_function, c_total, c_average + ) + statistics.callbacks = function() + return result + end + return result +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 + -- stoptiming(statistics) -- to be sure + local shipped = texgetcount('nofshipouts') + local pages = texgetcount('realpageno') + if pages > shipped then + pages = shipped + end + runtime = tonumber(runtime) + if shipped > 0 or pages > 0 then + local persecond = (runtime > 0) and (shipped/runtime) or pages + if pages == 0 then + pages = shipped + end + return format("%0.3f seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond) + else + return format("%0.3f seconds",runtime) + end + end +end + +implement { + name = "savevariable", + actions = job.variables.save, + arguments = "2 strings", +} + +implement { + name = "setjobcomment", + actions = job.comment, + arguments = { { "*" } } +} + +implement { + name = "initializejob", + actions = job.initialize +} + +implement { + name = "disablejobsave", + actions = job.disablesave +} diff --git a/tex/context/base/mkxl/core-uti.mkxl b/tex/context/base/mkxl/core-uti.mkxl new file mode 100644 index 000000000..b8d3bf7eb --- /dev/null +++ b/tex/context/base/mkxl/core-uti.mkxl @@ -0,0 +1,35 @@ +%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}{} + +% savecurrentvalue#1#2% immediate, expanded, defined at lua end + +\appendtoks + \clf_setjobcomment + file {\jobname}% + format {\contextformat}% + stamp {\contextversion}% + escape {\!!bs\space...\space\!!es}% + \relax +\to \everystarttext + +\appendtoks + \clf_initializejob +\to \everyjob + +\protect \endinput diff --git a/tex/context/base/mkxl/driv-ini.mkxl b/tex/context/base/mkxl/driv-ini.mkxl new file mode 100644 index 000000000..9f489a2a1 --- /dev/null +++ b/tex/context/base/mkxl/driv-ini.mkxl @@ -0,0 +1,20 @@ +%D \module +%D [ file=driv-ini, +%D version=2018.07.26, +%D title=\CONTEXT\ Driver Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Driver Macros / Initialization} + +\registerctxluafile{driv-ini}{} + +\unprotect + +\protect \endinput diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt new file mode 100644 index 000000000..8e3a936bb --- /dev/null +++ b/tex/context/base/mkxl/driv-shp.lmt @@ -0,0 +1,1360 @@ +if not modules then modules = { } end modules ['driv-shp'] = { + version = 1.001, + optimize = true, + comment = "companion to driv-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, next = type, next +local round = math.round + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local concat = table.concat +local keys = table.keys +local sortedhash = table.sortedhash +local splitstring = string.split +local idiv = number.idiv +local extract = bit32.extract +local nuts = nodes.nuts + +local tonut = nodes.tonut +local tonode = nodes.tonode + +local getdirection = nuts.getdirection +local getlist = nuts.getlist +local getoffsets = nuts.getoffsets +local getorientation = nuts.getorientation +local getfield = nuts.getfield +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getheight = nuts.getheight +local getdepth = nuts.getdepth +----- getwidth = nuts.getwidth +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local getid = nuts.getid +local getleader = nuts.getleader +----- getglue = nuts.getglue +local getshift = nuts.getshift +local getdata = nuts.getdata +----- getexpansion = nuts.getexpansion +local getreplace = nuts.getreplace +local setreplace = nuts.setreplace +local getfont = nuts.getfont +local getkerndimension = nuts.getkerndimension + +local setdirection = nuts.setdirection +local setfield = nuts.setfield +local setlink = nuts.setlink + +local isglyph = nuts.isglyph +local findtail = nuts.tail +local nextdir = nuts.traversers.dir +local nextnode = nuts.traversers.node + +local rangedimensions = node.direct.rangedimensions -- nuts ? +local effectiveglue = nuts.effective_glue +local start_of_par = nuts.start_of_par +local dirdimensions = nuts.dirdimensions + +local texget = tex.get + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local characters = fonthashes.characters +local parameters = fonthashes.parameters + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local gluecodes = nodes.gluecodes +local dircodes = nodes.dircodes +local dirvalues = nodes.dirvalues +local subtypes = nodes.subtypes + +local normaldir_code = dircodes.normal + +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local glyph_code = nodecodes.glyph +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 disc_code = nodecodes.disc +local math_code = nodecodes.math +local rule_code = nodecodes.rule +local whatsit_code = nodecodes.whatsit +----- penalty_code = nodecodes.penalty +----- boundary_code = nodecodes.boundary + +local leaders_code = gluecodes.leaders +local cleaders_code = gluecodes.cleaders +local xleaders_code = gluecodes.xleaders +local gleaders_code = gluecodes.gleaders + +local spaceskip_code = gluecodes.spaceskip + +local saveposwhatsit_code = whatsitcodes.savepos +local userdefinedwhatsit_code = whatsitcodes.userdefined +local openwhatsit_code = whatsitcodes.open +local writewhatsit_code = whatsitcodes.write +local closewhatsit_code = whatsitcodes.close +local lateluawhatsit_code = whatsitcodes.latelua +local literalwhatsit_code = whatsitcodes.literal +local setmatrixwhatsit_code = whatsitcodes.setmatrix +local savewhatsit_code = whatsitcodes.save +local restorewhatsit_code = whatsitcodes.restore + +local getpagedimensions getpagedimensions = function() + getpagedimensions = backends.codeinjections.getpagedimensions + return getpagedimensions() +end + +local drivers = drivers +local instances = drivers.instances + +local report = logs.reporter("drivers") + +--------------------------------------------------------------------------------------- + +local lastfont = nil +local fontcharacters = nil + +local magicconstants = tex.magicconstants +local trueinch = magicconstants.trueinch +local maxdimen = magicconstants.maxdimen +local running = magicconstants.running + +local pos_h = 0 +local pos_v = 0 +local pos_r = lefttoright_code +local shippingmode = "none" + +local abs_max_v = 0 +local abs_max_h = 0 + +local shipbox_h = 0 +local shipbox_v = 0 +local page_size_h = 0 +local page_size_v = 0 +----- page_h_origin = 0 -- trueinch +----- page_v_origin = 0 -- trueinch + +local initialize +local finalize +local updatefontstate +local pushorientation +local poporientation +local flushcharacter +local flushfontchar +local flushrule +local flushliteral +local flushsetmatrix +local flushsave +local flushrestore +local flushspecial +----- flushimage + +-- make local + +function drivers.getpos () return round(pos_h), round(pos_v) end +function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end +function drivers.gethpos() return round(pos_h) end +function drivers.getvpos() return round(pos_v) end + +-- characters + +local flush_character + +local stack = setmetatableindex("table") +local level = 0 +local nesting = 0 +local main = 0 + +-- experiment (smaller page stream but might be fragile) + +local tospace = false directives.register("backends.spaces", function(v) tospace = v end) + +-- todo: cache streams + +local default = 16384 * number.dimenfactors.bp -- 65536 // 4 + +local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) + + if nesting > 100 then + return + elseif nesting == 0 then + main = font + end + + nesting = nesting + 1 + + local saved_h = pos_h + local saved_v = pos_v + local saved_r = pos_r + pos_r = lefttoright_code + + local data = fontdata[font] + local fnt = font + local fonts = data.fonts + local siz = (data.parameters.factor or 1)/65536 + + local function flushchar(font,char,fnt,chr,f,e) + if fnt then + local nest = char ~= chr or font ~= fnt + if fnt == 0 then + fnt = main + end + return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) + else + return 0 + end + end + + -- we assume resolved fonts: id mandate but maybe also size + + for i=1,#vfcommands do + local packet = vfcommands[i] + local command = packet[1] + if command == "char" then + local chr = packet[2] + local f = packet[3] + local e = packet[4] + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + elseif command == "slot" then + local index = packet[2] + local chr = packet[3] + local f = packet[4] + local e = packet[5] + if index == 0 then + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + else + local okay = fonts and fonts[index] + if okay then + local fnt = okay.id + if fnt then + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + end + else + -- safeguard, we assume the font itself (often index 1) + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + end + end + elseif command == "use" then + local index = packet[2] + if index then + local fnt + if index == 0 then + fnt = font + else + local okay = fonts and fonts[index] + if okay then + fnt = okay.id + end + end + if fnt then + -- not efficient but ok for now as experiment + local d = characters[fnt] + if d then + for i=3,#packet do + local chr = packet[i] + local dat = d[chr] + if dat then + flushfontchar(fnt,chr,dat) + end + end + end + end + end + elseif command == "right" then + local h = packet[2] -- already scaled + if factor ~= 0 and h ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h + elseif command == "down" then + local v = packet[2] -- already scaled + pos_v = pos_v - v + elseif command == "push" then + level = level + 1 + local s = stack[level] + s[1] = pos_h + s[2] = pos_v + elseif command == "pop" then + if level > 0 then + local s = stack[level] + pos_h = s[1] + pos_v = s[2] + level = level - 1 + end + elseif command == "pdf" then + flushliteral(false,pos_h,pos_v,packet[2],packet[3]) + elseif command == "rule" then + local size_v = packet[2] + local size_h = packet[3] + if size_h > 0 and size_v > 0 then + if factor ~= 0 then + size_h = size_h + size_h * factor / 1000 + end + if size_h > 0 then + flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) + pos_h = pos_h + size_h + end + end + elseif command == "frame" then + local width = packet[2] + if width > 0 then + local height = packet[3] or 0 + local depth = packet[4] or 0 + local total = height + depth + if total > 0 then + if factor ~= 0 then + width = width + width * factor / 1000 + end + if width > 0 then + local line = packet[5] or default + local outline = not packet[6] + local advance = not packet[7] + flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline) + if advance then + pos_h = pos_h + width + end + end + end + end + elseif command == "font" then + local index = packet[2] + local okay = fonts and fonts[index] + if okay then + fnt = okay.id or fnt -- or maybe just return + end + elseif command == "lua" then + local code = packet[2] + if type(code) ~= "function" then + code = loadstring(code) + end + if type(code) == "function" then + code(font,char,pos_h,pos_v) + end + elseif command == "node" then + local h = packet[2] + hlist_out(h,getlist(h)) + elseif command == "image" then + -- doesn't work because intercepted by engine so we use a different + -- mechanism (for now) + local image = packet[2] + -- to do + elseif command == "pdfmode" then + -- doesn't happen + -- elseif command == "special" then + -- -- not supported + -- elseif command == "nop" then + -- -- nothing to do| + -- elseif command == "scale" then + -- -- not supported + end + end + + pos_h = saved_h + pos_v = saved_v + pos_r = saved_r + + nesting = nesting - 1 +end + +local onetimemessage -- could be defined later (todo: make plug for this) + +flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) + + if font ~= lastfont then + lastfont = font + fontcharacters = characters[font] + updatefontstate(font) + end + + local data = fontcharacters[char] + if not data then + if char > 0 then + if not onetimemessage then + onetimemessage = fonts.loggers.onetimemessage + end + onetimemessage(font,char,"missing") + end + return 0, 0, 0 + end + if vfcommands then + vfcommands = data.commands + end + local width, height, depth, naturalwidth + if current then + naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width + if factor == 0 then + width = naturalwidth + else + -- width = (1.0 + factor/1000000.0) * naturalwidth + width = naturalwidth + naturalwidth * factor/1000000.0 + -- width = naturalwidth + naturalwidth * 0.000001 * factor + end + else + width = data.width or 0 + height = data.height or 0 + depth = data.depth or 0 + naturalwidth = width + if not factor then + factor = 0 + end + end + if pos_r == righttoleft_code then + pos_h = pos_h - width -- here ? + end + if vfcommands then + flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? + else + -- kind of messy that we do orientation here and offsets elsewhere + local orientation = data.orientation + if orientation and (orientation == 1 or orientation == 3) then + local x = data.xoffset + local y = data.yoffset + if x then + pos_h = pos_h + x + end + if y then + pos_v = pos_v + y + end + pushorientation(orientation,pos_h,pos_v) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + poporientation(orientation,pos_h,pos_v) + else + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + end + end + return width, height, depth +end + +-- end of characters + +local function reset_state() + pos_h = 0 + pos_v = 0 + pos_r = lefttoright_code + shipbox_h = 0 + shipbox_v = 0 + shippingmode = "none" + page_size_h = 0 + page_size_v = 0 + -- page_h_origin = 0 -- trueinch + -- page_v_origin = 0 -- trueinch +end + +-- local function dirstackentry(t,k) +-- local v = { +-- cur_h = 0, +-- cur_v = 0, +-- ref_h = 0, +-- ref_v = 0, +-- } +-- t[k] = v +-- return v +-- end +-- +-- local dirstack = setmetatableindex(dirstackentry) +-- +-- local function reset_dir_stack() +-- dirstack = setmetatableindex(dirstackentry) +-- end + +local dirstack = { } + +local function reset_dir_stack() + dirstack = { } +end + +local leaderlevel = 0 + +local function flushlatelua(current,h,v) + -- Here we assume maganement by the lua function so currently we don't + -- check for leaderlevel. + return backends.latelua(current,h,v) +end + +local function flushwriteout(current) + if leaderlevel == 0 then + backends.writeout(current) + end +end + +local function flushopenout(current) + if leaderlevel == 0 then + backends.openout(current) + end +end + +local function flushcloseout(current) + if leaderlevel == 0 then + backends.closeout(current) + end +end + +local hlist_out, vlist_out do + + local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + local ot = extract(orientation, 0,4) + local ay = extract(orientation, 4,4) + local ax = extract(orientation, 8,4) + local of = extract(orientation,12,4) + if ot == 4 then + ot, ay = 0, 1 + elseif ot == 5 then + ot, ay = 0, 2 + end + if ot == 0 or ot == 2 then + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + end + if ot == 2 then + doffset, hoffset = hoffset, doffset + end + if ay == 1 then y = y - doffset + elseif ay == 2 then y = y + hoffset + elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset + end + elseif ot == 1 or ot == 3 then + if ay == 1 then y = y - height + elseif ay == 2 then y = y + height + elseif ay == 3 then y = y - height/2 + end + if ot == 1 then + doffset, hoffset = hoffset, doffset + end + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + elseif ax == 5 then x = x - hoffset + elseif ax == 6 then x = x + doffset + end + end + return ot, x + xoffset, y - yoffset + end + + -- to be checked: begin- or enddir kan nil zijn, weird + + -- local function calculate_width_to_enddir(this_box,begindir) -- can be a helper + -- local dir_nest = 1 + -- local enddir = begindir + -- for current, subtype in nextdir, getnext(begindir) do + -- if subtype == normaldir_code then -- todo + -- dir_nest = dir_nest + 1 + -- else + -- dir_nest = dir_nest - 1 + -- end + -- if dir_nest == 0 then -- does the type matter + -- enddir = current + -- local width = rangedimensions(this_box,begindir,enddir) + -- return enddir, width + -- end + -- end + -- if enddir == begindir then + -- local width = rangedimensions(this_box,begindir) -- ,enddir) + -- return enddir, width + -- end + -- return enddir, 0 + -- end + + -- check frequencies of nodes + + hlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = 0 + + -- if not current then + -- current = getlist(this_box) + -- end + + -- we can encounter par, boundary and penalty nodes but a special + -- iterator over content nodes won't save much + for current, id, subtype in nextnode, current do + if id == glyph_code then + local char, font = isglyph(current) + local x_offset, y_offset = getoffsets(current) + if x_offset ~= 0 or y_offset ~= 0 then + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + x_offset) + else + pos_h = ref_h + (cur_h + x_offset) + end + pos_v = ref_v - (cur_v - y_offset) + -- synced + end + local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) + cur_h = cur_h + wd + elseif id == glue_code then + local gluewidth = effectiveglue(current,this_box) + if gluewidth ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + if getid(leader) == rule_code then + if gluewidth > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + if pos_r == righttoleft_code then + pos_h = pos_h - gluewidth + end + pos_v = pos_v - depth + flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader)) + end + cur_h = cur_h + gluewidth + end + elseif width > 0 and gluewidth > 0 then + local boxdir = getdirection(leader) or lefttoright_code + gluewidth = gluewidth + 10 + local edge = cur_h + gluewidth + local lx = 0 + if subtype == gleaders_code then + local save_h = cur_h + if pos_r == righttoleft_code then + cur_h = ref_h - shipbox_h - cur_h + cur_h = width * (cur_h / width) + cur_h = ref_h - shipbox_h - cur_h + else + cur_h = cur_h + ref_h - shipbox_h + cur_h = width * (cur_h / width) + cur_h = cur_h - ref_h - shipbox_h + end + if cur_h < save_h then + cur_h = cur_h + width + end + elseif subtype == leaders_code then + local save_h = cur_h + cur_h = width * (cur_h / width) + if cur_h < save_h then + cur_h = cur_h + width + end + else + lq = gluewidth / width + lr = gluewidth % width + if subtype == cleaders_code then + cur_h = cur_h + lr / 2 + else + lx = lr / (lq + 1) + cur_h = cur_h + (lr - (lq - 1) * lx) / 2 + end + end + local shift = getshift(leader) + leaderlevel = leaderlevel + 1 + while cur_h + width <= edge do + local basepoint_h = 0 + -- local basepoint_v = shift + if boxdir ~= pos_r then + basepoint_h = boxwidth + end + -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift) + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_h = cur_h + width + lx + end + leaderlevel = leaderlevel - 1 + cur_h = edge - 10 + else + cur_h = cur_h + gluewidth + end + else + cur_h = cur_h + gluewidth + end + else + if tospace and subtype == spaceskip_code then + -- todo: flush_space + flush_character(false,getfont(current),32,false,true,pos_h,pos_v,pos_r) + end + cur_h = cur_h + gluewidth + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h + xoffset) + else + pos_h = ref_h + (cur_h + basepoint_h + xoffset) + end + pos_v = ref_v - (shift - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + doffset + if boxdir == pos_r then + basepoint_v = basepoint_v - height + end + elseif orientation == 2 then + if boxdir == pos_r then + basepoint_h = basepoint_h + width + end + elseif orientation == 3 then + basepoint_h = basepoint_h + hoffset + if boxdir ~= pos_r then + basepoint_v = basepoint_v - height + end + end + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_h = cur_h + width + elseif id == kern_code then + -- we can use getkerndimension(current) but then we get rounded values so for + -- now we calculate ourselves + local kern, factor = getkern(current,true) + if kern ~= 0 then + if factor ~= 0 then + cur_h = cur_h + (1.0 + factor/1000000.0) * kern + else + cur_h = cur_h + kern + end + end + elseif id == rule_code then + local width, height, depth = getwhd(current) + if width > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + local xoffset, yoffset, left, right = getoffsets(current) -- top bottom + if left ~= 0 then + pos_v = pos_v + left + total = total - left + end + if right ~= 0 then + depth = depth - right + total = total - right + end + if pos_r == righttoleft_code then + pos_h = pos_h - width + xoffset = - xoffset + end + pos_v = pos_v - depth + flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype) + end + end + cur_h = cur_h + width + elseif id == math_code then + -- local kern = getkern(current) + -- if kern ~= 0 then + -- cur_h = cur_h + kern + -- else + cur_h = cur_h + effectiveglue(current,this_box) + -- end + elseif id == dir_code then + -- We normally have proper begin-end pairs. A begin without end is (silently) handled + -- and an end without a begin will be (silently) skipped we only need to move forward + -- so we then have a faster calculation. + local dir, cancel = getdirection(current) + if cancel then + local ds = dirstack[current] + if ds then + ref_h = ds.ref_h + ref_v = ds.ref_v + cur_h = ds.cur_h + cur_v = ds.cur_v + else + -- pardir + end + pos_r = dir + else + local width, enddir = dirdimensions(this_box,current) + local new_h = cur_h + width + if dir ~= pos_r then + cur_h = new_h + end + if enddir ~= current then + dirstack[enddir] = { + cur_h = new_h, + cur_v = cur_v, + ref_h = ref_h, + ref_v = ref_v, + } + setdirection(enddir,pos_r) + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + ref_h = pos_h + ref_v = pos_v + cur_h = 0 + cur_v = 0 + pos_r = dir + goto synced + end + elseif id == whatsit_code then + if subtype == literalwhatsit_code then + flushliteral(current,pos_h,pos_v) + elseif subtype == lateluawhatsit_code then + flushlatelua(current,pos_h,pos_v) + elseif subtype == setmatrixwhatsit_code then + flushsetmatrix(current,pos_h,pos_v) + elseif subtype == savewhatsit_code then + flushsave(current,pos_h,pos_v) + elseif subtype == restorewhatsit_code then + flushrestore(current,pos_h,pos_v) + elseif subtype == saveposwhatsit_code then + last_position_x = pos_h + last_position_y = pos_v + elseif subtype == writewhatsit_code then + flushwriteout(current) + elseif subtype == closewhatsit_code then + flushcloseout(current) + elseif subtype == openwhatsit_code then + flushopenout(current) + end + elseif id == disc_code then + local replace, tail = getreplace(current) + if replace and subtype ~= select_disc then + -- we could flatten .. no gain + setlink(tail,getnext(current)) + setlink(current,replace) + setreplace(current) + end + -- elseif id == par_code and start_of_par(current) then + -- local pardir = getdirection(current) or lefttoright_code + -- if pardir == righttoleft_code then + -- end + -- end + else + -- penalty, boundary ... no dimensions + goto synced + end + -- There is no gain in skipping over this when we have zero progression + -- and such. + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + + vlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = - boxheight + local top_edge = cur_v + + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + + -- if not current then + -- current = getlist(this_box) + -- end + + -- while current do + -- local id = getid(current) + for current, id, subtype in nextnode, current do + if id == glue_code then + local glueheight = effectiveglue(current,this_box) + if glueheight ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + local total = height + depth + if getid(leader) == rule_code then + depth = 0 -- hm +-- forgotten ... needs testing +total = glueheight + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + if pos_r == righttoleft_code then + cur_h = cur_h - width + end + flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader)) + end + cur_v = cur_v + total + end + elseif total > 0 and glueheight > 0 then + glueheight = glueheight + 10 + local edge = cur_v + glueheight + local ly = 0 + if subtype == gleaders_code then + save_v = cur_v + cur_v = ref_v - shipbox_v - cur_v + cur_v = total * (cur_v / total) + cur_v = ref_v - shipbox_v - cur_v + if cur_v < save_v then + cur_v = cur_v + total + end + elseif subtype == leaders_code then -- aleader + save_v = cur_v + cur_v = top_edge + total * ((cur_v - top_edge) / total) + if cur_v < save_v then + cur_v = cur_v + total + end + else + lq = glueheight / total + lr = glueheight % total + if subtype == cleaders_code then + cur_v = cur_v + lr / 2 + else + ly = lr / (lq + 1) + cur_v = cur_v + (lr - (lq - 1) * ly) / 2 + end + end + local shift = getshift(leader) + leaderlevel = leaderlevel + 1 + while cur_v + total <= edge do -- todo: <= edge - total + -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height) + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + pos_v = ref_v - (cur_v + height) + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_v = cur_v + total + ly + end + leaderlevel = leaderlevel - 1 + cur_v = edge - 10 + else + cur_v = cur_v + glueheight + end + end + else + cur_v = cur_v + glueheight + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + -- local basepoint_h = shift + -- local basepoint_v = height + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + pos_v = ref_v - (cur_v + height) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + -- local basepoint_h = shift + -- local basepoint_v = height + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - (shift + xoffset) + else + pos_h = ref_h + (shift + xoffset) + end + pos_v = ref_v - (cur_v + height - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + width - height + basepoint_v = basepoint_v - height + elseif orientation == 2 then + basepoint_h = basepoint_h + width + basepoint_v = basepoint_v + depth - height + elseif orientation == 3 then -- weird + basepoint_h = basepoint_h + height + end + if pos_r == righttoleft_code then + pos_h = ref_h - basepoint_h + else + pos_h = ref_h + basepoint_h + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_v = cur_v + height + depth + elseif id == kern_code then + cur_v = cur_v + getkern(current) + elseif id == rule_code then + local width, height, depth = getwhd(current) + local total = height + depth + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + local xoffset, yoffset, left, right = getoffsets(current) + if left ~= 0 then + width = width - left + xoffset = left + end + if right ~= 0 then + width = width - right + end + if pos_r == righttoleft_code then + xoffset = - xoffset - width + end + flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype) + end + end + cur_v = cur_v + total + elseif id == whatsit_code then + if subtype == literalwhatsit_code then + flushliteral(current,pos_h,pos_v) + elseif subtype == lateluawhatsit_code then + flushlatelua(current,pos_h,pos_v) + elseif subtype == setmatrixwhatsit_code then + flushsetmatrix(current,pos_h,pos_v) + elseif subtype == savewhatsit_code then + flushsave(current,pos_h,pos_v) + elseif subtype == restorewhatsit_code then + flushrestore(current,pos_h,pos_v) + elseif subtype == saveposwhatsit_code then + last_position_x = pos_h + last_position_y = pos_v + elseif subtype == writewhatsit_code then + flushwriteout(current) + elseif subtype == closewhatsit_code then + flushcloseout(current) + elseif subtype == openwhatsit_code then + flushopenout(current) + end + else + -- penalty + goto synced + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + +end + +function drivers.converters.lmtx(driver,box,smode,objnum,specification) + + if not driver then + report("error in converter, no driver") + return + end + + if box then + box = tonut(box) + else + report("error in converter, no box") + return + end + + local actions = driver.actions + local flushers = driver.flushers + + initialize = actions.initialize + finalize = actions.finalize + + updatefontstate = flushers.updatefontstate + + pushorientation = flushers.pushorientation + poporientation = flushers.poporientation + + flushcharacter = flushers.character + flushfontchar = flushers.fontchar + flushrule = flushers.rule + flushsimplerule = flushers.simplerule + flushspecialrule = flushers.specialrule + flushspecial = flushers.special + flushliteral = flushers.literal + flushsetmatrix = flushers.setmatrix + flushsave = flushers.save + flushrestore = flushers.restore + -- flushimage = flushers.image + + reset_dir_stack() + reset_state() + + shippingmode = smode + + local details = nil -- must be outside labels + + local width, height, depth = getwhd(box) + + local total = height + depth + + ----- v_offset_par = 0 + ----- h_offset_par = 0 + + local max_v = total -- + v_offset_par + local max_h = width -- + h_offset_par + + if height > maxdimen or depth > maxdimen or width > maxdimen then + goto DONE + end + + if max_v > maxdimen then + goto DONE + elseif max_v > abs_max_v then + abs_max_v = max_v + end + + if max_h > maxdimen then + goto DONE + elseif max_h > abs_max_h then + abs_max_h = max_h + end + + if shippingmode == "page" then + + -- We have zero offsets in ConTeXt. + + local pagewidth, pageheight = getpagedimensions() + + -- local h_offset_par = texget("hoffset") + -- local v_offset_par = texget("voffset") + + -- page_h_origin = trueinch + -- page_v_origin = trueinch + + pos_r = lefttoright_code + + if pagewidth > 0 then + page_size_h = pagewidth + else + page_size_h = width + end + + if page_size_h == 0 then + page_size_h = width + end + + if pageheight > 0 then + page_size_v = pageheight + else + page_size_v = total + end + + if page_size_v == 0 then + page_size_v = total + end + + local refpoint_h = 0 -- + page_h_origin + h_offset_par + local refpoint_v = page_size_v -- - page_v_origin - v_offset_par + + pos_h = refpoint_h + pos_v = refpoint_v - height + -- synced + + else + + -- page_h_origin = 0 + -- page_v_origin = 0 + page_size_h = width + page_size_v = total + pos_r = getdirection(box) + pos_v = depth + pos_h = pos_r == righttoleft_code and width or 0 + + end + + shipbox_ref_h = pos_h + shipbox_ref_v = pos_v + + details = { + shippingmode = smode, -- target + boundingbox = { 0, 0, page_size_h, page_size_v }, + objectnumber = smode ~= "page" and objnum or nil, + pagenumber = smode == "page" and objnum or nil, + specification = specification, + } + + initialize(driver,details) + + lastfont = nil -- this forces a sync each page / object + + if getid(box) == vlist_code then + vlist_out(box,getlist(box)) + else + hlist_out(box,getlist(box)) + end + + ::DONE:: + + finalize(driver,details) + + shippingmode = "none" +end + +-- This will move to back-out.lua eventually. + +do + + ----- sortedhash = table.sortedhash + + ----- tonut = nodes.tonut + local properties = nodes.properties.data + local flush = texio.write_nl + + local periods = utilities.strings.newrepeater(".") + + local function showdetails(n,l) + local p = properties[tonut(n)] + if p then + local done = false + for k, v in sortedhash(p) do + if done then + flush("\n") + else + done = true + end + flush(periods[l+1] .. " " .. k .. " = " .. tostring(v)) + end + end + end + + local whatsittracers = { + latelua = showdetails, + literal = showdetails, + } + + callback.register("show_whatsit",function(n,l) + local s = nodes.whatsitcodes[n.subtype] + texio.write(" [" .. s .. "]") + local w = whatsittracers[s] + if w then + w(n,l) + end + end) + +end diff --git a/tex/context/base/mkxl/driv-shp.mkxl b/tex/context/base/mkxl/driv-shp.mkxl new file mode 100644 index 000000000..199215a59 --- /dev/null +++ b/tex/context/base/mkxl/driv-shp.mkxl @@ -0,0 +1,18 @@ +%D \module +%D [ file=driv-shp, +%D version=2018.07.26, +%D title=\CONTEXT\ Driver Macros, +%D subtitle=Shipout, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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{driv-shp}{autosuffix,optimize} + +\unprotect + +\protect \endinput diff --git a/tex/context/base/mkxl/enco-ini.mkxl b/tex/context/base/mkxl/enco-ini.mkxl new file mode 100644 index 000000000..1f8a121d5 --- /dev/null +++ b/tex/context/base/mkxl/enco-ini.mkxl @@ -0,0 +1,510 @@ +%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 the original enco-ini.tex file. For more details +%D you might want to study the \MKII\ file but since \LUATEX\ is unicode inside we +%D need less code. + +%D Much in here will disappear in \LMTX\ because we assume proper \UNICODE\ usage. + +% When dealing with characters we have four cases to take into account when moving +% from \MKII\ to \MKIV: + +% 1. => ref to slot 200 in current font +% 2. \char 200 => ref to slot 200 in current font +% 3. => 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) + +\immutable\let\defaultencoding\s!default + +%D \macros +%D {defineaccent, definecharacter, definecommand} +%D +%D Some of these are used at the \LUA\ end but the names will change. + +\installcorenamespace{accents} + +\permanent\protected\def\defineaccent#1 #2 #3 % + {\dodefineaccentcommand{#1}% + \dodefineaccent{#1}{#2}{#3}} + +\permanent\protected\def\dodefineaccentcommand#1% + {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}} + +\permanent\protected\def\dodefineaccent#1#2#3% no spaces, used low level + {\setvalue{\??accents\string#1\string#2\empty}{#3}} + +% the following dirty trick is needed to catch \asciimath{\^{1/5}log}: + +\permanent\protected\def\dohandleaccent#1#2% expandable because we want them in the tuc file + {\csname\??accents + \ifcsname\??accents\string#1#2\empty\endcsname + \string#1#2\empty + \orelse\ifcsname\??accents\string#1\string#2\empty\endcsname + \string#1\string#2\empty + \else + \endcsname#2\csname\??accents % very dirty trick: ignore accent but keep char + \fi + \endcsname} + +\immutable\letvalue{\??accents}\empty + +\permanent\protected\def\dodefinecommand#1#2% + {\frozen\setuvalue{\string#1}{#2}} % not permanent as these are kind of obsolete + +\permanent\protected\def\definecharacter#1 #2 % + {\doifelsenumber{\string#2} + {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax} + {\setuvalue{\string#1}{#2}}} + +\permanent\protected\def\definecommand#1 #2 % + {\setuvalue{\string#1}{#2}} + +%D \macros +%D {everyuppercase, everylowercase, everysanitize} + +\newtoks \everyuppercase +\newtoks \everylowercase +\newtoks \everysanitize + +%D Accent handling (try to avoid this): + +% \buildtextaccent\greekdasia\greekalphamacron +% \buildtextaccent\textacute q + +%D We can use offsets in \LMTX\ but even that makes no sense because we have +%D a virtual feature already in \MKIV. + +\newbox\b_enco_accent + +\permanent\protected\def\buildmathaccent#1% + {\mathaccent#1 } + +\permanent\protected\def\buildtextaccent#1#2% we could do all at the lua end + {\dontleavehmode\begingroup % but that's no fun (yet) + \setbox\scratchboxone\hbox{#1}% accent + \setbox\scratchboxtwo\hbox{#2}% character + \scratchheight\dimexpr\ht\scratchboxtwo-\ht\scratchboxone\relax + \scratchdepth \dimexpr\dp\scratchboxtwo-\dp\scratchboxone\relax + \scratchwidth \wd\scratchboxtwo + \hbox to \wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi\bgroup + \hss\box\scratchboxtwo\hss + \hskip-\scratchwidth + \hss + \ifdim\ht\scratchboxone>\exheight + % top accent + \raise\dimexpr\scratchheight+\exheight/3\relax + \else + \lower-\dimexpr\scratchdepth+\exheight/3\relax + \fi + \box\scratchboxone + \hss + \egroup + \endgroup} + +\permanent\protected\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char + {\dontleavehmode % why this align mess + \vtop + {\forgetall + \baselineskip\zeropoint + \lineskip#1% + \everycr\emptytoks + \tabskip\zeropoint + \lineskiplimit\zeropoint + \setbox0\hbox{#4}% + \halign + {##\crcr\hbox{#5}\crcr + \hidewidth + \hskip#2\wd0 + \hskip-#3\slantperpoint % in plain 1ex * dimenless value + \vpack to .2\exheight{\box0\vss}\hidewidth + \crcr}}} + +\permanent\protected\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}} +\permanent\protected\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}} +\permanent\protected\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}} +\permanent\protected\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}} +\permanent\protected\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}} + +\aliased\let\d\buildtextbottomdot + +\permanent\protected\def\topaccent#1#2#3#4#5% down right slantcorrection accent char + {\dontleavehmode + \bgroup + \setbox0\hbox{#4}% + \setbox2\hbox{#5}% + \hbox to \wd2 \bgroup + \hss\copy2\hss + \hskip-\wd2 + \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss + \egroup + \egroup} + +\permanent\protected\def\buildtextgrave + {\topaccent{0pt}{0}{15}{\textgrave}} % e.g. + +\permanent\protected\def\definemathaccent#1 #2% + {\setvalue{#1}{\mathaccent#2 }} + +%D Math (will move): + +\definemathaccent acute \mathacute +\definemathaccent grave \mathgrave +\definemathaccent ddot \mathddot +\definemathaccent tilde \mathtilde +\definemathaccent bar \mathbar +\definemathaccent breve \mathbreve +\definemathaccent check \mathcheck +\definemathaccent hat \mathhat +\definemathaccent vec \mathvec +\definemathaccent dot \mathdot +%definemathaccent widetilde \mathwidetilde +%definemathaccent widehat \mathwidehat + +% from enco-def: + +% \aliased\let\i\dotlessi +% \aliased\let\j\dotlessj + +% \aliased\let\P\paragraphmark \aliased\let\textP\paragraphmark % obsolete (surfaced in bibliographic files) +% \aliased\let\S\sectionmark \aliased\let\textS\sectionmark % obsolete (surfaced in bibliographic files) + +\immutable\def\eszett {ß} \immutable\def\Eszett {SS} \permanent\def\Ssharp{SS} +\immutable\def\lslash {ł} \immutable\def\Lslash {Ł} +\immutable\def\dslash {đ} \immutable\def\Dslash {Đ} +%immutable\def\oslash {ø} %immutable\def\Oslash {Ø} % clashes with math: use \Ostroke +\immutable\def\dcroat {đ} \immutable\def\Dcroat {Đ} +\immutable\def\kcedilla{ķ} \immutable\def\Kcedilla{Ķ} +\immutable\def\lcedilla{ļ} \immutable\def\Lcedilla{Ļ} +\immutable\def\ncedilla{ņ} \immutable\def\Ncedilla{Ņ} +\immutable\def\rcedilla{ŗ} \immutable\def\Rcedilla{Ŗ} +\immutable\def\aumlaut {ä} \immutable\def\Aumlaut {Ä} +\immutable\def\eumlaut {ë} \immutable\def\Eumlaut {Ë} +\immutable\def\iumlaut {ï} \immutable\def\Iumlaut {Ï} +\immutable\def\oumlaut {ö} \immutable\def\Oumlaut {Ö} +\immutable\def\uumlaut {ü} \immutable\def\Uumlaut {Ü} + +% From \type {enco-com} we had these: + +% \aliased\let\AE\AEligature \aliased\let\ae\aeligature +% \aliased\let\OE\OEligature \aliased\let\oe\oeligature +% \aliased\let\IJ\IJligature \aliased\let\ij\ijligature +% \aliased\let\AA\textAngstrom \aliased\let\aa\aring +% \aliased\let\CC\Ccedilla \aliased\let\cc\ccedilla +% \aliased\let\L \Lslash \aliased\let\l \lslash +% \aliased\let\O \Oslash \aliased\let\o \oslash +% \aliased\let\SZ\Eszett \aliased\let\sz\eszett % \aliased\let\SS\Ssharp + +%D For old times sake we keep these (obsolete): + +\immutable\def\textflorin{ƒ} \immutable\def\florin {ƒ} +\immutable\def\pound {£} \immutable\def\sterling{£} +\immutable\def\promille {‰} \immutable\def\permille{‰} + +%D These are kind of \TEX\ specific + +\pushoverloadmode + +\permanent\protected\def\ampersand{\mathortext\mathampersand\textampersand} + +\immutable\let\percent\textpercent +\immutable\let\procent\textpercent +\immutable\let\dollar \textdollar +\immutable\let\hash \texthash + +\popoverloadmode + +%D These come from the \MKII\ file \type {enco-mis}: + +\permanent\protected\def\fakepercent + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}} + +\permanent\protected\def\fakeperthousand + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}} + +\permanent\protected\def\fakepermine + {\dontleavehmode + \bgroup + \setbox\scratchbox\hbox + {\mathematics{+}}% + \hbox to \wd\scratchbox + {\hss + \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}% + \hss}% + \egroup} + +\def\permine{\fakepermine} + +%D some more: what with freezing here? + +\ifdefined\softhyphen \else + \aliased\let\softhyphen\explicitdiscretionary +\fi + +%D The softhyhen is never used but we keep the definition below: + +\aliased\let\hyphen \softhyphen % never used + +% But we ditch these: + +% \def\hyphen {\softhyphen} % never used +% \def\compoundwordmark {\hyphen} +% \def\cwm {\hyphen} +% \def\nonbreakinghyphen{\hyphen} +% \def\breakinghyphen {\hyphen\prewordbreak} + +%D Quotes \unknown\ we keep these funny names because they indicate where we come +%D from \unknown\ long long ago when we had no real useful names for them. Some +%D ancient styles might still use them. + +\aliased\let\lowerleftsingleninequote \quotesinglebase +\aliased\let\lowerleftdoubleninequote \quotedblbase +\aliased\let\lowerrightsingleninequote\quotesinglebase +\aliased\let\lowerrightdoubleninequote\quotedblbase + +\aliased\let\upperleftsingleninequote \quoteright +\aliased\let\upperleftdoubleninequote \quotedblright +\aliased\let\upperrightsingleninequote\quoteright +\aliased\let\upperrightdoubleninequote\quotedblright + +\aliased\let\upperleftsinglesixquote \quoteleft +\aliased\let\upperleftdoublesixquote \quotedblleft +\aliased\let\upperrightsinglesixquote \quoteleft +\aliased\let\upperrightdoublesixquote \quotedblleft + +\aliased\let\leftsubguillemot \guilsingleleft +\aliased\let\rightsubguillemot \guilsingleright + +% Some left-overs that wil go away! + +\permanent\protected\def\textblacksquare{\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}} +%permanent\protected\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}} +\permanent\protected\def\schwagrave {\buildtextgrave\schwa} + +\installcorenamespace{controlspace} + +\permanent\protected\def\fallbackcontrolspace % beware, current font, we also need to honor color + {\hbox to \interwordspace \bgroup + \hss + \ifcsname\??controlspace\number\interwordspace\endcsname + \csname\??controlspace\number\interwordspace\endcsname + \else + \enco_fast_control_space_define % only regular + \fi + \textcontrolspace + \hss + \egroup} + +\protected\def\enco_fast_control_space_define + {\scratchdimen\interwordspace + \definedfont[LMTypewriter-Regular at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody]% see font-sym.mkiv + \gletcsname\??controlspace\number\scratchdimen\endcsname\lastrawfontcall} + +\permanent\protected\def\normalcontrolspace + %{\iffontchar\font\numexpr\expandafter`\textcontrolspace\relax + {\iffontchar\font\textcontrolspace % in luametatex we also accept a char + \textcontrolspace + \else + \fallbackcontrolspace + \fi} + +\aliased\let\textvisiblespace\normalcontrolspace + +\permanent\protected\def\optionalcontrolspace + %{\iffontchar\font\numexpr\expandafter`\textcontrolspace\relax + {\iffontchar\font\textcontrolspace % in luametatex we also accept a char + \textcontrolspace + \else + \asciispacechar % used for export ! + \fi} + +% a few defaults (\{}), we really need the verbose \empty as it will be +% stringified .. anyhow, we define this at the lua end now but keep it here as a +% reference +% +% \defineaccent ^ {\empty} {\textcircumflex} +% \defineaccent ` {\empty} {\textgrave} +% \defineaccent ~ {\empty} {\texttilde} +% \defineaccent " {\empty} {\textdiaeresis} +% \defineaccent ' {\empty} {\textacute} +% \defineaccent . {\empty} {\textdotaccent} +% \defineaccent = {\empty} {\textmacron} +% \defineaccent c {\empty} {\textcedilla} +% \defineaccent H {\empty} {\texthungarumlaut} +% \defineaccent k {\empty} {\textogonek} +% \defineaccent r {\empty} {\textring} +% \defineaccent u {\empty} {\textbreve} +% \defineaccent v {\empty} {\textcaron} + +\clf_defineaccents % one time + +%D A smaller and bolder variant, more like the math and monospaced ones. + +\permanent\protected\def\fakeunderscore + {\relax\ifmmode + \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax + \else + \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}% + \fi} + +\permanent\protected\def\fakeunderscores{\enforced\let\_\fakeunderscore} +\permanent\protected\def\textunderscores{\enforced\let\_\textunderscore} + +\textunderscores + +\ifdefined\mathunderscore \else \aliased\let\mathunderscore\fakeunderscore \fi +\ifdefined\textunderscore \else \aliased\let\textunderscore\fakeunderscore \fi + +\permanent\protected\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi} + +\let\_\normalunderscore + +%D To be sorted out: + +\pushoverloadmode + +\permanent\protected\def\textminus + {\char + \iffontchar\font"2012 "2012 \orelse % figuredash + \iffontchar\font"2013 "2013 \orelse % endash + \iffontchar\font"2212 "2212 \else % math minus + "002D \fi} % hyphen + +\permanent\protected\def\textplus + {\char"002B } % plus + +\popoverloadmode + +%D Moved from core-mis: + +\permanent\protected\def\celsius #1{#1\mathematics{^\circ}C} +\permanent\protected\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax} +\permanent\protected\def\fraction#1#2{\mathematics{#1\over#2}} + +%D \startbuffer +%D \startlines +%D x\periods x +%D x\periods[10]x +%D x\periods[n=10,symbol={,}]x +%D x\periods[n=4,symbol={!!},width=1em]x +%D x\periods[n=4,symbol={!!},width=fit]x +%D x\periods[n=4,symbol={!!},width=fit,distance=1em]x +%D x\unknown x +%D \stoplines +%D \stopbuffer +%D +%D \typbuffer \getbuffer + +\def\periodswidth {.5\emwidth} % downward compatible +\def\periodsdefault{3} % downward compatible + +\installcorenamespace {periods} + +\installsetuponlycommandhandler \??periods {periods} + +\setupperiods + [\c!n=\periodsdefault, + \c!width=\periodswidth, % can also be \v!fit + \c!distance=.25\emwidth, + \c!symbol=.] + +\permanent\protected\def\periods + {\dontleavehmode + \hbox\bgroup + \doifelsenextoptional\enco_periods_yes\enco_periods_nop} + +\protected\def\enco_periods_yes[#1]% + {\doifelseassignment{#1} + {\setupcurrentperiods[#1]% + \scratchcounter\periodsparameter\c!n} + {\doifelsenothing{#1} + {\scratchcounter\periodsparameter\c!n}% + {\scratchcounter#1}}% + \enco_periods_finish} + +\protected\def\enco_periods_nop + {\scratchcounter\periodsparameter\c!n + \enco_periods_finish} + +\protected\def\enco_periods_finish + {\edef\p_width{\periodsparameter\c!width}% + \ifx\p_width\v!fit + \enco_periods_finish_fit + \else + \enco_periods_finish_width + \fi + \egroup} + +\protected\def\enco_periods_finish_width + {\setbox\scratchbox\hbox to \p_width + {\hss\periodsparameter\c!symbol\hss}% + \dorecurse\scratchcounter{\copy\scratchbox}} + +\protected\def\enco_periods_finish_fit + {\edef\p_symbol{\periodsparameter\c!symbol}% + \scratchdistance\periodsparameter\c!distance + \hskip\scratchdistance + \dorecurse\scratchcounter{\p_symbol\hskip\scratchdistance}} + +\permanent\protected\def\unknown + {\dontleavehmode + \hbox\bgroup + \enco_periods_nop} + +%D Left-overs: + +\appendtoks + \enforced\let\buildtextaccent\secondoftwoarguments +\to \everysimplifycommands + +%D A plain one: + +% \protected\def\t#1{% +% \dontleavehmode +% \begingroup +% \setbox\scratchboxone\hpack{#1}% +% \setbox\scratchboxtwo\hpack\bgroup +% \iffontchar\font"0361\relax +% \char"0361\relax +% \else +% \iffontchar\font"2040\relax\else +% \the\textfont0 +% \fi +% \char"2040 +% \fi +% \egroup +% \scratchdimenone\wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi +% \scratchdimentwo\dimexpr-\ht\scratchboxtwo+\ht\scratchboxone+.45\exheight\relax +% \hpack to \scratchdimenone\bgroup +% \hpack to \scratchdimenone{\hss\box\scratchboxone\hss}% +% \hskip -\scratchdimenone +% \hpack to \scratchdimenone{\hss\raise\scratchdimentwo\box\scratchboxtwo\hss}% +% \egroup +% \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/file-ini.mklx b/tex/context/base/mkxl/file-ini.mklx new file mode 100644 index 000000000..66d03b2f9 --- /dev/null +++ b/tex/context/base/mkxl/file-ini.mklx @@ -0,0 +1,231 @@ +%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 is a separate module +%D for file commands. In \CONTEXT\ files 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 the \type {\input} +%D primitive or load them on a line||by||line basis, using \type {\read}. Writing is +%D always done line by line, using \type {\write}. + +\writestatus{loading}{ConTeXt File Macros / Helpers} + +\registerctxluafile{file-ini}{} + +\unprotect + +%D \macros +%D {scratchread, scratchwrite} +%D +%D We define a scratch file for reading. Keep in mind that the number of files is +%D limited to~16, so use this one when possible. We also define a scratch output +%D file. In \MKIV\ and \LMTX\ we never use these file handles. + +\ifdefined\scratchread \else \newread \scratchread \fi +\ifdefined\scratchwrite \else \newwrite\scratchwrite \fi + +%D Seldom needed: + +\permanent\def\openinputfile #handle#name{\immediate\openin #handle={#name}\relax} +\permanent\def\openoutputfile #handle#name{\immediate\openout#handle={#name}\relax} + +\permanent\def\closeinputfile #handle{\immediate\closein #handle\relax} +\permanent\def\closeoutputfile#handle{\immediate\closeout#handle\relax} + +%D \macros +%D {writeln} +%D +%D This saves a few tokens: + +\permanent\def\writeln#handle{\write#handle{}} + +%D \macros +%D {pushendofline,popendofline} +%D +%D When we are loading files in the middle of the typesetting process, for instance +%D when we load references, we have to be sure that the reading process does not +%D generate so called 'spurious spaces'. This can be prevented by assigning the line +%D ending character the \CATCODE\ comment. This is accomplished by +%D +%D \starttyping +%D \pushendofline +%D ... reading ... +%D \popendofline +%D \stoptyping + +\installsystemnamespace{eolstack} + +\newcount\c_system_files_eol_level + +\permanent\protected\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} + +\permanent\protected\def\popendofline + {\catcode\endoflineasciicode\csname\??eolstack\number\c_system_files_eol_level\endcsname + \advance\c_system_files_eol_level\minusone} + +\permanent\protected\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 + +\permanent\protected\def\startreadingfile% beter een every en \setnormalcatcodes + {\global\advance\readingfilelevel\plusone + \the\everystartreadingfile + \pushcatcodetable % saveguard + \setcatcodetable\ctxcatcodes + \clf_pushregime}% temporarily this way + +\permanent\protected\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 expanded, e.g. in +%D a \type {\write} (which happens in the metafun manual when we permit long MP +%D lines). So, instead of fixing that, we go for a redefinition of \type {\input}. +%D Of course it's better to use \type {\readfile} or \type {\processfile}. + +\permanent\def\inputgivenfile#name{\normalinput{#name}} % expands + +%D \macros +%D {doifelsefile} +%D +%D The next alternative only looks if a file is present. No loading is done. This +%D one obeys the standard \TEX\ lookup. +%D +%D \starttyping +%D \doiffileelse {filename} {found} {not found} +%D \stoptyping + +\permanent\protected\def\doifelsefile {\clf_doifelsefileexist} +\permanent\protected\def\doifelsepath {\clf_doifelsepathexist} +\permanent\protected\def\doiffile #name{\clf_doifelsefileexist{#name}\firstofoneargument\gobbleoneargument} +\permanent\protected\def\doifnotfile #name{\clf_doifelsefileexist{#name}\gobbleoneargument\firstofoneargument} + +\aliased\let\doiffileelse\doifelsefile +\aliased\let\doifpathelse\doifelsepath + +\aliased\let\doifelsefileexists\doifelsefile +\aliased\let\doifelsepathexists\doifelsepath + +\aliased\let\doiffileexistselse\doifelsefileexists +\aliased\let\doifpathexistselse\doifelsepathexists + +%D \macros +%D {doifparentfileelse} +%D +%D \starttyping +%D \doifparentfileelse{filename}{yes}{no} +%D \stoptyping + +\ifdefined\outputfilename \else \def\outputfilename{\jobname} \fi + +\permanent\protected\def\doifelseparentfile{\clf_doifelseparentfile} + +\aliased\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 +\newconstant\splitoffkind + +\mutable\def\splitoffroot{.} +\mutable\let\splitofffull\empty +\mutable\let\splitoffpath\empty +\mutable\let\splitoffbase\empty +\mutable\let\splitoffname\empty +\mutable\let\splitofftype\empty + +\permanent\protected\def\splitfilename{\clf_splitfilename} + +%D \macros +%D {doonlyonce, doinputonce, doendinputonce} +%D +%D Especially macropackages need only be loaded once. Repetitive loading not only +%D costs time, relocating registers often leads to abortion of the processing +%D because \TEX's 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 move this +%D function to the \LUA\ end. + +\installsystemnamespace {fileonce} + +\permanent\protected\def\doonlyonce#whatever% + {\ifcsname\??fileonce#whatever\endcsname + \expandafter\gobbleoneargument + \else + \letgvalue{\??fileonce#whatever}\relax + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\doinputonce#name% + {\doonlyonce{#name}{\doifelsefile{#name}{\inputgivenfile{#name}}\donothing}} + +\permanent\protected\def\doendinputonce#name% + {\ifcsname\??fileonce#name\endcsname + \expandafter\endinput + \fi} + +\permanent\protected\def\forgetdoingonce#whatever% + {\global\undefinevalue{\??fileonce#whatever}} + +\protect \endinput diff --git a/tex/context/base/mkxl/file-job.lmt b/tex/context/base/mkxl/file-job.lmt new file mode 100644 index 000000000..95ad48e82 --- /dev/null +++ b/tex/context/base/mkxl/file-job.lmt @@ -0,0 +1,1283 @@ +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 next, rawget, tostring, tonumber = next, rawget, tostring, tonumber +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 setmetatableindex, setmetatablenewindex = table.setmetatableindex, table.setmetatablenewindex + +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 = logs.reporter("system") +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 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 is_qualified_path = file.is_qualified_path + +local cleanpath = resolvers.cleanpath +local toppath = resolvers.toppath +local resolveprefix = resolvers.resolve + +local hasscheme = url.hasscheme + +local jobresolvers = resolvers.jobs + +local registerextrapath = resolvers.registerextrapath +local resetextrapaths = resolvers.resetextrapaths +local getextrapaths = resolvers.getextrapath +local pushextrapath = resolvers.pushextrapath +local popextrapath = resolvers.popextrapath + +----- 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", + public = true, + protected = true, + actions = function(name) + name = findctxfile(name) + if name ~= "" then + context.input(name) + end + end +} + +implement { + name = "doifelseinputfile", + arguments = "string", + public = true, + protected = true, + 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 = "optional", + public = true, + protected = true, + actions = function(paths) + report_jobfiles("using path: %s",paths) + registerextrapath(paths) + end +} + +implement { + name = "pushpath", + arguments = "optional", + public = true, + protected = true, + actions = function(paths) + report_jobfiles("pushing path: %s",paths) + pushextrapath(paths) + end +} + +implement { + name = "poppath", + public = true, + protected = true, + actions = function(paths) + popextrapath() + report_jobfiles("popping path") + end +} + +implement { + name = "usesubpath", + arguments = "optional", + public = true, + protected = true, + actions = function(subpaths) + report_jobfiles("using subpath: %s",subpaths) + registerextrapath(nil,subpaths) + end +} + +implement { + name = "resetpath", + public = true, + protected = true, + actions = function() + report_jobfiles("resetting path") + resetextrapaths() + end +} + +implement { + name = "allinputpaths", + public = true, + actions = function() + context(concat(getextrapaths(),",")) + end +} + +implement { + name = "usezipfile", + public = true, + protected = true, + arguments = { "optional", "optional" }, + 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 +} + +-- moved from tex to lua: + +local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.mklx", "%s.mkxl", "%s.tex" } +local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua", "%s.lmt" } +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", + public = true, + protected = true, + arguments = "string", + actions = function(name) + insert(processstack,name) + processedfile = name + insert(processedfiles,name) + end +} + +implement { + name = "dostoptextfile", + public = true, + protected = true, + actions = function() + processedfile = remove(processstack) or "" + end +} + +local function startprocessing(name,notext) + if not notext then + -- report("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("end file %a at line %a",name,status.linenumber or 0) + end +end + +-- + +local typestack = { } +local currenttype = v_text +local nofmissing = 0 +local missing = { + tex = setmetatableindex("number"), + lua = setmetatableindex("number"), + cld = setmetatableindex("number"), + xml = setmetatableindex("number"), +} + +local function reportfailure(kind,name) + nofmissing = nofmissing + 1 + missing[kind][name] = true + report_jobfiles("unknown %s file %a",kind,name) +end + +-- + +local function action(name,foundname) + input(foundname) +end +local function failure(name,foundname) + reportfailure("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 function action(name,foundname) + dofile(foundname) +end +local function failure(name,foundname) + reportfailure("lua",name) +end +local function useluafile(name,onlyonce,notext) + uselibrary { + name = name, + patterns = luapatterns, + action = action, + failure = failure, + onlyonce = onlyonce, + } +end + +local function action(name,foundname) + dofile(foundname) +end +local function failure(name,foundname) + reportfailure("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 function action(name,foundname) + context.xmlprocess(foundname,"main","") +end +local function failure(name,foundname) + reportfailure("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, + mklx = usetexfile, + mkxl = 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 = "loadtexfile", public = true, protected = true, actions = usetexfile, arguments = "optional" } +implement { name = "loadluafile", public = true, protected = true, actions = useluafile, arguments = "optional" } +implement { name = "loadcldfile", public = true, protected = true, actions = usecldfile, arguments = "optional" } +implement { name = "loadxmlfile", public = true, protected = true, actions = usexmlfile, arguments = "optional" } + +implement { name = "loadtexfileonce", public = true, protected = true, actions = usetexfile, arguments = { "optional", true } } +implement { name = "loadluafileonce", public = true, protected = true, actions = useluafile, arguments = { "optional", true } } +implement { name = "loadcldfileonce", public = true, protected = true, actions = usecldfile, arguments = { "optional", true } } +implement { name = "loadxmlfileonce", public = true, protected = true, actions = usexmlfile, arguments = { "optional", 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("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 + 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() + stopped = true + end + end +end + +implement { + name = "starttext", + public = true, + protected = true, + actions = starttext +} + +implement { + name = "stoptext", + public = true, + protected = true, + actions = stoptext +} + +implement { + name = "forcequitjob", + arguments = "string", + public = true, + protected = true, + actions = function(reason) + if reason then + report("forcing quit: %s",reason) + else + report("forcing quit") + end + context.batchmode() + while textlevel >= 0 do + context.stoptext() + end + end +} + +implement { + name = "forceendjob", + public = true, + protected = true, + actions = function() + report([[don't use \end to finish a document]]) + context.stoptext() + end +} + +implement { + name = "autostarttext", + public = true, + protected = true, + actions = function() + if textlevel == 0 then + report([[auto \starttext ... \stoptext]]) + end + context.starttext() + end +} + +implement { + name = "autostoptext", + public = true, + protected = true, + actions = stoptext +} + +-- project structure + +implement { + name = "processfilemany", + public = true, + protected = true, + arguments = { "string", false }, + actions = useanyfile +} + +implement { + name = "processfileonce", + public = true, + protected = true, + arguments = { "string", true }, + actions = useanyfile +} + +implement { + name = "processfilenone", + arguments = "string", + public = true, + protected = true, + 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 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 + +do + + local function log_tree(report,top,depth) + report("%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(report,branches[i],depth) + end + end + end + + logs.registerfinalactions(function() + root.name = environment.jobname + -- + logs.startfilelogging(report,"used files") + log_tree(report,root,"") + logs.stopfilelogging() + -- + if nofmissing > 0 and logs.loggingerrors() then + logs.starterrorlogging(report,"missing files") + for kind, list in sortedhash(missing) do + for name in sortedhash(list) do + report("%w%s %s",6,kind,name) + end + end + logs.stoperrorlogging() + end + end) + +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 ctx_processfilemany = context.processfilemany +local ctx_processfileonce = context.processfileonce +local ctx_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,ctx_processfilemany) end +local function processfileonce(name) processfilecommon(name,ctx_processfileonce) end +local function processfilenone(name) processfilecommon(name,ctx_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 + +local scan_delimited = tokens.scanners.delimited + +local function getname() + return scan_delimited(91,93) or scan_delimited(0,32) -- [name] or name +end + +implement { name = "project", public = true, protected = true, actions = function() process(v_project, getname()) end } +implement { name = "environment", public = true, protected = true, actions = function() process(v_environment,getname()) end } +implement { name = "product", public = true, protected = true, actions = function() process(v_product, getname()) end } -- will be overloaded +implement { name = "component", public = true, protected = true, actions = function() process(v_component, getname()) end } + +implement { name = "useproject", public = true, protected = true, actions = function(name) process(v_project, name) end, arguments = "optional" } +implement { name = "useenvironment", public = true, protected = true, actions = function(name) process(v_environment,name) end, arguments = "optional" } +implement { name = "useproduct", public = true, protected = true, actions = function(name) process(v_product, name) end, arguments = "optional" } -- will be overloaded +implement { name = "usecomponent", public = true, protected = true, actions = function(name) process(v_component, name) end, arguments = "optional" } + +-- 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() + local name = scan_delimited(91,93) or scan_delimited(0,32) -- [name] or name + if name == "*" then + name = nameonly(toppath() or name) + end + return name +end + +implement { name = "startproject", public = true, protected = true, actions = function() gotonextlevel(v_project, autoname()) end } +implement { name = "startproduct", public = true, protected = true, actions = function() gotonextlevel(v_product, autoname()) end } +implement { name = "startcomponent", public = true, protected = true, actions = function() gotonextlevel(v_component, autoname()) end } +implement { name = "startenvironment", public = true, protected = true, actions = function() gotonextlevel(v_environment,autoname()) end } + +implement { name = "stopproject", public = true, protected = true, actions = function() gotopreviouslevel(v_project ) end } +implement { name = "stopproduct", public = true, protected = true, actions = function() gotopreviouslevel(v_product ) end } +implement { name = "stopcomponent", public = true, protected = true, actions = function() gotopreviouslevel(v_component ) end } +implement { name = "stopenvironment", public = true, protected = true, actions = function() gotopreviouslevel(v_environment) end } + +implement { name = "currentproject", public = true, actions = function() context(topofstack(v_project )) end } +implement { name = "currentproduct", public = true, actions = function() context(topofstack(v_product )) end } +implement { name = "currentcomponent", public = true, actions = function() context(topofstack(v_component )) end } +implement { name = "currentenvironment", public = true, actions = function() context(topofstack(v_environment)) end } + +-- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- +-- +-- +-- nee +-- standaard +-- +-- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +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, + public = true, + protected = true, + arguments = "optional" +} + +-- 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 = "2 strings" +} + +implement { + name = "setdocumentdefaultargument", + actions = document.setdefaultargument, + arguments = "2 strings" +} + +implement { + name = "setdocumentfilename", + actions = document.setfilename, + arguments = { "integer", "string" } +} + +implement { + name = "getdocumentargument", + actions = { document.getargument, context }, + arguments = "2 strings" +} + +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.usage then + trackers.enable("system.usage") + 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 } + +do + + logs.registerfinalactions(function() + local foundintrees = resolvers.foundintrees() + if #foundintrees > 0 then + logs.startfilelogging(report,"used files") + for i=1,#foundintrees do + report("%4i: % T",i,foundintrees[i]) + end + logs.stopfilelogging() + end + end) + + logs.registerfinalactions(function() + local files = document.files -- or environment.files + local arguments = document.arguments -- or environment.arguments + -- + logs.startfilelogging(report,"commandline options") + if arguments and next(arguments) then + for argument, value in sortedhash(arguments) do + report("%s=%A",argument,value) + end + else + report("no arguments") + end + logs.stopfilelogging() + -- + logs.startfilelogging(report,"commandline files") + if files and #files > 0 then + for i=1,#files do + report("% 4i: %s",i,files[i]) + end + else + report("no files") + end + logs.stopfilelogging() + end) + +end + +if environment.initex then + + logs.registerfinalactions(function() + local startfilelogging = logs.startfilelogging + local stopfilelogging = logs.stopfilelogging + startfilelogging(report,"stored tables") + for k,v in sortedhash(storage.data) do + report("%03i %s",k,v[1]) + end + stopfilelogging() + startfilelogging(report,"stored modules") + for k,v in sortedhash(lua.bytedata) do + report("%03i %s %s",k,v.name) + end + stopfilelogging() + startfilelogging(report,"stored attributes") + for k,v in sortedhash(attributes.names) do + report("%03i %s",k,v) + end + stopfilelogging() + startfilelogging(report,"stored catcodetables") + for k,v in sortedhash(catcodes.names) do + report("%03i % t",k,v) + end + stopfilelogging() + startfilelogging(report,"stored corenamespaces") + for k,v in sortedhash(interfaces.corenamespaces) do + report("%03i %s",k,v) + end + stopfilelogging() + end) + +end + +implement { + name = "continueifinputfile", + public = true, + protected = true, + 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("continuing input file %a",inpname) + else + context.endinput() + end +-- ctx_doifelse(continue) + end +} diff --git a/tex/context/base/mkxl/file-job.mklx b/tex/context/base/mkxl/file-job.mklx new file mode 100644 index 000000000..b455b1770 --- /dev/null +++ b/tex/context/base/mkxl/file-job.mklx @@ -0,0 +1,349 @@ +%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. + +\writestatus{loading}{ConTeXt File Macros / Job Handling} + +\unprotect + +%D This module delegates most of the work to \LUA\ and therefore also let it +%D define the commands, which is more efficient. + +\registerctxluafile{file-job}{autosuffix} + +%D Here are some helpers for processing and path control. In the following example +%D the lookup order is \type {.}, {/foo}, \type {foo/bar} as one can always +%D explicitly prefix a wanted file. +%D +%D \starttyping +%D \pushpath[foo] +%D \pushpath[foo/bar] +%D \input test +%D \poppath +%D \poppath +%D \stoptyping + +% \usepath [#path] % defined at lua end +% \usesubpath [#path] % defined at lua end +% \pushpath [#path] % defined at lua end +% \poppath % defined at lua end +% \resetpath % defined at lua end (not the pushed paths) +% \allinputpaths % defined at lua end +% \doifelseinputfile #name % defined at lua end +% \processfile #name % defined at lua end + +\aliased\let\doifinputfileelse\doifelseinputfile + +% helper (not really needed nowadays) + +\mutable\let\locatedfilepath\empty + +\permanent\protected\def\locatefilepath#name% + {\edef\locatedfilepath{\clf_locatefilepath{#name}}} % todo: set at the lua end, catcodes and such + +% % 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 +% exa stuff might become obsolete: + +% \usezipfile [#zipname]#spacer[#subtree] % defined at lua end +% \loadexamodes [#name] % defined at lua end + +\protected\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 + +\protected\def\dostarttext + {\enforced\glet\dostarttext\relax + \the\everystarttext + \global\everystarttext\emptytoks} + +\protected\def\dostoptext + {\enforced\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 + % tex's \end: + \normalend} + +% \starttext % defined at lua end +% \stoptext % defined at lua end +% \forcequitjob % defined at lua end +% \autostarttext % defined at lua end +% \autostoptext % defined at lua end + +\pushoverloadmode + \aliased\let\end\forceendjob +\popoverloadmode + +\aliased\let\finishjob\stoptext % nicer in luatex call commandline + +\newtoks\everystartnotext +\newtoks\everystopnotext + +\permanent\protected\def\startnotext{\the\everystartnotext} +\permanent\protected\def\stopnotext {\the\everystopnotext\normalend} + +% protect structure + +% \processfilemany {#name} % defined at lua end +% \processfileonce {#name} % defined at lua end +% \processfilenone {#name} % defined at lua end + +% \useproject [#name] % defined at lua end +% \useproduct [#name] % defined at lua end +% \usecomponent [#name] % defined at lua end +% \useenvironment [#name] % defined at lua end + +% \project [#name] or #name % defined at lua end +% \product [#name] or #name % defined at lua end +% \component [#name] or #name % defined at lua end +% \environment [#name] or #name % defined at lua end + +% \startproject [#name] or #name % defined at lua end +% \startproduct [#name] or #name % defined at lua end +% \startcomponent [#name] or #name % defined at lua end +% \startenvironment [#name] or #name % defined at lua end + +\newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua + +% \protected\def\signalendofinput#1% argument just for tracing +% {\global\settrue\endofinput} +% +% \protected\def\honorendofinput +% {\ifconditional\endofinput +% \global\setfalse\endofinput +% \endinput +% \fi} + +% \protected\def\stopproject {\clf_stopproject \honorendofinput} % todo +% \protected\def\stopproduct {\clf_stopproduct \honorendofinput} % todo +% \protected\def\stopcomponent {\clf_stopcomponent \honorendofinput} % todo +% \protected\def\stopenvironment {\clf_stopenvironment\honorendofinput} % todo + +% \currentproject % defined at lua end +% \currentproduct % defined at lua end +% \currentcomponent % defined at lua end +% \currentenvironment % defined at lua end +% \processedfile % defined at lua end +% \processedfiles % defined at lua end +% +% \dostarttextfile #name % defined at lua end +% \dostoptextfile % defined at lua end +% +% \loadtexfile [#name] % defined at lua end +% \loadluafile [#name] % defined at lua end +% \loadcldfile [#name] % defined at lua end +% \loadanyfile [#name] % defined at lua end +% +% \loadtexfileonce [#name] % defined at lua end +% \loadluafileonce [#name] % defined at lua end +% \loadcldfileonce [#name] % defined at lua end +% \loadanyfileonce [#name] % defined at lua end + +%D Handy for modules that have a test/demo appended (true added). + +% \permanent\protected\def\continueifinputfile#name{\clf_doifelsecontinuewithfile{#name}\relax\endinput} % we cannot do \endinput via lua + +% \continueifinputfile #name % defined at lua end + +% \startproject test +% 1: \startmode[*project] project \stopmode \endgraf +% 2: \startmode[*product] product \stopmode \endgraf +% \stopproject + +% A bit 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 + +\permanent\protected\def\startprojectindeed + {%starttext + \pushsystemmode\v!project + \setsystemmode\v!project} + +\permanent\protected\def\stopprojectindeed + {\popsystemmode\v!project + %stoptext + }%\signalendofinput\v!project} + +\permanent\protected\def\startproductindeed + {\starttext + \pushsystemmode\v!product + \setsystemmode\v!product} + +\permanent\protected\def\stopproductindeed + {\popsystemmode\v!product + \stoptext + }%\signalendofinput\v!product} + +\permanent\protected\def\startcomponentindeed + {\starttext + \pushreferenceprefix\currentcomponent + \pushsystemmode\v!component + \setsystemmode\v!component} + +\permanent\protected\def\stopcomponentindeed + {\popsystemmode\v!component + \popreferenceprefix + \stoptext + }%\signalendofinput\v!component} + +\permanent\protected\def\startenvironmentindeed + {\pushsystemmode\v!environment + \setsystemmode\v!environment} + +\permanent\protected\def\stopenvironmentindeed + {\popsystemmode\v!environment + }%\signalendofinput\v!environment} + +%D Upgraded after the ctx 2020 meeting: +%D +%D \starttyping +%D \definedocument[thesis] +%D +%D \setupdocument[a=b,e=f] +%D \setupdocument[thesis][a=x,c=d] +%D +%D % \startsetups[thesis:start] +%D \startsetups[document:start] +%D START +%D \stopsetups +%D +%D \startsetups[thesis:stop] +%D % \startsetups[document:stop] +%D STOP +%D \stopsetups +%D +%D % \startdocument[thesis] +%D \startthesis +%D (\currentdocument/a): \documentvariable{a}\par +%D (\currentdocument/c): \documentvariable{c}\par +%D (\currentdocument/e): \documentvariable{e}\par +%D \stopthesis +%D % \stopdocument +%D \stoptyping + +\installcorenamespace {document} + +\installcommandhandler \??document \s!document \??document + +\setupdocument + [\c!before=\directsetup{\s!document:\v!start}, + \c!after =\directsetup{\s!document:\v!stop}] + +\def\syst_document_setup#1% + {\directsetup{\doifelsesetups{\currentdocument:\v!start}\currentdocument\s!document:\v!start}} + +\appendtoks + \normalexpanded {% + \startsetups[\currentdocument:\v!start]\noexpand\directsetup{\ifx\empty\currentdocumentparent\s!document\else\currentdocumentparent\fi:\v!start}\stopsetups + \startsetups[\currentdocument:\v!stop ]\noexpand\directsetup{\ifx\empty\currentdocumentparent\s!document\else\currentdocumentparent\fi:\v!stop }\stopsetups + \permanent\setvalue{\e!start\currentdocument}{\startdocument[\currentdocument]}% + \permanent\setvalue{\e!stop \currentdocument}{\stopdocument} + }% +\to \everydefinedocument + +% todo: dostarttagged\t!document + +\permanent\tolerant\protected\def\startdocument[#namespace]#spacer[#settings]% + {\pushmacro\currentdocument + \ifparameters + \or + \ifhastok={#namespace}% + \let\currentdocument\empty + \setupcurrentdocument[#namespace]% + \else + \edef\currentdocument{#namespace}% + \fi + \or + \edef\currentdocument{#namespace}% + \setupcurrentdocument[#settings]% + \fi + \ifempty\currentdocument\else\setmode\currentdocument\fi + \starttext + \the\everystartdocument + \documentvariable\c!before} + +\permanent\protected\def\stopdocument % todo: dostoptagged\t!document + {\documentvariable\c!after + \the\everystopdocument + \stoptext + \ifx\empty\currentdocument\else\resetmode\currentdocument\fi + \popmacro\currentdocument} + +\aliased \let\documentvariable \documentparameter +\permanent\protected\def\unexpandeddocumentvariable{\documentparameter} + +\permanent\protected\def\doifelsedocumentvariable#name{\doifelsesomething{\documentvariable{#name}}} +\permanent\protected\def\doifdocumentvariable #name{\doifsomething {\documentvariable{#name}}} +\permanent\protected\def\doifnotdocumentvariable #name{\doifnot {\documentvariable{#name}}} + +\aliased\let\doifdocumentvariableelse\doifelsedocumentvariable + +\permanent\tolerant\protected\def\presetdocument[#namespace]#spacer[#settings]% + {\pushmacro\currentdocument + \ifparameters + \or + \ifhastok={#namespace}% + \let\currentdocument\empty + \setupcurrentdocument[#namespace]% + \fi + \or + \edef\currentdocument{#namespace}% + \setupcurrentdocument[#settings]% + \fi + \popmacro\currentdocument} + +% Bonus: + +% \installcorenamespace{samplefile} +% +% \protected\def\samplefile#1% +% {\ifcsname\??samplefile#1\endcsname \else +% \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% +% \fi +% \lastnamedcs} + +\permanent\protected\def\samplefile#1{\clf_samplefile{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/file-lib.mkxl b/tex/context/base/mkxl/file-lib.mkxl new file mode 100644 index 000000000..c2ec555cf --- /dev/null +++ b/tex/context/base/mkxl/file-lib.mkxl @@ -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}{} + +\protect \endinput diff --git a/tex/context/base/mkxl/file-mod.mklx b/tex/context/base/mkxl/file-mod.mklx new file mode 100644 index 000000000..5e9cd0159 --- /dev/null +++ b/tex/context/base/mkxl/file-mod.mklx @@ -0,0 +1,277 @@ +%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}{} + +%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. + +\installcorenamespace{module} + +\let\currentmodule \s!unknown +\let\currentmodulecategory \empty +\let\currentmoduleparameters\empty + +\installmacrostack\currentmodule +\installmacrostack\currentmodulecategory +\installmacrostack\currentmoduleparameters + +\permanent\tolerant\protected\def\usemodules[#category]#spacer[#name]#spacer[#parameters]% category=t|m|x|p|... + {\push_macro_currentmodule + \push_macro_currentmodulecategory + \push_macro_currentmoduleparameters + \ifparameters + \let\currentmodule\empty + \or + \let \currentmodulecategory \empty + \edef\currentmodule {#category}% + \let \currentmoduleparameters\empty + \or + \ifhastok={#name}% + \let\currentmodulecategory \empty + \edef\currentmodule {#category}% + \edef\currentmoduleparameters{#name}% + \else + \edef\currentmodulecategory {#category}% + \edef\currentmodule {#name}% + \let \currentmoduleparameters\empty + \fi + \or + \edef\currentmodulecategory {#category}% + \edef\currentmodule {#name}% + \def \currentmoduleparameters{#parameters}% + \fi + \processcommacommand[\currentmodule]{\strc_modules_use\currentmodulecategory}% + \pop_macro_currentmoduleparameters + \pop_macro_currentmodulecategory + \pop_macro_currentmodule} + +\def\strc_modules_use#category#name% + {\ifempty\currentmoduleparameters\else + \scratchtoks\expandafter{\currentmoduleparameters}% + \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% + \fi + \clf_usemodules{#category}{#name}} + +\aliased\let\usemodule \usemodules +\aliased\let\usetexmodule\usemodules + +\newcount\c_syst_modules_nesting +\newtoks \everysetupmodule + +\permanent\tolerant\protected\def\startmodule[#1]#;#2 % + {\global\advance\c_syst_modules_nesting\plusone + \push_macro_currentmodule + \push_macro_currentmoduleparameters + \def\currentmodule{#1#2}} + +\permanent\protected\def\stopmodule + {\ifcase\c_syst_modules_nesting + \writestatus\m!system{module wrapping error in '\currentmodule'}% + \else + \pop_macro_currentmoduleparameters + \pop_macro_currentmodule + \global\advance\c_syst_modules_nesting\minusone + \fi} + +\permanent\protected\def\setupmodule % to be lmtx'd + {\ifempty\currentmoduleparameters + \expandafter\syst_modules_setup_nop + \else + \expandafter\syst_modules_setup_yes + \fi} + +\tolerant\def\syst_modules_setup_nop[#name]#spacer[#parameters]% + {\ifarguments + % nothing + \or + \doifassignmentelse{#name}{\getparameters[\??module\currentmodule:][#name]}\donothing + \or + \getparameters[\??module#name:][#parameters]% internal (defaults) + \fi + \the\everysetupmodule} + +\tolerant\def\syst_modules_setup_yes[#name]#spacer[#parameters]% + {\scratchtoks\expandafter{\currentmoduleparameters}% + \ifparameters + \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% + \or + \ifhastok={#name}% + \getparameters[\??module\currentmodule:][#name]% internal (defaults) + \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% loadtime (user) + \else + \normalexpanded{\getparameters[\??module#1:][\the\scratchtoks]}% loadtime (user) + \fi + \or + \getparameters[\??module#name:][#parameters]% internal (defaults) + \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% loadtime (user) + \fi + \let\currentmoduleparameters\empty + \the\everysetupmodule} + +\permanent\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 + +\permanent\def\currentmoduleparameter{\moduleparameter\currentmodule} % no need for inlining + +%permanent\protected\def\useluamodule[#name]{\clf_loadluamodule{#1}} % why not use useluamodule + +\permanent\protected\def\useluamodule [#name]{\clf_useluamodule{#1}} +\permanent\protected\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: + +\permanent\protected\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}} + +\aliased\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!file_run % last is a file name +%D \stoptyping + +\installcorenamespace{runtimeloaded} + +\permanent\protected\def\fetchruntimecommand#1#2% + {\protected\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 + \glet#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}% + \protected\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). + +\permanent\protected\def\doifelseolderversion#parent#child{\clf_doifelseolderversion{#parent}{#child}} +\permanent\protected\def\doifelseoldercontext #child{\clf_doifelseolderversion{#child}{}} + +\aliased\let\doifolderversionelse\doifelseolderversion +\aliased\let\doifoldercontextelse\doifelseoldercontext + +%D Relatively new (no need for a speedup here). Can't this now be done nicer? + +\permanent\protected\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}} + +\permanent\protected\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} + +\permanent\protected\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}} + +\permanent\protected\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} + +\permanent\protected\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}} + +\permanent\protected\def\installmodulecommandlua #1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_direct_lua{\csstring#1}{#2}}}} +\permanent\protected\def\installmodulecommandluasingle#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_single_lua{\csstring#1}{#2}}}} +\permanent\protected\def\installmodulecommandluadouble#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_double_lua{\csstring#1}{#2}}}} + +\protected\def\syst_modules_one_lua#1#2#3% + {\directsetup{module:#1:start}% + \ctxlua{#2(\!!bs#3\!!es)}% + \directsetup{module:#1:stop}} + +\protected\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}} + +\permanent\protected\def\installmodulecommandluaone#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_one_lua{\csstring#1}{#2}}}} +\permanent\protected\def\installmodulecommandluatwo#1#2{\enforced\permanent\protected\def#1{\normalexpanded{\syst_modules_two_lua{\csstring#1}{#2}}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/file-res.mklx b/tex/context/base/mkxl/file-res.mklx new file mode 100644 index 000000000..a523302d1 --- /dev/null +++ b/tex/context/base/mkxl/file-res.mklx @@ -0,0 +1,145 @@ +%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. + +%D We could move some more to the lua end (implementors). + +\writestatus{loading}{ConTeXt File Macros / Resolvers} + +\unprotect + +\registerctxluafile{file-res}{} + +%D \macros +%D {readfile,ReadFile} +%D +%D One cannot be sure if a file exists. When no file can be found, the \type +%D {\input} primitive gives an error message and switches to interactive mode. The +%D macro \type {\readfile} takes care of non||existing files. This macro has two +%D 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 locating files. This +%D can lead to unexpected results, especially when one loads files that are not +%D found in the current directory. Let's give an example of this. In \CONTEXT\ +%D illustrations can be defined in an external file. The resizing macro first looks +%D if an illustration is defined in the local definitions file. When no such file is +%D found, it searches for a global file and when this file is not found either, the +%D illustration itself is scanned for dimensions. One can imagine what happens if an +%D adapted, localy stored illustration, is scaled according to dimensions stored +%D somewhere else. +%D +%D When some \TEX\ implementation starts looking for a file, it normally first looks +%D in the current directory. When no file is found, \TEX\ starts searching on the +%D path where format and|/|or style files are stored. Depending on the +%D implementation this can considerably slow down processing speed. +%D +%D In \CONTEXT, we support a project||wise ordening of files. In such an approach it +%D seems feasible to store common files in a lower directory. When for instance +%D searching for a general layout file, we therefore have to backtrack. +%D +%D These three considerations have lead to a more advanced approach for loading +%D files. +%D +%D We first present an earlier implementation of \type {\readfile}. This command +%D backtracks parent 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} because we want to be able +%D to redefine the original \type {\input} when needed, for instance when loading +%D third party libraries. + +\let\readfilename\empty + +\def\syst_files_read_file#protocol#path#name% #true #false + {\edef\readfilename{\clf_getreadfilename{#protocol}{#path}{#name}}% + \ifempty\readfilename + \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 still can get unwanted +%D files loaded and/or can get involved in extensive searching. +%D +%D Due to different needs, we decided to offer four alternative loading commands. +%D With \type {\readjobfile} we load a local file and do no backtracking, while +%D \type {\readlocfile} backtracks~\number \maxreadlevel\ directories, including the +%D current one. +%D +%D System files can be anywhere and therefore \type {\readsysfile} is not bound to +%D the current directory and obeys the \TEX\ implementation. +%D +%D Of the last two, \type {\readfixfile} searches on the directory specified and +%D backtracks too, while \type {\readsetfile} does only search on the specified +%D path. +%D +%D The most liberal is \type {\readfile}. + +\permanent\protected\def\readjobfile #name{\syst_files_read_file{job} {.}{#name}} % current path, no backtracking +\permanent\protected\def\readlocfile #name{\syst_files_read_file{loc} {.}{#name}} % current path, backtracking +\permanent\protected\def\readsysfile #name{\syst_files_read_file{sys} {.}{#name}} % current path, obeys tex search +\permanent\protected\def\readfixfile#path#name{\syst_files_read_file{fix}{#path}{#name}} % specified path, backtracking +\permanent\protected\def\readsetfile#path#name{\syst_files_read_file{set}{#path}{#name}} % specified path, no backtracking +\permanent\protected\def\readfile #name{\syst_files_read_file{any} {.}{#name}} +\permanent\protected\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 + +\permanent\protected\def\readtexfile#name#true#false% + {\pushcatcodetable + \catcodetable\ctxcatcodes + \readfile{#name}{#true}{#false}% + \popcatcodetable} + +\permanent\protected\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 + +\permanent\protected\def\doifelselocfile#name{\clf_doifelselocfile{#name}} +\permanent \def\locfilename #name{\clf_locfilename {#name}} + +\aliased\let\doiflocfileelse\doifelselocfile + +\protect \endinput diff --git a/tex/context/base/mkxl/file-syn.mklx b/tex/context/base/mkxl/file-syn.mklx new file mode 100644 index 000000000..25f36f742 --- /dev/null +++ b/tex/context/base/mkxl/file-syn.mklx @@ -0,0 +1,61 @@ +%D \module +%D [ file=file-syn, % was core-fil, +%D version=20110701, % 1997.11.15, +%D title=\CONTEXT\ File Macros, +%D subtitle=Module Support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt File Macros / Synonyms} + +\unprotect + +\registerctxluafile{file-syn}{} + +%D \macros +%D {definefilesynonym,definefilefallback} +%D +%D One of the problems with loading files is that their names can depend on the +%D interface language. We therefore need a method to define filesynonyms. The actual +%D synonyms are defined elsewhere, but look like: +%D +%D \starttyping +%D \definefilesynonym [chemic] [chemie] +%D \definefilesynonym [einheit] [unit] +%D \definefilesynonym [unit] [unit] +%D \stoptyping +%D +%D So we can say in english: +%D +%D \starttyping +%D \usemodules[pictex,chemic,unit] +%D \stoptyping +%D +%D and in dutch: +%D +%D \starttyping +%D \usemodules[pictex,chemie,unit] +%D \stoptyping + +\permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}} +\permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}} + +%D \macros +%D {truefilename} +%D +%D At the system level such a filename can be called upon by saying: +%D +%D \starttyping +%D \truefilename{filename/filesynonym} +%D \stoptyping +%D +%D The implementation shows that nesting is supported. + +\permanent\def\truefilename#1{\clf_truefilename{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-aux.mklx b/tex/context/base/mkxl/font-aux.mklx new file mode 100644 index 000000000..caf32510e --- /dev/null +++ b/tex/context/base/mkxl/font-aux.mklx @@ -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: + +\permanent\protected\def\xbox {\bgroup\aftergroup\egroup\hbox\bgroup\tx \let\next=} +\permanent\protected\def\xxbox{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-chk.mkxl b/tex/context/base/mkxl/font-chk.mkxl new file mode 100644 index 000000000..b84056e4e --- /dev/null +++ b/tex/context/base/mkxl/font-chk.mkxl @@ -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}{} + +\tracinglostchars\zerocount + +% Use this instead: +% +% \definefontfeature[default][default][missing=yes] +% \enabletrackers[fonts.missing=replace] + +\permanent\protected\def\checkcharactersinfont {\enabletrackers[fonts.missing]} +\permanent\protected\def\removemissingcharacters {\enabletrackers[fonts.missing=remove]} +\permanent\protected\def\replacemissingcharacters{\enabletrackers[fonts.missing=replace]} + +\endinput diff --git a/tex/context/base/mkxl/font-col.mklx b/tex/context/base/mkxl/font-col.mklx new file mode 100644 index 000000000..1dd5b25c6 --- /dev/null +++ b/tex/context/base/mkxl/font-col.mklx @@ -0,0 +1,148 @@ +%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. + +% 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] +% +% \definefontfeature [emboldened] [effect={width=0.1,delta=0.4,factor=0.3}] +% \definefontsynonym [SansEmboldened] [Sans] [features=emboldened] +% \definefontfallback[FakeSansCaps] [SansEmboldened] [0x0000-0xFFFF] [rscale=.8,method=uppercase] +% \definefontsynonym [SansCaps] [file:MyriadPro-Regular.otf] [fallbacks=FakeSansCaps] + +\writestatus{loading}{ConTeXt Font Macros / Collections} + +\registerctxluafile{font-col}{} + +\unprotect + +\permanent\tolerant\protected\def\definefontfallback[#name]#spacer[#font]#spacer[#ranges]#spacer[#settings]% + {\let\mathsizesuffix\relax + \clf_fontcollectiondefine{#name}{#font}{#ranges}{#settings}% + \let\mathsizesuffix\empty} + +\permanent\tolerant\protected\def\resetfontfallback[#name]#spacer[#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 + \ifempty\m_font_fallbacks + \ifempty\m_font_class_fallbacks\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}} + +% math (experiment, todo clf_) + +\def\font_fallbacks_register_math#1#2#3#4% + {\doifelsenothing{#3}% + {\definedfont[#2 at #4sp]}% + {\definedfont[#2*#3\space at #4\scaledpoint]}% + \clf_registerfontfallbackid#1\space\fontid\font\space{#2}} + +% \def\font_fallbacks_finish_math +% {\ctxlua{mathematics.finishfallbacks()}} + +% 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/tex/context/base/mkxl/font-emp.mklx b/tex/context/base/mkxl/font-emp.mklx new file mode 100644 index 000000000..33104a6d7 --- /dev/null +++ b/tex/context/base/mkxl/font-emp.mklx @@ -0,0 +1,256 @@ +%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 \type {\em} (\TUGNEWS\ +%D Vol.~3, no.~1, 1994). His implementation was a bit more sophisticated version of +%D the standard \LATEX\ one. We further enhanced the macro, so now it also adapts +%D itself to boldface mode. Because we favor {\sl slanted} type over {\it italic}, +%D we made the emphasis 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 \protected\def\emphasistypeface{\sl} +%D \protected\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% + \orelse\ifx\m_font_emphasized_typeface\v!italic + #italic% + \orelse\ifempty\m_font_emphasized_typeface + #slanted% + \else + \csname\m_font_emphasized_typeface\endcsname + \fi} + +\permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it} +\permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi} + +\permanent\protected\def\normalboldface % public + {\relax + \ifx\fontalternative\s!it\bi\orelse + \ifx\fontalternative\s!sl\bs\else + \bf\fi} + +\permanent\protected\def\normalitalicface % public + {\relax + \ifx\fontalternative\s!tf\it\orelse + \ifx\fontalternative\s!bf\bi\else + \tf\fi} + +\permanent\protected\def\normalslantedface % public + {\relax \ifx\fontalternative\s!tf\sl + \orelse\ifx\fontalternative\s!bf\bs + \else \tf\fi} + +\permanent\protected\def\normaltypeface % public + {\relax + \ifx\fontalternative\s!bi \it \orelse + \ifx\fontalternative\s!bs \sl \else + \tf \fi} + +\permanent\protected\def\swaptypeface % public + {\relax + \ifx\fontalternative\s!it \tf \orelse + \ifx\fontalternative\s!sl \tf \orelse + \ifx\fontalternative\s!bf \emphasisboldface \orelse + \ifx\fontalternative\s!bs \bf \orelse + \ifx\fontalternative\s!bi \bf \else + \emphasistypeface \fi} + +\aliased\let\typeface \normaltypeface % public +\aliased\let\boldface \normalboldface % public +\aliased\let\slantedface\normalslantedface % public +\aliased\let\italicface \normalitalicface % public +\aliased\let\swapface \swaptypeface % public + +%D To be set with the default body font environment: \type {em} being \type +%D {slanted} or \type {italic}. + +% maybe a \csname...\fontalternative\endcsname + +\newconditional\c_font_emphasis_needed + +\permanent\protected\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 + \enforced\permanent\protected\def\emphasistypeface{\it}\tf + \orelse\ifx\fontalternative\s!sl + \enforced\permanent\protected\def\emphasistypeface{\sl}\tf + \orelse\ifx\fontalternative\s!bf + \emphasisboldface + \orelse\ifx\fontalternative\s!bs + \enforced\permanent\protected\def\emphasisboldface{\bs}\bf + \orelse\ifx\fontalternative\s!bi + \enforced\permanent\protected\def\emphasisboldface{\bi}\bf + \else + \emphasistypeface + \fi + \ifconditional\c_font_emphasis_needed\else + \expandafter\aftergroup + \fi + \emphasiscorrection} + +%D The next feature was not present in previous versions. It takes care of \type +%D {\em \bf ...} situations. + +\let\font_emphasis_saved_emphasis_boldface\relax + +\def\font_emphasis_set_emphasis_boldface + {\let\font_emphasis_saved_emphasis_boldface\bf + \let\font_emphasis_set_emphasis_boldface\relax + \enforced\let\bf\font_emphasis_bold_bold} + +\protected\def\font_emphasis_bold_bold + {%\relax + \enforced\let\bf\relax % new + \ifx\fontalternative\s!it + \bi + \orelse\ifx\fontalternative\s!sl + \bs + \else + \font_emphasis_saved_emphasis_boldface + \fi + \enforced\let\bf\font_emphasis_saved_emphasis_boldface} + +%D Donald's (adapted) macros take the next character into account when placing +%D italic correction. As a bonus we also look for something that looks like a dash, +%D in which case we don't correct. + +\let\italiccorrection=\/ % tex primitive + +\permanent\protected\def\emphasiscorrection % public, not in raw alignment groups, else omit problem + {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else + \expandafter\expandafter\expandafter\font_emphasis_look + \fi\fi} + +\def\font_emphasis_look + {\begingroup + \futurelet\nexttoken\font_emphasis_test} + +\def\font_emphasis_test + {\ifcat\noexpand\nexttoken,% we can do better in luatex ... some day ... + \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 + \ifzeropt\ht\scratchbox % probably a space + \expandafter\font_emphasis_b + \orelse\ifdim\ht\scratchbox<.3\exheight + \expandafter\expandafter\expandafter\endgroup + \else + \expandafter\expandafter\expandafter\font_emphasis_b + \fi} + +\def\font_emphasis_b + {\scratchskip\lastskip + \ifzeropt\scratchskip + \italiccorrection\relax + \else + \unskip\italiccorrection\hskip\scratchskip + \fi + \endgroup} + +%D We end with some examples which show the behavior when some punctuation is met. +%D We also show how the mechanism 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 their style as good as +%D possible. These macros are obsolete in \MKIV. + +% \protected\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} +% \protected\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} +% \protected\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} +% \protected\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} +% \protected\def\emph {\groupedcommand{\em}{}} + +\protected\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}} +\protected\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}} +\protected\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}} +\protected\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}} + +\permanent\protected\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf} +\permanent\protected\def\emphit{\triggergroupedcommandcs\font_emphasis_it} +\permanent\protected\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl} +\permanent\protected\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf} +\permanent\protected\def\emph {\triggergroupedcommandcs\em} + +\permanent\protected\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/tex/context/base/mkxl/font-fea.mklx b/tex/context/base/mkxl/font-fea.mklx new file mode 100644 index 000000000..5f83c87d3 --- /dev/null +++ b/tex/context/base/mkxl/font-fea.mklx @@ -0,0 +1,382 @@ +%D \module +%D [ file=font-sty, +%D version=2011.01.13, % (copied fron font-ini) +%D title=\CONTEXT\ Font Macros, +%D subtitle=features, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Font Macros / Features} + +\unprotect + +%D Feature management. +%D +%D \starttyping +%D \definefontfeature[smallcaps][smcp=yes,script=latn] +%D \definefontfeature[smallcaps][SmallCapitals=yes,script=latn] +%D \definefontfeature[smallcaps][Small Capitals=yes,script=latn] +%D \definefontfeature[smallcaps][small capitals=yes,script=latn] +%D \definefontfeature[smallcaps][smallcapitals=yes,script=latn] +%D +%D \definedfont[cambria*smallcaps] test +%D +%D \starttext +%D \definefontfeature[basekerned][default][mode=base] +%D \definefontfeature[nodekerned][default][mode=node] +%D \definefontfeature[nonekerned][default][mode=base,kern=no] +%D \setupcolors[state=start] +%D \startoverlay +%D {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }} +%D {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }} +%D {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }} +%D \stopoverlay +%D \stoptext +%D +%D \enabletrackers[otf.kerns] +%D +%D \definefontfeature[withkern][default][mode=node] +%D \definefontfeature[nokern] [default][mode=node,kern=no] +%D \definefontfeature[single] [default][mode=node,cpsp=yes] +%D \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no] +%D +%D {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D \stoptyping + +% \definefontfeature[slanted] [default][slant=.25] +% \definefontfeature[stretched][default][stretch=2] +% +% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop +% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop +% +% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes] +% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn] +% +% \starttypescript [serif] [palatino-nova-regular] [name] +% \definefontsynonym[Serif] [palatinonova-regular][features=default] +% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif +% \stoptypescript +% +% \starttypescript [serif] [palatino-nova-regular] [name] +% \definefontsynonym[Serif] [palatinonova-regular*default] +% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps] +% \stoptypescript +% +% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface] +% +% \starttext +% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl +% \stoptext +% +% \definefontfeature +% [default-base] +% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes] +% \definefontfeature +% [default-node] +% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node] +% \definefontfeature +% [default-none] +% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes] +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \blank +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \blank +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \definefontfeature[superdefault][default][compose=yes] +% +% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683} +% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683} + +\permanent\tolerant\protected\def\definefontfeature[#featureset]#spacer[#parent]#spacer[#settings]% + {\clf_definefontfeature{#featureset}{#parent}{#settings}} + +\permanent\tolerant\protected\def\adaptfontfeature[#pattern]#spacer[#settings]% + {\clf_adaptfontfeature{#pattern}{#settings}} + +\permanent\protected\def\fontfeatureslist[#name]#spacer[#separator]% todo: arg voor type + {\clf_featurelist{#name}{\detokenize{#separator}}} + +\attribute\zerocount\attributeunsetvalue + +\glyphdatafield\zerocount + +\let\font_dynamic_value\glyphdatafield + +% beware: these are global features on top of existing font features + +\let\currentfeature \s!current +\let\m_font_feature_list \s!current +\let\m_font_feature_asked\empty + +\newconstant\c_font_feature_state + +% hashing at this end is slower + +\permanent\tolerant\protected\def\addfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_add} +\permanent\tolerant\protected\def\subtractfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_subtract} +\permanent\tolerant\protected\def\replacefeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_replace} +\permanent\tolerant\protected\def\resetandaddfeature[#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_reset_add} +\permanent\tolerant\protected\def\feature [#1]#;#2{\begincsname\??featureshortcut#1#2\endcsname} + +% for old times sake + +\permanent\protected\def\doaddfeature #1{\edef\m_font_feature_asked{#1}\font_feature_add} +\permanent\protected\def\dosubtractfeature #1{\edef\m_font_feature_asked{#1}\font_feature_subtract} +\permanent\protected\def\doreplacefeature #1{\edef\m_font_feature_asked{#1}\font_feature_replace} +\permanent\protected\def\doresetandaddfeature#1{\edef\m_font_feature_asked{#1}\font_feature_reset_add} + +\protected\def\font_feature_add + {\ifnum\c_font_feature_state=\plusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_add_indeed + \fi + \else + \font_feature_add_indeed + \fi} + +\protected\def\font_feature_add_indeed + {\clf_addfeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list+\m_font_feature_asked}% also + at the lua end + \c_font_feature_state\plusone + \let\currentfeature\m_font_feature_asked} + +\protected\def\font_feature_subtract + {\ifnum\c_font_feature_state=\minusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_subtract_indeed + \fi + \else + \font_feature_subtract_indeed + \fi} + +\protected\def\font_feature_subtract_indeed + {\clf_subtractfeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list-\m_font_feature_asked}% also - at the lua end + \c_font_feature_state\minusone + \let\currentfeature\m_font_feature_asked} + +\protected\def\font_feature_replace + {\ifnum\c_font_feature_state=\zerocount + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_replace_indeed + \fi + \else + \font_feature_replace_indeed + \fi} + +\protected\def\font_feature_replace_indeed + {\clf_replacefeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list=\m_font_feature_asked}% also = at the lua end + \c_font_feature_state\zerocount + \let\currentfeature\m_font_feature_asked} + +\permanent\protected\def\resetfeature + {\ifx\currentfeature\s!current \else + \font_feature_reset_indeed + \fi} + +\protected\def\font_feature_reset_indeed + {\let\m_font_feature_asked\empty + \let\currentfeature \s!current + \let\m_font_feature_list \s!current + \clf_resetfeature} + +\permanent\protected\def\revivefeature + {\ifx\currentfeature\s!current \else + \font_feature_revive_indeed + \fi} + +\protected\def\font_feature_revive_indeed + {\clf_revivefeature{\m_font_feature_list}} + +\protected\def\font_feature_reset_add + {\ifnum\c_font_feature_state=\plusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_reset_add_indeed + \fi + \else + \font_feature_reset_add_indeed + \fi} + +\protected\def\font_feature_reset_add_indeed + {\clf_addfeature{\s!current}{\m_font_feature_asked}% + \edef\m_font_feature_list{\s!current+\m_font_feature_asked}% also + at the lua end + \c_font_feature_state\plusone + \let\currentfeature\m_font_feature_asked} + +\installcorenamespace{featureshortcut} + +\letvalue{\??featureshortcut +}\addfeature +\letvalue{\??featureshortcut -}\subtractfeature +\letvalue{\??featureshortcut =}\replacefeature +\letvalue{\??featureshortcut !}\resetandaddfeature +\letvalue{\??featureshortcut >}\revivefeature +\letvalue{\??featureshortcut <}\resetfeature + +\letvalue{\??featureshortcut\v!more }\addfeature % add set to previous set and combine with font set +\letvalue{\??featureshortcut\v!less }\subtractfeature % subtract set from previous set and combine with font set +\letvalue{\??featureshortcut\v!new }\replacefeature % replace font set +\letvalue{\??featureshortcut\v!reset }\resetfeature % forget sets and revert to font set +\letvalue{\??featureshortcut\v!default}\revivefeature % make sure the current set is used on top of the font set +\letvalue{\??featureshortcut\v!old }\revivefeature +\letvalue{\??featureshortcut\v!local }\resetandaddfeature +\letvalue{\??featureshortcut\s!unknown}\empty + +% experimental bonus: + +% \protected\def\addfflanguage +% {\ifnum\c_font_feature_state=\plusone +% \ifx\currentlanguage\currentfeature\else +% \font_feature_add_language_indeed +% \fi +% \else +% \font_feature_add_language_indeed +% \fi} +% +% \protected\def\font_feature_add_language_indeed +% {\clf_addfeature{\m_font_feature_list}{\currentlanguage}% +% \edef\m_font_feature_list{\m_font_feature_list+\currentlanguage}% also + at the lua end +% \c_font_feature_state\plusone +% \let\currentfeature\currentlanguage} +% +% some 3% slower: + +% \protected\def\addfflanguage +% {\let\m_font_feature_asked\currentlanguage +% \font_feature_add} + +\let\m_font_feature_language\currentlanguage + +\permanent\protected\def\addfflanguage + {\ifx\currentlanguage\m_font_feature_language\else + \let\m_font_feature_language\currentlanguage + \let\m_font_feature_asked \currentlanguage + \font_feature_add + \fi} + +% just for old times sake: + +\permanent\protected\def\featureattribute#feature% + {\clf_featureattribute{#feature}} + +\permanent\protected\def\setfontfeature#feature% + {\edef\currentfeature{#feature}% + \let\m_font_feature_list\currentfeature + \clf_setfontfeature{\currentfeature}} + +% these are obsolete (don't use them any longer) + +\aliased\let\resetfontfeature\resetfeature % obsolete + +% these are obsolete (don't use them any longer) + +% \let\addfontfeaturetoset \font_feature_add_nop % obsolete +% \let\subtractfontfeaturefromset \font_feature_subtract_nop % obsolete +% \let\addfontfeaturetofont \font_feature_add_nop % obsolete +% \let\subtractfontfeaturefromfont\font_feature_subtract_nop % obsolete + +% these are obsolete (don't use them any longer) + +\aliased\let\setff\setfontfeature % obsolete +\aliased\let\addfs\doaddfeature % obsolete +\aliased\let\subfs\dosubtractfeature % obsolete +\aliased\let\addff\doaddfeature % obsolete +\aliased\let\subff\dosubtractfeature % obsolete + +%D \macros +%D {os} +%D +%D In good old \TEX, the old style numerals were often taken from the math fonts. No +%D longer. + +\definefontfeature + [just-os] + [mode=node,onum=yes] + +%frozen\protected\def\sc{\setfontfeature{smallcaps}} +\permanent\protected\def\os{\setfontfeature{just-os}} + +% \doifelsecurrentfonthasfeature{smcp}{YES}{NO} +% \doifelsecurrentfonthasfeature{crap}{YES}{NO} +% \doifelsecurrentfonthasfeature{kern}{YES}{NO} + +\permanent\def\doifelsecurrentfonthasfeature#feature{\clf_doifelsecurrentfonthasfeature{#feature}} % expandable +\permanent\def\doifelsefontfeature #feature{\clf_doifelsefontfeature {#feature}} % expandable +\permanent\def\doifunknownfontfeature #feature{\clf_doifunknownfontfeature {#feature}} % expandable + +\aliased\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature +\aliased\let\doiffontfeatureelse \doifelsefontfeature + +% new: + +\clf_registerlanguagefeatures + +% also new + +\permanent\protected\def\useaddfontfeatureparameter#namespace% faster local variant + {\edef\m_font_feature_asked{#namespace\c!features}% + \ifempty\m_font_feature_asked\else + \font_feature_add + \fi} + +% let's put this here: + +\permanent\protected\def\slashedzero + {\dontleavehmode + \begingroup + %\addff{zero} + \doaddfeature{zero}% + 0% + \endgroup} + +% not nice but maybe handy + +% \starttyping +% \blockligatures[fi,ff] \blockligatures[fl] +% +% \definefontfeature[default:b][default][blockligatures=yes] +% +% \setupbodyfont[pagella] \showfontkerns +% +% \definedfont[Serif*default:b] +% +% \startTEXpage[offset=1em] +% fi ff fl +% \stopTEXpage +% \stoptyping + +\permanent\protected\def\blockligatures[#1]{\clf_blockligatures{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-fil.mklx b/tex/context/base/mkxl/font-fil.mklx new file mode 100644 index 000000000..08c9241aa --- /dev/null +++ b/tex/context/base/mkxl/font-fil.mklx @@ -0,0 +1,385 @@ +%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 complicated by the way +%D fonts are handled. Apart from the many encodings, we also deal with different +%D naming schemes. Confronted with this problem, I decided to change the definitions +%D 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] + +\permanent\protected\tolerant\protected\def\startfontclass[#class]% + {\push_macro_fontclass + \doifelse{#class}\v!each + {\let\fontclass\empty} + {\doifsomething{#class}{\def\fontclass{#class}}}} + +\permanent\protected\def\stopfontclass + {\pop_macro_fontclass} + +\permanent\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt] + +%D \macros +%D {definefontsynonym, doifelsefontsynonym, +%D expandfontsynonym, truefontname, truefontdata} +%D +%D While looking for fonts, fontsynonyms are used for accessing 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} + +\permanent\protected\def\definefontsynonym[#name]#spacer[#file]% + {\edef\m_font_name{#name}% + \edef\m_font_file{#file}% + \ifempty\fontclass + \expandafter\font_basics_define_font_synonym_nop + \else + \expandafter\font_basics_define_font_synonym_yes + \fi} + +\protected\def\font_basics_define_font_synonym_nop + {\letcsname\??fontfile\m_font_name\endcsname\m_font_file + \doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil} + +\protected\def\font_basics_define_font_synonym_yes + {\letcsname\??fontfile\fontclass\m_font_name\endcsname\m_font_file + \doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil} + +\permanent\protected\def\edefinefontsynonym[#name]#spacer[#file]% + {\edef\m_font_name{#name}% + \edef\m_font_file{#file}% + \ifempty\fontclass + \expandafter\font_basics_define_font_synonym_nop_expanded + \else + \expandafter\font_basics_define_font_synonym_yes_expanded + \fi} + +\protected\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]% + {\letcsname\??fontfile\m_font_name\endcsname\m_font_file + \normalexpanded{\font_basics_define_font_synonym_nop_opt[#spec]}} + +\protected\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]% + {\letcsname\??fontfile\fontclass\m_font_name\endcsname\m_font_file + \normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}} + +\protected\def\font_basics_define_font_synonym_nop_opt[#specification]% + {\let\p_features \undefined + \let\p_fallbacks \undefined + \let\p_goodies \undefined + \let\p_designsize\undefined + \expandafter\font_basics_get_font_parameter_nop#specification,\ignorearguments} + +\protected\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,\ignorearguments} + +% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that +% can be default then: \let\mathsizesuffix\relax .. i need to play with it first + +\def\font_basics_get_font_parameter_nop#key=#value,% + {\ifarguments + \font_basics_get_font_parameter_nop_finish + \else + \defcsname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix + \expandafter\font_basics_get_font_parameter_nop + \fi} + +\def\font_basics_get_font_parameter_yes#key=#value,% + {\ifarguments + \font_basics_get_font_parameter_yes_finish + \else + \defcsname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix + \expandafter\font_basics_get_font_parameter_yes + \fi} + +% helpers, some day these will be toks and counts + +% \def\fntsetdefname {\glet\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 + {\letcsname\??fontfile\m_font_name\s!features \endcsname\undefined + \letcsname\??fontfile\m_font_name\s!fallbacks \endcsname\undefined + \letcsname\??fontfile\m_font_name\s!goodies \endcsname\undefined + \letcsname\??fontfile\m_font_name\s!designsize\endcsname\undefined} + +\def\font_basics_define_font_synonym_yes_nil + {\gletcsname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined + \gletcsname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined + \gletcsname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined + \gletcsname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined} + +\def\font_basics_get_font_parameter_nop_finish + {\letcsname\??fontfile\m_font_name\s!features \endcsname\p_features + \letcsname\??fontfile\m_font_name\s!fallbacks \endcsname\p_fallbacks + \letcsname\??fontfile\m_font_name\s!goodies \endcsname\p_goodies + \letcsname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize} + +\def\font_basics_get_font_parameter_yes_finish + {\gletcsname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features + \gletcsname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks + \gletcsname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies + \gletcsname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize} + +%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}] +%\defineclassfontsynonym [KopFont] [officina] [SerifBold] +%\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]} + +\permanent\tolerant\protected\def\defineclassfontsynonym[#tag]#spacer[#class]#spacer[#fileortag]% needs testing + {\defcsname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}% + \font_basics_define_font_synonym_yes_nil} + +\aliased\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater + +\permanent\tolerant\protected\def\setupfontsynonym[#name]#spacer[#settings]% not yet supported, will do when needed + {} + +% todo: replace * by ... less messy with features + +% no \ifempty here as #1 can be empty + +\permanent\def\truefontname#name% + {\expandafter\font_helpers_true_fontname#name*\empty*\relax} + +\def\font_helpers_true_fontname#name*#first#rest*#ignore\relax + {\ifcsname\??fontfile\fontclass#name\endcsname + \ifx#first\empty + \expandafter\truefontname\lastnamedcs + \else + \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% + \fi + \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname + \ifx#first\empty + \expandafter\truefontname\lastnamedcs + \else + \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% + \fi + \orelse\ifcsname\??fontfile#name\endcsname + \ifx#first\empty + \expandafter\truefontname\lastnamedcs + \else + \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% + \fi + \else + #name\ifx#first\empty\else*#first#rest\fi + \fi} + +\def\font_helpers_true_fontname_check#name% + {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax} + +\def\font_helpers_true_fontname_check_indeed#name*#ignore\relax + {\ifcsname\??fontfile\fontclass#name\endcsname + \expandafter\font_helpers_true_fontname_check\lastnamedcs + \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname + \expandafter\font_helpers_true_fontname_check\lastnamedcs + \orelse\ifcsname\??fontfile#name\endcsname + \expandafter\font_helpers_true_fontname_check\lastnamedcs + \else + #name% + \fi} + +% ok when the last lookup is not stripped .. we need to be able to define synonyms for symbols + +\permanent\def\expandfontsynonym#command#name% one level expansion + {\ifcsname\??fontfile\fontclass#name\endcsname + \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% + \orelse\ifcsname\??fontfile\defaultfontclass#2\endcsname + \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% + \fi} + +\permanent\def\doifelsefontsynonym#name% + {\ifcsname\??fontfile\fontclass#name\endcsname + \expandafter\firstoftwoarguments + \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiffontsynonymelse\doifelsefontsynonym + +%D \macros +%D {tracedfontname} +%D +%D A goody: + +\permanent\def\tracedfontname#name% + {#name\ifcsname\??fontfile\fontclass#name\endcsname + %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname + \expandafter\tracedfontname\lastnamedcs + \orelse\ifcsname\??fontfile#name\endcsname + %\expandafter\tracedfontname\csname\??fontfile#name\endcsname + \expandafter\tracedfontname\lastnamedcs + \fi} + +%D \macros +%D {fontclass, defaultfontclass} +%D +%D The fontclass model was introduced a while after we implement the basic font +%D model and at that time we still defaulted to no model at all. Nowadays we default +%D to the \type {modern} fontclass. + +\let\fontclass \empty +\let\defaultfontclass\empty + +\permanent\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting + {\ifcsname\??fontfile#class#name\endcsname + \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}% + \orelse\ifcsname\??fontfile#name\endcsname + \fontclassname{#class}{\csname\??fontfile#name\endcsname}% + \else + #2% + \fi} + +\installmacrostack\fontclass + +%D Files or names can have properties and these need to be consulted at some point. +%D They can inherit them. + +% Why these expanded and rscale not ... maybe not worth the trouble (delayed +% expansion actually would be better i.e. macros in feature specs). Test without +% pre-expansion. + +\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{\lastnamedcs}\orelse % class + symbolic_name + \ifcsname\??fontfile #name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse % symbolic_name + \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \orelse % class + parent_name + \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % parent_name + \let\m_font_features\empty\fi} + +\def\font_helpers_set_fallbacks_yes#name% + {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse + \ifcsname\??fontfile #name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse + \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \orelse + \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else + \let\m_font_fallbacks\empty\fi} + +\def\font_helpers_set_goodies_yes#name% + {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse + \ifcsname\??fontfile #name\s!goodies \endcsname \edef\m_font_goodies{\lastnamedcs}\orelse + \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \orelse + \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else + \let\m_font_goodies\empty\fi} + +\def\font_helpers_set_designsize_yes#name% + {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse + \ifcsname\??fontfile #name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse + \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \orelse + \ifcsname\??fontfile #name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else + \let\m_font_designsize\empty\fi} + +\def\font_helpers_set_features_nop#name% + {\ifcsname\??fontfile#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\orelse + \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_features_nop\lastnamedcs \else + \let\m_font_features\empty\fi} + +\def\font_helpers_set_fallbacks_nop#name% + {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\orelse + \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_fallbacks_nop\lastnamedcs \else + \let\m_font_fallbacks\empty\fi} + +\def\font_helpers_set_goodies_nop#name% + {\ifcsname\??fontfile#name\s!goodies\endcsname \edef\m_font_goodies{\lastnamedcs}\orelse + \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_goodies_nop\lastnamedcs \else + \let\m_font_goodies\empty\fi} + +\def\font_helpers_set_designsize_nop#name% + {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\orelse + \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_designsize_nop\lastnamedcs \else + \let\m_font_designsize\empty\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 + {\ifempty\fontclass\font_helpers_update_font_parameters_nop\else\font_helpers_update_font_parameters_yes\fi} + +\installcorenamespace{fontclass} + +% we can pack them (don't use \setxvalue!) + +\permanent\protected\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction% + {\gletcsname\??fontclass\fontclass#style\s!rscale \endcsname#rscale% + \gletcsname\??fontclass\fontclass#style\s!features \endcsname#features% + \gletcsname\??fontclass\fontclass#style\s!fallbacks \endcsname#fallbacks% + \gletcsname\??fontclass\fontclass#style\s!goodies \endcsname#goodies% + \gletcsname\??fontclass\fontclass#style\s!designsize\endcsname#designsize% + \gletcsname\??fontclass\fontclass#style\s!direction \endcsname#direction}% math + +% bonus + +\let\currentfontinstancespec\clf_currentfontinstancespec % expandable + +\protect \endinput diff --git a/tex/context/base/mkxl/font-gds.mklx b/tex/context/base/mkxl/font-gds.mklx new file mode 100644 index 000000000..897478273 --- /dev/null +++ b/tex/context/base/mkxl/font-gds.mklx @@ -0,0 +1,97 @@ +%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}{} + +\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] + +\definecolor[colorscheme:4:1] [r=.6] % a +\definecolor[colorscheme:4:5] [g=.6] % e +\definecolor[colorscheme:4:9] [b=.6] % i +\definecolor[colorscheme:4:15][g=.6,b=.6] % o +\definecolor[colorscheme:4:21][r=.6,b=.6] % u +\definecolor[colorscheme:4:25][r=.6,b=.6] % y + +\definesystemattribute[colorscheme][public] + +\permanent\protected\def\loadfontgoodies[#filename]{\clf_loadfontgoodies{#filename}} % todo: public implementor + +\permanent\protected\def\setfontcolorscheme % will move to the lua end + {\clf_enablefontcolorschemes + \enforced\permanent\protected\xdef\setfontcolorscheme[##1]{\c_attr_colorscheme##1\relax}% + \setfontcolorscheme} + +\permanent\protected\def\resetfontcolorscheme + {\c_attr_colorscheme\attributeunsetvalue} + +\protect \endinput + +% \definefontfeature[husayni-colored][goodies=husayni,colorscheme=default,featureset=default] +% +% \definedfont[husayni*husayni-colored at 36pt] +% +% \starttext \righttoleft +% +% \setfontcolorscheme[1] +% +% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ +% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛ +% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ، +% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ +% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ. +% +% \setfontcolorscheme[2] +% +% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ +% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛ +% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ، +% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ +% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ. +% +% \resetfontcolorscheme +% +% اَلْحَمْ‍دُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ +% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛ +% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ، +% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ +% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ. +% +% \stoptext diff --git a/tex/context/base/mkxl/font-ini.mklx b/tex/context/base/mkxl/font-ini.mklx new file mode 100644 index 000000000..5d39001b1 --- /dev/null +++ b/tex/context/base/mkxl/font-ini.mklx @@ -0,0 +1,2512 @@ +%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: frozen tolerant iftok etc + +% 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 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 pure \TEX\ ones, the +%D 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 at}. This means as +%D much as: scale the bodyfontsize with this factor. The scaled option is not that +%D useful as one needs to know the design size. +%D +%D Because \type {sa} (scaled at) and \type {mo} (mapped on) are not low level \TEX\ +%D supported alternatives, we have to test for it ourselves. In doing so, we need an +%D auxiliary \DIMENSION. We cannot use \type{\scratchdimen} because font loading can +%D happen at any moment due to postponed loading. We could instead have used dirty +%D grouping tricks, but this 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, we distinguish +%D between several styles. In most cases we will 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 using Lucida Bright we +%D 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}) we can define a number +%D 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}. Users are not confronted +%D with sizes, but use the style or style+alternative to activate them. +%D +%D During the definition of a bodyfont one can also declare the available larger +%D 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 larger alternatives on the +%D other hand have no limitations. +%D +%D These larger alternatives are mostly used in chapter and section titles or on +%D title pages. When one switches to a larger alternative, the bold an other ones +%D automatically 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 before, we tried to make +%D 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 normally sized +%D typeface. This commands results in roman, sans serif, teletype or whatever style +%D is in charge. Such rather massive switches of style sometimes take more +%D processing time than comfortable. Of course there is a workaround for this: we +%D can call fonts directly by means of commands like: +%D +%D \starttyping +%D \rmtf \sssl \tttf \rmbsa +%D \stoptyping +%D +%D One should realize that this fast calls have limitations, they lack for instance +%D automatic super- and subscript support. +%D +%D This leaves us two more commands: \type {\tx} and \type {\txx}. These activate a +%D smaller and even more smaller font than the current one and adapt themselves to +%D the current alternative, so when \type {\bf} is active, \type {\tx} gives a +%D smaller boldface, which in turn can be called directly by \type {\bfx}. +%D +%D These two smaller alternatives are specified by the bodyfont environment and +%D therefore not necessarily have similar sizes as \type {\scriptsize} and \type +%D {\scriptscriptsize}. The main reason for this incompatibility (which can easily +%D be undone) lays in the fact that we often want a bit bigger characters than in +%D math mode. In \CONTEXT\ for instance the \type {\tx} and \type {\txx} commands +%D are used for surrogate \cap {smallcaps} which support both nesting and +%D alternatives, 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 \cap {THIS}: +%D \ruledhbox {$\rm \scriptstyle scriptstyle: THIS$} or \ruledhbox {\cap {x style: +%D THIS}} makes a big difference. +%D +%D The \type {x..d} sizes should be used grouped. If you don't group them, i.e. call +%D them in a row, \CONTEXT\ will not be able to sort out your intention (\type {x} +%D inside \type {d} inside \type {x}. etc.). The following table 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 + +\appendtoks + \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 +\to \everyjob + +%D Tracing + +\newtoks\t_font_tracers_definitions + +\permanent\protected\def\tracefontdefinitions + {\the\t_font_tracers_definitions} + +%D Some housekeeping macros: + +\permanent\protected\def\setfontparameters + {\setfalse\c_font_synchronize + \the\everybodyfont + \settrue\c_font_synchronize} + +\let\savedfont\empty + +\installmacrostack\savedfont + +% \fontname\font : string +% \fontid \font : integer +% \the \font : token (reference to font) +% \fontspecifiedname : string +% \the \fontspecifiedsize : dimension + +\permanent\protected\def\savefont + {\edef\savedfont{\the\font}% + \push_macro_savedfont} + +\permanent\protected\def\restorefont + {\pop_macro_savedfont + \savedfont} + +\permanent\protected\def\pushcurrentfont + {\enforced\permanent\protected\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} + +\mutable\let\thedefinedfont\relax % not to be confused with \everydefinefont + +\permanent\tolerant\protected\def\definedfont[#specification]% + {\ifarguments + \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly + \or + \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly + \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% + \fi + \thedefinedfont + \the\everydefinedfont} + +%D \macros{startfont} + +\permanent\protected\def\startfont{\begingroup\definedfont} +\permanent\protected\def\stopfont {\endgroup} + +%D \macros +%D {everybodyfont,everyglobalbodyfont} +%D +%D Every change in bodyfont size has conseqences for the baseline distance and skips +%D between paragraphs. These are initialized in other modules. Here we only provide +%D the hooks that 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 +%D Here we have to distinguish between the global (overal) bodyfont size and the +%D local (sometimes in the textflow) size. We store these dimensions in two +%D \DIMENSION\ registers. These registers are 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 {\the}'d +%D value comes out as 12.0pt, which is often not the way users specify the bodyfont +%D size. Therefore we use normalized values. They are cached to save overhead in +%D \LUA\ calls. + +\installcorenamespace{fontnormalizedbody} + +\permanent\protected\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}% + \gletcsname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro} + +\permanent\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 slightly different sizes +%D than the ones given. This happens for instance with the Math Times fonts. Mapped +%D font sizes can be specified by using the \type {mo} key instead of \type {sa} in +%D 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} + +\permanent\tolerant\protected\def\mapfontsize[#from]#spacer[#to]% + {\ifarguments\or\or\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}\fi} + +\def\font_basics_set_mapped_fontsize#from% + {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname + \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 + \orelse\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr + \lastnamedcs + \else + \v_font_rscale_default + \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% + {\letcsname\??fontbodyknown#body\endcsname\empty} + +%D \macros +%D {definefontstyle,definefontsize,definefontalternative} +%D +%D When setting of switching the overall style we can use the short identifier like +%D rm and ss, but when defined we can also use more verbose names like roman or +%D sansserif. Such 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{\letcsname\??fontstyleknown #style\endcsname\empty} +\def\font_helpers_register_size #size{\letcsname\??fontsizeknown #size\endcsname\empty} +\def\font_helpers_register_alternative#alternative{\letcsname\??fontalternativeknown#alternative\endcsname\empty} + +\permanent\protected\def\definefontstyle[#commands]#spacer[#style]% style: rm ss tt ... + {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw) + \font_helpers_register_style{#style}% + \toksapp\t_font_style_commands{\m_font_style_command{#style}}% + \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}} + +\permanent\protected\def\definefontsize[#size]% + {\ifcsname\??fontsizeknown#size\endcsname \else + \font_helpers_register_size{#size}% + \toksapp\t_font_size_commands{\m_font_size_command{#size}}% + \fi + \font_helpers_check_fontname_combinations} + +\permanent\protected\def\definefontalternative[#alternative]% + {\ifcsname\??fontalternativeknown#alternative\endcsname \else + \font_helpers_register_alternative{#alternative}% + \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}% + \fi + \font_helpers_check_fontname_combinations} + +\protected\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb) + {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s} + +\def\font_helpers_check_fontname_combinations_s#style% + {\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 of +%D the formal font interface once defined. The size can be empty (so checking is +%D needed as \type {\bf} is already defined). +%D +%D The \type {\normal..} variants are available as extras for cases where the \type +%D {..} 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% + {} + +\def\font_basics_check_text_bodyfont_step#whatever#body% size can be empty (checking needed as \bf is already defined) + {\ifcsname#whatever\endcsname\else + \permanent\setugvalue{#whatever}{#body}% + \fi} + +\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined) + {\font_basics_check_text_bodyfont_step{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma + \font_basics_check_text_bodyfont_step{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla + \font_basics_check_text_bodyfont_step{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla + \font_basics_check_text_bodyfont_step{#style}{\font_helpers_set_current_font_style{#style}}% \rm + \font_basics_check_text_bodyfont_step{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl + \font_basics_check_text_bodyfont_step{#style\s!x }{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx + \font_basics_check_text_bodyfont_step{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx + \font_basics_check_text_bodyfont_step{#alternative\s!x }{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx + \font_basics_check_text_bodyfont_step{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx + \font_basics_check_text_bodyfont_step{#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) demands: +%D +%D \startitemize +%D \item We support wildcards like \type {sa *} which will adapt to the current +%D size. This is also the default specification. +%D \item We support named scales like \type {sa d}; beware: \type {x} and \type {xx} +%D are valid scales but they are not alway the same as the ones used in for +%D instance \type {\bfx} because there the sized come from the bodyfont +%D environment. In the future there maybe a switch that also honors the +%D environment in named scales. +%D \stopitemize +%D +%D Keep in mind that the smaller sizes are just for text super and subscripts while +%D larger sizes can be used in titles where for 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 + +\permanent\def\safontscale{\number\dimexpr\v_font_size_absolute\relax} +\permanent\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax} + +\mutable\let\somefontname\s!unknown +\mutable\let\somefontspec\s!unknown +\mutable\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 + +\mutable\let\relativefontid\minusone + +\aliased\let\c_font_feature_inheritance_fontnone \zerocount % none +\aliased\let\c_font_feature_inheritance_fontonly \plusone % fontonly +\aliased\let\c_font_feature_inheritance_classonly \plustwo % classonly +\aliased\let\c_font_feature_inheritance_fontfirst \plusthree % fontfirst +\aliased\let\c_font_feature_inheritance_classfirst\plusfour % classfirst + +\aliased\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 + +\protected\def\font_helpers_low_level_define#specification#csname% + {% we can now set more at the lua end + \glet\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 + \ifempty\fontclass\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 + \letcsname#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 + \expandafter\let\expandafter\f_font_body_scale\lastnamedcs + \setfalse\c_font_body_scale % ! + \orelse\ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname + \expandafter\let\expandafter\f_font_body_scale\lastnamedcs + \settrue\c_font_body_scale + \orelse\ifcsname\??fontenvironments\fontbody#fontsize\endcsname + \expandafter\let\expandafter\f_font_body_scale\lastnamedcs + \setfalse\c_font_body_scale % ! + \orelse\ifcsname\??fontenvironments\s!default#fontsize\endcsname + \expandafter\let\expandafter\f_font_body_scale\lastnamedcs + \settrue\c_font_body_scale + \orelse\ifcsname\??fontenvironments\fontclass\s!default\s!text\endcsname + \expandafter\let\expandafter\f_font_body_scale\lastnamedcs + \settrue\c_font_body_scale + \orelse\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} + +\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue + +\tracingfonts\plussix % + +%D When fontclasses are used, we define the font global, since namespaces are +%D used. Otherwise we parse the specs each time. + +\mutable\let\fontfile\s!unknown + +%D Relatively new: + +\installcorenamespace{fonts} +\installcorenamespace{fontslanguage} + +\installsetuponlycommandhandler \??fonts {fonts} + +\newconstant\c_fonts_auto_language + +\letvalue{\??fontslanguage\v!auto}\plusone % experimental +%letvalue{\??fontslanguage\v!yes }\plustwo % less efficient, for experiments + +\appendtoks + \c_fonts_auto_language + \ifcsname\??fontslanguage\fontsparameter\c!language\endcsname + \lastnamedcs + \else + \zerocount + \fi +\to \everysetupfonts + +\appendtoks + \ifcase\c_fonts_auto_language + % nothing + \or + \addfflanguage + % \or + % font + \fi +\to \everylanguage + +% \setupfonts +% [\c!language=\v!auto] + +%D \macros +%D {everyfont,everyfontswitch} + +\ifdefined\everyfont \else \newtoks\everyfont \fi +\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi + +\permanent\def\setfontcharacteristics{\the\everyfont} + +% \appendtoks +% \ifcase\c_fonts_auto_language +% % nothing +% \or +% % auto +% \or +% \addfflanguage +% \fi +% \to \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 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: + +\permanent\tolerant\protected\def\definefont[#1]#*[#2]#*[#3]% [name][spec][1.6 | line=10pt | setup_id] + {\ifparameter#3\or + \expandafter\font_basics_define_font_a + \else + \expandafter\font_basics_define_font_b + \fi[#1][#2][#3]} + +\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. + +\permanent\tolerant\protected\def\definefrozenfont[#name]#spacer[#specification]#spacer[#settings]% + {\ifparameter#name\or + \begingroup + \definefont[#name][#specification][#settings]% + \csname#name\endcsname + \glet\lastglobalrawfontcall\lastrawfontcall + \endgroup + \letcsname#name\endcsname\lastglobalrawfontcall + \fi} + +%D The instance namespace protection makes the switch local so that we can redefine a +%D logical name and/or change the size in between. + +% 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 + +\mutable\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} + +\protected\def\font_helpers_trigger#identifier% make a traced variant + {\edef\lastfontidentifier{#identifier}% + \ifcsname\v_font_identifier_class\endcsname + % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}% + \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 including the \type {a}||\type +%D {d} sizes. The next macro returns the current scaling factor. Take a look at +%D \type {cont-log.tex} for an example of its use. + +\installcorenamespace{fontenvironments} + +\permanent\def\currentfontbodysize % gets number (the normal sa 1 etc) + {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname + \lastnamedcs + \orelse\ifcsname\??fontenvironments\s!default\somefontsize\endcsname + \lastnamedcs + \else + \somefontsize + \fi} + +\permanent\def\currentfontbodyscale % gets character (x xx a etc) + {\csname\??fontenvironments + \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\orelse + \ifcsname\??fontenvironments \s!default\fontsize\endcsname \s!default\fontsize\orelse + \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse + \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else + \s!default \fi + \endcsname} + +\def\font_currentfontbodyscale % gets character (x xx a etc) + {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments \s!default\fontsize\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else + \csname\??fontenvironments \s!default \endcsname \fi} + +\permanent\def\currentfontscale % used in default definition + {\csname\??fontenvironments + \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\orelse + \ifcsname\??fontenvironments \s!default\xfontsize\endcsname \s!default\fontsize\orelse + \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \orelse + \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else + \s!default \fi + \endcsname} + +\def\font_currentfontscale % used in default definition + {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments \s!default\xfontsize\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments \s!default\s!text \endcsname\lastnamedcs\else + \csname\??fontenvironments \s!default \endcsname \fi} + +\setvalue{\??fontenvironments\s!default}{1} + +%D In the following macros we use \type {\currentxfontsize} to hold the current +%D x||size of the font. This enables us to support for instance \type {\sl} inside a +%D \type {\tx} switch. + +\newconstant\currentxfontsize + +\permanent\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi} + +%D Now we enter the area of font switching. The switching mechanism has to take care +%D of several situations, like: +%D +%D \startitemize[packed] +%D \item changing the overal document fonts (including margins, headers and footers) +%D \item changing local fonts (only the running text) +%D \item smaller and even more smaller alternatives (super- and subscripts) +%D \stopitemize +%D +%D \TEX\ offers a powerfull family mechanism for super- and subscripts in math mode. +%D In text mode however, we don't use families for the smaller alternatives, and +%D therefore have to take care of it otherwise. +%D +%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 the moment we stick +%D 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 settings apply. All +%D second parameters are specified in dimensions and tell us more about related +%D 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 get +%D 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 environment checks +%D local. This means that multiple local checks resulting in definitions are not +%D that efficient. 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 + +\permanent\def\bodyfontvariable#parameter% + {\csname\??fontenvironments + \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\orelse + \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse + \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \normalizedbodyfontsize#parameter\orelse + \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi + \endcsname} + +\def\font_bodyfontvariable#parameter% + {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi} + +\permanent\def\bodyfontsizevariable#size#parameter% + {\csname\??fontenvironments + \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\orelse + \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\orelse + \ifcsname\??fontenvironments #size#parameter\endcsname #size#parameter\orelse + \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi + \endcsname} + +\def\font_bodyfontsizevariable#size#parameter% + {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\fontclass #parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments #size#parameter\endcsname\lastnamedcs\orelse + \ifcsname\??fontenvironments\s!default #parameter\endcsname\lastnamedcs\fi} + +\permanent\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere + +\permanent\def\bodyfontdimension#class#size#parameter#body% + {\the\dimexpr + \ifcsname\??fontenvironments #class#size#parameter\endcsname \lastnamedcs \orelse + \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\orelse % factor + \ifcsname\??fontenvironments #size#parameter\endcsname \lastnamedcs \else + \lastnamedcs\dimexpr#body\relax\fi % factor + \relax} + +\installcorenamespace{fontenvironmentknown} + +\def\font_helpers_register_environment#class#body% + {\letcsname\??fontenvironmentknown#class#body\endcsname\empty} + +\newmacro\m_font_body +\newmacro\m_font_body_normalized + +\permanent\tolerant\protected\def\definebodyfontenvironment[#1]#*[#2]#*[#3]% todo + {\ifarguments + \expandafter\font_basics_define_body_font_environment_unset + \or + \expandafter\font_basics_define_body_font_environment_unset + \or + \expandafter\font_basics_define_body_font_environment_empty + \or + \expandafter\font_basics_define_body_font_environment_class + \fi[#1][#2][#3]} + +\aliased\let\setupbodyfontenvironment\definebodyfontenvironment + +%D First we handle the class specific case. Beware: you can change values before +%D a bodyfont is loaded but changing them afterwards can be sort of tricky as +%D values are not consulted afterwards. + +\permanent\def\processbodyfontenvironmentlist#1% no \protected as then we cannot use it in alignments (still?) + {\clf_processbodyfontsizes{\strippedcsname#1}} + +\permanent\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 settings +%D (just to be sure, as it's not really needed). + +\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]% + {\push_macro_fontclass + \let\fontclass\empty + \font_basics_define_body_font_environment_class[][#body][#settings]% + \pop_macro_fontclass} + +\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]% + {\push_macro_fontclass + \let\fontclass\empty + \font_basics_define_body_font_environment_class[][#body][]% + \pop_macro_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 + \orelse\ifproductionrun + \push_macro_fontclass + \edef\fontclass{#class}% + \font_helpers_register_environment{#class}{#normalizedbody}% + \settrue\c_font_defining_environment_state + \font_helpers_define_unknown_font{#normalizedbody}% current class + \setfalse\c_font_defining_environment_state + \pop_macro_fontclass + \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 setup is valid +%D too: +%D +%D \starttyping +%D \definebodyfontenvironment[24pt] +%D \stoptyping +%D +%D All parameters can be redefined when needed, so one doesnot have to stick to the +%D default ones. + +%D \macros +%D {definebodyfont} +%D +%D The next step in defining a bodyfont involves the actual font files, which can be +%D recognized by their extension \type {tfm}. Installing those file is often beyond +%D the 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 size(s), the style +%D group to which the definitions belong, and an alternative, as specified by the +%D \TEX\ (math) families, extended with~a, b~\unknown. +%D +%D We show two examples, that show all the alternative scaling options. The \type +%D {\tfa} alternatives can be extended with \type {\bfa}, \type {\slb}, etc. or even +%D \type {e} and higher alternatives. The magic scaled values are derived from plain +%D \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 once. The main +%D difference between these examples is that the Computer Modern Roman come in many +%D design sizes. This means that there we cannot define them in bulk using \type +%D {sa}. Instead of \type {rm} (roman) one can define \type {ss} (sans serif), \type +%D {tt} (teletype), \type {hw} (hand written), \type {cg} (calygraphic) and whatever +%D styles. +%D +%D The first argument may be a comma separated list. This, combined with +%D specifications using \type{sa} can save a lot of typing. Although all arguments +%D should be specified, we treat the second argument as optional. +%D +%D Defining a bodyfont involves two actions: defining the specific style related +%D alternatives, like \type {\rma}, \type {\bfa} and \type {\rmsla}, and storing the +%D definitions of their bodyfont size related fonts. The first step is bodyfont +%D independant but executed every time. This permits user definitions like \type +%D {\tfw} or \type {\bfq} for real large alternatives. +%D +%D If we move design size info to the lfg file (after all only lm has design sizes) +%D 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] + +\permanent\tolerant\protected\def\definebodyfont[#1]#*[#2]#*[#3]#*[#4]% + {\ifarguments + \or + \font_basics_define_body_font[#1][\s!rm][]% + \or + \font_basics_define_body_font[#1][\s!rm][#2]% + \or + \font_basics_define_body_font[#1][#2][#3]% + \or + \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}% + \fi} + +\protected\def\font_basics_define_body_font[#whatever]% + {\doifelsenumber{#whatever}\font_basics_define_body_font_body\font_basics_define_body_font_name[#whatever]} + +\protected\def\font_basics_define_body_font_class_given[#1][#2][#3]#4% + {\push_macro_fontclass + \doifelse{#4}\s!default + {\let\fontclass\empty} + {\def\fontclass{#4}}% + \definebodyfont[#1][#2][#3]% + \pop_macro_fontclass} + +\protected\def\font_basics_define_body_font_body[#body][#style][#specification]% + {\ifcondition\validassignment{#specification}% + \expandafter\font_basics_define_body_font_body_assignment + \else + \expandafter\font_basics_define_body_font_body_identifier + \fi + [#body][#style][#specification]}% + +\protected\def\font_basics_define_body_font_name[#name][#style][#specification]% + {\ifcondition\validassignment{#specification}% + \expandafter\font_basics_define_body_font_name_assignment + \else + \expandafter\font_basics_define_body_font_name_identifier + \fi + [#name][#style][#specification]}% + +\protected\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]% + {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}} + +\protected\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body% + {\normalizebodyfontsize\m_font_asked_body{#body}% + % normally we define quite a lot in advance, i.e global defs + \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! + \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}} + +\protected\def\font_basics_define_body_font_body_assignment_b#assignments#style% + {\edef\m_font_asked_style{#style}% + \processcommalist[#assignments]\font_basics_define_body_font_defs} + +\protected\def\font_basics_define_body_font_defs + {\ifempty\fontclass + \expandafter\font_basics_define_body_font_defs_nop + \else + \expandafter\font_basics_define_body_font_defs_yes + \fi} + +\protected\def\font_basics_define_body_font_defs_yes_normal#assignment% + {\ifx\m_font_asked_style\s!mm + \expandafter\font_basics_define_body_font_yes_mm + \else + \expandafter\font_basics_define_body_font_yes_xx + \fi[#assignment]} + +\protected\def\font_basics_define_body_font_defs_nop_normal#assignment% + {\ifx\m_font_asked_style\s!mm + \expandafter\font_basics_define_body_font_nop_mm + \else + \expandafter\font_basics_define_body_font_nop_xx + \fi[#assignment]} + +\protected\def\font_basics_define_body_font_defs_yes_traced#assignment% + {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% + \ifx\m_font_asked_style\s!mm + \expandafter\font_basics_define_body_font_yes_mm + \else + \expandafter\font_basics_define_body_font_yes_xx + \fi[#assignment]} + +\protected\def\font_basics_define_body_font_defs_nop_traced#assignment% + {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% + \ifx\m_font_asked_style\s!mm + \expandafter\font_basics_define_body_font_nop_mm + \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 + +%D We split into two characters (first part of spec) and the rest: the first two are +%D the style and the rest is a size, although in practice one will seldom define the +%D size directly. We might even drop that as it gives faster code. + +\protected\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local + {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi + \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined + \protected\edefcsname\??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}}}% + \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined + \protected\edefcsname\??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}}}% + \letcsname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined + \protected\edefcsname\??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}}}% + } + +\protected\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global + {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi + \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined + \protected\xdefcsname\??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}}}% + \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined + \protected\xdefcsname\??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}}}% + \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined + \protected\xdefcsname\??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. + +\protected\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local + {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi + \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined + % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined + % \letcsname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined + \protected\xdefcsname\??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}% + +\protected\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global + {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi + \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined + % \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined + % \gletcsname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined + \protected\xdefcsname\??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}% + +\protected\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]% + {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}} + +\protected\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body% + {\normalizebodyfontsize\m_font_asked_body{#body}% + \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! + \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}} + +\protected\def\font_basics_define_body_font_body_identifier_b#name#style% + {\edef\m_font_asked_style{#style}% + %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}% + \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking + +\protected\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]% + {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}} + +\protected\def\font_basics_define_body_font_name_assignment_a#name#assignments#style% + {%\writestatus\m!fonts{[#name:#style] => [#assignments]}% + \edefcsname\??fontdefinitions#name:#style\endcsname{\font_basics_define_body_font_default{#assignments}}} + +\protected\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]% + {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}} + +\protected\def\font_basics_define_body_font_name_identifier_a#name#identifier#style% + {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}% + \ifcsname\??fontdefinitions#name:#style\endcsname + \letcsname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname + \else + \defcsname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}% + \fi} + +%D The unknown: + +\newconditional\c_font_defining_unknown +\newconditional\c_font_defining_state + +\protected\def\font_helpers_define_unknown_font#body% one level only + {\font_helpers_register_fontbody{#body}% prevents loop, can go + \setfalse\c_font_defining_state + \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}% + \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 + \clf_registerunknownbodysize{#body}% + \fi + \setfalse\c_font_defining_state + \font_helpers_register_fontbody{#body}% + % needed ? + \ifconditional\c_font_defining_unknown + \else + \settrue\c_font_defining_unknown + \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}% + \setfalse\c_font_defining_unknown + \fi + \fi + \fi} + +\def\font_helpers_define_unknown_check_sizes#body#relativesize% + {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ? + \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}% + \settrue\c_font_defining_state + \fi} + +\def\font_helpers_define_unknown_check_definitions#body#style% + {\ifcsname\??fontdefinitions\s!default:#style\endcsname + \edef\m_font_asked_body{#body}% + \edef\m_font_asked_style{#style}% + \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 + \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname + \settrue\c_font_defining_state + \fi} + +\protected\def\font_basics_define_body_font_default#assignments% + {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here? + \ifcsname\m_font_asked_style\endcsname\else + \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}% + \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. + +\protected\def\font_basics_switch_points#body% + {\ifcsname\??fontbodyknown#body\endcsname \else + % we need to check the relative sizes for this body + \font_helpers_define_unknown_font{#body}% + \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} + +\protected\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 handle changes in size as +%D well as returning to the global 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}% + \ifempty\m_font_specification \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 + \ifempty\defaultfontclass + \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 + +\protected\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message% + {\edef\m_font_keyword{#keyword}% + \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname + \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}% + \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}% + \orelse\ifx\m_font_keyword\v!reset + \let\fontstyle\empty % new 31/7/2006 + \let\fontsize \empty + \orelse\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} + +\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later + {\let\fontstyle\s!rm} + +\protected\def\font_helpers_set_font_set_font_option_body#method#body#message% + {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls + \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else + \font_helpers_define_unknown_font\normalizedsetfont + \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 + +\permanent\def\registerfontclass#class% + {\letgvalue{\??fontclassyes#class}\v!yes} % global ? + +\permanent\def\setcurrentfontclass#class% + {\ifcsname\??fontclassyes#class\endcsname + \edef\fontclass{#class}% + \orelse\ifcsname\??fontclassnop#class\endcsname + % already tried + \else % too messy: \ifcase\currentgrouplevel % (unpredictable) + \trycurrentfontclass{#class}% + \fi} + +\ifdefined\trycurrentfontclass \else + + \protected\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.) + +\permanent\protected\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} + +\permanent\protected\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 + +\protected\def\font_helpers_set_current_font_style#style% + {\edef\fontstyle{#style}% + \font_typescripts_inherit_check\fontstyle + \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_xsize_alternative#xsize#alternative% + {\edef\fontface{#xsize}% + \edef\fontalternative{#alternative}% + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_alternative#alternative% + {\edef\fontalternative{#alternative}% + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_size#size% + {\edef\fontsize{#size}% + \font_helpers_check_big_math_synchronization % double? better in everymath? + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl + {\edef\fontstyle {#style}% + \edef\fontalternative{#alternative}% + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_style_size#style#size% \rma + {\edef\fontstyle{#style}% + \edef\fontsize {#size}% + \font_helpers_check_big_math_synchronization % double? better in everymath? + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla + {\edef\fontalternative{#alternative}% + \edef\fontsize {#size}% + \font_helpers_check_big_math_synchronization % double? better in everymath? + \font_helpers_synchronize_font} + +\protected\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla + {\edef\fontstyle {#style}% + \edef\fontalternative{#alternative}% + \edef\fontsize {#size}% + \font_helpers_check_big_math_synchronization % double? better in everymath? + \font_helpers_synchronize_font} + +\protected\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy + {\ifempty\fontclass + \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 +%D that often 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} + +\permanent\let\applyfontstrategies \font_helpers_check_strategy_a +\permanent\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 sizes is accomplished by +%D the next set of macros. When in math mode, the commands \type {\tx} and \type +%D {\txx} are just a switch to the script and double script styles, but in text mode +%D the values defined by the bodyfontenvironment are used. Here we also set \type +%D {\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_reset_x_fontsize + {\ifcase\currentxfontsize\else + \currentxfontsize\zerocount + % also \sx and \sxx ? + \enforced\let\tx \normaltx + \enforced\let\txx\normaltxx + \fi} + +\let\font_helpers_check_nested_x_fontsize\relax + +\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 + \enforced\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 + \enforced\let\tx\empty + \enforced\let\txx\empty} + +%D This alterative is not really needed, but for old time's sake we keep it there. +%D 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}, this macro is +%D redefined to be \type {\txx}. Therefore calls 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 takes a bit more +%D time. Keep in mind that the fontsize is represented by a character or empty. + +\installcorenamespace{fontscalex} +\installcorenamespace{fontscalexx} + +\newconditional\c_font_inherit_scale + +\def\font_scale_inherit#1% + {\begingroup + \scratchcounterone\fontid\font\relax + \currentxfontsize\plusone + \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}% + \scratchcountertwo\fontid\font\relax + \currentxfontsize\plustwo + \normalexpanded{\definedfont[\clf_specifiedfont\scratchcounterone\font_currentfontscale\relax]}% + \scratchcounterthree\fontid\font\relax + % parent -> x -> xx + % parent -> xx + \global\expandafter\chardef\csname\??fontscalex \number\scratchcounterone\endcsname\scratchcountertwo + \global\expandafter\chardef\csname\??fontscalexx\number\scratchcounterone\endcsname\scratchcounterthree + \global\expandafter\chardef\csname\??fontscalex \number\scratchcountertwo\endcsname\scratchcounterthree + \global\expandafter\chardef\csname\??fontscalexx\number\scratchcountertwo\endcsname\scratchcounterthree + \endgroup + \setfontid\csname#1\number\fontid\font\endcsname} + +\def\font_scale_inherit_x + {\ifcsname\??fontscalex\number\fontid\font\endcsname + \setfontid\lastnamedcs + \else + \font_scale_inherit\??fontscalex + \fi + \ifskipfontcharacteristics + \setfontcharacteristics + \the\everyfontswitch + \fi} + +\def\font_scale_inherit_xx + {\ifcsname\??fontscalexx\number\fontid\font\endcsname + \setfontid\lastnamedcs + \else + \font_scale_inherit\??fontscalexx + \fi + \ifskipfontcharacteristics + \setfontcharacteristics + \the\everyfontswitch + \fi} + +\def\font_scale_defined_x + {\let\fontface\!!plusfour + \let\fontalternative\fontalternative + \font_helpers_synchronize_font} + +\def\font_scale_defined_xx + {\let\fontface\!!plusfive + \let\fontalternative\fontalternative + \font_helpers_synchronize_font} + +% to freeze or not ... + +\permanent\protected\def\tx + {\currentxfontsize\plusone + \ifmmode + \scriptstyle + \orelse\ifconditional\c_font_inherit_scale + \font_scale_inherit_x + \else + \font_scale_defined_x + \fi + \enforced\let\tx\txx} + +\permanent\protected\def\txx + {\currentxfontsize\plustwo + \ifmmode + \scriptscriptstyle + \orelse\ifconditional\c_font_inherit_scale + \font_scale_inherit_xx + \else + \font_scale_defined_xx + \fi + \enforced\let\tx \empty + \enforced\let\txx\empty} + +\permanent\protected\def\sx + {\currentxfontsize\plusone + \ifmmode + \scriptstyle + \else + \font_scale_inherit_x + \fi + \enforced\let\tx\txx + \enforced\let\sx\sxx} + +\permanent\protected\def\sxx + {\currentxfontsize\plustwo + \ifmmode + \scriptscriptstyle + \else + \font_scale_inherit_xx + \fi + \enforced\let\tx \empty + \enforced\let\txx\empty + \enforced\let\sx \empty + \enforced\let\sxx\empty} + +\permanent\protected\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me +\permanent\protected\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me + +\aliased\let\normaltx \tx +\aliased\let\normaltxx\txx + +\aliased\let\normalsx \sx +\aliased\let\normalsxx\sxx + +%D When asking for a complete font switch, for instance from 10 to 12~points, the +%D next macro does the job. First we normalize the size, next we define the current +%D range of text, script and scriptscript sizes, then we set the text fonts and the +%D math families and finally we activate the default typeface and also set the font +%D specific parameters assigned to \type {\everybodyfont}. + +\permanent\def\textface {\currentbodyfontdimension\s!text } +\permanent\def\scriptface {\currentbodyfontdimension\s!script } +\permanent\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript} +\permanent\def\xtextface {\currentbodyfontdimension\s!x } +\permanent\def\xxtextface {\currentbodyfontdimension\s!xx } + +\installcorenamespace{fontbodyfaces} + +\protected\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 + \enforced\noexpand\edef\noexpand\textface {\currentbodyfontdimension\s!text }% + \enforced\noexpand\edef\noexpand\scriptface {\currentbodyfontdimension\s!script }% + \enforced\noexpand\edef\noexpand\scriptscriptface{\currentbodyfontdimension\s!scriptscript}% + \enforced\noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }% + \enforced\noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }% + }% + \gletcsname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces} + +\permanent\def\currentbodyfontdimension#parameter% there can be factors here + {\the\dimexpr + \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname + \lastnamedcs + \orelse\ifcsname\??fontenvironments\fontclass\s!default#parameter\endcsname + \lastnamedcs + \dimexpr\normalizedbodyfontsize\relax + \orelse\ifcsname\??fontenvironments\normalizedbodyfontsize#parameter\endcsname + \lastnamedcs + \else + \csname\??fontenvironments\s!default#parameter\endcsname + \dimexpr\normalizedbodyfontsize\relax + \fi + \relax} + +%D \macros +%D {setupbodyfont,switchtobodyfont} +%D +%D The next two macros are user ones. With \type {\setupbodyfont} one can set the +%D document bodyfont size, font family, style and/or options defined in files, for +%D example: +%D +%D \starttyping +%D \setupbodyfont[modern,12pt,roman] +%D \stoptyping +%D +%D This command affects the document as a whole: text, headers and footers. The +%D 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 all kind of keywords into +%D account. + +\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi +\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi + +% \newtoks \everysetupbodyfont +% \newtoks \everyswitchtobodyfont + +\permanent\protected\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}} + +\protected\def\font_basics_switchtobodyfont#specification% + {\edef\m_font_step{\font_bodyfontvariable{#specification}}% + \ifempty\m_font_step + \font_helpers_set_font\zerocount{#specification}% + \else + \font_helpers_switch_bodyfont_step % so we have a fast [small] switch + \fi + \the\everybodyfont + \the\everyswitchtobodyfont} + +\permanent\protected\def\switchtobodyfont[#specification]% could become an ifx + {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}} + +\permanent\protected\def\usebodyfontparameter#1% + {\edef\m_font_bodyfont_asked{#1\c!bodyfont}% + \ifempty\m_font_bodyfont_asked\else + \font_basics_switchtobodyfont\m_font_bodyfont_asked + \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 switching and will be +%D optimized. + +\permanent\protected\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 + +\permanent\protected\def\usebodyfont[#1]% + {\ifempty\fontclass + \setupbodyfont[#1]% + \else + \switchtobodyfont[#1]% + \fullrestoreglobalbodyfont + \fi} + +\permanent\protected\def\showbodyfontstate + {\dontleavehmode + \start + \infofont + [fontclass: \fontclass,\space + fontbody: \fontbody ,\space + fontface: \fontface ,\space + fontsize: \fontsize ]% + \stop} + +%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 \NC u \NC unicode descriptions \NC u:dog \NC \NR +%D \NC a \NC all (also descriptions) \NC a:rewind \NC \NR +%D \stoptabulate +%D +%D This is an expandable command! + +\permanent\protected\def\fontchar #character{\clf_fontchar{#character}} +\permanent\protected\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax} +\permanent \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef) + +%D The next auxilliary macro is an alternative to \type {\fontname}. + +\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 + +\permanent\protected\def\switchstyleonly + {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg} + +\def\font_basics_switch_style_only_arg#name% stupid version + {\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} to switch to a specific +%D bodyfontsize. Just for the sake of 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. + +\permanent\tolerant\protected\def\definebodyfontswitch[#command]#spacer[#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 the \type {small} as +%D well as the \type {big} alternative, related to this main size, using \type +%D {\switchtobodyfont[small]}. The three alternatives can be activated by the next +%D three 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} + +\permanent\protected\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont} +\permanent\protected\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont} + +\permanent\protected\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. Pagenumbers, +%D footers, headers etc. however must be typeset in the main bodyfont and style of +%D the document. Returning to the global state can be done with the next macro: +%D +%D This macro has to be called when entering the pagebody handling routine as well +%D as the footnote insert routine. Users can access this feature |<|for instance +%D when one wants to typeset tables and alike in the main bodyfont and style while +%D the running text is temporary set to a smaller one|>| by saying \type +%D {\switchtobodyfont [global]}. + +\let\globalfontstyle\s!rm + +\permanent\protected\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} + +\permanent\protected\def\partialrestoreglobalbodyfont + {\let\fontsize\defaultfontsize + \let\fontbody\defaultfontbody + \let\fontface\defaultfontface + \currentxfontsize\zerocount + \redoconvertfont + \tf + \the\everybodyfont % indeed needed + \the\everyglobalbodyfont % indeed needed + \saveinterlinespace} + +\permanent\protected\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 system is +%D 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} + +\permanent\protected\def\predefinefont[#1]#*[#2]% global ! + {\setugvalue{#1}{\font_basics_predefine{#1}{#2}}} + +\permanent\protected\def\predefinedfont[#1]% global ! + {\ifcsname\??predefinedfont#1\endcsname + \lastnamedcs + \else + \font_basics_predefined{#1}% + \fi} + +\protected\def\font_basics_predefine#1#2% + {\font_basics_defined_font_yes[#2]% + \gletcsname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname} + +\protected\def\font_basics_predefined#1% + {\font_basics_predefine{\??predefinedfont#1}{#1}} + +%D Handy helper: + +\permanent\protected\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} + +%D Ugly helper: + +\permanent\protected\def\saverunningstyleandcolor + {\enforced\permanent\protected\edef\restorerunningstyleandcolor + {\setfontid \number\fontid\font + \c_attr_colormodel \the\c_attr_colormodel + \c_attr_color \the\c_attr_color + \c_attr_transparency\the\c_attr_transparency + \relax}} + +\let\restorerunningstyleandcolor\relax + +%D Handy for defining additional glyphs: + +% todo: public implementors + +\let\getprivateglyphslot\clf_getprivateglyphslot % kind of private macro + +\let\getprivatechar \clf_getprivatechar % gives back a utf ! +\let\getprivatemathchar \clf_getprivatemathchar % gives back a utf ! +\let\getprivateslot \clf_getprivateslot % companion to fonts.helpers.addprivate + +% \protected\def\getprivatemathchar#1% +% {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup} + +\permanent\protected\def\privatechar % the text variant gets expanded to utf + {\ifmmode + \expandafter\getprivatemathchar + \else + \expandafter\getprivatechar + \fi} + +%D Some fonts can have color specifiers: +%D +%D \starttyping +%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes] +%D \definefontsynonym[emoji][seguiemj*seguiemj-cl] +%D +%D \definecolor[emoji-red] [r=.4] +%D \definecolor[emoji-gray][s=1,t=.5,a=1] +%D +%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad +%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] % okay +%D +%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r] +%D +%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt] +%D +%D \startTEXpage[offset=10pt] +%D \MyEmojiR\resolvedemoji{triangular ruler} +%D \stopTEXpage +%D \stoptyping + +\permanent\tolerant\protected\def\definefontcolorpalette[#1]#*[#2]% + {\clf_definefontcolorpalette{#1}{#2}} + +%D \macros +%D {addfontpath} +%D +%D A way to add a path at runtime (no need to generate database): + +\permanent\protected\def\usefontpath[#1]% + {\clf_addfontpath{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx new file mode 100644 index 000000000..4a0c1627f --- /dev/null +++ b/tex/context/base/mkxl/font-lib.mklx @@ -0,0 +1,170 @@ +%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}{} +\registerctxluafile{font-log}{} +\registerctxluafile{font-con}{} +\registerctxluafile{font-cft}{} +\registerctxluafile{font-enc}{} +\registerctxluafile{font-agl}{} % if needed we can comment this and delay loading +\registerctxluafile{font-cid}{} % cid maps +\registerctxluafile{font-map}{optimize} + +% helpers + +\registerctxluafile{font-otr}{optimize} % opentype fontloader +\registerctxluafile{font-web}{} % opentype fontloader +\registerctxluafile{font-cff}{optimize} % quadratic outlines +\registerctxluafile{font-ttf}{optimize} % cubic outlines +\registerctxluafile{font-dsp}{optimize} % ... for this one +\registerctxluafile{font-hsh}{} % hashes used by context +\registerctxluafile{font-vfc}{} +\registerctxluafile{font-prv}{} % needs hashes +\registerctxluafile{font-nod}{optimize} +\registerctxluafile{font-oti}{} % otf initialization +\registerctxluafile{font-ott}{} % otf tables (first) +\registerctxluafile{font-otl}{} +\registerctxluafile{font-oto}{} +\registerctxluafile{font-otj}{optimize} +\registerctxluafile{font-oup}{} +\registerctxluafile{font-ota}{} +\registerctxluafile{font-ots}{optimize} +\registerctxluafile{font-otd}{optimize} +\registerctxluafile{font-otc}{} +\registerctxluafile{font-oth}{} +\registerctxluafile{font-osd}{} +%registerctxluafile{font-osm}{} +\registerctxluafile{font-ogr}{autosuffix} + +% we use otf code for type one + +\registerctxluafile{font-onr}{optimize} +\registerctxluafile{font-one}{optimize} +\registerctxluafile{font-afk}{} + +% tfm + +\registerctxluafile{font-tpk}{optimize} +\registerctxluafile{font-tfm}{} + +% name database + +\registerctxluafile{font-syn}{} +\registerctxluafile{font-trt}{} + +% shapes + +\registerctxluafile{font-shp}{} + +% so far + +\registerctxluafile{font-pat}{} % patchers + +\registerctxluafile{node-fnt}{} % here + +\registerctxluafile{font-mps}{} % outline fun + +\registerctxluafile{font-lua}{} + +\registerctxluafile{font-vir}{} +\registerctxluafile{font-enh}{} + +\registerctxluafile{good-ini}{} +\registerctxluafile{good-gen}{} +\registerctxluafile{good-ctx}{} +\registerctxluafile{good-mth}{} + +\registerctxluafile{font-def}{} +\registerctxluafile{font-ctx}{} % after def as it overloads + +% extensions, order matters + +\registerctxluafile{font-imp-ligatures}{} +\registerctxluafile{font-imp-tex}{} +\registerctxluafile{font-imp-reorder}{} +\registerctxluafile{font-imp-properties}{} +\registerctxluafile{font-imp-unicode}{} +\registerctxluafile{font-imp-math}{} +\registerctxluafile{font-imp-notused}{} +\registerctxluafile{font-imp-effects}{} +\registerctxluafile{font-imp-quality}{} +\registerctxluafile{font-imp-italics}{} +\registerctxluafile{font-imp-dimensions}{} +\registerctxluafile{font-imp-spacekerns}{} +\registerctxluafile{font-imp-tweaks}{} +\registerctxluafile{font-imp-combining}{} + +\doifelsefileexists{font-imp-scripts.lua} { + \registerctxluafile{font-imp-scripts}{} +} { + % not yet, lmtx feature +} + +\registerctxluafile{font-imp-tracing}{} % comes last! + +\registerctxluafile{font-fbk}{} + +\registerctxluafile{font-aux}{} + +\registerctxluafile{font-lig}{} % only for experiments so try to avoid it + +%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 + +%D We can also move the lookups to the fonts.namespace (of commands) one can also +%D directly use the clf calls when speed is needed. + +% todo: public implementors: + +\permanent \def\dolookupfontbyspec #1{\clf_fontlookupinitialize{#1}} +\permanent \def\dolookupnoffound {\clf_fontlookupnoffound} +\permanent \def\dolookupgetkeyofindex#1#2{\clf_fontlookupgetkeyofindex{#1}\numexpr#2\relax} +\permanent \def\dolookupgetkey #1{\clf_fontlookupgetkey{#1}} +\permanent \def\cleanfontname #1{\clf_cleanfontname{#1}} +\permanent\protected\def\setfontofid #1{\clf_setfontofid\numexpr#1\relax} + +% this is an ugly hack needed for postponed inclusion stuff ... don't try +% to understand this ... these are kind of old mkiv solutions + +\permanent\protected\def\typethreefont#1{\setfontid#1\relax} +\permanent\protected\def\typethreechar#1{\char#1\hskip-\fontcharwd\font#1\relax} +\permanent\protected\def\typethreelast#1{\char#1\relax} +\permanent\protected\def\typethreecode#1{\pdfliteral direct {#1}} + +\newtoks\typethreetoks +\let \typethreemacro\empty + +\typethreetoks {% + \setbox\zerocount\hpack{\typethreemacro}% + \setbox\zerocount\hpack{\raise\dp\zerocount\box\zerocount}% +} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-mat.mklx b/tex/context/base/mkxl/font-mat.mklx new file mode 100644 index 000000000..39e799ec3 --- /dev/null +++ b/tex/context/base/mkxl/font-mat.mklx @@ -0,0 +1,489 @@ +%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 The order 3 2 1 of siuze matters: needed for math-fbk relative size storage! + +%D \macros +%D {textonly} +%D +%D Traditionally math has a big impact on font definitions, mainly because we need +%D to define alphabet variants using families and fonts. This means that one can +%D easily get 10 fonts loaded per math size. In \MKIV\ we use a different approach: +%D one family which has either a virtual font made of traditional fonts, or an +%D \OPENTYPE\ font that has it all. +%D +%D We currently use only one math family but in the future we might consider using a +%D second one for bold math. For the moment we keep the \MKII\ method of using a +%D token register for definitions but we already dropped the text and symbols ones +%D 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 + +\protected\def\font_helpers_synchronize_math % math stuff in mmode + {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi} + +\permanent\protected\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this + +%D The main math font definer. We have removed some optimized code simply because we +%D now always have a fontclass. We could check for fontclass being default or empty +%D and save a few tests but it does not help us when no math is defined. +%D +%D Because we want to keep mr=.. and mb=... settings (read: not break downward +%D compatibility by enforcing mrlr etc) we need a bit more code that optimal. + +% todo: \c_font_fam_mr + +\aliased\let\c_font_fam_mr \zerocount % math regular +\aliased\let\c_font_fam_mr_lr\plusone % math regular l2r +\aliased\let\c_font_fam_mr_rl\plustwo % math regular r2l + +\aliased\let\c_font_fam_mb \plusthree % math bold +\aliased\let\c_font_fam_mb_lr\plusfour % math bold l2r +\aliased\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 + +% \frozen ... + +\immutable\def\mathtextsuffix {-text} +\immutable\def\mathscriptsuffix {-script} +\immutable\def\mathscriptscriptsuffix{-scriptscript} + +%D Beware: truefontname also does a fallback on defaultfontclass so there +%D can be some interference here, which is why we use a different method +%D for bold. + +\def\font_helpers_set_math_family_a + {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size + \lastnamedcs \orelse + \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size + \lastnamedcs \else + \font_helpers_set_math_family_b + \fi} + +\def\font_helpers_set_math_family_b + {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size + \lastnamedcs \orelse + \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size + \lastnamedcs \else + \font_helpers_set_math_family_c + \fi} + +\def\font_helpers_set_math_family_c + {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size + \lastnamedcs \orelse + \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size + \lastnamedcs \else + \settrue \c_font_auto_size + \fi} + +%def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi} +\mutable\let\mathsizesuffix\empty + +\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 + % enabling is needed when we have fallbacks which spoils the families + \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree + \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % defines + \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % enables + \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo + \font_helpers_set_math_family_a\scriptfont #mrtag\font % defines + \font_helpers_set_math_family_a\scriptfont #mrtag\font % enables + \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone + \font_helpers_set_math_family_a\textfont #mrtag\font % defines + \font_helpers_set_math_family_a\textfont #mrtag\font % enables + \let\mathsizesuffix\empty \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 + \lastnamedcs #font#mbfam\font \orelse + \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size + \lastnamedcs #font#mbfam\font \else + #font#mbfam#font#mrfam% + \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\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree + \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% defines + \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% enables + \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo + \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% defines + \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% enables + \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone + \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines + \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables + \let\mathsizesuffix\empty \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 we have a problem +%D with setting the global bodyfont size in the 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 +%D little in restoring global states and, what's more important, we get rid of large +%D math parameter 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 + \orelse\ifnum\fontid\textfont#fam=\fontid\v_font_math_one\else + \font_helpers_preset_math_family_indeed_changed#fam#familytag% + \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 + +%D It would be nice if characters could be defined in a neutral way (say fam 255) +%D and be mapped to a real family during noad list construction. However, this +%D changes tex in critical places so for the moment we simulate this using +%D manipulation. +%D +%D For tracing purposes we use three families but in l2r mode 1 and 2 are copies of +%D 0 while in rl mode 0 is a copy of 1. There is no real overhead involved in this. +%D 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_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 + \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr + \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr + \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr} + +\appendtoks + \ifconditional\c_font_bidirectional_mathstrategy + \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_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 + \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl + \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl + \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl} + +\def\font_helpers_apply_complete_bold_mathstrategy + {\ifconditional\c_font_complete_bold_mathstrategy + \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 + +\protected\def\font_helpers_synchronize_math_family_mr + {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy + \ifconditional\c_math_right_to_left + \plustwo + \else + \plusone + \fi + \else + \zerocount + \fi} + +\protected\def\font_helpers_synchronize_math_family_mb + {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy + \ifconditional\c_math_right_to_left + \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi + \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} + +\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 + +%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 + +%D Bold is somewhat special as we might want both full-bold-math mixed regular-math, +%D as well as automatic adaption to outer bold (in titles and inline text bold) so +%D we will need explicit switches as well as an automatic one. (We will use lucida +%D as an example.) + +\ifdefined\mathdefault \else \let\mathdefault\relax \fi + +\newconditional\c_math_bold + +\protected\def\mr % math regular + {\ifmmode + \font_helpers_synchronize_math_family_mr + \else + \font_helpers_set_current_font_alternative\s!mr + \fi + \mathdefault + \setfalse\c_math_bold} + +\protected\def\mb % math bold + {\ifmmode + \font_helpers_synchronize_math_family_mb + \else + \font_helpers_set_current_font_alternative\s!mb + \fi + \mathdefault + \settrue\c_math_bold} + +\appendtoks + \font_helpers_synchronize_math_family % auto bold +\to \everymathematics + +\appendtoks + \ifconditional\c_math_bold\mb\fi +\to \everymathematics + +%D \macros +%D {bigmath,nobigmath} +%D +%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 + +\protected\def\nobigmath {\synchronizebigmathflag\zerocount} +\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} +\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} + +\let\bigmathfontsize\empty + +\protected\def\synchronizebigmath + {\ifx\bigmathfontsize\fontsize + % already in sync + \else + \let\bigmathfontsize\fontsize + \font_helpers_synchronize_math + \fi} + +\protected\def\font_helpers_check_big_math_synchronization + {\ifcase\synchronizebigmathflag + % never + \or + \ifmmode \synchronizebigmath \fi + \or + \synchronizebigmath + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-ogr.lmt b/tex/context/base/mkxl/font-ogr.lmt new file mode 100644 index 000000000..e57e88ed6 --- /dev/null +++ b/tex/context/base/mkxl/font-ogr.lmt @@ -0,0 +1,673 @@ +if not modules then modules = { } end modules ['font-ogr'] = { + 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" +} + +-- Here we deal with graphic variants and for now also color support ends up here +-- but that might change. It's lmtx only code. + +if not context then + return +elseif CONTEXTLMTXMODE == 0 then + return +end + +local tostring, tonumber, next, type = tostring, tonumber, next, type +local round, max, mod, div = math.round, math.max, math.mod, math.div +local find = string.find +local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash +local utfbyte = utf.byte +local formatters = string.formatters +local settings_to_hash_strict, settings_to_array = utilities.parsers.settings_to_hash_strict, utilities.parsers.settings_to_array + +local otf = fonts.handlers.otf +local otfregister = otf.features.register +otf.svgenabled = true +otf.pngenabled = true + +-- Just to remind me ... rewritten around the time this was posted on YT which +-- was also around the 2019 ctx meeting: +-- +-- Gavin Harrison - "Threatening War" by The Pineapple Thief +-- https://www.youtube.com/watch?v=ENF9wth4kwM + +-- todo: svg color plugin +-- todo: get rid of double cm in svg (tricky as also elsewhere) +-- todo: png offsets (depth) +-- todo: maybe collapse indices so that we have less files (harder to debug) +-- todo: manage (read: assign) font id's in lua so we know in advance + +-- what here and what in backend ... + +do + + -- This is a prelude to something better but I'm still experimenting. + + local dropins = { } + fonts.dropins = dropins + local droppedin = 0 + local identifiers = fonts.hashes.identifiers + + function dropins.nextid() + droppedin = droppedin - 1 + return droppedin + end + + -- todo: pass specification table instead + + function dropins.provide(method,t_tfmdata,indexdata,...) + local droppedin = dropins.nextid() + local t_characters = t_tfmdata.characters + local t_descriptions = t_tfmdata.descriptions + local t_properties = t_tfmdata.properties + local d_tfmdata = setmetatableindex({ },t_tfmdata) + local d_properties = setmetatableindex({ },t_properties) + d_tfmdata.properties = d_properties + local d_characters = { } -- setmetatableindex({ },t_characters) -- hm, index vs unicode + local d_descriptions = { } -- setmetatableindex({ },t_descriptions) -- hm, index vs unicode + d_tfmdata.characters = d_characters + d_tfmdata.descriptions = d_descriptions + d_tfmdata.parentdata = t_tfmdata -- so we can access it if needed + d_properties.instance = - droppedin -- will become an extra element in the hash + t_properties.virtualized = true + identifiers[droppedin] = d_tfmdata + local fonts = t_tfmdata.fonts or { } + t_tfmdata.fonts = fonts + d_properties.format = "type3" + d_properties.method = method + d_properties.indexdata = { indexdata, ... } -- can take quite some memory + local slot = #fonts + 1 + fonts[slot] = { id = droppedin } + return slot, droppedin, d_tfmdata, d_properties + end + + -- todo: delay this, in which case we can be leaner and meaner + + function dropins.clone(method,tfmdata,shapes,...) -- by index + if method and shapes then + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local droppedin, tfmdrop, dropchars, dropdescs, colrshapes + local idx = 255 + local slot = 0 + for k, v in next, characters do + local index = v.index + if index then + local description = descriptions[k] + if description then + local shape = shapes[index] + if shape then + if idx >= 255 then + idx = 1 + colrshapes = setmetatableindex({ },shapes) + slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) + dropchars = tfmdrop.characters + dropdescs = tfmdrop.descriptions + else + idx = idx + 1 + end + colrshapes[idx] = shape -- so not: description + -- todo: prepend + v.commands = { { "slot", slot, idx } } + -- hack to prevent that type 3 also gets 'use' flags .. todo + local c = { commands = false, index = idx, dropin = tfmdrop } + local d = { } -- { index = idx, dropin = tfmdrop } + setmetatableindex(c,v) + setmetatableindex(d,description) + dropchars[idx] = c + dropdescs[idx] = d -- not needed + end + end + end + end + else + -- error + end + end + + function dropins.swap(method,tfmdata,shapes,...) -- by unicode + if method and shapes then + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local droppedin, tfmdrop, dropchars, dropdescs, colrshapes + local idx = 255 + local slot = 0 + -- we can have a variant where shaped are by unicode and not by index + for k, v in next, characters do + local description = descriptions[k] + if description then + local shape = shapes[k] + if shape then + if idx >= 255 then + idx = 1 + colrshapes = setmetatableindex({ },shapes) + slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) + dropchars = tfmdrop.characters + dropdescs = tfmdrop.descriptions + else + idx = idx + 1 + end + colrshapes[idx] = shape -- so not: description + -- todo: prepend + v.commands = { { "slot", slot, idx } } + -- hack to prevent that type 3 also gets 'use' flags .. todo + local c = { commands = false, index = idx, dropin = tfmdrop } + local d = { } -- index = idx, dropin = tfmdrop } + setmetatableindex(c,v) + setmetatableindex(d,description) + dropchars[idx] = c + dropdescs[idx] = d -- not needed + end + end + end + else + -- error + end + end + +end + +do -- this will move to its own module + + local dropins = fonts.dropins + + local shapes = setmetatableindex(function(t,k) + local v = { + glyphs = { }, + parameters = { + units = 1000 + }, + } + t[k] = v + return v + end) + + function dropins.registerglyphs(parameters) + local category = parameters.name + local target = shapes[category].parameters + for k, v in next, parameters do + if k ~= "glyphs" then + target[k] = v + end + end + end + + function dropins.registerglyph(parameters) + local category = parameters.category + local unicode = parameters.unicode + local private = parameters.private + local unichar = parameters.unichar + if private then + unicode = fonts.helpers.newprivateslot(private) + elseif type(unichar) == "string" then + unicode = utfbyte(unichar) + else + local unitype = type(unicode) + if unitype == "string" then + local uninumber = tonumber(unicode) + if uninumber then + unicode = round(uninumber) + else + unicode = utfbyte(unicode) + end + elseif unitype == "number" then + unicode = round(unicode) + end + end + if unicode then + parameters.unicode = unicode + -- print(category,unicode) + shapes[category].glyphs[unicode] = parameters + else + -- error + end + end + + -- local function hascolorspec(t) + -- if (t.color or "") ~= "" then + -- return true + -- elseif (t.fillcolor or "") ~= "" then + -- return true + -- elseif (t.drawcolor or "") ~= "" then + -- return true + -- elseif (t.linecolor or "") ~= "" then + -- return true + -- else + -- return false + -- end + -- end + + local function hascolorspec(t) + for k, v in next, t do + if find(k,"color") then + return true + end + end + return false + end + + local function initializemps(tfmdata,kind,value) + if value then + local specification = settings_to_hash_strict(value) + if not specification or not next(specification) then + specification = { category = value } + end + -- todo: multiple categories but then maybe also different + -- clones because of the units .. for now we assume the same + -- units + local category = specification.category + if category and category ~= "" then + local categories = settings_to_array(category) + local usedshapes = nil + local index = 0 + local spread = tonumber(specification.spread or 0) + local hascolor = hascolorspec(specification) + specification.spread = spread -- now a number + for i=1,#categories do + local category = categories[i] + local mpsshapes = shapes[category] + if mpsshapes then + local properties = tfmdata.properties + local parameters = tfmdata.parameters + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local mpsparameters = mpsshapes.parameters + local units = mpsparameters.units or 1000 + local defaultwidth = mpsparameters.width or 0 + local defaultheight = mpsparameters.height or 0 + local defaultdepth = mpsparameters.depth or 0 + local usecolor = mpsparameters.usecolor + local spread = spread * units + local defaultcode = mpsparameters.code or "" + local scale = parameters.size / units + if hascolor then + -- the graphic has color + usecolor = false + else + -- do whatever is specified + end + usedshapes = usedshapes or { + instance = "simplefun", + units = units, + usecolor = usecolor, + specification = specification, + shapes = mpsshapes, + } + -- todo: deal with extensibles and more properties + for unicode, shape in sortedhash(mpsshapes.glyphs) do + -- local oldc = characters[unicode] + -- if oldc then + index = index + 1 -- todo: somehow we end up with 2 as first entry after 0 + local wd = shape.width or defaultwidth + local ht = shape.height or defaultheight + local dp = shape.depth or defaultdepth + local newc = { + index = index, -- into usedshapes + width = scale * (wd + spread), + height = scale * ht, + depth = scale * dp, + unicode = unicode, + } + -- + characters [unicode] = newc + descriptions[unicode] = newc + -- + usedshapes[unicode] = shape.code or defaultcode + -- end + end + end + end + if usedshapes then + -- todo: different font when units and usecolor changes, maybe move into loop + -- above + dropins.swap("mps",tfmdata,usedshapes) + end + end + end + end + + -- This kicks in quite late, after features have been checked. So if needed + -- substitutions need to be defined with force. + + otfregister { + name = "metapost", + description = "metapost glyphs", + manipulators = { + base = initializemps, + node = initializemps, + } + } + +end + +-- This sits here for historcal reasons so for now we keep it here. + +local startactualtext = nil +local stopactualtext = nil + +function otf.getactualtext(s) + if not startactualtext then + startactualtext = backends.codeinjections.startunicodetoactualtextdirect + stopactualtext = backends.codeinjections.stopunicodetoactualtextdirect + end + return startactualtext(s), stopactualtext() +end + +-- This is also somewhat specific. + +local sharedpalettes do + + sharedpalettes = { } + + local colors = attributes.list[attributes.private('color')] or { } + local transparencies = attributes.list[attributes.private('transparency')] or { } + + function otf.registerpalette(name,values) + sharedpalettes[name] = values + local color = lpdf.color + local transparency = lpdf.transparency + local register = colors.register + for i=1,#values do + local v = values[i] + if v == "textcolor" then + values[i] = false + else + local c = nil + local t = nil + if type(v) == "table" then + c = register(name,"rgb", + max(round((v.r or 0)*255),255)/255, + max(round((v.g or 0)*255),255)/255, + max(round((v.b or 0)*255),255)/255 + ) + else + c = colors[v] + t = transparencies[v] + end + if c and t then + values[i] = color(1,c) .. " " .. transparency(t) + elseif c then + values[i] = color(1,c) + elseif t then + values[i] = color(1,t) + end + end + end + end + +end + +local initializeoverlay do + + -- we should use the proper interface instead but for now: + + local colors = attributes.colors + local rgbtocmyk = colors.rgbtocmyk + + local f_cmyk = formatters["%.3N %.3f %.3N %.3N k"] + local f_rgb = formatters["%.3N %.3f %.3N rg"] + local f_gray = formatters["%.3N g"] + + local function convert(t,k) + local v = { } + local m = colors.model + for i=1,#k do + local p = k[i] + local r, g, b = p[1]/255, p[2]/255, p[3]/255 + if r == g and g == b then + p = f_gray(r) + elseif m == "cmyk" then + p = f_cmyk(rgbtocmyk(r,g,b)) + else + p = f_rgb(r,g,b) + end + v[i] = p + end + t[k] = v + return v + end + + initializeoverlay = function(tfmdata,kind,value) -- we really need the id ... todo + if value then + local resources = tfmdata.resources + local palettes = resources.colorpalettes + if palettes then + -- + local converted = resources.converted + if not converted then + converted = setmetatableindex(convert) + resources.converted = converted + end + local colorvalues = sharedpalettes[value] + local default = false -- so the text color (bad for icon overloads) + if colorvalues then + default = colorvalues[#colorvalues] + else + colorvalues = converted[palettes[tonumber(value) or 1] or palettes[1]] or { } + end + local classes = #colorvalues + if classes == 0 then + return + end + -- + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local droppedin, tfmdrop, dropchars, dropdescs, colrshapes + local idx = 255 + local slot = 0 + -- + -- maybe delay in which case we have less fonts as we can be sparse + -- + for k, v in next, characters do + local index = v.index + if index then + local description = descriptions[k] + if description then + local colorlist = description.colors + if colorlist then + if idx >= 255 then + idx = 1 + colrshapes = { } + slot, droppedin, tfmdrop = fonts.dropins.provide("color",tfmdata,colrshapes,colorvalues) + dropchars = tfmdrop.characters + dropdescs = tfmdrop.descriptions + else + idx = idx + 1 + end + -- + colrshapes[idx] = description + -- todo: use extender + local u = { "use", 0 } + for i=1,#colorlist do + u[i+2] = colorlist[i].slot + end + v.commands = { u, { "slot", slot, idx } } + -- hack to prevent that type 3 also gets 'use' flags .. todo + local c = { commands = false, index = idx, dropin = tfmdata } + local d = { } -- index = idx, dropin = tfmdrop + setmetatableindex(c,v) + setmetatableindex(d,description) + dropchars[idx] = c + dropdescs[idx] = d -- not needed + end + end + end + end + return true + end + end + end + + fonts.handlers.otf.features.register { + name = "colr", + description = "color glyphs", + manipulators = { + base = initializeoverlay, + node = initializeoverlay, + } + } + +end + +local initializesvg do + + local report_svg = logs.reporter("fonts","svg") + + local cached = true -- maybe always false (after i've optimized the lot) + + directives.register("fonts.svg.cached", function(v) cached = v end) + + initializesvg = function(tfmdata,kind,value) -- hm, always value + if value then + local properties = tfmdata.properties + local svg = properties.svg + local hash = svg and svg.hash + local timestamp = svg and svg.timestamp + if not hash then + return + end + local shapes = nil + local method = nil + local enforce = attributes.colors.model == "cmyk" + if cached and not enforce then + -- we need a different hash than for mkiv, so we append: + local pdfhash = hash .. "-svg" + local pdffile = containers.read(otf.pdfcache,pdfhash) + local pdfshapes = pdffile and pdffile.pdfshapes + local pdftarget = file.join(otf.pdfcache.writable,file.addsuffix(pdfhash,"pdf")) + if not pdfshapes or pdffile.timestamp ~= timestamp or not next(pdfshapes) or not lfs.isfile(pdftarget) then + local svgfile = containers.read(otf.svgcache,hash) + local svgshapes = svgfile and svgfile.svgshapes + pdfshapes = svgshapes and metapost.svgshapestopdf(svgshapes,pdftarget,report_svg,tfmdata.parameters.units) or { } + -- look at ocl: we should store scale and x and y + containers.write(otf.pdfcache, pdfhash, { + pdfshapes = pdfshapes, + timestamp = timestamp, + }) + end + shapes = pdfshapes + method = "pdf" + else + local mpsfile = containers.read(otf.mpscache,hash) + local mpsshapes = mpsfile and mpsfile.mpsshapes + if not mpsshapes or mpsfile.timestamp ~= timestamp or not next(mpsshapes) then + local svgfile = containers.read(otf.svgcache,hash) + local svgshapes = svgfile and svgfile.svgshapes + -- still suboptimal + mpsshapes = svgshapes and metapost.svgshapestomp(svgshapes,report_svg,tfmdata.parameters.units) or { } + if enforce then + -- cheap conversion, no black component generation + mpsshapes.preamble = "interim svgforcecmyk := 1;" + end + containers.write(otf.mpscache, hash, { + mpsshapes = mpsshapes, + timestamp = timestamp, + }) + end + shapes = mpsshapes + method = "mps" + end + if shapes then + shapes.fixdepth = value == "fixdepth" + fonts.dropins.clone(method,tfmdata,shapes) + end + return true + end + end + + otfregister { + name = "svg", + description = "svg glyphs", + manipulators = { + base = initializesvg, + node = initializesvg, + } + } + +end + +local initializepng do + + -- If this is really critical we can also use a pdf file as cache but I don't expect + -- png fonts to remain used. + + local colors = attributes.colors + + local report_png = logs.reporter("fonts","png conversion") + + initializepng = function(tfmdata,kind,value) -- hm, always value + if value then + local properties = tfmdata.properties + local png = properties.png + local hash = png and png.hash + local timestamp = png and png.timestamp + if not hash then + return + end + local pngfile = containers.read(otf.pngcache,hash) + local pngshapes = pngfile and pngfile.pngshapes + if pngshapes then + if colors.model == "cmyk" then + pngshapes.enforcecmyk = true + end + fonts.dropins.clone("png",tfmdata,pngshapes) + end + return true + end + end + + otfregister { + name = "sbix", + description = "sbix glyphs", + manipulators = { + base = initializepng, + node = initializepng, + } + } + + otfregister { + name = "cblc", + description = "cblc glyphs", + manipulators = { + base = initializepng, + node = initializepng, + } + } + +end + +do + + -- I need to check jpeg and such but will do that when I run into + -- it. + + local function initializecolor(tfmdata,kind,value) + if value == "auto" then + return + initializeoverlay(tfmdata,kind,value) or + initializesvg(tfmdata,kind,value) or + initializepng(tfmdata,kind,value) + elseif value == "overlay" then + return initializeoverlay(tfmdata,kind,value) + elseif value == "svg" then + return initializesvg(tfmdata,kind,value) + elseif value == "png" or value == "bitmap" then + return initializepng(tfmdata,kind,value) + else + -- forget about it + end + end + + otfregister { + name = "color", + description = "color glyphs", + manipulators = { + base = initializecolor, + node = initializecolor, + } + } + +end diff --git a/tex/context/base/mkxl/font-pre.mkxl b/tex/context/base/mkxl/font-pre.mkxl new file mode 100644 index 000000000..8468fbbd7 --- /dev/null +++ b/tex/context/base/mkxl/font-pre.mkxl @@ -0,0 +1,999 @@ +%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 + +% frac : with numr dnom +% +% vkrn valt vert vrt2 vpal : when vertical +% +% rtlm rtla : in r2l runs +% ltrm ltra : in l2r runs +% +% rvrn : variable fonts +% +% rtbd lfbd : opbd +% +% rkrf rphf vatu vjmo tjmo rclt psts pstf ljmo haln +% pres pref nukt +% abvs abvm blwm blws cjct blwf akhn (indic) +% half +% abvf cfar (khmer) +% +% ccmp locl calt clig liga rlig +% +% mkmk mark kern (palt pwid) curs (by choice but some fonts need it) +% +% init medi isol fina (unicode) +% fin3 fin2 med2 : syriac +% +% cpsp : percentage spacing (todo) +% +% dtls flac :math + +\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, +% ccmp=yes, % maybe too +% locl=yes, % maybe too +% calt=yes, % maybe too +% clig=yes, % maybe too +% rlig=yes, % maybe too + tlig=yes, + trep=yes] % texligatures=yes,texquotes=yes + +\definefontfeature + [original] % a clone of default so we can revert + [default] + +\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, +% ccmp=yes, +% locl=yes, +% calt=yes, +% clig=yes, +% rlig=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, + % fin2=yes,fin3=yes,med2=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, + % fin2=yes,fin3=yes,med2=yes, + mark=yes,mkmk=yes,kern=yes,curs=yes, + rlig=yes,calt=yes] + +\definefontfeature + [arabic] + [semitic-complete] + [script=arab] + +\definefontfeature + [syriac] + [arabic] + [fin2=yes,fin3=yes,med2=yes] + +\definefontfeature + [reordercombining] + [reordercombining=yes] + +\definefontfeature + [hebrew] + [semitic-complete] + [script=hebr, + reordercombining=yes] % seems to work best with reasonable fonts + +\definefontfeature + [simplearabic] + [semitic-simple] + [script=arab] + +\definefontfeature + [simplehebrew] + [semitic-simple] + [script=hebr] + +% indic + +\definefontfeature + [indic-common] + [mode=node, + language=dflt, + % localized + locl=yes, + % positioning + kern=yes, + dist=yes, + % above/below base marks + abvm=yes, + blwm=yes, + % basic shaping + nukt=yes, + akhn=yes, + rphf=yes, + % presentation + pres=yes, + abvs=yes, + blws=yes, + psts=yes, + haln=yes, + calt=yes] + +\definefontfeature + [devanagari-one] + [indic-common] + [script=deva, + % basic shaping + rkrf=yes, + blwf=yes, + half=yes, + vatu=yes, + cjct=yes] + +\definefontfeature + [bengali-one] + [indic-common] + [script=beng, + % basic shaping + blwf=yes, + half=yes, + pstf=yes, + vatu=yes, + cjct=yes, + % presentation + init=yes] + +\definefontfeature + [gujarati-one] + [indic-common] + [script=gujr, + % basic shaping + rkrf=yes, + blwf=yes, + half=yes, + vatu=yes, + cjct=yes] + +\definefontfeature + [gurmukhi-one] + [indic-common] + [script=guru, + % basic shaping + blwf=yes, + half=yes, + pstf=yes, + vatu=yes, + cjct=yes] + +\definefontfeature + [kannada-one] + [indic-common] + [script=knda, + % basic shaping + pref=yes, + blwf=yes, + half=yes, + pstf=yes, + cjct=yes] + +\definefontfeature + [malayalam-one] + [indic-common] + [script=mlym, + % basic shaping + pref=yes, + blwf=yes, + half=yes, + pstf=yes, + cjct=yes] + +\definefontfeature + [oriya-one] + [indic-common] + [script=orya, + % basic shaping + blwf=yes, + pstf=yes, + cjct=yes] + +\definefontfeature + [tamil-one] + [indic-common] + [script=taml, + % basic shaping + pref=yes, + half=yes] + +\definefontfeature + [telugu-one] + [indic-common] + [script=telu, + % basic shaping + pref=yes, + blwf=yes, + half=yes, + pstf=yes, + cjct=yes] + +\definefontfeature [devanagari-two] [devanagari-one] [script=dev2] +\definefontfeature [bengali-two] [bengali-one] [script=bng2] +\definefontfeature [gujarati-two] [gujarati-one] [script=gjr2] +\definefontfeature [gurmukhi-two] [gurmukhi-one] [script=gur2] +\definefontfeature [kannada-two] [kannada-one] [script=knd2] +\definefontfeature [malayalam-two] [malayalam-one] [script=mlm2] +\definefontfeature [oriya-two] [oriya-one] [script=ory2] +\definefontfeature [tamil-two] [tamil-one] [script=tml2] +\definefontfeature [telugu-two] [telugu-one] [script=tel2] + +% mongolian + +\definefontfeature + [mongolian] + [default] + [script=mong, + init=yes,medi=yes,fina=yes,isol=yes, + rlig=yes,rclt=yes,calt=yes, + %dlig=yes,cswh=yes, % optional + mset] + +% tibetan + +\definefontfeature + [tibetan] + [always] + [script=tibt, + language=dflt, + locl=yes, + ccmp=yes, + abvs=yes, + blws=yes, + calt=yes, + liga=yes, + abvm=yes, + blwm=yes] + +% cjk + +\definefontfeature + [jamoforms] + [ljmo=yes, + tjmo=yes, + vjmo=yes] + +% \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, + kern=yes, + % liga=yes, % makes no sense + % tlig=yes, % makes no sense + % trep=yes, % makes no sense + mathnolimitsmode={0,800}, % this looks okay on the average font + mathalternates=yes, + mathitalics=yes, % we pass them + mathdimensions=all, + % mathgaps=yes, + language=dflt, + script=math] + +\ifdefined\mathnolimitsmode + \mathnolimitsmode\plusone % font driven (only opentype) +\fi + +\ifdefined\mathitalicsmode + \mathitalicsmode\plusone % simple noads become zero + % \mathitalicsmode\plustwo % idem but inner is kept (for testing) +\fi + +% \adaptfontfeature[*math*][mathnolimitsmode=1000] % only subscript + +\definefontfeature + [mathematics-l2r] + [mathematics] + [] + +% \definefontfeature +% [mathematics-r2l] +% [mathematics] +% [language=ara, +% rtlm=yes, +% locl=yes] + +\definefontfeature + [mathematics-r2l] + [mathematics] + [rtlm=yes, + locl=yes] + +\definefontfeature[virtualmath] [mathematics] % downward compatibility +\definefontfeature[virtualmath-l2r] [mathematics-l2r] % downward compatibility +\definefontfeature[virtualmath-r2l] [mathematics-r2l] % downward compatibility + +\definefontfeature[math-text] [mathematics] [ssty=no] +\definefontfeature[math-script] [mathematics] [ssty=1,mathsize=yes] +\definefontfeature[math-scriptscript] [mathematics] [ssty=2,mathsize=yes] + +\definefontfeature[math-text-l2r] [mathematics-l2r] [ssty=no] +\definefontfeature[math-script-l2r] [mathematics-l2r] [ssty=1,mathsize=yes] +\definefontfeature[math-scriptscript-l2r] [mathematics-l2r] [ssty=2,mathsize=yes] + +\definefontfeature[math-text-r2l] [mathematics-r2l] [ssty=no] +\definefontfeature[math-script-r2l] [mathematics-r2l] [ssty=1,mathsize=yes] +\definefontfeature[math-scriptscript-r2l] [mathematics-r2l] [ssty=2,mathsize=yes] + +\definefontfeature[math-nostack-text] [math-text] [nostackmath=yes] +\definefontfeature[math-nostack-script] [math-script] [nostackmath=yes] +\definefontfeature[math-nostack-scriptscript][math-scriptscript][nostackmath=yes] + +% \definefontfeature[mathtext] [math-text] +% \definefontfeature[mathscript] [math-script] +% \definefontfeature[mathscriptscript] [math-scriptscript] + +\definefontfeature + [missing] + [missing=yes] + +%D Nice to have too: + +\definefontfeature + [quality] + [expansion=quality, + protrusion=quality] + +\definefontfeature + [fullprotrusion] + [protrusion=pure] + +\definefontfeature + [slanted] + [slant=.2] + +% \definefontfeature +% [boldened] +% [extend=1.2] + +%D Neat: + +% By eye: +% +% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.125,extend=1.025,squeeze=0.99250}] +% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.250,extend=1.050,squeeze=0.98750}] +% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.375,extend=1.075,squeeze=0.98125}] +% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.500,extend=1.100,squeeze=0.97500}] +% +% By calculation: +% +% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.02500,ddelta=0.02500,vshift=0.02500,extend=1.050,squeeze=0.99500}] +% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.05625,ddelta=0.05625,vshift=0.05625,extend=1.075,squeeze=0.99250}] +% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.10000,ddelta=0.10000,vshift=0.10000,extend=1.100,squeeze=0.99000}] +% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.22500,ddelta=0.22500,vshift=0.22500,extend=1.150,squeeze=0.98500}] +% +% So we can do this: + +\definefontfeature[boldened-10][effect={width=0.10,auto=yes}] +\definefontfeature[boldened-15][effect={width=0.15,auto=yes}] +\definefontfeature[boldened-20][effect={width=0.20,auto=yes}] +\definefontfeature[boldened-25][effect={width=0.25,auto=yes}] +\definefontfeature[boldened-30][effect={width=0.30,auto=yes}] + +\definefontfeature + [boldened] + [boldened-30] + +%D Emoji etc: + +\definefontfeature[bandw:overlay][ccmp=yes,dist=yes] +\definefontfeature[color:overlay][ccmp=yes,dist=yes,colr=yes] +%definefontfeature[bandw:svg] [ccmp=yes,dist=yes] +\definefontfeature[color:svg] [ccmp=yes,dist=yes,svg=yes] +%definefontfeature[bandw:bitmap] [ccmp=yes,dist=yes,sbix=yes] +\definefontfeature[color:bitmap] [ccmp=yes,dist=yes,sbix=yes] % also cblc + +% Plus an automatic one: + +\definefontfeature[color] [ccmp=yes,dist=yes,color=auto] + +%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[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[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] [] + +\definealternativestyle [typeface] [\typeface] [] % no translation here (quite basic) +\definealternativestyle [boldface] [\boldface] [] +\definealternativestyle [slantedface] [\slantedface] [] +\definealternativestyle [italicface] [\italicface] [] +\definealternativestyle [swapface] [\swapface] [] + +\definealternativestyle [emphasize] [\em] [\em] % new + +% 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 different. We also provide +%D 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] +\definefontfeature[f:inferiors][subs=yes] +\definefontfeature[f:fractions][frac=yes] +\definefontfeature[f:kern] [kern=yes] +\definefontfeature[f:kerns] [kern=yes] + +\definealternativestyle [\v!smallcaps] [\setsmallcaps] [\setsmallcaps] +\definealternativestyle [\v!oldstyle] [\setoldstyle ] [\setoldstyle ] +\definealternativestyle [\v!fractions] [\setfractions\resetbreakpoints] [\setfractions\resetbreakpoints] + +\permanent\protected\def\setsmallcaps{\doaddfeature{f:smallcaps}} +\permanent\protected\def\setoldstyle {\doaddfeature{f:oldstyle}} +\permanent\protected\def\settabular {\doaddfeature{f:tabular}} +\permanent\protected\def\setsuperiors{\doaddfeature{f:superiors}} +\permanent\protected\def\setfractions{\doaddfeature{f:fractions}} + +% \permanent\protected\def\frc#1#2% +% {\dontleavehmode +% \begingroup +% \addff{frac}% +% \resetbreakpoints +% #1/#2% +% \endgroup} + +%D \macros +%D {uppercasing, lowercasing} + +\definefontfeature[lowercasing][lowercasing=yes] +\definefontfeature[uppercasing][uppercasing=yes] + +\permanent\protected\def\uppercasing{\addff{uppercasing}} +\permanent\protected\def\lowercasing{\addff{lowercasing}} + +%D \macros +%D {tinyfont} +%D +%D By default we load the Computer Modern Roman fonts (but not yet at this moment) +%D and activate the 12pt roman bodyfont. Sans serif and teletype are also available +%D and can be called for by \type {\ss} and \type {\tt}. Loading takes place +%D elsewhere. For tracing purposes we define: + +\definefont[tinyfont][file:dejavusansmono at 1ex] + +%D \macros +%D {infofont} +%D +%D The second situation occurs when we enable the info mode, and put all kind of +%D status information in the margin. We don't want huge switches to the main +%D bodyfont and style, so here too we use a direct method. + +\pushoverloadmode + +\let\infofont \relax +\let\infofontbold \relax +\let\smallinfofont \relax +\let\smallinfofontbold\relax + +\definefont[infofont] [file:dejavusansmono*none at 6pt] +\definefont[infofontbold] [file:dejavusansmono-bold*none at 6pt] +\definefont[smallinfofont] [file:dejavusansmono*none at 3pt] +\definefont[smallinfofontbold][file:dejavusansmono-bold*none at 3pt] + +%D Optimization (later we overload in math). Also needed in order to get \type {\ss} +%D properly defined. + +\permanent\protected\def\normaltf{\let\fontalternative\s!tf\font_helpers_synchronize_font} +\permanent\protected\def\normalbf{\let\fontalternative\s!bf\font_helpers_synchronize_font} +\permanent\protected\def\normalit{\let\fontalternative\s!it\font_helpers_synchronize_font} +\permanent\protected\def\normalsl{\let\fontalternative\s!sl\font_helpers_synchronize_font} +\permanent\protected\def\normalbi{\let\fontalternative\s!bi\font_helpers_synchronize_font} +\permanent\protected\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 + +\permanent\protected\def\normalrm{\font_helpers_set_current_font_style{\s!rm}} +\permanent\protected\def\normalss{\font_helpers_set_current_font_style{\s!ss}} +\permanent\protected\def\normaltt{\font_helpers_set_current_font_style{\s!tt}} + +\let\rm\normalrm +\let\ss\normalss +\let\tt\normaltt + +\popoverloadmode + +\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/tex/context/base/mkxl/font-sel.mklx b/tex/context/base/mkxl/font-sel.mklx new file mode 100644 index 000000000..6c9ab3d7e --- /dev/null +++ b/tex/context/base/mkxl/font-sel.mklx @@ -0,0 +1,276 @@ +%D \module +%D [ file=font-sel, +%D version=2016.08.28, +%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}{} + +\unprotect + +\installcorenamespace {selectfont} +\installsimplecommandhandler \??selectfont {selectfont} + +\protected\def\selectfont_register[#style][#settings]% + {\begingroup + \edef\currentselectfont{\expandnamespacevalue\??fontshortstyle{#style}\s!rm}% + \checkselectfontparent + \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 + \font_helpers_process_alternative_list\clf_registerfontalternative + \setexpandedselectfontparameter\c!style{\expandnamespaceparameter\??fontshortstyle\selectfontparameter\c!style\s!rm}% + \xdef\selectfont_index{\clf_registerfontfamily + metadata {% + typeface {\selectfontparameter\c!label}% + style {\selectfontparameter\c!style}% + family {\selectfontparameter\c!name}% + } + options {% + designsize {\selectfontparameter\s!designsize}% + rscale {\selectfontparameter\s!rscale}% + goodies {\selectfontparameter\c!goodies}% + extras {\selectfontparameter\c!extras}% + features {\selectfontparameter\c!features}% + preset {\selectfontparameter\c!preset}% + range {\selectfontparameter\c!range}% fallback only + offset {\selectfontparameter\c!offset}% fallback only + check {\selectfontparameter\c!check}% fallback only + force {\selectfontparameter\c!force}% fallback only + } + userdata {% + \luaexpanded{#settings}% + }}% + \endgroup} + +%D \macros +%D {definefontfamilypreset} + +\installcorenamespace {selectfontpreset} + +\permanent\tolerant\protected\def\definefontfamilypreset[#name]#spacer[#settings]% + {\setvalue{\??selectfontpreset#name}{\setupcurrentselectfont[#settings]}% + \clf_definefontfamilypreset{#name}{\luaexpanded{#settings}}} + +\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] + [\c!range={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 {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 mandatory 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] [rscale=1.1] +%D +%D \definefontfamily [office] [serif] [Times New Roman] +%D \definefontfamily [office] [sans] [Arial] [rscale=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] [rscale=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{designsize} 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][designsize=auto] +%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 + +% tf = … | * … | name:… | name:* … | file:… | file:* … | style:medium + +\permanent\tolerant\protected\def\definefontfamily[#typeface]#spacer[#style]#spacer[#family]#spacer[#settings]% + {\doifelseassignment{#settings} + {\selectfont_register[#style][\c!label={#typeface},\c!style={#style},\c!name={#family},#settings]} + {\selectfont_register[#style][\c!label={#typeface},\c!style={#style},\c!name={#family},\c!preset={#settings}]}% + \clf_definefontfamily\selectfont_index\relax} + +\permanent\tolerant\def\definefallbackfamily[#typeface]#spacer[#style]#spacer[#family]#spacer[#settings]% + {\doifelseassignment{#settings} + {\selectfont_register[#style][\c!label={#typeface},\c!style={#style},\c!name={#family},#settings]} + {\selectfont_register[#style][\c!label={#typeface},\c!style={#style},\c!name={#family},\c!preset={#settings}]}% + \clf_definefallbackfamily\selectfont_index\relax} + +\permanent\tolerant\protected\def\setupfontfamily[#style]#spacer[#settings]% + {\ifparameter#settings\or + \edef\currentselectfont{\expandnamespacevalue\??fontshortstyle{#style}\s!rm}% + \setupcurrentselectfont[#settings]% + \else + \let\currentselectfont\empty + \setupcurrentselectfont[#style]% + \fi} + +\setupselectfont + [ \c!features=\s!default, + \s!designsize=\s!default, + \s!rscale=\selectfontparameter\c!scale, + \c!scale=1] + +\protect diff --git a/tex/context/base/mkxl/font-set.mklx b/tex/context/base/mkxl/font-set.mklx new file mode 100644 index 000000000..03dc8bb32 --- /dev/null +++ b/tex/context/base/mkxl/font-set.mklx @@ -0,0 +1,159 @@ +%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 prefer to +%D predefine at least the Computer Modern Roman fonts. However, loading all those +%D fonts at definition time would take both time and space. But even worse, once +%D fonts are loaded into memory, their encoding vector is fixed, which is a handicap +%D when we want to distribute the compact \type {fmt} files. So what we want to do +%D is defining fonts in a way that postpones the loading. We accomplish this by only +%D loading the fonts when we switch to another bodyfont size. Among the other +%D alternatives, such as loading the font at the moment of activation and redefining +%D the activation 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 scheme. When at format +%D generation time we load the default font file, the one that defines the Computer +%D Modern Fonts, we don't want the fonts metrics to end up in the format file, so we +%D temporary prohibit loading. This means that at runtime we have to load the +%D default bodyfont size just before 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 +% \glet\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]} + +\protected\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} + +\protected\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}}} + +\protected\def\font_preloads_second_stage + {\writestatus\m!fonts{preloading latin modern fonts (second stage)}% + \font_preload_default_fonts} + +\protected\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 + \push_macro_fontstyle + \ifcsname\??fontclass\fontclass\s!mm\s!features\endcsname \else + \font_preload_default_fonts_mm + \fi + \ifcsname\??fontclass\fontclass\s!tt\s!features\endcsname \else + \font_preload_default_fonts_tt + \fi + \pop_macro_fontstyle + \font_preloads_reset_checked % reset third, mm and tt + \setupbodyfont[\fontstyle]% + \fi} + +\protected\def\font_preloads_fourth_stage + {\begingroup + %ifzeropt\fontcharwd\font\number`!\relax + \setbox\scratchbox\hpack{\tf 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 + +\protected\def\font_preloads_at_every_job {\font_preloads_first_stage } +\protected\def\font_preloads_at_start_text{\font_preloads_second_stage} +\protected\def\font_preloads_at_stop_text {\font_preloads_fourth_stage} +\protected\def\font_preloads_at_definition{\font_preloads_third_stage + \glet\font_preloads_at_definition\relax} + +% \protected\def\checkpreloadedbodyfont % no \let here +% {\font_preloads_at_start_text} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-sol.mklx b/tex/context/base/mkxl/font-sol.mklx new file mode 100644 index 000000000..8f3d3d712 --- /dev/null +++ b/tex/context/base/mkxl/font-sol.mklx @@ -0,0 +1,131 @@ +%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}{} + +\unprotect + +\definesystemattribute[splitter][public] + +\installcorenamespace{fontsolution} + +\installcommandhandler \??fontsolution {fontsolution} \??fontsolution + +\aliased\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 + +\permanent\protected\def\setfontsolution[#solution]% just one + {\edef\currentfontsolution{#solution}% + \clf_setfontsolution + {\currentfontsolution}% + {% + method {\fontsolutionparameter\c!method}% + criterium {\fontsolutionparameter\c!criterium}% + % randomseed {\fontsolutionparameter\c!random}% + }% + \relax} + +\let\currentfontsolution\empty + +\permanent\protected\def\resetfontsolution % resets all + {\clf_resetfontsolution + \let\currentfontsolution\empty} + +\permanent\protected\def\startfontsolution % [#1] + {\pushmacro\currentfontsolution + \setfontsolution} + +\permanent\protected\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/tex/context/base/mkxl/font-sty.mklx b/tex/context/base/mkxl/font-sty.mklx new file mode 100644 index 000000000..9444232ba --- /dev/null +++ b/tex/context/base/mkxl/font-sty.mklx @@ -0,0 +1,441 @@ +%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 parameterized commands and +%D one of these parameters will concern the font to use. To suit consistent use of +%D fonts we here implement a mechanism for defining the keywords that present a +%D 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 second command takes +%D care of headings and alike. Consider 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 \type {\tfd} does not look +%D that well, so therefore we leave the second argument of \type +%D {\definealternativestyle} empty. When we capatalize characters using the pseudo +%D small cap command \type {\cap}, we want this to take effect in both text and +%D headings, which is accomplished by assigning both arguments. + +\installcorenamespace{alternativestyles} % settings +\installcorenamespace{alternativestyle} % instances + +\installsetuponlycommandhandler \??alternativestyles {alternativestyles} + +\setnewconstant \c_font_current_alternative_style_index \plusone + +\permanent\tolerant\protected\def\definealternativestyle[#commands]#spacer[#variantone]#spacer[#varianttwo]% + {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}} + +% \let\definestyle\definealternativestyle % later redefined + +\newconstant\c_fonts_basics_alternative_style_method + +% maybe permanent + +\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command% + {\setuvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}% + \ifcsname#command\endcsname + % no redefinition + \orelse\ifnum\c_fonts_basics_alternative_style_method=\plusone + \ifparameter#command\or + \permanent\setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}% + \else + \permanent\setuvalue{#command}{\triggergroupedcommand{#variantone}}% + \fi + \else + \permanent\setuvalue{#command}{\triggergroupedcommand{#variantone}}% + \fi} + +\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} + +\permanent\def\applyalternativestyle#name% public .. expandable? frozen? + {\begincsname\??alternativestyle#name\endcsname} + +\appendtoks + \doifelse{\alternativestylesparameter\c!method}\v!auto + {\c_fonts_basics_alternative_style_method\plusone}% + {\c_fonts_basics_alternative_style_method\zerocount}% +\to \everysetupalternativestyles + +%D Maybe too generic, but probably ok is the following. (Maybe one day we will use a +%D dedicated grouped command for styles.) + +% \appendtoks +% \let\groupedcommand\thirdofthreearguments +% \to \everysimplifycommands + +%D This command also defines the keyword as command. This means that the example +%D definition of \type {bold} we gave before, results in a command \type {\bold} +%D 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} because this would +%D result in an endless recursive call. Therefore we check on the existance of both +%D the command and the substitution. The latter is needed because for instance \type +%D {\type} is an entirely diferent command. That command handles verbatim, while the +%D style command would just switch to teletype font. This is just an example of a +%D tricky naming coincidence. +%D +%D \macros +%D {doconvertfont,noconvertfont, +%D dontconvertfont,redoconvertfont} +%D +%D After having defined such keywords, we can call for them by using +%D +%D \starttyping +%D \doconvertfont{keyword}{text} +%D \stoptyping +%D +%D We deliberately pass an argument. This enables us to assign converters that +%D handle one argument, like \type {\cap}. +%D +%D By default the first specification is used to set the style, exept when we say +%D \type {\dontconvertfont}, after which the second specification is used. We can +%D also directly call for \type {\noconvertfont}. In nested calls, we can restore +%D the conversion by saying \type {\redoconvertfont}. +%D +%D These commands are not grouped! Grouping is most probably done by the calling +%D macro's and would lead to unnecessary overhead. + +\let\m_current_convert_font \empty +\let\m_current_convert_font_dt\empty + +\permanent\protected\def\doconvertfont#specification% takes second argument / this command is obsolete + {\edef\m_current_convert_font{#specification}% + \ifempty\m_current_convert_font + %\expandafter\firstofoneargument + \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\??alternativestyle\m_current_convert_font_dt\endcsname + \expandafter\lastnamedcs + \orelse\ifcsname\m_current_convert_font_dt\endcsname + \expandafter\lastnamedcs + \else + \expandafter\m_current_convert_font + \fi} + +%D Low level switches (downward compatible, but we keep them as one can use them in +%D 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 + +\permanent\protected\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage +\permanent\protected\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage + +%D The new one: + +\setfalse\fontattributeisset + +\let\currentstyleparameter \empty % these might become private (possible conflict with defines) +\let\currentdetokenizedstyleparameter\empty % these might become private (possible conflict with defines) + +\permanent\protected\def\dousestyleparameter#value% + {\edef\currentstyleparameter{#value}% + \ifempty\currentstyleparameter\else + \expandafter\dousecurrentstyleparameter + \fi} + +\permanent\protected\def\dousestylehashparameter#hash#parameter% + {\ifcsname#hash#parameter\endcsname + \expandafter\dousestyleparameter\lastnamedcs + \fi} + +\permanent\protected\def\dousecurrentstyleparameter % empty check outside here + {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% + \settrue\fontattributeisset % reset is done elsewhere + \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname + \lastnamedcs + \orelse\ifcsname\currentdetokenizedstyleparameter\endcsname + \lastnamedcs + \else + \currentstyleparameter + \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} +\installcorenamespace{stylehack} + +\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 + \frozen\instance\setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}% + \frozen\instance\setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}% + \frozen\instance\setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here + \fi +\to \everydefinestyle + +\protected\def\font_styles_apply_start#name% + {\begingroup + \font_styles_use_defined{#name}} + +\protected\def\font_styles_apply_stop + {\endgroup} + +\protected\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup + {\bgroup + \def\g_style{\font_styles_use_defined{#name}}% + \afterassignment\g_style + \let\nexttoken} + +\protected\def\font_styles_use_defined#name% + {\edef\currentstyle{#name}% + \usestylestyleandcolor\c!style\c!color} + +\protected\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} + +\protected\def\style[#name]% as this is can be a switch we use groupedcommand % frozen? + {\csname\??styleargument + \ifcsname\??stylecheck#name\endcsname + 2% defined as style + \orelse\ifcsname\??stylehack#name\endcsname + 4% defined as command + \orelse\ifcsname#name\endcsname + 1% defined as command + \else + 3% specification + \fi + \endcsname{#name}} + +\setvalue{\??styleargument1}#name% + {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname} + +\setvalue{\??styleargument2}#name% + {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}} + +\setvalue{\??styleargument3}#specification% + {\doifelseassignment{#specification}\font_styles_assignment\font_styles_direct{#specification}} + +\setvalue{\??styleargument4}#name% + {\expandafter\triggergroupedcommandcs\begincsname\??stylehack#name\endcsname} + +\setvalue{\??stylehack\s!math}% dirty trick + {\groupedcommand\normalstartimath\normalstopimath} + +% \def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}} +% \def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}} + +\def\font_styles_assignment#specification{\triggergroupedcommand{\font_styles_use_generic{#specification}}} +\def\font_styles_direct #specification{\triggergroupedcommand{\definedfont[#specification]}} + +% environments + +\installcorenamespace{styleenvironment} + +\permanent\protected\def\startstyle[#name]% + {\begingroup + \csname\??styleenvironment + \ifcsname\??stylecheck#name\endcsname + 2% defined as style + \orelse\ifcsname#name\endcsname + 1% defined as command + \else + 3% specification + \fi + \endcsname{#name}} + +\permanent\protected\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} + +\permanent\tolerant\protected\def\definestylecollection[#name]% + {\ifarguments\or + \setuvalue{#name}{\styleinstance[#name]}% + \def\font_styles_define_style_collection_a#style% + {\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}% + \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 + +\permanent\tolerant\protected\def\definestyleinstance[#instance]#*[#2]#*[#3]#*[#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever] + {\ifparameter#instance\or + \ifarguments\or\or + \letvalueempty{\??stylecollection#instance::#2}% + \or + \setvalue{\??stylecollection#instance::#2}{#3}% + \or + \setvalue{\??stylecollection#instance:#2:#3}{#4}% + \fi + \ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi + \fi} + +\permanent\protected\def\styleinstance[#instance]% maybe \lastnamedcs here too + {\csname\??stylecollection#instance:% + \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname + \fontstyle:\fontalternative + \orelse\ifcsname\??stylecollection#instance:\fontstyle:\s!default\endcsname + \fontstyle:\s!default + \orelse\ifcsname\??stylecollection#instance::\fontalternative\endcsname + :\fontalternative + \else + :\s!default + \fi + \endcsname} + +%D Variant selectors +%D +%D \starttyping +%D \mathematics {\vsone{\utfchar{0x2229}}} +%D \mathematics {\utfchar{0x2229}\vsone{}} +%D \stoptyping + +\permanent\protected\edef\vsone#character{#character\normalUchar"FE00 } % used +\permanent\protected\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing + +%D For historic reasons we keep the following around but they are no longer that +%D relevant for \MKIV. But \unknown\ they will be dropped in \LMTX ! + +\permanent\protected\def\doattributes#1#2#3#4% + {\begingroup % geen \bgroup, anders in mathmode lege \hbox + \dousestylehashparameter{#1}{#2}% + \dousecolorhashparameter{#1}{#3}% + #4% + \endgroup} + +\permanent\protected\def\dostartattributes#1#2#3% + {\begingroup % geen \bgroup, anders in mathmode lege \hbox + \dousestylehashparameter{#1}{#2}% + \dousecolorhashparameter{#1}{#3}} + +\let\dostopattributes\endgroup + +%D New but it needs to be supported explicitly (as in natural tables). + +\newconditional\c_font_styles_math + +\protected\def\font_styles_math_reset + {\setfalse\c_font_styles_math} + +\protected\def\font_styles_math_start + {\ifconditional\c_font_styles_math + \startimath + \fi + \relax} + +\protected\def\font_styles_math_stop + {\relax + \ifconditional\c_font_styles_math + \stopimath + \fi} + +\definealternativestyle[\v!math][\settrue\c_font_styles_math] + +\protect \endinput diff --git a/tex/context/base/mkxl/font-sym.mklx b/tex/context/base/mkxl/font-sym.mklx new file mode 100644 index 000000000..7f68d267e --- /dev/null +++ b/tex/context/base/mkxl/font-sym.mklx @@ -0,0 +1,246 @@ +%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 as one can see, it does +%D obey the small and even smaller sizes. The \type {\symbolicfont} macro can be +%D used to switch to a font named \type {fontname} (see \type {cont-log} and \type +%D {symb-eur} for examples of symbolic definitions. + +\def\v_font_string_a + {\ifx\fontstyle\s!rm \s!Serif \orelse + \ifx\fontstyle\s!ss \s!Sans \orelse + \ifx\fontstyle\s!tt \s!Mono \else + \s!Serif \fi} + +\def\v_font_string_b + {\ifx\fontstyle\s!rm \s!Regular \orelse + \ifx\fontstyle\s!ss \s!Support \orelse + \ifx\fontstyle\s!tt \s!Type \else + \s!Serif \fi} + +\def\v_font_string_c + {\ifx\fontalternative\s!bf \s!Bold \orelse + \ifx\fontalternative\s!sl \s!Slanted \orelse + \ifx\fontalternative\s!it \s!Italic \orelse + \ifx\fontalternative\s!bs \s!BoldSlanted \orelse + \ifx\fontalternative\s!bi \s!BoldItalic \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. + +% \frozen ... + +\permanent\def\fontstylesuffix% why the \s!Regular ? see \getglyph + {\ifx\fontalternative\s!tf \s!Regular \orelse + \ifx\fontalternative\s!bf \s!Bold \orelse + \ifx\fontalternative\s!sl \s!Slanted \orelse + \ifx\fontalternative\s!it \s!Italic \orelse + \ifx\fontalternative\s!bs \s!BoldSlanted \orelse + \ifx\fontalternative\s!bi \s!BoldItalic \orelse + \ifx\fontalternative\s!sc \s!Caps \else + \s!Regular \fi} + +\permanent\def\glyphfontfile#base% appends + {#base% + \ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname + \v_font_string_a\v_font_string_c + \orelse\ifcsname\??fontfile#base\v_font_string_b\v_font_string_c\endcsname + \v_font_string_b\v_font_string_c + \orelse\ifcsname\??fontfile#base\v_font_string_a\endcsname + \v_font_string_a + \orelse\ifcsname\??fontfile#base\v_font_string_b\endcsname + \v_font_string_b + \orelse\ifcsname\??fontfile#base\v_font_string_c\endcsname + \v_font_string_c + \fi} + +%D The next macro can be used to make decisions based on the shape: + +\permanent\def\doifelseitalic#yes#nop% + {\ifx\fontalternative\s!sl#yes\orelse + \ifx\fontalternative\s!it#yes\orelse + \ifx\fontalternative\s!bs#yes\orelse + \ifx\fontalternative\s!bi#yes\else#nop\fi} + +\aliased\let\doifitalicelse\doifelseitalic + +%D For an example of usage of the following command, 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 implement a much faster +%D alternative: + +\installcorenamespace{symbolfont} + +\let\thedefinedfont\relax + +\permanent\protected\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile + {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% + \ifcsname\??symbolfont\askedsymbolfont\endcsname + \lastnamedcs + \else + \font_basics_define_symbolic_font + \fi} + +\permanent\protected\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile + {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% + \ifcsname\??symbolfont\askedsymbolfont\endcsname + \lastnamedcs + \else + \font_basics_define_symbolic_font + \fi} + +\permanent\protected\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile + {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}% + \ifcsname\??symbolfont\askedsymbolfont\endcsname + \lastnamedcs + \else + \font_basics_define_symbolic_font + \fi} + +\permanent\protected\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 + \gletcsname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall} + +\permanent\protected\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}} +\permanent\protected\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}} +\permanent\protected\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} +\permanent\protected\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} +\permanent\protected\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}} +\permanent\protected\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}} + +% this one is wrong: + +\permanent\protected\def\getscaledglyph#scale#name#content% + {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}} + +\aliased\let\getglyph \getglyphstyled % old, soon obsolete +\aliased\let\getrawglyph \getglyphdirect % old, soon obsolete +\aliased\let\symbolicsizedfont\setscaledstyledsymbolicfont % old, soon obsolete +\aliased\let\symbolicfont \setstyledsymbolicfont % old, soon obsolete + +\permanent\protected\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody} + +%D The last implementation of \type {\getglyph} permits 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 environment. + +%D \macros +%D {setfont} +%D +%D Every now and then we want to define a font directly, for instance when we +%D typeset title pages. The next macro saves some typing: + +\permanent\protected\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 struts are set. + +%D \macros{doiffontcharelse} + +\permanent\protected\def\doifelsefontchar#specification#unicode% this could be a direct lua call + {\begingroup + \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% + \iffontchar\font#unicode\relax + \endgroup\expandafter\firstoftwoarguments + \else + \endgroup\expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiffontcharelse\doifelsefontchar + +\protect \endinput diff --git a/tex/context/base/mkxl/font-tra.mkxl b/tex/context/base/mkxl/font-tra.mkxl new file mode 100644 index 000000000..72addc5e9 --- /dev/null +++ b/tex/context/base/mkxl/font-tra.mkxl @@ -0,0 +1,343 @@ +%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 relations between +%D 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 \type {\halign}. + +\fetchruntimecommand \showbodyfont \f!font_run + +%D \macros +%D {showfontstrip, testminimalbaseline, showminimalbaseline} +%D +%D The next command can come in handy when combining different fonts into a +%D collection (typeface) and determining optimal baseline distances. +%D +%D \showfontstrip \blank \showminimalbaseline + +\fetchruntimecommand \showfontstrip \f!font_run +\fetchruntimecommand \testminimalbaseline \f!font_run +\fetchruntimecommand \showminimalbaseline \f!font_run + +%D \macros +%D {showkerning} +%D +%D A goody is: +%D +%D \showkerning{Can you guess what kerning is?} + +\fetchruntimecommand \showkerning \f!font_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!font_run + +%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!font_run +\fetchruntimecommand \showfontstyle \f!font_run +\fetchruntimecommand \showligature \f!font_run +\fetchruntimecommand \showligatures \f!font_run +\fetchruntimecommand \showcharratio \f!font_run +\fetchruntimecommand \showfontparameters \f!font_run + +\permanent\protected\def\showchardata#1{\ctxcommand{showchardata("#1")}} % todo: direct implementor +\permanent\protected\def\showfontdata {\ctxcommand{showfontparameters()}} % todo: direct implementor + +%D \macros +%D {doiffontpresentelse} +%D +%D \starttyping +%D \doiffontpresentelse{texnansi-lmr10}{YES}{NO} +%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO} +%D \stoptyping + +\permanent\protected\def\doifelsefontpresent#1{\clf_doifelsefontpresent{#1}} + +\aliased\let\doiffontpresentelse\doifelsefontpresent + +% experimental, maybe this becomes a module + +\newbox\otfcollector + +\permanent\protected\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}} +\permanent\protected\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}} +\permanent\protected\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}} + +% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page +% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page + +\permanent\protected\def\showotfstepglyphs#1% + {\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}% + \unhbox\otfcollector} + +\permanent\protected\def\otfstepspace + {\removeunwantedspaces + \hskip.5\emwidth \s!plus .125\emwidth \s!minus .125\emwidth\relax} + +\permanent\protected\def\otfstepcharcommand#1#2#3% font char class + {\otfstepspace + \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:% + \setbox\scratchbox\hbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}% + \ifzeropt\wd\scratchbox + \scratchwidth.125\onepoint + \scratchdistance\dimexpr(\emwidth/2-\scratchwidth)\relax + \kern\scratchdistance + \ruledhbox to \scratchwidth{\hss\box\scratchbox\hss}% + \kern-\scratchwidth + \hskip\scratchdistance + \else + \ruledhbox{\box\scratchbox}% + \fi + \otfstepspace} + +\permanent\protected\def\otfstepfontcommand#1#2#3% id font size + {\begingroup + \tttf #1: #2 @ \the\dimexpr#3\scaledpoint\relax + \endgroup} + +\permanent\protected\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} + +\permanent\protected\def\showotfstepfont + {\ctxlua{nodes.tracers.steppers.font("otfstepfontcommand")}} + +\permanent\protected\def\showotfstepchars#1% + {\ctxlua{nodes.tracers.steppers.codes(#1,"otfstepcharcommand","otfstepspace")}} + +\permanent\protected\def\showotfstepmessages#1% + {\ctxlua{nodes.tracers.steppers.messages(#1,"otfstepmessagecommand",true)}} + +\permanent\protected\def\showotfstepfeatures + {\ctxlua{nodes.tracers.steppers.features()}} + +\permanent\protected\def\otfnoffeaturesteps + {\ctxlua{nodes.tracers.steppers.nofsteps()}} + +\newconstant\showotfstepsmode \showotfstepsmode\plusfour + +\protected\def\showotfsteps_n + {\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 + \lefttoright + \dontleavehmode + \ifnum\recurselevel=\scratchcounter + \ruledhbox{\box\otfcompositionbox}% + \else + \ruledhbox{\showotfstepglyphs\recurselevel}% + \fi + \quad + \showotfstepchars\recurselevel + \hfill + \par + \egroup + \egroup + \blank} + +\permanent\protected\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 + {\ifcase\showotfstepsmode + \or % 1 = only first + \ifnum\recurselevel=\plusone + \showotfsteps_n + \fi + \or % 2 = only last + \ifnum\recurselevel=\scratchcounter + \showotfsteps_n + \fi + \or % 3 = first and last + \ifnum\recurselevel=\plusone + \showotfsteps_n + \orelse\ifnum\recurselevel=\scratchcounter + \showotfsteps_n + \fi + \else % everything + \showotfsteps_n + \fi}% + \endgroup} + +\permanent\protected\def\startotfsample + {\enabletrackers[otf.sample.silent]% beware, kind of global + \startotfcollecting + \begingroup + \veryraggedright + \forgetparindent + \forgeteverypar} + +\permanent\protected\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 + +\permanent\protected\def\setotfcompositiondirection#1% + {\begincsname\??otfcompositiondir#1\endcsname} + +\permanent\protected\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\setotfcompositiondirection{#2}\relax#3}% + \stopotfsample + \endgroup} + +%D \startbuffer +%D \startotfcompositionlist{Serif*default @ 11pt}{l2r}% +%D \showotfcompositionsample{effe} +%D \stopotfcompositionlist +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\permanent\protected\def\showotfcompositionlist#1#2#3% + {\begingroup + \definedfont[#1]% + \setbox\scratchbox\hbox\bgroup + \setotfcompositiondirection{#2}% + #3% + \egroup + \strut + \def|##1|{\kern\onepoint\string|\kern\onepoint##1\kern\onepoint\string|\kern\onepoint}% + \cldcontext{nodes.listtoutf(tex.box[\number\scratchbox].list,"{\\kern\\onepoint}",true)}% + \endgroup} + +\aliased\let\showotfcompositionsample\gobbleoneargument + +\permanent\protected\def\startotfcompositionlist#1#2#3\stopotfcompositionlist + {\begingroup + \enforced\protected\def\showotfcompositionsample##1% + {\NC\type{##1}% + \NC\showotfcompositionlist{Mono}{#2}{##1}% + \NC\showotfcompositionlist{#1}{#2}{##1}% + \NC\definedfont[#1]##1% + \NC\NR}% + \starttabulate[|||||]% + #3% + \stoptabulate + \endgroup} + +\aliased\let\stopotfcompositionlist\relax + +% new + +\permanent\protected\def\savefontdata[#1]% not yet in i-*.xml + {\begingroup + \getdummyparameters[#1]% + \clf_savefont { + filename {\dummyparameter\c!file} + fontname {\dummyparameter\c!name} + method {\dummyparameter\c!method} + }% + \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/font-uni.mkxl b/tex/context/base/mkxl/font-uni.mkxl new file mode 100644 index 000000000..390f17468 --- /dev/null +++ b/tex/context/base/mkxl/font-uni.mkxl @@ -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 an +%D \UTF\ converter. We expand it so best not use not use it for active characters. +%D In practice this command is probably never used anyway but we keep if for old +%D styles. + +\unprotect + +\permanent\def\uchar#1#2{\clf_uchar\numexpr#1\relax\numexpr#2\relax} + +\aliased\let\uc\uchar + +\protect \endinput diff --git a/tex/context/base/mkxl/font-unk.mkxl b/tex/context/base/mkxl/font-unk.mkxl new file mode 100644 index 000000000..986a5c9bf --- /dev/null +++ b/tex/context/base/mkxl/font-unk.mkxl @@ -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 define and call for not +%D yet defined fonts in a way completely independant of real font names. First we +%D map 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 style (so, Bold +%D may expand to SansBold or SerifBold, depending on the default style in the +%D typeface). The \LUA\ call is used to set the current alternative in a +%D non|-|interfering way. This make sure that the CurrentFont synonym (in font-sym) +%D is working as expected (e.g.\ in MixedCaps). Yes, this is complicates stuff. + +\definefontsynonym[\s!Normal] [\noexpand\clf_tf\noexpand\v_font_string_d] +\definefontsynonym[\s!Bold] [\noexpand\clf_bf\noexpand\v_font_string_d\noexpand\s!Bold] +\definefontsynonym[\s!Italic] [\noexpand\clf_it\noexpand\v_font_string_d\noexpand\s!Italic] +\definefontsynonym[\s!Slanted] [\noexpand\clf_sl\noexpand\v_font_string_d\noexpand\s!Slanted] +\definefontsynonym[\s!BoldItalic] [\noexpand\clf_bi\noexpand\v_font_string_d\noexpand\s!BoldItalic] +\definefontsynonym[\s!BoldSlanted][\noexpand\clf_bs\noexpand\v_font_string_d\noexpand\s!BoldSlanted] +\definefontsynonym[\s!Caps] [\noexpand\clf_tf\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 mapped onto real file +%D names (or names that themselves are mapped). + +\protect \endinput diff --git a/tex/context/base/mkxl/font-var.mklx b/tex/context/base/mkxl/font-var.mklx new file mode 100644 index 000000000..421521f50 --- /dev/null +++ b/tex/context/base/mkxl/font-var.mklx @@ -0,0 +1,57 @@ +%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 \type {\tf} is +%D accompanied by \type {\tfa}, \type {\tfb} etc. The first two characters denote +%D the alternative, while the third character in these sequences represents the +%D size. The actual size is saved in a macro. The styles, being roman (\type {\rm}), +%D sans serif (\type {\ss}) etc. are also available. + +% 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) + +\mutable\def\normalizedbodyfontsize{12pt} + +\immutable\def\defaultfontbody {\normalizedbodyfontsize} +\immutable\let\defaultfontstyle \s!rm +\immutable\let\defaultfontalternative\s!tf +\immutable\let\defaultfontsize \empty +\immutable\let\defaultfontface \!!zerocount + +\mutable\let\globalfontclass\empty +\mutable\let\fontclass \empty +\mutable\let\fontbody \defaultfontbody +\mutable\let\fontstyle \defaultfontstyle +\mutable\let\fontalternative\defaultfontalternative +\mutable\let\fontsize \defaultfontsize +\mutable\let\fontface \!!zerocount + +\installmacrostack\fontstyle + +% we can use an indirect mapping for fontclasses (map string onto numbers) and indeed this +% is somewhat more efficient but also makes the code messy ... maybe some day ... + +\protect \endinput diff --git a/tex/context/base/mkxl/grph-epd.mkxl b/tex/context/base/mkxl/grph-epd.mkxl new file mode 100644 index 000000000..a0fcc51da --- /dev/null +++ b/tex/context/base/mkxl/grph-epd.mkxl @@ -0,0 +1,91 @@ +%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}{} + +\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}] + +\protected\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 + +\defineframed + [epdfstampsymbol] + [\c!foregroundstyle=\v!mono, + \c!background=\c!color, + \c!rulethickness=.125\exheight, + \c!offset=.250\exheight, + \c!backgroundcolor=lightgray, % can be adapted before first usage + \c!framecolor=darkgray, % can be adapted before first usage + \c!corner=\v!round] + +\definesymbol[Stamped] [\epdfstampsymbol{Stamped}] + +\definesymbol[Approved] [\epdfstampsymbol{Approved}] +\definesymbol[Experimental] [\epdfstampsymbol{Experimental}] +\definesymbol[NotApproved] [\epdfstampsymbol{NotApproved}] +\definesymbol[AsIs] [\epdfstampsymbol{AsIs}] +\definesymbol[Expired] [\epdfstampsymbol{Expired}] +\definesymbol[NotForPublicRelease] [\epdfstampsymbol{NotForPublicRelease}] +\definesymbol[Confidential] [\epdfstampsymbol{Confidential}] +\definesymbol[Final] [\epdfstampsymbol{Final}] +\definesymbol[Sold] [\epdfstampsymbol{Sold}] +\definesymbol[Departmental] [\epdfstampsymbol{Departmental}] +\definesymbol[ForComment] [\epdfstampsymbol{ForComment}] +\definesymbol[TopSecret] [\epdfstampsymbol{TopSecret}] +\definesymbol[Draft] [\epdfstampsymbol{Draft}] +\definesymbol[ForPublicRelease] [\epdfstampsymbol{ForPublicRelease}] + +\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/tex/context/base/mkxl/grph-fig.mkxl b/tex/context/base/mkxl/grph-fig.mkxl new file mode 100644 index 000000000..723a627a5 --- /dev/null +++ b/tex/context/base/mkxl/grph-fig.mkxl @@ -0,0 +1,362 @@ +%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. + +% This is (yet) untested in LMTX! + +\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 + +\permanent\protected\def\typesetbuffer {\bgroup\setconstant\c_grph_buffers_mode\plusone \grph_buffers_typeset} +\permanent\protected\def\typesetbufferonly{\bgroup\setconstant\c_grph_buffers_mode\zerocount\grph_buffers_typeset} + +\tolerant\permanent\protected\def\grph_buffers_typeset[#1]#*[#2]% + {\ifparameters + \grph_buffers_typeset_indeed\jobname\empty + \or + \ifhastok={#1}% + \grph_buffers_typeset_indeed\jobname{#1}% + \else + \grph_buffers_typeset_indeed{#1}\empty + \fi + \or + \grph_buffers_typeset_indeed{#1}{#2}% + \fi} + +\def\grph_buffers_typeset_indeed#1#2% we could use the via files + {\doifnot{#1}{*}{\xdef\lasttypesetbuffer{\clf_typesetbuffer{#1}}}% + \ifcase\c_grph_buffers_mode + % typesetonly + \or + \externalfigure[\lasttypesetbuffer][#2]% + \fi + \egroup} + +\tolerant\permanent\protected\def\runbuffer[#1]#*[#2]% + {\xdef\lasttypesetbuffer{\clf_runbuffer{#1}{#2}}} + +% 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} + +\tolerant\permanent\protected\def\definetypesetting[#1]#*[#2]#*[#3]% options settings-a + {\ifparameter#1\or\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}\fi} + +\tolerant\permanent\protected\def\typesetfile[#1]#*[#2]#*[#3]% filename settings-b | filename options settings + {\ifcsname\??typesettingfile#1\endcsname + \lastnamedcs{#2}{#3}% + \orelse\ifparameter#3\or + \grph_typesetting_process_indeed{#2}{#3}{#1}{}% + \orelse\ifparameter#2\or % filename settings + \grph_typesetting_process_indeed{}{#2}{#1}{}% + \fi} + +\defineexternalfigure[typesetting] % so one can set a frame and such + +\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 + \normalexpanded{\externalfigure[\m_typesetting_name][typesetting]}[#2,#4]% + \fi + \endgroup} + +%D Whatever ... hardly used ... but historic ... needs checking ... will probably +%D become m-fig-nn.mkiv .. or I will extend it cq. clean it up when I needed it. +%D 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 + +\tolerant\protected\def\grph_steps_place_figure#1#2#3#4[#5]% + {\hpack + {\setbox\scratchbox\hpack + {\useexternalfigure[\s!dummy][#2][#3,#5]% + \externalfigure[\s!dummy]}% + \grph_steps_calculate + \startpositioning + \enforced\let\referring\grph_steps_one_referring + \enforced\let\marking \grph_steps_one_marking + \enforced\let\remark \grph_steps_one_remark + \enforced\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% + \enforced\let\referring\grph_steps_two_referring + \enforced\let\marking \grph_steps_two_marking + \enforced\let\remark \grph_steps_two_remark + \enforced\let\colorbar \grph_steps_two_colorbar + \ignorespaces#4\removeunwantedspaces % or just grab #4 unspaced + \stoppositioning + \ifvoid\b_grph_steps_colorbar\else\box\b_grph_steps_colorbar\fi}} % not really needed + +\protected\def\grph_steps_one_referring(#1,#2)#*(#3,#4)#*[#5]% + {\position(#1,#2){\grph_steps_goto(#3,#4){\externalfigureparameter\c!frames}[#5]}} + +\protected\def\grph_steps_one_marking(#1,#2)#*(#3,#4)#*[#5]% + {\position(#1,#2){\grph_steps_this_is(#3,#4){\externalfigureparameter\c!frames}[#5]}} + +\protected\def\grph_steps_one_remark (#-,#-)#*(#-,#-)#*[#-]#*#:#-{}% (x,y)(h,b)[...]{tekst} +\protected\def\grph_steps_one_colorbar #-[#-]{} +\protected\def\grph_steps_two_referring(#-,#-)#*(#-,#-)#*[#-]{} + +\let\grph_steps_two_marking\grph_steps_two_referring + +\protected\def\grph_steps_two_remark + {\grph_steps_comment\v!no} + +\protected\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} + +\protected\def\grph_colorbar_make_step#1% + {\blackrule[\c!color=#1,\c!width=2\emwidth,\c!height=\exheight,\c!depth=\zeropoint]% + \endgraf} + +\permanent\protected\def\startfigure[#1]#*[#2]#*[#3]#:#4\stopfigure + {\doifelse{\externalfigureparameter\c!option}\v!test + {\grph_steps_test_figure{#1}{#2}{#3}{#4}% + \letexternalfigureparameter\c!frames\v!on}% + {\letexternalfigureparameter\c!frames\v!off}% + \setvalue{\??externalfigureinstance#1}% + {\grph_steps_place_figure{#1}{#2}{#3}{#4}}} + +\aliased\let\stopfigure\relax + +\ifdefined\referring \else \let\referring\relax \fi +\ifdefined\marking \else \let\marking \relax \fi +\ifdefined\remark \else \let\remark \relax \fi +\ifdefined\colorbar \else \let\colorbar \relax \fi + +\protected\def\grph_steps_test_figure#1#2#3#4% + {\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 + \setbox\scratchboxone\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\removeunwantedspaces % or just grab #4 unspaced + \stoppositioning + \vfill}% + \c_grph_steps_reference\zerocount + \enforced\let\referring\grph_steps_four_referring + \enforced\let\marking \grph_steps_four_marking + \enforced\let\remark \grph_steps_four_remark + \enforced\let\colorbar \grph_steps_four_colorbar + \setbox\scratchboxtwo\vbox % \vpack ? + {\forgetall + \begingroup + \tfa\doifelsenothing{#1}{#2}{#1}% + \endgroup + \blank + \tfxx#4% + \vfilll}% + \ifdim\ht\scratchboxone>\ht\scratchboxtwo + \ht\scratchboxtwo\ht\scratchboxone + \else + \ht\scratchboxone\ht\scratchboxtwo + \fi + \hpack + {\hskip3\emwidth + \tpack{\vskip12\points\box\scratchboxone\vskip6\points}% + \tpack{\vskip12\points\box\scratchboxtwo\vskip6\points}}% + \endgroup} + +\definesystemconstant{vwa} +\definesystemconstant{vwb} + +\tolerant\protected\def\grph_steps_three_referring(#1,#2)#*(#3,#4)#*[#5]% + {\advance\c_grph_steps_reference\plusone + \position(#1,#2) + {\hbox{\the\c_grph_steps_reference}}% + \position(#1,#2) + {\gotosomeinternal\s!vwb{#5}\realfolio + {\grph_steps_marker(#3,#4)\v!on{\thisissomeinternal\s!vwa{#5}}}}} + +\protected\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 + +\protected\def\grph_steps_four_referring{\grph_steps_text{\normalstartimath\rightarrow\normalstopimath}} +\protected\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} + +\tolerant\def\grph_steps_comment#1(#2,#3)#*(#4,#5)#*[#6]#*#:#7% {kader}(x,y)(h,b)[...]{tekst} + {\position(#2,#3)% + {\setnostrut + \framed[\c!width=#4\d_grph_steps_x,\c!height=#5\d_grph_steps_y,\c!offset=\v!none,\c!frame=#1,#6]{#7}}} + +% \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]} + +\tolerant\def\grph_steps_text#1(#2,#3)#*(#4,#5)#*[#6]% + {\advance\c_grph_steps_reference\plusone + \hbox % \hpack ? + {\quad + \thisissomeinternal\s!vwb{#6}% + \gotosomeinternal\s!vwa{#6}\realfolio{\hbox to 1.5\emwidth{\the\c_grph_steps_reference\presetgoto\hfill}}% + \quad#1 (#2,#3) (#4,#5) [#6]\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/tex/context/base/mkxl/grph-inc.mkxl b/tex/context/base/mkxl/grph-inc.mkxl new file mode 100644 index 000000000..21be4abf6 --- /dev/null +++ b/tex/context/base/mkxl/grph-inc.mkxl @@ -0,0 +1,1076 @@ +%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-img}{} +\registerctxluafile{grph-inc}{} +\registerctxluafile{grph-bmp}{} +\registerctxluafile{grph-chk}{} +\registerctxluafile{grph-con}{} +\registerctxluafile{grph-fil}{} +\registerctxluafile{grph-mem}{} +\registerctxluafile{grph-u3d}{} % this will become a module +%registerctxluafile{grph-swf}{} % this will become a module + +\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 not so much less code as in \MKII\ but it's +%D more powerful, flexible, pluggable and some of the extended functionality has been +%D moved from modules to the core. The overall functionality is rather stable and has +%D not changed much over the years. + +\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi + +\installcorenamespace{externalfigure} +\installcorenamespace{externalfigureinstance} +\installcorenamespace{externalfigurecollection} + +\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure + +\aliased\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!file =, + \c!display =, + \c!mask =, + \c!preset =\v!yes, + \c!split =, + \c!color =, + \c!arguments =, + \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. + \c!crossreference =\v!no, + \c!transform =\v!auto, + \c!userpassword =, + \c!ownerpassword =, + \c!compact =, + \c!cmyk =, + ] + +%D Defining figures. + +\newcount\c_grph_include_nesting + +\newtoks \everyexternalfigureresets % for the moment still public +\newtoks \everyexternalfigurechecks % for the moment still public + +% \useexternalfigure[alpha][cow] +% \useexternalfigure[beta] [cow] [width=1cm] +% \useexternalfigure[gamma][cow][alpha] +% \useexternalfigure[delta][cow][alpha][width=2cm] +% +% full width : \externalfigure[cow] \par +% 3cm width : \externalfigure[cow] [width=3cm] \par +% full width : \externalfigure[alpha] \par +% 1cm width : \externalfigure[beta] \par +% full width : \externalfigure[gamma] \par +% 2cm width : \externalfigure[delta] \par +% 4cm width : \externalfigure[beta] [width=4cm] \par +% 5cm width : \externalfigure[gamma][width=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, the already set +%D parameters need to be set again or otherwise the old values will be used. +%D +%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 the web +%D tools need a suffix (like gif) which we don't want as we want a high quality +%D format. + +\newconditional\c_grph_include_trace_inheritance + +\installtextracker + {graphics.inheritance} + {\settrue \c_grph_include_trace_inheritance} + {\setfalse\c_grph_include_trace_inheritance} + +\installcorenamespace{externalfiguredefinition} + +% \protected\def\defineexternalfigure +% {\dodoubleargument\grph_include_define} +% +% \def\grph_include_define[#1][#2]% +% {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}} + +\aliased\let\defineexternalfigures\defineexternalfigure + +% label file parent settings +% label file settings +% label file parent + +\permanent\tolerant\protected\def\useexternalfigure[#1]#*[#2]#*[#3]#*[#4]% + {\iftok{#1}\emptytoks + \iftok{#2}\emptytoks\else + \ifhastok={#3}% + \grph_include_use_indeed{#2}{#2}{#3}{#4}% + \else + \grph_include_use_indeed{#2}{#2}\empty{#4}% + \fi + \fi + \orelse\iftok{#2}\emptytoks + \ifhastok={#3}% + \grph_include_use_indeed{#1}{#1}\empty{#3}% + \else + \grph_include_use_indeed{#1}{#1}{#3}{#4}% + \fi + \else + \ifhastok={#3}% + \grph_include_use_indeed{#1}{#2}\empty{#3} + \else + \grph_include_use_indeed{#1}{#2}{#3}{#4}% + \fi + \fi} + +\def\grph_include_use_indeed#1#2#3#4% + {\dodoglobal\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}% + \grph_include_analyze_collection[#2][#4]} + +% inclusion + +\permanent\tolerant\protected\def\externalfigure[#1]#*[#2]#*[#3]% + {\ifhastok={#2}% + \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}% + \ifempty\m_grph_include_name \else + \let\p_grph_include_name\m_grph_include_name + \fi + \ifempty\m_grph_include_parent \else + \grph_include_inherit_from_parent\m_grph_include_parent + \fi + \setupcurrentexternalfigure[#3]} + +\def\grph_include_inherit_from_parent#1% + {\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 + \ifempty\p_grph_include_parent + % nothing to be done + \orelse\ifx\p_grph_include_parent\p_grph_include_label + % redundant + \else + \grph_include_inherit_from_parent\p_grph_include_parent + \fi + \ifempty\p_grph_include_label + % 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 + \ifhastok={#2}% + % [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}% + \ifempty\p_grph_include_parent + \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}% + \edef\p_reference{\externalfigureparameter\c!reference}% + % + \dostarttagged\t!image\empty + \clf_figure_push { + name {\p_grph_include_name}% + label {\ifempty\p_label\p_grph_include_label\else\p_label\fi}% + page {\externalfigureparameter\c!page}% + file {\externalfigureparameter\c!file}% + size {\externalfigureparameter\c!size}% + object {\externalfigureparameter\c!object}% + prefix {\externalfigureparameter\c!prefix}% + cache {\externalfigureparameter\c!cache}% + format {\externalfigureparameter\c!method}% + preset {\externalfigureparameter\c!prefix}% + controls {\externalfigureparameter\c!controls}% + resources {\externalfigureparameter\c!resources}% + preview {\externalfigureparameter\c!preview}% + display {\externalfigureparameter\c!display}% + mask {\externalfigureparameter\c!mask}% + conversion {\externalfigureparameter\c!conversion}% + resolution {\externalfigureparameter\c!resolution}% + color {\externalfigureparameter\c!color}% unprocessed raw key + cmyk {\externalfigureparameter\c!cmyk}% kind of special + arguments {\externalfigureparameter\c!arguments}% used for converters + repeat {\externalfigureparameter\c!repeat}% + transform {\externalfigureparameter\c!transform}% + compact {\externalfigureparameter\c!compact}% experiment, share fonts + userpassword {\externalfigureparameter\c!userpassword}% + ownerpassword{\externalfigureparameter\c!ownerpassword}% + \ifempty\p_width \else + width \dimexpr\p_width\relax + \fi + \ifempty\p_height \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 + % + \scratchcounter\zerocount + \edef\p_crossreference{\externalfigureparameter\c!crossreference}% + \iflocation\iftrialtypesetting\else + \ifempty\p_crossreference + % nothing + \orelse\ifx\p_crossreference\v!no + % nothing + \orelse\ifx\p_crossreference\v!yes + \ifhastok={#2}% + \scratchcounter\clf_figure_register_page{#1}{}{#2}\relax + \else + \scratchcounter\clf_figure_register_page{#1}{#2}{#3}\relax + \fi + \else + \scratchcounter-\p_crossreference % passed by repeater + \fi + \fi\fi + \naturalvpack + attr \imageattribute \plustwo + \ifnum\scratchcounter>\zerocount + {\strc_references_cross_forward {ex:\number \scratchcounter}{\box\foundexternalfigure}}% + \orelse\ifnum\scratchcounter<\zerocount + {\strc_references_cross_backward{ex:\number-\scratchcounter}{\box\foundexternalfigure}}% + \else + {\box\foundexternalfigure}% + \fi + % + % \naturalvpack attr \imageattribute \plustwo \bgroup + % \ifcmpnum\scratchcounter\zerocount + % \strc_references_cross_backward{ex:\number-\scratchcounter}{\box\foundexternalfigure}% + % \or % equal + % \box\foundexternalfigure% + % \or % more + % \strc_references_cross_forward {ex:\number \scratchcounter}{\box\foundexternalfigure}% + % \fi + % \egroup + % + \dostoptagged + \egroup} + +%D Next we provide a cross referenced scale-up mechanism: + +\def\strc_references_cross_forward#1#2% + {\begingroup + \strc_references_set_simple_internal_reference{cross:b:#1}% + \naturalhpack + attr \destinationattribute\number\lastdestinationattribute + {\naturalhpack{\strc_references_flush_destination_nodes\directgotodumbbox{#2}[cross:f:#1]}}% + \endgroup} + +\def\strc_references_cross_backward#1#2% + {\begingroup + \strc_references_set_simple_internal_reference{cross:f:#1}% + \naturalhpack + attr \destinationattribute\number\lastdestinationattribute + {\naturalhpack{\strc_references_flush_destination_nodes\directgotodumbbox{#2}[cross:b:#1]}}% + \endgroup} + +\let\doexternalfigurerepeat\gobblefourarguments % called from lua end + +\permanent\tolerant\protected\def\placeregisteredexternalfigures[#1]% + {\page + \begingroup + \protected\def\doexternalfigurerepeat{\grph_include_place_registered_indeed{#1}}% + \dorecurse\clf_figure_nof_registered_pages + {\page + \clf_figure_flush_registered_pages\recurselevel + \page}% + \endgroup + \page} + +\protected\def\grph_include_place_registered_indeed#1#2#3#4#5% called from lua end + {\grph_include_place[#2][#3][#4,% + \c!hfactor=,\c!wfactor=,\c!factor=,% + \c!maxwidth=,\c!maxheight=,% + \c!xscale=,\c!yscale=,\c!scale=,% + \c!sx=,\c!sy=,\c!s=,% + \c!width=,\c!height=,% + \c!crossreference=#5,% + #1]} + +%D Scaling: + +\let\dowithfigure\relax % name might change (into a proper hook) + +\permanent\protected\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] + +%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 + +\permanent\tolerant\protected\def\definegraphictypesynonym[#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. + +\permanent\protected\def\setfigurepathlist + {\clf_setfigurepaths{\externalfigureparameter\c!location}{\externalfigureparameter\c!directory}} + +%D Variables: + +\newbox \foundexternalfigure +\newtoks\externalfigurepostprocessors + +\def\defaultfigurewidth {8\lineheight} % permanent ? frozen ? +\def\defaultfigureheight {6\lineheight} % permanent ? frozen ? + +\permanent\def\figurestatus {\numexpr\clf_figurestatus{status}{0}\relax} % number: 0 = not found +\permanent\def\figurewidth {\clf_figurestatus{width}{0}sp} +\permanent\def\figureheight {\clf_figurestatus{height}{0}sp} +\permanent\def\figurexscale {\clf_figurestatus{xscale}{1}} +\permanent\def\figureyscale {\clf_figurestatus{yscale}{1}} + +\permanent\def\figuresize {\clf_figurerequest{size}{}} +\permanent\def\figurelabel {\clf_figurerequest{label}{}} +\permanent\def\figurefileoriginal {\clf_figurerequest{name}{}} +\permanent\def\figurefilepage {\clf_figurerequest{page}{1}} +\permanent\def\figurefileoptions {\clf_figurerequest{options}{}} +\permanent\def\figurefileconversion{\clf_figurerequest{conversion}{}} +\permanent\def\figurefileresolution{\clf_figurerequest{resolution}{}} +\permanent\def\figurefilecolor {\clf_figurerequest{color}{}} +\permanent\def\figurefilearguments {\clf_figurerequest{arguments}{}} +\permanent\def\figurefilecache {\clf_figurerequest{cache}{}} +\permanent\def\figurefileprefix {\clf_figurerequest{prefix}{}} + +\permanent\def\figurenaturalwidth {\clf_figureused{width}{\number\dimexpr\defaultfigurewidth\relax}sp} +\permanent\def\figurenaturalheight {\clf_figureused{height}{\number\dimexpr\defaultfigureheight\relax}sp} +\permanent\def\figurexresolution {\clf_figureused{xresolution}{0}} +\permanent\def\figureyresolution {\clf_figureused{yresolution}{0}} +\permanent\def\figureorientation {\clf_figureused{orientation}{1}} +\permanent\def\figurerotation {\clf_figureused{rotation}{0}} +\permanent\def\figurexsize {\clf_figureused{xsize}{0}} +\permanent\def\figureysize {\clf_figureused{ysize}{0}} +\permanent\def\figurecolordepth {\clf_figureused{colordepth}{0}} +\permanent\def\figuredepth {\clf_figureused{depth}{0}} + +\permanent\def\figurefullname {\clf_figureused{fullname}{}} +\permanent\def\noffigurepages {\clf_figureused{pages}{0}} + +% \permanent\def\figurefilepath {\clf_figurefilepath} % public in lua +% \permanent\def\figurefilename {\clf_figurefilename} % public in lua +% \permanent\def\figurefiletype {\clf_figurefiletype} % public in lua + +\permanent\let\naturalfigurewidth \figurenaturalwidth +\permanent\let\naturalfigureheight \figurenaturalheight + +\aliased\let\figurescalewidth \figurewidth +\aliased\let\figurescaleheight \figureheight +\aliased\let\figurescalexscale \figurexscale +\aliased\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 + \globalresetsystemmode\v!figure % todo, also: \v!resource + \else + \globalsetsystemmode \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 + \orelse\ifx\p_option\v!empty + \settrue\c_grph_include_skip + \letexternalfigureparameter\c!frame\v!off + \else + \setfalse\c_grph_include_skip + \fi + % fake color in gray bitmaps, assumes that + % a transparent color is used + \edef\p_foregroundcolor{\externalfigureparameter\c!foregroundcolor}% + \ifempty\p_foregroundcolor \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: + +\permanent\protected\def\docheckfigurebuffer #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\getbuffer[#1]}}} +\permanent\protected\def\docheckfiguretex #1{\global\setbox\foundexternalfigure\vpack{\grph_include_process_tex{\input{#1}}}} +\permanent\protected\def\docheckfigurecld #1{\global\setbox\foundexternalfigure\vbox {\cldprocessfile{#1}}} +\permanent\protected\def\docheckfiguremps #1{\global\setbox\foundexternalfigure\vpack{\convertMPtoPDF{#1}11}} +\permanent\protected\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vpack{\useMPrun{#1}{#2}}} + +\permanent\protected\def\relocateexternalfigure + {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup + % + % The \vss can (!) introduce 1 sp excess visible in xform which in itself + % is not that important but some don't like these cosmetic side effects, for + % instance we can get: + % + % vss : \vbox(845.1575+0.0)x597.23125, glue set 845.15747fil, direction TLT + % vskip : \vbox(845.1575+0.0)x597.23125, direction TLT + % + % or + % + % 1 0 0 1 0 0.00003 cm + % 1 0 0 1 0 0 cm + % + % This is a known property of using glue and can even depend on the architecture + % (float implementation). Anyway, let's for now use a skip. Of course this can + % shift the issue elsewhere, as vss is used a lot elsewhere. + % + % \vss + \vkern\ht\foundexternalfigure + % + \ht\foundexternalfigure\zeropoint + \dp\foundexternalfigure\zeropoint + \hpack to \wd\foundexternalfigure\bgroup + \box\foundexternalfigure + \hss + \egroup + \egroup} + +\permanent\protected\def\startfoundexternalfigure#1#2% ht wd + {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup} + +\permanent\protected\def\stopfoundexternalfigure + {\hss\egroup\egroup} + +\permanent\protected\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 + \orelse\ifcase\figurestatus + % nothing + \else + \the\externalfigurepostprocessors + \box\foundexternalfigure + \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 + \orelse\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 + \inheritedexternalfigureframed{\box\foundexternalfigure}% + \fi + \fi + \fi + \else + % maybe also \the\externalfigurepostprocessors + \iftrialtypesetting \else \feedbackexternalfigure \fi + \fi}} + +\let\feedbackexternalfigure\relax % hook + +\permanent\protected\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} + +\permanent\protected\def\doifelsefigure#1% + {\getfiguredimensions[#1]% so data is available ! + \ifcase\figurestatus + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doiffigureelse\doifelsefigure + +% No placement, handy for preprocessing: + +\permanent\tolerant\protected\def\registerexternalfigure[#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. + +\permanent\protected\def\dosetfigureobject#1#2% + {\setobject{#1}{#2}\vpack{\box\foundexternalfigure}} + +\permanent\protected\def\doboxfigureobject#1#2% + {\global\setbox\foundexternalfigure\vpack{\getobject{#1}{#2}}} % probably one vbox too many + +% Figure bases + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\def\externalfigurecollectionparameter#1#2% + {\csname + \ifcsname\??externalfigurecollection#1:#2\endcsname + \??externalfigurecollection#1:#2% + \else + \s!empty + \fi + \endcsname} + +\permanent\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth } +\permanent\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth } +\permanent\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight} +\permanent\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight} + +\aliased\let\efcparameter\externalfigurecollectionparameter % still needed ? +\aliased\let\efcminwidth \externalfigurecollectionminwidth % still needed ? +\aliased\let\efcmaxwidth \externalfigurecollectionmaxwidth % still needed ? +\aliased\let\efcminheight\externalfigurecollectionminheight % still needed ? +\aliased\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 + +\permanent\protected\def\overlayfigure#1% + {\externalfigure[#1][\c!width=\d_overlay_width,\c!height=\d_overlay_height]} + +% Experimental (will become cleaner): + +\permanent\tolerant\protected\def\includesvgfile[#1]#*[#2]% + {\dontleavehmode\begingroup + \getdummyparameters[\c!offset=\zeropoint,#2]% + \clf_includesvgfile{#1}\dimexpr\dummyparameter\c!offset\relax + \endgroup} + +\permanent\tolerant\protected\def\includesvgbuffer[#1]#*[#2]% + {\dontleavehmode\begingroup + \getdummyparameters[\c!offset=\zeropoint,#2]% + \clf_includesvgbuffer{#1}\dimexpr\dummyparameter\c!offset\relax + \endgroup} + +% Bonus: + +\useexternalfigure + [\v!buffer] + [\jobname.buffer] + [\c!object=\v!no] + +% Another two: + +\defineexternalfigure + [\v!inline] + [\c!height=\lineheight] + +\definemeasure + [\v!combination] + [(\textwidth + -\effectiveleftskip + -\effectiverightskip + -\numexpr\combinationparameter\c!nx-\plusone\relax\dimexpr\combinationparameter\c!distance\relax + )/\combinationparameter\c!nx] + +\defineexternalfigure + [\v!combination] + [\c!width=\measure{\v!combination}] + +% \startcombination[nx=2,ny=1] +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% \stopcombination + +% \startcombination[nx=2,ny=1] +% {\externalfigure[dummy][width=\measure{combination}]} {} +% {\externalfigure[dummy][width=\measure{combination}]} {} +% \stopcombination + +% \startcombination[nx=2,ny=2] +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% \stopcombination + +% \startcombination[nx=3,ny=1] +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% \stopcombination + +% \startcombination[nx=4,ny=1] +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% {\externalfigure[dummy][combination]} {} +% \stopcombination + +\permanent\protected\def\inlinefigure[#1]% + {\dontleavehmode + \sbox{\externalfigure[#1][\v!inline]}} + +%D Needs to be done global: + +\definelayer[epdfcontent] + +\protect \endinput + +%D Moved here because this already old code is nowhere documents (so I need to check +%D it: +% +% \starttyping +% \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][frame=on,display=u3d:myset:display:2]} +% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:3]} +% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:4]} +% \placefigure[here]{none}{\externalfigure[axes] [frame=on,display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]} +% +% \stoptext diff --git a/tex/context/base/mkxl/grph-pat.mkxl b/tex/context/base/mkxl/grph-pat.mkxl new file mode 100644 index 000000000..92fd5ad74 --- /dev/null +++ b/tex/context/base/mkxl/grph-pat.mkxl @@ -0,0 +1,119 @@ +%D \module +%D [ file=grph-par, +%D version=2016.07.08, +%D title=\CONTEXT\ Graphic Macros, +%D subtitle=Patterns, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This works ok in Okular and MuPDF but somehow xforms don't work in Acrobat +%D (full nor reader). Also the basic offset is kind of unspecified. So \unknown\ +%D we're dealing with a fragile feature. So, don't rely on where the first (ulr) +%D tile occurs. +%D +%D The two commands introduced here are not documented (yet). + +\writestatus{loading}{ConTeXt Graphic Macros / Patterns} + +\unprotect + +\registerctxluafile{grph-pat}{} + +\permanent\tolerant\protected\def\registerpattern[#1]#*[#2]% + {\begingroup + \letdummyparameter\c!name \s!dummy + \letdummyparameter\c!width \v!auto + \letdummyparameter\c!height \v!auto + \letdummyparameter\c!hoffset\zeropoint + \letdummyparameter\c!voffset\zeropoint + \unless\iftok{#2}\emptytoks + \setdummyparameter\c!name{#1}% + \getdummyparameters[#2]% + \orelse\ifhastok={#1}% + \getdummyparameters[#1]% + \else + \setdummyparameter\c!name{#1}% + \fi + \dowithnextboxcs\syst_boxes_registerpattern_indeed\hbox} + +\immutable\edef\v!auto_m{-\v!auto} + +\def\syst_boxes_registerpattern_indeed + {%\finalizeobjectbox\nextbox + \edef\p_width {\dummyparameter\c!width}% + \edef\p_height {\dummyparameter\c!height}% + \edef\p_hoffset{\dummyparameter\c!hoffset}% + \edef\p_voffset{\dummyparameter\c!voffset}% + \scratchwidth \dimexpr\ifx\p_width \v!auto\wd \nextbox\else\p_width \fi\relax + \scratchheight \dimexpr\ifx\p_height \v!auto\htdp\nextbox\else\p_height \fi\relax + \scratchhoffset\dimexpr\ifx\p_hoffset\v!auto\scratchwidth /2\orelse\ifx\p_hoffset\v!auto_m-\scratchwidth /2\else\p_hoffset\fi\relax + \scratchvoffset\dimexpr\ifx\p_voffset\v!auto\scratchheight/2\orelse\ifx\p_voffset\v!auto_m-\scratchheight/2\else\p_voffset\fi\relax + \clf_registerpattern + name {\dummyparameter\c!name} + number \nextbox + width \scratchwidth + height \scratchheight + hoffset \scratchhoffset + voffset \scratchvoffset + \relax + \endgroup} + +\permanent\tolerant\protected\def\applypattern[#1]#*[#2]% + {\hbox\bgroup + \letdummyparameter\c!name \s!dummy + \letdummyparameter\c!width \zeropoint + \letdummyparameter\c!height\zeropoint + \unless\iftok{#2}\emptytoks + \setdummyparameter\c!name{#1}% + \getdummyparameters[#2]% + \orelse\ifhastok={#1}% + \getdummyparameters[#1]% + \else + \setdummyparameter\c!name{#1}% + \fi + \clf_applypattern + name {\dummyparameter\c!name} + number \nextbox + width \dimexpr\dummyparameter\c!width\relax + height \dimexpr\dummyparameter\c!height\relax + \relax + \box\nextbox + \egroup} + +\protect + +\continueifinputfile{grph-pat.mkxl} + +\nopdfcompression + +\starttext + + \registerpattern[demo]{It \darkred Works!} + + \framed[offset=overlay]{\applypattern[demo][width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=0bp,voffset=0pt]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=auto,voffset=auto]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=-auto,voffset=-auto]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + +\stoptext + diff --git a/tex/context/base/mkxl/grph-raw.mkxl b/tex/context/base/mkxl/grph-raw.mkxl new file mode 100644 index 000000000..66194551b --- /dev/null +++ b/tex/context/base/mkxl/grph-raw.mkxl @@ -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}{} + +\unprotect + +\permanent\protected\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} + +\permanent\protected\def\startbitmapimage[#1]#2\stopbitmapimage + {\bitmapimage[#1]{#2}} + +\aliased\let\stopbitmapimage\relax + +\protect \endinput diff --git a/tex/context/base/mkxl/grph-rul.mkxl b/tex/context/base/mkxl/grph-rul.mkxl new file mode 100644 index 000000000..ef65b1fe4 --- /dev/null +++ b/tex/context/base/mkxl/grph-rul.mkxl @@ -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}{} + +\unprotect + +\permanent\protected\def\frule{\relax\clf_frule} % will become a public implementer + +% 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/tex/context/base/mkxl/grph-trf.mkxl b/tex/context/base/mkxl/grph-trf.mkxl new file mode 100644 index 000000000..9e00da7a4 --- /dev/null +++ b/tex/context/base/mkxl/grph-trf.mkxl @@ -0,0 +1,1011 @@ +%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 go away. Some of +%D this is an inheritance of limited backends (some supported fractions, some +%D 1000's, some dimentions) so we calculate all of them. Nowadays scaling is always +%D available so we could simplify the code. On the other hand, we now get some extra +%D values for free. +%D +%D We could move the calculations to \LUA\ and clean up this lot anyway. On the +%D other hand, there is some danger of messing up so it has a real low priority. + +\registerctxluafile{grph-trf}{} + +% 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 + +\newconditional\c_grph_scale_swap_factor + +\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} +\installcorenamespace{scalefact} + +\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] + +\permanent\tolerant\protected\def\scale[#1]#*[#2]% + {\bgroup + % this is quite common so we might make this a helper + \ifarguments + \let\currentscale\empty + \or + \ifhastok={#1}% + \let\currentscale\empty + \setupcurrentscale[#1]% + \else + \edef\currentscale{#1}% + \fi + \or + \edef\currentscale{#1}% + \setupcurrentscale[#2]% + \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\naturalhpack{\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 + % + \glet\finalscaleboxxscale \!!plusone + \glet\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 + \ifdim\d_grph_scale_wd=\wd\nextbox + \ifdim\d_grph_scale_ht=\ht\nextbox + \ifdim\d_grph_scale_dp=\dp\nextbox + % \grph_scale_apply_nop + \else + \grph_scale_apply_yes + \fi + \else + \grph_scale_apply_yes + \fi + \else + \grph_scale_apply_yes + \fi} + +\def\grph_scale_apply_yes + {\setbox\nextbox\naturalhpack + {\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}% + \ifempty\m_grph_scale_stamp_a + \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 + \ifempty\m_grph_scale_stamp_b + % 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% + {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax} + +\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 + \ifempty\finalscaleboxxscale\let\finalscaleboxxscale\!!plusone\fi + \ifempty\finalscaleboxyscale\let\finalscaleboxyscale\!!plusone\fi} + +\let\grph_scale_calculations_report\relax + +\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 + {\ifempty\p_maxwidth \else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi + \ifempty\p_maxheight\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi + \ifempty\p_lines \else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi + \csname\??scalegrid\scaleparameter\c!grid\endcsname} + +\def\grph_scale_by_nature % where ! ! ! ! ! + {\ifempty\p_width \else \global\d_grph_scale_used_x_size\p_width \fi + \ifempty\p_height\else \global\d_grph_scale_used_y_size\p_height\fi + \ifempty\p_scale \else \c_grph_scale_used_x_scale\p_scale + \c_grph_scale_used_y_scale\p_scale \fi + \ifempty\p_xscale\else \c_grph_scale_used_x_scale\p_xscale\fi + \ifempty\p_yscale\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]}} + +%D The \typpe {min} option makes sure that the smallest available space determines +%D the max size (so we can get a bleed on the other axis): +%D +%D \startlinecorrection +%D \startcombination[nx=2,ny=2,distance=4cm] +%D {\externalfigure[hacker][factor=max,maxwidth=6cm,maxheight=6cm]} {} +%D {\externalfigure[mill] [factor=max,maxwidth=6cm,maxheight=6cm]} {} +%D {\externalfigure[hacker][factor=min,maxwidth=6cm,maxheight=6cm]} {} +%D {\externalfigure[mill] [factor=min,maxwidth=6cm,maxheight=6cm]} {} +%D \stopcombination +%D \stoplinecorrection + +\def\m_grph_scale_factor_set{\v!min,\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\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 + {\grph_scale_calculate_fact\p_factor + \settrue\c_grph_scale_scaling_done + \ifconditional\c_grph_scale_limit_factors + \ifdim\d_grph_scale_used_x_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\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 + \orelse\ifdim\d_grph_scale_used_y_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\d_grph_scale_v_size + \global\d_grph_scale_used_x_size\zeropoint + \global\d_grph_scale_used_y_size\d_grph_scale_v_size + \fi + \fi + \grph_scale_by_dimension} + +\def\grph_scale_by_scale + {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}% + \ifempty\m_grph_scale_temp \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 + % + \ifempty\p_maxwidth + \ifempty\p_maxheight + \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\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 + \ifempty\p_maxwidth \else + \ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax + \global\d_grph_scale_used_x_size\p_maxwidth + #2\relax + \fi + \fi + \ifempty\p_maxheight \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} + +\def\grph_scale_calculate_fact#1% + {\csname\??scalefact\ifcsname\??scalefact#1\endcsname#1\else\s!unknown\fi\endcsname} + +%setvalue{\??scalenorm\v!min }#1#2#3#4#5{\global#1#4} +\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} + +\setvalue{\??scalefact\v!min }{\global\settrue \c_grph_scale_swap_factor} +\setvalue{\??scalefact\s!unknown}{\global\setfalse\c_grph_scale_swap_factor} + +% \setvalue{\??scalenorm\v!min }#1#2#3#4#5% an ugly hack +% {\ifdim\d_grph_scale_used_x_size>\d_grph_scale_h_size +% \d_grph_scale_used_y_size\vsize +% \else +% \d_grph_scale_used_x_size\hsize +% \fi} + +\setvalue{\??scalenorm\v!min}#1#2#3#4#5% an ugly hack + {\d_grph_scale_used_x_size\hsize + \d_grph_scale_used_y_size\vsize} + +\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} + +\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 + {% no overflow + \edef#1{\luaexpr + {\number + \ifx#2\empty + \ifempty\p_scale \plusthousand \else + \ifnum \p_scale=\zerocount \plusthousand \else + \p_scale \fi\fi + \orelse\ifnum#2=\zerocount + \ifempty\p_scale \plusthousand \else + \ifnum \p_scale=\zerocount \plusthousand \else + \p_scale \fi\fi + \else + #2% + \fi + /1000}}} + +\def\grph_scale_apply_size + {\ifempty\p_maxheight + \d_grph_scale_outer_v_size\textheight + \ifinner + \d_grph_scale_outer_v_size \vsize % \textheight =\vsize + \scratchdimen\vsize % \scratchdimen=\textheight + \orelse\ifinsidefloat + \d_grph_scale_outer_v_size \vsize % \textheight =\vsize + \scratchdimen\vsize % \scratchdimen=\textheight + \orelse\ifinpagebody + \d_grph_scale_outer_v_size \vsize % \textheight =\vsize + \scratchdimen\vsize % \scratchdimen=\textheight + \orelse\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 + \else + \scratchdimen\p_maxheight + \d_grph_scale_outer_v_size\scratchdimen + \fi + \ifempty\p_height + \d_grph_scale_v_size\scratchdimen + \else + \d_grph_scale_v_size\p_height + \fi + \ifempty\p_width + \d_grph_scale_h_size\hsize + \else + \d_grph_scale_h_size\p_width + \fi} + +% \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 + {\ifempty\p_equalwidth \else + \scratchdimen\p_equalwidth\relax + \ifdim\d_grph_scale_wd<\scratchdimen + \setbox\nextbox\naturalhpack to \scratchdimen{\hss\box\nextbox\hss}% + \fi + \fi + \ifempty\p_equalheight \else + \scratchdimen\p_equalheight\relax + \ifdim\d_grph_scale_ht<\scratchdimen + \setbox\nextbox\naturalvpack to \scratchdimen{\vss\box\nextbox\vss}% + \fi + \fi} + +\permanent\protected\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} + +\permanent\protected\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 + \d_grph_scale_wd\wd\nextbox + \d_grph_scale_ht\ht\nextbox + \d_grph_scale_dp\dp\nextbox + \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 arbitrary content. We can +%D use \METAPOST\ to provide a non 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, 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} + +\permanent\tolerant\protected\def\clip[#1]% nb top->bottom left->right + {\bgroup + \ifparameter#1\or + \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\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\naturalhpack + {\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\naturalhpack + {\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\naturalhpack + {\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. + +\permanent\protected\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\naturalhpack + {\dostartmirroring + \hskip-\wd\nextbox + \box\nextbox + \dostopmirroring}% + \wd\nextbox\scratchdimen + \box\nextbox + \egroup} + +%D A couple of examples, demonstrating how the depth is 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 +%D +%D When we rotate over arbitrary angles, we need to relocate the resulting box +%D because rotation brings that box onto the negative axis. The calculations (mostly +%D sin and cosine) need to be tuned for the way a box is packages (i.e. the refence +%D point). A typical example of drawing, scribbling, and going back to the days of +%D school math. +%D +%D We do a bit more calculations than needed, simply because that way it's easier to +%D debug the code. + +\installcorenamespace {rotate} +\installcorenamespace {rotatelocation} +\installcorenamespace {rotatepreset} + +% todo: scratchcounters + +\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 + +\newdimen\d_grph_rotate_width +\newdimen\d_grph_rotate_height +\newdimen\d_grph_rotate_depth + +\newdimen\d_grph_rotate_saved_width +\newdimen\d_grph_rotate_saved_height +\newdimen\d_grph_rotate_saved_depth + +\newdimen\d_grph_rotate_new_width +\newdimen\d_grph_rotate_new_height +\newdimen\d_grph_rotate_new_depth + +\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 + +\permanent\tolerant\protected\def\rotate[#1]% \bgroup: \rotate kan argument zijn + {\bgroup + \ifparameter#1\or + \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} + +\permanent\protected\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 + {\naturalhpack\bgroup + \ifempty\p_rotation_rotation + \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{90}} + +\setvalue{\??rotatepreset\v!right}% + {\edef\p_rotation_rotation{270}} + +\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}% + {} + +\def\grph_rotate_finish_yes + {\begincsname\??rotatepreset\p_rotation_rotation\endcsname + \setbox\nextbox\naturalvpack{\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\naturalhpack{\hskip-.5\wd\nextbox\lower.5\ht\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\naturalvpack{\naturalhpack{\raise\dp\nextbox\box\nextbox}}% can we do without + % + \d_grph_rotate_used_height\ht\nextbox + % + \clf_analyzerotate % rather accurate + \p_rotation_rotation\space + \d_grph_rotate_width + \d_grph_rotate_height + \d_grph_rotate_depth + \d_grph_rotate_used_height + \c_grph_rotate_not_fit + \c_grph_rotate_obey_depth + \relax + % + \setbox\nextbox\naturalvpack to \d_grph_rotate_y_size + {\vfilll + \naturalhpack 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\naturalhpack + {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax + \lower\d_grph_rotate_y_offset + \box\nextbox}% + % + \ifconditional\c_grph_rotate_center + \setbox\nextbox\naturalhpack{\hskip.5\d_grph_rotate_saved_width\lower-.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 + \else + \wd\nextbox\d_grph_rotate_new_width + \ht\nextbox\d_grph_rotate_new_height + \dp\nextbox\d_grph_rotate_new_depth + \fi + % + \boxcursor\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} + +% \def\Test{\ruledhbox{% +% \def\DemoX{\vl\kern.5\emwidth\vl}% +% \kern\emwidth\ruledhpack{\green\rotate[rotation=20] {\ruledhpack{\DemoX}}}% +% \kern\emwidth\ruledhpack{\blue \rotate[rotation=0] {\ruledhpack{\DemoX}}}% +% \kern\emwidth\ruledhpack{\red \rotate[rotation=-20] {\ruledhpack{\DemoX}}}% +% \kern\emwidth\ruledhpack{\green\rotate[rotation=200] {\ruledhpack{\DemoX}}}% +% \kern\emwidth\ruledhpack{\blue \rotate[rotation=180] {\ruledhpack{\DemoX}}}% +% \kern\emwidth\ruledhpack{\red \rotate[rotation=-200]{\ruledhpack{\DemoX}}}% +% \kern\emwidth}} + +% \startTEXpage[offset=10pt,align=middle] +% \setuprotate[location=fit] \Test \par {\infofont\setstrut\strut fit} \par +% \setuprotate[location=depth] \Test \par {\infofont\setstrut\strut depth} \par +% \setuprotate[location=broad] \Test \par {\infofont\setstrut\strut broad} \par +% \setuprotate[location=high] \Test \par {\infofont\setstrut\strut high} \par +% \setuprotate[location=middle] \Test \par {\infofont\setstrut\strut middle} \par +% \setuprotate[location=default] \Test \par {\infofont\setstrut\strut default} \par +% \stopTEXpage + +\protect \endinput diff --git a/tex/context/base/mkxl/hand-ini.mkxl b/tex/context/base/mkxl/hand-ini.mkxl new file mode 100644 index 000000000..3fd82f239 --- /dev/null +++ b/tex/context/base/mkxl/hand-ini.mkxl @@ -0,0 +1,113 @@ +%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 Probbaly not yet used by many. + +\permanent\tolerant\protected\def\setupfontexpansion [#1]#*[#2]{\clf_setupfontexpansion {#1}{#2}} +\permanent\tolerant\protected\def\setupfontprotrusion[#1]#*[#2]{\clf_setupfontprotrusion{#1}{#2}} + +% \setupfontprotrusion[quality-upright][vector=quality] +% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5] + +\pushoverloadmode + + \let\adjustspacing\relax \newcount\adjustspacing % a little bit protection + \let\protrudechars\relax \newcount\protrudechars % a little bit protection + +\popoverloadmode + +%D At some point we can introduce extreme expansion, i.e. \type {\normaladjustspacing\plustwo}. + +% 0 = disabled +% 1 = notused (thesis) +% 2 = glyph + kern +% 3 = glyph only (default) + +\def\font_expansion_enable {\normaladjustspacing\plusthree} +\def\font_expansion_enable_k{\normaladjustspacing\plustwo} +%def\font_expansion_enable_n{\normaladjustspacing\plusone} +\def\font_expansion_disable {\normaladjustspacing\zerocount} + +\def\font_protruding_enable_b{\normalprotrudechars\plusthree} % also deal with r2l (experimental lmtx) +\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 +% +% \protected\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen +% \protected\def\definefonthandling {\dotripleempty\dodefinefonthandling} +% \protected\def\setupfonthandling {\dodoubleempty\dosetupfonthandling } +% \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror} +% \def\dosetupfonthandling [#1][#2]{\fonthandlingerror} +% \def\usehandling [#1]{\fonthandlingerror} + +\installcorenamespace{expansion} + +\installcommandhandler \??expansion {expansion} \??expansion + +\appendtoks + \setuevalue{\??expansion:\currentexpansion}% + {\adjustspacingstep \expansionparameter\c!step\relax + \adjustspacingstretch\expansionparameter\c!stretch\relax + \adjustspacingshrink \expansionparameter\c!shrink\relax}% +\to \everydefineexpansion + +\setupexpansion + [\c!step=1, + \c!stretch=40, + \c!shrink=20] + +% \defineexpansion +% [myexpansion] +% [\c!stretch=50, +% \c!shrink=20] + +\permanent\tolerant\protected\def\setexpansion[#1]{\begincsname\??expansion:#1\endcsname} + +%D New in \LMTX: can be used grouped. + +\permanent\protected\def\noexpansion {\bitwiseflip\glyphoptions\noexpansioncode} +\permanent\protected\def\noprotrusion{\bitwiseflip\glyphoptions\noprotrusioncode} + +\protect \endinput diff --git a/tex/context/base/mkxl/java-ini.mkxl b/tex/context/base/mkxl/java-ini.mkxl new file mode 100644 index 000000000..513dc20e3 --- /dev/null +++ b/tex/context/base/mkxl/java-ini.mkxl @@ -0,0 +1,157 @@ +%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}{} + +\unprotect + +%D \macros +%D {JS*} +%D +%D Because \JAVASCRIPT's are activated by the user, for instance by activating on a +%D button, their support is closely related to the referencing mechanism. +%D Integration takes 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, the keyword is +%D treated as a normal reference. 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 always loaded, the +%D next definition also tells \CONTEXT\ to actually include the preamble needed. +%D +%D \starttyping +%D \startJScode{uses} used {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 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 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 the first page is +%D shipped out. +%D +%D \macros +%D {setJSpreamble, addtoJSpreamble} +%D +%D In addition to the previous preamble definitions, we can set a preamble \quote +%D {in||line} and add tokens to a preamble. +%D +%D \macros +%D {useJSpreamblenow} +%D +%D This macro can be used to force inclusion of postponed \JAVASCRIPT\ preambles. + +\def\m_java_escape_u{\letterbackslash u} + +\permanent\protected\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}}} + +\aliased\let\stopJScode\relax + +\permanent\protected\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}}} + +\aliased\let\stopJSpreamble\relax + +\permanent\protected\def\setJSpreamble #1#2{\clf_setjavascriptpreamble {#1}{#2}} +\permanent\protected\def\addtoJSpreamble#1#2{\clf_addtojavascriptpreamble{#1}{#2}} + +%D \macros +%D {useJSscripts} +%D +%D In due time, users will build their collections of scripts, which can be used +%D (loaded) when applicable. Although not all public, we will provide some general +%D purpose scripts, 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: + +\permanent\tolerant\protected\def\useJSscripts[#1]#*[#2]% + {\clf_usejavascriptscripts {#1}% two steps as this one calls tex code + \clf_usejavascriptpreamble{#2}}% so this one comes later + +\permanent\tolerant\protected\def\useJSpreamble[#1]% + {\clf_usejavascriptpreamble{#1}}% so this one comes later + +%D Here: + +\definefilesynonym[java-imp-fld.mkiv] [java-imp-fields.mkiv] +\definefilesynonym[java-imp-stp.mkiv] [java-imp-steps.mkiv] +\definefilesynonym[java-imp-fil.mkiv] [java-imp-print.mkiv] +\definefilesynonym[java-imp-rhh.mkiv] [java-imp-highlight.mkiv] +\definefilesynonym[java-imp-exa.mkiv] [java-imp-example.mkiv] + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-def.mkxl b/tex/context/base/mkxl/lang-def.mkxl new file mode 100644 index 000000000..5698bb4af --- /dev/null +++ b/tex/context/base/mkxl/lang-def.mkxl @@ -0,0 +1,800 @@ +%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!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!nl] + [\c!spacing=\v!packed, + \c!leftsentence=\emdash, + \c!rightsentence=\emdash, + \c!leftsubsentence=\emdash, + \c!rightsubsentence=\emdash, + \c!leftquote=\lowerleftsingleninequote, + \c!rightquote=\upperrightsingleninequote, + \c!leftquotation=\lowerleftdoubleninequote, + \c!rightquotation=\upperrightdoubleninequote, + \c!date={\v!day,\space,\v!month,\space,\v!year}] + +\installlanguage + [\s!de] + [\c!spacing=\v!packed, + \s!lefthyphenmin=3, + \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!command=\v!no, + \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!et] + [\c!default=\s!en, + \c!spacing=\v!packed, + \c!leftsentence=\emdash, + \c!rightsentence=\emdash, + \c!leftsubsentence=\emdash, + \c!rightsubsentence=\emdash, + \c!leftquote=\leftguillemot, + \c!rightquote=\rightguillemot, + \c!leftquotation=\lowerrightdoubleninequote, + \c!rightquotation=\upperrightdoublesixquote, + \c!time={h,{.},m}, + \c!date={\v!day,.,\space,\v!month,\space,\v!year}, + \s!patterns=\s!et] + +\installlanguage + [\s!hu] + [\c!spacing=\v!packed, + \c!leftsentence=\emdash, + \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!finnish] [\s!fi] +\installlanguage [\s!estonian] [\s!et] +\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 + +% Hebrew + +\installlanguage % same as arabic now .. someone needs to fix this + [\s!he] + [\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 % same as arabic now .. someone needs to fix this + [\s!yi] + [\s!he] + +\installlanguage [\s!hebrew] [\s!he] +\installlanguage [\s!yiddish] [\s!yi] + +% 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] + +\installlanguage + [\s!pe] + [\c!spacing=\v!broad, + \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,\space,\v!month,\space,\v!year}] + +\installlanguage [\s!persian] [\s!pe] +\installlanguage [\s!fa] [\s!pe] % these two are redundant but sometimes might +\installlanguage [\s!farsi] [\s!fa] % sound more natural .. best set labels to 'pe' + +% 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 + +% Farsi (Persian) + +\installlanguage[\s!ar-ir][\c!default=\s!pe] +%installlanguage[\s!pe-ir][\c!default=\s!pe] +%installlanguage[\s!fa-ir][\c!default=\s!fa] + +% 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 + +\installlanguage + [\s!esperanto] + [%\c!spacing=\v!packed, + %\c!leftsentence=\emdash, + %\c!rightsentence=\emdash, + %\c!leftsubsentence=\emdash, + %\c!rightsubsentence=\emdash, + %\c!leftquote=\lowerleftdoubleninequote, + %\c!rightquote=\upperrightdoublesixquote, + %\c!leftquotation=\lowerleftdoubleninequote, + %\c!rightquotation=\upperrightdoublesixquote, + %\c!date={\v!year,~m.,\space,\v!month,\space,\v!day,~d.}, + \s!patterns=eo, + \s!lefthyphenmin=2, + \s!righthyphenmin=2] + +% Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian + +\installlanguage + [\s!lt] + [\c!command=\v!no, + \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 + +% CJK: Chinese, Japanese, Korean + +\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}}] + +\installlanguage [\s!chinese] [\s!cn] +\installlanguage [\s!japanese] [\s!ja] +\installlanguage [\s!korean] [\s!kr] + +% Greek + +\installlanguage + [\s!gr] + [\c!spacing=\v!packed, + \c!leftsentence=\emdash, + \c!rightsentence=\emdash, + \c!leftsubsentence=\emdash, + \c!rightsubsentence=\emdash, + \c!leftquote=“, + \c!rightquote=”, + \c!leftquotation=«, + \c!rightquotation=», + \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!time={h,{\Uchar104 },m},% we need to cheat in order to get the h + \c!date={\v!day:mnem,\v!space,\v!month,\v!space,\v!year}] + +\installlanguage + [\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!command=\v!no, + \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/tex/context/base/mkxl/lang-dis.lmt b/tex/context/base/mkxl/lang-dis.lmt new file mode 100644 index 000000000..263225691 --- /dev/null +++ b/tex/context/base/mkxl/lang-dis.lmt @@ -0,0 +1,222 @@ +if not modules then modules = { } end modules ['lang-dis'] = { + version = 1.001, + comment = "companion to lang-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local concat = table.concat + +local tex = tex +local nodes = nodes + +local tasks = nodes.tasks +local nuts = nodes.nuts + +local enableaction = tasks.enableaction +local setaction = tasks.setaction + +local setfield = nuts.setfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getattr = nuts.getattr +local getsubtype = nuts.getsubtype +local setsubtype = nuts.setsubtype +local getchar = nuts.getchar +local setchar = nuts.setchar +local getdisc = nuts.getdisc +local setdisc = nuts.setdisc +local getlanguage = nuts.getlanguage +local getboth = nuts.getboth +local setlist = nuts.setlist +local setlink = nuts.setlink +local isglyph = nuts.isglyph + +local copy_node = nuts.copy +local remove_node = nuts.remove +local flush_list = nuts.flush_list +local flush_node = nuts.flush_node + +local nextdisc = nuts.traversers.disc + +local new_disc = nuts.pool.disc + +local nodecodes = nodes.nodecodes +local disccodes = nodes.disccodes + +local disc_code = nodecodes.disc +local glyph_code = nodecodes.glyph + +local explicitdisc_code = disccodes.explicit + +local a_visualize = attributes.private("visualizediscretionary") +local setattribute = tex.setattribute + +local getlanguagedata = languages.getdata +local prehyphenchar = language.prehyphenchar +local posthyphenchar = language.posthyphenchar + +local check_regular = true + +local setlistcolor = nodes.tracers.colors.setlist + +function languages.visualizediscretionaries(head) + for d in nextdisc, head do + if getattr(d,a_visualize) then + local pre, post, replace = getdisc(d) + if pre then + setlistcolor(pre,"darkred") + end + if post then + setlistcolor(post,"darkgreen") + end + if replace then + setlistcolor(replace,"darkblue") + end + end + end + return head +end + +local enabled = false + +function languages.showdiscretionaries(v) + if v == false then + setattribute(a_visualize,unsetvalue) + else -- also nil + if not enabled then + enableaction("processors","languages.visualizediscretionaries") + enabled = true + end + setattribute(a_visualize,1) + end +end + +interfaces.implement { + name = "showdiscretionaries", + actions = languages.showdiscretionaries +} + +do + + local toutf = nodes.listtoutf + local utfchar = utf.char + local f_disc = string.formatters["{%s}{%s}{%s}"] + local replace = lpeg.replacer( { + [utfchar(0x200C)] = "|", + [utfchar(0x200D)] = "|", + }, nil, true) + + local function convert(list) + return list and replace(toutf(list)) or "" + end + + function languages.serializediscretionary(d) -- will move to tracer + local pre, post, replace = getdisc(d) + return f_disc(convert(pre),convert(post),convert(replace)) + end + +end + +-- -- + +local wiped = 0 + +local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes + +-- if flatten_discretionaries then + + function languages.flatten(head) + local h, n = flatten_discretionaries(head) + wiped = wiped + n + return h, n > 0 + end + +-- else +-- +-- local function wipe(head,delayed) +-- local p, n = getboth(delayed) +-- local _, _, h, _, _, t = getdisc(delayed,true) +-- if p or n then +-- if h then +-- setlink(p,h) +-- setlink(t,n) +-- setfield(delayed,"replace") +-- else +-- setlink(p,n) +-- end +-- end +-- if head == delayed then +-- head = h +-- end +-- wiped = wiped + 1 +-- flush_node(delayed) +-- return head +-- end +-- +-- function languages.flatten(head) +-- local delayed = nil +-- for d in nextdisc, head do +-- if delayed then +-- head = wipe(head,delayed) +-- end +-- delayed = d +-- end +-- if delayed then +-- return wipe(head,delayed), true +-- else +-- return head, false +-- end +-- end +-- +-- end + +function languages.nofflattened() + return wiped -- handy for testing +end + +-- experiment: for now not in not in export mode! + +local flatten = languages.flatten + +nodes.handlers.flattenline = flatten + +function nodes.handlers.flatten(head,where) + if head and (where == "box" or where == "adjusted_hbox") then + return flatten(head) + end + return head +end + +directives.register("hyphenator.flatten",function(v) + -- use with care + setaction("processors","nodes.handlers.flatten",v) + setaction("contributers","nodes.handlers.flattenline",v) +end) + +-- moved here: + +function languages.explicithyphen(template) + local pre, post + local disc = new_disc() + if template then + local langdata = getlanguagedata(getlanguage(template)) + local instance = langdata and langdata.instance + if instance then + local prechr = prehyphenchar(instance) + local postchr = posthyphenchar(instance) + if prechr >= 0 then + pre = copy_node(template) + setchar(pre,prechr) + end + if postchr >= 0 then + post = copy_node(template) + setchar(post,postchr) + end + end + end + setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty) + return disc +end diff --git a/tex/context/base/mkxl/lang-frd.mkxl b/tex/context/base/mkxl/lang-frd.mkxl new file mode 100644 index 000000000..352e5016d --- /dev/null +++ b/tex/context/base/mkxl/lang-frd.mkxl @@ -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/tex/context/base/mkxl/lang-frq.mkxl b/tex/context/base/mkxl/lang-frq.mkxl new file mode 100644 index 000000000..07bc1654d --- /dev/null +++ b/tex/context/base/mkxl/lang-frq.mkxl @@ -0,0 +1,234 @@ +%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 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. + +\setnewconstant\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} + +\aliased\let\stopcharactertable\relax + +\permanent\protected\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. + +\permanent\def\charactertable#1% + {\csname\??frequencywidths\ifcsname\??frequencywidths#1\endcsname#1\else\s!en\fi\endcsname} + +\permanent\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)). + +\permanent\def\averagecharwidth{\dimexpr(\zeropoint\charactertable\charwidthlanguage)/100\relax} + +\permanent\protected\def\showcharfreq + {\hbox\bgroup + \charwidthlanguage:% + \dostepwiserecurse\zerocount\plusfour\plusone + {\setconstant\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. + +\aliased\let\normalaveragecharacterwidth\averagecharacterwidth + +\permanent\def\freezeaveragecharacterwidth % global + {\enforced\xdef\averagecharacterwidth{\dimexpr\the\normalaveragecharacterwidth\relax}} + +%D Example: +%D +%D \starttyping +%D \input lang-frq.mkiv +%D \input lang-frd.mkiv +%D +%D \setupbodyfont +%D [dejavu] +%D +%D \setemeasure{textwidth}{\the\dimexpr70\averagecharwidth} +%D +%D \setuplayout +%D [width=\measure{textwidth}] +%D +%D \showframe +%D +%D \starttext +%D \input ward +%D \stoptext +%D \stoptyping + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-hyp.lmt b/tex/context/base/mkxl/lang-hyp.lmt new file mode 100644 index 000000000..c2862f536 --- /dev/null +++ b/tex/context/base/mkxl/lang-hyp.lmt @@ -0,0 +1,1806 @@ +if not modules then modules = { } end modules ['lang-hyp'] = { + version = 1.001, + comment = "companion to lang-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- In an automated workflow hypenation of long titles can be somewhat problematic +-- especially when demands conflict. For that reason I played a bit with a Lua based +-- variant of the traditional hyphenation machinery. This mechanism has been extended +-- several times in projects, of which a good description can be found in TUGboat, +-- Volume 27 (2006), No. 2 — Proceedings of EuroTEX2006: Automatic non-standard +-- hyphenation in OpenOffice.org by László Németh. +-- +-- Being the result of two days experimenting the following implementation is probably +-- not completely okay yet. If there is demand I might add some more features and plugs. +-- The performance is quite okay but can probably improved a bit, although this is not +-- the most critital code. For instance, on a metafun manual run the overhead is about +-- 0.3 seconds on 19 seconds which is not that bad. +-- +-- In the procecess of wrapping up (for the ctx conference proceedings) I cleaned up +-- and extended the code a bit. It can be used in production. +-- +-- . a l g o r i t h m . +-- 4l1g4 +-- l g o3 +-- 1g o +-- 2i t h +-- 4h1m +-- --------------------- +-- 4 1 4 3 2 0 4 1 +-- a l-g o-r i t h-m + +-- . a s s z o n n y a l . +-- s1s z/sz=sz,1,3 +-- n1n y/ny=ny,1,3 +-- ----------------------- +-- 0 1 0 0 0 1 0 0 0/sz=sz,2,3,ny=ny,6,3 +-- a s-s z o n-n y a l/sz=sz,2,3,ny=ny,6,3 +-- +-- ab1cd/ef=gh,2,2 : acd - efd (pattern/replacement,start,length +-- +-- todo : support hjcodes (<32 == length) like luatex does now (no need/demand so far) +-- maybe : support hyphenation over range (can alsready be done using attributes/language) +-- maybe : reset dictionary.hyphenated when a pattern is added and/or forced reset option +-- todo : check subtypes (because they have subtle meanings in the line breaking) +-- +-- word start (in tex engine): +-- +-- boundary : yes when wordboundary +-- hlist : when hyphenationbounds 1 or 3 +-- vlist : when hyphenationbounds 1 or 3 +-- rule : when hyphenationbounds 1 or 3 +-- dir : when hyphenationbounds 1 or 3 +-- whatsit : when hyphenationbounds 1 or 3 +-- glue : yes +-- math : skipped +-- glyph : exhyphenchar (one only) : yes (so no -- ---) +-- otherwise : yes +-- +-- word end (in tex engine): +-- +-- boundary : yes +-- glyph : yes when different language +-- glue : yes +-- penalty : yes +-- kern : yes when not italic (for some historic reason) +-- hlist : when hyphenationbounds 2 or 3 +-- vlist : when hyphenationbounds 2 or 3 +-- rule : when hyphenationbounds 2 or 3 +-- dir : when hyphenationbounds 2 or 3 +-- whatsit : when hyphenationbounds 2 or 3 +-- ins : when hyphenationbounds 2 or 3 +-- adjust : when hyphenationbounds 2 or 3 + +local type, rawget, rawset, tonumber, next = type, rawget, rawset, tonumber, next + +local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs +local lpegmatch = lpeg.match + +local context = context + +local concat = table.concat +local insert = table.insert +local remove = table.remove +local formatters = string.formatters +local utfchar = utf.char +local utfbyte = utf.byte + +if not characters then + require("char-ini") +end + +local setmetatableindex = table.setmetatableindex + +-- \enabletrackers[hyphenator.steps=silent] will not write to the terminal + +local trace_steps = false trackers.register("hyphenator.steps", function(v) trace_steps = v end) +local trace_visualize = false trackers.register("hyphenator.visualize",function(v) trace_visualize = v end) + +local report = logs.reporter("hyphenator") + +local implement = interfaces and interfaces.implement or function() end + +languages = languages or { } +local hyphenators = languages.hyphenators or { } +languages.hyphenators = hyphenators +local traditional = hyphenators.traditional or { } +hyphenators.traditional = traditional + +local dictionaries = setmetatableindex(function(t,k) + local v = { + patterns = { }, + hyphenated = { }, + specials = { }, + exceptions = { }, + loaded = false, + } + t[k] = v + return v +end) + +hyphenators.dictionaries = dictionaries + +local character = lpeg.patterns.utf8character +local digit = R("09") +local weight = digit/tonumber + Cc(0) +local fence = P(".") +local hyphen = P("-") +local space = P(" ") +local char = character - space +local validcharacter = (character - S("./")) +local keycharacter = character - S("/") +----- basepart = Ct( (Cc(0) * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc(0))^-1) +local specpart = (P("/") * Cf ( Ct("") * + Cg ( Cc("before") * C((1-P("="))^1) * P("=") ) * + Cg ( Cc("after") * C((1-P(","))^1) ) * + ( P(",") * + Cg ( Cc("start") * ((1-P(","))^1/tonumber) * P(",") ) * + Cg ( Cc("length") * ((1-P(-1) )^1/tonumber) ) + )^-1 + , rawset))^-1 + +local make_hashkey_p = Cs((digit/"" + keycharacter)^1) +----- make_pattern_p = basepart * specpart +local make_hashkey_e = Cs((hyphen/"" + keycharacter)^1) +local make_pattern_e = Ct(P(char) * (hyphen * Cc(true) * P(char) + P(char) * Cc(false))^1) -- catch . and char after - + +-- local make_hashkey_c = Cs((digit + keycharacter/"")^1) +-- local make_pattern_c = Ct((P(1)/tonumber)^1) + +-- local cache = setmetatableindex(function(t,k) +-- local n = lpegmatch(make_hashkey_c,k) +-- local v = lpegmatch(make_pattern_c,n) +-- t[k] = v +-- return v +-- end) +-- +-- local weight_n = digit + Cc("0") +-- local basepart_n = Cs( (Cc("0") * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc("0"))^-1) / cache +-- local make_pattern_n = basepart_n * specpart + +local make_pattern_c = Ct((P(1)/tonumber)^1) + +-- us + nl: 17664 entries -> 827 unique (saves some 3M) + +local cache = setmetatableindex(function(t,k) + local v = lpegmatch(make_pattern_c,k) + t[k] = v + return v +end) + +local weight_n = digit + Cc("0") +local fence_n = fence / "0" +local char_n = validcharacter / "" +local basepart_n = Cs(fence_n^-1 * (weight_n * char_n)^1 * weight_n * fence_n^-1) / cache +local make_pattern_n = basepart_n * specpart + +local function register_pattern(patterns,specials,str,specification) + local k = lpegmatch(make_hashkey_p,str) + -- local v1, v2 = lpegmatch(make_pattern_p,str) + local v1, v2 = lpegmatch(make_pattern_n,str) + patterns[k] = v1 -- is this key still ok for complex patterns + if specification then + specials[k] = specification + elseif v2 then + specials[k] = v2 + end +end + +local function unregister_pattern(patterns,specials,str) + local k = lpegmatch(make_hashkey_p,str) + patterns[k] = nil + specials[k] = nil +end + +local p_lower = lpeg.patterns.utf8lower + +local function register_exception(exceptions,str,specification) + local l = lpegmatch(p_lower,str) + local k = lpegmatch(make_hashkey_e,l) + local v = lpegmatch(make_pattern_e,l) + exceptions[k] = v +end + +local p_pattern = ((Carg(1) * Carg(2) * C(char^1)) / register_pattern + 1)^1 +local p_exception = ((Carg(1) * C(char^1)) / register_exception + 1)^1 +local p_split = Ct(C(character)^1) + +function traditional.loadpatterns(language,filename) + local dictionary = dictionaries[language] + if not dictionary.loaded then + if not filename or filename == "" then + filename = "lang-" .. language + end + filename = file.addsuffix(filename,"lua") + local fullname = resolvers.findfile(filename) + if fullname and fullname ~= "" then + local specification = dofile(fullname) + if specification then + local patterns = specification.patterns + if patterns then + local data = patterns.data + if data and data ~= "" then + lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) + end + end + local exceptions = specification.exceptions + if exceptions then + local data = exceptions.data + if data and data ~= "" then + lpegmatch(p_exception,data,1,dictionary.exceptions) + end + end + end + end + dictionary.loaded = true + end + return dictionary +end + +local lcchars = characters.lcchars +local uccodes = characters.uccodes +local categories = characters.categories +local nofwords = 0 +local nofhashed = 0 + +local steps = nil +local f_show = formatters["%w%s"] + +local function show_log() + if trace_steps == true then + report() + local w = #steps[1][1] + for i=1,#steps do + local s = steps[i] + report("%s%w%S %S",s[1],w - #s[1] + 3,s[2],s[3] or "") + end + report() + end +end + +local function show_1(wsplit) + local u = concat(wsplit," ") + steps = { { f_show(0,u), f_show(0,u) } } +end + +local function show_2(c,m,wsplit,done,i,spec) + local s = lpegmatch(p_split,c) + local t = { } + local n = #m + local w = #wsplit + for j=1,n do + t[#t+1] = m[j] + t[#t+1] = s[j] + end + local m = 2*i-2 + local l = #t + local s = spec and table.sequenced(spec) or "" + if m == 0 then + steps[#steps+1] = { f_show(m, concat(t,"",2)), f_show(1,concat(done," ",2,#done),s) } + elseif i+1 == w then + steps[#steps+1] = { f_show(m-1,concat(t,"",1,#t-1)), f_show(1,concat(done," ",2,#done),s) } + else + steps[#steps+1] = { f_show(m-1,concat(t)), f_show(1,concat(done," ",2,#done),s) } + end +end + +local function show_3(wsplit,done) + local t = { } + local h = { } + local n = #wsplit + for i=1,n do + local w = wsplit[i] + if i > 1 then + local d = done[i] + t[#t+1] = i > 2 and d % 2 == 1 and "-" or " " + h[#h+1] = d + end + t[#t+1] = w + h[#h+1] = w + end + steps[#steps+1] = { f_show(0,concat(h)), f_show(0,concat(t)) } + show_log() +end + +local function show_4(wsplit,done) + steps = { { concat(wsplit," ") } } + show_log() +end + +function traditional.lasttrace() + return steps +end + +-- We could reuse the w table but as we cache the resolved words there is not much gain in +-- that complication. +-- +-- Beware: word can be a table and when n is passed to we can assume reuse so we need to +-- honor that n then. +-- +-- todo: a fast variant for tex ... less lookups (we could check is dictionary has changed) +-- ... although due to caching the already done words, we don't do much here + +local function hyphenate(dictionary,word,n) -- odd is okay + nofwords = nofwords + 1 + local hyphenated = dictionary.hyphenated + local isstring = type(word) == "string" + if isstring then + local done = hyphenated[word] + if done ~= nil then + return done + end + elseif n then + local done = hyphenated[concat(word,"",1,n)] + if done ~= nil then + return done + end + else + local done = hyphenated[concat(word)] + if done ~= nil then + return done + end + end + local key + if isstring then + key = word + word = lpegmatch(p_split,word) + if not n then + n = #word + end + else + if not n then + n = #word + end + key = concat(word,"",1,n) + end + local l = 1 + local w = { "." } + -- local d = dictionary.codehash + for i=1,n do + local c = word[i] + -- l = l + (d[c] or 1) + l = l + 1 + w[l] = lcchars[c] or c + end + l = l + 1 + w[l] = "." + local c = concat(w,"",2,l-1) + -- + local done = hyphenated[c] + if done ~= nil then + hyphenated[key] = done + nofhashed = nofhashed + 1 + return done + end + -- + local exceptions = dictionary.exceptions + local exception = exceptions[c] + if exception then + if trace_steps then + show_4(w,exception) + end + hyphenated[key] = exception + nofhashed = nofhashed + 1 + return exception + end + -- + if trace_steps then + show_1(w) + end + -- + local specials = dictionary.specials + local patterns = dictionary.patterns + -- + local spec + for i=1,l do + for j=i,l do + local c = concat(w,"",i,j) + local m = patterns[c] + if m then + local s = specials[c] + if not done then + done = { } + spec = nil + -- the string that we resolve has explicit fences (.) so done starts at + -- the first fence and runs upto the last one so we need one slot less + for i=1,l do + done[i] = 0 + end + end + -- we run over the pattern that always has a (zero) value for each character + -- plus one more as we look at both sides + for k=1,#m do + local new = m[k] + if not new then + break + elseif new == true then + report("fatal error") + break + elseif new > 0 then + local pos = i + k - 1 + local old = done[pos] + if not old then + -- break ? + elseif new > old then + done[pos] = new + if s then + local b = i + (s.start or 1) - 1 + if b > 0 then + local e = b + (s.length or 2) - 1 + if e > 0 then + if pos >= b and pos <= e then + if spec then + spec[pos] = { s, k - 1 } + else + spec = { [pos] = { s, k - 1 } } + end + end + end + end + end + end + end + end + if trace_steps and done then + show_2(c,m,w,done,i,s) + end + end + end + end + if trace_steps and done then + show_3(w,done) + end + if done then + local okay = false + for i=3,#done do + if done[i] % 2 == 1 then + done[i-2] = spec and spec[i] or true + okay = true + else + done[i-2] = false + end + end + if okay then + done[#done] = nil + done[#done] = nil + else + done = false + end + else + done = false + end + hyphenated[key] = done + nofhashed = nofhashed + 1 + return done +end + +function traditional.gettrace(language,word) + if not word or word == "" then + return + end + local dictionary = dictionaries[language] + if dictionary then + local hyphenated = dictionary.hyphenated + hyphenated[word] = nil + hyphenate(dictionary,word) + return steps + end +end + +local methods = setmetatableindex(function(t,k) local v = hyphenate t[k] = v return v end) + +function traditional.installmethod(name,f) + if rawget(methods,name) then + report("overloading %a is not permitted",name) + else + methods[name] = f + end +end + +local s_detail_1 = "-" +local f_detail_2 = formatters["%s-%s"] +local f_detail_3 = formatters["{%s}{%s}{}"] +local f_detail_4 = formatters["{%s%s}{%s%s}{%s}"] + +function traditional.injecthyphens(dictionary,word,specification) + if not word then + return false + end + if not specification then + return word + end + local hyphens = hyphenate(dictionary,word) + if not hyphens then + return word + end + + -- the following code is similar to code later on but here we have strings while there + -- we have hyphen specs + + local word = lpegmatch(p_split,word) + local size = #word + + local leftmin = specification.leftcharmin or 2 + local rightmin = size - (specification.rightcharmin or leftmin) + local leftchar = specification.leftchar + local rightchar = specification.rightchar + + local result = { } + local rsize = 0 + local position = 1 + + while position <= size do + if position >= leftmin and position <= rightmin then + local hyphen = hyphens[position] + if not hyphen then + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + elseif hyphen == true then + rsize = rsize + 1 + result[rsize] = word[position] + rsize = rsize + 1 + if leftchar and rightchar then + result[rsize] = f_detail_3(rightchar,leftchar) + else + result[rsize] = s_detail_1 + end + position = position + 1 + else + local o, h = hyphen[2] + if o then + h = hyphen[1] + else + h = hyphen + o = 1 + end + local b = position - o + (h.start or 1) + local e = b + (h.length or 2) - 1 + if b > 0 and e >= b then + for i=1,b-position do + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + rsize = rsize + 1 + if leftchar and rightchar then + result[rsize] = f_detail_4(h.before,rightchar,leftchar,h.after,concat(word,"",b,e)) + else + result[rsize] = f_detail_2(h.before,h.after) + end + position = e + 1 + else + -- error + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + else + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + return concat(result) +end + +do + + local word = C((1-space)^1) + local spaces = space^1 + + local u_pattern = (Carg(1) * Carg(2) * word / unregister_pattern + spaces)^1 + local r_pattern = (Carg(1) * Carg(2) * word * Carg(3) / register_pattern + spaces)^1 + local e_pattern = (Carg(1) * word / register_exception + spaces)^1 + + function traditional.registerpattern(language,str,specification) + local dictionary = dictionaries[language] + if specification == false then + lpegmatch(u_pattern,str,1,dictionary.patterns,dictionary.specials) + -- unregister_pattern(dictionary.patterns,dictionary.specials,str) + else + lpegmatch(r_pattern,str,1,dictionary.patterns,dictionary.specials,type(specification) == "table" and specification or false) + -- register_pattern(dictionary.patterns,dictionary.specials,str,specification) + end + end + + function traditional.registerexception(language,str) + lpegmatch(e_pattern,str,1,dictionaries[language].exceptions) + end + +end + +-- todo: unicodes or utfhash ? + +if context then + + local nodecodes = nodes.nodecodes + local disccodes = nodes.disccodes + + local glyph_code = nodecodes.glyph + local disc_code = nodecodes.disc + local math_code = nodecodes.math + local hlist_code = nodecodes.hlist + + local automaticdisc_code = disccodes.automatic + local regulardisc_code = disccodes.regular + + local nuts = nodes.nuts + local tonode = nodes.tonode + local nodepool = nuts.pool + + local new_disc = nodepool.disc + local new_penalty = nodepool.penalty + + local getfield = nuts.getfield + local getfont = nuts.getfont + local getid = nuts.getid + local getattr = nuts.getattr + local getnext = nuts.getnext + local getprev = nuts.getprev + local getsubtype = nuts.getsubtype + local getlist = nuts.getlist + local getlanguage = nuts.getlanguage + local getattrlist = nuts.getattrlist + local setattrlist = nuts.setattrlist + local isglyph = nuts.isglyph + local ischar = nuts.ischar + + local setchar = nuts.setchar + local setdisc = nuts.setdisc + local setlink = nuts.setlink + local setprev = nuts.setprev + local setnext = nuts.setnext + + local insert_before = nuts.insert_before + local insert_after = nuts.insert_after + local copy_node = nuts.copy + local copy_list = nuts.copy_list + local remove_node = nuts.remove + local end_of_math = nuts.end_of_math + local node_tail = nuts.tail + + local nexthlist = nuts.traversers.hlist + local nextdisc = nuts.traversers.disc + + local setcolor = nodes.tracers.colors.set + + local variables = interfaces.variables + local v_reset = variables.reset + local v_yes = variables.yes + local v_word = variables.word + local v_all = variables.all + + local settings_to_array = utilities.parsers.settings_to_array + + local unsetvalue = attributes.unsetvalue + local texsetattribute = tex.setattribute + + local prehyphenchar = language.prehyphenchar + local posthyphenchar = language.posthyphenchar + local preexhyphenchar = language.preexhyphenchar + local postexhyphenchar = language.postexhyphenchar + + local a_hyphenation = attributes.private("hyphenation") + + local interwordpenalty = 5000 + + function traditional.loadpatterns(language) + return dictionaries[language] + end + + -- for the moment we use an independent data structure + + setmetatableindex(dictionaries,function(t,k) + if type(k) == "string" then + -- this will force a load if not yet loaded (we need a nicer way) for the moment + -- that will do (nneeded for examples that register a pattern specification + languages.getnumber(k) + end + local specification = languages.getdata(k) + local dictionary = { + patterns = { }, + exceptions = { }, + hyphenated = { }, + specials = { }, + instance = false, + characters = { }, + unicodes = { }, + } + if specification then + local resources = specification.resources + if resources then + local characters = dictionary.characters or { } + local unicodes = dictionary.unicodes or { } + for i=1,#resources do + local r = resources[i] + if not r.in_dictionary then + r.in_dictionary = true + local patterns = r.patterns + if patterns then + local data = patterns.data + if data then + -- regular patterns + lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) + end + local extra = patterns.extra + if extra then + -- special patterns + lpegmatch(p_pattern,extra,1,dictionary.patterns,dictionary.specials) + end + end + local exceptions = r.exceptions + if exceptions then + local data = exceptions.data + if data and data ~= "" then + lpegmatch(p_exception,data,1,dictionary.exceptions) + end + end + local usedchars = lpegmatch(p_split,patterns.characters) + for i=1,#usedchars do + local char = usedchars[i] + local code = utfbyte(char) + local upper = uccodes[code] + characters[char] = code + unicodes [code] = char + if type(upper) == "table" then + for i=1,#upper do + local u = upper[i] + unicodes[u] = utfchar(u) + end + else + unicodes[upper] = utfchar(upper) + end + end + end + end + dictionary.characters = characters + dictionary.unicodes = unicodes + setmetatableindex(characters,function(t,k) local v = k and utfbyte(k) t[k] = v return v end) + end + t[specification.number] = dictionary + dictionary.instance = specification.instance -- needed for hyphenchars + end + t[k] = dictionary + return dictionary + end) + + -- Beware: left and right min doesn't mean that in a 1 mmm hsize there can be snippets + -- with less characters than either of them! This could be an option but such a narrow + -- hsize doesn't make sense anyway. + + -- We assume that featuresets are defined global ... local definitions (also mid paragraph) + -- make not much sense anyway. For the moment we assume no predefined sets so we don't need + -- to store them. Nor do we need to hash them in order to save space ... no sane user will + -- define many of them. + + local featuresets = hyphenators.featuresets or { } + hyphenators.featuresets = featuresets + + storage.shared.noflanguagesfeaturesets = storage.shared.noflanguagesfeaturesets or 0 + + local noffeaturesets = storage.shared.noflanguagesfeaturesets + + storage.register("languages/hyphenators/featuresets",featuresets,"languages.hyphenators.featuresets") + + ----- hash = table.sequenced(featureset,",") -- no need now + + local function register(name,featureset) + noffeaturesets = noffeaturesets + 1 + featureset.attribute = noffeaturesets + featuresets[noffeaturesets] = featureset -- access by attribute + featuresets[name] = featureset -- access by name + storage.shared.noflanguagesfeaturesets = noffeaturesets + return noffeaturesets + end + + local function makeset(...) + -- a bit overkill, supporting variants but who cares + local set = { } + for i=1,select("#",...) do + local list = select(i,...) + local kind = type(list) + local used = nil + if kind == "string" then + if list == v_all then + -- not ok ... now all get ignored + return setmetatableindex(function(t,k) local v = utfchar(k) t[k] = v return v end) + elseif list ~= "" then + used = lpegmatch(p_split,list) + set = set or { } + for i=1,#used do + local char = used[i] + set[utfbyte(char)] = char + end + end + elseif kind == "table" then + if next(list) then + set = set or { } + for byte, char in next, list do + set[byte] = char == true and utfchar(byte) or char + end + elseif #list > 0 then + set = set or { } + for i=1,#list do + local l = list[i] + if type(l) == "number" then + set[l] = utfchar(l) + else + set[utfbyte(l)] = l + end + end + end + end + end + return set + end + + -- category pd (tex also sees --- and -- as hyphens but do we really want that + + local defaulthyphens = { + [0x002D] = true, -- HYPHEN-MINUS + [0x00AD] = 0x002D, -- SOFT HYPHEN (active in ConTeXt) + -- [0x058A] = true, -- ARMENIAN HYPHEN + -- [0x1400] = true, -- CANADIAN SYLLABICS HYPHEN + -- [0x1806] = true, -- MONGOLIAN TODO SOFT HYPHEN + [0x2010] = true, -- HYPHEN + -- [0x2011] = true, -- NON-BREAKING HYPHEN + -- [0x2012] = true, -- FIGURE DASH + [0x2013] = true, -- EN DASH + [0x2014] = true, -- EM DASH + -- [0x2015] = true, -- HORIZONTAL BAR + -- [0x2027] = true, -- HYPHENATION POINT + -- [0x2E17] = true, -- DOUBLE OBLIQUE HYPHEN + -- [0x2E1A] = true, -- HYPHEN WITH DIAERESIS + -- [0x2E3A] = true, -- TWO-EM DASH + -- [0x2E3B] = true, -- THREE-EM DASH + -- [0x2E40] = true, -- DOUBLE HYPHEN + -- [0x301C] = true, -- WAVE DASH + -- [0x3030] = true, -- WAVY DASH + -- [0x30A0] = true, -- KATAKANA-HIRAGANA DOUBLE HYPHEN + -- [0xFE31] = true, -- PRESENTATION FORM FOR VERTICAL EM DASH + -- [0xFE32] = true, -- PRESENTATION FORM FOR VERTICAL EN DASH + -- [0xFE58] = true, -- SMALL EM DASH + -- [0xFE63] = true, -- SMALL HYPHEN-MINUS + -- [0xFF0D] = true, -- FULLWIDTH HYPHEN-MINUS + } + + local defaultjoiners = { + [0x200C] = true, -- nzwj + [0x200D] = true, -- zwj + } + + local function somehyphenchar(c) + c = tonumber(c) + return c ~= 0 and c or nil + end + + local function definefeatures(name,featureset) + local extrachars = featureset.characters -- "[]()" + local hyphenchars = featureset.hyphens + local joinerchars = featureset.joiners + local alternative = featureset.alternative + local rightwordmin = tonumber(featureset.rightwordmin) + local charmin = tonumber(featureset.charmin) -- luatex now also has hyphenationmin + local leftcharmin = tonumber(featureset.leftcharmin) + local rightcharmin = tonumber(featureset.rightcharmin) + local leftchar = somehyphenchar(featureset.leftchar) + local rightchar = somehyphenchar(featureset.rightchar) + local rightchars = featureset.rightchars +local rightedge = featureset.rightedge +local autohyphen = v_yes -- featureset.autohyphen -- insert disc +local hyphenonly = v_yes -- featureset.hyphenonly -- don't hyphenate around + rightchars = rightchars == v_word and true or tonumber(rightchars) + joinerchars = joinerchars == v_yes and defaultjoiners or joinerchars -- table + hyphenchars = hyphenchars == v_yes and defaulthyphens or hyphenchars -- table + -- not yet ok: extrachars have to be ignored so it cannot be all) + featureset.extrachars = makeset(joinerchars or "",extrachars or "") + featureset.hyphenchars = makeset(hyphenchars or "") + featureset.alternative = alternative or "hyphenate" + featureset.rightwordmin = rightwordmin and rightwordmin > 0 and rightwordmin or nil + featureset.charmin = charmin and charmin > 0 and charmin or nil + featureset.leftcharmin = leftcharmin and leftcharmin > 0 and leftcharmin or nil + featureset.rightcharmin = rightcharmin and rightcharmin > 0 and rightcharmin or nil + featureset.rightchars = rightchars + featureset.leftchar = leftchar + featureset.rightchar = rightchar + -- featureset.strict = rightedge == "tex" +featureset.autohyphen = autohyphen == v_yes +featureset.hyphenonly = hyphenonly == v_yes + return register(name,featureset) + end + + local function setfeatures(n) + if not n or n == v_reset then + n = false + else + local f = featuresets[n] + if not f and type(n) == "string" then + local t = settings_to_array(n) + local s = { } + for i=1,#t do + local ti = t[i] + local fs = featuresets[ti] + if fs then + for k, v in next, fs do + s[k] = v + end + end + end + n = register(n,s) + else + n = f and f.attribute + end + end + texsetattribute(a_hyphenation,n or unsetvalue) + end + + traditional.definefeatures = definefeatures + traditional.setfeatures = setfeatures + + implement { + name = "definehyphenationfeatures", + actions = definefeatures, + arguments = { + "string", + { + { "characters" }, + { "hyphens" }, + { "joiners" }, + { "rightchars" }, + { "rightwordmin", "integer" }, + { "charmin", "integer" }, + { "leftcharmin", "integer" }, + { "rightcharmin", "integer" }, + { "leftchar", "integer" }, + { "rightchar", "integer" }, + { "alternative" }, + { "rightedge" }, + } + } + } + + implement { + name = "sethyphenationfeatures", + actions = setfeatures, + arguments = "string" + } + + implement { + name = "registerhyphenationpattern", + actions = traditional.registerpattern, + arguments = { "string", "string", "boolean" } + } + + implement { + name = "registerhyphenationexception", + actions = traditional.registerexception, + arguments = "2 strings", + } + + -- This is a relative large function with local variables and local functions. A previous + -- implementation had the functions outside but this is cleaner and as efficient. The test + -- runs 100 times over tufte.tex, knuth.tex, zapf.tex, ward.tex and darwin.tex in lower + -- and uppercase with a 1mm hsize. + -- + -- language=0 language>0 4 | 3 * slower + -- + -- tex 2.34 | 1.30 2.55 | 1.45 0.21 | 0.15 + -- lua 2.42 | 1.38 3.30 | 1.84 0.88 | 0.46 + -- + -- Of course we have extra overhead (virtual Lua machine) but also we check attributes and + -- support specific local options). The test puts the typeset text in boxes and discards + -- it. If we also flush the runtime is 4.31|2.56 and 4.99|2.94 seconds so the relative + -- difference is (somehow) smaller. The test has 536 pages. There is a little bit of extra + -- overhead because we store the patterns in a different way. + -- + -- As usual I will look for speedups. Some 0.01 seconds could be gained by sharing patterns + -- which is not impressive but it does save some 3M memory on this test. (Some optimizations + -- already brought the 3.30 seconds down to 3.14 but it all depends on aggressive caching.) + + -- As we kick in the hyphenator before fonts get handled, we don't look at implicit (font) + -- kerns or ligatures. + + local starttiming = statistics.starttiming + local stoptiming = statistics.stoptiming + + -- local strictids = { + -- [nodecodes.hlist] = true, + -- [nodecodes.vlist] = true, + -- [nodecodes.rule] = true, + -- [nodecodes.dir] = true, + -- [nodecodes.whatsit] = true, + -- [nodecodes.ins] = true, + -- [nodecodes.adjust] = true, + -- + -- [nodecodes.math] = true, + -- [nodecodes.disc] = true, + -- + -- [nodecodes.accent] = true, -- never used in context + -- } + + -- a lot of overhead when only one char + + function traditional.hyphenate(head) + + local first = head + local tail = nil + local last = nil + local current = first + local dictionary = nil + local instance = nil + local characters = nil + local unicodes = nil + local exhyphenchar = tex.exhyphenchar + local extrachars = nil + local hyphenchars = nil + local language = nil + local lastfont = nil + local start = nil + local stop = nil + local word = { } -- we reuse this table + local size = 0 + local leftchar = false + local rightchar = false -- utfbyte("-") + local leftexchar = false + local rightexchar = false -- utfbyte("-") + local leftmin = 0 + local rightmin = 0 + local charmin = 1 + local leftcharmin = nil + local rightcharmin = nil + ----- leftwordmin = nil + local rightwordmin = nil + local rightchars = nil + local leftchar = nil + local rightchar = nil + local attr = nil + local lastwordlast = nil + local hyphenated = hyphenate + ----- strict = nil + local exhyphenpenalty = tex.exhyphenpenalty + local hyphenpenalty = tex.hyphenpenalty + local autohyphen = false + local hyphenonly = false + + -- We cannot use an 'enabled' boolean (false when no characters or extras) because we + -- can have plugins that set a characters metatable and so) ... it doesn't save much + -- anyway. Using (unicodes and unicodes[code]) and a nil table when no characters also + -- doesn't save much. So there not that much to gain for languages that don't hyphenate. + -- + -- enabled = (unicodes and (next(unicodes) or getmetatable(unicodes))) + -- or (extrachars and next(extrachars)) + -- + -- This can be used to not add characters i.e. keep size 0 but then we need to check for + -- attributes that change it, which costs time too. Not much to gain there. + + starttiming(traditional) + + local function insertpenalty() + local p = new_penalty(interwordpenalty) + setattrlist(p,last) + if trace_visualize then + nuts.setvisual(p,"penalty") + end + last = getprev(last) + first, last = insert_after(first,last,p) + end + + local function synchronizefeatureset(a) + local f = a and featuresets[a] + if f then + hyphenated = methods[f.alternative or "hyphenate"] + extrachars = f.extrachars + hyphenchars = f.hyphenchars + rightwordmin = f.rightwordmin + charmin = f.charmin + leftcharmin = f.leftcharmin + rightcharmin = f.rightcharmin + leftchar = f.leftchar + rightchar = f.rightchar + -- strict = f.strict and strictids + rightchars = f.rightchars + autohyphen = f.autohyphen + hyphenonly = f.hyphenonly + if rightwordmin and rightwordmin > 0 and lastwordlast ~= rightwordmin then + -- so we can change mid paragraph but it's kind of unpredictable then + if not tail then + tail = node_tail(first) + end + last = tail + local inword = false + local count = 0 + while last and rightwordmin > 0 do + local id = getid(last) + if id == glyph_code then + count = count + 1 + inword = true + if trace_visualize then + setcolor(last,"darkgreen") + end + elseif inword then + inword = false + rightwordmin = rightwordmin - 1 + if rightchars == true then + if rightwordmin > 0 then + insertpenalty() + end + elseif rightchars and count <= rightchars then + insertpenalty() + end + end + last = getprev(last) + end + lastwordlast = rightwordmin + end + if not charmin or charmin == 0 then + charmin = 1 + end + else + hyphenated = methods.hyphenate + extrachars = false + hyphenchars = false + rightwordmin = false + charmin = 1 + leftcharmin = false + rightcharmin = false + leftchar = false + rightchar = false + -- strict = false + autohyphen = false + hyphenonly = false + end + + return a + end + + local function flush(hyphens) -- todo: no need for result + + local rightmin = size - rightmin + local result = { } + local rsize = 0 + local position = 1 + + -- todo: remember last dics and don't go back to before that (plus message) ... + -- for simplicity we also assume that we don't start with a dics node + -- + -- there can be a conflict: if we backtrack then we can end up in another disc + -- and get out of sync (dup chars and so) + + while position <= size do + if position >= leftmin and position <= rightmin then + local hyphen = hyphens[position] + if not hyphen then + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + elseif hyphen == true then + rsize = rsize + 1 + result[rsize] = word[position] + rsize = rsize + 1 + result[rsize] = true + position = position + 1 + else + local o, h = hyphen[2] + if o then + -- { hyphen, offset) + h = hyphen[1] + else + -- hyphen + h = hyphen + o = 1 + end + local b = position - o + (h.start or 1) + local e = b + (h.length or 2) - 1 + if b > 0 and e >= b then + for i=1,b-position do + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + rsize = rsize + 1 + result[rsize] = { + h.before or "", -- pre + h.after or "", -- post + concat(word,"",b,e), -- replace + h.right, -- optional after pre + h.left, -- optional before post + } + position = e + 1 + else + -- error + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + else + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + + local function serialize(replacement,leftchar,rightchar) + if not replacement then + return + elseif replacement == true then + local glyph = copy_node(stop) + setchar(glyph,leftchar or rightchar) + return glyph + end + local head = nil + local current = nil + if leftchar then + head = copy_node(stop) + current = head + setchar(head,leftchar) + end + local rsize = #replacement + if rsize == 1 then + local glyph = copy_node(stop) + setchar(glyph,characters[replacement]) + if head then + insert_after(current,current,glyph) + else + head = glyph + end + current = glyph + elseif rsize > 0 then + local list = lpegmatch(p_split,replacement) -- this is an utf split (could be cached) + for i=1,#list do + local glyph = copy_node(stop) + setchar(glyph,characters[list[i]]) + if head then + insert_after(current,current,glyph) + else + head = glyph + end + current = glyph + end + end + if rightchar then + local glyph = copy_node(stop) + insert_after(current,current,glyph) + setchar(glyph,rightchar) + end + return head + end + + local current = start + local attrnode = start -- will be different, just the first char + + for i=1,rsize do + local r = result[i] + if r == true then + local disc = new_disc() + local pre = nil + local post = nil + if rightchar then + pre = serialize(true,rightchar) + end + if leftchar then + post = serialize(true,leftchar) + end + setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty) + if attrnode then + setattrlist(disc,attrnode) + end + -- could be a replace as well + insert_before(first,current,disc) + elseif type(r) == "table" then + local disc = new_disc() + local pre = r[1] + local post = r[2] + local replace = r[3] + local right = r[4] ~= false and rightchar + local left = r[5] ~= false and leftchar + if pre then + if pre ~= "" then + pre = serialize(pre,false,right) + else + pre = nil + end + end + if post then + if post ~= "" then + post = serialize(post,left,false) + else + post = nil + end + end + if replace then + if replace ~= "" then + replace = serialize(replace) + else + replace = nil + end + end + -- maybe regular code + setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty) + if attrnode then + setattrlist(disc,attrnode) + end + insert_before(first,current,disc) + else + setchar(current,characters[r]) + if i < rsize then + current = getnext(current) + end + end + end + if current and current ~= stop then + local current = getnext(current) + local last = getnext(stop) + while current ~= last do + first, current = remove_node(first,current,true) + end + end + + end + + local function inject(leftchar,rightchar,code,attrnode) + if first ~= current then + local disc = new_disc() + first, current, glyph = remove_node(first,current) + first, current = insert_before(first,current,disc) + if trace_visualize then + setcolor(glyph,"darkred") -- these get checked + setcolor(disc,"darkgreen") -- in the colorizer + end + local pre = nil + local post = nil + local replace = glyph + if leftchar and leftchar > 0 then + post = copy_node(glyph) + setchar(post,leftchar) + end + pre = copy_node(glyph) + setchar(pre,rightchar and rightchar > 0 and rightchar or code) + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? + if attrnode then + setattrlist(disc,attrnode) + end + end + return current + end + + local function injectseries(current,last,next,attrnode) + local disc = new_disc() + local start = current + first, current = insert_before(first,current,disc) + setprev(start) + setnext(last) + if next then + setlink(current,next) + else + setnext(current) + end + local pre = copy_list(start) + local post = nil + local replace = start + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? + if attrnode then + setattrlist(disc,attrnode) + end + return current + end + + local a = getattr(first,a_hyphenation) + if a ~= attr then + attr = synchronizefeatureset(a) + end + + -- The first attribute in a word determines the way a word gets hyphenated and if + -- relevant, other properties are also set then. We could optimize for silly one-char + -- cases but it has no priority as the code is still not that much slower than the + -- native hyphenator and this variant also provides room for extensions. + + local skipping = false + + -- In "word word word." the sequences "word" and "." can be a different font! + + while current and current ~= last do -- and current + local code, id = isglyph(current) + if code then + if skipping then + current = getnext(current) + else + local lang = getlanguage(current) + local font = getfont(current) + if lang ~= language or font ~= lastfont then + if dictionary and size > charmin and leftmin + rightmin <= size then + -- only german has many words starting with an uppercase character + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + lastfont = font + if language ~= lang and lang > 0 then + -- + dictionary = dictionaries[lang] + instance = dictionary.instance + characters = dictionary.characters + unicodes = dictionary.unicodes + -- + local a = getattr(current,a_hyphenation) + attr = synchronizefeatureset(a) + leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more + rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed + leftexchar = (instance and preexhyphenchar (instance)) + rightexchar = (instance and postexhyphenchar(instance)) + leftmin = leftcharmin or getfield(current,"left") + rightmin = rightcharmin or getfield(current,"right") + if not leftchar or leftchar < 0 then + leftchar = false + end + if not rightchar or rightchar < 0 then + rightchar = false + end + -- + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + word[1] = char + size = 1 + start = current + else + size = 0 + end + else + size = 0 + end + language = lang + elseif language <= 0 then + -- + elseif size > 0 then + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + size = size + 1 + word[size] = char + elseif dictionary then + if not hyphenonly or code ~= exhyphenchar then + if size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + end + size = 0 + if code == exhyphenchar then -- normally the - + local next = getnext(current) + local last = current + local font = getfont(current) + while next and ischar(next,font) == code do + last = next + next = getnext(next) + end + if not autohyphen then + current = last + elseif current == last then + current = inject(leftexchar,rightexchar,code,current) + else + current = injectseries(current,last,next,current) + end + if hyphenonly then + skipping = true + end + elseif hyphenchars then + local char = hyphenchars[code] + if char == true then + char = code + end + if char then + current = inject(leftchar and char or nil,rightchar and char or nil,char,current) + end + end + end + else + local a = getattr(current,a_hyphenation) + if a ~= attr then + attr = synchronizefeatureset(a) -- influences extrachars + leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more + rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed + leftexchar = (instance and preexhyphenchar (instance)) + rightexchar = (instance and postexhyphenchar(instance)) + leftmin = leftcharmin or getfield(current,"left") + rightmin = rightcharmin or getfield(current,"right") + if not leftchar or leftchar < 0 then + leftchar = false + end + if not rightchar or rightchar < 0 then + rightchar = false + end + end + -- + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + word[1] = char + size = 1 + start = current + end + end + stop = current + current = getnext(current) + end + else + if skipping then + skipping = false + end + if id == disc_code then + size = 0 + current = getnext(current) + if hyphenonly then + skipping = true + end + -- elseif strict and strict[id] then + -- current = id == math_code and getnext(end_of_math(current)) or getnext(current) + -- size = 0 + else + current = id == math_code and getnext(end_of_math(current)) or getnext(current) + end + if size > 0 then + if dictionary and size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + size = 0 + end + end + end + -- we can have quit due to last so we need to flush the last seen word, we could move + -- this in the loop and test for current but ... messy + if dictionary and size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + + stoptiming(traditional) + + return head + end + + statistics.register("hyphenation",function() + if nofwords > 0 or statistics.elapsed(traditional) > 0 then + return string.format("%s words hyphenated, %s unique, used time %s", + nofwords,nofhashed,statistics.elapsedseconds(traditional) or 0) + end + end) + + local texmethod = "builders.kernel.hyphenation" + local oldmethod = texmethod + local newmethod = texmethod + + -- local newmethod = "languages.hyphenators.traditional.hyphenate" + -- + -- nodes.tasks.prependaction("processors","words",newmethod) + -- nodes.tasks.disableaction("processors",oldmethod) + -- + -- nodes.tasks.replaceaction("processors","words",oldmethod,newmethod) + + -- \enabledirectives[hyphenators.method=traditional] + -- \enabledirectives[hyphenators.method=builtin] + + -- push / pop ? check first attribute + + -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches) + + local hyphenate = language.hyphenate + local hyphenating = nuts.hyphenating + local methods = { } + local usedmethod = false + local stack = { } + + local original = hyphenating and + function(head) + return (hyphenating(head)) + end + or + function(head) + hyphenate(tonode(head)) + return head -- a nut + end + + -- local has_language = language.has_language + -- + -- local function original(head) -- kernel.hyphenation(head) + -- local h = tonode(head) + -- if has_language(h) then + -- hyphenate(h) + -- end + -- return head + -- end + + local getcount = tex.getcount + + hyphenators.methods = methods + local optimize = false + + directives.register("hyphenator.optimize", function(v) optimize = v end) + + function hyphenators.handler(head,groupcode) + if usedmethod then + if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then + if getcount("hyphenstate") > 0 then + forced = false + return usedmethod(head) + else + return head + end + else + return usedmethod(head) + end + else + return head + end + end + + methods.tex = original + methods.original = original + methods.expanded = original -- was expanded before 1.005 + methods.traditional = languages.hyphenators.traditional.hyphenate + methods.none = false -- function(head) return head, false end + + usedmethod = original + + local function setmethod(method) + usedmethod = type(method) == "string" and methods[method] + if usedmethod == nil then + usedmethod = methods.tex + end + end + local function pushmethod(method) + insert(stack,usedmethod) + usedmethod = type(method) == "string" and methods[method] + if usedmethod == nil then + usedmethod = methods.tex + end + end + local function popmethod() + usedmethod = remove(stack) or methods.tex + end + + hyphenators.setmethod = setmethod + hyphenators.pushmethod = pushmethod + hyphenators.popmethod = popmethod + + directives.register("hyphenators.method",setmethod) + + function hyphenators.setup(specification) + local method = specification.method + if method then + setmethod(method) + end + end + + implement { name = "sethyphenationmethod", actions = setmethod, arguments = "string" } + implement { name = "pushhyphenation", actions = pushmethod, arguments = "string" } + implement { name = "pophyphenation", actions = popmethod } + + -- can become a runtime loaded one: + + local context = context + local ctx_NC = context.NC + local ctx_NR = context.NR + local ctx_verbatim = context.verbatim + + function hyphenators.showhyphenationtrace(language,word) + if not word or word == "" then + return + end + local saved = trace_steps + trace_steps = "silent" + local steps = traditional.gettrace(language,word) + trace_steps = saved + if steps then + local n = #steps + if n > 0 then + context.starttabulate { "|r|l|l|l|" } + for i=1,n do + local s = steps[i] + ctx_NC() if i > 1 and i < n then context(i-1) end + ctx_NC() ctx_verbatim(s[1]) + ctx_NC() ctx_verbatim(s[2]) + ctx_NC() ctx_verbatim(s[3]) + ctx_NC() + ctx_NR() + end + context.stoptabulate() + end + end + end + + implement { + name = "showhyphenationtrace", + actions = hyphenators.showhyphenationtrace, + arguments = "2 strings", + } + + function nodes.stripdiscretionaries(head) + for l in nexthlist, head do + for d in nextdisc, getlist(l) do + remove_node(h,false,true) + end + end + return head + end + + +else + + -- traditional.loadpatterns("nl","lang-nl") + -- traditional.loadpatterns("de","lang-de") + -- traditional.loadpatterns("us","lang-us") + + -- traditional.registerpattern("nl","e1ë", { start = 1, length = 2, before = "e", after = "e" } ) + -- traditional.registerpattern("nl","oo7ë", { start = 2, length = 3, before = "o", after = "e" } ) + -- traditional.registerpattern("de","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } ) + + -- local specification = { + -- leftcharmin = 2, + -- rightcharmin = 2, + -- leftchar = "<", + -- rightchar = ">", + -- } + + -- print("reëel", traditional.injecthyphens(dictionaries.nl,"reëel", specification),"r{e>}{}{}{ 32 hyphenated with length 1 + +local function sethjcodes(instance,loaded,what,factor) + local l = loaded[what] + local c = l and l.characters + if c then + local hjcounts = factor and languages.hjcounts or false + -- + local h = loaded.codehash + if not h then + h = { } + loaded.codehash = h + end + -- + local function setcode(l) + local u = uccodes[l] + local s = l + if hjcounts then + local c = hjcounts[l] + if c then + c = c.count + if not c then + -- error, keep as 1 + elseif c <= 0 then + -- counts as 0 i.e. ignored + s = 32 + elseif c >= 31 then + -- counts as 31 + s = 31 + else + -- count c times + s = c + end + end + end + sethjcode(instance,l,s) + h[l] = s + if u ~= l and type(u) == "number" then + sethjcode(instance,u,s) + h[u] = lccodes[l] + end + end + -- + local s = tex.savinghyphcodes + tex.savinghyphcodes = 0 + if type(c) == "table" then + for l in next, c do + setcode(utfbyte(l)) + end + else + for l in utfvalues(c) do + setcode(l) + end + end + tex.savinghyphcodes = s + end +end + +-- 2'2 conflicts with 4' ... and luatex barks on it + +local P, R, Cs, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.match, lpeg.patterns + +local utfsplit = utf.split + +local space = lpegpatterns.space +local whitespace = lpegpatterns.whitespace^1 +local nospace = lpegpatterns.utf8char - whitespace +local digit = lpegpatterns.digit +----- endofstring = #whitespace + P(-1) +local endofstring = #whitespace + +local word = (digit/"")^0 * (digit/"" * endofstring + digit/" " + nospace)^1 +local anyword = (1-whitespace)^1 +local analyze = Ct((whitespace + Cs(word))^1) + +local function unique(tag,requested,loaded) + local nofloaded = #loaded + if nofloaded == 0 then + return "" + elseif nofloaded == 1 then + return loaded[1] + else + insert(loaded,1," ") -- no need then for special first word + -- insert(loaded, " ") + loaded = concat(loaded," ") + local t = lpegmatch(analyze,loaded) or { } + local h = { } + local b = { } + for i=1,#t do + local ti = t[i] + local hi = h[ti] + if not hi then + h[ti] = 1 + elseif hi == 1 then + h[ti] = 2 + b[#b+1] = utfsplit(ti," ") + end + end + -- sort + local nofbad = #b + if nofbad > 0 then + local word + for i=1,nofbad do + local bi = b[i] + local p = P(bi[1]) + for i=2,#bi do + p = p * digit * P(bi[i]) + end + if word then + word = word + p + else + word = p + end + report_initialization("language %a, patterns %a, discarding conflict (0-9)%{[0-9]}t(0-9)",tag,requested,bi) + end + t, h, b = nil, nil, nil -- permit gc + local someword = digit^0 * word * digit^0 * endofstring / "" + -- local strip = Cs(someword^-1 * (someword + anyword + whitespace)^1) + local strip = Cs((someword + anyword + whitespace)^1) + return lpegmatch(strip,loaded) or loaded + else + return loaded + end + end +end + +local shared = false + +local function loaddefinitions(tag,specification) + statistics.starttiming(languages) + local data, instance = resolve(tag) + local requested = specification.patterns or "" + local definitions = settings_to_array(requested) + if #definitions > 0 then + if trace_patterns then + report_initialization("pattern specification for language %a: %s",tag,specification.patterns) + end + local ploaded = instance:patterns() + local eloaded = instance:hyphenation() + if not ploaded or ploaded == "" then + ploaded = { } + else + ploaded = { ploaded } + end + if not eloaded or eloaded == "" then + eloaded = { } + else + eloaded = { eloaded } + end + local dataused = data.used + local ok = false + local resources = data.resources or { } + data.resources = resources + if not shared then + local found = resolvers.findfile("lang-exc.lua") + if found then + shared = dofile(found) + if type(shared) == "table" then + shared = concat(shared," ") + else + shared = true + end + else + shared = true + end + end + for i=1,#definitions do + local definition = definitions[i] + if definition == "" then + -- error + elseif definition == v_reset then + if trace_patterns then + report_initialization("clearing patterns for language %a",tag) + end + instance:clear_patterns() + instance:clear_hyphenation() + ploaded = { } + eloaded = { } + elseif not dataused[definition] then + dataused[definition] = definition + local filename = "lang-" .. definition .. ".lua" + local fullname = resolvers.findfile(filename) or "" + if fullname == "" then + fullname = resolvers.findfile(filename .. ".gz") or "" + end + if fullname ~= "" then + if trace_patterns then + report_initialization("loading definition %a for language %a from %a",definition,tag,fullname) + end + local suffix, gzipped = gzip.suffix(fullname) + local loaded = table.load(fullname,gzipped and gzip.load) + if loaded then -- todo: version test + ok, nofloaded = true, nofloaded + 1 + sethjcodes(instance,loaded,"patterns",specification.factor) + sethjcodes(instance,loaded,"exceptions",specification.factor) + local p = validdata(loaded,"patterns",tag) + local e = validdata(loaded,"exceptions",tag) + if p and p ~= "" then + ploaded[#ploaded+1] = p + end + if e and e ~= "" then + eloaded[#eloaded+1] = e + end + resources[#resources+1] = loaded -- so we can use them otherwise + else + report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) + end + elseif trace_patterns then + report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) + end + elseif trace_patterns then + report_initialization("definition %a for language %a already loaded",definition,tag) + end + end + if #ploaded > 0 then + -- why not always clear + instance:clear_patterns() + instance:patterns(unique(tag,requested,ploaded)) + end + if #eloaded > 0 then + -- why not always clear + instance:clear_hyphenation() + instance:hyphenation(concat(eloaded," ")) + end + if type(shared) == "string" then + instance:hyphenation(shared) + end + return ok + elseif trace_patterns then + report_initialization("no definitions for language %a",tag) + end + statistics.stoptiming(languages) +end + +storage.shared.noflanguages = storage.shared.noflanguages or 0 + +local noflanguages = storage.shared.noflanguages + +function languages.define(tag,parent) + noflanguages = noflanguages + 1 + if trace_patterns then + report_initialization("assigning number %a to %a",noflanguages,tag) + end + numbers[noflanguages] = tag + registered[tag] = { + tag = tag, + parent = parent or "", + patterns = "", + loaded = false, + used = { }, + dirty = true, + number = noflanguages, + instance = nil, -- luatex data structure + synonyms = { }, + } + storage.shared.noflanguages = noflanguages +end + +function languages.setsynonym(synonym,tag) -- convenience function + local l = registered[tag] + if l then + l.synonyms[synonym] = true -- maybe some day more info + end +end + +function languages.installed(separator) + return concat(sortedkeys(registered),separator or ",") +end + +function languages.current(n) + return numbers[n and tonumber(n) or currentlanguage()] +end + +function languages.associate(tag,script,language) -- not yet used + associated[tag] = { script, language } +end + +function languages.association(tag) -- not yet used + if not tag then + tag = numbers[currentlanguage()] + elseif type(tag) == "number" then + tag = numbers[tag] + end + local lat = tag and associated[tag] + if lat then + return lat[1], lat[2] + end +end + +function languages.loadable(tag,defaultlanguage) -- hack + local l = registered[tag] -- no synonyms + if l and resolvers.findfile("lang-"..l.patterns..".lua") then + return true + else + return false + end +end + +-- a bit messy, we will do all language setting in lua as we can now assign +-- and 'patterns' will go away here. + +function languages.unload(tag) + local l = registered[tag] + if l then + l.dirty = true + end +end + +if environment.initex then + + function languages.getnumber() + return 0 + end + +else + + function languages.getnumber(tag,default,patterns,factor) + local l = registered[tag] + if l then + if l.dirty then + l.factor = factor == v_yes and true or false + if trace_patterns then + report_initialization("checking patterns for %a with default %a",tag,default) + end + -- patterns is already resolved to parent patterns if applicable + if patterns and patterns ~= "" then + if l.patterns ~= patterns then + l.patterns = patterns + if trace_patterns then + report_initialization("loading patterns for %a using specification %a",tag,patterns) + end + loaddefinitions(tag,l) + else + -- unchanged + end + elseif l.patterns == "" then + l.patterns = tag + if trace_patterns then + report_initialization("loading patterns for %a using tag",tag) + end + local ok = loaddefinitions(tag,l) + if not ok and tag ~= default then + l.patterns = default + if trace_patterns then + report_initialization("loading patterns for %a using default",tag) + end + loaddefinitions(tag,l) + end + end + l.loaded = true + l.dirty = false + end + return l.number + else + return 0 + end + end + + numbers[0] = "null" + + registered.null = { + number = 0, + instance = new_language(0), + } + +end + +-- not that usefull, global values + +function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) end +function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end +function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end +function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end +-------- languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end +-------- languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end + +-- e['implementer']= 'imple{m}{-}{-}menter' +-- e['manual'] = 'man{}{}{}' +-- e['as'] = 'a-s' +-- e['user-friendly'] = 'user=friend-ly' +-- e['exceptionally-friendly'] = 'excep-tionally=friend-ly' + +local invalid = { "{", "}", "-" } + +local function collecthjcodes(data,str) + local found = data.extras and data.extras.characters or { } + for s in utfcharacters(str) do + if not found[s] then + found[s] = true + end + end + for i=1,#invalid do -- less checks this way + local c = invalid[i] + if found[c] then + found[c] = nil + end + end + data.extras = { characters = found } + sethjcodes(data.instance,data,"extras",data.factor) +end + +function languages.loadwords(tag,filename) + local data, instance = resolve(tag) + if data then + statistics.starttiming(languages) + local str = io.loaddata(filename) or "" + collecthjcodes(data,str) + instance:hyphenation(str) + statistics.stoptiming(languages) + end +end + + +function languages.setexceptions(tag,str) + local data, instance = resolve(tag) + if data then + str = strip(str) -- we need to strip leading spaces + collecthjcodes(data,str) + instance:hyphenation(str) + end +end + +function languages.hyphenate(tag,str) + -- todo: does this still work? + local data, instance = resolve(tag) + if data then + return instance:hyphenate(str) + else + return str + end +end + +-- hyphenation.define ("zerolanguage") +-- hyphenation.loadpatterns ("zerolanguage") -- else bug +-- hyphenation.loadexceptions("zerolanguage") -- else bug + +languages.logger = languages.logger or { } + +function languages.logger.report() + local result, r = { }, 0 + for tag, l in sortedpairs(registered) do + if l.loaded then + r = r + 1 + result[r] = format("%s:%s:%s",tag,l.parent,l.number) + end + end + return r > 0 and concat(result," ") or "none" +end + +-- must happen at the tex end .. will use lang-def.lua + +languages.associate('en','latn','eng') +languages.associate('uk','latn','eng') +languages.associate('nl','latn','nld') +languages.associate('de','latn','deu') +languages.associate('fr','latn','fra') + +statistics.register("loaded patterns", function() + local result = languages.logger.report() + if result ~= "none" then + -- return result + return format("%s, load time: %s",result,statistics.elapsedtime(languages)) + end +end) + +-- statistics.register("language load time", function() +-- -- often zero so we can merge that in the above +-- return statistics.elapsedseconds(languages, format(", nofpatterns: %s",nofloaded)) +-- end) + +-- interface + +implement { + name = "languagenumber", + actions = { languages.getnumber, context }, + arguments = "4 strings" +} + +implement { + name = "installedlanguages", + actions = { languages.installed, context }, +} + +implement { + name = "definelanguage", + actions = languages.define, + arguments = "2 strings" +} + +implement { + name = "setlanguagesynonym", + actions = languages.setsynonym, + arguments = "2 strings" +} + +implement { + name = "unloadlanguage", + actions = languages.unload, + arguments = "string" +} + +implement { + name = "setlanguageexceptions", + actions = languages.setexceptions, + arguments = "2 strings" +} + +implement { + name = "currentprehyphenchar", + actions = function() + local c = prehyphenchar(tolang()) + if c and c > 0 then + context.char(c) + end + end +} + +implement { + name = "currentposthyphenchar", + actions = function() + local c = posthyphenchar(tolang()) + if c and c > 0 then + context.char(c) + end + end +} diff --git a/tex/context/base/mkxl/lang-ini.mkxl b/tex/context/base/mkxl/lang-ini.mkxl new file mode 100644 index 000000000..6a230e165 --- /dev/null +++ b/tex/context/base/mkxl/lang-ini.mkxl @@ -0,0 +1,766 @@ +%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. + +% We can protect \currentlanguage etc too. + +% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]} + +%D This module implements multi||language support of \CONTEXT, which should not be +%D confused with the multi||lingual interface. This support will be extended when +%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\ +%D files. + +\writestatus{loading}{ConTeXt Language Macros / Initialization} + +\registerctxluafile{lang-ini}{autosuffix} +\registerctxluafile{lang-def}{} +\registerctxluafile{lang-cnt}{} + +\unprotect + +\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi +\ifdefined\frenchspacing \else \let\frenchspacing \relax \fi + +%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table, +%D starting with~0. Switching to a specific table is done by assigning the relevant +%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot +%D of management is delegated to \LUA. + +%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This +%D just one of those situations in which we don't want to spent a real one. Language +%D zero has no patterns, first of all because I like to start numbering at one. It +%D may come in handy for special purposes as well. + +\normallanguage\zerocount \def\loadedlanguage{1} + +%D \macros +%D {currentlanguage, setupcurrentlanguage} +%D +%D Instead of numbers,we are going to use symbolic names for the languages. The +%D current langage is saved in the macro \type {\currentlanguage}. The setup macro +%D is mainly used for cosmetic purposes. +%D +%D \starttyping +%D \dorecurse{3} +%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 +%D We don't use the commandhandler here (yet) because we have a rather special +%D fallback mechanism so quite some compatibility testing is needed. + +\installcorenamespace{language} +\installcorenamespace{languagelinked} + +\def\currentusedlanguage{\currentlanguage} + +\permanent\def\defaultlanguage#1% + {\ifcsname\??language#1\s!default\endcsname + \expandafter\defaultlanguage\lastnamedcs + \else + #1% + \fi} + +\permanent\def\languageparameter#1% + {\ifcsname\??language\currentlanguage#1\endcsname + \lastnamedcs + \orelse\ifcsname\??language\currentlanguage\s!default\endcsname + \expandafter\specificlanguageparameter\lastnamedcs{#1}% + \orelse\ifcsname\??language\s!default#1\endcsname + \lastnamedcs + \fi} + +\permanent\def\specificlanguageparameter#1#2% + {\ifcsname\??language#1#2\endcsname + \lastnamedcs + \orelse\ifcsname\??language#1\s!default\endcsname + \expandafter\specificlanguageparameter\lastnamedcs{#2}% + \orelse\ifcsname\??language\s!default#2\endcsname + \lastnamedcs + \fi} + +\permanent\def\mainlanguageparameter#1% + {\ifcsname\??language\currentmainlanguage#1\endcsname + \lastnamedcs + \orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname + \expandafter\specificlanguageparameter\lastnamedcs{#1}% + \orelse\ifcsname\??language\s!default#1\endcsname + \lastnamedcs + \fi} + +\aliased\let\usedlanguageparameter\languageparameter + +\permanent\def\askedlanguageparameter#1% assumes \currentusedlanguage being set + {\ifcsname\??language\currentusedlanguage#1\endcsname + \lastnamedcs + \orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname + \expandafter\specificlanguageparameter\lastnamedcs{#1}% + \orelse\ifcsname\??language\s!default#1\endcsname + \lastnamedcs + \fi} + +\permanent\protected\def\setusedlanguage#1% + {\edef\currentusedlanguage{\reallanguagetag{#1}}% + \ifempty\currentusedlanguage + \let\currentusedlanguage \currentlanguage + \enforced\let\usedlanguageparameter\languageparameter + \orelse\ifx\currentusedlanguage\v!global + \let\currentusedlanguage \currentmainlanguage + \enforced\let\usedlanguageparameter\mainlanguageparameter + \orelse\ifx\currentusedlanguage\v!local + \let\currentusedlanguage \currentlanguage + \enforced\let\usedlanguageparameter\languageparameter + \else + \enforced\let\usedlanguageparameter\askedlanguageparameter + \fi} + +\permanent\protected\def\setupcurrentlanguage[#1]% + {\setcurrentlanguage\currentmainlanguage{#1}} + +\permanent\protected\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current) + {\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage + \ifempty\xaskedlanguage \else + \ifempty\currentmainlanguage\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi + \let\currentmainlanguage\xaskedlanguage + \setsystemmode{\systemmodeprefix\currentmainlanguage}% + \fi + \edef\xaskedlanguage{#2}% + \ifempty\xaskedlanguage \else + \ifempty\currentlanguage\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 is prepared. The +%D next macro takes care of this loading. A language is specified with +%D +%D \showsetup{installlanguage} +%D +%D When \type {state} equals \type {start}, both patterns and additional hyphenation +%D specifications are loaded. These files are seached for in the patterns path +%D have names like \type {lang-nl.lua}. +%D +%D The \type {spacing} variable specifies how the spaces after punctuation has to be +%D handled. English is by tradition more tolerant to inter||sentence spacing than +%D other languages. +%D +%D This macro also defines \type {\identifier} as a shortcut switch to the language. +%D Furthermore the command defined as being language specific, are executed. With +%D \type {default} we can default to another language (patterns) at format +%D generation time. Patterns are loaded at runtime. + +\newtoks \everysetuplanguage + +\aliased\let\installedlanguages\clf_installedlanguages % no need for \clf_ + +\permanent\protected\def\doifelselanguage#1% + {\ifcsname\??language#1\c!state\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflanguageelse\doifelselanguage + +\permanent\def\reallanguagetag#1% + {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi} + +% \language[#1] gave unwanted side effect of loading language specifics + +\permanent\tolerant\protected\def\installlanguage[#1]#*[#2]% + {\ifcondition\validassignment{#2}% + \doifelselanguage{#1} + {\getparameters[\??language#1][#2]} + {\setvalue{\??languagelinked#1}{#1}% + \getparameters[\??language#1][\c!state=\v!start,#2]% + \lang_basics_install_indeed{#1}{#1}}% + \edef\currentsetuplanguage{#1}% + \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}% + \the\everysetuplanguage + \else + \setvalue{\??languagelinked#1}{#2}% + \clf_setlanguagesynonym{#1}{#2}% + \lang_basics_install_indeed{#1}{#2}% + \fi} + +\def\lang_basics_install_indeed#1#2% + {\doifnot{\specificlanguageparameter{#1}\c!command}\v!no + {\ifcsname#1\endcsname\else\frozen\instance\setuvalue{#1}{\lang_basics_set_current[#2]}\fi}} + +%D When the second argument is a language identifier, a synonym is created. This +%D feature is present because we used dutch mnemonics in the dutch version, but +%D nowadays conform a standard. + +\permanent\protected\def\doifelsepatterns#1% + {\begingroup % will change + \lang_basics_set_current[#1]% + \ifnum\normallanguage>\zerocount + \endgroup\expandafter\firstoftwoarguments + \else + \endgroup\expandafter\secondoftwoarguments + \fi} + +\aliased\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. + +\ifdefined\lang_basics_synchronize \else + \let\lang_basics_synchronize\relax % be nice for setups till we have one +\fi + +\installmacrostack\currentlanguage + +\permanent\tolerant\protected\def\setuplanguage[#1]#*[#2]% + {\ifarguments + % only synchronize + \or + \let\currentsetuplanguage\currentlanguage + \getparameters[\??language\currentsetuplanguage][#1]% + \the\everysetuplanguage + \or + \push_macro_currentlanguage % can be default + \edef\currentsetuplanguage{\reallanguagetag{#1}}% + \getparameters[\??language\currentsetuplanguage][#2]% + \the\everysetuplanguage + \pop_macro_currentlanguage + %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default) + \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!time={h,:,m}, + \c!date={\v!year,\ ,\v!month,\ ,\v!day}, + \c!text=Ag, + \c!font=] % \v!auto : experimental ! + +% to be tested: +% +% \setuplanguage +% [\s!default] +% [\c!righthyphenchar="AD] + +%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used +%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french +%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like +%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into +%D view \quotation {when we quote} or \quote {quote} something. + +%D \macros +%D {currentdatespecification, currenttimespecification} +%D +%D Just to make things easy we can ask for the current date specification by saying: + +\permanent\def\currentdatespecification{\languageparameter\c!date} +\permanent\def\currenttimespecification{\languageparameter\c!time} + +%D Carefull reading of these macros shows that it's legal to say +%D +%D \starttyping +%D \installlanguage [du] [de] +%D \stoptyping + +%D \macros +%D {language,mainlanguage} +%D +%D Switching to another language (actually another hyphenation pattern) is done +%D with: +%D +%D \starttyping +%D \language[identifier] +%D \stoptyping +%D +%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still +%D support the original meaning, so +%D +%D \starttyping +%D \language=1 +%D \stoptyping +%D +%D is a valid operation, where the relation between number and language depends on +%D the order in installing languages. +%D +%D \showsetup{language} +%D \showsetup{mainlanguage} +%D +%D Both commands take a predefined language identifier as argument. We can use \type +%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the +%D language used for translating labels like {\em figure} and {\em table}. The main +%D language defaults to the current language. + +\newtoks \everylanguage + +\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 + \gletcsname\??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}% + {\languageparameter\c!factor}% + \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 + {\normallanguage\csname\??languagenumbers + \ifcsname\??languagenumbers\currentlanguage\endcsname + \currentlanguage + \fi + \endcsname + \relax + \the\everylanguage + \relax} + +\newcount\hyphenstate +\newcount\hyphenminoffset + +% This is the old implementation: a hack that sets the min values, because we want +% to keep the language set: +% +% \protected\def\nohyphens % nicer for url's +% {\ifx\dohyphens\relax +% \protected\edef\dohyphens +% {\hyphenminoffset\the\hyphenminoffset\relax +% \lang_basics_synchronize_min_max}% +% \fi +% \hyphenminoffset\plusthousand +% \lang_basics_synchronize_min_max} +% +% \let\dohyphens\relax + +% But this one is nicer because we do keep the language set as well as don't mess +% with the min values (it's more efficient too). We might get some more bits in +% this mode (engine specific). + +\exhyphenchar 45 % to permit breaking at explicit hyphens + +% \uchyph\plusone : + +\chardef \completehyphenationmodecode \numexpr + \normalhyphenationmodecode % \discretionary + + \automatichyphenationmodecode % - + + \explicithyphenationmodecode % \- + + \syllablehyphenationmodecode % pattern driven + + \uppercasehyphenationmodecode % replaces \uchyph + + \compoundhyphenationmodecode % replaces \compoundhyphenmode + % \strictstarthyphenationmodecode % replaces \hyphenationbounds (strict = original tex) + % \strictendhyphenationmodecode % replaces \hyphenationbounds (strict = original tex) + + \automaticpenaltyhyphenationmodecode % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty) + + \explicitpenaltyhyphenationmodecode % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty) + + \permitgluehyphenationmodecode % turn glue into kern in \discretionary + + \permitallhyphenationmodecode % okay, let's be even more tolerant + + \permitmathreplacehyphenationmodecode % and again we're more permissive +\relax + +\permanent\protected\def\dohyphens{\hyphenationmode\completehyphenationmodecode} +\permanent\protected\def\nohyphens{\hyphenationmode\zerocount} + +\permanent\protected\def\usehyphensparameter#1% + {\edef\p_hyphens{#1\c!hyphens}% + \ifx\p_hyhens\v!no + \nohyphens + \fi} + +\dohyphens + +%D The rest stays the same as in mkiv: + +\permanent\protected\def\lesshyphens + {\advance\hyphenminoffset\plusone + \lang_basics_synchronize_min_max} + +\permanent\protected\def\morehyphens + {\ifcase\hyphenminoffset \else + \advance\hyphenminoffset\minusone + \fi + \lang_basics_synchronize_min_max} + +\protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end + {% these values are stored along with glyph nodes + \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax + \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax + \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 + +\permanent\protected\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}% + \ifempty\currentlanguagesetups \else + \setups[\currentlanguagesetups]% + \fi +\to \everylanguage + +% new + +\appendtoks + \usebidiparameter\languageparameter +\to \everylanguage + +% this will move to core-spa ! + +\appendtoks + \edef\p_spacing{\languageparameter\c!spacing}% + \ifx\p_spacing\v!broad + \nonfrenchspacing + \else + \frenchspacing + \fi +\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 + +\permanent\protected\def\setuplanguages + {\setuplanguage[\s!default]} + +% \setuplanguages[\c!font=\v!auto] +% \setuplanguage[\s!default][\c!font=\v!auto] +% \setuplanguage[nl][\c!font=\v!auto] + +\appendtoks + \edef\p_language_font{\languageparameter\c!font}% + \ifempty\p_language_font + \orelse\ifx\p_language_font\v!auto + \doaddfeature\currentlanguage + \else + \doaddfeature\p_language_font + \fi +\to \everylanguage + +%D Fast switcher + +\def\lang_basics_switch_asked + {\ifcsname\??languagelinked\askedlanguage\endcsname + \edef\askedlanguage{\lastnamedcs}% + \ifx\currentlanguage\askedlanguage \else + \setcurrentlanguage\currentmainlanguage\askedlanguage + \lang_basics_synchronize + \fi + \fi} + +\permanent\protected\def\uselanguageparameter#1% + {\edef\askedlanguage{#1\c!language}% + \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} + +\permanent\protected\def\douselanguageparameter#1% fast setter + {\edef\askedlanguage{#1}% + \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} + +\protected\def\lang_basics_set_current[#1]% + {\edef\askedlanguage{#1}% + \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} + +\pushoverloadmode + + \permanent\protected\def\language + {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage} + + \let\setlanguage\language % we make these synonyms + + \let\patterns\gobbleoneargument + +\popoverloadmode + +\newcount\mainlanguagenumber + +%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par} +%D inside the group! + +\permanent\protected\def\startlanguage + {\begingroup\language} + +\permanent\let\stoplanguage\endgroup + +\permanent\protected\def\mainlanguage[#1]% + {\edef\askedlanguage{#1}% + \ifempty\askedlanguage + \orelse\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 + \mainlanguagenumber\normallanguage} + +\appendtoks + \normallanguage\mainlanguagenumber +\to \everybeforepagebody + +%D Used at all? + +\permanent\def\splitsequence#1#2% + {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}} + +\permanent\def\splitsymbol#1% + {\splitsequence{#1}{\languageparameter\c!limittext}} + +%D Just like with subsentence boundary symbols, quotes placement depends on the +%D current language, therefore we show the defaults here. +%D +%D \def\ShowLanguageValues [#1] [#2] #3 #4 +%D {\blank +%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 [et] [estonian] ... +%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 loaded in separate files, +%D according to their roots. Here we only take care of (postponed) setting of the +%D current language. +%D +%D \unprotect +%D \placetable{The germanic languages (\type{lang-ger})} +%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 + +\permanent\protected\def\nopatterns{\normallanguage\minusone} + +%D We default to the language belonging to the interface. This is one of the few +%D places outside the interface modules where \type {\startinterface} is used. + +\setupcurrentlanguage[\s!en] + +\permanent\protected\def\initializemainlanguage + {\mainlanguage[\currentlanguage]% + \showmessage\m!languages9\currentlanguage} + +%D New: + +\permanent\let\stopexceptions\relax + +\tolerant\permanent\protected\def\startexceptions[#1]#:#2\stopexceptions + {\begingroup + \edef\askedlanguage{\reallanguagetag{#1}}% + \ifempty\askedlanguage + \let\askedlanguage\currentlanguage + \fi + \clf_setlanguageexceptions{\askedlanguage}{#2}% + \endgroup} + +\pushoverloadmode + +\permanent\protected\def\hyphenation + {\clf_setlanguageexceptions{\currentlanguage}} + +\popoverloadmode + +%D New: + +\permanent\protected\def\traceddiscretionary#1#% + {\dontleavehmode\lang_basics_traced_discretionary{#1}} + +\protected\def\lang_basics_traced_discretionary#1#2#3#4% + {\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}} + +\installtextracker + {discretionaries} + {\enforced\let\discretionary\traceddiscretionary} + {\enforced\let\discretionary\normaldiscretionary} + +\permanent\protected\def\samplediscretionary + {\traceddiscretionary + {pre\clf_currentprehyphenchar}% + {\clf_currentposthyphenchar post}% + {replace}} + +%D Also new: + +\immutable\chardef\nokerningcode \numexpr\noleftkerncode +\norightkerncode \relax +\immutable\chardef\noligaturingcode\numexpr\noleftligaturecode+\norightligaturecode\relax + +\permanent\protected\def\nokerning {\bitwiseflip\glyphoptions\nokerningcode} +\permanent\protected\def\noligaturing{\bitwiseflip\glyphoptions\noligaturingcode} + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-lab.mkxl b/tex/context/base/mkxl/lang-lab.mkxl new file mode 100644 index 000000000..8968631a0 --- /dev/null +++ b/tex/context/base/mkxl/lang-lab.mkxl @@ -0,0 +1,364 @@ +%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}{} +\registerctxluafile{lang-txt}{} + +\unprotect + +%D Left-overs: + +\ifdefined\sixperemspace \else + \permanent\def\sixperemspace{\normalUchar"2006} +\fi + +%D In this module we deal with language dependant labels and prefixes, like in {\em +%D Figure~12} and {\em Chapter 1}. In this file we set the default values. Users can +%D easily overrule these. +%D +%D This module is dedicated to the grandfather of Tobias Burnus, who's extensive +%D languages oriented library helped us a lot in finding the right translations. All +%D those labels are collected in files that reflect their common ancestor. +%D +%D Not all languages can be satisfied with the labeling mechanism as provided here. +%D Chinese for instance put a label in front as well as after a part number. This is +%D why the 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 call head and label +%D 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 + +\permanent\tolerant\protected\def\definelabelclass[#1]#*[#2]% + {\normalexpanded + {\lang_labels_define_class_indeed + {#1}% + {\ifchknum#2\or#2\else\zerocount\fi}% + \expandafter\noexpand\csname lang_labels_#1_text_1\endcsname + \expandafter\noexpand\csname #1language\endcsname + \expandafter\noexpand\csname lang_labels_#1_text_2\endcsname + \expandafter\noexpand\csname left#1text\endcsname + \expandafter\noexpand\csname right#1text\endcsname + \expandafter\noexpand\csname #1texts\endcsname + \expandafter\noexpand\csname #1text\endcsname}} + +% hm, not interfaced + +\let\thetextprefix\empty + +\protected\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9% + {\permanent\instance\setuvalue {setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% + \permanent\instance\setuvalue{preset#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% + \permanent\instance\setuvalue {copy#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_copy }% + \permanent\instance\setuvalue {start#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_start[#1]}% + \permanent\instance\letvalue {stop#1text}\relax + \permanent\instance\def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}% + \ifnum#2=\plustwo % used for math and tags + \instance\def#3{#5#4}% + \instance\def#5##1##2% ##1=language + {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname + \lastnamedcs + \orelse\ifcsname\??label#1:##1:##2\endcsname + \lastnamedcs + \orelse\ifcsname\??language##1\s!default\endcsname + \expandafter#5\lastnamedcs{##2}% + \orelse\ifcsname\??label\currentlabelcategory#1:##2\endcsname + \lastnamedcs + \orelse\ifcsname\??label#1:##2\endcsname + \lastnamedcs + \orelse\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname + \lastnamedcs + \orelse\ifcsname\??label#1:\s!en:##2\endcsname + \lastnamedcs + \else + ##2% + \fi}% + \permanent\instance\let#6\gobbleoneargument + \permanent\instance\let#7\gobbleoneargument + \permanent\instance\let#8\gobbletwoarguments + \permanent\instance\let#9#3% + \else + \instance\protected\def#3{#5#4}% + \instance\protected\def#5##1##2% + {\ifcsname\??label#1:##1:##2\endcsname + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs + \orelse\ifcsname\??language#4\s!default\endcsname + \expandafter#5\lastnamedcs{##2}% + \orelse\ifcsname\??label#1:##2\endcsname + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs + \orelse\ifcsname\??label#1:\s!en:##2\endcsname + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs + \else + \enforced\let\thetextprefix\dummytextprefix + \fi}% + \permanent\instance\protected\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% + \permanent\instance\protected\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}% + \permanent\instance\protected\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2 + \permanent\instance\protected\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% + \fi + \appendtoks + \enforced\permanent\instance\let#6\firstofoneargument % to be checked + \enforced\permanent\instance\let#7\firstofoneargument % to be checked + \enforced\permanent\instance\let#8\firstofoneargument % to be checked + \enforced\permanent\instance\let#9\firstofoneargument % to be checked + \to \everysimplifycommands} + +% why not lang_* ? + +\let\flushleftlabelclass \firstoftwoarguments +\let\flushrightlabelclass\secondoftwoarguments + +\permanent\def\flushbothlabelclass#1#2#3{#1#3#2} + +\permanent\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 texts without +%D replacing predefined ones. They are internal macros. + +\appendtoks \enforced\let\labellanguage\currentlanguage \to \everycurrentdate + +\newconstant\protecttextprefixes + +\let\currenttextprefixtag \s!unknown +\let\currenttextprefixclass\s!unknown + +\tolerant\def\lang_labels_text_prefix_start[#1]#*[#2]#*[#3]% class language name + {\ifarguments\or\or + \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% + \edef\currenttextprefixname{#2}% + \else + \edef\currenttextprefixtag{\reallanguagetag{#2}}% + \edef\currenttextprefixname{#3}% + \fi + \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed} + +\def\lang_labels_text_prefix_start_indeed#1% text (not special checking done here yet, only for long texts anyway) + {\edefcsname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname{{\clf_strip{#1}}\empty}} + +\tolerant\def\lang_labels_text_prefix_setup[#1]#*[#2]% + {\ifarguments\or + \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% + \processcommalist[#1]\lang_labels_text_prefix_setup_indeed + \else + \edef\currenttextprefixtag{\reallanguagetag{#1}}% + \processcommalist[#2]\lang_labels_text_prefix_setup_indeed + \fi} + +\def\lang_labels_text_prefix_setup_indeed#1% + {\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 + \defcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1% + \ifempty\m_lang_labels_right + \ifempty\m_lang_labels_left + \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]% + {\defcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}} + +\permanent\protected\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end + {%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}% + \defcsname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right + +\tolerant\def\lang_labels_text_prefix_copy[#1]#*[#2]% + {\ifarguments\or + \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% + \processcommalist[#1]\lang_labels_text_prefix_copy_indeed + \else + \edef\currenttextprefixtag{\reallanguagetag{#1}}% + \processcommalist[#2]\lang_labels_text_prefix_copy_indeed + \fi} + +\def\lang_labels_text_prefix_copy_indeed#1% + {\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} +% +% this delays the aliasing so that we can switch mainlanguage in between + +\def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]% + {\edefcsname\??label\currenttextprefixclass:#1\endcsname + {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#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 be typeset. Such +%D macros can be made (more) language 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 de current language. + +\installcorenamespace{translation} + +\permanent\tolerant\protected\def\translate[#1]% + {\getparameters[\??translation][#1]% + \ifcsname\??translation\currentlanguage\endcsname + \lastnamedcs + \orelse\ifcsname\??translation\s!en\endcsname + \lastnamedcs + \else + [translation #1]% + \fi} + +%D When used without argument, the last defined values are used. This enables +%D 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 translation to a macro. +%D Its form is: +%D +%D \starttyping +%D \assigntranslation[en=something,nl=iets]\to\command +%D \stoptyping + +% nicer is \edef\command{\translated[...]} ... todo + +\permanent\protected\def\assigntranslation[#1]\to#2% bad, this \to + {\getparameters[\??translation][#1]% + \edef#2{\begincsname\??translation\currentlanguage\endcsname}} + +%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 + +\permanent\tolerant\protected\def\commalistsentence[#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): + +\permanent\protected\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases! + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-mis.mkxl b/tex/context/base/mkxl/lang-mis.mkxl new file mode 100644 index 000000000..de15ec526 --- /dev/null +++ b/tex/context/base/mkxl/lang-mis.mkxl @@ -0,0 +1,586 @@ +%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. + +%D This one will be updated stepwise to \LMTX. See lang-mis.mkiv for previous +%D implementations and removed code. + +\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 +%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. + +% hm why ex + +\ifx\compoundhyphen\undefined + \permanent\protected\def\compoundhyphen{\hbox{-\kern-.10775\emwidth-}} % .25\exheight +\fi + +%D The last two variables are needed for subsentences |<|like this one|>| which we +%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 \permanent\protected\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi +\ifx\postwordbreak\undefined \permanent\protected\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi +\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % will be overloaded + +%frozen\protected\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces +\permanent\protected\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces + +%D \macros +%D {beginofsubsentence,endofsubsentence, +%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. + +%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}2xxx + +\def\lang_discretionaries_hyphen_like#1#2% + {\ifconditional\spaceafterdiscretionary + %prewordbreak\hbox{#1}\relax + \wordboundary\hbox{#1}\relax + \orelse\ifconditional\punctafterdiscretionary + %prewordbreak\hbox{#1}\relax + \wordboundary\hbox{#1}\relax + \else + %\prewordbreak#2\postwordbreak % was prewordbreak + \wordboundary#2\wordboundary + \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 + (\wordboundary + \else + %\prewordbreak\discretionary{}{(-}{(}\prewordbreak + \wordboundary\discretionary{}{(-}{(}\wordboundary + %\discretionary options \plusthree{}{(-}{(}% + \fi} + +\definetextmodediscretionary ~ + %{\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak} + {\wordboundary\discretionary{-}{}{\thinspace}\wordboundary} + %{\discretionary options \plusthree{-}{}{\thinspace}} + +\definetextmodediscretionary ' + %{\prewordbreak\discretionary{-}{}{'}\postwordbreak} + {\wordboundary\discretionary{-}{}{'}\wordboundary} + %{\discretionary options \plusthree{-}{}{'}} + +\definetextmodediscretionary ^ + %{\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% + % \postwordbreak} % bugged + {\wordboundary + \discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% + \wordboundary} % bugged + %{\discretionary options \plusthree{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}} + +\definetextmodediscretionary < + %{\beginofsubsentence\prewordbreak\beginofsubsentencespacing + {\beginofsubsentence\wordboundary\beginofsubsentencespacing + \aftergroup\ignorespaces} % tricky, we need to go over the \nextnextnext + +\definetextmodediscretionary > + {\removeunwantedspaces + %\endofsubsentencespacing\prewordbreak\endofsubsentence} + \endofsubsentencespacing\wordboundary\endofsubsentence} + +\definetextmodediscretionary = + {\removeunwantedspaces + %\prewordbreak\midsentence\prewordbreak + \wordboundary\midsentence\wordboundary + \aftergroup\ignorespaces} + +% french + +%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:} +%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};} +%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?} +%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!} + +\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{:}:} +\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{;};} +\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{?}?} +\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{!}!} + +%definetextmodediscretionary * {\prewordbreak\discretionary{-}{}{\kern.05\emwidth}\prewordbreak} +\definetextmodediscretionary * {\wordboundary\discretionary{-}{}{\kern.05\emwidth}\wordboundary} + +% spanish + +%definetextmodediscretionary ?? {\prewordbreak\questiondown} +%definetextmodediscretionary !! {\prewordbreak\exclamdown} + +\definetextmodediscretionary ?? {\wordboundary\questiondown} +\definetextmodediscretionary !! {\wordboundary\exclamdown} + +%D \installdiscretionary | + +%D \installdiscretionary + = + +\permanent\protected\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 + +\permanent\protected\def\fakecompoundhyphen + {\enforced\permanent\protected\def\|{\mathortext\vert\lang_compounds_fake_hyphen}} + +\def\lang_compounds_fake_hyphen + {\enforced\permanent\protected\def##1|% + {\doifelsenothing{##1}\compoundhyphen{##1}% + \kern\d_lang_discretionaries_breakpoint + \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. + +\permanent\protected\def\midworddiscretionary + {\futurelet\nexttoken\lang_discretionaries_mid_word} + +\def\lang_discretionaries_mid_word + {\ifx\nexttoken\blankspace\orelse + \ifx\nexttoken\bgroup \orelse + \ifx\nexttoken\egroup \orelse + \discretionary{-}{}{}% + \fi} + +\let\ignorecompoundcharacter\relax + +%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 + + \permanent\protected\gdef\compound#1{|#1|} + + \doglobal \appendtoks + \enforced\permanent\protected\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 + +%D Here: +%D +%D \startbuffer +%D {\red somelongword}{\blue \compounddiscretionary}{\green somelongword} +%D \stopbuffer +%D +%D \typebuffer \blank {\hsize3mm\getbuffer\par} \blank + +\permanent\protected\def\compounddiscretionary + {\discretionary + options \plusthree + {\ifnum\prehyphenchar >\zerocount\char\prehyphenchar \fi}% + {\ifnum\posthyphenchar>\zerocount\char\posthyphenchar\fi}% + {\ifnum\posthyphenchar>\zerocount\char\posthyphenchar\fi}} + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-rep.mkxl b/tex/context/base/mkxl/lang-rep.mkxl new file mode 100644 index 000000000..36e484242 --- /dev/null +++ b/tex/context/base/mkxl/lang-rep.mkxl @@ -0,0 +1,74 @@ +%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}{} + +\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 + +\permanent\protected\def\setreplacements[#1]% + {\clf_setreplacements{#1}} + +\permanent\protected\def\resetreplacements + {\c_attr_replacements\attributeunsetvalue} + +\permanent\tolerant\protected\def\replaceword[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \clf_addreplacementslist{#1}{#2}% + \or + \clf_addreplacements{#1}{#2}{#3}% + \fi} + +\appendtoks + \resetreplacements +\to \everyresettypesetting + +\appendtoks + \resetreplacements +\to \everyinitializeverbatim + +\protect \endinput diff --git a/tex/context/base/mkxl/lang-spa.mkxl b/tex/context/base/mkxl/lang-spa.mkxl new file mode 100644 index 000000000..3e4972acb --- /dev/null +++ b/tex/context/base/mkxl/lang-spa.mkxl @@ -0,0 +1,74 @@ +%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 support for French (with the +%D 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{!}!} + +\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{:}:} +\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{;};} +\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{?}?} +\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{!}!} + +%D \startbuffer +%D \mainlanguage[en] \quotation{test \quotation{test} test}\par +%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/tex/context/base/mkxl/lang-tra.mkxl b/tex/context/base/mkxl/lang-tra.mkxl new file mode 100644 index 000000000..b087832e0 --- /dev/null +++ b/tex/context/base/mkxl/lang-tra.mkxl @@ -0,0 +1,95 @@ +%D \module +%D [ file=lang-tra, +%D version=2020.10.31, +%D title=\CONTEXT\ Language Macros, +%D subtitle=Transliteration, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Transliteration} + +\registerctxluafile{lang-tra}{} + +\unprotect + +\definesystemattribute[transliteration][public,global] + +\installcorenamespace {transliteration} + +\permanent\tolerant\protected\def\definetransliteration[#1]#*[#2]% + {\clf_definedtransliteration{#1}{#2}} + +\permanent\protected\def\settransliteration[#1]% + {\clf_settransliteration{#1}} + +\permanent\protected\def\starttransliteration[#1]% + {\begingroup + \clf_settransliteration{#1}} + +\permanent\protected\def\stoptransliteration + {\endgroup} + +\permanent\protected\def\resettransliteration + {\c_attr_transliteration\attributeunsetvalue} + +\appendtoks + \resettransliteration +\to \everyinitializeverbatim + +\protect \endinput + +% \setupbodyfont[dejavu] +% +% \input lang-tra.mkiv +% +% \definetransliteration[serbian][serbian to latin] +% +% \starttext +% +% \settransliteration[serbian to latin] +% +% \startchapter[title={АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ}] +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \start +% \settransliteration[serbian to latin] +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \stop +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \stopchapter +% +% \resettransliteration +% +% \startchapter[title={АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ}] +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \start +% \settransliteration[serbian to latin] +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \stop +% АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ +% \stopchapter +% +% \definehead[ChapterA][chapter] +% \definehead[ChapterB][chapter] +% +% \startsetups s-to-l +% \settransliteration[serbian to latin] +% \red +% \stopsetups +% +% % maybe we need a setups key for this +% % hm, \definesetups [xxx] [aa,bb,cc] +% +% \setuphead[ChapterB][commandbefore=\setups{s-to-l}] +% +% \startChapterA[title={АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ}] +% \stopChapterA +% +% \startChapterB[title={АБВ ГДЕ ЖЗИЙ КЛМНОП РСТУ ФХЦЧ ШЩЪЬ ЮЯ}] +% \stopChapterB +% +% \stoptext diff --git a/tex/context/base/mkxl/lang-url.mkxl b/tex/context/base/mkxl/lang-url.mkxl new file mode 100644 index 000000000..bb51f838a --- /dev/null +++ b/tex/context/base/mkxl/lang-url.mkxl @@ -0,0 +1,167 @@ +%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}{} + +\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 + % + \enforced\let\&\letterampersand + \enforced\let\#\letterhash + \enforced\let\~\lettertilde + \enforced\let\\\letterbackslash + \enforced\let\$\letterdollar + \enforced\let\^\letterhat + \enforced\let\_\letterunderscore + \enforced\let\{\letterleftbrace + \enforced\let\}\letterrightbrace + \enforced\let\|\letterbar + \enforced\let~=\lettertilde + \enforced\let|=\letterbar + \enforced\let\Ux\eUx +\to \everyhyphenatedurl + +\let\hyphenatedurlseparator \empty % \periodcentered +\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} + +\permanent\protected\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 + +\permanent\protected\def\sethyphenatedurlnormal#1{\clf_sethyphenatedurlcharacters{#1}{\v!normal}} +\permanent\protected\def\sethyphenatedurlbefore#1{\clf_sethyphenatedurlcharacters{#1}{\v!before}} +\permanent\protected\def\sethyphenatedurlafter #1{\clf_sethyphenatedurlcharacters{#1}{\v!after }} + +% \sethyphenatedurlafter{ABCDEF} + +\permanent\protected\def\hyphenatedurl#1% + {\dontleavehmode + \begingroup + \the\everyhyphenatedurl + \normallanguage\zerocount % \nohyphens in mkiv + \scratchskipone\zeropoint\s!plus\dimexpr\emwidth/12\s!minus\dimexpr\emwidth/24\relax % 1.00pt @ 12pt + \scratchskiptwo\zeropoint\s!plus\dimexpr\emwidth/48\s!minus\dimexpr\emwidth/96\relax % 0.25pt @ 12pt + \unprotect + \normalexpanded{\noexpand\clf_hyphenatedurl + {\noexpand\detokenize{#1}}% + \hyphenatedurllefthyphenmin + \hyphenatedurlrighthyphenmin + {\hyphenatedurldiscretionary}% + }% + \protect + \endgroup} + +%D \macros +%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 \aliased\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] +% +% \protected\def\WhateverA#1% +% {\dontleavehmode +% \begingroup +% \prehyphenchar"B7\relax +% \setbox\scratchbox\hbox{\tttf#1}% +% \prehyphenchar`-\relax +% \unhbox\scratchbox +% \endgroup} +% +% \protected\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/tex/context/base/mkxl/lang-wrd.mkxl b/tex/context/base/mkxl/lang-wrd.mkxl new file mode 100644 index 000000000..d0964a677 --- /dev/null +++ b/tex/context/base/mkxl/lang-wrd.mkxl @@ -0,0 +1,67 @@ +%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}{} + +\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 + +\permanent\tolerant\protected\def\loadspellchecklist[#1]#*[#2]% can be public implementor + {\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/tex/context/base/mkxl/layo-ini.mkxl b/tex/context/base/mkxl/layo-ini.mkxl new file mode 100644 index 000000000..4979989cd --- /dev/null +++ b/tex/context/base/mkxl/layo-ini.mkxl @@ -0,0 +1,30 @@ +%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 and code from other +%D modules will move here. This will make 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}{} + +\protect \endinput diff --git a/tex/context/base/mkxl/libs-imp-curl.lmt b/tex/context/base/mkxl/libs-imp-curl.lmt new file mode 100644 index 000000000..b30739794 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-curl.lmt @@ -0,0 +1,296 @@ +if not modules then modules = { } end modules ['libs-imp-curl'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/curl/libcurl.dll + +local libname = "curl" +local libfile = "libcurl" + +local curllib = resolvers.libraries.validoptional(libname) + +if not curllib then return end + +-- We're good, so we continue. + +local next, type = next, type +local lower, gsub = string.lower, string.gsub + +local mapping = { + ["acceptencoding"] = 102, + ["accepttimeoutms"] = 212, + ["addressscope"] = 171, + ["append"] = 50, + ["autoreferer"] = 58, + ["buffersize"] = 98, + ["cainfo"] = 65, + ["capath"] = 97, + ["certinfo"] = 172, + -- ["chunkbgnfunction"] = 198, + ["chunkdata"] = 201, + -- ["chunkendfunction"] = 199, + ["closepolicy"] = 72, + ["closesocketdata"] = 209, + -- ["closesocketfunction"] = 208, + ["connectonly"] = 141, + ["connecttimeout"] = 78, + ["connecttimeoutms"] = 156, + -- ["convfromnetworkfunction"] = 142, + -- ["convfromutf8function"] = 144, + -- ["convtonetworkfunction"] = 143, + ["cookie"] = 22, + ["cookiefile"] = 31, + ["cookiejar"] = 82, + ["cookielist"] = 135, + ["cookiesessionv"] = 96, + ["copypostfields"] = 165, + ["crlf"] = 27, + ["crlfile"] = 169, + ["customrequest"] = 36, + ["debugdata"] = 95, + -- ["debugfunction"] = 94, + ["dirlistonly"] = 48, + ["dnscachetimeout"] = 92, + ["dnsinterface"] = 221, + ["dnslocalip4"] = 222, + ["dnslocalip6"] = 223, + ["dnsservers"] = 211, + ["dnsuseglobalcache"] = 91, + ["egdsocket"] = 77, + ["errorbuffer"] = 10, + ["expect100timeoutms"] = 227, + ["failonerror"] = 45, + ["file"] = 1, + ["filetime"] = 69, + ["fnmatchdata"] = 202, + -- ["fnmatchfunction"] = 200, + ["followlocation"] = 52, + ["forbidreuse"] = 75, + ["freshconnect"] = 74, + ["ftpaccount"] = 134, + ["ftpalternativetouser"] = 147, + ["ftpcreatemissingdirs"] = 110, + ["ftpfilemethod"] = 138, + ["ftpresponsetimeout"] = 112, + ["ftpskippasvip"] = 137, + ["ftpsslccc"] = 154, + ["ftpuseeprt"] = 106, + ["ftpuseepsv"] = 85, + ["ftpusepret"] = 188, + ["ftpport"] = 17, + ["ftpsslauth"] = 129, + ["gssapidelegation"] = 210, + ["header"] = 42, + ["headerdata"] = 29, + -- ["headerfunction"] = 79, + ["http200aliases"] = 104, + ["httpcontentdecoding"] = 158, + ["httptransferdecoding"] = 157, + ["httpversion"] = 84, + ["httpauth"] = 107, + ["httpget"] = 80, + ["httpheader"] = 23, + ["httppost"] = 24, + ["httpproxytunnel"] = 61, + ["ignorecontentlength"] = 136, + ["infile"] = 9, + ["infilesize"] = 14, + ["infilesizelarge"] = 115, + ["interface"] = 62, + ["interleavedata"] = 195, + -- ["interleavefunction"] = 196, + ["ioctldata"] = 131, + -- ["ioctlfunction"] = 130, + ["ipresolve"] = 113, + ["issuercert"] = 170, + ["keypasswd"] = 26, + ["krblevel"] = 63, + ["localport"] = 139, + ["localportrange"] = 140, + ["loginoptions"] = 224, + ["lowspeedlimit"] = 19, + ["lowspeedtime"] = 20, + ["mailauth"] = 217, + ["mailfrom"] = 186, + ["mailrcpt"] = 187, + ["maxrecvspeedlarge"] = 146, + ["maxsendspeedlarge"] = 145, + ["maxconnects"] = 71, + ["maxfilesize"] = 114, + ["maxfilesizelarge"] = 117, + ["maxredirs"] = 68, + ["netrc"] = 51, + ["netrcfile"] = 118, + ["newdirectoryperms"] = 160, + ["newfileperms"] = 159, + ["nobody"] = 44, + ["noprogress"] = 43, + ["noproxy"] = 177, + ["nosignal"] = 99, + ["opensocketdata"] = 164, + -- ["opensocketfunction"] = 163, + ["password"] = 174, + ["port"] = 3, + ["post"] = 47, + -- ["postfields"] = 15, + -- ["postfieldsize"] = 60, + -- ["postfieldsizelarge"] = 120, + ["postquote"] = 39, + ["postredir"] = 161, + ["prequote"] = 93, + ["private"] = 103, + ["progressdata"] = 57, + -- ["progressfunction"] = 56, + ["protocols"] = 181, + ["proxy"] = 4, + ["proxytransfermode"] = 166, + ["proxyauth"] = 111, + ["proxypassword"] = 176, + ["proxyport"] = 59, + ["proxytype"] = 101, + ["proxyusername"] = 175, + ["proxyuserpwd"] = 6, + ["put"] = 54, + ["quote"] = 28, + ["randomfile"] = 76, + ["range"] = 7, + ["readdata"] = 9, + -- ["readfunction"] = 12, + ["redirprotocols"] = 182, + ["referer"] = 16, + ["resolve"] = 203, + ["resumefrom"] = 21, + ["resumefromlarge"] = 116, + ["rtspclientcseq"] = 193, + ["rtsprequest"] = 189, + ["rtspservercseq"] = 194, + ["rtspsessionid"] = 190, + ["rtspstreamuri"] = 191, + ["rtsptransport"] = 192, + ["rtspheader"] = 23, + ["saslir"] = 218, + ["seekdata"] = 168, + -- ["seekfunction"] = 167, + ["serverresponsetimeout"] = 112, + ["share"] = 100, + ["sockoptdata"] = 149, + -- ["sockoptfunction"] = 148, + ["socks5gssapinec"] = 180, + ["socks5gssapiservice"] = 179, + ["sshauthtypes"] = 151, + ["sshhostpublickeymd5"] = 162, + ["sshkeydata"] = 185, + -- ["sshkeyfunction"] = 184, + ["sshknownhosts"] = 183, + ["sshprivatekeyfile"] = 153, + ["sshpublickeyfile"] = 152, + ["sslcipherlist"] = 83, + ["sslctxdata"] = 109, + -- ["sslctxfunction"] = 108, + ["sslenablealpn"] = 226, + ["sslenablenpn"] = 225, + ["ssloptions"] = 216, + ["sslsessionidcache"] = 150, + ["sslverifyhost"] = 81, + ["sslverifypeer"] = 64, + ["sslcert"] = 25, + ["sslcerttype"] = 86, + ["sslengine"] = 89, + ["sslenginedefault"] = 90, + ["sslkey"] = 87, + ["sslkeytype"] = 88, + ["sslversion"] = 32, + ["stderr"] = 37, + ["tcpkeepalive"] = 213, + ["tcpkeepidle"] = 214, + ["tcpkeepintvl"] = 215, + ["tcpnodelay"] = 121, + ["telnetoptions"] = 70, + ["tftpblksize"] = 178, + ["timecondition"] = 33, + ["timeout"] = 13, + ["timeoutms"] = 155, + ["timevalue"] = 34, + ["tlsauthpassword"] = 205, + ["tlsauthtype"] = 206, + ["tlsauthusername"] = 204, + ["transferencoding"] = 207, + ["transfertext"] = 53, + ["unrestrictedauth"] = 105, + ["upload"] = 46, + ["url"] = 2, + ["usessl"] = 119, + ["useragent"] = 18, + ["username"] = 173, + ["userpwd"] = 5, + ["verbose"] = 41, + ["wildcardmatch"] = 197, + ["writedata"] = 1, + -- ["writefunction"] = 11, + ["writeheader"] = 29, + ["writeinfo"] = 40, + ["xferinfodata"] = 57, + -- ["xferinfofunction"] = 219, + ["xoauth2bearer"] = 220, +} + +table.setmetatableindex(mapping,function(t,k) + local s = gsub(lower(k),"[^a-z0-9]","") + local v = rawget(t,s) or false + t[k] = v + return v +end) + +local curl_fetch = curllib.fetch +local curl_escape = curllib.escape +local curl_unescape = curllib.unescape +local curl_getversion = curllib.getversion + +local report = logs.reporter(libname) + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local function fetch(options) + if okay() then + local t = type(options) + if t == "table" then + local o = { } + for name, value in next, options do + local index = mapping[name] + if index then + o[index] = value + end + end + return curl_fetch(o) + elseif t == "string" then + return curl_fetch { [mapping.url] = options } + else + report("invalid argument") + end + end +end + +local curl = { + getversion = function () return okay() and curl_getversion() end, + escape = function (s) return okay() and curl_escape (s) end, + unescape = function (s) return okay() and curl_unescape (s) end, + fetch = fetch, +} + +-- inspect(curl.fetch("http://www.pragma-ade.com/index.html")) +-- inspect(curl.fetch { url = "http://www.pragma-ade.com/index.html" }) + +package.loaded[libname] = curl + +return curl diff --git a/tex/context/base/mkxl/libs-imp-ghostscript.lmt b/tex/context/base/mkxl/libs-imp-ghostscript.lmt new file mode 100644 index 000000000..b129a58c1 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-ghostscript.lmt @@ -0,0 +1,111 @@ +if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "ghostscript" +local libfile = "gsdll64" -- what on unix? + +local gslib = resolvers.libraries.validoptional(libname) + +if not gslib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local insert = table.insert +local formatters = string.formatters + +local ghostscript = utilities.ghostscript or { } +utilities.ghostscript = ghostscript + +local gs_execute = gslib.execute +local nofruns = 0 +local report = logs.reporter(libname) + +function ghostscript.convert(specification) + if okay() then + -- + nofruns = nofruns + 1 + statistics.starttiming(ghostscript) + -- + local inputname = specification.inputname + if not inputname or inputname == "" then + report("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("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 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("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) + report("") + local done = gslib_execute(options) + report("") + -- + statistics.stoptiming(ghostscript) + if done then + return outputname + else + report("run %s quit with errors",nofruns) + return false + end + end +end + +function ghostscript.statistics(report) + local runtime = statistics.elapsedtime(ghostscript) + if report then + report("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/tex/context/base/mkxl/libs-imp-graphicsmagick.lmt b/tex/context/base/mkxl/libs-imp-graphicsmagick.lmt new file mode 100644 index 000000000..6f5d1d967 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-graphicsmagick.lmt @@ -0,0 +1,77 @@ +if not modules then modules = { } end modules ['libs-imp-graphicsmagick'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "graphicsmagick" +local libfile = { "CORE_RL_magick_", "CORE_RL_wand_" } + +local gmlib = resolvers.libraries.validoptional(libname) + +if not gmlib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local graphicsmagick = utilities.graphicsmagick or { } +utilities.graphicsmagick = graphicsmagick +utilities.graphicmagick = graphicsmagick + +local gm_execute = gmlib.execute +local nofruns = 0 +local report = logs.reporter(libname) + +function graphicsmagick.convert(specification) + if okay() then + -- + nofruns = nofruns + 1 + statistics.starttiming(graphicsmagick) + -- + local inputname = specification.inputname + if not inputname or inputname == "" then + report("invalid run %s, no inputname specified",nofruns) + statistics.stoptiming(graphicsmagick) + 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("invalid run %s, input file %a is not found",nofruns,inputname) + statistics.stoptiming(graphicsmagick) + return false + end + -- + report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) + -- + gm_execute { inputfile = inputname, outputfile = outputname } + -- + statistics.stoptiming(graphicsmagick) + end +end + +function graphicsmagick.statistics(report) + local runtime = statistics.elapsedtime(graphicsmagick) + if report then + report("nofruns %s, runtime %s",nofruns,runtime) + else + return { + runtime = runtime, + nofruns = nofruns, + } + end +end + +-- graphicsmagick.convert { inputname = "t:/sources/hacker.jpg", outputname = "e:/tmp/hacker.png" } +-- graphicsmagick.statistics(true) diff --git a/tex/context/base/mkxl/libs-imp-kpse.lmt b/tex/context/base/mkxl/libs-imp-kpse.lmt new file mode 100644 index 000000000..f8e4a9907 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-kpse.lmt @@ -0,0 +1,58 @@ +if not modules then modules = { } end modules ['libs-imp-kpse'] = { + version = 1.001, + comment = "companion to luat-imp-kpse.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. It might make sense to have this available in case I want +-- more runners to use LuaMetaTeX in which case (as with mtxrun using LuaTeX) we +-- need to load kpse. + +local libname = "kpse" +local libfile = (os.platform == "win64" and "kpathsea*w64") + or (os.platform == "win32" and "kpathsea*w32") + or "libkpathsea" +local libkpse = resolvers.libraries.validoptional(libname) + +if package.loaded[libname] then + return package.loaded[libname] +end + +-- This is a variant that loaded directly: + +-- kpse = libkpse -- the library will issue warnings anyway +-- +-- resolvers.libraries.optionalloaded(libname,libfile) -- no need to chedk if true + +-- This variant delays loading and has a bit more protection: + +local function okay() + if libkpse and resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local kpse = { } + +for k, v in next, libkpse do + kpse[k] = function(...) if okay() then return v(...) end end +end + +-- We properly register the module: + +package.loaded[libname] = kpse + +optional.loaded.kpse = kpse + +-- A simple test: + +-- kpse.set_program_name("pdftex") +-- print("find file:",kpse.find_file("oeps.tex")) +-- print("find file:",kpse.find_file("context.mkii")) + +return kpse diff --git a/tex/context/base/mkxl/libs-imp-kpse.mkxl b/tex/context/base/mkxl/libs-imp-kpse.mkxl new file mode 100644 index 000000000..f76c99029 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-kpse.mkxl @@ -0,0 +1,38 @@ +%D \module +%D [ file=libs-imp-kpse, +%D version=2020.05.19, +%D title=\CONTEXT\ System Modules, +%D subtitle=KPSE File Searching, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 not really a module. It's more some left over from an experiment. Who +%D know when it comes in handy; probably never in a real run, but I might want to +%D make a \LUAMETATEX\ plain format one day, just for the fun of it. + +% \registerctxluafile{libs-imp-kpse}{autosuffix} + +\continueifinputfile{libs-imp-kpse.mkxl} + +\starttext + +\startTEXpage + \startluacode + local kpse = require("libs-imp-kpse") + + kpse.set_program_name("pdftex") + + local name = "context.mkii" + + context("%s: %s",name,kpse.find_file(name)) + \stopluacode +\stopTEXpage + +\stoptext + + diff --git a/tex/context/base/mkxl/libs-imp-mujs.lmt b/tex/context/base/mkxl/libs-imp-mujs.lmt new file mode 100644 index 000000000..264c8e531 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-mujs.lmt @@ -0,0 +1,126 @@ +if not modules then modules = { } end modules ['libs-imp-mujs'] = { + version = 1.001, + comment = "companion to luat-imp-mujs.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a +-- stepping stone to using \LUA. + +-- local ecmascript = optional.mujs.initialize("libmujs") +-- local execute = optional.mujs.execute + +local libname = "mujs" +local libfile = "libmujs" + +if package.loaded[libname] then + return package.loaded[libname] +end + +local mujslib = resolvers.libraries.validoptional(libname) + +if not mujslib then + return +end + +local files = { } +local openfile = io.open +local findfile = resolvers.findfile + +local mujs_execute = mujslib.execute +local mujs_dofile = mujslib.dofile +local mujs_reset = mujslib.reset + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + mujs_execute( + "var catcodes = { " .. + "'tex': " .. tex.texcatcodes .. "," .. + "'ctx': " .. tex.ctxcatcodes .. "," .. + "'prt': " .. tex.prtcatcodes .. "," .. + "'vrb': " .. tex.vrbcatcodes .. "," .. + "};" + ) + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +mujslib.setfindfile(findfile) + +mujslib.setopenfile(function(name) + local full = findfile(name) + if full then + local f = openfile(full,"rb") + if f then + for i=1,100 do + if not files[i] then + files[i] = f + return i + end + end + end + end +end) + +mujslib.setclosefile(function(id) + local f = files[id] + if f then + f:close() + files[id] = false + end +end) + +mujslib.setreadfile(function(id,how) + local f = files[id] + if f then + return (f:read(how or "*l")) + end +end) + +mujslib.setseekfile(function(id,whence,offset) + local f = files[id] + if f then + return (f:seek(whence,offset)) + end +end) + +local reporters = { + console = logs.reporter("mujs","console"), + report = logs.reporter("mujs","report"), +} + +mujslib.setconsole(function(category,name) + reporters[category](name) +end) + +local mujs = { + ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, + ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, + ["reset"] = function(n) if okay() then mujs_reset(n) end end, +} + +package.loaded[libname] = mujs + +optional.loaded.mujs = mujs + +interfaces.implement { + name = "ecmacode", + actions = mujs.execute, + arguments = "string", + public = true, +} + +interfaces.implement { + name = "ecmafile", + actions = mujs.dofile, + arguments = "string", + public = true, + protected = true, +} + +return mujs diff --git a/tex/context/base/mkxl/libs-imp-mujs.mkxl b/tex/context/base/mkxl/libs-imp-mujs.mkxl new file mode 100644 index 000000000..a8fe5801f --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-mujs.mkxl @@ -0,0 +1,121 @@ +%D \module +%D [ file=libs-imp-mujs, +%D version=2020.02.08, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=MuJS interpreter, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 an experiment: +%D +%D \starttyping +%D http://mujs.com +%D \stoptyping + +\ifdefined\ecmacode + \expandafter \endinput +\fi + +\registerctxluafile{libs-imp-mujs}{autosuffix} + +\unprotect + +% todo: environment + +\let\stopecmacode\relax + +\protected\def\startecmacode % \stopecmacode + {\begingroup + \obeylualines + \obeyluatokens + \luat_start_ecma_code_indeed} + +\def\luat_start_ecma_code_indeed#1\stopecmacode + {\normalexpanded{\endgroup\noexpand\ecmacode{#1}}} + +\protect + +\continueifinputfile{libs-imp-mujs.mkxl} + +\usemodule[article-basic,abbreviations-logos] + +\starttext + +\startbuffer +\startluacode + local mujs = require("libs-imp-mujs") + + mujs.execute [[ + var MyMax = 1000; + ]] + + mujs.execute [[ + console("Example One!"); + texsprint("\\startpacked"); + for (var i = 1; i <= MyMax; i = i + 1) { + texprint( + "This is a buildbot compilation challenge for Mojca: " + .concat(Math.sqrt(i/MyMax)) + .concat("!\\par") + ); + } + texsprint("\\stoppacked"); + ]] + + -- mujs.execute [[ + -- something very bad: an error + -- ]] +\stopluacode + +\startecmacode + console("Example Two!"); + for (var i = 1; i <= MyMax; i = i + 1) { + texsprint( + "And an opportunity for Alan to attract highschool students to \\TeX: " + .concat(i) + .concat("! ") + ); + } +\stopecmacode + +\ecmacode { + console("Example Three!"); + texprint("And otherwise a way to prototype \\JAVASCRIPT\\ code in \\PDF.") +} + +\startecmacode + var f = File("libs-imp-mujs.mkxl","r"); + console(f); + // var l = f.read(400); + var l = f.read("*a"); + console(l); + f.close(); +\stopecmacode + +\startecmacode + console("Example Four!"); + texsprint("\\startMPcode " + .concat(' fill fullcircle scaled 6cm withcolor "darkred";') + .concat(' fill fullcircle scaled 4cm withcolor "darkgreen";') + .concat(' fill fullcircle scaled 2cm withcolor "darkblue";') + .concat("\\stopMPcode ") + ); +\stopecmacode + +\startluacode + context.startMPcode() + context('fill fullcircle scaled 6cm withcolor "middlecyan";') + context('fill fullcircle scaled 4cm withcolor "middlemagenta";') + context('fill fullcircle scaled 2cm withcolor "middleyellow";') + context.stopMPcode() +\stopluacode +\stopbuffer + +\typebuffer \page \getbuffer + +\stoptext diff --git a/tex/context/base/mkxl/libs-imp-mysql.lmt b/tex/context/base/mkxl/libs-imp-mysql.lmt new file mode 100644 index 000000000..3e938a6de --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-mysql.lmt @@ -0,0 +1,220 @@ +if not modules then modules = { } end modules ['libs-imp-mysql'] = { + 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" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/mysql/libmysql.dll + +local libname = "mysql" +local libfile = "libmysql" + +local mysqllib = resolvers.libraries.validoptional(libname) + +if not mysqllib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local lpegmatch = lpeg.match +local setmetatable = setmetatable + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +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 mysql_open = mysqllib.open +local mysql_close = mysqllib.close +local mysql_execute = mysqllib.execute +local mysql_getmessage = mysqllib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local querysplitter = helpers.querysplitter +local cache = { } +local timeout -- = 3600 -- to be tested + +local function connect(specification) + local db = mysql_open( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) + if db and timeout then + mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) + end + return db +end + +local function execute_once(specification,retry) + if okay() then + if trace_sql then + report("executing mysql") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + else + query = lpegmatch(querysplitter,query) + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local result = { } + local keys = { } + local id = specification.id + local db = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = connect(specification) + if not db then + report("no session database specified") + else + cache[id] = { + specification = specification, + db = db, + } + end + end + else + db = connect(specification) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if converter then + local convert = converter.mysql + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + for i=1,#query do + local okay = mysql_execute(db,query[i],callback) + if not okay then + if id and retry and i == 1 then + report("error: %s, retrying to connect",mysql_getmessage(db)) + mysql_close(db) + cache[id] = nil + return execute_once(specification,false) + else + report("error: %s",mysql_getmessage(db)) + end + end + end + end + if db and not id then + mysql_close(db) + end + -- bonus + local one = result[1] + if one then + setmetatable(result,{ __index = one } ) + end + -- + return result, keys + else + report("error: ","no library loaded") + end +end + +local function execute(specification) + return execute_once(specification,true) +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(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +-- return function(result) +-- if not result then +-- return { } +-- end +-- local nofrows = #result +-- if nofrows == 0 then +-- return { } +-- end +-- local target = { } -- no %s needed here +-- for i=1,nofrows do +-- target[%s] = { +-- %s +-- } +-- end +-- return result +-- end + +local celltemplate = "cells[%s]" + +methods.mysql = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-ffi"] = methods.mysql +package.loaded["util-sql-imp-mysql"] = methods.mysql +package.loaded["util-sql-imp-library"] = methods.mysql +package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkxl/libs-imp-postgress.lmt b/tex/context/base/mkxl/libs-imp-postgress.lmt new file mode 100644 index 000000000..629079b01 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-postgress.lmt @@ -0,0 +1,200 @@ +if not modules then modules = { } end modules ['libs-imp-postgress'] = { + 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" +} + +-- Not yet untested ! + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/postgress/libpq.dll + +-- we can now share the code between mysql, postgress, sqlite ... todo + +local libname = "postgress" +local libfile = "libpq" + +local postgresslib = resolvers.libraries.validoptional(libname) + +if not postgresslib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local lpegmatch = lpeg.match +local setmetatable = setmetatable + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +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 postgress_open = postgresslib.open +local postgress_close = postgresslib.close +local postgress_execute = postgresslib.execute +local postgress_getmessage = postgresslib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local querysplitter = helpers.querysplitter -- not needed +local cache = { } + +local function connect(specification) + return postgress_open( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) +end + +local function execute_once(specification,retry) + if okay() then + if trace_sql then + report("executing postgress") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + else + query = lpegmatch(querysplitter,query) -- not needed + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local result = { } + local keys = { } + local id = specification.id + local db = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = connect(specification) + if not db then + report("no session database specified") + else + cache[id] = { + specification = specification, + db = db, + } + end + end + else + db = connect(specification) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if converter then + local convert = converter.postgress + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + for i=1,#query do + local okay = postgress_execute(db,query[i],callback) + if not okay then + if id and retry and i == 1 then + report("error: %s, retrying to connect",postgress_getmessage(db)) + postgress_close(db) + cache[id] = nil + return execute_once(specification,false) + else + report("error: %s",postgress_getmessage(db)) + end + end + end + end + if db and not id then + postgress_close(db) + end + -- bonus + local one = result[1] + if one then + setmetatable(result,{ __index = one } ) + end + -- + return result, keys + else + report("error: ","no library loaded") + end +end + +local function execute(specification) + return execute_once(specification,true) +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(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +local celltemplate = "cells[%s]" + +methods.postgress = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-postgress"] = methods.postgress +package.loaded[libname] = methods.postgress diff --git a/tex/context/base/mkxl/libs-imp-sqlite.lmt b/tex/context/base/mkxl/libs-imp-sqlite.lmt new file mode 100644 index 000000000..5d38986f3 --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-sqlite.lmt @@ -0,0 +1,187 @@ +if not modules then modules = { } end modules ['libs-imp-sqlite'] = { + 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" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/sqlite/sqlite3.dll + +local libname = "sqlite" +local libfile = "sqlite3" + +local sqlitelib = resolvers.libraries.validoptional(libname) + +if not sqlitelib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local next, tonumber = next, tonumber +local setmetatable = setmetatable +local formatters = string.formatters + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +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 sqlite_open = sqlitelib.open +local sqlite_close = sqlitelib.close +local sqlite_execute = sqlitelib.execute +local sqlite_getmessage = sqlitelib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local cache = { } + +-- synchronous journal_mode locking_mode 1000 logger inserts +-- +-- normal normal normal 6.8 +-- off off normal 0.1 +-- normal off normal 2.1 +-- normal persist normal 5.8 +-- normal truncate normal 4.2 +-- normal truncate exclusive 4.1 + +local f_preamble = formatters[ [[ +ATTACH `%s` AS `%s` ; +PRAGMA `%s`.synchronous = normal ; +]] ] + +local function execute(specification) + if okay() then + if trace_sql then + report("executing sqlite") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local filename = file.addsuffix(base,"db") + local result = { } + local keys = { } + local id = specification.id + local db = nil + local preamble = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = sqlite_open(filename) + preamble = f_preamble(filename,base,base) + if not db then + report("no session database specified") + else + cache[id] = { + name = filename, + db = db, + } + end + end + else + db = open_db(filename) + preamble = f_preamble(filename,base,base) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if preamble then + query = preamble .. query -- only needed in open + end + if converter then + local convert = converter.sqlite + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + local okay = sqlite_execute(db,query,callback) + if not okay then + report("error: %s",sqlite_getmessage(db)) + -- elseif converter then + -- result = converter.sqlite(result) + end + end + if db and not id then + sqlite_close(db) + end + return result, keys + else + report("error: ","no library loaded") + end +end + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +local celltemplate = "cells[%s]" + +methods.sqlite = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-sqlite"] = methods.sqlite +package.loaded[libname] = methods.sqlite + +return methods.sqlite diff --git a/tex/context/base/mkxl/libs-imp-zint.lmt b/tex/context/base/mkxl/libs-imp-zint.lmt new file mode 100644 index 000000000..2c346ae7d --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-zint.lmt @@ -0,0 +1,161 @@ +if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "zint" +local libfile = "libzint" -- what on unix? +-- local libfile = "/usr/local/lib/libzint.so" + +local zintlib = resolvers.libraries.validoptional(libname) + +if not zintlib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local zint = utilities.zint or { } +utilities.zint = zint + +local zintlib_execute = zintlib.execute + +local next, type, unpack = next, type, unpack +local lower, gsub = string.lower, string.gsub + +local mapping = { + ["code 11"] = 1, ["pharma one-track"] = 51, ["aztec code"] = 92, + ["standard 2of5"] = 2, ["pzn"] = 52, ["daft code"] = 93, + ["interleaved 2of5"] = 3, ["pharma two-track"] = 53, ["micro qr code"] = 97, + ["iata 2of5"] = 4, ["pdf417"] = 55, ["hibc code 128"] = 98, + ["data logic"] = 6, ["pdf417 trunc"] = 56, ["hibc code 39"] = 99, + ["industrial 2of5"] = 7, ["maxicode"] = 57, ["hibc data matrix"] = 102, + ["code 39"] = 8, ["qr code"] = 58, ["hibc qr code"] = 104, + ["extended code 39"] = 9, ["code 128-b"] = 60, ["hibc pdf417"] = 106, + ["ean"] = 13, ["ap standard customer"] = 63, ["hibc micropdf417"] = 108, + ["ean + check"] = 14, ["ap reply paid"] = 66, ["hibc codablock-f"] = 110, + ["gs1-128"] = 16, ["ap routing"] = 67, ["hibc aztec code"] = 112, + ["codabar"] = 18, ["ap redirection"] = 68, ["dotcode"] = 115, + ["code 128"] = 20, ["isbn"] = 69, ["han xin code"] = 116, + ["leitcode"] = 21, ["rm4scc"] = 70, ["rm mailmark"] = 121, + ["identcode"] = 22, ["data matrix"] = 71, ["aztec runes"] = 128, + ["code 16k"] = 23, ["ean-14"] = 72, ["code 32"] = 129, + ["code 49"] = 24, ["vin (north america)"] = 73, ["comp ean"] = 130, + ["code 93"] = 25, ["codablock-f"] = 74, ["comp gs1-128"] = 131, + ["flattermarken"] = 28, ["nve-18"] = 75, ["comp databar omni"] = 132, + ["gs1 databar omni"] = 29, ["japanese post"] = 76, ["comp databar ltd"] = 133, + ["gs1 databar ltd"] = 30, ["korea post"] = 77, ["comp databar expom"] = 134, + ["gs1 databar expom"] = 31, ["gs1 databar stack"] = 79, ["comp upc-a"] = 135, + ["telepen alpha"] = 32, ["gs1 databar stack omni"] = 80, ["comp upc-e"] = 136, + ["upc-a"] = 34, ["gs1 databar eso"] = 81, ["comp databar stack"] = 137, + ["upc-a + check"] = 35, ["planet"] = 82, ["comp databar stack omni"] = 138, + ["upc-e"] = 37, ["micropdf"] = 84, ["comp databar eso"] = 139, + ["upc-e + check"] = 38, ["usps onecode"] = 85, ["channel code"] = 140, + ["postnet"] = 40, ["uk plessey"] = 86, ["code one"] = 141, + ["msi plessey"] = 47, ["telepen numeric"] = 87, ["grid matrix"] = 142, + ["fim"] = 49, ["itf-14"] = 89, ["upnqr"] = 143, + ["logmars"] = 50, ["kix code"] = 90, ["rmqr"] = 145, +} + +table.setmetatableindex(mapping,function(t,k) + local s = gsub(lower(k),"[^a-z0-9]","") + local v = rawget(t,s) or false + t[k] = v + return v +end) + +local report = logs.reporter("zint") +local context = context +local shown = false + +----- f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] + +local function execute(specification) + if okay() then + local code = specification.code + local text = specification.text + if code then + local id = mapping[code] + if id then + specification.code = id + local result = zintlib_execute(specification) + if result then + -- not that fast but if needed we can speed it up + context.startMPcode() + local rectangles = result.rectangles + local hexagons = result.hexagons + local circles = result.circles + local strings = result.strings + if rectangles then + local n = #rectangles + for i=1,n do + local r = rectangles[i] + context("%sofill unitsquare xysized (%N,%N) shifted (%N,%N);", + i == n and "d" or "n",r[3],r[4],r[1],r[2]) + -- rectangles[i] = f_rectangle(i == n and "d" or "n",r[3],r[4],r[1],r[2]) + end + -- context("% t",rectangles) + end + if hexagons then + local n = #hexagons + for i=1,#hexagons do + context("%sofill (%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--cycle;", + i == n and "d" or "n",unpack(hexagons[i])) + end + end + if circles then + local n = #circles + for i=1,#circles do + local c = circles[i] + context("%sofill unitcircle scaled %N shifted (%N,%N);", + i == n and "d" or "n",c[3],c[1],c[2]) + end + end + if strings then + -- We set the font at the encapsulating level. + for i=1,#strings do + local s = strings[i] + context('draw textext("%s") scaled (%N/10) shifted (%N,%N);', + s[4],s[3],s[1],s[2]) + end + end + context.stopMPcode() + end + else + report("unknown barcode alternative %a",code) + if not shown then + report("") + report("valid barcode alternatives:") + report("") + local list = table.sortedkeys(mapping) + for i=1,#list do + report(" %s", list[i]) + end + report("") + shown = true + end + end + end + end +end + +optional.loaded.zint = { execute = execute } + +interfaces.implement { + name = "zint", + actions = execute, + arguments = { + { + { "code" }, + { "text" }, + } + } +} diff --git a/tex/context/base/mkxl/libs-imp-zint.mkxl b/tex/context/base/mkxl/libs-imp-zint.mkxl new file mode 100644 index 000000000..b2adf05ad --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-zint.mkxl @@ -0,0 +1,64 @@ +%D \module +%D [ file=m-zint, +%D version=2010.12.07, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=Zint Barcode Generator, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 Using \type {zint} seems to be the easiest way to generate +%D (PDF417) barcodes so therefore we now have this module. There +%D are proper (also windows) binaries at: +%D +%D \starttyping +%D http://www.zint.org.uk +%D \stoptyping +%D +%D There is a bit more code than needed as we want to be able to +%D feed names. + +\registerctxluafile{libs-imp-zint}{autosuffix} + +\unprotect + +\definefont[usedzintfont][dejavusansmono at 10bp] + +\permanent\protected\def\barcode[#1]% [alternative=,text=] + {\bgroup + \usedzintfont + \getdummyparameters + [\c!alternative=,\c!text=,#1]% + \scale + [#1]% + {\clf_zint + code {\dummyparameter\c!alternative} + text {\dummyparameter\c!text} + \relax} + \egroup} + +\protect + +\continueifinputfile{libs-imp-zint.mkxl} + +\starttext + +% \dorecurse{1000}{ + \startTEXpage + \barcode[alternative=PDF417,text={Hans Hagen}]% + \blank + \barcode[alternative=PDF417,text={Ton Otten}]% + \blank + \barcode[alternative=ISBN,text=9789490688011]% + \blank + \barcode[alternative=isbn,text=9789490688011,width=3cm]% + \stopTEXpage +% } + +\stoptext + + diff --git a/tex/context/base/mkxl/libs-ini.mkxl b/tex/context/base/mkxl/libs-ini.mkxl new file mode 100644 index 000000000..d77046fbf --- /dev/null +++ b/tex/context/base/mkxl/libs-ini.mkxl @@ -0,0 +1,32 @@ +%D \module +%D [ file=libs-ini, +%D version=2020.01.02, +%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. + +\registerctxluafile{libs-ini}{} % shared with mkiv + +\registerctxluafile{libs-imp-curl}{autosuffix} +\registerctxluafile{libs-imp-ghostscript}{autosuffix} +\registerctxluafile{libs-imp-graphicsmagick}{autosuffix} + +% These are loaded on demand: + +% \registerctxluafile{libs-imp-mysql}{autosuffix} +% \registerctxluafile{libs-imp-sqlite}{autosuffix} +% \registerctxluafile{libs-imp-postgress}{autosuffix} +% \registerctxluafile{libs-imp-kpse}{autosuffix} + +\unprotect + +% \permanent\protected\def\uselibrary[#1]% +% {\clf_uselibrary{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt new file mode 100644 index 000000000..d2da4473a --- /dev/null +++ b/tex/context/base/mkxl/lpdf-emb.lmt @@ -0,0 +1,2236 @@ +if not modules then modules = { } end modules ['lpdf-ini'] = { + version = 1.001, + optimize = true, + 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" +} + +-- vkgoeswild: Pink Floyd - Shine on You Crazy Diamond - piano cover (around that +-- time I redid the code, a reminder so to say) + +-- At some point I wanted to have access to the shapes so that we could use them in +-- metapost. So, after looking at the cff and ttf specifications, I decided to write +-- parsers. At somepoint we needed a cff parser anyway in order to calculate the +-- dimensions. Then variable fonts came around and a option was added to recreate +-- streams of operators and a logical next step was to do all inclusion that way. It +-- was only then that I found out that some of the juggling also happens in the the +-- backend, but spread over places, so I could have saved myself some time +-- deciphering the specifications. Anyway, here we go. +-- +-- Color fonts are a bit messy. Catching issues with older fonts will break new ones +-- so I don't think that it's wise to build in too many catches (like for fonts with +-- zero boundingboxes, weird dimensions, transformations that in a next version are +-- fixed, etc.). Better is then to wait till something gets fixed. If a spec doesn't +-- tell me how to deal with it ... I'll happily wait till it does. After all we're +-- not in a hurry as these fonts are mostly meant for the web or special purposes +-- with manual tweaking in desk top publishing applications. Keep in mind that Emoji +-- can have funny dimensions (e.g. to be consistent within a font, so no tight ones). + +-- When we have moved to lmtx I will document a bit more. Till then it's experimental +-- and subjected to change. + +local next, type, unpack, rawget = next, type, unpack, rawget +local char, byte, gsub, sub, match, rep, gmatch = string.char, string.byte, string.gsub, string.sub, string.match, string.rep, string.gmatch +local formatters = string.formatters +local format = string.format +local concat, sortedhash, sort = table.concat, table.sortedhash, table.sort +local utfchar = utf.char +local random, round, max, abs, ceiling = math.random, math.round, math.max, math.abs, math.ceiling +local extract, lshift, rshift, band, bor = bit32.extract, bit32.lshift, bit32.rshift, bit32.band, bit32.bor +local idiv = number.idiv +local setmetatableindex = table.setmetatableindex + +local pdfnull = lpdf.null +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfstring = lpdf.string +local pdfreference = lpdf.reference +local pdfreserveobject = lpdf.reserveobject +local pdfflushobject = lpdf.flushobject +local pdfflushstreamobject = lpdf.flushstreamobject + +local report_fonts = logs.reporter("backend","fonts") + +local trace_fonts = false +local trace_details = false + +local dimenfactors = number.dimenfactors +local bpfactor = dimenfactors.bp +local ptfactor = dimenfactors.pt + +trackers.register("backend.pdf.fonts",function(v) trace_fonts = v end) + +local readers = fonts.handlers.otf.readers +local getinfo = readers.getinfo + +local setposition = utilities.files.setposition +local readstring = utilities.files.readstring +local openfile = utilities.files.open +local closefile = utilities.files.close + + +-- needs checking: signed vs unsigned + +local tocardinal1 = char + +local function tocardinal2(n) + return char(extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal3(n) + return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal4(n) + return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tointeger2(n) + return char(extract(n,8,8),extract(n,0,8)) +end + +local function tointeger3(n) + return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tointeger4(n) + return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal8(n) + local l = idiv(n,0x100000000) + local r = n % 0x100000000 + return char(extract(l,24,8),extract(l,16,8),extract(l,8,8),extract(l,0,8), + extract(r,24,8),extract(r,16,8),extract(r,8,8),extract(r,0,8)) +end + +-- A couple of shared helpers. + +local tounicodedictionary, widtharray, collectindices, subsetname, includecidset, forcecidset, tocidsetdictionary + +do + + -- Because we supply tounicodes ourselves we only use bfchar mappings (as in the + -- backend). In fact, we can now no longer pass the tounicodes to the frontend but + -- pick them up from the descriptions. + + local f_mapping_2 = formatters["<%02X> <%s>"] + local f_mapping_4 = formatters["<%04X> <%s>"] + + local tounicode = fonts.mappings.tounicode + +local tounicode_template = [[ +%%!PS-Adobe-3.0 Resource-CMap +%%%%DocumentNeededResources: ProcSet (CIDInit) +%%%%IncludeResource: ProcSet (CIDInit) +%%%%BeginResource: CMap (TeX-%s-0) +%%%%Title: (TeX-%s-0 TeX %s 0)| +%%%%Version: 1.000 +%%%%EndComments +/CIDInit /ProcSet findresource begin + 12 dict begin + begincmap + /CIDSystemInfo + << /Registry (TeX) /Ordering (%s) /Supplement 0 >> + def + /CMapName + /TeX-Identity-%s + def + /CMapType + 2 + def + 1 begincodespacerange + <%s> <%s> + endcodespacerange + %i beginbfchar +%s + endbfchar + endcmap + CMapName currentdict /CMap defineresource pop + end +end +%%%%EndResource +%%%%EOF]] + + tounicodedictionary = function(details,indices,maxindex,name,wide) + local mapping = { } + local length = 0 + if maxindex > 0 then + local f_mapping = wide and f_mapping_4 or f_mapping_2 + for index=1,maxindex do + local data = indices[index] + if data then + length = length + 1 + local unicode = data.unicode + if unicode then + unicode = tounicode(unicode) + else + unicode = "FFFD" + end + mapping[length] = f_mapping(index,unicode) + end + end + end + local name = gsub(name,"%+","-") -- like luatex does + local first = wide and "0000" or "00" + local last = wide and "FFFF" or "FF" + local blob = format(tounicode_template,name,name,name,name,name,first,last,length,concat(mapping,"\n")) + return blob + end + + widtharray = function(details,indices,maxindex,units) + local widths = pdfarray() + local length = 0 + local factor = 10000 / units + if maxindex > 0 then + local lastindex = -1 + local sublist = nil + for index=1,maxindex do + local data = indices[index] + if data then + local width = data.width -- hm, is inaccurate for cff, so take from elsewhere + if width then + -- width = round(width * 10000 / units) / 10 + width = round(width * factor) / 10 + else + width = 0 + end + if index == lastindex + 1 then + sublist[#sublist+1] = width + else + if sublist then + length = length + 1 + widths[length] = sublist + end + sublist = pdfarray { width } + length = length + 1 + widths[length] = index + end + lastindex = index + end + end + length = length + 1 + widths[length] = sublist + end + return widths + end + + collectindices = function(descriptions,indices) + local minindex = 0xFFFF + local maxindex = 0 + local reverse = { } + -- todo: already at definition time trigger copying streams + -- and add extra indices ... first i need a good example of + -- a clash + -- for unicode, data in next, descriptions do + -- local i = data.index or unicode + -- if reverse[i] then + -- print("CLASH") + -- else + -- reverse[i] = data + -- end + -- end + for unicode, data in next, descriptions do + reverse[data.index or unicode] = data + end + for index in next, indices do + if index > maxindex then + maxindex = index + end + if index < minindex then + minindex = index + end + indices[index] = reverse[index] + end + if minindex > maxindex then + minindex = maxindex + end + return indices, minindex, maxindex + end + + includecidset = false + forcecidset = false -- for private testing only + + directives.register("backend.pdf.forcecidset",function(v) + forcecidset = v + end) + + tocidsetdictionary = function(indices,min,max) + if includecidset or forcecidset then + local b = { } + local m = idiv(max+7,8) + for i=0,max do + b[i] = 0 + end + b[0] = bor(b[0],lshift(1,7)) -- force notdef into the file + for i=min,max do + if indices[i] then + local bi = idiv(i,8) + local ni = i % 8 + b[bi] = bor(b[bi],lshift(1,7-ni)) + end + end + b = char(unpack(b,0,#b)) + return pdfreference(pdfflushstreamobject(b)) + end + end + + -- Actually we can use the same as we only embed once. + + -- subsetname = function(name) + -- return "CONTEXT" .. name + -- end + + local prefixes = { } -- todo: set fixed one + + subsetname = function(name) + local prefix + while true do + prefix = utfchar(random(65,90),random(65,90),random(65,90),random(65,90),random(65,90),random(65,90)) + if not prefixes[prefix] then + prefixes[prefix] = true + break + end + end + return prefix .. "+" .. name + end + +end + +-- Map file mess. + +local loadmapfile, loadmapline, getmapentry do + + -- We only need to pick up the filename and optionally the enc file + -- as we only use them for old school virtual math fonts. We might as + -- we drop this completely. + + local find, match, splitlines = string.find, string.match, string.splitlines + + + local mappings = { } + + loadmapline = function(n) + if trace_fonts then + report_fonts("mapline: %s",n) + end + local name, fullname, encfile, pfbfile = match(n,"(%S+)%s+(%S+).-<(.-%.enc).-<(.-%.pfb)") + if name then + mappings[name] = { fullname, encfile, pfbfile } + end + end + + loadmapfile = function(n) + local okay, data = resolvers.loadbinfile(n,"map") + if okay and data then + data = splitlines(data) + for i=1,#data do + local d = data[i] + if d ~= "" and not find(d,"^[#%%]") then + loadmapline(d) + end + end + end + end + + getmapentry = function(n) + local n = file.nameonly(n) + local m = mappings[n] + if m then + local encfile = m[2] + local encoding = fonts.encodings.load(encfile) + if not encoding then + return + end + local pfbfile = resolvers.findfile(m[3],"pfb") + if not pfbfile or pfbfile == "" then + return + end + return encoding, pfbfile, encfile + end + end + + lpdf.getmapentry = getmapentry + +end + +-- The three writers: opentype, truetype and type1. + +local mainwriters = { } + +do + + -- advh = os2.ascender - os2.descender + -- tsb = default_advh - os2.ascender + + -- truetype has the following tables: + + -- head : mandate + -- hhea : mandate + -- vhea : mandate + -- hmtx : mandate + -- maxp : mandate + -- glyf : mandate + -- loca : mandate + -- + -- cvt : if needed (but we flatten) + -- fpgm : if needed (but we flatten) + -- prep : if needed (but we flatten) + -- PCLT : if needed (but we flatten) + -- + -- name : not needed for T2: backend does that + -- post : not needed for T2: backend does that + -- OS/2 : not needed for T2: backend does that + -- cmap : not needed for T2: backend does that + + local streams = utilities.streams + local openstring = streams.openstring + local readcardinal2 = streams.readcardinal2 + ----- readcardinal4 = streams.readcardinal4 + + local otfreaders = fonts.handlers.otf.readers + + local function readcardinal4(f) -- this needs to be sorted out + local a = readcardinal2(f) + local b = readcardinal2(f) + if a and b then + return a * 0x10000 + b + end + end + + -- -- -- + + local tablereaders = { } + local tablewriters = { } + local tablecreators = { } + local tableloaders = { } + + local openfontfile, closefontfile, makefontfile, makemetadata do + + local details = { + details = true, + platformnames = true, + platformextras = true, + } + + -- .022 sec on luatex manual, neglectable: + + -- local function checksum(data) + -- local s = openstring(data) + -- local n = 0 + -- local d = #data + -- while true do + -- local c = readcardinal4(s) + -- if c then + -- n = (n + c) % 0x100000000 + -- else + -- break + -- end + -- end + -- return n + -- end + + local function checksum(data) + local s = openstring(data) + local n = 0 + local d = #data + while true do + local a = readcardinal2(s) + local b = readcardinal2(s) + if b then + n = (n + a * 0x10000 + b) % 0x100000000 + else + break + end + end + return n + end + + openfontfile = function(details) + return { + offset = 0, + order = { }, + used = { }, + details = details, + streams = details.streams, + } + end + + closefontfile = function(fontfile) + for k, v in next, fontfile do + fontfile[k] = nil -- so it can be collected asap + end + end + + local metakeys = { + "uniqueid", "version", + "copyright", "license", "licenseurl", + "manufacturer", "vendorurl", + "family", "subfamily", + "typographicfamily", "typographicsubfamily", + "fullname", "postscriptname", + } + + local template = [[ + + + + + +%s + + + + +]] + + makemetadata = function(fontfile) + local names = fontfile.streams.names + local list = { } + local f_name = formatters["%s"] + for i=1,#metakeys do + local m = metakeys[i] + local n = names[m] + if n then + list[#list+1] = f_name(m,n,m) + end + end + return format(template,concat(list,"\n")) + end + + makefontfile = function(fontfile) + local order = fontfile.order + local used = fontfile.used + local count = 0 + for i=1,#order do + local tag = order[i] + local data = fontfile[tag] + if data and #data > 0 then + count = count + 1 + else + fontfile[tag] = false + end + end + local offset = 12 + (count * 16) + local headof = 0 + local list = { + "" -- placeholder + } + local i = 1 + local k = 0 + while i <= count do + i = lshift(i,1) + k = k + 1 + end + local searchrange = lshift(i,3) + local entryselector = k - 1 + local rangeshift = lshift(count,4) - lshift(i,3) + local index = { + tocardinal4(0x00010000), -- tables.version + tocardinal2(count), + tocardinal2(searchrange), + tocardinal2(entryselector), + tocardinal2(rangeshift), + } + -- + local ni = #index + local nl = #list + for i=1,#order do + local tag = order[i] + local data = fontfile[tag] + if data then + local csum = checksum(data) + local dlength = #data + local length = idiv(dlength+3,4) * 4 + local padding = length - dlength + nl = nl + 1 ; list[nl] = data + for i=1,padding do + nl = nl + 1 ; list[nl] = "\0" + end + if #tag == 3 then + tag = tag .. " " + end + ni = ni + 1 ; index[ni] = tag -- must be 4 chars + ni = ni + 1 ; index[ni] = tocardinal4(csum) + ni = ni + 1 ; index[ni] = tocardinal4(offset) + ni = ni + 1 ; index[ni] = tocardinal4(dlength) + used[i] = offset -- not used + if tag == "head" then + headof = offset + end + offset = offset + length + end + end + list[1] = concat(index) + local off = #list[1] + headof + 1 + 8 + list = concat(list) + local csum = (0xB1B0AFBA - checksum(list)) % 0x100000000 + list = sub(list,1,off-1) .. tocardinal4(csum) .. sub(list,off+4,#list) + return list + end + + local function register(fontfile,name) + local u = fontfile.used + local o = fontfile.order + if not u[name] then + o[#o+1] = name + u[name] = true + end + end + + local function create(fontfile,name) + local t = { } + fontfile[name] = t + return t + end + + local function write(fontfile,name) + local t = fontfile[name] + if not t then + return + end + register(fontfile,name) + if type(t) == "table" then + if t[0] then + fontfile[name] = concat(t,"",0,#t) + elseif #t > 0 then + fontfile[name] = concat(t) + else + fontfile[name] = false + end + end + end + + tablewriters.head = function(fontfile) + register(fontfile,"head") + local t = fontfile.streams.fontheader + fontfile.head = concat { + tocardinal4(t.version), + tocardinal4(t.fontversionnumber), + tocardinal4(t.checksum), + tocardinal4(t.magic), + tocardinal2(t.flags), + tocardinal2(t.units), + tocardinal8(t.created), + tocardinal8(t.modified), + tocardinal2(t.xmin), + tocardinal2(t.ymin), + tocardinal2(t.xmax), + tocardinal2(t.ymax), + tocardinal2(t.macstyle), + tocardinal2(t.smallpixels), + tocardinal2(t.directionhint), + tocardinal2(t.indextolocformat), + tocardinal2(t.glyphformat), + } + end + + tablewriters.hhea = function(fontfile) + register(fontfile,"hhea") + local t = fontfile.streams.horizontalheader + local n = t and fontfile.nofglyphs or 0 + fontfile.hhea = concat { + tocardinal4(t.version), + tocardinal2(t.ascender), + tocardinal2(t.descender), + tocardinal2(t.linegap), + tocardinal2(t.maxadvancewidth), + tocardinal2(t.minleftsidebearing), + tocardinal2(t.minrightsidebearing), + tocardinal2(t.maxextent), + tocardinal2(t.caretsloperise), + tocardinal2(t.caretsloperun), + tocardinal2(t.caretoffset), + tocardinal2(t.reserved_1), + tocardinal2(t.reserved_2), + tocardinal2(t.reserved_3), + tocardinal2(t.reserved_4), + tocardinal2(t.metricdataformat), + tocardinal2(n) -- t.nofmetrics + } + end + + tablewriters.vhea = function(fontfile) + local t = fontfile.streams.verticalheader + local n = t and fontfile.nofglyphs or 0 + register(fontfile,"vhea") + fontfile.vhea = concat { + tocardinal4(t.version), + tocardinal2(t.ascender), + tocardinal2(t.descender), + tocardinal2(t.linegap), + tocardinal2(t.maxadvanceheight), + tocardinal2(t.mintopsidebearing), + tocardinal2(t.minbottomsidebearing), + tocardinal2(t.maxextent), + tocardinal2(t.caretsloperise), + tocardinal2(t.caretsloperun), + tocardinal2(t.caretoffset), + tocardinal2(t.reserved_1), + tocardinal2(t.reserved_2), + tocardinal2(t.reserved_3), + tocardinal2(t.reserved_4), + tocardinal2(t.metricdataformat), + tocardinal2(n) -- t.nofmetrics + } + end + + tablewriters.maxp = function(fontfile) + register(fontfile,"maxp") + local t = fontfile.streams.maximumprofile + local n = fontfile.nofglyphs + -- if fontfile.streams.cffinfo then + -- error + -- end + fontfile.maxp = concat { + tocardinal4(0x00010000), + tocardinal2(n), + tocardinal2(t.points), + tocardinal2(t.contours), + tocardinal2(t.compositepoints), + tocardinal2(t.compositecontours), + tocardinal2(t.zones), + tocardinal2(t.twilightpoints), + tocardinal2(t.storage), + tocardinal2(t.functiondefs), + tocardinal2(t.instructiondefs), + tocardinal2(t.stackelements), + tocardinal2(t.sizeofinstructions), + tocardinal2(t.componentelements), + tocardinal2(t.componentdepth), + } + end + + tablecreators.loca = function(fontfile) return create(fontfile,"loca") end + tablewriters .loca = function(fontfile) return write (fontfile,"loca") end + + tablecreators.glyf = function(fontfile) return create(fontfile,"glyf") end + tablewriters .glyf = function(fontfile) return write (fontfile,"glyf") end + + tablecreators.hmtx = function(fontfile) return create(fontfile,"hmtx") end + tablewriters .hmtx = function(fontfile) return write (fontfile,"hmtx") end + + tablecreators.vmtx = function(fontfile) return create(fontfile,"vmtx") end + tablewriters .vmtx = function(fontfile) return write (fontfile,"vmtx") end + + tableloaders .cmap = function(fontfile) return read (fontfile,"cmap") end + tablewriters .cmap = function(fontfile) return write (fontfile,"cmap") end + + tableloaders .name = function(fontfile) return read (fontfile,"name") end + tablewriters .name = function(fontfile) return write (fontfile,"name") end + + tableloaders .post = function(fontfile) return read (fontfile,"post") end + tablewriters .post = function(fontfile) return write (fontfile,"post") end + + end + + mainwriters["truetype"] = function(details) + -- + local fontfile = openfontfile(details) + local basefontname = details.basefontname + local streams = details.streams + local blobs = streams.streams + local fontheader = streams.fontheader + local horizontalheader = streams.horizontalheader + local verticalheader = streams.verticalheader + local maximumprofile = streams.maximumprofile + local names = streams.names + local descriptions = details.rawdata.descriptions + local metadata = details.rawdata.metadata + local indices = details.indices + local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } + local indices, + minindex, + maxindex = collectindices(descriptions,indices) + local glyphstreams = tablecreators.glyf(fontfile) + local locations = tablecreators.loca(fontfile) + local horizontals = tablecreators.hmtx(fontfile) + local verticals = tablecreators.vmtx(fontfile) + -- + local zero2 = tocardinal2(0) + local zero4 = tocardinal4(0) + -- + local horizontal = horizontalheader.nofmetrics > 0 + local vertical = verticalheader.nofmetrics > 0 + -- + local streamoffset = 0 + local lastoffset = zero4 + local g, h, v = 0, 0, 0 + -- + -- todo: locate notdef + -- + if minindex > 0 then + local blob = blobs[0] + if blob and #blob > 0 then + locations[0] = lastoffset + g = g + 1 ; glyphstreams[g] = blob + h = h + 1 ; horizontals [h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + else + report_fonts("missing .notdef in font %a",basefontname) + end + -- todo: use a rep for h/v + for index=1,minindex-1 do + locations[index] = lastoffset + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + end + end + for index=minindex,maxindex do + locations[index] = lastoffset + local data = indices[index] + if data then + local blob = blobs[index] -- we assume padding + if blob and #blob > 0 then + g = g + 1 ; glyphstreams[g] = blob + h = h + 1 ; horizontals [h] = tocardinal2(data.width or 0) + h = h + 1 ; horizontals [h] = tocardinal2(data.boundingbox[1]) + if vertical then + v = v + 1 ; verticals[v] = tocardinal2(data.height or 0) + v = v + 1 ; verticals[v] = tocardinal2(data.boundingbox[3]) + end + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + else + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + report_fonts("missing blob for index %i in font %a",index,basefontname) + end + else + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + end + end + locations[maxindex+1] = lastoffset -- cf spec + -- + local nofglyphs = maxindex + 1 -- include zero + -- + fontheader.checksum = 0 + fontheader.indextolocformat = 1 + maximumprofile.nofglyphs = nofglyphs + -- + fontfile.format = "tff" + fontfile.basefontname = basefontname + fontfile.nofglyphs = nofglyphs + -- + tablewriters.head(fontfile) + tablewriters.hhea(fontfile) + if vertical then + tablewriters.vhea(fontfile) + end + tablewriters.maxp(fontfile) + + tablewriters.loca(fontfile) + tablewriters.glyf(fontfile) + + tablewriters.hmtx(fontfile) + if vertical then + tablewriters.vmtx(fontfile) + end + -- + local fontdata = makefontfile(fontfile) + local fontmeta = makemetadata(fontfile) + -- + fontfile = closefontfile(fontfile) + -- + local units = metadata.units + local basefont = pdfconstant(basefontname) + local widths = widtharray(details,indices,maxindex,units) + local object = details.objectnumber + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) + local tocidset = tocidsetdictionary(indices,minindex,maxindex) + local metabbox = metadata.boundingbox or { 0, 0, 0, 0 } + local fontbbox = pdfarray { unpack(metabbox) } + local ascender = metadata.ascender + local descender = metadata.descender + local capheight = metadata.capheight or fontbbox[4] + local stemv = metadata.weightclass + local italicangle = metadata.italicangle + local xheight = metadata.xheight or fontbbox[4] + -- + if stemv then + stemv = (stemv/65)^2 + 50 + end + -- + local function scale(n) + if n then + return round((n) * 10000 / units) / 10 + else + return 0 + end + end + -- + local reserved = pdfreserveobject() + local child = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("CIDFontType2"), + BaseFont = basefont, + FontDescriptor = pdfreference(reserved), + W = pdfreference(pdfflushobject(widths)), + CIDToGIDMap = pdfconstant("Identity"), + CIDSystemInfo = pdfdictionary { + Registry = pdfstring("Adobe"), + Ordering = pdfstring("Identity"), + Supplement = 0, + } + } + local descendants = pdfarray { + pdfreference(pdfflushobject(child)), + } + local descriptor = pdfdictionary { + Type = pdfconstant("FontDescriptor"), + FontName = basefont, + Flags = 4, + FontBBox = fontbbox, + Ascent = scale(ascender), + Descent = scale(descender), + ItalicAngle = round(italicangle or 0), + CapHeight = scale(capheight), + StemV = scale(stemv), + XHeight = scale(xheight), + FontFile2 = pdfreference(pdfflushstreamobject(fontdata)), + CIDSet = tocidset, + Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type0"), + Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), + BaseFont = basefont, + DescendantFonts = descendants, + ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(reserved,descriptor) + pdfflushobject(object,parent) + -- + -- if trace_details then + -- local name = "temp.ttf" + -- report_fonts("saving %a",name) + -- io.savedata(name,fontdata) + -- inspect(fonts.handlers.otf.readers.loadfont(name)) + -- end + -- + end + + do + -- todo : cff2 + + local details = { + details = true, + platformnames = true, + platformextras = true, + } + + tablecreators.cff = function(fontfile) + fontfile.charstrings = { } + fontfile.charmappings = { } + fontfile.cffstrings = { } + fontfile.cffhash = { } + return fontfile.charstrings , fontfile.charmappings + end + + local todictnumber, todictreal, todictinteger, todictoffset do + + local maxnum = 0x7FFFFFFF + local minnum = - 0x7FFFFFFF - 1 + local epsilon = 1.0e-5 + + local int2tag = "\28" + local int4tag = "\29" + local realtag = "\30" + + todictinteger = function(n) + if not n then + return char(band(139,0xFF)) + elseif n >= -107 and n <= 107 then + return char(band(n + 139,0xFF)) + elseif n >= 108 and n <= 1131 then + n = 0xF700 + n - 108 + return char(band(rshift(n,8),0xFF),band(n,0xFF)) + elseif n >= -1131 and n <= -108 then + n = 0xFB00 - n - 108 + return char(band(rshift(n,8),0xFF),band(n,0xFF)) + elseif n >= -32768 and n <= 32767 then + -- return int2tag .. tointeger2(n) + return char(28,extract(n,8,8),extract(n,0,8)) + else + -- return int4tag .. tointeger4(n) + return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) + end + end + + -- -- not called that often + -- + -- local encoder = readers.cffencoder + -- + -- todictinteger = function(n) + -- if not n then + -- return encoder[0] + -- elseif n >= -1131 and n <= 1131 then + -- return encoder[n] + -- elseif n >= -32768 and n <= 32767 then + -- -- return int2tag .. tointeger2(n) + -- return char(28,extract(n,8,8),extract(n,0,8)) + -- else + -- -- return int4tag .. tointeger4(n) + -- return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) + -- end + -- end + + todictoffset = function(n) + return int4tag .. tointeger4(n) + end + + local e = false + local z = byte("0") + local dp = 10 + local ep = 11 + local em = 12 + local mn = 14 + local es = 15 + + local fg = formatters["%g"] + + todictreal = function(v) + local s = fg(v) + local t = { [0] = realtag } + local n = 0 + for s in gmatch(s,".") do + if s == "e" or s == "E" then + e = true + elseif s == "+" then + -- skip + elseif s == "-" then + n = n + 1 + if e then + t[n] = em + e = false + else + t[n] = mn + end + else + if e then + n = n + 1 + t[n] = ep + e = false + end + n = n + 1 + if s == "." then + t[n] = dp + else + t[n] = byte(s) - z + end + end + end + n = n + 1 + t[n] = es + if (n % 2) ~= 0 then + n = n + 1 + t[n] = es + end + local j = 0 + for i=1,n,2 do + j = j + 1 + t[j] = char(t[i]*0x10+t[i+1]) + end + t = concat(t,"",0,j) + return t + end + + todictnumber = function(n) + if not n or n == 0 then + return todictinteger(0) + elseif (n > maxnum or n < minnum or (abs(n - round(n)) > epsilon)) then + return todictreal(n) + else + return todictinteger(n) + end + end + + end + + local todictkey = char + + local function todictstring(fontfile,value) + if not value then + value = "" + end + local s = fontfile.cffstrings + local h = fontfile.cffhash + local n = h[value] + if not n then + n = #s + 1 + s[n] = value + h[value] = n + end + return todictinteger(390+n) + end + + local function todictboolean(b) + return todictinteger(b and 1 or 0) + end + + local function todictdeltas(t) + local r = { } + for i=1,#t do + r[i] = todictnumber(t[i]-(t[i-1] or 0)) + end + return concat(r) + end + + local function todictarray(t) + local r = { } + for i=1,#t do + r[i] = todictnumber(t[i]) + end + return concat(r) + end + + local function writestring(target,source,offset,what) + target[#target+1] = source + -- report_fonts("string : %-11s %06i # %05i",what,offset,#source) + return offset + #source + end + + local function writetable(target,source,offset,what) + source = concat(source) + target[#target+1] = source + -- report_fonts("table : %-11s %06i # %05i",what,offset,#source) + return offset + #source + end + + local function writeindex(target,source,offset,what) + local n = #source + local t = #target + t = t + 1 ; target[t] = tocardinal2(n) + if n > 0 then + local data = concat(source) + local size = #data -- assume the worst + local offsetsize, tocardinal + if size < 0xFF then + offsetsize, tocardinal = 1, tocardinal1 + elseif size < 0xFFFF then + offsetsize, tocardinal = 2, tocardinal2 + elseif size < 0xFFFFFF then + offsetsize, tocardinal = 3, tocardinal3 + elseif size < 0xFFFFFFFF then + offsetsize, tocardinal = 4, tocardinal4 + end + -- report_fonts("index : %-11s %06i # %05i (%i entries with offset size %i)",what,offset,#data,n,offsetsize) + offset = offset + 2 + 1 + (n + 1) * offsetsize + size + -- bytes per offset + t = t + 1 ; target[t] = tocardinal1(offsetsize) + -- list of offsets (one larger for length calculation) + local offset = 1 -- mandate + t = t + 1 ; target[t] = tocardinal(offset) + for i=1,n do + offset = offset + #source[i] + t = t + 1 ; target[t] = tocardinal(offset) + end + t = t + 1 ; target[t] = data + else + -- report_fonts("index : %-11s %06i # %05i (no entries)",what,offset,0) + offset = offset + 2 + end + -- print("offset",offset,#concat(target)) + return offset + end + + tablewriters.cff = function(fontfile) + -- + local streams = fontfile.streams + local cffinfo = streams.cffinfo or { } + local names = streams.names or { } + local fontheader = streams.fontheader or { } + local basefontname = fontfile.basefontname + -- + local offset = 0 + local dictof = 0 + local target = { } + -- + local charstrings = fontfile.charstrings + local nofglyphs = #charstrings + 1 + local fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 } -- todo + local fontbbox = fontfile.fontbbox + local defaultwidth = cffinfo.defaultwidth or 0 + local nominalwidth = cffinfo.nominalwidth or 0 + local bluevalues = cffinfo.bluevalues + local otherblues = cffinfo.otherblues + local familyblues = cffinfo.familyblues + local familyotherblues = cffinfo.familyotherblues + local bluescale = cffinfo.bluescale + local blueshift = cffinfo.blueshift + local bluefuzz = cffinfo.bluefuzz + local stdhw = cffinfo.stdhw + local stdvw = cffinfo.stdvw + -- + if defaultwidth == 0 then defaultwidth = nil end + if nomimalwidth == 0 then nominalwidth = nil end + if bluevalues then bluevalues = todictarray(bluevalues) end + if otherblues then otherblues = todictarray(otherblues) end + if familyblues then familyblues = todictarray(familyblues) end + if familyotherblues then familyotherblues = todictarray(familyotherblues) end + if bluescale then bluescale = todictnumber(bluescale) end + if blueshift then blueshift = todictnumber(blueshift) end + if bluefuzz then bluefuzz = todictnumber(bluefuzz) end + if stdhw then stdhw = todictdeltas(stdhw) end + if stdvw then stdvw = todictdeltas(stdvw) end + -- + local fontversion = todictstring(fontfile,fontheader.fontversion or "uknown version") + local familyname = todictstring(fontfile,cffinfo.familyname or names.family or basefontname) + local fullname = todictstring(fontfile,cffinfo.fullname or basefontname) + local weight = todictstring(fontfile,cffinfo.weight or "Normal") + local fontbbox = todictarray(fontbbox) + local strokewidth = todictnumber(cffinfo.strokewidth) + local monospaced = todictboolean(cffinfo.monospaced) + local italicangle = todictnumber(cffinfo.italicangle) + local underlineposition = todictnumber(cffinfo.underlineposition) + local underlinethickness = todictnumber(cffinfo.underlinethickness) + local charstringtype = todictnumber(2) + local fontmatrix = todictarray(fontmatrix) + local ros = todictstring(fontfile,"Adobe") -- registry + .. todictstring(fontfile,"Identity") -- identity + .. todictnumber(0) -- supplement + local cidcount = todictnumber(fontfile.nofglyphs) + local fontname = todictstring(fontfile,basefontname) + local fdarrayoffset = todictoffset(0) + local fdselectoffset = todictoffset(0) + local charstringoffset = todictoffset(0) + local charsetoffset = todictoffset(0) + local privateoffset = todictoffset(0) + -- + local defaultwidthx = todictnumber(defaultwidth) + local nominalwidthx = todictnumber(nominalwidth) + local private = "" + .. (defaultwidthx and (defaultwidthx .. todictkey(20)) or "") + .. (nominalwidthx and (nominalwidthx .. todictkey(21)) or "") + .. (bluevalues and (bluevalues .. todictkey(6)) or "") + .. (otherblues and (otherblues .. todictkey(7)) or "") + .. (familyblues and (familyblues .. todictkey(8)) or "") + .. (familyotherblues and (familyotherblues .. todictkey(9)) or "") + .. (bluescale and (bluescale .. todictkey(12,9)) or "") + .. (blueshift and (blueshift .. todictkey(12,10)) or "") + .. (bluefuzz and (bluefuzz .. todictkey(12,11)) or "") + .. (stdhw and (stdhw .. todictkey(12,12)) or "") + .. (stdvw and (stdvw .. todictkey(12,13)) or "") + local privatesize = todictnumber(#private) + local privatespec = privatesize .. privateoffset + -- + -- header (fixed @ 1) + -- + local header = + tocardinal1(1) -- major + .. tocardinal1(0) -- minor + .. tocardinal1(4) -- header size + .. tocardinal1(4) -- offset size + -- + offset = writestring(target,header,offset,"header") + -- + -- name index (fixed @ 2) (has to be sorted) + -- + local names = { + basefontname, + } + -- + offset = writeindex(target,names,offset,"names") + -- + -- topdict index (fixed @ 3) + -- + local topvars = + charstringoffset .. todictkey(17) + .. charsetoffset .. todictkey(15) + .. fdarrayoffset .. todictkey(12,36) + .. fdselectoffset .. todictkey(12,37) + .. privatespec .. todictkey(18) + -- + local topdict = { + ros .. todictkey(12,30) -- first + .. cidcount .. todictkey(12,34) + .. familyname .. todictkey( 3) + .. fullname .. todictkey( 2) + .. weight .. todictkey( 4) + .. fontbbox .. todictkey( 5) + .. monospaced .. todictkey(12, 1) + .. italicangle .. todictkey(12, 2) + .. underlineposition .. todictkey(12, 3) + .. underlinethickness .. todictkey(12, 4) + .. charstringtype .. todictkey(12, 6) + .. fontmatrix .. todictkey(12, 7) + .. strokewidth .. todictkey(12, 8) + .. topvars + } + -- + offset = writeindex(target,topdict,offset,"topdict") + dictof = #target + -- + -- string index (fixed @ 4) + -- + offset = writeindex(target,fontfile.cffstrings,offset,"strings") + -- + -- global subroutine index (fixed @ 5) + -- + offset = writeindex(target,{},offset,"globals") + -- + -- Encoding (cff1) + -- + -- offset = writeindex(target,{},offset,"encoding") + -- + -- Charsets + -- + charsetoffset = todictoffset(offset) + offset = writetable(target,fontfile.charmappings,offset,"charsets") + -- + -- fdselect + -- + local fdselect = + tocardinal1(3) -- format + .. tocardinal2(1) -- n of ranges + -- entry 1 + .. tocardinal2(0) -- first gid + .. tocardinal1(0) -- fd index + -- entry 2 +-- .. tocardinal2(fontfile.sparsemax-1) -- sentinel + .. tocardinal2(fontfile.sparsemax) -- sentinel + -- + fdselectoffset = todictoffset(offset) + offset = writestring(target,fdselect,offset,"fdselect") + -- + -- charstrings + -- + charstringoffset = todictoffset(offset) + offset = writeindex(target,charstrings,offset,"charstrings") + -- + -- font dict + -- + -- offset = writeindex(target,{},offset,"fontdict") + -- + -- private + -- + privateoffset = todictoffset(offset) + privatespec = privatesize .. privateoffset + offset = writestring(target,private,offset,"private") + -- + local fdarray = { + fontname .. todictkey(12,38) + .. privatespec .. todictkey(18) + } + fdarrayoffset = todictoffset(offset) + offset = writeindex(target,fdarray,offset,"fdarray") + -- + topdict = target[dictof] + topdict = sub(topdict,1,#topdict-#topvars) + topvars = + charstringoffset .. todictkey(17) + .. charsetoffset .. todictkey(15) + .. fdarrayoffset .. todictkey(12,36) + .. fdselectoffset .. todictkey(12,37) + .. privatespec .. todictkey(18) + target[dictof] = topdict .. topvars + -- + target = concat(target) + -- if trace_details then + -- local name = "temp.cff" + -- report_fonts("saving %a",name) + -- io.savedata(name,target) + -- inspect(fonts.handlers.otf.readers.cffcheck(name)) + -- end + return target + end + + end + + -- todo: check widths (missing a decimal) + + mainwriters["opentype"] = function(details) + -- + local fontfile = openfontfile(details) + local basefontname = details.basefontname + local streams = details.streams + local blobs = streams.streams + local fontheader = streams.fontheader + local maximumprofile = streams.maximumprofile + local names = streams.names + local descriptions = details.rawdata.descriptions + local metadata = details.rawdata.metadata + local indices = details.indices + local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } + local correction = 1 + + -- (*) We share code with type1 and when we have old school tfm with + -- pfb but without descriptions we're kind of toast. + + if not descriptions or not next(descriptions) then + -- This is good enough, we only need indices and widths. + descriptions = details.fontdata.characters + -- This is a hack, we have no basepoints. + correction = details.fontdata.parameters.size / 1000 + -- And this needs checking. + correction = correction * bpfactor / ptfactor + metadata = { } + end + + -- + + local indices, + minindex, + maxindex = collectindices(descriptions,indices) + local streamoffset = 0 + local glyphstreams, + charmappings = tablecreators.cff(fontfile) + -- + local zero2 = tocardinal2(0) + local zero4 = tocardinal4(0) + -- + -- we need to locate notdef (or store its unicode someplace) + -- + local blob = blobs[0] or "\14" + local sparsemax = 1 + local lastoffset = zero4 + glyphstreams[sparsemax] = blob + charmappings[sparsemax] = tocardinal1(0) -- format 0 + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + if minindex == 0 then + minindex = 1 + end + for index=minindex,maxindex do + if indices[index] then + local blob = blobs[index] or "\14" + sparsemax = sparsemax + 1 + glyphstreams[sparsemax] = blob + charmappings[sparsemax] = tocardinal2(index) + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + end + end + -- + fontfile.nofglyphs = maxindex + 1 + fontfile.sparsemax = sparsemax + fontfile.format = "cff" + fontfile.basefontname = basefontname + fontfile.fontbbox = metabbox + -- + local fontdata = tablewriters.cff(fontfile) + local fontmeta = makemetadata(fontfile) + -- + fontfile = closefontfile(fontfile) + -- + local units = fontheader.units or metadata.units + + local basefont = pdfconstant(basefontname) + local widths = widtharray(details,indices,maxindex,units * correction) + local object = details.objectnumber + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) + local tocidset = tocidsetdictionary(indices,minindex,maxindex) + local fontbbox = pdfarray { unpack(metabbox) } + local ascender = metadata.ascender or 0 + local descender = metadata.descender or 0 + local capheight = metadata.capheight or fontbbox[4] + local stemv = metadata.weightclass + local italicangle = metadata.italicangle + local xheight = metadata.xheight or fontbbox[4] + if stemv then + stemv = (stemv/65)^2 + 50 + else +-- stemv = 2 + end + -- + local function scale(n) + if n then + return round((n) * 10000 / units) / 10 + else + return 0 + end + end + -- + local reserved = pdfreserveobject() + local child = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("CIDFontType0"), + BaseFont = basefont, + FontDescriptor = pdfreference(reserved), + W = pdfreference(pdfflushobject(widths)), + CIDSystemInfo = pdfdictionary { + Registry = pdfstring("Adobe"), + Ordering = pdfstring("Identity"), + Supplement = 0, + } + } + local descendants = pdfarray { + pdfreference(pdfflushobject(child)), + } + local fontstream = pdfdictionary { + Subtype = pdfconstant("CIDFontType0C"), + } + local descriptor = pdfdictionary { + Type = pdfconstant("FontDescriptor"), + FontName = basefont, + Flags = 4, + FontBBox = fontbbox, + Ascent = scale(ascender), + Descent = scale(descender), + ItalicAngle = round(italicangle or 0), + CapHeight = scale(capheight), + StemV = scale(stemv), + XHeight = scale(xheight), + CIDSet = tocidset, + FontFile3 = pdfreference(pdfflushstreamobject(fontdata,fontstream())), + Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type0"), + Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), + BaseFont = basefont, + DescendantFonts = descendants, + ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(reserved,descriptor) + pdfflushobject(object,parent) + end + + mainwriters["type1"] = function(details) + -- We abuse the cff includer which is ok but for special cases like + -- tfm -> pfb we don't have the right descriptions and scale so this + -- is why we cheat elsewhere. Maybe I should just drop that kind of + -- support and assume afm files to be present. See (*) above. + local s = details.streams + local m = details.rawdata.metadata + if m then + local h = s.horizontalheader + local c = s.cffinfo + local n = s.names + h.ascender = m.ascender or h.ascender + h.descender = m.descender or h.descender + n.copyright = m.copyright or n.copyright + n.family = m.familyname or n.familyname + n.fullname = m.fullname or n.fullname + n.fontname = m.fontname or n.fontname + n.subfamily = m.subfamilyname or n.subfamilyname + n.version = m.version or n.version + setmetatableindex(h,m) + setmetatableindex(c,m) + setmetatableindex(n,m) + end + mainwriters["opentype"](details) + end + + do + + -- The methods might become plugins. + + local methods = { } + + local pdfimage = lpdf.epdf.image + local openpdf = pdfimage.open + local closepdf = pdfimage.close + local copypage = pdfimage.copy + + local embedimage = images.embed + + local f_glyph = formatters["G%d"] + local f_char = formatters["BT /V%d 1 Tf [<%04X>] TJ ET"] + local f_width = formatters["%.6N 0 d0"] + local f_index = formatters["I%d"] + local f_image_xy = formatters["%.6N 0 d0 1 0 0 1 %.6N %.6N cm /%s Do"] + local f_image_c = formatters["/%s Do"] + local f_image_c_xy = formatters["%.6N 0 0 %.6N %.6N %.6N cm /%s Do"] + local f_image_w = formatters["%.6N 0 d0 %s"] + local f_image_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm /%s Do"] + local f_stream = formatters["%.6N 0 d0 %s"] + local f_stream_c = formatters["%.6N 0 0 0 0 0 d1 %s"] + local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm %s"] + + -- A type 3 font has at most 256 characters and Acrobat also wants a zero slot + -- to be filled. We can share a mandate zero slot character. We also need to + -- make sure that we use bytes as index in the page stream as well as in the + -- tounicode vector. + + local c_notdef = nil + local r_notdef = nil + local w_notdef = nil + local fontbbox = nil + + -- pk inclusion (not really tested but not really used either) + + function methods.pk(filename) + local pkfullname = resolvers.findpk(basedfontname,resolution) + if not pkfullname or pkfullname == "" then + return + end + local readers = fonts.handlers.tfm.readers + local result = readers.loadpk(pkfullname) + local convert = readers.pktopdf + if not result or result.error then + return + end + local resolution = 600 + local widthfactor = resolution / 72 + local scalefactor = 72 / resolution / 10 + local factor = widthfactor / 65536 + local function pktopdf(glyph,data) + return convert(glyph,data,factor) -- return pdfcode, width + end + return result.glyphs, scalefactor, pktopdf, false, false + end + + -- pdf inclusion + + local used = setmetatableindex("table") + + function methods.pdf(filename,details) + local properties = details.properties + local pdfshapes = properties.indexdata[1] + local pdfdoc = openpdf(pdfshapes.filename) + local xforms = pdfdictionary() + local nofglyphs = 0 + if pdfdoc then + local scale = 10 * details.parameters.size/details.parameters.designsize + local units = details.parameters.units + local factor = units * bpfactor / scale + local fixdepth = pdfshapes.fixdepth + local useddoc = used[pdfdoc] + local function pdftopdf(glyph,data) + local width = (data.width or 0) * factor + local image = useddoc[glyph] + local reference = nil + if not image then + image = embedimage(copypage(pdfdoc,glyph)) + nofglyphs = nofglyphs + 1 + local name = f_glyph(nofglyphs) + local stream = nil + if fixdepth then + local depth = data.depth or 0 + local height = data.height or 0 + if depth ~= 0 or height ~= 0 then + local d = data.dropin.descriptions[data.index] + local b = d.boundingbox + local l = b[1] + local r = b[3] + local w = r - l + local scale = w / d.width + local x = l + local y = - b[4] - b[2] - d.depth + local scale = w / (image.width * bpfactor) + stream = f_image_c_xy(scale,scale,x,y,name) + else + stream = f_image_c(name) + end + else + stream = f_image_c(name) + end + useddoc[glyph] = image + image.embedded_name = name + image.embedded_stream = stream + image.embedded_reference = pdfreference(image.objnum) + end + xforms[image.embedded_name] = image.embedded_reference + return f_image_w(width,image.embedded_stream), width + end + local function closepdf() + -- closepdf(pdfdoc) + end + local function getresources() + return pdfdictionary { XObject = xforms } + end + return pdfshapes, 1/units, pdftopdf, closepdf, getresources + end + end + + -- mps inclusion + + local decompress = gzip.decompress + local metapost = metapost + local simplemprun = metapost.simple + local setparameterset = metapost.setparameterset + + function methods.mps(filename,details) + local properties = details.properties + local parameters = details.parameters + local mpshapes = properties.indexdata[1] -- indexdata will change + if mpshapes then + local scale = 10 * parameters.size/parameters.designsize + local units = mpshapes.units or parameters.units + local factor = units * bpfactor / scale + local fixdepth = mpshapes.fixdepth + local usecolor = mpshapes.usecolor + local specification = mpshapes.specification or { } + local shapedefinitions = mpshapes.shapes + local instance = mpshapes.instance + -- + simplemprun(instance,"begingroup;",true,true) + setparameterset("mpsfont",specification) + specification.scale = specification.scale or scale + specification.parameters = parameters + specification.properties = properties + specification.parentdata = details.fontdata.parentdata + -------------.characters = details.fontdata.characters + -------------.descriptions = details.fontdata.descriptions + if shapedefinitions then + local preamble = shapedefinitions.parameters.preamble + if preamble then + simplemprun(instance,preamble,true,true) + end + end + -- + local function mpstopdf(mp,data) + local width = data.width + if decompress then + mp = decompress(mp) + end + local pdf = simplemprun(instance,mp,true) -- can be sped up, minifun + local width = width * factor + if usecolor then + return f_stream_c(width,pdf), width + elseif fixdepth then + local depth = data.depth or 0 + local height = data.height or 0 + if depth ~= 0 or height ~= 0 then + return f_stream_d(width,(-height-depth)*factor,pdf), width + end + end + return f_stream(width,pdf), width + end + -- + local function resetmps() + setparameterset("mpsfont") + simplemprun(instance,"endgroup;",true,true) + specification.parameters = nil + specification.properties = nil + specification.parentdata = nil + -------------.characters = nil + -------------.descriptions = nil + end + -- + local function getresources() + return lpdf.collectedresources { + serialize = false, + } + end + -- + return mpshapes, 1/units, mpstopdf, resetmps, getresources + end + end + + -- png inclusion + + -- With d1 the image mask is used when given and obeys color. So it is needed for pure bw + -- bitmap fonts, so here we really need d0. + -- + -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat + -- reader crashes. We really need to add a notdef! + + local files = utilities.files + local openfile = files.open + local closefile = files.close + local setposition = files.setposition + local readstring = files.readstring + + function methods.png(filename,details) + local properties = details.properties + local pngshapes = properties.indexdata[1] + if pngshapes then + local parameters = details.parameters + local png = properties.png + local hash = png.hash + local xforms = pdfdictionary() + local nofglyphs = 0 + local scale = 10 * parameters.size/parameters.designsize + local factor = bpfactor / scale + -- local units = parameters.units -- / 1000 + local units = 1000 + local filehandle = openfile(details.filename,true) + local function pngtopdf(glyph,data) + -- local info = graphics.identifiers.png(glyph.data,"string") + local offset = glyph.o + local size = glyph.s + local pdfdata = nil + if offset and size then + setposition(filehandle,offset) + local blob = readstring(filehandle,size) + local info = graphics.identifiers.png(blob,"string") + info.enforcecmyk = pngshapes.enforcecmyk + local image = lpdf.injectors.png(info,"string") + local width = (data.width or 0) * factor + if image then + embedimage(image) + nofglyphs = nofglyphs + 1 + local xoffset = (glyph.x or 0) / units + local yoffset = (glyph.y or 0) / units + local name = f_glyph(nofglyphs) + xforms[name] = pdfreference(image.objnum) + pdfdata = f_image_xy(width,xoffset,yoffset,name) + end + end + return pdfdata or f_stream(width), width + end + local function closepng() + if filehandle then + closefile(filehandle) + end + pngshapes = nil + end + local function getresources() + return pdfdictionary { XObject = xforms } + end + return pngshapes, 1, pngtopdf, closepng, getresources + end + end + + function methods.color(filename,details) + local colrshapes = details.properties.indexdata[1] + local colrvalues = details.properties.indexdata[2] + local usedfonts = { } + local function colrtopdf(description,data) + -- descriptions by index + local colorlist = description.colors + if colorlist then + local dropdata = data.dropin + local dropid = dropdata.properties.id + local dropunits = dropdata.parameters.units -- shared + local descriptions = dropdata.descriptions + usedfonts[dropid] = dropid + local w = description.width or 0 + local s = #colorlist + local l = nil + local t = { f_width(w) } + local n = 1 + local d = colrvalues[#colrvalues] + for i=1,s do + local entry = colorlist[i] + local v = colrvalues[entry.class] or d + if v and l ~= v then + n = n + 1 ; t[n] = v + l = v + end + local e = descriptions[entry.slot] + if e then + n = n + 1 ; t[n] = f_char(dropid,e.index) + end + end + return concat(t," "), w / dropunits + end + end + local function getresources() + return lpdf.collectedresources { + serialize = false, + fonts = usedfonts, + fontprefix = "V", + } + end + return colrshapes, 1, colrtopdf, false, getresources + end + + mainwriters["type3"] = function(details) + local properties = details.properties + local basefontname = details.basefontname or properties.name + local askedmethod = properties.method or "pk" + local method = methods[askedmethod] or methods.pk + if not method then + return + end + local glyphs, scalefactor, glyphtopdf, reset, getresources = method(basedfontname,details) + if not glyphs then + return + end + local parameters = details.parameters + local object = details.objectnumber + local factor = parameters.factor -- normally 1 + local fontmatrix = pdfarray { scalefactor, 0, 0, scalefactor, 0, 0 } + local indices, + minindex, + maxindex = collectindices(details.fontdata.characters,details.indices) + local widths = pdfarray() + local differences = pdfarray() + local charprocs = pdfdictionary() + local basefont = pdfconstant(basefontname) + local d = 0 + local w = 0 + local forcenotdef = minindex > 0 + local lastindex = -0xFF + if forcenotdef then + widths[0] = 0 + minindex = 0 + lastindex = 0 + d = 2 + if not c_notdef then + w_notdef = 0 + c_notdef = pdfconstant(".notdef") + r_notdef = pdfreference(pdfflushstreamobject("0 0 d0")) + end + differences[1] = w_notdef + differences[2] = c_notdef + charprocs[".notdef"] = r_notdef + end + + for i=1,maxindex-minindex+1 do + widths[i] = 0 + end + + for index, data in sortedhash(indices) do + local name = f_index(index) + local glyph = glyphs[index] + if glyph then + local stream, width = glyphtopdf(glyph,data) + if stream then + if index - 1 ~= lastindex then + d = d + 1 differences[d] = index + end + lastindex = index + d = d + 1 differences[d] = pdfconstant(name) + charprocs[name] = pdfreference(pdfflushstreamobject(stream)) + widths[index-minindex+1] = width + end + else + report_fonts("missing glyph %i in type3 font %a",index,basefontname) + end + end + if not fontbbox then + -- The specification permits zero values and these are actually also more + -- robust as then there are no assumptions and no accuracy is needed. + fontbbox = pdfarray { 0, 0, 0, 0 } + end + local encoding = pdfdictionary { + Type = pdfconstant("Encoding"), + Differences = differences, + } + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,false) + local resources = getresources and getresources() + if not resources or not next(resources) then + -- resources = lpdf.procset(true) + resources = nil + end + local descriptor = pdfdictionary { + -- most is optional in type3 + Type = pdfconstant("FontDescriptor"), + FontName = basefont, + Flags = 4, + ItalicAngle = 0, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type3"), + Name = basefont, + FontBBox = fontbbox, + FontMatrix = fontmatrix, + CharProcs = pdfreference(pdfflushobject(charprocs)), + Encoding = pdfreference(pdfflushobject(encoding)), + FirstChar = minindex, + LastChar = maxindex, + Widths = pdfreference(pdfflushobject(widths)), + FontDescriptor = pdfreference(pdfflushobject(descriptor)), + Resources = resources, + ToUnicode = tounicode and pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(object,parent) + if reset then + reset() + end + end + + end + +end + +-- writingmode + +local usedfonts = fonts.hashes.identifiers -- for now +local noffonts = 0 + +-- The main injector. + +-- here we need to test for sharing otherwise we reserve too many +-- objects + +local getstreamhash = fonts.handlers.otf.getstreamhash +local loadstreamdata = fonts.handlers.otf.loadstreamdata + +-- we can actually now number upwards (so not use fontid in /F) + +local objects = setmetatableindex(function(t,k) + local v + if type(k) == "number" then + local h = getstreamhash(k) + v = rawget(t,h) + if not v then + v = pdfreserveobject() + t[h] = v + end + if trace_fonts then + report_fonts("font id %i bound to hash %s and object %i",k,h,v) + end + else + -- no problem as it can be svg only + -- report_fonts("fatal error, hash %s asked but not used",k,h,v) + v = pdfreserveobject() + t[k] = v + end + return v +end) + +local n = 0 + +local names = setmetatableindex(function(t,k) + local v + if type(k) == "number" then + local h = getstreamhash(k) + v = rawget(t,h) + if not v then + n = n + 1 + v = n + t[h] = v + end + if trace_fonts then + report_fonts("font id %i bound to hash %s and name %i",k,h,n) + end + end + t[k] = v + return v +end) + +function lpdf.flushfonts() + + local mainfonts = { } + + statistics.starttiming(objects) + + for fontid, used in sortedhash(lpdf.usedcharacters) do + + -- for a bitmap we need a different hash unless we stick to a fixed high + -- resolution which makes much sense + + local hash = getstreamhash(fontid) + if hash then + local parent = mainfonts[hash] + if not parent then + local fontdata = usedfonts[fontid] + local rawdata = fontdata.shared and fontdata.shared.rawdata + local resources = fontdata.resources + local properties = fontdata.properties -- writingmode and type3 + local parameters = fontdata.parameters -- used in type3 + if not rawdata then + -- we have a virtual font that loaded directly ... at some point i will + -- sort this out (in readanddefine we need to do a bit more) .. the problem + -- is that we have a hybrid font then + for xfontid, xfontdata in next, fonts.hashes.identifiers do + if fontid ~= xfontid then + local xhash = getstreamhash(xfontid) + if hash == xhash then + rawdata = xfontdata.shared and xfontdata.shared.rawdata + if rawdata then + resources = xfontdata.resources + properties = xfontdata.properties + parameters = xfontdata.parameters + break + end + end + end + end + end + if rawdata then + parent = { + hash = hash, + fontdata = fontdata, + filename = resources.filename or properties.filename or "unset", + indices = { }, + rawdata = rawdata, + properties = properties, -- we assume consistency + parameters = parameters, -- we assume consistency + streams = { }, + objectnumber = objects[hash], + basefontname = subsetname(properties.psname or properties.name or "unset"), + name = names[hash], + } + mainfonts[hash] = parent + noffonts = noffonts + 1 + end + end + if parent then + local indices = parent.indices + for k in next, used do + indices[k] = true + end + end + end + end + + -- this is no not yet ok for tfm / type 1 .. we need to move the nested blobs ourside the loop + + for hash, details in sortedhash(mainfonts) do + local filename = details.filename + if next(details.indices) then + if trace_fonts then + report_fonts("embedding %a hashed as %a",filename,hash) + end + local properties = details.properties + local bitmap = properties.usedbitmap + local method = properties.method -- will be pk | pdf | svg | ... + if bitmap or method then + local format = "type3" + local writer = mainwriters[format] + if writer then + if trace_fonts then + report_fonts("using main writer %a",format) + end + writer(details) + end + else + local format = properties.format + local writer = mainwriters[format] + if not writer then + -- This will move to the tpk module where we will also deal + -- with bitmaps then. + local encoding, pfbfile, encfile = getmapentry(filename) + if trace_fonts then + report_fonts("file %a resolved to encoding %a and file %a",filename,encoding,pfbfile) + end + if encoding and pfbfile then + filename = pfbfile + format = "type1" + -- + -- another (temp) hack + local size = details.fontdata.parameters.size + local factor = details.fontdata.parameters.factor + local descriptions = { } + local characters = details.fontdata.characters + -- + local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) + local reverse = table.swapped(names) + local vector = encoding.vector + local indices = details.indices + local remapped = { } + local factor = bpfactor * size / 65536 + for k, v in next, indices do + local name = vector[k] + local index = reverse[name] or 0 + local width = factor * (characters[k].width or 0) + descriptions[k] = { + width = width, + index = index, + name = name, + } + remapped[index] = true + end + details.indices = remapped + -- + details.rawdata.descriptions = descriptions + details.filename = filename + details.rawdata.metadata = { } + -- + properties.filename = filename + properties.format = format + writer = mainwriters[format] + end + end + if not writer then + local pfbfile = file.replacesuffix(filename,"pfb") + if encoding and pfbfile then + filename = pfbfile + format = "type1" + -- + -- another (temp) hack + local size = details.fontdata.parameters.size + local factor = details.fontdata.parameters.factor + local descriptions = { } + local characters = details.fontdata.characters + -- + local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) + local reverse = table.swapped(names) + local vector = encoding.vector + local indices = details.indices + local remapped = { } + local factor = bpfactor * size / 65536 + for k, v in next, indices do + local name = vector[k] + local index = reverse[name] or 0 + local width = factor * (characters[k].width or 0) + descriptions[k] = { + width = width, + index = index, + name = name, + } + remapped[index] = true + end + details.indices = remapped + -- + details.rawdata.descriptions = descriptions + details.filename = filename + details.rawdata.metadata = { } + -- + properties.filename = filename + properties.format = format + writer = mainwriters[format] + end + end + if writer then + if trace_fonts then + report_fonts("using main writer %a",format) + end + -- better move this test to the writers .. cleaner + local streams = loadstreamdata(details.fontdata) + if streams and streams.fontheader and streams.names then + details.streams = streams + writer(details) + details.streams = { } + elseif trace_fonts then + -- can be ok for e.g. emoji + report_fonts("no streams in %a",filename) + end + -- free some memory + else -- if trace_fonts then + report_fonts("no %a writer for %a",format,filename) + end + end + else -- not problem for svg ... + -- report_fonts("no indices for %a",filename) + end + if trace_fonts then + report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) + end + mainfonts[details.hash] = false -- done + end + + statistics.stoptiming(objects) + +end + +statistics.register("font embedding time",function() + if noffonts > 0 then + return format("%s seconds, %s fonts", statistics.elapsedtime(objects),noffonts) + end +end) + +-- this is temporary + +local done = false + +updaters.register("backend.update.pdf",function() + if not done then + function pdf.getfontobjnum (k) return objects[k] end + function pdf.getfontname (k) return names [k] end + function pdf.includechar () end -- maybe, when we need it + function pdf.includefont () end -- maybe, when we need it + function pdf.includecharlist () end -- maybe, when we need it + function pdf.setomitcidset (v) includecidset = not toboolean(v) end + function pdf.setomitcharset () end -- we don't need that in lmtx + function pdf.setsuppressoptionalinfo() end -- we don't need that in lmtx + function pdf.mapfile (n) loadmapfile(n) end + function pdf.mapline (n) loadmapline(n) end + -- this will change + lpdf.registerdocumentfinalizer(lpdf.flushfonts,1,"wrapping up fonts") + done = true + end +end) diff --git a/tex/context/base/mkxl/lpdf-img.lmt b/tex/context/base/mkxl/lpdf-img.lmt new file mode 100644 index 000000000..fc53740f6 --- /dev/null +++ b/tex/context/base/mkxl/lpdf-img.lmt @@ -0,0 +1,1341 @@ +if not modules then modules = { } end modules ['lpdf-img'] = { + version = 1.001, + optimize = true, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This started as an experiment but has potential for some (cached) optimizations. +-- At some point we can also use it for fonts. For small images performance is ok +-- with pure lua but for bigger images we can use some helpers. Normally in a +-- typesetting workflow non-interlaced images are used. One should convert +-- interlaced images to more efficient non-interlaced ones (ok, we can cache +-- them if needed). +-- +-- The \LUA\ code is slightly optimized so we could have done with less lines if +-- we wanted but best gain a little. The idea is that we collect striped (in stages) +-- so that we can play with substitutions. + +local type = type +local concat, move = table.concat, table.move +local ceil, min = math.ceil, math.min +local char, byte, find, gmatch = string.char, string.byte, string.find, string.gmatch +local idiv = number.idiv +local band, rshift = bit32.band, bit32.rshift + +local loaddata = io.loaddata +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters + +local streams = utilities.streams +local openstring = streams.openstring +local readstring = streams.readstring +local readbytetable = streams.readbytetable + +local newreader = io.newreader + +local tobytetable = string.bytetable + +local lpdf = lpdf or { } +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfstring = lpdf.string +local pdfflushstreamobject = lpdf.flushstreamobject +local pdfreference = lpdf.reference +local pdfverbose = lpdf.verbose + +local pdfmajorversion = lpdf.majorversion +local pdfminorversion = lpdf.minorversion + +local createimage = images.create + +local zlibcompress = (xzip or zlib).compress +local zlibdecompress = (xzip or zlib).decompress + +local trace = false + +local report_jpg = logs.reporter("graphics","jpg") +local report_jp2 = logs.reporter("graphics","jp2") +local report_png = logs.reporter("graphics","png") + +trackers.register("graphics.backend", function(v) trace = v end) + +local injectors = { } +lpdf.injectors = injectors + +-- todo: load from a virtual file + +local function loadcontent(filename,method) + return method == "string" and filename or loaddata(filename) +end + +local function newcontent(filename,method) + return newreader(filename,method) +end + +-- + +local chars = setmetatableindex(function(t,k) -- share this one + local v = (k <= 0 and "\000") or (k >= 255 and "\255") or char(k) + t[k] = v + return v +end) + +do + + function injectors.jpg(specification,method) + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + local colorspace = specification.colorspace or jpg_gray + local decodearray = nil + ----- procset = colorspace == 0 and "image b" or "image c" + if colorspace == 1 then + colorspace = "DeviceGray" + elseif colorspace == 2 then + colorspace = "DeviceRGB" + elseif colorspace == 3 then + colorspace = "DeviceCMYK" + decodearray = pdfarray { 1, 0, 1, 0, 1, 0, 1, 0 } + end + -- todo: set filename + local xsize = specification.xsize + local ysize = specification.ysize + local colordepth = specification.colordepth + local content = loadcontent(filename,method) + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + -- BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + Filter = pdfconstant("DCTDecode"), + ColorSpace = pdfconstant(colorspace), + Decode = decodearray, + Length = #content, -- specification.length + } + specification.attr + if trace then + report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content) + end + return createimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + transform = specification.transform, + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + function injectors.jp2(specification,method) + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + -- todo: set filename + local xsize = specification.xsize + local ysize = specification.ysize + local content = loadcontent(filename,method) + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + Filter = pdfconstant("JPXDecode"), + Length = #content, -- specification.length + } + specification.attr + if trace then + report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content) + end + return createimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + transform = specification.transform, + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + -- We don't like interlaced files. You can deinterlace them beforehand because otherwise + -- each run you add runtime. Actually, even masked images can best be converted to PDF + -- beforehand. + + -- The amount of code is larger that I like and looks somewhat redundant but we sort of + -- optimize a few combinations that happen often. + + local pngapplyfilter = pngdecode.applyfilter + local pngsplitmask = pngdecode.splitmask + local pnginterlace = pngdecode.interlace + local pngexpand = pngdecode.expand + local pngtocmyk = pngdecode.tocmyk + + local filtermask, decodemask, decodestrip, transpose, expand, tocmyk + + local newindex = lua.newindex + local newtable = lua.newtable + + local function newoutput(size) + if newindex then + return newindex(size,0) + end + local t = newtable and newtable(size,0) or { } + for i=1,size do + t[i] = 0 + end + return t + end + + local function convert(t) + if type(t) == "table" then + for i=1,#t do + local ti = t[i] + if ti ~= "" then -- soon gone + t[i] = chars[ti] + end + end + return concat(t) + else + return t + end + end + + local function zero(t,k) + return 0 + end + + local function applyfilter(t,xsize,ysize,bpp) + local len = xsize * bpp + 1 + local n = 1 + local m = len - 1 + for i=1,ysize do + local filter = t[n] + t[n] = "" + if filter == 0 then + elseif filter == 1 then + for j=n+bpp+1,n+m do + t[j] = (t[j] + t[j-bpp]) % 256 + end + elseif filter == 2 then + for j=n+1,n+m do + t[j] = (t[j] + t[j-len]) % 256 + end + elseif filter == 3 then + for j=n+1,n+bpp do + t[j] = (t[j] + idiv(t[j-len],2)) % 256 + end + for j=n+bpp+1,n+m do + t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256 + end + elseif filter == 4 then + for j=n+1,n+bpp do + local p = j - len + local b = t[p] + if b > 0 then + t[j] = (t[j] + b) % 256 + end + end + for j=n+bpp+1,n+m do + local p = j - len + local a = t[j-bpp] + local b = t[p] + local c = t[p-bpp] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + n = n + len + end + return t + end + + local filtermask_l = function (content,xsize,ysize,colordepth,colorspace,hasfilter) + local mask = { } + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local length = #content + local size = ysize * xsize * ((bpp+1)*bytes + (hasfilter and 1 or 0)) + local n = 1 + local l = 1 + if bytes == 2 then + if bpp == 1 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + elseif bpp == 3 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + else + return "", "" + end + else + if bpp == 1 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + elseif bpp == 3 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + else + return "", "" + end + end + return concat(content), concat(mask) + end + + local decodemask_l = function(content,xsize,ysize,colordepth,colorspace) + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local slice = bytes*(bpp+1) + local length = #content + local size = ysize * xsize * ((bpp+1)*bytes + 1) -- assume filter + content = openstring(content) + content = readbytetable(content,length) + setmetatableindex(content,zero) + applyfilter(content,xsize,ysize,slice) + content, mask = filtermask(content,xsize,ysize,colordepth,colorspace,true) + return content, mask + end + + local filtermask_c = function(content,xsize,ysize,colordepth,colorspace) + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + return pngsplitmask(content,xsize,ysize,bpp,bytes) + end + + local decodemask_c = function(content,xsize,ysize,colordepth,colorspace) + local mask = true + local filter = false + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local slice = bytes * (bpp + 1) -- always a mask + content = pngapplyfilter(content,xsize,ysize,slice) + return pngsplitmask(content,xsize,ysize,bpp,bytes,mask,filter) + end + + local function decodestrip_l(s,nx,ny,slice) + local input = readbytetable(s,ny*(nx*slice+1)) + setmetatableindex(input,zero) + applyfilter(input,nx,ny,slice) + return input, true + end + + local function decodestrip_c(s,nx,ny,slice) + local input = readstring(s,ny*(nx*slice+1)) + input = pngapplyfilter(input,nx,ny,slice) + return input, false + end + + local xstart = { 0, 4, 0, 2, 0, 1, 0 } + local ystart = { 0, 0, 4, 0, 2, 0, 1 } + local xstep = { 8, 8, 4, 4, 2, 2, 1 } + local ystep = { 8, 8, 8, 4, 4, 2, 2 } + + local xblock = { 8, 4, 4, 2, 2, 1, 1 } + local yblock = { 8, 8, 4, 4, 2, 2, 1 } + + local function transpose_l(xsize,ysize,slice,pass,input,output,filter) + local xstart = xstart[pass] + local xstep = xstep[pass] + local ystart = ystart[pass] + local ystep = ystep[pass] + local nx = idiv(xsize + xstep - xstart - 1,xstep) + local ny = idiv(ysize + ystep - ystart - 1,ystep) + local offset = filter and 1 or 0 + local xstep = xstep * slice + local xstart = xstart * slice + local xsize = xsize * slice + local target = ystart * xsize + xstart + 1 + local ystep = ystep * xsize + local start = 1 + local plus = nx * xstep + local step = plus - xstep + if not output then + output = newoutput(xsize*(parts or slice)*ysize) + end + if slice == 1 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + start = start + slice + end + end + elseif slice == 2 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + start = start + slice + end + end + elseif slice == 3 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + output[target+2] = input[start+2] + start = start + slice + end + end + elseif slice == 4 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + output[target+2] = input[start+2] + output[target+3] = input[start+3] + start = start + slice + end + end + else + local delta = slice - 1 + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + move(input,start,start+delta,target,output) + start = start + slice + end + end + end + return output; + end + + local transpose_c = pnginterlace + + -- print(band(rshift(v,4),0x03),extract(v,4,2)) + -- print(band(rshift(v,6),0x03),extract(v,6,2)) + + local function expand_l(t,xsize,ysize,parts,run,factor,filter) + local size = ysize * xsize + 1 -- a bit of overshoot, needs testing, probably a few bytes us ok + local xline = filter and (run+1) or run + local f = filter and 1 or 0 + local l = xline - 1 + local n = 1 + local o = newoutput(size) + local k = 0 + if factor then + if parts == 4 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 2 + else + k = k + 1 ; o[k] = extract4(v,4) * 0x11 + k = k + 1 ; o[k] = extract4(v,0) * 0x11 + end + end + k = i * xsize + n = n + xline + end + elseif parts == 2 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 4 + else + k = k + 1 ; o[k] = extract2(v,6) * 0x55 + k = k + 1 ; o[k] = extract2(v,4) * 0x55 + k = k + 1 ; o[k] = extract2(v,2) * 0x55 + k = k + 1 ; o[k] = extract2(v,0) * 0x55 + end + end + k = i * xsize + n = n + xline + end + else + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 8 + else + k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,7) * 0xFF + k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,6) * 0xFF + k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,5) * 0xFF + k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,4) * 0xFF + k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,3) * 0xFF + k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,2) * 0xFF + k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,1) * 0xFF + k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,0) * 0xFF + end + end + k = i * xsize + n = n + xline + end + end + else + if parts == 4 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 2 + else + k = k + 1 ; o[k] = extract4(v,4) + k = k + 1 ; o[k] = extract4(v,0) + end + end + k = i * xsize + n = n + xline + end + elseif parts == 2 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 4 + else + k = k + 1 ; o[k] = extract2(v,6) + k = k + 1 ; o[k] = extract2(v,4) + k = k + 1 ; o[k] = extract2(v,2) + k = k + 1 ; o[k] = extract2(v,0) + end + end + k = i * xsize + n = n + xline + end + else + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 8 + else + k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,7) + k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,6) + k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,5) + k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,4) + k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,3) + k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,2) + k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,1) + k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,0) + end + end + k = i * xsize + n = n + xline + end + end + end + for i=size,xsize * ysize +1,-1 do + o[i] = nil + end + return o, false + end + + local expand_c = pngexpand + + local function analyze(colordepth,colorspace,palette,mask) + -- return bytes, parts, factor + if palette then + if colordepth == 16 then + return 2, false, false + elseif colordepth == 8 then + return 1, false, false + elseif colordepth == 4 then + return 1, 4, false + elseif colordepth == 2 then + return 1, 2, false + elseif colordepth == 1 then + return 1, 1, false + end + elseif colorspace == "DeviceGray" then + if colordepth == 16 then + return mask and 4 or 2, false, false + elseif colordepth == 8 then + return mask and 2 or 1, false, false + elseif colordepth == 4 then + return 1, 4, true + elseif colordepth == 2 then + return 1, 2, true + elseif colordepth == 1 then + return 1, 1, true + end + else + if colordepth == 16 then + return mask and 8 or 6, false, false + elseif colordepth == 8 then + return mask and 4 or 3, false, false + elseif colordepth == 4 then + return 3, 4, true + elseif colordepth == 2 then + return 3, 2, true + elseif colordepth == 1 then + return 3, 1, true + end + end + return false, false, false + end + + -- 1 6 4 6 2 6 4 6 + -- 7 7 7 7 7 7 7 7 + -- 5 6 5 6 5 6 5 6 + -- 7 7 7 7 7 7 7 7 + -- 3 6 4 6 3 6 4 6 + -- 7 7 7 7 7 7 7 7 + -- 5 6 5 6 5 6 5 6 + -- 7 7 7 7 7 7 7 7 + + local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) + local slice, parts, factor = analyze(colordepth,colorspace,palette,mask) + if slice then + content = openstring(zlibdecompress(content)) + local filter = false + local output = false + for pass=1,7 do + local xstart = xstart[pass] + local xstep = xstep[pass] + local ystart = ystart[pass] + local ystep = ystep[pass] + local nx = idiv(xsize + xstep - xstart - 1,xstep) + local ny = idiv(ysize + ystep - ystart - 1,ystep) + if nx > 0 and ny > 0 then + local input, filter + if parts then + local nxx = ceil(nx*parts/8) + input, filter = decodestrip(content,nxx,ny,slice) + input, filter = expand(input,nx,ny,parts,nxx,factor,filter) + else + input, filter = decodestrip(content,nx,ny,slice) + end + output = transpose(xsize,ysize,slice,pass,input,output,filter) + end + -- if pass == 3 then + -- break -- still looks ok, could be nice for a preroll + -- end + end + return output, parts and 8 or false + end + end + + -- 1 (palette used), 2 (color used), and 4 (alpha channel used) + + -- paeth: + -- + -- p = a + b - c + -- pa = abs(p - a) => a + b - c - a => b - c + -- pb = abs(p - b) => a + b - c - b => a - c + -- pc = abs(p - c) => a + b - c - c => a + b - c - c => a - c + b - c => pa + pb + + local function full(t,k) local v = "\xFF" t[k] = v return v end + + local function expandvector(transparent) + local s = openstring(transparent) + local n = #transparent + local r = { } + for i=0,n-1 do + r[i] = readstring(s,1) -- readchar + end + setmetatableindex(r,full) + return r + end + + local function createmask_l(content,palette,transparent,xsize,ysize,colordepth,colorspace) + if palette then + local r = expandvector(transparent) + local size = xsize*ysize + local len = ceil(xsize*colordepth/8) + 1 + local o = newoutput(xsize*ysize) + local u = setmetatableindex(zero) + content = zlibdecompress(content) + content = openstring(content) + for i=0,ysize-1 do + local t = readbytetable(content,len) + local k = i * xsize + local filter = t[1] + if filter == 0 then + elseif filter == 1 then + for j=3,len do + t[j] = (t[j] + t[j-1]) % 256 + end + elseif filter == 2 then + for j=2,len do + t[j] = (t[j] + u[j]) % 256 + end + elseif filter == 3 then + local j = 2 + t[j] = (t[j] + idiv(u[j],2)) % 256 + for j=3,len do + t[j] = (t[j] + idiv(t[j-1] + u[j],2)) % 256 + end + elseif filter == 4 then + local j = 2 + local p = j - len + local b = t[p] + if b < 0 then + b = - b + end + if b > 0 then + t[j] = (t[j] + b) % 256 + end + for j=3,len do + local p = j - len + local a = t[j-1] + local b = t[p] + local c = t[p-1] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + if colordepth == 8 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[v] + end + elseif colordepth == 4 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract4(v,4)] + k = k + 1 ; o[k] = r[extract4(v,0)] + end + elseif colordepth == 2 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract2(v,6)] + k = k + 1 ; o[k] = r[extract2(v,4)] + k = k + 1 ; o[k] = r[extract2(v,2)] + k = k + 1 ; o[k] = r[extract2(v,0)] + end + else + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract1(v,7)] + k = k + 1 ; o[k] = r[extract1(v,6)] + k = k + 1 ; o[k] = r[extract1(v,5)] + k = k + 1 ; o[k] = r[extract1(v,4)] + k = k + 1 ; o[k] = r[extract1(v,3)] + k = k + 1 ; o[k] = r[extract1(v,2)] + k = k + 1 ; o[k] = r[extract1(v,1)] + k = k + 1 ; o[k] = r[extract1(v,0)] + end + end + u = t + end + return concat(o,"",1,size) + end + end + + local function createmask_c(content,palette,transparent,xsize,ysize,colordepth,colorspace) + if palette then + local r = expandvector(transparent) + local size = xsize*ysize + local len = ceil(xsize*colordepth/8) + local o = newoutput(size) + content = zlibdecompress(content) + content = pngapplyfilter(content,len,ysize,1) -- nostrip (saves copy) + content = openstring(content) + for i=0,ysize-1 do + local t = readbytetable(content,len) + local k = i * xsize + if colordepth == 8 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[v] + end + elseif colordepth == 4 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract4(v,4)] + k = k + 1 ; o[k] = r[extract4(v,0)] + end + elseif colordepth == 2 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract2(v,6)] + k = k + 1 ; o[k] = r[extract2(v,4)] + k = k + 1 ; o[k] = r[extract2(v,2)] + k = k + 1 ; o[k] = r[extract2(v,0)] + end + else + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract1(v,7)] + k = k + 1 ; o[k] = r[extract1(v,6)] + k = k + 1 ; o[k] = r[extract1(v,5)] + k = k + 1 ; o[k] = r[extract1(v,4)] + k = k + 1 ; o[k] = r[extract1(v,3)] + k = k + 1 ; o[k] = r[extract1(v,2)] + k = k + 1 ; o[k] = r[extract1(v,1)] + k = k + 1 ; o[k] = r[extract1(v,0)] + end + end + end + return concat(o,"",1,size) + end + end + + local function tocmyk_l(content,colordepth) + local l = #content + local t = { } + local n = 0 + if colordepth == 8 then + for i=1,l,3 do + local r, g, b = byte(content,i,i+2) + n = n + 1 ; t[n] = char(255-r,255-g,255-b,0) -- a tad faster than chars[...] + end + else + for i=1,l,6 do + local r1, r2, g1, g2, b1, b2 = byte(content,i,i+5) + n = n + 1 ; t[n] = char(255-r1,255-r2,255-g1,255-g2,255-b1,255-b2,0,0) + end + end + return concat(t) + end + + local tocmyk_c = pngtocmyk or tocmyk_l + + local function converttocmyk(content,colorspace,colordepth) + if colorspace == "DeviceRGB" and colordepth == 8 or colordepth == 16 then + local done = tocmyk(content,colordepth) + if done then + content = done + colorspace = "DeviceCMYK" + end + end + return content, colorspace + end + + local function switch(v) + if v then + filtermask = filtermask_l + decodemask = decodemask_l + decodestrip = decodestrip_l + transpose = transpose_l + expand = expand_l + createmask = createmask_l + tocmyk = tocmyk_l + else + filtermask = filtermask_c + decodemask = decodemask_c + decodestrip = decodestrip_c + transpose = transpose_c + expand = expand_c + createmask = createmask_c + tocmyk = tocmyk_c + end + end + + if pngapplyfilter then + switch(false) + directives.register("graphics.png.purelua",switch) + else + switch(true) + end + + local alwaysdecode = false -- trucky with palettes + local compresslevel = 3 + + directives.register("graphics.png.recompress", function(v) + alwaysdecode = v + end) + + directives.register("graphics.png.compresslevel", function(v) + v = tonumber(v) + if compresslevel >= 0 or compresslevel <= 9 then + compresslevel = v + end + end) + + function injectors.png(specification,method) -- todo: method in specification + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + local colorspace = specification.colorspace + if not colorspace then + return + end + local interlace = specification.interlace or 0 + if interlace == 1 then + interlace = true + elseif interlace == 0 then + interlace = false + else + report_png("unknown interlacing %i",interlace) + return + end + local tables = specification.tables + if not tables then + return + end + local idat = tables.idat + if not idat then + return + end + local pngfile = newcontent(filename,method) + if not pngfile then + return + end + local content = idat(pngfile,true) + tables.idat = false + -- + -- if tables.gama then + -- report_png("ignoring gamma correction") + -- end + -- + local xsize = specification.xsize + local ysize = specification.ysize + local colordepth = specification.colordepth or 8 + local mask = false + local transparent = false + local palette = false + local enforcecmyk = specification.enforcecmyk + local colors = 1 + if colorspace == 0 then -- gray | image b + colorspace = "DeviceGray" + transparent = true + elseif colorspace == 2 then -- rgb | image c + colorspace = "DeviceRGB" + colors = 3 + transparent = true + elseif colorspace == 3 then -- palette | image c+i + colorspace = "DeviceRGB" + palette = true + transparent = true + elseif colorspace == 4 then -- gray | alpha | image b + colorspace = "DeviceGray" + mask = true + elseif colorspace == 6 then -- rgb | alpha | image c + colorspace = "DeviceRGB" + colors = 3 + mask = true + else + report_png("unknown colorspace %i",colorspace) + return + end + -- + if transparent then + local trns = tables.trns + if trns then + transparent = trns(pngfile,true) + if transparent == "" then + transparent = false + end + tables.trns = false + else + transparent = false + end + end + -- + local decode = alwaysdecode -- tricky, might go away + local filter = pdfconstant("FlateDecode") + local major = pdfmajorversion() + local minor = pdfminorversion() + if major > 1 then + -- we're okay + elseif minor < 5 and colordepth == 16 then + report_png("16 bit colordepth not supported in pdf < 1.5") + return + elseif minor < 4 and (mask or transparent) then + report_png("alpha channels not supported in pdf < 1.4") + return + elseif minor < 2 then + report_png("you'd better use a version > 1.2") + return + -- decode = true + end + -- + -- todo: compresslevel (or delegate) + -- + if palette then + local plte = tables.plte + if plte then + palette = plte(pngfile,true) + if palette == "" then + palette = false + end + tables.plte = false + else + palette = false + end + end + -- + if interlace then + local r, p = deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) + if not r then + return + end + if p then + colordepth = p + end + if mask then + if not (colordepth == 8 or colordepth == 16) then + report_png("mask can't be split from the image") + return + end -- get rid of bpp: + content, mask = filtermask(r,xsize,ysize,colordepth,colorspace,false) + else + content = convert(r) -- can be in deinterlace if needed + end + if enforcecmyk then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + decode = true + elseif mask then + if not (colordepth == 8 or colordepth == 16) then + report_png("mask can't be split from the image") + return + end + content = zlibdecompress(content) + content, mask = decodemask(content,xsize,ysize,colordepth,colorspace) + if enforcecmyk and not palette then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + decode = true -- we don't copy the filter byte + elseif transparent then + -- in test suite + -- how about decode/recompress here + if palette then + mask = createmask(content,palette,transparent,xsize,ysize,colordepth,colorspace) + else + pallette = false + end + elseif decode or (enforcecmyk and not palette) then + -- this one needs checking + local bytes = analyze(colordepth,colorspace) + if bytes then + content = zlibdecompress(content) + content = decodestrip(openstring(content),xsize,ysize,bytes) + if enforcecmyk and not palette then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + else + return + end + decode = true -- due to enforcecmyk + else + -- print("PASS ON") + end + if palette then + local colorspace = "DeviceRGB" + local nofbytes = 3 + if enforcecmyk then + palette = converttocmyk(palette,colorspace,8) + colorspace = "DeviceCMYK" + nofbytes = 4 + end + palette = pdfarray { + pdfconstant("Indexed"), + pdfconstant(colorspace), + idiv(#palette,nofbytes), + pdfreference(pdfflushstreamobject(palette)), + } + end + pngfile:close() + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + -- BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + Filter = filter, + ColorSpace = palette or pdfconstant(colorspace), + Length = #content, + } + specification.attr + if mask then + local d = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + Width = xsize, + Height = ysize, + BitsPerComponent = palette and 8 or colordepth, + ColorSpace = pdfconstant("DeviceGray"), + } + xobject.SMask = pdfreference(pdfflushstreamobject(mask,d())) + end + if not decode then + xobject.DecodeParms = pdfdictionary { + Colors = colors, + Columns = xsize, + BitsPerComponent = colordepth, + Predictor = 15, + } + end + if trace then + report_png("%s: width %i, height %i, colordepth %i, size %i, palette %l, mask %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode) + end + if specification.colorref then + xobject.ColorSpace = pdfreference(specification.colorref) + end + local width = specification.width or xsize * 65536 + local height = specification.height or ysize * 65536 + return createimage { + bbox = { 0, 0, width/xsize, height/ysize }, -- mandate + transform = specification.transform, + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + local function pack(specification,what) + local t = { } + local n = 0 + local s = specification.colorspace + local d = specification.data + local x = specification.xsize + local y = specification.ysize + if what == "mask" then + d = specification.mask + s = 1 + elseif what == "indexed" then + s = 1 + elseif what == "index" then + d = specification.index + s = - s + end + if s > 0 then + if s == 1 then + for i=1,y do + local r = d[i] + for j=1,x do + n = n + 1 ; t[n] = chars[r[j]] + end + end + elseif s == 2 then + for i=1,y do + local r = d[i] + for j=1,x do + local c = r[j] + n = n + 1 ; t[n] = chars[c[1]] + n = n + 1 ; t[n] = chars[c[2]] + n = n + 1 ; t[n] = chars[c[3]] + -- n = n + 1 ; t[n] = char(c[1],c[2],c[3]) -- test this + end + end + elseif s == 3 then + for i=1,y do + local r = d[i] + for j=1,x do + local c = r[j] + n = n + 1 ; t[n] = chars[c[1]] + n = n + 1 ; t[n] = chars[c[2]] + n = n + 1 ; t[n] = chars[c[3]] + n = n + 1 ; t[n] = chars[c[4]] + -- n = n + 1 ; t[n] = char(c[1],c[2],c[3],c[4]) -- test this + end + end + end + return concat(t) + else + local z = d[0] and 0 or 1 + if s == -1 then + local f = formatters["%02X"] + for i=z,#d do + n = n + 1 ; t[n] = f(d[i]) + end + elseif s == -2 then + local f = formatters["%02X%02X%02X"] + for i=z,#d do + local c = d[i] + n = n + 1 ; t[n] = f(c[1],c[2],c[3]) + end + elseif s == -3 then + local f = formatters["%02X%02X%02X%02X"] + for i=z,#d do + local c = d[i] + n = n + 1 ; t[n] = f(c[1],c[2],c[3],c[4]) + end + end + return "<" .. concat(t," ") .. ">" + end + return "" + end + + function injectors.bitmap(specification) + local data = specification.data + if not data then + return + end + local xsize = specification.xsize or 0 + local ysize = specification.ysize or 0 + if xsize == 0 or ysize == 0 then + return + end + local colorspace = specification.colorspace or 1 + if colorspace == 1 then + colorspace = "DeviceGray" + elseif colorspace == 2 then + colorspace = "DeviceRGB" + elseif colorspace == 3 then + colorspace = "DeviceCMYK" + end + local colordepth = (specification.colordepth or 2) == 16 or 8 + local index = specification.index + local content = pack(specification,index and "indexed" or "data") + local mask = specification.mask + local colorspace = pdfconstant(colorspace) + if index then + colorspace = pdfarray { + pdfconstant("Indexed"), + colorspace, + #index + (index[0] and 0 or -1), -- upper index + pdfverbose(pack(specification,"index")) + } + end + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + ColorSpace = colorspace, + Length = #content, -- specification.length + } + if mask then + local d = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + ColorSpace = pdfconstant("DeviceGray"), + } + xobject.SMask = pdfreference(pdfflushstreamobject(pack(specification,"mask"),d())) + end + return createimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + -- nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + + backends.pdf.codeinjections.bitmap = injectors.bitmap + +end + +-- local function validcompression(data) +-- local d = utilities.streams.openstring(data) +-- local b1 = utilities.streams.readbyte(d) +-- local b2 = utilities.streams.readbyte(d) +-- print(b1,b2) +-- if (b1 * 256 + b2) % 31 ~= 0 then +-- return false, "no zlib compressed file" +-- end +-- local method = band(b1,15) +-- if method ~= 8 then +-- return false, "method 8 expected" +-- end +-- local detail = band(rshift(b1,4),15) +-- if detail > 7 then +-- return false, "window 32 expected" +-- end +-- local preset = band(rshift(b2,5),1) +-- if preset ~= 0 then +-- return false, "unexpected preset dictionary" +-- end +-- return true +-- end diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt new file mode 100644 index 000000000..2bbf5ba61 --- /dev/null +++ b/tex/context/base/mkxl/lpdf-lmt.lmt @@ -0,0 +1,2840 @@ +if not modules then modules = { } end modules ['lpdf-lmt'] = { + version = 1.001, + optimize = true, + 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 code below was originally in back-lpd.lua but it makes more sense in +-- this namespace. I will rename variables. +-- +-- There is no way that a lua based backend can compete with the original one +-- for relative simple text runs. And we're talking seconds here on say 500 +-- pages with paragraphs alternativng between three fonts and colors. But such +-- documents are rare so in practice we are quite okay, especially because in +-- ConTeXt we can gain quite a bit elsewhere. So, when we loose 30% on such +-- simple documents, we break even on for instance the manual, and gain 30% on +-- Thomas's turture test (also for other reasons). But .. who knows what magic +-- I can cook up in due time. + +-- If you consider this complex, watch: +-- +-- https://www.youtube.com/watch?v=6H-cAzfB2qo +-- +-- or in distractionmode: +-- +-- https://www.youtube.com/watch?v=TYuTE_1jvvE +-- https://www.youtube.com/watch?v=nnicGKX3lvM +-- +-- For the moment we have to support the built in backend as well as the alternative. So +-- the next interface is suboptimal and will change at some time. At that moment I will +-- also optimize and extend. + +local type, next, unpack, tonumber, rawget = type, next, unpack, tonumber, rawget +local char, rep, find = string.char, string.rep, string.find +local formatters, splitupstring = string.formatters, string.splitup +local band, extract = bit32.band, bit32.extract +local concat, sortedhash = table.concat, table.sortedhash +local setmetatableindex = table.setmetatableindex +local loaddata = io.loaddata + +local bpfactor = number.dimenfactors.bp + +local md5HEX = md5.HEX +local osuuid = os.uuid +local zlibcompress = (xzip or zlib).compress + +local nuts = nodes.nuts +local tonut = nodes.tonut + +local getdata = nuts.getdata +local getsubtype = nuts.getsubtype +local getwhd = nuts.getwhd +local flushlist = nuts.flush_list + +local pdfincludeimage = lpdf.includeimage +local pdfgetfontname = lpdf.getfontname +local pdfgetfontobjnumber = lpdf.getfontobjnumber + +local pdfreserveobject = lpdf.reserveobject +local pdfpagereference = lpdf.pagereference +local pdfflushobject = lpdf.flushobject +local pdfsharedobject = lpdf.shareobjectreference +local pdfreference = lpdf.reference +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfflushstreamobject = lpdf.flushstreamobject +local pdfliteral = lpdf.literal -- not to be confused with a whatsit! + +local pdf_pages = pdfconstant("Pages") +local pdf_page = pdfconstant("Page") +local pdf_xobject = pdfconstant("XObject") +local pdf_form = pdfconstant("Form") + +local fonthashes = fonts.hashes +local characters = fonthashes.characters +local descriptions = fonthashes.descriptions +local parameters = fonthashes.parameters +local properties = fonthashes.properties + +local report = logs.reporter("backend") + +-- used variables + +local pdf_h, pdf_v +local need_tm, need_tf, cur_tmrx, cur_factor, cur_f, cur_e +local need_width, need_mode, done_width, done_mode +local mode +local f_pdf_cur, f_pdf, fs_cur, fs, f_cur +local tj_delta, cw +local usedfonts, usedxforms, usedximages, usedxgroups +local getxformname, getximagename +local boundingbox, shippingmode, objectnumber +local tmrx, tmry, tmsx, tmsy, tmtx, tmty +local cmrx, cmry, cmsx, cmsy, cmtx, cmty +local tmef + +local function usefont(t,k) -- a bit redundant hash + local v = pdfgetfontname(k) + t[k] = v + return v +end + +local function reset_variables(specification) + pdf_h, pdf_v = 0, 0 + cmrx, cmry = 1.0, 1.0 + cmsx, cmsy = 0.0, 0.0 + cmtx, cmty = 0.0, 0.0 + tmrx, tmry = 1.0, 1.0 + tmsx, tmsy = 0.0, 0.0 + tmtx, tmty = 0.0, 0.0 + tmef = 1.0 + need_tm = false + need_tf = false + need_width = 0 + need_mode = 0 + done_width = false + done_mode = false + mode = "page" + shippingmode = specification.shippingmode + objectnumber = specification.objectnumber + cur_tmrx = 0.0 + f_cur = 0 + f_pdf_cur = 0 -- nullfont + f_pdf = 0 -- nullfont + fs_cur = 0 + fs = 0 + cur_factor = 0 + cur_f = false + cur_e = false + tj_delta = 0.0 + cw = 0.0 + usedfonts = setmetatableindex(usefont) + usedxforms = { } + usedximages = { } + -- usedxgroups = { } + boundingbox = specification.boundingbox +end + +-- buffer + +local buffer = lua.newtable(1024,0) -- { } +local b = 0 + +local function reset_buffer() + b = 0 +end + +-- fonts + +local fontcharacters +local fontdescriptions +local fontparameters +local fontproperties +local usedcharacters = setmetatableindex("table") +local pdfcharacters + +local horizontalmode = true +----- widefontmode = true +local scalefactor = 1 +local threshold = 655360 +local thresfactor = 100 +local tjfactor = 100 / 65536 + +lpdf.usedcharacters = usedcharacters + +local function updatefontstate(font) + fontcharacters = characters[font] + fontdescriptions = descriptions[font] + fontparameters = parameters[font] + fontproperties = properties[font] + local size = fontparameters.size -- or bad news + local designsize = fontparameters.designsize or size + pdfcharacters = usedcharacters[font] + horizontalmode = fontparameters.writingmode ~= "vertical" + -- widefontmode = fontproperties.encodingbytes == 2 + scalefactor = (designsize/size) * tjfactor + local fthreshold = fontproperties.threshold + threshold = (fthreshold and (size * fthreshold / 100)) or 655360 + -- when we bolden the threshold should be smaller .. a hack .. i need to redo all this + if (fontparameters.extendfactor or 1) == 1 then + -- we're probably okay + elseif fontparameters.hshift or fontparameters.vshift then + -- we could be okay + else + -- some vf magic going on + threshold = threshold / 5 + end +end + +-- helpers + +local f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] +local f_tm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N Tm"] + +local saved_text_pos_v = 0 +local saved_text_pos_h = 0 + +local function begin_text() + saved_text_pos_h = pdf_h + saved_text_pos_v = pdf_v + b = b + 1 ; buffer[b] = "BT" + need_tf = true + need_width = 0 + need_mode = 0 + mode = "text" +end + +local function end_text() + if done_width then + b = b + 1 ; buffer[b] = "0 w" + done_width = false + end + if done_mode then + b = b + 1 ; buffer[b] = "0 Tr" + done_mode = false + end + b = b + 1 ; buffer[b] = "ET" + pdf_h = saved_text_pos_h + pdf_v = saved_text_pos_v + mode = "page" +end + +local saved_chararray_pos_h +local saved_chararray_pos_v + +local saved_b = 0 + +local function begin_chararray() + saved_chararray_pos_h = pdf_h + saved_chararray_pos_v = pdf_v + cw = horizontalmode and saved_chararray_pos_h or - saved_chararray_pos_v + tj_delta = 0 + saved_b = b + b = b + 1 ; buffer[b] = " [" + mode = "chararray" +end + +local function end_chararray() + b = b + 1 ; buffer[b] = "] TJ" + buffer[saved_b] = concat(buffer,"",saved_b,b) + b = saved_b + pdf_h = saved_chararray_pos_h + pdf_v = saved_chararray_pos_v + mode = "text" +end + +local function begin_charmode() + b = b + 1 ; buffer[b] = "<" + mode = "char" +end + +local function end_charmode() + b = b + 1 ; buffer[b] = ">" + mode = "chararray" +end + +local function calc_pdfpos(h,v) + -- mostly char + if mode == "page" then + cmtx = h - pdf_h + cmty = v - pdf_v + return h ~= pdf_h or v ~= pdf_v + elseif mode == "text" then + tmtx = h - saved_text_pos_h + tmty = v - saved_text_pos_v + return h ~= pdf_h or v ~= pdf_v + elseif horizontalmode then + tmty = v - saved_text_pos_v + tj_delta = cw - h + return tj_delta ~= 0 or v ~= pdf_v + else + tmtx = h - saved_text_pos_h + tj_delta = cw + v + return tj_delta ~= 0 or h ~= pdf_h + end +end + +local function pdf_set_pos(h,v) + local move = calc_pdfpos(h,v) + if move then + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + pdf_h = pdf_h + cmtx + pdf_v = pdf_v + cmty + end +end + +local function pdf_reset_pos() + if mode == "page" then + cmtx = - pdf_h + cmty = - pdf_v + if pdf_h == 0 and pdf_v == 0 then + return + end + elseif mode == "text" then + tmtx = - saved_text_pos_h + tmty = - saved_text_pos_v + if pdf_h == 0 and pdf_v == 0 then + return + end + elseif horizontalmode then + tmty = - saved_text_pos_v + tj_delta = cw + if tj_delta == 0 and pdf_v == 0 then + return + end + else + tmtx = - saved_text_pos_h + tj_delta = cw + if tj_delta == 0 and pdf_h == 0 then + return + end + end + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + pdf_h = pdf_h + cmtx + pdf_v = pdf_v + cmty +end + +local function pdf_set_pos_temp(h,v) + local move = calc_pdfpos(h,v) + if move then + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + end +end + +-- these dummy returns makes using them a bit faster + +local function pdf_end_string_nl() + if mode == "char" then + end_charmode() + return end_chararray() + elseif mode == "chararray" then + return end_chararray() + end +end + +local function pdf_goto_textmode() + if mode == "page" then + pdf_reset_pos() + return begin_text() + elseif mode ~= "text" then + if mode == "char" then + end_charmode() + return end_chararray() + else -- if mode == "chararray" then + return end_chararray() + end + end +end + +local function pdf_goto_pagemode() + if mode ~= "page" then + if mode == "char" then + end_charmode() + end_chararray() + return end_text() + elseif mode == "chararray" then + end_chararray() + return end_text() + elseif mode == "text" then + return end_text() + end + end +end + +local function pdf_goto_fontmode() + if mode == "char" then + end_charmode() + end_chararray() + end_text() + elseif mode == "chararray" then + end_chararray() + end_text() + elseif mode == "text" then + end_text() + end + pdf_reset_pos() + mode = "page" +end + +-- characters + +local flushcharacter do + + local round = math.round + + -- across pages ... todo: clean up because we don't need to pass the font + -- as fontparameters already has checked / set it we can also have a variable + -- for it so + + local naturalwidth = nil + local hshift = false + local vshift = false + + -- local naturalwidths = setmetatableindex(function(t,font) + -- local d = descriptions[font] + -- local c = characters[font] + -- local f = parameters[font].hfactor + -- local v = setmetatableindex(function(t,char) + -- local w + -- local e = d and d[char] + -- if e then + -- w = e.width + -- if w then + -- w = w * f + -- end + -- end + -- if not w then + -- e = c[char] + -- if e then + -- w = e.width or 0 + -- end + -- end + -- if not w then + -- w = 0 + -- end + -- t[char] = w + -- return w + -- end) + -- t[font] = v + -- return v + -- end) + + local naturalwidths = setmetatableindex(function(t,font) + local d = descriptions[font] + local c = characters[font] + local f = parameters[font].hfactor + local v = setmetatableindex(function(t,char) + local w + local e = c[char] + if e then + w = e.width or 0 + end + if not w then + e = d and d[char] + if e then + w = e.width + if w then + w = w * f + end + end + end + if not w then + w = 0 + end + t[char] = w + return w + end) + t[font] = v + return v + end) + + local function setup_fontparameters(font,factor,f,e) + local slant = fontparameters.slantfactor or 0 + local extend = fontparameters.extendfactor or 1 + local squeeze = fontparameters.squeezefactor or 1 + local expand = 1 + factor / 1000000 + local format = fontproperties.format + if e then + extend = extend * e + end + tmef = expand + tmrx = expand * extend + tmsy = slant + tmry = squeeze + need_width = fontparameters.width or 0 + need_mode = fontparameters.mode or 0 + f_cur = font + f_pdf = usedfonts[font] -- cache + cur_factor = factor + cur_f = f + cur_e = e + tj_delta = 0 + fs = fontparameters.size * bpfactor + if f then + fs = fs * f + end + -- kind of special: + if format == "opentype" or format == "type1" then + fs = fs * 1000 / fontparameters.units -- can we avoid this ? + end + -- + naturalwidth = naturalwidths[font] + -- + hshift = fontparameters.hshift + vshift = fontparameters.vshift + end + + local f_width = formatters["%.6N w"] + local f_mode = formatters["%i Tr"] -- can be hash + local f_font = formatters["/F%i %.6N Tf"] -- can be hash + + local s_width = "0 w" + local s_mode = "0 Tr" + + local width_factor = 72.27 / 72000.0 + + local function set_font() + -- if need_width and need_width ~= 0 then + if need_width ~= 0 then + b = b + 1 ; buffer[b] = f_width(width_factor*need_width) + done_width = true + elseif done_width then + b = b + 1 ; buffer[b] = s_width + done_width = false + end + -- if need_mode and need_mode ~= 0 then + if need_mode ~= 0 then + b = b + 1 ; buffer[b] = f_mode(need_mode) + done_mode = true + elseif done_mode then + b = b + 1 ; buffer[b] = s_mode + done_mode = false + end + b = b + 1 ; buffer[b] = f_font(f_pdf,fs) + f_pdf_cur = f_pdf + fs_cur = fs + need_tf = false + need_tm = true + end + + local function set_textmatrix(h,v) + local move = calc_pdfpos(h,v) + if need_tm or move then + b = b + 1 ; buffer[b] = f_tm(tmrx, tmsx, tmsy, tmry, tmtx*bpfactor, tmty*bpfactor) + pdf_h = saved_text_pos_h + tmtx + pdf_v = saved_text_pos_v + tmty + need_tm = false + end + cur_tmrx = tmrx + end + + local f_hex_4 = formatters["%04X"] + local f_hex_2 = formatters["%02X"] + + local h_hex_4 = setmetatableindex(function(t,k) -- we already have this somewhere + if k < 256 then -- maybe 512 + -- not sparse in this range + for i=0,255 do + t[i] = f_hex_4(i) + end + return t[k] + else + local v = f_hex_4(k) + t[k] = v + return v + end + end) + local h_hex_2 = setmetatableindex(function(t,k) -- we already have this somewhere + local v = k < 256 and f_hex_2(k) or "00" + t[k] = v + return v + end) + + -- local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) + + -- local f_skip = formatters["%.2N"] + + -- I will redo this mess ... we no longer have the mkiv pdf generator that we used in + -- luatex (a precursor to lmtx and also for comparison) but only in lmtx now so ... + -- time to move on I guess. + + flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then + pdf_goto_textmode() + setup_fontparameters(font,factor,f,e) + set_font() + elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then + setup_fontparameters(font,factor,f,e) + need_tm = true + end + local move = calc_pdfpos(pos_h,pos_v) + + -- if trace_threshold then + -- report( + -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", + -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw + -- ) + -- end + + if move or need_tm then + if not need_tm then + if horizontalmode then + if (saved_text_pos_v + tmty) ~= pdf_v then + need_tm = true + elseif tj_delta >= threshold or tj_delta <= -threshold then + need_tm = true + end + else + if (saved_text_pos_h + tmtx) ~= pdf_h then + need_tm = true + elseif tj_delta >= threshold or tj_delta <= -threshold then + need_tm = true + end + end + end + + if hshift then pos_h = pos_h + hshift end + if vshift then pos_v = pos_v - vshift end + + if need_tm then + pdf_goto_textmode() + set_textmatrix(pos_h,pos_v) + begin_chararray() + move = calc_pdfpos(pos_h,pos_v) + end + if move then + local d = tj_delta * scalefactor + if d <= -0.5 or d >= 0.5 then + if mode == "char" then + end_charmode() + end + b = b + 1 ; buffer[b] = round(d) -- or f_skip(d) + end + cw = cw - tj_delta + end + end + + if mode == "chararray" then + begin_charmode() + end + + cw = cw + naturalwidth[char] * tmef + + local index = data.index or char + + b = b + 1 ; buffer[b] = font > 0 and h_hex_4[index] or h_hex_2[index] + + if not pdfcharacters[index] then + pdfcharacters[index] = true + end + + end + + flushfontchar = function(font,char,data) + local dummy = usedfonts[font] + local index = data.index or char + if not pdfcharacters[index] then + pdfcharacters[index] = true + end + return dummy + end + +end + +-- literals + +local flushliteral do + + local nodeproperties = nodes.properties.data + local literalvalues = nodes.literalvalues + + local originliteral_code = literalvalues.origin + local pageliteral_code = literalvalues.page + local alwaysliteral_code = literalvalues.always + local rawliteral_code = literalvalues.raw + local textliteral_code = literalvalues.text + local fontliteral_code = literalvalues.font + + flushliteral = function(current,pos_h,pos_v,mode,str) + if mode then + if not str then + mode, str = originliteral_code, mode + elseif mode == "mode" then + mode = literalvalues[str] + if mode == originliteral_code then + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + end + return + else + mode = literalvalues[mode] + end + else + local p = nodeproperties[current] + if p then + str = p.data + mode = p.mode + else + str, mode = getdata(current) + end + end + if str and str ~= "" then + if mode == originliteral_code then + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + else + report("check literal") + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + end + b = b + 1 ; buffer[b] = str + end + end + + updaters.register("backend.update.pdf",function() + function pdf.print(mode,str) + -- This only works inside objects, don't change this to flush + -- in between. It's different from luatex but okay. + if str then + mode = literalvalues[mode] + else + mode, str = originliteral_code, mode + end + if str and str ~= "" then + if mode == originliteral_code then + pdf_goto_pagemode() + -- pdf_set_pos(pdf_h,pdf_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + else + pdf_goto_pagemode() + -- pdf_set_pos(pdf_h,pdf_v) + end + b = b + 1 ; buffer[b] = str + end + end + end) + +end + +-- grouping & orientation + +local flushsave, flushrestore, flushsetmatrix do + + local matrices = { } + local positions = { } + local nofpositions = 0 + local nofmatrices = 0 + + local f_matrix = formatters["%s 0 0 cm"] + + flushsave = function(current,pos_h,pos_v) + nofpositions = nofpositions + 1 + positions[nofpositions] = { pos_h, pos_v, nofmatrices } + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "q" + end + + flushrestore = function(current,pos_h,pos_v) + if nofpositions < 1 then + return + end + local t = positions[nofpositions] + -- local h = pos_h - t[1] + -- local v = pos_v - t[2] + if shippingmode == "page" then + nofmatrices = t[3] + end + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "Q" + nofpositions = nofpositions - 1 + end + + local function pdf_set_matrix(str,pos_h,pos_v) + if shippingmode == "page" then + local rx, sx, sy, ry = splitupstring(str," ") + if rx and ry and sx and ry then + rx, sx, sy, ry = tonumber(rx), tonumber(sx), tonumber(sy), tonumber(ry) + local tx = pos_h * (1 - rx) - pos_v * sy + local ty = pos_v * (1 - ry) - pos_h * sx + if nofmatrices > 0 then + local t = matrices[nofmatrices] + local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6] + rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y + sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y + tx, ty = tx * r_x + ty * s_y, tx * s_x + ty * r_y + end + nofmatrices = nofmatrices + 1 + matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty } + end + end + end + + local nodeproperties = nodes.properties.data + + flushsetmatrix = function(current,pos_h,pos_v) + local str + if type(current) == "string" then + str = current + else + local p = nodeproperties[current] + if p then + str = p.matrix + else + str = getdata(current) -- for the moment + end + end + if str and str ~= "" then + pdf_set_matrix(str,pos_h,pos_v) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = f_matrix(str) + end + end + + do + + local function hasmatrix() + return nofmatrices > 0 + end + + local function getmatrix() + if nofmatrices > 0 then + return unpack(matrices[nofmatrices]) + else + return 1, 0, 0, 1, 0, 0 + end + end + + updaters.register("backend.update.pdf",function() + pdf.hasmatrix = hasmatrix + pdf.getmatrix = getmatrix + end) + + end + + pushorientation = function(orientation,pos_h,pos_v,pos_r) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "q" + if orientation == 1 then + b = b + 1 ; buffer[b] = "0 -1 1 0 0 0 cm" -- 90 + elseif orientation == 2 then + b = b + 1 ; buffer[b] = "-1 0 0 -1 0 0 cm" -- 180 + elseif orientation == 3 then + b = b + 1 ; buffer[b] = "0 1 -1 0 0 0 cm" -- 270 + end + end + + poporientation = function(orientation,pos_h,pos_v,pos_r) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "Q" + end + + -- pushorientation = function(orientation,pos_h,pos_v,pos_r) + -- flushsave(false,pos_h,pos_v) + -- if orientation == 1 then + -- flushsetmatrix("0 -1 1 0",pos_h,pos_v) + -- elseif orientation == 2 then + -- flushsetmatrix("-1 0 0 -1",pos_h,pos_v) + -- elseif orientation == 3 then + -- flushsetmatrix("0 1 -1 0",pos_h,pos_v) + -- end + -- end + + -- poporientation = function(orientation,pos_h,pos_v,pos_r) + -- flushrestore(false,pos_h,pos_v) + -- end + +end + +-- rules + +local flushedxforms = { } -- actually box resources but can also be direct +local localconverter = nil -- will be set + +local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do + + local rulecodes = nodes.rulecodes + local newrule = nodes.pool.rule + + local setprop = nuts.setprop + local getprop = nuts.getprop + + local normalrule_code = rulecodes.normal + local boxrule_code = rulecodes.box + local imagerule_code = rulecodes.image + local emptyrule_code = rulecodes.empty + local userrule_code = rulecodes.user + local overrule_code = rulecodes.over + local underrule_code = rulecodes.under + local fractionrule_code = rulecodes.fraction + local radicalrule_code = rulecodes.radical + local outlinerule_code = rulecodes.outline + + local rule_callback = callbacks.functions.process_rule + + local f_fm = formatters["/Fm%d Do"] + local f_im = formatters["/Im%d Do"] + local f_gr = formatters["/Gp%d Do"] + + local s_b = "q" + local s_e = "Q" + + local f_v = formatters["[] 0 d 0 J %.6N w 0 0 m %.6N 0 l S"] + local f_h = formatters["[] 0 d 0 J %.6N w 0 0 m 0 %.6N l S"] + + local f_f = formatters["0 0 %.6N %.6N re f"] + local f_o = formatters["[] 0 d 0 J 0 0 %.6N %.6N re S"] + local f_w = formatters["[] 0 d 0 J %.6N w 0 0 %.6N %.6N re S"] + + local f_b = formatters["%.6N w 0 %.6N %.6N %.6N re f"] + local f_x = formatters["[] 0 d 0 J %.6N w %.6N %.6N %.6N %.6N re S"] + + -- Historically the index is an object which is kind of bad. + + local boxresources, n = { }, 0 + + getxformname = function(index) + local l = boxresources[index] + if l then + return l.name + else + report("no box resource %S",index) + end + end + + updaters.register("backend.update.pdf",function() + pdf.getxformname = getxformname + end) + + local function saveboxresource(box,attributes,resources,immediate,kind,margin) + n = n + 1 + local immediate = true + local margin = margin or 0 -- or dimension + local objnum = pdfreserveobject() + local list = tonut(type(box) == "number" and tex.takebox(box) or box) + -- + local width, height, depth = getwhd(list) + -- + local l = { + width = width, + height = height, + depth = depth, + margin = margin, + attributes = attributes, + resources = resources, + list = nil, + type = kind, + name = n, + index = objnum, + objnum = objnum, + } + boxresources[objnum] = l + if immediate then + localconverter(list,"xform",objnum,l) + flushedxforms[objnum] = { true , objnum } + flushlist(list) + else + l.list = list + end + return objnum + end + + local function useboxresource(index,wd,ht,dp) + local l = boxresources[index] + if l then + if wd or ht or dp then + wd, ht, dp = wd or 0, ht or 0, dp or 0 + else + wd, ht, dp = l.width, l.height, l.depth + end + local rule = newrule(wd,ht,dp) -- newboxrule + rule.subtype = boxrule_code + setprop(tonut(rule),"index",index) + return rule, wd, ht, dp + else + report("no box resource %S",index) + end + end + + local function getboxresourcedimensions(index) + local l = boxresources[index] + if l then + return l.width, l.height, l.depth, l.margin + else + report("no box resource %S",index) + end + end + + local function getboxresourcebox(index) + local l = boxresources[index] + if l then + return l.list + end + end + + updaters.register("backend.update.tex",function() + tex.saveboxresource = saveboxresource + tex.useboxresource = useboxresource + tex.getboxresourcedimensions = getboxresourcedimensions + tex.getboxresourcebox = getboxresourcebox + end) + + -- a bit of a mess: index is now objnum but that has to change to a proper index + -- ... an engine inheritance + + local function flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) + -- object properties + local objnum = getprop(current,"index") + local name = getxformname(objnum) + local info = flushedxforms[objnum] + local r = boxresources[objnum] + if not info then + info = { false , objnum } + flushedxforms[objnum] = info + end + local wd, ht, dp = getboxresourcedimensions(objnum) + -- or: wd, ht, dp = r.width, r.height, r.depth + -- sanity check + local htdp = ht + dp + if wd == 0 or size_h == 0 or htdp == 0 or size_v == 0 then + return + end + -- calculate scale + local rx, ry = 1, 1 + if wd ~= size_h or htdp ~= size_v then + rx = size_h / wd + ry = size_v / htdp + end + -- flush the reference + usedxforms[objnum] = true + pdf_goto_pagemode() + calc_pdfpos(pos_h,pos_v) + tx = cmtx * bpfactor + ty = cmty * bpfactor + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,0,0,ry,tx,ty) + b = b + 1 ; buffer[b] = f_fm(name) + b = b + 1 ; buffer[b] = s_e + end + + -- place image also used in vf but we can use a different one if we need it + + local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream + local img_none = imagetypes.none + local img_pdf = imagetypes.pdf + local img_stream = imagetypes.stream + local img_memstream = imagetypes.memstream + + local one_bp = 65536 * bpfactor + + local imageresources, n = { }, 0 + + getximagename = function(index) + local l = imageresources[index] + if l then + return l.name + else + report("no image resource %S",index) + end + end + + updaters.register("backend.update.pdf",function() + pdf.getximagename = getximagename + end) + + -- Groups are flushed immediately but we can decide to make them into a + -- specific whatsit ... but not now. We could hash them if needed when + -- we use lot sof them in mp ... but not now. + + usedxgroups = { } + local groups = 0 + local group = nil + + flushgroup = function(content,bbox) + if not group then + group = pdfdictionary { + Type = pdfconstant("Group"), + S = pdfconstant("Transparency"), + } + end + local wrapper = pdfdictionary { + Type = pdf_xobject, + Subtype = pdf_form, + FormType = 1, + Group = group, + BBox = pdfarray(bbox), + Resources = lpdf.collectedresources { serialize = false }, + } + local objnum = pdfflushstreamobject(content,wrapper,false) + groups = groups + 1 + usedxgroups[groups] = objnum + return f_gr(groups) + end + + lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps + + -- end of experiment + + local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) + + local width, + height, + depth = getwhd(current) + local total = height + depth + local transform = getprop(current,"transform") or 0 -- we never set it ... so just use rotation then + local index = getprop(current,"index") or 0 + local kind, + xorigin, + yorigin, + xsize, + ysize, + rotation, -- transform / orientation / rotation : it's a mess (i need to redo this) + objnum, + groupref = pdfincludeimage(index) -- needs to be sorted out, bad name (no longer mixed anyway) + + if not kind then + report("invalid image %S",index) + return + end + + local rx, sx, sy, ry, tx, ty = 1, 0, 0, 1, 0, 0 + + -- tricky: xsize and ysize swapped + + if kind == img_pdf or kind == img_stream or kind == img_memstream then + rx, ry, tx, ty = 1/xsize, 1/ysize, xorigin/xsize, yorigin/ysize + else + -- if kind == img_png then + -- -- if groupref > 0 and img_page_group_val == 0 then + -- -- img_page_group_val = groupref + -- -- end + -- end + rx, ry = bpfactor, bpfactor + end + + if band(transform,7) > 3 then + -- mirror + rx, tx = -rx, -tx + end + local t = band(transform + rotation,3) + if t == 0 then + -- nothing + elseif t == 1 then + -- rotation over 90 degrees (counterclockwise) + rx, sx, sy, ry, tx, ty = 0, rx, -ry, 0, -ty, tx + elseif t == 2 then + -- rotation over 180 degrees (counterclockwise) + rx, ry, tx, ty = -rx, -ry, -tx, -ty + elseif t == 3 then + -- rotation over 270 degrees (counterclockwise) + rx, sx, sy, ry, tx, ty = 0, -rx, ry, 0, ty, -tx + end + + rx = rx * width + sx = sx * total + sy = sy * width + ry = ry * total + tx = pos_h - tx * width + ty = pos_v - ty * total + + local t = transform + rotation + + if band(transform,7) > 3 then + t = t + 1 + end + + t = band(t,3) + + if t == 0 then + -- no transform + elseif t == 1 then + -- rotation over 90 degrees (counterclockwise) + tx = tx + width + elseif t == 2 then + -- rotation over 180 degrees (counterclockwise) + tx = tx + width + ty = ty + total + elseif t == 3 then + -- rotation over 270 degrees (counterclockwise) + ty = ty + total + end + + -- a flaw in original, can go: + -- + -- if img_page_group_val == 0 then + -- img_page_group_val = group_ref + -- end + + usedximages[index] = objnum -- hm + + pdf_goto_pagemode() + + calc_pdfpos(tx,ty) + + tx = cmtx * bpfactor + ty = cmty * bpfactor + + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) + b = b + 1 ; buffer[b] = f_im(index) + b = b + 1 ; buffer[b] = s_e + end + + flushimage = function(index,width,height,depth,pos_h,pos_v) + + -- used in vf characters + + local total = height + depth + local kind, + xorigin, yorigin, + xsize, ysize, + rotation, + objnum, + groupref = pdfincludeimage(index) + + local rx = width / xsize + local sx = 0 + local sy = 0 + local ry = total / ysize + local tx = pos_h + -- to be sorted out + -- local ty = pos_v - depth + local ty = pos_v -- we assume that depth is dealt with in the caller (for now) + + usedximages[index] = objnum + + pdf_goto_pagemode() + + calc_pdfpos(tx,ty) + + tx = cmtx * bpfactor + ty = cmty * bpfactor + + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) + b = b + 1 ; buffer[b] = f_im(index) + b = b + 1 ; buffer[b] = s_e + end + + -- For the moment we need this hack because the engine checks the 'image' + -- command in virtual fonts (so we use lua instead). + -- + -- These will be replaced by a new more advanced one ... some day ... or + -- never because the next are like the other engines and compensate for + -- small sizes which is needed for inaccurate viewers. + + flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) + + if subtype == emptyrule_code then + return + elseif subtype == boxrule_code then + return flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) + elseif subtype == imagerule_code then + return flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) + end + if subtype == userrule_code or subtype >= overrule_code and subtype <= radicalrule_code then + pdf_goto_pagemode() + b = b + 1 ; buffer[b] = s_b + pdf_set_pos_temp(pos_h,pos_v) + rule_callback(current,size_h,size_v,pos_r) -- so we pass direction + b = b + 1 ; buffer[b] = s_e + return + end + + pdf_goto_pagemode() + + -- local saved_b = b + + b = b + 1 ; buffer[b] = s_b + + local dim_h = size_h * bpfactor + local dim_v = size_v * bpfactor + local rule + + if dim_v <= one_bp then + pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) + rule = f_v(dim_v,dim_h) + elseif dim_h <= one_bp then + pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) + rule = f_h(dim_h,dim_v) + else + pdf_set_pos_temp(pos_h,pos_v) + if subtype == outlinerule_code then + local linewidth = getdata(current) + if linewidth > 0 then + rule = f_w(linewidth * bpfactor,dim_h,dim_v) + else + rule = f_o(dim_h,dim_v) + end + else + rule = f_f(dim_h,dim_v) + end + end + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + + -- buffer[saved_b] = concat(buffer," ",saved_b,b) + -- b = saved_b + + end + + flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v) + pdf_goto_pagemode() + + b = b + 1 ; buffer[b] = s_b + + local dim_h = size_h * bpfactor + local dim_v = size_v * bpfactor + local rule + + if dim_v <= one_bp then + pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) + rule = f_v(dim_v,dim_h) + elseif dim_h <= one_bp then + pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) + rule = f_h(dim_h,dim_v) + else + pdf_set_pos_temp(pos_h,pos_v) + rule = f_f(dim_h,dim_v) + end + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + end + + flushspecialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline) + pdf_goto_pagemode() + + b = b + 1 ; buffer[b] = s_b + + local width = bpfactor * width + local height = bpfactor * height + local depth = bpfactor * depth + local total = height + depth + local line = bpfactor * line + local half = line / 2 + local rule + + if outline then + rule = f_x(line,half,-depth+half,width-line,total-line) + else + rule = f_b(line,-depth,width,total) + end + pdf_set_pos_temp(pos_h,pos_v) + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + end + +end + +--- basics + +local wrapup, registerpage do + + local pages = { } + local maxkids = 10 + local nofpages = 0 + local pagetag = "unset" + + registerpage = function(object) + nofpages = nofpages + 1 + local objnum = pdfpagereference(nofpages) + pages[nofpages] = { + page = nofpages, -- original number, only for diagnostics + objnum = objnum, + object = object, + tag = pagetag, + } + end + + function lpdf.setpagetag(tag) + pagetag = tag or "unset" + end + + function lpdf.getnofpages() + return nofpages + end + + function lpdf.getpagetags() + local list = { } + for i=1,nofpages do + list[i] = pages[i].tag + end + return list + end + + function lpdf.setpageorder(mapping) + -- mapping can be a hash so: + local list = table.sortedkeys(mapping) + local n = #list + if n == nofpages then + local done = { } + local hash = { } + for i=1,n do + local order = mapping[list[i]] + if hash[order] then + report("invalid page order, duplicate entry %i",order) + return + elseif order < 1 or order > nofpages then + report("invalid page order, no page %i",order) + return + else + done[i] = pages[order] + hash[order] = true + end + end + pages = done + else + report("invalid page order, %i entries expected",nofpages) + end + end + + -- We can have this, but then via codeinjections etc. Later. + + -- function structures.pages.swapthem() + -- local n = lpdf.getnofpages() + -- local t = { } + -- for i=1,n do + -- t[i] = i + -- end + -- for i=2,math.odd(n) and n or (n-1),2 do + -- t[i] = i+1 + -- t[i+1] = i + -- end + -- lpdf.setpageorder(t) + -- end + + wrapup = function(driver) + + -- hook (to reshuffle pages) + local pagetree = { } + local parent = nil + local minimum = 0 + local maximum = 0 + local current = 0 + if #pages > 1.5 * maxkids then + repeat + local plist, pnode + if current == 0 then + plist, minimum = pages, 1 + elseif current == 1 then + plist, minimum = pagetree, 1 + else + plist, minimum = pagetree, maximum + 1 + end + maximum = #plist + if maximum > minimum then + local kids + for i=minimum,maximum do + local p = plist[i] + if not pnode or #kids == maxkids then + kids = pdfarray() + parent = pdfreserveobject() + pnode = pdfdictionary { + objnum = parent, + Type = pdf_pages, + Kids = kids, + Count = 0, + } + pagetree[#pagetree+1] = pnode + end + kids[#kids+1] = pdfreference(p.objnum) + pnode.Count = pnode.Count + (p.Count or 1) + p.Parent = pdfreference(parent) + end + end + current = current + 1 + until maximum == minimum + -- flush page tree + for i=1,#pagetree do + local entry = pagetree[i] + local objnum = entry.objnum + entry.objnum = nil + pdfflushobject(objnum,entry) + end + else + -- ugly + local kids = pdfarray() + local list = pdfdictionary { + Type = pdf_pages, + Kids = kids, + Count = nofpages, + } + parent = pdfreserveobject() + for i=1,nofpages do + local page = pages[i] + kids[#kids+1] = pdfreference(page.objnum) + page.Parent = pdfreference(parent) + end + pdfflushobject(parent,list) + end + for i=1,nofpages do + local page = pages[i] + local object = page.object + object.Parent = page.Parent + pdfflushobject(page.objnum,object) + end + lpdf.addtocatalog("Pages",pdfreference(parent)) + + end + +end + +pdf_h, pdf_v = 0, 0 + +local function initialize(driver,details) + reset_variables(details) + reset_buffer() +end + +-- This will all move and be merged and become less messy. + +-- todo: more clever resource management: a bit tricky as we can inject +-- stuff in the page stream + +local compact = false + +do + + -- This is more a convenience feature and it might even be not entirely robust. + -- It removes redundant color directives which makes the page stream look a bit + -- nicer (also when figuring out issues). I might add more here but there is + -- some additional overhead involved so runtime can be impacted. + + local P, R, S, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs, lpeg.match + + local p_ds = (R("09") + S(" ."))^1 + ----- p_nl = S("\n\r")^1 + local p_nl = S("\n")^1 + local p_eg = P("Q") + + local p_cl = p_ds * (P("rg") + P("g") + P("k")) * p_ds * (P("RG") + P("G") + P("K")) + ----- p_cl = (p_ds * (P("rg") + P("g") + P("k") + P("RG") + P("G") + P("K")))^1 + local p_tr = P("/Tr") * p_ds * P("gs") + + local p_no_cl = (p_cl * p_nl) / "" + local p_no_tr = (p_tr * p_nl) / "" + local p_no_nl = 1 - p_nl + + local p_do_cl = p_cl * p_nl + local p_do_tr = p_tr * p_nl + + local p_do_eg = p_eg * p_nl + + local pattern = Cs( ( + (p_no_cl + p_no_tr)^0 * p_do_eg -- transparencies and colors before Q + + p_no_tr * p_no_cl * p_do_tr * p_do_cl -- transparencies and colors before others + + p_no_cl * p_do_cl -- successive colors + + p_no_tr * p_do_tr -- successive transparencies + + p_no_nl^1 + + 1 + )^1 ) + + local oldsize = 0 + local newsize = 0 + + directives.register("pdf.compact", function(v) + compact = v and function(s) + oldsize = oldsize + #s + s = lpegmatch(pattern,s) or s + newsize = newsize + #s + return s + end + end) + + statistics.register("pdf pagestream",function() + if oldsize ~= newsize then + return string.format("old size: %i, new size %i",oldsize,newsize) + end + end) + + +end + +local flushdeferred -- defined later + +local level = 0 + +local finalize do + + local f_font = formatters["F%d"] + + local f_form = formatters["Fm%d"] + local f_group = formatters["Gp%d"] + local f_image = formatters["Im%d"] + + finalize = function(driver,details) + + level = level + 1 + + pdf_goto_pagemode() -- for now + + local objnum = details.objnum + local specification = details.specification + + local content = concat(buffer,"\n",1,b) + + if compact then + content = compact(content) + end + + local fonts = nil + local xforms = nil + + if next(usedfonts) then + fonts = pdfdictionary { } + for k, v in next, usedfonts do + fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing + end + end + + -- messy: use real indexes for both ... so we need to change some in the + -- full luatex part + + if next(usedxforms) or next(usedximages) or next(usedxgroups) then + xforms = pdfdictionary { } + for k in sortedhash(usedxforms) do + -- xforms[f_form(k)] = pdfreference(k) + xforms[f_form(getxformname(k))] = pdfreference(k) + end + for k, v in sortedhash(usedximages) do + xforms[f_image(k)] = pdfreference(v) + end + for k, v in sortedhash(usedxgroups) do + xforms[f_group(k)] = pdfreference(v) + end + end + + reset_buffer() + + -- finish_pdfpage_callback(shippingmode == "page") + + if shippingmode == "page" then + + local pageproperties = lpdf.getpageproperties() + + local pageresources = pageproperties.pageresources + local pageattributes = pageproperties.pageattributes + local pagesattributes = pageproperties.pagesattributes + + pageresources.Font = fonts + pageresources.XObject = xforms + pageresources.ProcSet = lpdf.procset() + + local xorigin, yorigin, relocated = backends.codeinjections.getpageorigin() -- for now here + + local bbox = pdfarray { + (boundingbox[1] + xorigin) * bpfactor, + (boundingbox[2] + yorigin) * bpfactor, + (boundingbox[3] + xorigin) * bpfactor, + (boundingbox[4] + yorigin) * bpfactor, + } + + if relocated then + content = formatters["1 0 0 1 %.6N %.6N cm\n%s"](bbox[1],bbox[2],content) + end + + local contentsobj = pdfflushstreamobject(content,false,false) + + pageattributes.Type = pdf_page + pageattributes.Contents = pdfreference(contentsobj) + pageattributes.Resources = pageresources + -- pageattributes.Resources = pdfreference(pdfflushobject(pageresources)) + -- pageattributes.MediaBox = bbox + pageattributes.MediaBox = pdfsharedobject(bbox) + pageattributes.Parent = nil -- precalculate + pageattributes.Group = nil -- todo + + -- resources can be indirect + + registerpage(pageattributes) + + lpdf.finalizepage(true) + + local TrimBox = pageattributes.TrimBox + local CropBox = pageattributes.CropBox + local BleedBox = pageattributes.BleedBox + + if relocated then + if TrimBox then TrimBox = box end + if CropBox then CropBox = box end + if BleedBox then BleedBox = box end + end + + -- Indirect objects don't work in all viewers. + + if TrimBox then pageattributes.TrimBox = pdfsharedobject(TrimBox ) end + if CropBox then pageattributes.CropBox = pdfsharedobject(CropBox ) end + if BleedBox then pageattributes.BleedBox = pdfsharedobject(BleedBox) end + + else + + local xformtype = specification.type or 0 + local margin = specification.margin or 0 + local attributes = specification.attributes or "" + local resources = specification.resources or "" + + local wrapper = nil + + if xformtype == 0 then + wrapper = pdfdictionary { + Type = pdf_xobject, + Subtype = pdf_form, + FormType = 1, + BBox = nil, + Matrix = nil, + Resources = nil, + } + else + wrapper = pdfdictionary { + BBox = nil, + Matrix = nil, + Resources = nil, + } + end + if xformtype == 0 or xformtype == 1 or xformtype == 3 then + wrapper.BBox = pdfarray { + -margin * bpfactor, + -margin * bpfactor, + (boundingbox[3] + margin) * bpfactor, + (boundingbox[4] + margin) * bpfactor, + } + end + if xformtype == 0 or xformtype == 2 or xformtype == 3 then + -- can be shared too + wrapper.Matrix = pdfarray { 1, 0, 0, 1, 0, 0 } + end + + -- todo: additional = resources + + local boxresources = lpdf.collectedresources { serialize = false } + boxresources.Font = fonts + boxresources.XObject = xforms + + -- todo: maybe share them + -- wrapper.Resources = pdfreference(pdfflushobject(boxresources)) + + if resources ~= "" then + boxresources = boxresources + resources + end + if attributes ~= "" then + wrapper = wrapper + attributes + end + + wrapper.Resources = next(boxresources) and boxresources or nil + wrapper.ProcSet = lpdf.procset() + + -- pdfflushstreamobject(content,wrapper,false,objectnumber) + pdfflushstreamobject(content,wrapper,false,specification.objnum) + + end + + for objnum in sortedhash(usedxforms) do + local f = flushedxforms[objnum] + if f[1] == false then + f[1] = true + local objnum = f[2] -- specification.objnum + local specification = boxresources[objnum] + local list = specification.list + localconverter(list,"xform",f[2],specification) + end + end + + pdf_h, pdf_v = 0, 0 + + if level == 1 then + flushdeferred() + end + level = level - 1 + + end + +end + +updaters.register("backend.update.pdf",function() + job.positions.registerhandlers { + getpos = drivers.getpos, + getrpos = drivers.getrpos, + gethpos = drivers.gethpos, + getvpos = drivers.getvpos, + } +end) + +updaters.register("backend.update",function() + local saveboxresource = tex.boxresources.save + -- + -- also in lpdf-res .. brrr .. needs fixing + -- + backends.codeinjections.registerboxresource = function(n,offset) + local r = saveboxresource(n,nil,nil,false,0,offset or 0) + return r + end +end) + +-- now comes the pdf file handling + +local objects = { } +local streams = { } -- maybe just parallel to objects (no holes) +local nofobjects = 0 +local offset = 0 +local f = false +local flush = false +local threshold = 40 -- also #("/Filter /FlateDecode") (compression threshold) +local objectstream = true +local compress = true +local cache = false +local info = "" +local catalog = "" +local lastdeferred = false +local majorversion = 1 +local minorversion = 7 +local trailerid = true + +directives.register("backend.pdf.threshold",function(v) + if v then + threshold = tonumber(v) or 40 + else + threshold = -1000 + end +end) + +local f_object = formatters["%i 0 obj\010%s\010endobj\010"] +local f_stream_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010%s\010endstream\010endobj\010"] + +----- f_object_b = formatters["%i 0 obj\010"] +local f_stream_b_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010"] +local f_stream_b_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010"] +local f_stream_b_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010"] +local f_stream_b_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010"] +local f_stream_b_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010"] + +----- s_object_e = "\010endobj\010" +local s_stream_e = "\010endstream\010endobj\010" + +do + + local function setinfo() end -- we get it + local function setcatalog() end -- we get it + + local function settrailerid(v) + trailerid = v or false + end + + local function setmajorversion(v) majorversion = tonumber(v) or majorversion end + local function setminorversion(v) minorversion = tonumber(v) or minorversion end + + local function getmajorversion(v) return majorversion end + local function getminorversion(v) return minorversion end + + local function setcompresslevel (v) compress = v and v ~= 0 and true or false end + local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end + + local function getcompresslevel (v) return compress and 3 or 0 end + local function getobjcompresslevel(v) return objectstream and 1 or 0 end + + local function setpageresources () end -- needs to be sorted out + local function setpageattributes () end + local function setpagesattributes() end + + updaters.register("backend.update.pdf",function() + pdf.setinfo = setinfo + pdf.setcatalog = setcatalog + pdf.settrailerid = settrailerid + pdf.setmajorversion = setmajorversion + pdf.setminorversion = setminorversion + pdf.getmajorversion = getmajorversion + pdf.getminorversion = getminorversion + pdf.setcompresslevel = setcompresslevel + pdf.setobjcompresslevel = setobjcompresslevel + pdf.getcompresslevel = getcompresslevel + pdf.getobjcompresslevel = getobjcompresslevel + pdf.setpageresources = setpageresources + pdf.setpageattributes = setpageattributes + pdf.setpagesattributes = setpagesattributes + end) + +end + +local addtocache, flushcache, cache do + + local data, d = { }, 0 + local list, l = { }, 0 + local coffset = 0 + local indices = { } + + local maxsize = 32 * 1024 -- uncompressed + local maxcount = 0xFF + + addtocache = function(n,str) + local size = #str + if size == 0 then + -- todo: message + return + end + if coffset + size > maxsize or d == maxcount then + flushcache() + end + if d == 0 then + nofobjects = nofobjects + 1 + objects[nofobjects] = false + streams[nofobjects] = indices + cache = nofobjects + end + objects[n] = - cache + indices[n] = d + d = d + 1 + -- can have a comment n 0 obj as in luatex + data[d] = str + l = l + 1 ; list[l] = n + l = l + 1 ; list[l] = coffset + coffset = coffset + size + 1 + end + + local p_ObjStm = pdfconstant("ObjStm") + + flushcache = function() -- references cannot be stored + if l > 0 then + list = concat(list," ") + data[0] = list + data = concat(data,"\010",0,d) + local strobj = pdfdictionary { + Type = p_ObjStm, + N = d, + First = #list + 1, + } + objects[cache] = offset + local b = nil + local e = s_stream_e + if compress then + local comp = zlibcompress(data,3) + if comp and #comp < #data then + data = comp + b = f_stream_b_d_c(cache,strobj(),#data) + else + b = f_stream_b_d_u(cache,strobj(),#data) + end + else + b = f_stream_b_d_u(cache,strobj(),#data) + end + flush(f,b) + flush(f,data) + flush(f,e) + offset = offset + #b + #data + #e + data, d = { }, 0 + list, l = { }, 0 + coffset = 0 + indices = { } + end + end + +end + +local function pdfreserveobj() + nofobjects = nofobjects + 1 + objects[nofobjects] = false + return nofobjects +end + +local pages = table.setmetatableindex(function(t,k) + local v = pdfreserveobj() + t[k] = v + return v +end) + +local function getpageref(n) + return pages[n] +end + +local function refobj() + -- not needed, as we have auto-delay +end + +local function flushnormalobj(data,n) + if not n then + nofobjects = nofobjects + 1 + n = nofobjects + end + data = f_object(n,data) + if level == 0 then + objects[n] = offset + offset = offset + #data + flush(f,data) + else + if not lastdeferred then + lastdeferred = n + elseif n < lastdeferred then + lastdeferred = n + end + objects[n] = data + end + return n +end + +local function flushstreamobj(data,n,dict,comp,nolength) + if not data then + report("no data for %S",dict) + return + end + if not n then + nofobjects = nofobjects + 1 + n = nofobjects + end + local size = #data + if level == 0 then + local b = nil + local e = s_stream_e + if nolength then + b = f_stream_b_d_r(n,dict) + elseif comp ~= false and compress and size > threshold then + local compdata = zlibcompress(data,3) + if compdata then + local compsize = #compdata + if compsize > size - threshold then + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + else + data = compdata + b = dict and f_stream_b_d_c(n,dict,compsize) or f_stream_b_n_c(n,compsize) + end + else + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + end + else + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + end + flush(f,b) + flush(f,data) + flush(f,e) + objects[n] = offset + offset = offset + #b + #data + #e + else + if nolength then + data = f_stream_d_r(n,dict,data) + elseif comp ~= false and compress and size > threshold then + local compdata = zlibcompress(data,3) + if compdata then + local compsize = #compdata + if compsize > size - threshold then + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + else + data = dict and f_stream_d_c(n,dict,compsize,compdata) or f_stream_n_c(n,compsize,compdata) + end + else + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + end + else + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + end + if not lastdeferred then + lastdeferred = n + elseif n < lastdeferred then + lastdeferred = n + end + objects[n] = data + end + return n +end + +flushdeferred = function() -- was forward defined + if lastdeferred then + for n=lastdeferred,nofobjects do + local o = objects[n] + if type(o) == "string" then + objects[n] = offset + offset = offset + #o + flush(f,o) + end + end + lastdeferred = false + end +end + +-- n = pdf.obj([n,] objtext) +-- n = pdf.obj([n,] "file", filename) +-- n = pdf.obj([n,] "stream", streamtext [, attrtext]) +-- n = pdf.obj([n,] "streamfile", filename [, attrtext]) +-- +-- n = pdf.obj { +-- type = , -- raw|stream +-- immediate = , +-- objnum = , +-- attr = , +-- compresslevel = , +-- objcompression = , +-- file = , +-- string = , +-- nolength = , +-- } + +local function obj(a,b,c,d) + local kind --, immediate + local objnum, data, attr, filename + local compresslevel, objcompression, nolength + local argtype = type(a) + if argtype == "table" then + kind = a.type -- raw | stream + -- immediate = a.immediate + objnum = a.objnum + attr = a.attr + compresslevel = a.compresslevel + objcompression = a.objcompression + filename = a.file + data = a.string or a.stream or "" + nolength = a.nolength + if kind == "stream" then + if filename then + data = loaddata(filename) or "" + end + elseif kind == "raw"then + if filename then + data = loaddata(filename) or "" + end + elseif kind == "file"then + kind = "raw" + data = filename and loaddata(filename) or "" + elseif kind == "streamfile" then + kind = "stream" + data = filename and loaddata(filename) or "" + end + else + if argtype == "number" then + objnum = a + a, b, c = b, c, d + else + nofobjects = nofobjects + 1 + objnum = nofobjects + end + if b then + if a == "stream" then + kind = "stream" + data = b + elseif a == "file" then + -- kind = "raw" + data = loaddata(b) + elseif a == "streamfile" then + kind = "stream" + data = loaddata(b) + else + data = "" -- invalid object + end + attr = c + else + -- kind = "raw" + data = a + end + end + if not objnum then + nofobjects = nofobjects + 1 + objnum = nofobjects + end + -- todo: immediate + if kind == "stream" then + flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) + elseif objectstream and objcompression ~= false then + addtocache(objnum,data) + else + flushnormalobj(data,objnum) + end + return objnum +end + +updaters.register("backend.update.pdf",function() + pdf.reserveobj = pdfreserveobj + pdf.getpageref = getpageref + pdf.refobj = refobj + pdf.flushstreamobj = flushstreamobj + pdf.flushnormalobj = flushnormalobj + pdf.obj = obj + pdf.immediateobj = obj +end) + +-- In lua 5.4 the methods are now moved one metalevel deeper so we need to get them +-- from mt.__index instead. (I did get that at first.) It makes for a slightly (imo) +-- nicer interface but no real gain in speed as we don't flush that often. + +local openfile, closefile do + + -- I used to do but then figured out that when I open and save a file in a mode + -- that removes trailing spaces, the xref becomes invalid. The problem was then that a + -- reconstruction of the file by a viewer gives weird effects probably because percent symbols + -- gets interpreted then. Thanks to Ross Moore for noticing this side effect! + + local f_used = formatters["%010i 00000 n\013\010"] + local f_link = formatters["%010i 00000 f\013\010"] + local f_first = formatters["%010i 65535 f\013\010"] + + local f_pdf = formatters["%%PDF-%i.%i\010"] + local f_xref = formatters["xref\0100 %i\010"] + local f_trailer_id = formatters["trailer\010<< %s /ID [ <%s> <%s> ] >>\010startxref\010%i\010%%%%EOF"] + local f_trailer_no = formatters["trailer\010<< %s >>\010startxref\010%i\010%%%%EOF"] + local f_startxref = formatters["startxref\010%i\010%%%%EOF"] + + local inmemory = false + local close = false + local update = false + + -- local removefile = os.remove + + openfile = function(filename) + if inmemory then + local n = 0 + f = { } + flush = function(f,s) + n = n + 1 f[n] = s + -- offset = offset + #s + end + close = function(f) + f = concat(f) + io.savedata(filename,f) + f = false + end + update = function(f,s) + f[1] = s + end + -- local n = 0 + -- f = { + -- write = function(self,s) + -- n = n + 1 f[n] = s + -- end, + -- close = function(self) + -- f = concat(f) + -- io.savedata(filename,f) + -- f = false + -- end, + -- } + else + f = io.open(filename,"wb") + if not f then + -- message + os.exit() + end + -- f:setvbuf("full",64*1024) + local m = getmetatable(f) + flush = m.write or m.__index.write + close = m.close or m.__index.close + update = function(f,s) + f:seek("set",0) + f:write(s) + end + end + local v = f_pdf(majorversion,minorversion) + -- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128) + local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128) + flush(f,v) + flush(f,b) + offset = offset + #v + #b + end + + closefile = function(abort) + if abort then + close(f) + if not environment.arguments.nodummy then + f = io.open(abort,"wb") + if f then + local name = resolvers.findfile("context-lmtx-error.pdf") + if name then + local data = io.loaddata(name) + if data then + f:write(data) + f:close() + return + end + end + f:close() + end + end + os.remove(abort) + else + local xrefoffset = offset + local lastfree = 0 + local noffree = 0 + local catalog = lpdf.getcatalog() + local info = lpdf.getinfo() + if trailerid == true then + trailerid = md5HEX(osuuid()) + elseif trailerid and #trailerid > 32 then + trailerid = md5HEX(trailerid) + else + trailerid = false + end + if objectstream then + flushdeferred() + flushcache() + -- + xrefoffset = offset + -- + nofobjects = nofobjects + 1 + objects[nofobjects] = offset -- + 1 + -- + -- combine these three in one doesn't really give less code so + -- we go for the efficient ones + -- + local nofbytes = 4 + local c1, c2, c3, c4 + if offset <= 0xFFFF then + nofbytes = 2 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,8,8) + c2 = extract(o,0,8) + if strm then + objects[i] = char(2,c1,c2,streams[o][i]) + else + objects[i] = char(1,c1,c2,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,8,8) + local f2 = extract(lastfree,0,8) + objects[i] = char(0,f1,f2,0) + lastfree = i + end + end + end + elseif offset <= 0xFFFFFF then + nofbytes = 3 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,16,8) + c2 = extract(o, 8,8) + c3 = extract(o, 0,8) + if strm then + objects[i] = char(2,c1,c2,c3,streams[o][i]) + else + objects[i] = char(1,c1,c2,c3,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,16,8) + local f2 = extract(lastfree, 8,8) + local f3 = extract(lastfree, 0,8) + objects[i] = char(0,f1,f2,f3,0) + lastfree = i + end + end + end + else + nofbytes = 4 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,24,8) + c2 = extract(o,16,8) + c3 = extract(o, 8,8) + c4 = extract(o, 0,8) + if strm then + objects[i] = char(2,c1,c2,c3,c4,streams[o][i]) + else + objects[i] = char(1,c1,c2,c3,c4,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,24,8) + local f2 = extract(lastfree,16,8) + local f3 = extract(lastfree, 8,8) + local f4 = extract(lastfree, 0,8) + objects[i] = char(0,f1,f2,f3,f4,0) + lastfree = i + end + end + end + end + objects[0] = rep("\0",1+nofbytes+1) + local data = concat(objects,"",0,nofobjects) + local xref = pdfdictionary { + Type = pdfconstant("XRef"), + Size = nofobjects + 1, + W = pdfarray { 1, nofbytes, 1 }, + Root = catalog, + Info = info, + ID = trailerid and pdfarray { pdfliteral(trailerid,true), pdfliteral(trailerid,true) } or nil, + } + if compress then + local comp = zlibcompress(data,3) + if comp then + data = comp + flush(f,f_stream_b_d_c(nofobjects,xref(),#data)) + else + flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) + end + else + flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) + end + flush(f,data) + flush(f,s_stream_e) + flush(f,f_startxref(xrefoffset)) + else + flushdeferred() + xrefoffset = offset + flush(f,f_xref(nofobjects+1)) + local trailer = pdfdictionary { + Size = nofobjects+1, + Root = catalog, + Info = info, + } + for i=1,nofobjects do + local o = objects[i] + if o then + objects[i] = f_used(o) + end + end + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + objects[i] = f_link(lastfree) + lastfree = i + end + end + objects[0] = f_first(lastfree) + flush(f,concat(objects,"",0,nofobjects)) + trailer.Size = nofobjects + 1 + if trailerid then + flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset)) + else + flush(f,f_trailer_no(trailer(),xrefoffset)) + end + end + update(f,f_pdf(majorversion,minorversion)) + close(f) + end + io.flush() + closefile = function() end + end + +end + +-- For the moment we overload it here, although back-fil.lua eventually will +-- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so. + +updaters.register("backend.update.pdf",function() + + -- We overload img but at some point it will even go away, so we just + -- reimplement what we need in context. This will change completely i.e. + -- we will drop the low level interface! + + local codeinjections = backends.pdf.codeinjections + + local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream + local img_none = imagetypes.none + + local rulecodes = nodes.rulecodes + + local setprop = nodes.nuts.setprop + + local report_images = logs.reporter("backend","images") + + local lastindex = 0 + local indices = { } + + local bpfactor = number.dimenfactors.bp + local imagerule_code = rulecodes.image + + function codeinjections.newimage(specification) + return specification + end + + function codeinjections.copyimage(original) + return setmetatableindex(original) + end + + function codeinjections.scanimgage(specification) + return specification + end + + local function embedimage(specification) + if specification then + lastindex = lastindex + 1 + index = lastindex + specification.index = index + local xobject = pdfdictionary { } + if not specification.notype then + xobject.Type = pdf_xobject + xobject.Subtype = pdf_form + xobject.FormType = 1 + end + local bbox = specification.bbox + if bbox and not specification.nobbox then + xobject.BBox = pdfarray { + bbox[1] * bpfactor, + bbox[2] * bpfactor, + bbox[3] * bpfactor, + bbox[4] * bpfactor, + } + end + xobject = xobject + specification.attr + if bbox and not specification.width then + specification.width = bbox[3] + end + if bbox and not specification.height then + specification.height = bbox[4] + end + local dict = xobject() + -- + nofobjects = nofobjects + 1 + local objnum = nofobjects + local nolength = specification.nolength + local stream = specification.stream or specification.string + -- + -- We cannot set type in native img so we need this hack or + -- otherwise we need to patch too much. Better that i write + -- a wrapper then. Anyway, it has to be done better: a key that + -- tells either or not to scale by xsize/ysize when flushing. + -- + if not specification.type then + local kind = specification.kind + if kind then + -- take that one + elseif attr and find(attr,"BBox") then + kind = img_stream + else + -- hack: a bitmap + kind = img_none + end + specification.type = kind + specification.kind = kind + end + local compress = compresslevel and compresslevel > 0 or nil + flushstreamobj(stream,objnum,dict,compress,nolength) + specification.objnum = objnum + specification.rotation = specification.rotation or 0 + specification.orientation = specification.orientation or 0 + specification.transform = specification.transform or 0 + specification.stream = nil + specification.attr = nil + specification.type = specification.kind or specification.type or img_none + indices[index] = specification -- better create a real specification + return specification + end + end + + codeinjections.embedimage = embedimage + + function codeinjections.wrapimage(specification) + -- + local index = specification.index + if not index then + embedimage(specification) + end + -- + local width = specification.width or 0 + local height = specification.height or 0 + local depth = specification.depth or 0 + -- newimagerule + local n = nodes.pool.rule(width,height,depth) + n.subtype = imagerule_code + setprop(tonut(n),"index",specification.index) + return n + end + + function pdf.includeimage(index) + local specification = indices[index] + if specification then + local bbox = specification.bbox + local xorigin = bbox[1] + local yorigin = bbox[2] + local xsize = bbox[3] - xorigin -- we need the original ones, not the 'rotated' ones + local ysize = bbox[4] - yorigin -- we need the original ones, not the 'rotated' ones + local transform = specification.transform or 0 + local objnum = specification.objnum or pdfreserveobj() + local groupref = nil + local kind = specification.kind or specification.type or img_none -- determines scaling type + return + kind, + xorigin, yorigin, + xsize, ysize, + transform, + objnum, + groupref + end + end + +end) + +updaters.register("backend.update.lpdf",function() + + -- todo: an md5 or sha2 hash can save space + -- todo: make a type 3 font instead + -- todo: move to lpdf namespace + + local pdfimage = lpdf.epdf.image + local newpdf = pdfimage.new + local openpdf = pdfimage.open + local closepdf = pdfimage.close + local copypage = pdfimage.copy + + local embedimage = images.embed + + local nofstreams = 0 + local topdf = { } + local toidx = { } + + local function storedata_s(pdf) + local idx = toidx[pdf] + if not idx then + nofstreams = nofstreams + 1 + idx = nofstreams + toidx[pdf] = nofstreams + topdf[idx] = pdf + end + return idx + end + + local function vfimage_s(id,wd,ht,dp,pos_h,pos_v) + local index = topdf[id] + if type(index) == "string" then + local pdfdoc = newpdf(index,#index) + local image = copypage(pdfdoc) + local bbox = image.bbox + image.width = bbox[3] - bbox[1] + image.height = bbox[4] - bbox[2] + embedimage(image) + index = image.index + topdf[id] = index + end + -- pdf.print or pdf.literal + flushimage(index,wd,ht,dp,pos_h,pos_v) + end + + local function storedata_n(name,page) + local idx = toidx[pdf] + if not idx then + nofstreams = nofstreams + 1 + idx = nofstreams + toidx[pdf] = nofstreams + topdf[idx] = pdf + end + return idx + end + + -- We need to have a way to close such a pdf ... esp for fonts. + + local pdfdocs = { } + + local function vfimage_n(name,page,wd,ht,dp,pos_h,pos_v) + local d = pdfdocs[name] + if not d then + d = { doc = openpdf(name), pages = { } } + pdfdocs[name] = d + end + local index = d.pages[page] + if not index then + local image = copypage(d.doc,page) + local bbox = image.bbox + image.width = bbox[3] - bbox[1] + image.height = bbox[4] - bbox[2] + embedimage(image) + index = image.index + d.pages[page] = index + end + flushimage(index,wd,ht,dp,pos_h,pos_v) + end + + local function pdfvfimage(wd,ht,dp,data,name) + if type(data) == "number" then + return { "lua", function(font,char,pos_h,pos_v) + vfimage_n(name,data,wd,ht,dp,pos_h,pos_v) + end } + else + return { "lua", function(font,char,pos_h,pos_v) + local id = storedata_s(data) + vfimage_s(id,wd,ht,dp,pos_h,pos_v) + end } + end + end + + lpdf.vfimage = pdfvfimage + +end) + +-- The driver. + +do + + -- local addsuffix = file.addsuffix + local texgetbox = tex.getbox + + local pdfname = nil + local converter = nil + local useddriver = nil -- a bit of a hack + + local function outputfilename(driver) + return pdfname + end + + -- todo: prevent twice + + local function prepare(driver) + if not environment.initex then + -- install new functions in pdf namespace + updaters.apply("backend.update.pdf") + -- install new functions in lpdf namespace + updaters.apply("backend.update.lpdf") + -- adapt existing shortcuts to lpdf namespace + updaters.apply("backend.update.tex") + -- adapt existing shortcuts to tex namespace + updaters.apply("backend.update") + -- + -- if rawget(pdf,"setforcefile") then + -- pdf.setforcefile(false) -- default anyway + -- end + -- + -- pdfname = file.addsuffix(tex.jobname,"pdf") + pdfname = tex.jobname .. ".pdf" + openfile(pdfname) + -- + luatex.registerstopactions(1,function() + if pdfname then + lpdf.finalizedocument() + closefile() + end + end) + -- + luatex.registerpageactions(1,function() + if pdfname then + lpdf.finalizepage(true) + end + end) + -- -- + lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up") + -- + end + -- + environment.lmtxmode = CONTEXTLMTXMODE + -- + converter = drivers.converters.lmtx + useddriver = driver + end + + local function wrapup(driver) + if pdfname then + closefile() + pdfname = nil + end + end + + local function cleanup(driver) + if pdfname then + closefile(pdfname) + pdfname = nil + end + end + + local function convert(driver,boxnumber) + converter(driver,texgetbox(boxnumber),"page") + end + + localconverter = function(...) + converter(useddriver,...) + end + + drivers.install { + name = "pdf", + flushers = { + character = flushcharacter, + fontchar = flushfontchar, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + pushorientation = pushorientation, + poporientation = poporientation, + -- + literal = flushliteral, + setmatrix = flushsetmatrix, + save = flushsave, + restore = flushrestore, + image = flushimage, + group = flushgroup, + -- + updatefontstate = updatefontstate, + }, + actions = { + prepare = prepare, + wrapup = wrapup, + cleanup = cleanup, + -- + initialize = initialize, + convert = convert, + finalize = finalize, + -- + outputfilename = outputfilename, + }, + } + +end diff --git a/tex/context/base/mkxl/lpdf-vfc.lmt b/tex/context/base/mkxl/lpdf-vfc.lmt new file mode 100644 index 000000000..65b863203 --- /dev/null +++ b/tex/context/base/mkxl/lpdf-vfc.lmt @@ -0,0 +1,40 @@ +if not modules then modules = { } end modules ['lpdf-vfc'] = { + 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 setmetatableindex = table.setmetatableindex + +local defaultline = 16384 +local vfspecials = backends.pdf.tables.vfspecials + +vfspecials.backgrounds = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, true, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) + +vfspecials.outlines = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, false, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) diff --git a/tex/context/base/mkxl/luat-bas.mkxl b/tex/context/base/mkxl/luat-bas.mkxl new file mode 100644 index 000000000..0add4ce69 --- /dev/null +++ b/tex/context/base/mkxl/luat-bas.mkxl @@ -0,0 +1,52 @@ +%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-bit32} {} % before sandbox +\registerctxluafile{l-lua} {} % before sandbox +\registerctxluafile{l-macro} {} +\registerctxluafile{l-sandbox} {} +\registerctxluafile{l-package} {} +\registerctxluafile{l-lpeg} {} +\registerctxluafile{l-function}{} +\registerctxluafile{l-string} {} +\registerctxluafile{l-table} {} +\registerctxluafile{l-boolean} {} +\registerctxluafile{l-number} {} +\registerctxluafile{l-math} {} +%registerctxluafile{l-aux} {} +\registerctxluafile{l-io} {} +\registerctxluafile{l-os} {} +\registerctxluafile{l-file} {} +\registerctxluafile{l-gzip} {} +\registerctxluafile{l-md5} {} +\registerctxluafile{l-sha} {} +\registerctxluafile{l-dir} {} +\registerctxluafile{l-unicode} {optimize} +%registerctxluafile{l-utils} {} +\registerctxluafile{l-url} {} +\registerctxluafile{l-set} {} + +\registerctxluafile{l-macro-imp-optimize}{} + +% \registerctxluafile{socket}{} +% \registerctxluafile{ltn12} {} +% \registerctxluafile{mime} {} +% \registerctxluafile{http} {} +% \registerctxluafile{url} {} +% \registerctxluafile{tp} {} +% \registerctxluafile{ftp} {} +% %registerctxluafile{smtp} {} + +\endinput diff --git a/tex/context/base/mkxl/luat-cod.lmt b/tex/context/base/mkxl/luat-cod.lmt new file mode 100644 index 000000000..e4432345e --- /dev/null +++ b/tex/context/base/mkxl/luat-cod.lmt @@ -0,0 +1,304 @@ +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, tonumber = type, loadfile, tonumber +local match, gsub, find, format, gmatch = string.match, string.gsub, string.find, string.format, string.gmatch + +local texconfig, lua = texconfig, lua + +-- maybe pick up from commandline: +-- +-- texconfig.interaction: 0=batchmode 1=nonstopmode 2=scrollmode 3=errornonstopmode 4=normal + +-- some basic housekeeping + +texconfig.kpse_init = false -- not needed in lmtx +texconfig.shell_escape = 't' -- not needed in lmtx + +texconfig.max_in_open = 2000 +texconfig.nest_size = 10000 +texconfig.param_size = 100000 +texconfig.save_size = 500000 +texconfig.stack_size = 100000 +texconfig.buffer_size = 10000000 +texconfig.token_size = 10000000 +texconfig.node_size = 50000000 + +texconfig.max_print_line = 100000 +texconfig.max_strings = 500000 +texconfig.max_pool = 10000000 + +texconfig.hash_extra = 200000 + +texconfig.expand_depth = 10000 +texconfig.function_size = 32768 +texconfig.properties_size = 10000 +texconfig.error_line = 250 +texconfig.half_error_line = 125 + +-- registering bytecode chunks + +local bytedata = lua.bytedata or { } +local bytedone = lua.bytedone or { } + +---.bytecode = bytecode +lua.bytedata = bytedata +lua.bytedone = bytedone + +local setbytecode = lua.setbytecode +----- getbytecode = lua.getbytecode + +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.* and utilities.parsers.* functions yet + +local strip = false if arg then for i=-1,#arg do if arg[i] == "--c:strip" then strip = true break end end end + +function lua.registercode(filename,options) + local barename = gsub(filename,"%.[%a%d]+$","") + local basename = match(barename,"^.+[/\\](.-)$") or barename + if not bytedone[basename] then + local opts = { } + if type(options) == "string" and options ~= "" then + for s in gmatch(options,"([a-z]+)") do + opts[s] = true + end + end + if barename == filename then + filename = filename .. (opts.autosuffix and CONTEXTLMTXMODE > 0 and ".lmt" or ".lua") + end + local code = environment.luafilechunk(filename,false,opts.optimize) + if code then + bytedone[basename] = true + if environment.initex and not opts.initexonly then + local n = lua.lastbytecode + 1 + bytedata[n] = { name = barename, options = opts } + if strip or opts.strip then + setbytecode(n,code,true) + else + setbytecode(n,code) + end + lua.lastbytecode = n + end + elseif environment.initex then + texio.write_nl(format("\nerror loading file: %s (aborting)",filename)) + 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) + +-- traditionally the revision has been a one character string and only +-- pdftex went beyond "9" but anyway we test for it + +if LUATEXENGINE == nil then + LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) + or (find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") +end + +if LUATEXVERSION == nil then + LUATEXVERSION = status.luatex_version/100 + + tonumber(status.luatex_revision)/10000 +end + +if CONTEXTLMTXMODE == nil then + CONTEXTLMTXMODE = LUATEXENGINE == "luametatex" and 1 or 0 +end + +if LUATEXFUNCTIONALITY == nil then + LUATEXFUNCTIONALITY = status.development_id or 6346 +end + +if LUATEXFORMATID == nil then + LUATEXFORMATID = status.format_id or 0 +end + +if JITSUPPORTED == nil then + JITSUPPORTED = LUATEXENGINE == "luajittex" or jit -- "or jit" can go +end + +if INITEXMODE == nil then + INITEXMODE = status.ini_version +end + +environment.luatexengine = LUATEXENGINE +environment.luatexversion = LUATEXVERSION +environment.luatexfunctionality = LUATEXFUNCTIONALITY +environment.jitsupported = JITSUPPORTED +environment.initex = INITEXMODE +environment.initexmode = INITEXMODE + +-- if INITEXMODE then +-- -- we have about that amount so we preallocate then which gives less +-- -- reallocations (we're talking tiny record so no real gain) +-- lua.setbytecode(1024,nil) +-- -- but we don't want to lie about the amount either so ... +-- end + +if not environment.luafilechunk then + + function environment.luafilechunk(filename) + local fullname = filename + if sourcepath ~= "" then + fullname = sourcepath .. "/" .. filename + end + local data = loadfile(fullname) + texio.write("terminal_and_logfile","<",data and "+ " or "- ",fullname,">") + if data then +-- package.loaded[gsub(filename,"%..-$"] = + 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. + +-- print("!!!!!!!!!!!!!!!!!!!!!!",lfs.isfile) os.exit() + +if not lfs.isfile then + + local attributes = lfs.attributes + + function lfs.isdir(name) + return attributes(name,"mode") == "directory" + end + + function lfs.isfile(name) + local a = attributes(name,"mode") + return a == "file" or a == "link" or nil + end + +end + +local isfile = lfs.isfile + +local function source_file(name) + 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_log_file(name) + return target_file(name) +end + +local function find_data_file(name) + return source_file(name) +end + +local function open_data_file(name) + local fullname = source_file(name) + if fullname then + local f = io.open(fullname,'rb') + return { + reader = function() + return f:read("*line") + end + } + else + return false + end +end + +callback.register('find_log_file', find_log_file) +callback.register('find_data_file' , find_data_file ) +callback.register('open_data_file' , open_data_file ) + +callback.register("trace_memory", function(what,success) + success = success and "succeeded" or "failed" + if logs then + logs.report("tex memory","bumping category %a %s, details: %s", + what,success,table.sequenced(status["get"..what.."state"]())) + elseif texio then + texio.write_nl(format("bumping tex '%s' memory %s", + what,success)) + end + -- os.exit() +end) diff --git a/tex/context/base/mkxl/luat-cod.mkxl b/tex/context/base/mkxl/luat-cod.mkxl new file mode 100644 index 000000000..fec88aecd --- /dev/null +++ b/tex/context/base/mkxl/luat-cod.mkxl @@ -0,0 +1,45 @@ +%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 + +\newif\ifproductionrun + +\permanent\let\ctxdirectlua \directlua +\permanent\let\ctxlatelua \latelua +\permanent\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens +\permanent\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens +\permanent\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens +\permanent\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens +\permanent\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens +\permanent\def\ctxreport #1{\directlua{logs.writer[[#1]]}} + +%D Take your choice \unknown + +\aliased\let\ctxlua \ctxdirectlua +\aliased\let\luacode \ctxdirectlua +\aliased\let\lateluacode \ctxlatelua +\aliased\let\directluacode\ctxdirectlua + +%D Reporting the version of \LUA\ that we use is done as follows: + +\permanent\def\luaversion{\ctxwrite{LUAVERSION}} + +\permanent\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}} +\permanent\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}} + +\registerctxluafile{luat-cod.lmt}{autosuffix} + +\protect \endinput diff --git a/tex/context/base/mkxl/luat-fio.lmt b/tex/context/base/mkxl/luat-fio.lmt new file mode 100644 index 000000000..c70ed54e4 --- /dev/null +++ b/tex/context/base/mkxl/luat-fio.lmt @@ -0,0 +1,107 @@ +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 + +texconfig.kpse_init = false -- can go away +texconfig.shell_escape = 't' -- can go away +texconfig.max_print_line = 100000 -- can go away +texconfig.max_in_open = 1000 -- can go away + +if not resolvers.initialized() then + + resolvers.reset() + + -- we now load the file database as we might need files other than + -- tex and lua file on the given path + + resolvers.load() + + if callback then + + local findbinfile = resolvers.findbinfile + local findtexfile = resolvers.findtexfile + local opentexfile = resolvers.opentexfile + local register = callbacks.register + + local ioflush = io.flush + local ioread = io.read + local writenl = texio.write_nl + + local function terminal() + writenl("\ntex console > ") + ioflush() + local line = ioread() + writenl("") + ioflush() + return line + end + + -- local function find_data_file(name) + -- if not name or name == "" then + -- return "context terminal" + -- else + -- return findbinfile(name,"tex") + -- end + -- end + -- + -- local function open_data_file(name) + -- if not name or name == "" or name == "context terminal" then + -- return { + -- reader = terminal, + -- noflines = 1, + -- filename = name, + -- } + -- else + -- name = opentexfile(name) + -- return name ~= "" and name or false + -- end + -- end + + local function open_data_file(name) + if not name or name == "" then + return { + reader = terminal, + noflines = 1, + filename = "context terminal" + } + else + local fullname = findbinfile(name,"tex") + if fullname then + return opentexfile(fullname) + else + return false + end + end + end + + local function find_any_file(name) + return name + end + + register('find_log_file' , find_any_file, true) + register('find_format_file', find_any_file, true) + -- register('find_data_file' , find_data_file, true) + register('open_data_file' , open_data_file, 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.foundintrees(), + #scandata.paths > 0 and concat(scandata.paths," ") or "" + ) +end) diff --git a/tex/context/base/mkxl/luat-ini.mkxl b/tex/context/base/mkxl/luat-ini.mkxl new file mode 100644 index 000000000..4f6556eda --- /dev/null +++ b/tex/context/base/mkxl/luat-ini.mkxl @@ -0,0 +1,296 @@ +%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 method uses +%D the \TEX\ input file locator of kpse. At least we need to use that way of loading +%D when we haven't yet define our own code, which we keep outside the format. We +%D will keep code outside \TEX\ files as much as possible. The solutions evolved +%D with the engine but one can find some history in the \MKIV\ files and articles. + +\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: + +\aliased\let\stoplua \relax % tex catcodes +\aliased\let\stopluacode\relax % lua catcodes + +%D It might makes sense to have a \type {\directelua} so that we can avoid the \type +%D {\normalexpanded} around \type {\directlua}. Something to discuss in the team. + +\permanent\protected\def\startlua % \stoplua + {\begingroup + \obeylualines + \luat_start_lua_indeed} + +\def\luat_start_lua_indeed#1\stoplua + {\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default + +\permanent\protected\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 + +%D It is nicer for checking with \type {s-system-macros} if we have some meaning: + +\ifdefined\n \else \def\n{n} \fi \ifdefined\r \else \def\r{r} \fi +\ifdefined\f \else \def\f{f} \fi \ifdefined\t \else \def\t{t} \fi +\ifdefined\a \else \def\a{a} \fi \ifdefined\b \else \def\b{b} \fi +\ifdefined\v \else \def\v{v} \fi \ifdefined\s \else \def\s{s} \fi + +\ifdefined\+ \else \def\+{+} \fi \ifdefined\- \else \def\-{-} \fi + +\ifdefined\1 \else \def\1{1} \fi \ifdefined\2 \else \def\2{2} \fi +\ifdefined\3 \else \def\3{3} \fi \ifdefined\4 \else \def\4{4} \fi +\ifdefined\5 \else \def\5{5} \fi \ifdefined\6 \else \def\6{6} \fi +\ifdefined\7 \else \def\7{7} \fi \ifdefined\8 \else \def\8{8} \fi +\ifdefined\9 \else \def\9{9} \fi \ifdefined\0 \else \def\0{0} \fi + +\immutable\edef\lua_letter_backslash{\string\\} +\immutable\edef\lua_letter_bar {\string\|} \immutable\edef\lua_letter_dash {\string\-} +\immutable\edef\lua_letter_lparent {\string\(} \immutable\edef\lua_letter_rparent {\string\)} +\immutable\edef\lua_letter_lbrace {\string\{} \immutable\edef\lua_letter_rbrace {\string\}} +\immutable\edef\lua_letter_squote {\string\'} \immutable\edef\lua_letter_dquote {\string\"} +\immutable\edef\lua_letter_n {\string\n} \immutable\edef\lua_letter_r {\string\r} +\immutable\edef\lua_letter_f {\string\f} \immutable\edef\lua_letter_t {\string\t} +\immutable\edef\lua_letter_a {\string\a} \immutable\edef\lua_letter_b {\string\b} +\immutable\edef\lua_letter_v {\string\v} \immutable\edef\lua_letter_s {\string\s} +\immutable\edef\lua_letter_one {\string\1} \immutable\edef\lua_letter_two {\string\2} +\immutable\edef\lua_letter_three {\string\3} \immutable\edef\lua_letter_four {\string\4} +\immutable\edef\lua_letter_five {\string\5} \immutable\edef\lua_letter_six {\string\6} +\immutable\edef\lua_letter_seven {\string\7} \immutable\edef\lua_letter_eight {\string\8} +\immutable\edef\lua_letter_nine {\string\9} \immutable\edef\lua_letter_zero {\string\0} + +\pushoverloadmode + \let\-\explicitdiscretionary +\popoverloadmode + +\everyluacode {% \appendtoks + \enforced\let\\\lua_letter_backslash + \enforced\let\|\lua_letter_bar \enforced\let\-\lua_letter_dash + \enforced\let\(\lua_letter_lparent \enforced\let\)\lua_letter_rparent + \enforced\let\{\lua_letter_lbrace \enforced\let\}\lua_letter_rbrace + \enforced\let\'\lua_letter_squote \enforced\let\"\lua_letter_dquote + \enforced\let\n\lua_letter_n \enforced\let\r\lua_letter_r + \enforced\let\f\lua_letter_f \enforced\let\t\lua_letter_t + \enforced\let\a\lua_letter_a \enforced\let\b\lua_letter_b + \enforced\let\v\lua_letter_v \enforced\let\s\lua_letter_s + \enforced\let\1\lua_letter_one \enforced\let\2\lua_letter_two + \enforced\let\3\lua_letter_three \enforced\let\4\lua_letter_four + \enforced\let\5\lua_letter_five \enforced\let\6\lua_letter_six + \enforced\let\7\lua_letter_seven \enforced\let\8\lua_letter_eight + \enforced\let\9\lua_letter_nine \enforced\let\0\lua_letter_zero +} % \to \everyluacode + +\permanent\protected\def\obeyluatokens + {\setcatcodetable\luacatcodes + \the\everyluacode} + +\immutable\edef\luamajorversion{\ctxwrite{LUAMINORVERSION}} +\immutable\edef\luaminorversion{\ctxwrite{LUAMAJORVERSION}} + +%D We need a way to pass strings safely to \LUA\ without the need for tricky +%D 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 for it: +%D +%D \starttyping +%D \edef\luaescapestring#1{\!!bs#1\!!es} +%D \stoptyping + +\permanent\protected\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}} +\permanent \def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax} +\permanent\protected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} +\permanent \def\getdocumentargument #1{\clf_getdocumentargument{#1}{}} +\permanent\protected\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}} +\permanent \def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}} + +% seldom used so no need for speedy variants: + +\permanent\def\doifelsedocumentargument #1{\doifelsesomething{\clf_getdocumentargument{#1}}} +\permanent\def\doifdocumentargument #1{\doifsomething {\clf_getdocumentargument{#1}}} +\permanent\def\doifnotdocumentargument #1{\doifnothing {\clf_getdocumentargument{#1}}} +\permanent\def\doifelsedocumentfilename #1{\doifelsesomething{\clf_getdocumentfilename\numexpr#1\relax}} +\permanent\def\doifdocumentfilename #1{\doifsomething {\clf_getdocumentfilename\numexpr#1\relax}} +\permanent\def\doifnotdocumentfilename #1{\doifnothing {\clf_getdocumentfilename\numexpr#1\relax}} + +\aliased\let\doifdocumentargumentelse\doifelsedocumentargument +\aliased\let\doifdocumentfilenameelse\doifelsedocumentfilename + +%D A handy helper: + +\permanent\def\luaexpanded#1{\luaescapestring\expandafter{\normalexpanded{#1}}} + +%D Experimental: + +\permanent\protected\def\startluaparameterset[#1]% \stopluaparameterset + {\begingroup + \obeylualines + \obeyluatokens + \luat_start_lua_parameter_set{#1}} + +\def\luat_start_lua_parameter_set#1#2\stopluaparameterset + {\ctxlua{parametersets["#1"]={#2}}% + \endgroup} + +\aliased\let\stopluaparameterset\relax + +\permanent\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: + +\permanent\def\luaconditional#1{\ifcase#1tru\else fals\fi e} + +%D Goodie: +%D +%D \starttyping +%D \ctxluacode{context("%0.5f",1/3)} +%D \stoptyping + +\permanent\protected\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} + +\permanent\protected\def\startctxfunctiondefinition #1 % \stopctxfunctiondefinition + {\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 + \edefcsname#1\endcsname{\noexpand\luafunction\csname\??luafunction#1\endcsname}} + +\permanent\protected\def\setctxluafunction#1#2% experiment + {\expandafter\chardef\csname\??luafunction#1\endcsname#2\relax + \edefcsname#1\endcsname{\noexpand\luafunction\csname\??luafunction#1\endcsname}} + +\aliased\let\stopctxfunctiondefinition\relax + +\permanent\protected\def\startctxfunction #1 % \stopctxfunction + {\begingroup \obeylualines \obeyluatokens \luat_start_lua_function_indeed{#1}} + +\def\luat_start_lua_function_indeed#1#2\stopctxfunction + {\endgroup\edefcsname\??ctxfunction#1\endcsname{\noexpand\luafunction\ctxcommand{ctxfunction(\!!bs#2\!!es)}\relax}} + +\aliased\let\stopctxfunction\relax + +\permanent\def\ctxfunction#1% + {\begincsname\??ctxfunction#1\endcsname} + +%D In theory this is faster due to the call not being wrapped in a function but in +%D practice the speedup can't be noticed. The actions called for often have lots of +%D lookups so an extra one doesn't matter much. The kind of calls differs a lot per +%D document and often there are other ways to optimize a style. For instance we can +%D gain a lot when defining a font, but when a frozen definition is used that gain +%D gets completely lost. For some calls (take list writers) it can get worse if only +%D because readability gets worse and passing is already efficient due to selective +%D flushing, while with the token scanners one has to scan all of them. + +% \startctxfunctiondefinition foo commands.foo() \stopctxfunctiondefinition +% +% \installctxfunction\foo{commands.foo} + +\protected\def\installctxfunction#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax} + +\protected\def\installctxscanner#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax} + +\protected\def\installprotectedctxfunction#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax} + +\protected\def\installprotectedctxscanner#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax} + +\protected\def\resetctxscanner#1% + {\edef\m_syst_name{\csstring#1}% + \gletcsname\m_syst_name\endcsname\relax} + +\protect \endinput diff --git a/tex/context/base/mkxl/luat-lib.mkxl b/tex/context/base/mkxl/luat-lib.mkxl new file mode 100644 index 000000000..d4d3e860f --- /dev/null +++ b/tex/context/base/mkxl/luat-lib.mkxl @@ -0,0 +1,104 @@ +%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}{} +\registerctxluafile{util-tab}{} +\registerctxluafile{util-fil}{optimize} +\registerctxluafile{util-sac}{optimize} +\registerctxluafile{util-sto}{} % could also be done in trac-deb.mkiv +\registerctxluafile{util-pck}{} +\registerctxluafile{util-prs}{} +\registerctxluafile{util-fmt}{} +\registerctxluafile{util-dim}{} + +\registerctxluafile{trac-set}{} +\registerctxluafile{luat-log}{autosuffix} +\registerctxluafile{trac-inf}{autosuffix} +\registerctxluafile{util-lua}{} +\registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv + +\registerctxluafile{util-tpl}{} % needs tracker +\registerctxluafile{util-seq}{} + +\registerctxluafile{util-sta}{} + +\registerctxluafile{util-sbx}{} % needs tracker and templates + +\registerctxluafile{util-soc-imp-reset} {} +\registerctxluafile{util-soc-imp-socket} {} +\registerctxluafile{util-soc-imp-ltn12} {} +\registerctxluafile{util-soc-imp-mime} {} +\registerctxluafile{util-soc-imp-url} {} +\registerctxluafile{util-soc-imp-headers}{} +\registerctxluafile{util-soc-imp-http} {} +\registerctxluafile{util-soc-imp-tp} {} + +\registerctxluafile{util-zip}{} + +\registerctxluafile{data-ini}{} +\registerctxluafile{data-exp}{} +\registerctxluafile{data-env}{} +\registerctxluafile{data-tmp}{} +\registerctxluafile{data-met}{} +\registerctxluafile{data-res}{} +\registerctxluafile{data-inp}{} +\registerctxluafile{data-out}{} +\registerctxluafile{data-fil}{} % opener gets overloaded in data-tex + +\registerctxluafile{data-pre}{} % after data-res +\registerctxluafile{data-bin}{} % before data-tex +\registerctxluafile{data-tex}{} % after data-pre +\registerctxluafile{data-vir}{} +\registerctxluafile{data-zip}{} +%registerctxluafile{data-crl}{} +\registerctxluafile{data-sch}{} +\registerctxluafile{data-tre}{} +\registerctxluafile{data-lua}{} +\registerctxluafile{data-ctx}{} +\registerctxluafile{data-con}{} +\registerctxluafile{data-use}{} +\registerctxluafile{data-aux}{} + +\registerctxluafile{luat-cbk}{} +\registerctxluafile{luat-run}{} +\registerctxluafile{luat-fio}{autosuffix} +\registerctxluafile{luat-cnf}{} +\registerctxluafile{luat-lua}{} +\registerctxluafile{luat-sto}{} +\registerctxluafile{luat-ini}{} +\registerctxluafile{util-env}{} +\registerctxluafile{luat-env}{} +\registerctxluafile{luat-exe}{} % simplified +\registerctxluafile{luat-iop}{} % simplified +%registerctxluafile{luat-bwc}{} +\registerctxluafile{trac-lmx}{} % might become l-lmx or luat-lmx +\registerctxluafile{luat-mac}{} +%registerctxluafile{luat-prp}{} % for the moment of not much use + +\registerctxluafile{lxml-tab}{} +\registerctxluafile{lxml-lpt}{} +\registerctxluafile{lxml-xml}{} +\registerctxluafile{lxml-aux}{} +\registerctxluafile{lxml-mis}{} + +\pushoverloadmode + +\permanent\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}} +\permanent\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}} +\permanent\protected\def\writeline {\ctxlua{logs.newline()}} + +\popoverloadmode + +\endinput diff --git a/tex/context/base/mkxl/luat-log.lmt b/tex/context/base/mkxl/luat-log.lmt new file mode 100644 index 000000000..684b2ac8d --- /dev/null +++ b/tex/context/base/mkxl/luat-log.lmt @@ -0,0 +1,739 @@ +if not modules then modules = { } end modules ['luat-log'] = { + version = 1.001, + comment = "companion to trac-log.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- In fact all writes could go through lua and we could write the console and +-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go. + +-- This used to be combined in trac-log but as we also split between mkiv and lmtx +-- we now have dedicated files. A side effect is a smaller format and a smaller +-- mtxrun. +-- +-- We use different targets: "terminal" "logfile", "both" and have no number +-- channel. + +local next, type, select, print = next, type, select, print +local format, gmatch, find = string.format, string.gmatch, string.find +local concat, insert, remove = table.concat, table.insert, table.remove +local topattern = string.topattern +local utfchar = utf.char +local datetime = os.date +local openfile = io.open + +local write_nl = texio.write_nl +local write = texio.write + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local settings_to_hash = utilities.parsers.settings_to_hash +local sortedkeys = table.sortedkeys + +-- variant is set now + +local variant = "default" +----- variant = "ansi" + +logs = logs or { } +local logs = logs + +-- we extend the formatters: + +formatters.add ( + formatters, "unichr", + [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] +) + +formatters.add ( + formatters, "chruni", + [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] +) + +-- basic loggers + +local function ignore() end + +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) + +local report, subreport, status, settarget, setformats, settranslations + +local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline + +-- we use formatters but best check for % then because for simple messages but +-- we don't want this overhead for single messages (not that there are that +-- many; we could have a special weak table) + +local function ansisupported(specification) + if specification ~= "ansi" and specification ~= "ansilog" then + return false + elseif os and os.enableansi then + return os.enableansi() + else + return false + end +end + +do + + if arg and ansisupported then + -- we're don't have environment.arguments yet + for k, v in next, arg do -- k can be negative ! + if v == "--ansi" or v == "--c:ansi" then + if ansisupported("ansi") then + variant = "ansi" + end + break + elseif v == "--ansilog" or v == "--c:ansilog" then + if ansisupported("ansilog") then + variant = "ansilog" + end + break + end + end + end + + local whereto = "both" + local target = nil + local targets = nil + + local formats = table.setmetatableindex("self") + local translations = table.setmetatableindex("self") + + local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes + local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop + + local variants = { + default = { + formats = { + report_yes = formatters["%-15s > %s\n"], + report_nop = formatters["%-15s >\n"], + direct_yes = formatters["%-15s > %s"], + direct_nop = formatters["%-15s >"], + subreport_yes = formatters["%-15s > %s > %s\n"], + subreport_nop = formatters["%-15s > %s >\n"], + subdirect_yes = formatters["%-15s > %s > %s"], + subdirect_nop = formatters["%-15s > %s >"], + status_yes = formatters["%-15s : %s\n"], + status_nop = formatters["%-15s :\n"], + }, + targets = setmetatableindex( { + logfile = "logfile", + log = "logfile", + file = "logfile", + console = "terminal", + terminal = "terminal", + both = "terminal_and_logfile", + }, function(t,k) t[k] = "terminal_and_logfile" end), + }, + ansi = { + formats = { + report_yes = formatters["%-15s > %s\n"], + report_nop = formatters["%-15s >\n"], + direct_yes = formatters["%-15s > %s"], + direct_nop = formatters["%-15s >"], + subreport_yes = formatters["%-15s > %s > %s\n"], + subreport_nop = formatters["%-15s > %s >\n"], + subdirect_yes = formatters["%-15s > %s > %s"], + subdirect_nop = formatters["%-15s > %s >"], + status_yes = formatters["%-15s : %s\n"], + status_nop = formatters["%-15s :\n"], + }, + targets = setmetatableindex( { + logfile = false, + log = false, + file = false, + console = "terminal", + terminal = "terminal", + both = "terminal", + }, function(t,k) t[k] = "terminal" end), + } + } + + variants.ansilog = { + formats = variants.ansi.formats, + targets = variants.default.targets, + } + + logs.flush = io.flush + + writer = function(...) + if target then + write_nl(target,...) + end + end + + newline = function() + if target then + write_nl(target,"\n") + end + end + + report = function(a,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,report_yes(translations[a],formats[b])) + elseif a then + write_nl(target,report_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + direct = function(a,b,c,...) + if not target then + return "" + elseif c ~= nil then + return direct_yes(translations[a],formatters[formats[b]](c,...)) + elseif b then + return direct_yes(translations[a],formats[b]) + elseif a then + return direct_nop(translations[a]) + else + return "" + end + end + + subreport = function(a,s,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) + elseif a then + write_nl(target,subreport_nop(translations[a],translations[s])) + else + write_nl(target,"\n") + end + end + + subdirect = function(a,s,b,c,...) + if not target then + return "" + elseif c ~= nil then + return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) + elseif b then + return subdirect_yes(translations[a],translations[s],formats[b]) + elseif a then + return subdirect_nop(translations[a],translations[s]) + else + return "" + end + end + + status = function(a,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,status_yes(translations[a],formats[b])) + elseif a then + write_nl(target,status_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + settarget = function(askedwhereto) + whereto = askedwhereto or whereto or "both" + target = targets[whereto] + if not target then + whereto = "both" + target = targets[whereto] + end + if target == "terminal" or target == "terminal_and_logfile" then + logs.flush = io.flush + else + logs.flush = ignore + end + end + + local stack = { } + + pushtarget = function(newtarget) + insert(stack,target) + settarget(newtarget) + end + + poptarget = function() + if #stack > 0 then + settarget(remove(stack)) + end + end + + setformats = function(f) + formats = f + end + + settranslations = function(t) + translations = t + end + + setprocessor = function(f) + local writeline = write_nl + write_nl = function(target,...) + if target then + writeline(target,f(...)) + end + end + end + + setformatters = function(specification) + local t = nil + local f = nil + local d = variants.default + if not specification then + -- + elseif type(specification) == "table" then + t = specification.targets + f = specification.formats or specification + else + if not ansisupported(specification) then + specification = "default" + end + local v = variants[specification] + if v then + t = v.targets + f = v.formats + variant = specification + end + end + targets = t or d.targets + target = targets[whereto] + if f then + d = d.formats + else + f = d.formats + d = f + end + setmetatableindex(f,d) + report_yes = f.report_yes + report_nop = f.report_nop + subreport_yes = f.subreport_yes + subreport_nop = f.subreport_nop + direct_yes = f.direct_yes + direct_nop = f.direct_nop + subdirect_yes = f.subdirect_yes + subdirect_nop = f.subdirect_nop + status_yes = f.status_yes + status_nop = f.status_nop + settarget(whereto) + end + + setformatters(variant) + + setlogfile = ignore + settimedlog = ignore + +end + +logs.report = report +logs.subreport = subreport +logs.status = status +logs.settarget = settarget +logs.pushtarget = pushtarget +logs.poptarget = poptarget +logs.setformats = setformats +logs.settranslations = settranslations + +logs.setlogfile = setlogfile +logs.settimedlog = settimedlog +logs.setprocessor = setprocessor +logs.setformatters = setformatters + +logs.direct = direct +logs.subdirect = subdirect +logs.writer = writer +logs.newline = newline + +local data = { } +local states = nil +local force = false + +function logs.reporter(category,subcategory) + local logger = data[category] + if not logger then + local state = states == true + if not state and type(states) == "table" then + for c, _ in next, states do + if find(category,c) then + state = true + break + end + end + end + logger = { + reporters = { }, + state = state, + } + data[category] = logger + end + local reporter = logger.reporters[subcategory or "default"] + if not reporter then + if subcategory then + reporter = function(...) + if force or not logger.state then + subreport(category,subcategory,...) + end + end + logger.reporters[subcategory] = reporter + else + local tag = category + reporter = function(...) + if force or not logger.state then + report(category,...) + end + end + logger.reporters.default = reporter + end + end + return reporter +end + +logs.new = logs.reporter -- for old times sake + +-- context specicific: this ends up in the macro stream + +local ctxreport = logs.writer + +function logs.setmessenger(m) + ctxreport = m +end + +function logs.messenger(category,subcategory) + -- we need to avoid catcode mess (todo: fast context) + if subcategory then + return function(...) + ctxreport(subdirect(category,subcategory,...)) + end + else + return function(...) + ctxreport(direct(category,...)) + end + end +end + +-- so far + +local function setblocked(category,value) -- v.state == value == true : disable + if category == true or category == "all" then + -- lock all + category, value = "*", true + elseif category == false then + -- unlock all + category, value = "*", false + elseif value == nil then + -- lock selective + value = true + end + if category == "*" then + states = value + for k, v in next, data do + v.state = value + end + else + alllocked = false + states = settings_to_hash(category,type(states)=="table" and states or nil) + for c in next, states do + local v = data[c] + if v then + v.state = value + else + c = topattern(c,true,true) + for k, v in next, data do + if find(k,c) then + v.state = value + end + end + end + end + end +end + +function logs.disable(category,value) + setblocked(category,value == nil and true or value) +end + +function logs.enable(category) + setblocked(category,false) +end + +function logs.categories() + return sortedkeys(data) +end + +function logs.show() + local n, c, s, max = 0, 0, 0, 0 + for category, v in table.sortedpairs(data) do + n = n + 1 + local state = v.state + local reporters = v.reporters + local nc = #category + if nc > c then + c = nc + end + for subcategory, _ in next, reporters do + local ns = #subcategory + if ns > c then + s = ns + end + local m = nc + ns + if m > max then + max = m + end + end + local subcategories = concat(sortedkeys(reporters),", ") + if state == true then + state = "disabled" + elseif state == false then + state = "enabled" + else + state = "unknown" + end + -- no new here + report("logging","category %a, subcategories %a, state %a",category,subcategories,state) + end + report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) +end + +local delayed_reporters = { } + +setmetatableindex(delayed_reporters,function(t,k) + local v = logs.reporter(k.name) + t[k] = v + return v +end) + +function utilities.setters.report(setter,...) + delayed_reporters[setter](...) +end + +directives.register("logs.blocked", function(v) + setblocked(v,true) +end) + +directives.register("logs.target", function(v) + settarget(v) +end) + +do + + local report = logs.reporter("pages") -- not needed but saves checking when we grep for it + local texgetcount = tex and tex.getcount + + local real, user, sub = 0, 0, 0 + + function logs.start_page_number() + real = texgetcount("realpageno") + user = texgetcount("userpageno") + sub = texgetcount("subpageno") + end + + local timing = false + local usage = false + local lasttime = nil + + logs.private = { + enablepagetiming = function() + usage = true + end, + getpagetiming = function() + return type(usage) == "table" and usage + end, + } + + trackers.register("pages.timing", function() timing = "" end) + + function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average + if timing or usage then + local elapsed = statistics.currenttime(statistics) + local average, page + if not lasttime or real < 2 then + average = elapsed + page = elapsed + else + average = elapsed / (real - 1) + page = elapsed - lasttime + end + lasttime = elapsed + if timing then + timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) + end + if usage then + usage = { + page = { + real = real, + user = user, + sub = sub, + }, + time = { + elapsed = elapsed, + page = page, + average = average, + } + } + end + end + if real <= 0 then + report("flushing page%s",timing) + elseif user <= 0 then + report("flushing realpage %s%s",real,timing) + elseif sub <= 0 then + report("flushing realpage %s, userpage %s%s",real,user,timing) + else + report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) + end + logs.flush() + end + +end + +-- we don't have show_open and show_close callbacks yet + +do + local texerror = tex and tex.error or print + local formatters = string.formatters + + function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here + texerror(first and formatters[fmt](first,...) or fmt) + end + +end + +-- this is somewhat slower but prevents out-of-order messages when print is mixed +-- with texio.write + +-- io.stdout:setvbuf('no') +-- io.stderr:setvbuf('no') + +-- windows: > nul 2>&1 +-- unix : > null 2>&1 + +if package.helpers.report then + package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun +end + +do + + local finalactions = { } + local fatalerrors = { } + local possiblefatal = { } + local loggingerrors = false + + function logs.loggingerrors() + return loggingerrors + end + + directives.register("logs.errors",function(v) + loggingerrors = v + if type(v) == "string" then + fatalerrors = settings_to_hash(v) + else + fatalerrors = { } + end + end) + + function logs.registerfinalactions(...) + insert(finalactions,...) -- so we can force an order if needed + end + + local what = nil + local report = nil + local state = nil + local target = nil + + local function startlogging(t,r,w,s) + target = t + state = force + force = true + report = type(r) == "function" and r or logs.reporter(r) + what = w + pushtarget(target) + newline() + if s then + report("start %s: %s",what,s) + else + report("start %s",what) + end + if target == "logfile" then + newline() + end + return report + end + + local function stoplogging() + if target == "logfile" then + newline() + end + report("stop %s",what) + if target == "logfile" then + newline() + end + poptarget() + state = oldstate + end + + function logs.startfilelogging(...) + return startlogging("logfile", ...) + end + + logs.stopfilelogging = stoplogging + + local done = false + + function logs.starterrorlogging(r,w,...) + if not done then + pushtarget("terminal") + newline() + logs.report("error logging","start possible issues") + poptarget() + done = true + end + if fatalerrors[w] then + possiblefatal[w] = true + end + return startlogging("terminal",r,w,...) + end + + logs.stoperrorlogging = stoplogging + + function logs.finalactions() + if #finalactions > 0 then + for i=1,#finalactions do + finalactions[i]() + end + if done then + pushtarget("terminal") + newline() + logs.report("error logging","stop possible issues") + poptarget() + end + return next(possiblefatal) and sortedkeys(possiblefatal) or false + end + end + +end + +-- just in case we load from context + +local dummy = function() end + +function logs.application(t) + return { + name = t.name or tex.jobname, + banner = t.banner, + report = logs.reporter(t.name), + moreinfo = dummy, + export = dummy, + help = dummy, + identify = dummy, + version = dummy, + } +end diff --git a/tex/context/base/mkxl/luat-soc.mkxl b/tex/context/base/mkxl/luat-soc.mkxl new file mode 100644 index 000000000..b2ce70483 --- /dev/null +++ b/tex/context/base/mkxl/luat-soc.mkxl @@ -0,0 +1,52 @@ +%D \module +%D [ file=luat-soc, +%D version=2018.08.05, +%D title=\CONTEXT\ Lua Macros, +%D subtitle=Socket Libraries, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Lua Macros / Socket Libraries} + +%D In \LUATEX\ we provide the socket library that is more or less the standard one +%D for \LUA. It has been around for a while and seems to be pretty stable. The +%D binary module is copmpiled into \LUATEX\ and the accompanying .lua files are +%D preloaded. These files are mostly written by Diego Nehab, Andre Carregal, Javier +%D Guerra, and Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall, +%D David Burgess, Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals +%D are part of and copyrighted by the Kepler project. +%D +%D Here we reload a slightly reworked version of these \type {.lua} files. We keep +%D the same (documented) interface but streamlined some fo the code. No more +%D modules, no more pre 5.2 \LUA, etc. Also, as it loads into the \CONTEXT +%D ecosystem, we plug in some logging. (and maybe tracing in the future). As we +%D don't support serial ports in \LUATEX, related code has been dropped. +%D +%D The files are reformatted so that we can more easilly add additional features +%D and|/|or tracing options. Any error introduced there is our fault! The url module +%D might be replaced by the one in \CONTEXT. When we need mbox a suitable variant +%D will be provided. + +%D Currently we preload the related \LUA\ code in \LUATEX, but that might change at +%D some point. We're prepared for that. + +% \registerctxluafile{util-soc-imp-reset} {} +% +% \registerctxluafile{util-soc-imp-socket} {} +% % registerctxluafile{util-soc-imp-copas} {} +% \registerctxluafile{util-soc-imp-ltn12} {} +% % registerctxluafile{util-soc-imp-mbox} {} +% \registerctxluafile{util-soc-imp-mime} {} +% \registerctxluafile{util-soc-imp-url} {} +% \registerctxluafile{util-soc-imp-headers}{} +% \registerctxluafile{util-soc-imp-http} {} +% \registerctxluafile{util-soc-imp-tp} {} +% % registerctxluafile{util-soc-imp-ftp} {} +% % registerctxluafile{util-soc-imp-smtp} {} + +\endinput diff --git a/tex/context/base/mkxl/luat-usr.mkxl b/tex/context/base/mkxl/luat-usr.mkxl new file mode 100644 index 000000000..8c43a5a72 --- /dev/null +++ b/tex/context/base/mkxl/luat-usr.mkxl @@ -0,0 +1,119 @@ +%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}{} + +%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 % todo: public implementors +\let\luathread\clf_luathread % todo: public implementors + +%D \macros +%D {definenamedlua} +%D +%D We provide an interface for defining instances. We don't have the definers yet +%D so we do it low level: + +\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 message will +%D show \type{} as part of the message. + +\installsystemnamespace{luacode} + +\permanent\tolerant\protected\def\definenamedlua[#1]#*[#2]% + {\ifarguments \orelse \ifcsname\??luacode#1\endcsname \else + \bgroup + % + \edef\fullname{lua_code_#1}% + % + \clf_registernamedlua{#1}{#2}{\fullname}% + % + \frozen\instance\protected\xdefcsname\s!start#1\s!code\endcsname + {\begingroup + \obeylualines + \obeyluatokens + \csname\??luacode#1\endcsname}% + % + \aliased\gletcsname\s!stop#1\s!code\endcsname\relax + % + \normalexpanded{\xdefcsname\??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}}}% + \frozen\instance\gletcsname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname + \egroup + \fi} + +%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/tex/context/base/mkxl/lxml-css.mkxl b/tex/context/base/mkxl/lxml-css.mkxl new file mode 100644 index 000000000..c7c8d8afd --- /dev/null +++ b/tex/context/base/mkxl/lxml-css.mkxl @@ -0,0 +1,76 @@ +%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}{} + +\unprotect + +\permanent\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 + +% \startxmlsetups html:settings +% \xmlsetsetup{#1}{p}{html:p} +% \stopxmlsetups +% +% \xmlmapvalue{ctx-before} {one} {\page BEFORE\par} +% \xmlmapvalue{ctx-after} {two} {\par AFTER\page} +% \xmlmapvalue{text-decoration}{underline}{U} +% \xmlmapvalue{text-decoration}{overline} {O} +% +% \startxmlsetups html:p +% \testfeatureonce{100000}{ +% \edef\foo{\xmlcssstylevalue{#1}{ctx-before}\xmlcssstylevalue{#1}{ctx-after}} +% } +% \page {\tttf style="\xmlatt{#1}{style}"} : \elapsedtime\ s \page +% \xmlvalue{ctx-before}{\xmlcssstylevalue{#1}{ctx-before}}{} +% \xmlflush{#1} +% (\xmlcssstylevalue{#1}{text-decoration}) +% (\xmlcssmappedstylevalue{#1}{text-decoration}{text-decoration}) +% \xmlvalue{ctx-after} {\xmlcssstylevalue{#1}{ctx-after}}{} +% \stopxmlsetups +% +% \startbuffer[temp] +% +%

foo 1

+%

foo 2

+% +% \stopbuffer +% +% \xmlregistersetup{html:settings} +% \xmlprocessbuffer{main}{temp}{} + +% \xmlcssstylevalue % defined at lua end +% \xmlcssmappedstylevalue % defined at lua end + +\protect \endinput + diff --git a/tex/context/base/mkxl/lxml-ctx.mkxl b/tex/context/base/mkxl/lxml-ctx.mkxl new file mode 100644 index 000000000..f4b2edc79 --- /dev/null +++ b/tex/context/base/mkxl/lxml-ctx.mkxl @@ -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}{} + +\unprotect + +\settrue \xmllshowbuffer +\setfalse\xmllshowtitle +\settrue \xmllshowwarning + +\definehead + [lshowtitle] + [subsubsubsubsubject] + +\setuphead + [lshowtitle] + [\c!style=\tta] + +\permanent\protected\def\xmllshow#1% + {\ctxlua{xml.ctx.tshow { + pattern = \!!bs\detokenize{#1}\!!es, + \ifconditional\xmllshowtitle + title = "lshowtitle", + \fi + \ifconditional\xmllshowwarning + warning = true, + \fi + } }} + +\permanent\protected\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/tex/context/base/mkxl/lxml-ini.mkxl b/tex/context/base/mkxl/lxml-ini.mkxl new file mode 100644 index 000000000..f331718e9 --- /dev/null +++ b/tex/context/base/mkxl/lxml-ini.mkxl @@ -0,0 +1,544 @@ +%D \module +%D [ file=lxml-ini, +%D version=2007.08.17, +%D title=\CONTEXT\ \XML\ Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Todo: auto apply setups (manage at lua end) +%D Todo: manuak: \xmlinclusion \xmlinclusions + +\writestatus{loading}{ConTeXt XML Support / Initialization} + +%registerctxluafile{lxml-tab}{} % loader +%registerctxluafile{lxml-lpt}{} % parser +%registerctxluafile{lxml-xml}{} % xml finalizers +%registerctxluafile{lxml-aux}{} % extras using parser +%registerctxluafile{lxml-mis}{} % extras independent of parser +\registerctxluafile{lxml-ent}{} % entity hacks +\registerctxluafile{lxml-tex}{} % tex finalizers +\registerctxluafile{lxml-dir}{} % ctx hacks +\registerctxluafile{lxml-ini}{} % interface + +\unprotect + +% todo: { } mandate so that we can alias + +% undocumented: + +\permanent\def\ctxlxml#1{\ctxlua{lxml.#1}} + +% for now indirect .. this will change when we have updated luatex (scan_argument) + +\permanent\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}} +\permanent\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}} + +%D Maybe I should add \type {\protected} here: + +\permanent\def\xmlloadfile #1#2{\clf_xmlloadfile {#1}{#2}{\directxmlparameter\c!compress}} +\permanent\def\xmlloadbuffer#1#2{\clf_xmlloadbuffer{#1}{#2}{\directxmlparameter\c!compress}} +\permanent\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}} + +\aliased\let\xmlload\xmlloadfile + +% aliased + +%let\xmlall \clf_xmlall +%let\xmlatt \clf_xmlatt +%let\xmlattdef \clf_xmlattdef +%let\xmlattribute \clf_xmlattribute +%let\xmlattributedef \clf_xmlattributedef +%let\xmlbadinclusions \clf_xmlbadinclusions +%let\xmlchainatt \clf_xmlchainatt +%let\xmlchainattdef \clf_xmlchainattdef +%let\xmlchecknamespace \clf_xmlchecknamespace +%let\xmlcommand \clf_xmlcommand +%let\xmlcontext \clf_xmlcontext +%let\xmlcount \clf_xmlcount +%let\xmldelete \clf_xmldelete +%let\xmldirect \clf_xmldirect % in loops, not dt but root +%let\xmldirectives \clf_xmldirectives +%let\xmldirectivesafter \clf_xmldirectivesafter +%let\xmldirectivesbefore \clf_xmldirectivesbefore +%let\xmldisplayverbatim \clf_xmldisplayverbatim +%let\xmlelement \clf_xmlelement +%let\xmlfilter \clf_xmlfilter +%let\xmlfilterlist \clf_xmlfilterlist +%let\xmlfirst \clf_xmlfirst +%let\xmlflush \clf_xmlflush +%let\xmlflushcontext \clf_xmlflushcontext +%let\xmlflushlinewise \clf_xmlflushlinewise +%let\xmlflushpure \clf_xmlflushpure +%let\xmlflushspacewise \clf_xmlflushspacewise +%let\xmlflushtext \clf_xmlflushtext +%let\xmlfunction \clf_xmlfunction +%let\xmlinclude \clf_xmlinclude +%let\xmlincludeoptions \clf_xmlincludeoptions +%let\xmlinclusion \clf_xmlinclusion +%let\xmlinclusionbase \clf_xmlinclusionbase +%let\xmlinclusions \clf_xmlinclusions +%let\xmlindex \clf_xmlindex +%let\xmlinlineverbatim \clf_xmlinlineverbatim +%let\xmllast \clf_xmllast +%let\xmllastatt \clf_xmllastatt +%let\xmllastmatch \clf_xmllastmatch +%let\xmllastpar \clf_xmllastpar +%let\xmlloaddirectives \clf_xmlloaddirectives +%let\xmlmain \clf_xmlmain +%let\xmlmatch \clf_xmlmatch +%let\xmlname \clf_xmlname +%let\xmlnamespace \clf_xmlnamespace +%let\xmlnonspace \clf_xmlnonspace +%let\xmlpar \clf_xmlpar +%let\xmlparam \clf_xmlparam +%let\xmlpath \clf_xmlpath +%let\xmlpopmatch \clf_xmlpopmatch +%let\xmlpos \clf_xmlpos +%let\xmlpure \clf_xmlpure +%let\xmlpushmatch \clf_xmlpushmatch +%let\xmlraw \clf_xmlraw +%let\xmlrefatt \clf_xmlrefatt +%let\xmlregisterns \clf_xmlregisterns % document +%let\xmlremapname \clf_xmlremapname % element +%let\xmlremapnamespace \clf_xmlremapnamespace % document +%let\xmlsave \clf_xmlsave +%let\xmlsetatt \clf_xmlsetatt +%let\xmlsetattribute \clf_xmlsetattribute +%let\xmlsetpar \clf_xmlsetpar +%let\xmlsetparam \clf_xmlsetparam +%let\xmlsetsetup \clf_xmlsetsetup +%let\xmlsnippet \clf_xmlsnippet +%let\xmlstrip \clf_xmlstrip +%let\xmlstripanywhere \clf_xmlstripanywhere +%let\xmlstripnolines \clf_xmlstripnolines +%let\xmlstripped \clf_xmlstripped +%let\xmlstrippednolines \clf_xmlstrippednolines +%let\xmltag \clf_xmltag +%let\xmltext \clf_xmltext +%let\xmltobuffer \clf_xmltobuffer % id pattern name +%let\xmltobuffertextonly \clf_xmltobuffertextonly % id pattern name +%let\xmltobufferverbose \clf_xmltobufferverbose % id pattern name +%let\xmltofile \clf_xmltofile % id pattern filename +%let\xmltoparameters \clf_xmltoparameters +%let\xmlverbatim \clf_xmlverbatim + +\aliased\let\xmlposition\xmlindex + +\permanent\protected\def\xmlinfo#1{\hbox{\ttxx[\xmlname{#1}]}} +\permanent\protected\def\xmlshow#1{\startpacked\ttx\xmlverbatim{#1}\stoppacked} + +% the next one is handy for mode runs because it enforces a consistent +% #1 indexing (needed when using \xmltext{main:123}{...} like calls + +%let\xmladdindex \clf_xmladdindex + +% we need to pass the last argument as function, so + +\permanent\protected\def\xmlsetfunction#1#2#3{\ctxcommand{xmlsetfunction("#1",\!!bs#2\!!es,#3)}} + +% goodie: + +\immutable\def\xmltempbuffername{xml-temp} + +\permanent\protected\def\prettyprintbuffer#1#2% only used here + {\ifdefined\scitebuffer + \scitebuffer[#2][#1]% + \else + \typebuffer[#1][\c!option=#2]% + \fi} + +\permanent\protected\def\xmlprettyprint#1#2% + {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% + \prettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\xmlprettyprinttext#1#2% + {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% + \prettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\inlineprettyprintbuffer#1#2% only used here + {\ifdefined\sciteinlinebuffer + \sciteinlinebuffer[#2][#1]% + \else + \typeinlinebuffer[#1][\c!option=#2]% + \fi} + +\permanent\protected\def\xmlinlineprettyprint#1#2% + {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% + \inlineprettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\xmlinlineprettyprinttext#1#2% + {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% + \inlineprettyprintbuffer\xmltempbuffername{#2}} + +% kind of special: + +\aliased\let\xmlstartraw\clf_xmlstartraw +\aliased\let\xmlstopraw \clf_xmlstopraw + +\aliased\let\startxmlraw\clf_xmlstartraw +\aliased\let\stopxmlraw \clf_xmlstopraw + +% these are expandable! todo: \xmldoifelseattribute + +%let\xmldoif \clf_xmldoif +%let\xmldoifnot \clf_xmldoifnot +%let\xmldoifelse \clf_xmldoifelse +%let\xmldoiftext \clf_xmldoiftext +%let\xmldoifnottext \clf_xmldoifnottext +%let\xmldoifelsetext \clf_xmldoifelsetext + +%let\xmldoifatt \clf_xmldoifatt +%let\xmldoifnotatt \clf_xmldoifnotatt +%let\xmldoifelseatt \clf_xmldoifelseatt + +%let\xmldoifempty \clf_xmldoifempty +%let\xmldoifnotempty \clf_xmldoifnotempty +%let\xmldoifelseempty \clf_xmldoifelseempty +%let\xmldoifselfempty \clf_xmldoifselfempty +%let\xmldoifnotselfempty \clf_xmldoifnotselfempty +%let\xmldoifelseselfempty \clf_xmldoifelseselfempty + +\aliased\let\xmldoiftextelse \xmldoifelsetext +\aliased\let\xmldoifemptyelse \xmldoifelseempty +\aliased\let\xmldoifselfemptyelse \xmldoifelseselfempty + +% \startxmlsetups xml:include +% \xmlinclude{main}{include}{filename|href} +% \stopxmlsetups +% +% \xmlprependsetup{xml:include} + +% \let\xmlgrab\xmlsetsetup % obsolete +% \let\xmlself\s!unknown % obsolete + +\aliased\let\xmlsetup\setupwithargumentswapped +\aliased\let\xmls \setupwithargumentswapped % hardly any faster +\aliased\let\xmlw \setupwithargument % hardly any faster + +% todo: 1:xml:whatever always before 3:xml:something + +\permanent\protected\def\xmlprependsetup #1{\clf_xmlprependsetup{*}{#1}} +\permanent\protected\def\xmlappendsetup #1{\clf_xmlappendsetup {*}{#1}} +\permanent\protected\def\xmlbeforesetup #1#2{\clf_xmlbeforesetup {*}{#1}{#2}} +\permanent\protected\def\xmlaftersetup #1#2{\clf_xmlaftersetup {*}{#1}{#2}} +\permanent\protected\def\xmlremovesetup #1{\clf_xmlremovesetup {*}{#1}} +\permanent\protected\def\xmlresetsetups {\clf_xmlresetsetups {*}} + +\permanent\protected\def\xmlprependdocumentsetup #1#2{\clf_xmlprependsetup{#1}{#2}} +\permanent\protected\def\xmlappenddocumentsetup #1#2{\clf_xmlappendsetup {#1}{#2}} +\permanent\protected\def\xmlbeforedocumentsetup #1#2#3{\clf_xmlbeforesetup {#1}{#2}{#3}} +\permanent\protected\def\xmlafterdocumentsetup #1#2#3{\clf_xmlaftersetup {#1}{#2}{#3}} +\permanent\protected\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}} +\permanent\protected\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}} + +\permanent\protected\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply * +\permanent\protected\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2 + +\aliased\let\xmlregistersetup \xmlappendsetup +\aliased\let\xmlregisterdocumentsetup\xmlappenddocumentsetup + +\mutable\def\xmldocument{main} + +\permanent\protected\def\xmlregisteredsetups + {\xmlstarttiming + \xmlflushsetups\xmldocument + \xmldefaulttotext\xmldocument % after include + \xmlstoptiming} + +\permanent\protected\def\xmlregistereddocumentsetups#1#2% id setups + {\xmlstarttiming + % todo: test for duplicates ! + \xmlflushdocumentsetups{#1}{#2}% + \xmldefaulttotext{#1}% after include + \xmlstoptiming} + +\permanent\protected\def\xmlstarttiming{\clf_xmlstarttiming} % undocumented +\permanent\protected\def\xmlstoptiming {\clf_xmlstoptiming} % undocumented + +\def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup + {\begingroup + \edef\xmldocument{#3}% #2 can be \xmldocument and set as such + %xmlpushdocument{#3}% + #2{#3}{#4}% + \setcatcodetable\notcatcodes + \doifelsenothing{#5}% + {\xmlsetup{#3}{xml:process}}% + {\xmlsetup{#3}{#5}}% + %xmlpopdocument + \endgroup} + +\permanent\protected\def\xmlprocessfile {\lxml_process\plusone \xmlload} +\permanent\protected\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} +\permanent\protected\def\xmlprocessbuffer{\lxml_process\zerocount\xmlloadbuffer} +\aliased \let\xmlprocess \xmlprocessfile + +\startxmlsetups xml:flush + \xmlflush{#1} +\stopxmlsetups + +\startxmlsetups xml:process + \xmlregistereddocumentsetups{#1}{#1} + \xmlmain{#1} +\stopxmlsetups + +\permanent\protected\def\xmlloadonly#1#2#3% + {\xmlload{#1}{#2}% + \xmlregistereddocumentsetups{#1}{#3}} + +% replaced by concat +% +% \protected\def\xmlconnect#1#2#3% inefficient +% {\scratchcounter\xmlcount{#1}{#2}\relax +% \ifcase\scratchcounter \or +% \xmlall{#1}{#2}% +% \else +% \dorecurse \scratchcounter +% {\ifnum\recurselevel>\plusone#3\fi +% \xmlidx{#1}{#2}\recurselevel}% +% \fi} + +\permanent\protected\def\xmlcdataobeyedline {\obeyedline} +\permanent\protected\def\xmlcdataobeyedspace{\strut\obeyedspace} +\permanent\protected\def\xmlcdatabefore {\begingroup\tt} +\permanent\protected\def\xmlcdataafter {\endgroup} + +% verbatim (dodo:pre/post whitespace, maybe splot verbatim and +% cdata commands), experimental: +% +% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim} +% \xmlsetfunction{main}{verb} {lxml.inlineverbatim} + +% we use an xml: namespace so one has to define a suitable verbatim, say +% +% \definetyping[xml:verbatim][typing] +% +% this is experimental! + +\permanent\tolerant\protected\def\startxmldisplayverbatim[#1]% + {\startpacked + \edef\currenttyping{#1}% + \ifempty\currenttyping + \let\currenttyping\v!typing + \else % maybe test for existence + \edef\currenttyping{xml:\currenttyping}% + \fi + \enforced\protected\def\stopxmldisplayverbatim + {\endofverbatimlines + \stoppacked}% + \doinitializeverbatim + \beginofverbatimlines} + +\aliased\let\stopxmldisplayverbatim\relax + +\permanent\tolerant\protected\def\startxmlinlineverbatim[#1]% + {\begingroup + \edef\currenttype{#1}% + \ifempty\currenttype + \let\currenttype\v!type + \else % maybe test for existence + \edef\currenttype{xml:\currenttype}% + \fi + \enforced\let\stopxmlinlineverbatim\endgroup + \doinitializeverbatim} + +\aliased\let\stopxmlinlineverbatim\relax + +% processing instructions + +\permanent\protected\def\xmlinstalldirective#1#2% + {\clf_xmlinstalldirective{#1}{\csstring#2}} + +% an example: + +% + +\appendtoks + \xmlinstalldirective{tex}{xmltexcommand}% +\to \everyjob + +\permanent\def\xmltexcommand#1{\begincsname#1\endcsname} + +% \def\xmlcontextdirective#1% kind class key value +% {\executeifdefined{xml#1directive}\gobblethreearguments} + +% setting up xml: +% +% \setupxml[\c!default=] % mkiv only == text +% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden +% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text + +% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}} + +\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden + +\installcorenamespace{xml} +\installcorenamespace{xmldefaults} +\installcorenamespace{xmlmapvalue} + +\installdirectcommandhandler \??xml {xml} + +\letvalue{\??xmldefaults\v!normal}\zerocount +\letvalue{\??xmldefaults\v!none }\zerocount +\letvalue{\??xmldefaults\v!text }\plusone +\letvalue{\??xmldefaults\v!hidden}\plustwo + +\permanent\protected\def\xmldefaulttotext + {\ifcase\xmlprocessingmode + \expandafter\gobbleoneargument % 0 (none) + \or + \expandafter\clf_xmlsetcommandtotext % 1 (normal) + \or + \expandafter\clf_xmlsetcommandtonone % 2 (hidden) + \else + \expandafter\gobbleoneargument % (none) + \fi} + +\appendtoks + \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone +\to \everysetupxml + +\setupxml + [\c!default=, % flush all + \c!compress=\v!no, % strip comment + \c!entities=\v!no] % load big entity file + +\appendtoks + \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities +\to \everysetupxml + +\permanent\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces +\permanent\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} + +\permanent\def\xmlvalue#1#2% #3 + {\ifcsname\??xmlmapvalue#1:#2\endcsname + \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\def\xmlmappedvalue#1#2#3% + {\ifcsname\??xmlmapvalue#1:#2\endcsname + \expandafter\lastnamedcs + \else + \csname\??xmlmapvalue#1:#3\expandafter\endcsname + \fi} + +\aliased\let\xmldoifvalueelse\xmldoifelsevalue + +\aliased\let\xmlmapval\xmlmapvalue +\aliased\let\xmlval \xmlvalue + +%D Experimental: + +\permanent\def\xmlgetindex #1{\clf_xmlgetindex {\xmldocument}{#1}} +\permanent\def\xmlwithindex #1#2{\clf_xmlwithindex{\xmldocument}{#1}{#2}} +\permanent\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}} + +%D Entities: +%D +%D \starttyping +%D \xmlsetentity{tex}{\TEX{}} % {} needed +%D \stoptyping + +\permanent\protected\def\xmlsetentity#1#2{\clf_xmlsetentity{#1}{\detokenize{#2}}} +\permanent\protected\def\xmltexentity#1#2{\clf_xmltexentity{#1}{\detokenize{#2}}} + +%D The following might change (or even disappear) so we keep it undocumented. + +\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower + +\permanent\protected\def\xmle + {\ifcase\xmlautoentities + \expandafter\lxml_e_none + \or + \expandafter\lxml_e_upper + \or + \expandafter\lxml_e_upperlower + \else + \expandafter\lxml_e_none + \fi} + +\def\lxml_e_none#1#2% safe + {#1} + +\def\lxml_e_upper#1#2% can be abbreviation + {\ifcsname#2\endcsname + \csname#2\expandafter\endcsname + \else + #1% + \fi} + +\def\lxml_e_upperlower#1#2% can be anything, so unsafe + {\ifcsname#2\endcsname + \csname#2\expandafter\endcsname + \orelse\ifcsname#1\endcsname + \csname#1\expandafter\endcsname + \else + #1% + \fi} + +%D We keep these around as there are also MP, LUA and TEX variants but they are not +%D the same as in \MKII. + +\permanent\tolerant\protected\def\processXMLbuffer[#1]{\xmlprocessbuffer{temp}{#1}{}} +\permanent \protected\def\processXMLfile #1{\xmlprocessfile {temp}{#1}{}} +\permanent \protected\def\XMLdata #1{\xmlprocessdata {temp}{#1}{}} + +\aliased\let\processxmlbuffer\processXMLbuffer +\aliased\let\processxmlfile \processXMLfile +\aliased\let\xmldata \XMLdata + +\permanent\protected\def\xmlsetinjectors [#1]{\clf_xmlsetinjectors{#1}} +\permanent\protected\def\xmlresetinjectors {\clf_xmlresetinjectors{}} + +% \def\xmlinjector#1{\executeifdefined{#1}\donothing} + +\permanent\def\xmlinjector#1{\fastsetup{xml:directive:injector:#1}} + +\startsetups xml:directive:injector:page + \page +\stopsetups + +\startsetups xml:directive:injector:column + \column +\stopsetups + +\startsetups xml:directive:injector:blank + \blank +\stopsetups + +\startsetups xml:directive:injector:noline + \vskip-\lineheight +\stopsetups + +\aliased\let\xmlapplyselectors\clf_xmlapplyselectors + +% \let\xmlcatcodes\notcatcodes + +\protect \endinput + +% \newcount\charactersactiveoffset \charactersactiveoffset="10000 +% +% \startextendcatcodetable\ctxcatcodes +% \catcode\numexpr\charactersactiveoffset+`<\relax=13 +% \catcode\numexpr\charactersactiveoffset+`&\relax=13 +% \catcode\numexpr\charactersactiveoffset+`>\relax=13 +% \stopextendcatcodetable +% +% \startextendcatcodetable\xmlcatcodes % not needed +% \catcode\numexpr\charactersactiveoffset+`<\relax=13 +% \catcode\numexpr\charactersactiveoffset+`&\relax=13 +% \catcode\numexpr\charactersactiveoffset+`>\relax=13 +% \stopextendcatcodetable +% +% \ctxlua { % entities are remembered in the format +% commands.remapentity("<",characters.activeoffset + utf.byte("<")) +% commands.remapentity("&",characters.activeoffset + utf.byte("&")) +% commands.remapentity(">",characters.activeoffset + utf.byte(">")) +% } diff --git a/tex/context/base/mkxl/lxml-sor.mkxl b/tex/context/base/mkxl/lxml-sor.mkxl new file mode 100644 index 000000000..798047e04 --- /dev/null +++ b/tex/context/base/mkxl/lxml-sor.mkxl @@ -0,0 +1,99 @@ +%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}{} + +\unprotect + +%D The flusher is unexpandable so that it can be used in tables (noalign +%D interferences). + +% todo: public implementors + +\permanent\protected\def\xmlresetsorter #1{\ctxlxml{sorters.reset("#1")}} +\permanent\protected\def\xmladdsortentry#1#2#3{\ctxlxml{sorters.add("#1","#2",\!!bs#3\!!es)}} +\permanent\protected\def\xmlshowsorter #1{\ctxlxml{sorters.show("#1")}} +\permanent \def\xmlflushsorter #1#2{\ctxlxml{sorters.flush("#1","#2")}} +\permanent\protected\def\xmlsortentries #1{\ctxlxml{sorters.sort("#1")}} + +\protect \endinput + +\startbuffer[test] + + + one + alpha + alpha indeed + + + one + gamma + gamma indeed + + + one + beta + beta indeed + + + two + alpha + alpha again + + + two + gamma + gamma again + + + two + beta + beta again + + +\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/tex/context/base/mkxl/m-mkivmkxl.mkxl b/tex/context/base/mkxl/m-mkivmkxl.mkxl new file mode 100644 index 000000000..9aea14eb2 --- /dev/null +++ b/tex/context/base/mkxl/m-mkivmkxl.mkxl @@ -0,0 +1,3 @@ +% mkiv spacing before figure + +% \let\checkprevdepth\baselinecorrection diff --git a/tex/context/base/mkxl/math-acc.mklx b/tex/context/base/mkxl/math-acc.mklx new file mode 100644 index 000000000..b5580fff2 --- /dev/null +++ b/tex/context/base/mkxl/math-acc.mklx @@ -0,0 +1,151 @@ +%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} $ + +%D Older implementations are kept in the \MKII\ and \MKIV\ modules for educational +%D purposes. + +\installcorenamespace{mathaccents} + +\installcommandhandler \??mathaccents {mathaccents} \??mathaccents + +\setupmathaccents + [\c!top=, + \c!bottom=, + \c!mathstyle=, + \c!color=, + \c!define=\v!yes] % not used + +\definemathaccents + [\v!both] + +\definemathaccents + [\v!top] + [\v!both] + +\definemathaccents + [\v!bottom] + [\v!both] + +\permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top + {\ifparameter#3\or + \frozen\instance\setuevalue{#2}{\math_accents_make_double {#1}\plusone{\number#3}\zerocount}% + \else + \frozen\instance\setuevalue{#1}{\math_accents_make_double\noexpand\currentmathaccents\plusone{\number#2}\zerocount}% + \fi} + +\permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom + {\ifparameter#3\or + \frozen\instance\setuevalue{#2}{\math_accents_make_double {#1}\plustwo\zerocount{\number#3}}% + \else + \frozen\instance\setuevalue{#1}{\math_accents_make_double\noexpand\currentmathaccents\plustwo\zerocount{\number#2}}% + \fi} + +\permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom + {\ifparameter#4\or + \frozen\instance\setuevalue{#2}{\math_accents_make_double {#1}\plusthree{\number#3}{\number#4}}% + \else + \frozen\instance\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} + +\protected\def\math_accents_make_double#class#kind#top#bottom#content% + {\begingroup + \edef\currentmathaccents {#class}% + \edef\p_math_accent_color{\mathaccentsparameter\c!color}% + \startusemathstyleparameter\mathaccentsparameter + \ifempty\p_math_accent_color + \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} + +%D Relative new: + +\newconditional\c_math_accents_auto_dotless \settrue\c_math_accents_auto_dotless % cf opentype math + +\aliased\let\normalgrave\grave \permanent\protected\def\dotlessgrave#1{\normalgrave{\mathdotless#1}} +\aliased\let\normalddot \ddot \permanent\protected\def\dotlessddot #1{\normalddot {\mathdotless#1}} +\aliased\let\normalbar \bar \permanent\protected\def\dotlessbar #1{\normalbar {\mathdotless#1}} +\aliased\let\normalacute\acute \permanent\protected\def\dotlessacute#1{\normalacute{\mathdotless#1}} +\aliased\let\normalhat \hat \permanent\protected\def\dotlesshat #1{\normalhat {\mathdotless#1}} +\aliased\let\normalcheck\check \permanent\protected\def\dotlesscheck#1{\normalcheck{\mathdotless#1}} +\aliased\let\normalbreve\breve \permanent\protected\def\dotlessbreve#1{\normalbreve{\mathdotless#1}} +\aliased\let\normaldot \dot \permanent\protected\def\dotlessdot #1{\normaldot {\mathdotless#1}} +\aliased\let\normalring \ring \permanent\protected\def\dotlessring #1{\normalring {\mathdotless#1}} +\aliased\let\normaltilde\tilde \permanent\protected\def\dotlesstilde#1{\normaltilde{\mathdotless#1}} +\aliased\let\normaldddot\dddot \permanent\protected\def\dotlessdddot#1{\normaldddot{\mathdotless#1}} + +\def\math_accents_auto_dotless#1#2{\ifconditional\c_math_accents_auto_dotless\expandafter#2\else\expandafter#1\fi} + +\permanent\protected\def\grave {\math_accents_auto_dotless\normalgrave \dotlessgrave } +\permanent\protected\def\ddot {\math_accents_auto_dotless\normalddot \dotlessddot } +\permanent\protected\def\bar {\math_accents_auto_dotless\normalbar \dotlessbar } +\permanent\protected\def\acute {\math_accents_auto_dotless\normalacute \dotlessacute } +\permanent\protected\def\hat {\math_accents_auto_dotless\normalhat \dotlesshat } +\permanent\protected\def\check {\math_accents_auto_dotless\normalcheck \dotlesscheck } +\permanent\protected\def\breve {\math_accents_auto_dotless\normalbreve \dotlessbreve } +\permanent\protected\def\dot {\math_accents_auto_dotless\normaldot \dotlessdot } +\permanent\protected\def\ring {\math_accents_auto_dotless\normalring \dotlessring } +\permanent\protected\def\tilde {\math_accents_auto_dotless\normaltilde \dotlesstilde } +\permanent\protected\def\dddot {\math_accents_auto_dotless\normaldddot \dotlessdddot } + +\aliased\let\mathring\ring % for a while + +\protect \endinput diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl new file mode 100644 index 000000000..587eaf6a1 --- /dev/null +++ b/tex/context/base/mkxl/math-ali.mkxl @@ -0,0 +1,1902 @@ +%D \module +%D [ file=math-ali, +%D version=2008.10.20, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Math Alignments, +%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan}, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Math Macros / Math Alignments} + +\unprotect + +%D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code +%D is not gathered in files with the same name. In the meantime this code has been +%D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the +%D fact that alignments are tricky with rspect to tagging. + +% export: +% +% alignment : ok +% cases : +% matrix : ok +% substack : + +%D \macros +%D {definemathalignment, setupmathalignment, startmathalignment} +%D +%D Modules may provide additional alignment features. The following mechanisms are +%D provided by the core. + +\newtoks\t_math_align_a +\newtoks\t_math_align_b +\newtoks\t_math_align_c + +\newskip\d_math_eqalign_distance + +\protected\def\math_eqalign_distance + {\relax + \ifdim\d_math_eqalign_distance>\zeropoint + % \hskip\d_math_eqalign_distance + \tabskip\d_math_eqalign_distance + \fi + \mathalignmentparameter\c!separator + \relax} + +\def\displayopenupvalue{.25\bodyfontsize} + +\def\math_build_eqalign + {\scratchtoks\emptytoks + \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax + \scratchcounterone\mathalignmentparameter\c!m + \scratchcountertwo\mathalignmentparameter\c!n + \etoksapp\scratchtoks{\the\t_math_align_a}% + \scratchcounter\plusone + \dorecurse{\numexpr\scratchcounterone*\scratchcountertwo-\plusone\relax} + {\ifnum\scratchcounter=\scratchcountertwo + \scratchcounter\plusone + \etoksapp\scratchtoks{\math_eqalign_distance}% + \else + \advance\scratchcounter\plusone + \fi + \etoksapp\scratchtoks{\the\t_math_align_b}}% + \etoksapp\scratchtoks{\the\t_math_align_c}} + +\def\math_math_in_eqalign#1% + {\startforceddisplaymath + \tabskip\zeropoint + \everycr\emptytoks + {{}#1{}}% + \stopforceddisplaymath} + +\def\math_text_in_eqalign#1% + {\startimath + \tabskip\zeropoint + \everycr\emptytoks + #1% + \stopimath} + +\def\eqalign#1% why no halign here, probably because of displaywidth + {\emptyhbox + \mskip\thinmuskip + \vcenter + {\math_openup\displayopenupvalue % was: \openup\jot + \mathsurround\zeropoint + \ialign{% + \strut + \hfil + \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath + \aligntab + \startforceddisplaymath{{}\alignmark\alignmark{}}\stopforceddisplaymath + \hfil\crcr + #1\crcr}% + }% + \mskip\thinmuskip} + +% preamble is scanned for tabskips so we need the span to prevent an error message + +\setnewconstant\eqalignmode\plusone + +% use zeroskipplusfill + +\def\math_prepare_r_eqalign_no + {\t_math_align_a + {\strut + \tabskip\zeropoint + \alignmark\alignmark % for picking up the number + \aligntab + \math_first_in_eqalign + \hfil + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \t_math_align_b + {\aligntab + \math_next_in_eqalign + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \ifnum\mathraggedstatus=\plusone + \t_math_align_c + {\hfil + \aligntab + \span + \math_text_in_eqalign{\alignmark\alignmark}% + \tabskip\zeropoint}% + \orelse\ifnum\mathraggedstatus=\plusthree + \t_math_align_c + {\hfil + \tabskip\zeropoint\s!plus 1\s!fill + \aligntab + \span + \math_text_in_eqalign{\alignmark\alignmark}% + \tabskip\zeropoint}% + \else + \t_math_align_c + {\hfil + \tabskip\centering + \aligntab + \span + \llap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\zeropoint}% + \fi + \math_build_eqalign + \the\mathdisplayaligntweaks + \tabskip\centering} + +\def\math_prepare_l_eqalign_no % \checkeddisplaymath + {\t_math_align_a + {\strut + \tabskip\zeropoint + \alignmark\alignmark % for picking up the number + \aligntab + \math_first_in_eqalign + \hfil + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \t_math_align_b + {\aligntab + \math_next_in_eqalign + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \ifnum\mathraggedstatus=\plusone + \t_math_align_c + {\hfil + \aligntab + \kern-\displaywidth + \span + \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \orelse\ifnum\mathraggedstatus=\plusthree + \t_math_align_c + {\hfil + \tabskip\zeropoint\s!plus 1\s!fill + \aligntab + \kern-\displaywidth + \span + \math_rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \else + \t_math_align_c + {\hfil + \tabskip\centering + \aligntab + \kern-\displaywidth + \span + \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \fi + \math_build_eqalign + \the\mathdisplayaligntweaks + \tabskip\centering} + +\def\math_halign_checked + {\halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi} + +\def\math_both_eqalign_no_normal#1#2% + {\ifmmode + \the\mathdisplayaligntweaks + \vcenter\bgroup + \enforced\let\math_finish_eqalign_no\egroup + \else + \enforced\let\math_finish_eqalign_no\relax + \fi + #1% + \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr#2\crcr\egroup + \math_finish_eqalign_no} + +\installcorenamespace {mathalignlocation} + +\setvalue{\??mathalignlocation\v!top }{\let\math_alignment_halign_method\halign\tpack} +\setvalue{\??mathalignlocation\v!bottom}{\let\math_alignment_halign_method\halign\vpack} +\setvalue{\??mathalignlocation\v!center}{\let\math_alignment_halign_method\halign\vcenter} + +\def\math_both_eqalign_no_aligned#1% + {\let\math_alignment_halign_method\math_halign_checked + \ifmmode + \the\mathdisplayaligntweaks + \global\mathnumberstatus\plusone + \ifcase\mathraggedstatus + \def\math_finish_eqalign_no{\crcr\egroup}% + \else % we're in a mathbox + \ifcsname\??mathalignlocation\mathalignmentparameter\c!location\endcsname + \lastnamedcs % top|bottom|center as suggested by HM + \else + \vcenter + \fi + \bgroup + \def\math_finish_eqalign_no{\crcr\egroup\egroup}% + \fi + \fi + #1% + \math_alignment_halign_method\expandafter\bgroup\the\scratchtoks\crcr} + +\def\math_rlap#1% + {\setbox\scratchbox\hbox{#1}% + \ifdim\wd\scratchbox>\d_math_number_correction + \global\d_math_number_correction\wd\scratchbox + \fi + \box\scratchbox + \global\mathnumberstatus\plustwo} + +\def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no} +\def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no} +\def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no} +\def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no} +\def\math_finish_eqalign_no {\crcr\egroup} + +\let\reqalignno\relax +\let\leqalignno\relax +\let\eqalignno \relax + +%D Here we implement the user interface part. We start with basic math alignments: + +\newcount \c_math_eqalign_column +\newconditional\c_math_eqalign_first + +\newtoks \everymathalignment +\newtoks \everymathalignmentdone + +\permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]% + {\aligntab + \strc_formulas_place_number_nested{#1}{#2}} + +\permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]% + {\aligntab + \dostoptagged % finish cell + \strc_formulas_place_number_nested{#1}{#2}% + \math_number_right_of_eqalign + \global\settrue\c_math_eqalign_first + \crcr + \dostoptagged} % finish row + +\permanent\protected\def\math_alignment_NC + {\relax + \ifconditional\c_math_eqalign_first + \ifx\p_math_alignment_number\v!auto + \strc_formulas_place_number_nested{+}{}% + \fi + \global\setfalse\c_math_eqalign_first + \fi + \math_number_left_of_eqalign + \aligntab} + +\permanent\protected\def\math_alignment_EQ + {\NC=} + +\noaligned\tolerant\protected\def\math_common_TB[#1]% + {\noalign{\blank[#1]}} + +\installmacrostack\NC % maybe more to shared table definitions +\installmacrostack\NN % maybe more to shared table definitions +\installmacrostack\EQ % maybe more to shared table definitions +\installmacrostack\NR % maybe more to shared table definitions +\installmacrostack\BC % maybe more to shared table definitions +\installmacrostack\EC % maybe more to shared table definitions +\installmacrostack\TB % maybe more to shared table definitions + +\appendtoks + \push_macro_NC + \push_macro_NN + \push_macro_EQ + \push_macro_NR + \push_macro_TB + \enforced\let\NC\math_alignment_NC + \enforced\let\NN\math_alignment_NN + \enforced\let\EQ\math_alignment_EQ + \enforced\let\NR\math_alignment_NR + \enforced\let\TB\math_common_TB + \global\settrue\c_math_eqalign_first +\to \everymathalignment + +\appendtoks + \pop_macro_TB + \pop_macro_NR + \pop_macro_EQ + \pop_macro_NN + \pop_macro_NC +\to \everymathalignmentdone + +\let\math_alignment_snap_start\relax +\let\math_alignment_snap_stop \relax + +% % experimental: +% +% \def\math_alignment_snap_start +% {\ifgridsnapping +% \edef\p_math_alignment_grid{\mathalignmentparameter\c!grid}% +% \ifx\p_math_alignment_grid\v!no\else +% \snaptogrid[\p_math_alignment_grid]\vbox\bgroup +% \fi +% \fi} +% +% \def\math_alignment_snap_stop +% {\ifgridsnapping +% \ifx\p_math_alignment_grid\v!no\else +% \egroup +% \fi +% \fi} +% +% % doesn't work well, so: + +\let\math_alignment_snap_start\relax +\let\math_alignment_snap_stop \relax + +% end of experimental + +\newconditional\c_math_alignment_auto_number + +% \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex + +\permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]% + {\edef\currentmathalignment{#1}% + \ifarguments\or\or + \setupmathalignment[#1][#2]% bad! ungrouped + \fi + \math_alignment_snap_start + \the\everymathalignment + \c_math_eqalign_column\zerocount + \edef\p_math_alignment_number{\mathalignmentparameter\c!number}% + \processcommacommand + [\mathalignmentparameter\c!align]% + {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument + \global\c_math_eqalign_column\plusone + \dostarttagged\t!math\empty + \dostarttagged\t!mtable\currentmathalignment + \numberedeqalign} + +\def\math_alignment_stop % can be protected + {\math_finish_eqalign_no + \dostoptagged + \dostoptagged + \the\everymathalignmentdone + \math_alignment_snap_stop} + +\installcorenamespace{mathalignment} +\installcorenamespace{mathalignmentvariant} + +\installcommandhandler \??mathalignment {mathalignment} \??mathalignment + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}% + \frozen\instance\setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}% +\to \everydefinemathalignment + +\setupmathalignment + [\c!n=2, + \c!m=1, + \c!distance=\emwidth, + \c!grid=\v!math] + +\definemathalignment[align] % default case (this is what amstex users expect) +\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing) + +% special case.. in case one mistypes .. + +\ifdefined \startalignment + + \pushoverloadmode + + \aliased\let\align_math_normal_start\startalign + \aliased\let\align_math_normal_stop \stopalign + + \aliased\let\align_text_normal_start\startalignment + \aliased\let\align_text_normal_stop \stopalignment + + \permanent\overloaded\protected\def\startalign + {\ifmmode + \enforced\let\stopalign\align_math_normal_stop % cannot be a protected def ... lookahead in align + \expandafter\align_math_normal_start + \orelse\ifinformula + \enforced\let\stopalign\align_math_normal_stop + \expandafter\align_math_normal_start + \else + \enforced\let\stopalign\align_text_normal_stop + \expandafter\align_text_normal_start + \fi} + + \aliased\let\stopalign\relax + + \permanent\overloaded\protected\def\startalignment + {\ifmmode + \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align + \expandafter\align_math_normal_start + \orelse\ifinformula + \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align + \expandafter\align_math_normal_start + \else + \enforced\let\stopalignment\align_text_normal_stop + \expandafter\align_text_normal_start + \fi} + + \aliased\let\stopalignment\relax + + \pushoverloadmode + +\fi + +% + +\permanent\protected\def\numberedeqalign + {\doifelse{\formulaparameter\c!location}\v!left + \math_handle_eqalign_no_l_aligned + \math_handle_eqalign_no_r_aligned} + +\def\math_first_in_eqalign + {\global\c_math_eqalign_column\plusone + \dostarttagged\t!mtablerow \empty + \dostarttagged\t!mtablecell\empty} + +\def\math_next_in_eqalign + {\global\advance\c_math_eqalign_column\plusone + \dostoptagged % finish cell + \dostarttagged\t!mtablecell\empty} + +\def\math_left_of_eqalign + {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname + \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi + \fi} + +\def\math_right_of_eqalign + {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname + \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi + \fi} + +\newconditional\c_math_alignment_local_number % not used but when true puts in front (todo) + +\def\math_number_right_of_eqalign + {\ifcase\wd\b_strc_formulas_number\else + \ifconditional\c_math_alignment_local_number + \ifcase\c_strc_math_number_location\or\or + \box\b_strc_formulas_number + \fi + \else + \box\b_strc_formulas_number + \fi + \fi} + +\def\math_number_left_of_eqalign + {\ifcase\wd\b_strc_formulas_number\else + \ifconditional\c_math_alignment_local_number + \ifcase\c_strc_math_number_location\or + \box\b_strc_formulas_number + \fi + \fi + \fi} + +\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) + {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname + \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} + +\letvalue{\??mathalignmentvariant\v!normal}\zerocount +\letvalue{\??mathalignmentvariant\v!left }\plusone +\letvalue{\??mathalignmentvariant\v!right }\plustwo +\letvalue{\??mathalignmentvariant\v!middle}\plusthree + +\permanent\protected\def\math_align_NR_generic[#1][#2]% + {\strc_formulas_place_number_nested{#1}{#2}\crcr} + +%D \starttyping +%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0] +%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1] +%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2] +%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3] +%D \stoptyping + +%D \startbuffer +%D \placeformula \startformula \eqalignno { +%D a &= b & \formulanumber \cr +%D c &= d \cr +%D &= e \cr +%D &= f & \formulanumber +%D } \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \EQ b \NR[+] +%D \NC c \EQ d \NR +%D \NC \EQ f \NR[for:demo-a-1] +%D \NC \EQ g \NR[for:demo-a-2][a] +%D \NC \EQ h \NR[for:demo-a-3][b] +%D \NC \EQ i \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \EQ b \NR[+] +%D \NC c \EQ d \NR +%D \NC \EQ f \NR +%D \NC \EQ g \NR +%D \NC \EQ h \NR +%D \NC \EQ i \NR[+] +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \NC \eq b \NR[+] +%D \NC c \NC \neq d \NR +%D \NC \NC \neq f \NR[for:demo-b-1] +%D \NC \NC \geq g \NR[for:demo-b-2][a] +%D \NC \NC \leq h \NR[for:demo-b-3][b] +%D \NC \NC \neq i \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={left,middle,right}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={right,middle,left}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformula +%D \startalign[n=3,align={middle,middle,middle}] +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformulas +%D \setupmathalignment[n=3,align={middle,middle,middle}]% +%D \startformula +%D \startalign +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \startformula +%D \startalign +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \stopformulas +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformulas +%D \dorecurse{5}{\startformula +%D \startalign[n=3,align={middle,middle,middle}] +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula} +%D \stopformulas +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {definemathcases, setupmathcases, startmathcases} +%D +%D Another wish \unknown + +\installcorenamespace{mathcases} + +\installcommandhandler \??mathcases {mathcases} \??mathcases + +\setupmathcases + [\c!distance=\emwidth, + \c!strut=\v!yes, % new + \c!numberdistance=2.5\emwidth, + \c!left={\left\{\mskip\thinmuskip}, + \c!right={\right.}] + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentmathcases}{\math_cases_start[\currentmathcases]}% + \frozen\instance\setvalue {\e!stop \currentmathcases}{\math_cases_stop}% +\to \everydefinemathcases + +\permanent\protected\def\math_cases_NC_zero + {\math_cases_NC} + +\permanent\protected\def\math_cases_MC_zero + {\math_cases_NC + \ifmmode\else + \startimath + \enforced\let\math_cases_end_math\stopimath + \fi} + +\let\math_cases_end_math\relax + +\permanent\protected\def\math_cases_NR_zero + {\unskip + \math_cases_end_math + \aligntab + \global\enforced\let\math_cases_NC\math_cases_NC_first + \dodirectdoubleempty\math_cases_NR} + +\permanent\protected\def\math_cases_NC_first + {\global\enforced\let\math_cases_NC\math_cases_NC_second} + +\permanent\protected\def\math_cases_NC_second + {\math_cases_end_math\aligntab} + +\let\math_cases_NR\math_align_NR_generic + +\installmacrostack\math_cases_NC + +\permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]% + {\begingroup + \edef\currentmathcases{#1}% + \ifarguments\or\or + \setupcurrentmathcases[#2]% + \fi + \edef\p_strut{\mathcasesparameter\c!strut}% + \ifx\p_strut\v!yes + \enforced\let\math_cases_strut\strut + \else + \enforced\let\math_cases_strut\relax + \fi + \mathcasesparameter\c!left + \vcenter\bgroup + \push_macro_math_cases_NC + \enforced\let\endmath\relax + \enforced\let\NC\math_cases_NC_zero + \enforced\let\MC\math_cases_MC_zero + \enforced\let\NR\math_cases_NR_zero + \enforced\let\TB\math_common_TB + \global\enforced\let\math_cases_NC\math_cases_NC_first + \normalbaselines + \mathsurround\zeropoint + \everycr\emptytoks + \tabskip\zeropoint + \global\c_math_eqalign_column\plusone + \halign\bgroup + \startimath + \mathcasesparameter\c!style + \alignmark\alignmark + \stopimath + \hfil + \aligntab + \hskip\mathcasesparameter\c!distance\relax + \pop_macro_math_cases_NC + \math_cases_strut % looks better + \alignmark\alignmark + \hfil + \aligntab + \hskip\mathcasesparameter\c!numberdistance\relax + \let\formuladistance\!!zeropoint + \span\math_text_in_eqalign{\alignmark\alignmark}% + \crcr} % todo: number + +% When we have just protected we get an extra row but we can no flag +% this as a proper alignment related command which means that uit gets +% expanded. + +\noaligned\permanent\protected\def\math_cases_stop + {\crcr + \egroup + \pop_macro_math_cases_NC + \egroup + \mathcasesparameter\c!right + \endgroup} + +\definemathcases[cases] +\definemathcases[\v!mathcases] + +%D \startbuffer +%D \placeformula \startformula \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR[+] +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula x \startcases +%D \NC 2 \NC $ y > 0 $ \NR[+] +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula x \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {definemathmatrix, setupmathmatrix, startmathmatrix} +%D +%D Yet another one \unknown. This time we implement the lot a bit +%D different which is a side effect of getting the tagging right. In +%D retrospect the main alignment could be done this way but \unknown + +\installcorenamespace{mathmatrix} + +\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix + +\setupmathmatrix + [\c!distance=\emwidth, + \c!left=, + \c!right=, + \c!align=\v!middle] + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}% + \frozen\instance\setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem +\to \everydefinemathmatrix + +\def\math_matrix_start_table + {\global\c_math_eqalign_column\zerocount + \dostarttagged\t!math\empty + \dostarttagged\t!mtable\empty} + +\def\math_matrix_stop_table + {\dostoptagged + \dostoptagged} + +\def\math_matrix_start_row + {\noalign{\global\c_math_eqalign_column\zerocount}% + \dostarttagged\t!mtablerow\empty} + +\def\math_matrix_stop_row + {\dostoptagged} + +\protected\def\math_matrix_start_cell + {\dostarttagged\t!mtablecell\empty + \hss + \math_left_of_eqalign + \startimath + \math_matrix_set_style + \tabskip\zeropoint + \everycr\emptytoks} + +\protected\def\math_matrix_stop_cell + {\stopimath + \math_right_of_eqalign + \hss + \dostoptagged} + +% We could construct a preamble with alignment and such embedded but the number +% of matrices with many rows is normally so low that it doesn't pay of at all. + +\protected\def\math_matrix_distance + {\relax + \ifdim\d_math_eqalign_distance>\zeropoint + \hskip\d_math_eqalign_distance + \fi + \relax} + +\def\math_matrix_preamble + {\math_matrix_strut + \global\advance\c_math_eqalign_column\plusone + \math_matrix_start_cell + \alignmark\alignmark + \math_matrix_stop_cell + \aligntab + \aligntab + \math_matrix_distance + \global\advance\c_math_eqalign_column\plusone + \math_matrix_start_cell + \alignmark\alignmark + \math_matrix_stop_cell} + +\newconditional\c_math_matrix_first + +\permanent\protected\def\math_matrix_NR + {\aligntab\omit + \math_matrix_stop_row + \math_matrix_pickup + \crcr + \math_matrix_start_row} + +\permanent\protected\def\math_matrix_NC + {\ifconditional\c_math_matrix_first + \expandafter\math_matrix_NC_yes + \else + \expandafter\math_matrix_NC_nop + \fi} + +\permanent\protected\def\math_matrix_pickup{\global\settrue \c_math_matrix_first} +\permanent\protected\def\math_matrix_NC_yes{\global\setfalse\c_math_matrix_first} +\permanent\protected\def\math_matrix_NC_nop{\aligntab} % avoids lookahead + +% \def\math_matrix_stop_wrapup +% {\crcr +% \strut +% \crcr +% \noalign{\vskip-\struthtdp}} + +\def\math_matrix_start_processing + {\dontleavehmode + \bgroup + \tabskip\zeropoint + \math_matrix_pickup + \enforced\let\NR\math_matrix_NR + \enforced\let\NC\math_matrix_NC + \enforced\let\MC\math_matrix_NC + \enforced\let\TB\math_common_TB + % + \enforced\let\endmath\relax + % + \setbox\nextbox\vbox\bgroup + \math_matrix_start_table + \halign \bgroup + % preamble + \span\math_matrix_preamble + % done + \crcr + \math_matrix_start_row} + +\def\math_matrix_stop_processing + {%\math_matrix_stop_wrapup % optional + \math_matrix_stop_row + \egroup + \math_matrix_stop_table + \egroup + \mathmatrixleft + \math_matrix_finish_nextbox + \mathmatrixright + \egroup} + +\let\math_matrix_strut \strut +\let\math_matrix_set_style\relax + +\def\math_matrix_check_settings + {\edef\p_strut{\mathmatrixparameter\c!strut}% + \ifx\p_strut\v!no + \enforced\let\math_matrix_strut\relax + \else + \enforced\let\math_matrix_strut\strut + \ifx\p_strut\v!yes\else + \spacing\p_strut + \fi + \fi + \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax + \edef\math_matrix_set_style{\mathmatrixparameter\c!style}} + +\def\math_matrix_set_defaults + {\normalbaselines % hm, spacing ? + \mathsurround\zeropoint + \tabskip\zeropoint} + +\def\math_matrix_set_columns_step + {\advance\c_math_eqalign_column\plusone + %\c_math_matrix_columns\c_math_eqalign_column + \math_eqalign_set_column} + +\def\math_matrix_set_columns + {\c_math_eqalign_column\zerocount + \rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step} + +\newcount\c_math_eqalign_column_saved + +% \installglobalmacrostack\c_math_matrix_first + +\tolerant\protected\def\math_matrix_start[#1]#*[#2]% + {\begingroup + \globalpushmacro\c_math_matrix_first % hm, does that work? + \c_math_eqalign_column_saved\c_math_eqalign_column + \globalpushmacro\c_math_eqalign_first + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \math_matrix_check_settings + \math_matrix_set_defaults + \math_matrix_set_columns + \math_matrix_start_processing} + +\def\math_matrix_stop + {\math_matrix_stop_processing + \globalpushmacro\c_math_eqalign_first + \global\c_math_eqalign_column\c_math_eqalign_column_saved + \globalpopmacro\c_math_matrix_first + \endgroup} + +% vcenter: +% +% delta = (height(v) + depth(v))/2 +% axis = math_axis_size(cur_size) +% height(v) = delta + axis +% depth(v) = delta - axis + +\installcorenamespace{mathmatrixalignlocation} + +\let\mathmatrixleft \empty % experimental hook +\let\mathmatrixright\empty % experimental hook + +\setvalue{\??mathmatrixalignlocation\v!top }{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} +\setvalue{\??mathmatrixalignlocation\v!high }{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax} +\setvalue{\??mathmatrixalignlocation\v!center}{\relax} +\setvalue{\??mathmatrixalignlocation\v!lohi} {\relax} +\setvalue{\??mathmatrixalignlocation\v!normal}{\relax} +\setvalue{\??mathmatrixalignlocation\v!bottom}{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} +\setvalue{\??mathmatrixalignlocation\v!low }{\lower\dimexpr(\nextboxdp-\nextboxht)/2\relax} + +\def\math_matrix_finish_nextbox + {\begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup + \normalstartimath + \mathmatrixparameter\c!left + \vcenter{\box\nextbox}% + \mathmatrixparameter\c!right + \normalstopimath + \egroup} + +\definemathmatrix[matrix] +\definemathmatrix[\v!mathmatrix] + +%D \startbuffer +%D \placeformula \startformula[-] \startmatrix +%D \NC 1 \NC x \NC a \NR +%D \NC 2 \NC y \NC b \NR +%D \NC 3 \NC z \NC c \NR +%D \stopmatrix \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25] +%D +%D \startbuffer +%D \placeformula \startformula[-] \startbmatrix +%D \NC 1 \NC x \NC a \NR +%D \NC 2 \NC y \NC b \NR +%D \NC 3 \NC z \NC c \NR +%D \stopbmatrix \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Taco added some code (dedicated to Aditya Mahajan) that gives more +%D control over aligments: + +%D \startbuffer +%D \startformula +%D \startmatrix +%D \NC a + x \NC = \NC a + d \NR +%D \NC y \NC = \NC d \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \startbuffer +%D \startformula +%D \startmatrix [distance=3pt,align={right,left}] +%D \NC a + x \NC = a + d \NR +%D \NC y \NC = d \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \startbuffer +%D \startformula +%D \startmatrix [left=\left(,right=\right)] +%D \NC a + x \NR +%D \NC y \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D A bit more complex code: +%D +%D \startbuffer +%D \startformula +%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}} +%D \left\{ (R_1, R_2) : +%D \startmatrix[distance=1em,align={left,left,right}] +%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR +%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR +%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR +%D \stopmatrix +%D \right\} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {startmatrices} +%D +%D Just a handy keystroke safer: + +\permanent\protected\def\startmatrices + {\begingroup + \setupmathmatrix} + +\permanent\protected\def\stopmatrices + {\endgroup} + +%D \startbuffer +%D \startformula +%D \startmatrix[left={\left(},right={\right)}] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[left={\left(},right={\right)},location=low] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[left={\left(},right={\right)},location=high] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \startformula +%D \startmatrices[left={\left(},right={\right)}] +%D \startmatrix +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[location=bottom] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[location=top] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D \stopmatrices +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer % does not run well: \getbuffer + +%D Handy for the \type {m-matrix} module: + +\permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#2]% + {\begingroup + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \math_matrix_start[\currentmathmatrix]} + +\permanent\protected\def\stopnamedmatrix + {\math_matrix_stop + \endgroup} + +%D The following code is derived from Aditya's simplematrix prototype but +%D adapted to regular mathmatrices (which saves some code so it can go into +%D the core): + +\def\math_matrix_simple_row#1% + {\rawprocesscommalist[#1]\math_matrix_simple_col + \toksapp\scratchtoks{\NR}} + +\def\math_matrix_simple_col#1% + {\toksapp\scratchtoks{\NC#1}} + +\permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% + {\begingroup + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \scratchtoks\emptytoks + \processlist[];\math_matrix_simple_row[#3]% + \math_matrix_start[\currentmathmatrix]% + \the\scratchtoks + \math_matrix_stop + \endgroup} + +%D We hook it into the normal mathmatrix code: + +\appendtoks + \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}% + \ifempty\p_simplecommand\else + \frozen\instance\setuevalue{\p_simplecommand}{\math_matrix_simple[\currentmathmatrix]}% + \fi +\to \everydefinemathmatrix + +%D And predefine some matrices: + +\definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle] +\definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle] +\definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle] + +\definemathmatrix[thematrix][matrix:parentheses][\c!simplecommand=thematrix] + +%D \startbuffer +%D \startformula +%D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \startformula +%D \startthematrix +%D \NC 1\NC 2\NC 3\NC 4\NR +%D \NC 5\NC 6\NC 7\NC 8\NR +%D \NC 9\NC10\NC11\NC12\NR +%D \stopthematrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {startintertext} +%D +%D Preliminary feature: +%D +%D {\em example code} +%D +%D The intertext commands have to be expandable (in aligment lookahead) so +%D we cannot use \type {\protected}. + +\permanent\def\startintertext#1\stopintertext + {\noalign{\math_intertext{#1}}} + +\permanent\let\stopintertext\relax + +\permanent\def\intertext#1% + {\noalign{\math_intertext{#1}}} + +\protected\def\math_intertext#1% + {\penalty\postdisplaypenalty + \afterdisplayspace + \vbox{\forgetall\noindent#1\par}% + \penalty\predisplaypenalty + \beforedisplayspace} + +%D \macros +%D {substack} +%D +%D Preliminary code: +%D +%D \startbuffer +%D \startformula +%D \sum_{% +%D \startsubstack +%D i = 1 \NR +%D i \neq n \NR +%D i \neq m +%D \stopsubstack +%D }a_i +%D \stopformula +%D \stopbuffer +%D +%D \getbuffer which was typed as \typebuffer +%D +%D Notice that these macros give the correct spacing for +%D subscripts. Compare for example +%D +%D \startbuffer +%D \startformula +%D \sum_{\startsubstack a \NR b \NR \stopsubstack} +%D \text{ and } +%D \sum_{\scriptstyle a \atop \scriptstyle} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer which gives \getbuffer + +% no tagging yet : how is it supposed to be coded? + +\permanent\protected\def\startsubstack + {\begingroup + \vcenter\bgroup + \baselineskip\mathstacktotal + \lineskip\mathstackvgap + \lineskiplimit\lineskip + \mathsurround\zeropoint + \everycr\emptytoks + \enforced\let\NC\relax + \enforced\let\MC\relax + \enforced\let\NR\crcr + \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr} + +\noaligned\permanent\protected\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 +% +% \protected\def\bordermatrix +% {\begingroup +% \setbox\scratchbox\hbox{\mr\char"239C}% +% \global\mathparentwd\wd\scratchbox +% \endgroup +% \normalbordermatrix} +% +% \def\bordermatrix +% {\begingroup +% \mr +% \global\mathparentwd\fontcharwd\font"239C\relax +% \endgroup +% \normalbordermatrix} + +%D \macros{overset, underset} +%D +%D The macros \type{\overset} and \type{\underset} are provided by +%D \AMS\ packages in \LATEX. These macro allows you to place a symbol +%D above or below another symbol, irrespective of whether the other +%D symbol is a relation or something else, and without influencing the +%D spacing. For most cases there is a better way to do such things +%D (declaring a math command with limop option, or using accents), but +%D occasionally these macros can be useful, for example: +%D +%D \startbuffer +%D \startformula +%D \overset{*}{X} \underset{*}{X} +%D \stopformula +%D \stopbuffer +%D \typebuffer \getbuffer +%D +%D Use these macros sparingly. Remember, \TEX\ was designed for +%D mathematics, so there is usually a proper method for typesetting +%D common math notation. +%D +%D These macros are a cleaner version of \type {\binrel@} and +%D \type {\binrel@@} macros in \AMSTEX\ packages. + +\def\math_binrel_apply#1% + {\begingroup + \setbox\scratchbox\hbox + {\thinmuskip 0mu + \medmuskip -1mu + \thickmuskip -1mu + \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}% + \kern-\wd\scratchbox + \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}% + \ifdim\wd\scratchbox<\zeropoint + \endgroup + \expandafter\mathbin + \orelse\ifdim\wd\scratchbox>\zeropoint + \endgroup + \doubleexpandafter\mathrel + \else + \endgroup + \doubleexpandafter\firstofoneargument + \fi} + +\permanent\protected\def\overset#1#2% + {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}} + +\permanent\protected\def\underset#1#2% + {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}} + +%D The following code comes from \type {math-str.mkiv}. +%D +%D Here we implement a basic math alignment mechanism. Numbers are also handled. The macros +%D \type {\startinnermath} and \type {\stopinnermath} can be overloaded in specialized +%D modules. + +\installcorenamespace{mathinnerstart} +\installcorenamespace{mathinnerstop} + +% \protected\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname} +% \protected\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname} + +\permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal} +\permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal} + +\permanent\protected\def\mathinnerstrut + {\doif{\formulaparameter\c!strut}\v!yes\strut} + +\permanent\protected\def\defineinnermathhandler#1#2#3% + {\setvalue{\??mathinnerstart#1}{#2}% + \setvalue{\??mathinnerstop #1}{#3}} + +\installtextracker + {formulas.boxes} + {\enforced\let\math_hbox\ruledhbox} + {\enforced\let\math_hbox\hbox} + +\let\math_hbox\hbox + +\newconstant\mathraggedstatus % normal left center right +\newconstant\mathnumberstatus % nothing normal shift_right + +\newdimen\d_math_number_correction + +\def\math_box_llapped_math_no + {\ifcase\mathraggedstatus\or + \box\b_strc_formulas_number + \or + \llap{\box\b_strc_formulas_number}% + \or + \llap{\box\b_strc_formulas_number}% + \fi} + +\def\math_box_rlapped_math_no + {\ifcase\mathraggedstatus\or + \rlap{\box\b_strc_formulas_number}% + \or + \rlap{\box\b_strc_formulas_number}% + \or + \box\b_strc_formulas_number + \fi} + +\newconditional\c_strc_math_has_number +\newconditional\c_strc_math_display_overflow +\newconstant \c_strc_math_number_location +\newdimen \d_strc_math_number_width +\newdimen \d_strc_math_display_width +\newbox \b_strc_math_display +\newconstant \c_strc_formulas_frame_mode +\newdimen \d_strc_math_indent +\newconditional\c_strc_math_indent + +\newdimen\d_strc_math_framed_width + +\setvalue{\??formulaoption\v!frame}% + {\edef\p_frame{\formulaparameter\c!frame}% + \ifx\p_frame\v!number + \c_strc_formulas_frame_mode\plustwo % inside frame + \else + \c_strc_formulas_frame_mode\plusone % outside frame + \fi} + +% mode: 0=no frame | 1=number inside frame | 2=number outside frame + +\def\strc_math_flush_aligned + {\ifcase\c_strc_math_vertical + \ifcase\mathraggedstatus\or\hfill\or\hfill\fi + \box\b_strc_math_display + \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi + \else + \ifconditional\c_strc_math_indent + \ifzeropt\d_strc_math_indent\else + \hangafter\plusone + \hangindent\d_strc_math_indent + \fi + \fi + \edef\p_interlinespace{\formulaparameter\c!interlinespace}% + \ifempty\p_interlinespace\else\baselineskip\p_interlinespace\fi + \global\d_strc_math_indent\zeropoint + \ifcase\mathraggedstatus\or\raggedleft\or\raggedcenter\or\raggedright\fi + \unhbox\b_strc_math_display + \fi} + +\def\strc_math_flush_box_normal + {\ifcase\c_strc_math_vertical + \hbox to \displaywidth\bgroup + \strc_math_flush_aligned + \egroup + \else + \strc_math_flush_aligned + \fi} + +\def\strc_math_flush_box_framed_common + {\d_strc_math_framed_width\displaywidth + \setformulaframedparameter\c!align{\formulaparameter\c!align}% + \letformulaframedparameter\c!strut\v!no + \d_framed_formula\ht\b_strc_math_display + \ifcase\mathraggedstatus\or\hfill\or\hfill \fi + \inheritedformulaframedframed{\box\b_strc_math_display}% + \ifcase\mathraggedstatus\or \or\hfill\or\hfill\fi} + +\def\strc_math_flush_box_framed_display + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\v!formula + \setformulaframedparameter\c!width{\d_strc_math_framed_width}% + \strc_math_flush_box_framed_common} + +\def\strc_math_flush_box_framed_fit_inline + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\empty + \letformulaframedparameter\c!width\v!fit + \strc_math_flush_box_framed_common} + +\def\strc_math_flush_box_framed_fit_display + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\v!formula + \letformulaframedparameter\c!width\v!fit + \strc_math_flush_box_framed_common} + +% combiners + +\def\strc_math_flush_box + {\ifcase\c_strc_formulas_frame_mode + \strc_math_flush_box_normal + \else + \strc_math_flush_box_framed_display + \fi} + +\def\strc_math_number_right_normal + {\strc_math_flush_aligned + \hss % hss makes room for number + \math_box_llapped_math_no} + +\def\strc_math_number_left_normal + {\math_box_rlapped_math_no + \strc_math_flush_aligned + \hss} % hss makes room for number + +\def\strc_math_number_right_normal_outside + {\ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_display + \else + \strc_math_flush_box_framed_display + \fi + \hss % hss makes room for number + \math_box_llapped_math_no} + +\def\strc_math_number_left_normal_outside + {\math_box_rlapped_math_no + \hss % hss makes room for number + \ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_display + \else + \strc_math_flush_box_framed_display + \fi} + +\def\strc_math_number_right_normal_inside + {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup + \strc_math_flush_aligned + \hss + \math_box_llapped_math_no + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_left_normal_inside + {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup + \math_box_rlapped_math_no + \hss + \strc_math_flush_aligned + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_right_overflow + {\vpack\bgroup + \strc_math_flush_box + \par + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \egroup + \egroup} + +\def\strc_math_number_left_overflow + {\vpack\bgroup + \hpack to \displaywidth\bgroup + \math_box_rlapped_math_no + \hss + \egroup + \strc_math_flush_box + \egroup} + +\def\strc_math_number_right_overflow_outside + {\vpack\bgroup + \strc_math_flush_box_framed_fit_inline + %\hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \egroup + \egroup} + +\def\strc_math_number_left_overflow_outside + {\vpack\bgroup + \hpack to \dimexpr\displaywidth-\d_framed_locator_lo\relax\bgroup + \math_box_rlapped_math_no + \hss + \egroup + \hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why + \strc_math_flush_box_framed_fit_inline + \egroup} + +\def\strc_math_number_right_overflow_inside + {\setbox\b_strc_math_display\vpack\bgroup + \box\b_strc_math_display + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \hskip\d_framed_locator_ro + \egroup + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_left_overflow_inside + {\setbox\b_strc_math_display\vpack\bgroup + \hpack to \displaywidth\bgroup + % \hskip\d_framed_locator_lo + \math_box_rlapped_math_no + \hss + \egroup + \box\b_strc_math_display + \egroup + \strc_math_flush_box_framed_fit_inline} + +% checkers + +\def\strc_math_number_check + {\d_strc_math_display_width\wd\b_strc_math_display + \ifconditional\c_strc_formulas_tight + \ifdim\d_strc_math_display_width>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \displaywidth\d_strc_math_display_width + \setfalse\c_strc_math_display_overflow + \fi + \else + \ifdim\d_strc_math_display_width>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \setfalse\c_strc_math_display_overflow + \fi + \fi} + +\def\strc_math_number_check_outside + {\d_strc_math_display_width\naturalwd\b_strc_math_display + \ifdim\dimexpr\d_strc_math_display_width+\d_framed_locator_lo+\d_framed_locator_ro\relax>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \setfalse\c_strc_math_display_overflow + \fi + % still ok? + \ifnum\mathraggedstatus=\plustwo + \d_strc_math_framed_width\dimexpr\displaywidth-2\wd\b_strc_formulas_number\relax + \else + \d_strc_math_framed_width\dimexpr\displaywidth- \wd\b_strc_formulas_number\relax + \fi} + +\let\strc_math_number_check_inside\strc_math_number_check_outside + +% offsets + +\def\strc_math_number_check_offsets + {\begingroup + \setbox\scratchbox\hbox + {\inheritedformulaframedframed + {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}% + \endgroup} + +% tracing + +\def\strc_math_traced_state_yes + {\llap{\setbox\scratchbox\hbox{\infofont + \ifcase\mathraggedstatus unset\or right\or middle\or left\fi + \space + \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi + \space + \ifconditional\c_strc_math_display_overflow overflow\else fit\fi + \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}} + +\let\strc_math_traced_state\relax + +\installtextracker + {formulas.framed} + {\let\strc_math_traced_state\strc_math_traced_state_yes} + {\let\strc_math_traced_state\relax} + +% packaging + +\protected\def\strc_math_box_start#1% + {\hsize\displaywidth % \checkeddisplaymath + \global\mathnumberstatus\plusone + \mathraggedstatus#1\relax + % + \global\d_math_number_correction\zeropoint + % + \edef\p_location{\formulaparameter\c!location}% + \useformulacolorparameter\c!color + \c_strc_math_number_location\ifx\p_location\v!left\plusone\orelse\ifx\p_location\v!right\plustwo\else\zerocount\fi + % + %\strc_formulas_place_number % not here as we can have inner alignment numbers + \dontcomplain + \setbox\b_strc_math_display\math_hbox\bgroup % \checkeddisplaymath + \mathinnerstrut + \startforceddisplaymath} + +\def\strc_math_flush_number_no + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_flush_box_normal + \else + \strc_math_flush_box_framed_fit_inline + \fi + \else + \ifcase\c_strc_formulas_frame_mode + %\ifconditional\c_strc_formulas_tight + % \strc_math_flush_box_normal + %\else + \strc_math_flush_box_normal + %\fi + \else + \ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_inline + \else + \strc_math_flush_box_framed_display + \fi + \fi + \fi + \else + \strc_math_flush_box + \fi} + +\def\strc_math_flush_number_left + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_left_overflow + \or + \strc_math_number_left_overflow_outside + \or + \strc_math_number_left_overflow_inside + \fi + \else + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_left_normal + \or + \strc_math_number_left_normal_outside + \or + \strc_math_number_left_normal_inside + \fi + \fi + \else + \box\b_strc_formulas_number + \hfill + \strc_math_flush_aligned + \fi} + +\def\strc_math_flush_number_right + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_right_overflow + \or + \strc_math_number_right_overflow_outside + \or + \strc_math_number_right_overflow_inside + \fi + \else + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_right_normal + \or + \strc_math_number_right_normal_outside + \or + \strc_math_number_right_normal_inside + \fi + \fi + \else + \strc_math_flush_aligned + \hfill + \box\b_strc_formulas_number + \fi} + +\protected\def\strc_math_box_stop + {\stopforceddisplaymath + \egroup + % check number + \d_strc_math_number_width\wd\b_strc_formulas_number + % + \ifcase\mathnumberstatus + \setfalse\c_strc_math_has_number + \or\ifzeropt\d_strc_math_number_width + \setfalse\c_strc_math_has_number + \else + \settrue\c_strc_math_has_number + \fi\fi + % preroll left and right offsets + \ifcase\c_strc_formulas_frame_mode + % no frame + \else + \strc_math_number_check_offsets + \fi + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_check + \or + \strc_math_number_check_outside + \else + \strc_math_number_check_inside + \fi + \noindent % \noindentation % not \dontleavehmode + \hskip\d_strc_formulas_display_margin_left % was kern but that doesn't indent + \strc_math_traced_state + \ifcase\c_strc_math_vertical + \hbox to \displaywidth \bgroup + \or + \vbox \bgroup \hsize\displaywidth + \or + \bgroup \hsize\displaywidth + \fi + \ifcase\mathnumberstatus + \strc_math_flush_box + \or % status 1 + \ifcase\c_strc_math_number_location + \strc_math_flush_box + \or % number left + \ifzeropt\wd\b_strc_formulas_number + \strc_math_flush_number_no + \else + \strc_math_flush_number_left + \fi + \else % number right + \ifzeropt\wd\b_strc_formulas_number + \strc_math_flush_number_no + \else + \strc_math_flush_number_right + \fi + \fi + \or % status 2 + \hskip\d_math_number_correction % probably no longer used + \strc_math_flush_box + \hss + \else + \strc_math_flush_box + \fi + \ifcase\c_strc_math_vertical + \or + \or + \par + \fi + \egroup} + +\defineinnermathhandler\v!left {\strc_math_box_start\plusone }{\strc_math_box_stop} +\defineinnermathhandler\v!middle {\strc_math_box_start\plustwo }{\strc_math_box_stop} +\defineinnermathhandler\v!right {\strc_math_box_start\plusthree}{\strc_math_box_stop} +\defineinnermathhandler\v!flushleft {\strc_math_box_start\plusthree}{\strc_math_box_stop} +\defineinnermathhandler\v!center {\strc_math_box_start\plustwo }{\strc_math_box_stop} +\defineinnermathhandler\v!flushright{\strc_math_box_start\plusone }{\strc_math_box_stop} +\defineinnermathhandler\v!normal {\strc_math_box_start\plustwo }{\strc_math_box_stop} + +%D Some inline math tweak. + +\appendtoks + \ifcase\mathnestinglevel\or + % 4=disable 6=only when no spaces + \mathsurroundskip\mathematicsparameter\c!textdistance\relax + \ifzeropt\mathsurroundskip + \ifzeropt\gluestretch\mathsurroundskip + \ifzeropt\glueshrink\mathsurroundskip + \mathsurroundmode\plussix + \else + \mathsurroundskip\zeropoint + \mathsurroundmode\plusfour + \fi + \else + \mathsurroundmode\plussix + \fi + \else + \mathsurroundmode\plussix + \fi + \else + \mathsurroundmode\plusfour + \mathsurroundskip\zeropoint + \fi +\to \everymathematics + +\setupmathematics + [\c!textdistance=\zeropoint] + +%D This is an experiment. No fancy spacing and alignments here. If we ever +%D go that route it might result in incompatible rendering. + +\permanent\protected\def\startsplitformula + {\ifhmode + \par + \fi + \begingroup + \beforedisplayspace + % subset of \everydisplay: + \c_attr_mathmode\plusone + \settrue \indisplaymath + % end of subset + \informulatrue} + +\permanent\protected\def\stopsplitformula + {\afterdisplayspace + \endgroup} + +\protect \endinput + +% \placeformula \startformula[-] \startmatrix +% \NC 1 \NC x \NC a \NR +% \NC 2 \NC y \NC b \NR +% \NC 3 \NC z \NC c \NR +% \stopmatrix \stopformula + +% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}] + +% \placeformula \startformula[-] \startbordermatrix +% \NC 1 \NC x \NC a \NR +% \NC 2 \NC y \NC b \NR +% \NC 3 \NC z \NC c \NR +% \stopbordermatrix \stopformula diff --git a/tex/context/base/mkxl/math-def.mkxl b/tex/context/base/mkxl/math-def.mkxl new file mode 100644 index 000000000..29ad9b465 --- /dev/null +++ b/tex/context/base/mkxl/math-def.mkxl @@ -0,0 +1,171 @@ + %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 + +\pushoverloadmode % cap etc + +\startluacode + mathematics.define(\number\defaultmathfamily) + -- mathematics.xml.registerentities() +\stopluacode + +\popoverloadmode + +\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 [arccosh] [nolop] {\mfunctionlabeltext{arccosh}} +\definemathcommand [arcsinh] [nolop] {\mfunctionlabeltext{arcsinh}} +\definemathcommand [arctanh] [nolop] {\mfunctionlabeltext{arctanh}} +\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}} + +\aliased\let\normalmatharg\arg % todo: maybe automatically + +%D This needs checking: + +\permanent\protected\def\setoperatorlimits#1#2% operator limits + {\savenormalmeaning{#1}% + \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}} + +\pushoverloadmode + +\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 + +\popoverloadmode + +%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. + +\pushoverloadmode + +\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} + +\popoverloadmode + +% \appendtoks +% \def\over{\primitive\over}% +% \to \everymathematics + +\protect \endinput diff --git a/tex/context/base/mkxl/math-del.mkxl b/tex/context/base/mkxl/math-del.mkxl new file mode 100644 index 000000000..3995c08b2 --- /dev/null +++ b/tex/context/base/mkxl/math-del.mkxl @@ -0,0 +1,164 @@ +%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 + +\permanent\protected\def\leftfakedelimiter {\advance\c_math_delimiter_nesting\minusone\gobbleoneargument} +\permanent\protected\def\rightfakedelimiter{\advance\c_math_delimiter_nesting\plusone \gobbleoneargument} + +\permanent\protected\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} + +\permanent\protected\def\fakeleftdelimiter {\ifnum\c_math_delimiter_nesting>\zerocount\left .\fi} +\permanent\protected\def\fakerightdelimiter{\ifnum\c_math_delimiter_nesting<\zerocount\right.\fi} + +%D The following macros are used in the MathML interpreter, so there is a good +%D change of them never being documented for other usage. + +\aliased\let\normalordelimiter\secondoftwoarguments +\aliased\let\normalorfiller \firstoftwoarguments + +\permanent\protected\def\enabledelimiter {\enforced\let\normalordelimiter\secondoftwoarguments} +\permanent\protected\def\disabledelimiter{\enforced\let\normalordelimiter\firstoftwoarguments} + +\permanent\protected\def\enablefiller {\enforced\let\normalorfiller\secondoftwoarguments} +\permanent\protected\def\disablefiller {\enforced\let\normalorfiller\firstoftwoarguments} + +\permanent\protected\def\mathopnolimits#1{\mathop{\mathrm#1}\nolimits} % was \rm, which follows text fonts (used in mml parser, check!) +\permanent\protected\def\mathopdolimits#1{\mathop{\mathrm#1}} % was \rm, which follows text fonts (used in mml parser, check!) + +% A new experiment: + +% Hm, we already have \definemathextensible so we need to preserve that one. We now +% use \definemathdelimiter. + +\installcorenamespace {mathdelimiter} + +\installcommandhandler \??mathdelimiter {mathdelimiter} \??mathdelimiter + +\aliased\let\setupmathdelimiters\setupmathdelimiter + +\setupmathdelimiters + [\c!symbol=0, + \c!define=\v!yes, + \c!factor=1.5, + \c!axis=\v!yes, + % \c!exact=\v!yes + \c!height=\exheight, + \c!depth=\exheight] + +\appendtoks + \ifcstok{\mathdelimiterparameter\c!define}\v!yes + \frozen\instance\setuevalue\currentmathdelimiter{\mathdelimiter[\currentmathdelimiter]}% + \fi +\to \everydefinemathdelimiter + +\permanent\tolerant\protected\def\mathdelimiter[#1]#*[#2]% + {\mathop + {\edef\currentmathdelimiter{#1}% + \iftok{#2}\emptytoks + \edef\p_factor{\mathdelimiterparameter\c!factor}% + \orelse\ifhastok={#2}% + \setupcurrentmathdelimiter[#2]% + \edef\p_factor{\mathdelimiterparameter\c!factor}% + \else + \edef\p_factor{#2}% + \fi + \edef\p_exact{\mathdelimiterparameter\c!exact}% + \edef\p_axis {\mathdelimiterparameter\c!axis}% + \edef\p_leftoffset{\mathdelimiterparameter\c!leftoffset}% + \edef\p_rightoffset{\mathdelimiterparameter\c!rightoffset}% + \ifx\p_leftoffset\empty\else + \mskip\p_leftoffset + \fi + \Uvextensible + \ifx\p_exact\v!yes exact \fi + \ifx\p_axis \v!yes axis \fi + height \p_factor\dimexpr\mathdelimiterparameter\c!height\relax + depth \p_factor\dimexpr\mathdelimiterparameter\c!depth \relax + \Udelimiter\zerocount\zerocount\mathdelimiterparameter\c!symbol + \relax + \ifx\p_rightoffset\empty\else + \mskip\p_rightoffset + \fi}} + +\definemathdelimiter[integral][\c!symbol="222B] + +% \setupmathdelimiter[integral][rightoffset=-3mu,exact=yes,factor=2] +% +% \let\inlineint \int +% \let\displayint\integral +% +% \protected\def\int{\ifmmode\inlineordisplaymath\inlineint\displayint\else\normalint\fi} +% +% \startlines +% \ruledhbox{$\integral f\frac{1}{2}$} +% \ruledhbox{$\integral[factor=1] f\frac{1}{2}$} +% \ruledhbox{$\integral[factor=3] f\frac{1}{2}$} +% \ruledhbox{$\int f\frac{1}{2}$} +% \stoplines + +\permanent\protected\def\autointegral#1#2#3% + {\ifmmode + \setbox\nextbox\mathstylehbox{#3}% + \scratchdimen\ifdim\nextboxht>\nextboxdp\nextboxht\else\nextboxdp\fi + \mathlimop{% + \Uvextensible + height \scratchdimen + depth \scratchdimen + exact% + axis% + \Udelimiter \plusfour \zerocount "222B% + }% + \limits % nolimits needs more work: kerning and so + \normalsuperscript{#1}% + \normalsubscript{#2}% + \box\nextbox + \else + \char"222B\relax + \fi} + +% \startformula +% a = +% \autointegral{t}{b}1 + +% \autointegral{t}{b}{\frac{\frac{3}{4}}{\frac{1}{2}}} + +% \autointegral{t}{b}{\frac{\frac{\frac{\frac{1}{2}}{2}}{2}}{2}} +% \stopformula + +\protect \endinput diff --git a/tex/context/base/mkxl/math-dis.mkxl b/tex/context/base/mkxl/math-dis.mkxl new file mode 100644 index 000000000..5b70970f3 --- /dev/null +++ b/tex/context/base/mkxl/math-dis.mkxl @@ -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/tex/context/base/mkxl/math-fen.mkxl b/tex/context/base/mkxl/math-fen.mkxl new file mode 100644 index 000000000..f18d72c85 --- /dev/null +++ b/tex/context/base/mkxl/math-fen.mkxl @@ -0,0 +1,829 @@ +%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 + +% maybe always "method=auto" for: +% +% \switchtobodyfont[cambria] +% \ruledhbox{$f(x)$} +% \ruledhbox{\mathdelimitersmode6$f\left(x\right)$} +% \ruledhbox{\mathdelimitersmode7$f\left(x\right)$} +% \ruledhbox{$f\left(\frac{1}{x}\right)$} + +% 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 + +\aliased\let\setupmathfences\setupmathfence + +\setupmathfences + [\c!method=, % maybe always \v!auto + \c!left=, + \c!right=, + \c!middle=, + \c!mathstyle=, + \c!color=, + \c!command=, + \c!mathclass=, + \c!factor=\v!auto] + +\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 + +%D So we can do: +%D +%D \starttyping +%D $ a + \fenced[bar][size=1] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=2] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=3] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=4] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=big] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=Big] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=bigg]{\frac {b} {c}} + d $ +%D $ a + \fenced[bar][size=Bigg]{\frac {b} {c}} + d $ +%D $ a + \fenced[bar][factor=1] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][factor=2] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar][factor=4] {\frac {b} {c}} + d $ +%D $ a + \fenced[bar] {\frac {b} {c}} + d $ +%D \stoptyping + +\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror +\newconditional\c_math_fenced_sized \setfalse\c_math_fenced_sized + +\installcorenamespace {mathfencesize} + +\setvalue{\??mathfencesize big}{1} +\setvalue{\??mathfencesize Big}{2} +\setvalue{\??mathfencesize bigg}{3} +\setvalue{\??mathfencesize Bigg}{4} + +\def\math_fenced_force_size#1#2% + {\c_attr_mathsize\numexpr + #1*\plushundred + +\ifcsname\??mathfencesize#2\endcsname\lastnamedcs\else#2\fi + \relax} + +\protected\def\math_fenced_inject#1#2#3#4% + {\ifx#1\empty + #2.% + \else + \edef\p_mathclass{\mathfenceparameter\c!mathclass}% + \ifconditional\c_math_fenced_sized + \let\p_factor\v!fixed + \else + \edef\p_factor{\mathfenceparameter\c!factor}% + \fi + \ifempty\p_factor + \ifempty\p_mathclass + #2% + \else + #3% + \s!class\p_mathclass + \fi + \orelse\ifx\p_factor\v!auto + \ifempty\p_mathclass + #2% + \else + #3% + \s!class\p_mathclass + \fi + \orelse\ifx\p_factor\v!none + #3% + \s!height\zeropoint + \s!depth\zeropoint + \ifempty\p_mathclass\else + \s!class\p_mathclass + \fi + \s!axis + % #2% + \else + \scratchdimen\ifx\p_factor\v!fixed\scaledpoint\else\dimexpr\p_factor\bodyfontsize/2\relax\fi + #3% + \s!height\scratchdimen + \s!depth\scratchdimen + \ifempty\p_mathclass\else + \s!class\p_mathclass + \fi + \s!axis + \fi + \Udelimiter#4\fam#1\relax + \fi} + +\permanent\def\math_fenced_left + {\edef\p_left + {\ifconditional\c_math_fenced_mirror + \ifconditional\c_math_right_to_left + \mathfenceparameter\c!right + \else + \mathfenceparameter\c!left + \fi + \else + \mathfenceparameter\c!left + \fi}% + \math_fenced_color_push + \math_fenced_inject\p_left\normalleft\Uleft\plusfour + \math_fenced_color_pop} + +\permanent\def\math_fenced_middle + {\edef\p_middle{\mathfenceparameter\c!middle}% + \mskip\thinmuskip + \math_fenced_color_push + \math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour + \math_fenced_color_pop + \mskip\thinmuskip} + +\permanent\def\math_fenced_right + {\edef\p_right + {\ifconditional\c_math_fenced_mirror + \ifconditional\c_math_right_to_left + \mathfenceparameter\c!left + \else + \mathfenceparameter\c!right + \fi + \else + \mathfenceparameter\c!right + \fi}% + \math_fenced_color_push + \math_fenced_inject\p_right\normalright\Uright\plusfive + \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 + +\aliased\let\fence \relax +\aliased\let\fenced\relax + +\newcount\c_math_fenced_nesting + +\protected\def\math_fenced_fenced_common + {\startusemathstyleparameter\mathfenceparameter + \enforced\let\fence\math_fenced_middle + \edef\p_math_fenced_color{\mathfenceparameter\c!color}% + \ifempty\p_math_fenced_color + \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} + +\protected\def\math_fenced_fenced_start#1% + {\advance\c_math_fenced_nesting\plusone + \begingroup + \edef\currentmathfence{#1}% + \math_fenced_fenced_common + \math_fenced_left} + +\protected\def\math_fenced_fenced_stop#1% + {\edef\currentmathfence{#1}% + \math_fenced_right + \stopusemathstyleparameter + \endgroup + \advance\c_math_fenced_nesting\minusone} + +\tolerant\protected\def\math_fenced_fenced[#1]#*[#2]% + {\advance\c_math_fenced_nesting\plusone + \begingroup + \edef\currentmathfence{#1}% + \ifparameter#2\or\setupcurrentmathfence[#2]\fi + \math_fenced_fenced_common + \edef\p_size{\mathfenceparameter\c!size}% + \ifempty\p_size + \expandafter\math_fenced_fenced_indeed_adapt + \else + \expandafter\math_fenced_fenced_indeed_fixed + \fi} + +\protected\def\math_fenced_fenced_indeed_finish + {\stopusemathstyleparameter + \endgroup + \advance\c_math_fenced_nesting\minusone} + +\protected\def\math_fenced_fenced_indeed_fixed#1% + {\math_fenced_force_size\bigmathdelimitervariant\p_size + \settrue\c_math_fenced_sized + \math_fenced_left + \setfalse\c_math_fenced_sized + #1% + \settrue\c_math_fenced_sized + \math_fenced_right + \setfalse\c_math_fenced_sized + \math_fenced_fenced_indeed_finish} + +\protected\def\math_fenced_fenced_indeed_adapt#1% + {\setfalse\c_math_fenced_sized + \math_fenced_left + #1% + \setfalse\c_math_fenced_sized + \math_fenced_right + \math_fenced_fenced_indeed_finish} + +\appendtoks + \enforced\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: + +\pushoverloadmode + +\immutable\protected\def\Lparenthesis {\math_fenced_fenced_start{parenthesis}} \immutable\protected\def\Rparenthesis {\math_fenced_fenced_stop {parenthesis}} +\immutable\protected\def\Lbracket {\math_fenced_fenced_start{bracket}} \immutable\protected\def\Rbracket {\math_fenced_fenced_stop {bracket}} +\immutable\protected\def\Lbrace {\math_fenced_fenced_start{brace}} \immutable\protected\def\Rbrace {\math_fenced_fenced_stop {brace}} +\immutable\protected\def\Langle {\math_fenced_fenced_start{angle}} \immutable\protected\def\Rangle {\math_fenced_fenced_stop {angle}} +\immutable\protected\def\Ldoubleangle {\math_fenced_fenced_start{doubleangle}} \immutable\protected\def\Rdoubleangle {\math_fenced_fenced_stop {doubleangle}} +\immutable\protected\def\Lbar {\math_fenced_fenced_start{bar}} \immutable\protected\def\Rbar {\math_fenced_fenced_stop {bar}} +\immutable\protected\def\Ldoublebar {\math_fenced_fenced_start{doublebar}} \immutable\protected\def\Rdoublebar {\math_fenced_fenced_stop {doublebar}} +\immutable\protected\def\Ltriplebar {\math_fenced_fenced_start{triplebar}} \immutable\protected\def\Rtriplebar {\math_fenced_fenced_stop {triplebar}} +\immutable\protected\def\Lsolidus {\math_fenced_fenced_start{solidus}} \immutable\protected\def\Rsolidus {\math_fenced_fenced_stop {solidus}} +\immutable\protected\def\Lfloor {\math_fenced_fenced_start{floor}} \immutable\protected\def\Rfloor {\math_fenced_fenced_stop {floor}} +\immutable\protected\def\Lceiling {\math_fenced_fenced_start{ceiling}} \immutable\protected\def\Rceiling {\math_fenced_fenced_stop {ceiling}} +\immutable\protected\def\Lmoustache {\math_fenced_fenced_start{moustache}} \immutable\protected\def\Rmoustache {\math_fenced_fenced_stop {moustache}} +\immutable\protected\def\Luppercorner {\math_fenced_fenced_start{uppercorner}} \immutable\protected\def\Ruppercorner {\math_fenced_fenced_stop {uppercorner}} +\immutable\protected\def\Llowercorner {\math_fenced_fenced_start{lowercorner}} \immutable\protected\def\Rlowercorner {\math_fenced_fenced_stop {lowercorner}} +\immutable\protected\def\Lgroup {\math_fenced_fenced_start{group}} \immutable\protected\def\Rgroup {\math_fenced_fenced_stop {group}} +\immutable\protected\def\Lopenbracket {\math_fenced_fenced_start{openbracket}} \immutable\protected\def\Ropenbracket {\math_fenced_fenced_stop {openbracket}} +\immutable\protected\def\Lnothing {\math_fenced_fenced_start{nothing}} \immutable\protected\def\Rnothing {\math_fenced_fenced_stop {nothing}} + +\immutable\protected\def\Lparenthesismirrored {\math_fenced_fenced_stop {mirroredparenthesis}} \immutable\protected\def\Rparenthesismirrored {\math_fenced_fenced_start{mirroredparenthesis}} +\immutable\protected\def\Lbracketmirrored {\math_fenced_fenced_stop {mirroredbracket}} \immutable\protected\def\Rbracketmirrored {\math_fenced_fenced_start{mirroredbracket}} +\immutable\protected\def\Lbracemirrored {\math_fenced_fenced_stop {mirroredbrace}} \immutable\protected\def\Rbracemirrored {\math_fenced_fenced_start{mirroredbrace}} +\immutable\protected\def\Langlemirrored {\math_fenced_fenced_stop {mirroredangle}} \immutable\protected\def\Ranglemirrored {\math_fenced_fenced_start{mirroredangle}} +\immutable\protected\def\Ldoubleanglemirrored {\math_fenced_fenced_stop {mirroreddoubleangle}} \immutable\protected\def\Rdoubleanglemirrored {\math_fenced_fenced_start{mirroreddoubleangle}} +\immutable\protected\def\Lbarmirrored {\math_fenced_fenced_stop {mirroredbar}} \immutable\protected\def\Rbarmirrored {\math_fenced_fenced_start{mirroredbar}} +\immutable\protected\def\Ldoublebarmirrored {\math_fenced_fenced_stop {mirroreddoublebar}} \immutable\protected\def\Rdoublebarmirrored {\math_fenced_fenced_start{mirroreddoublebar}} +\immutable\protected\def\Ltriplebarmirrored {\math_fenced_fenced_stop {mirroredtriplebar}} \immutable\protected\def\Rtriplebarmirrored {\math_fenced_fenced_start{mirroredtriplebar}} +\immutable\protected\def\Lsolidusmirrored {\math_fenced_fenced_stop {mirroredsolidus}} \immutable\protected\def\Rsolidusmirrored {\math_fenced_fenced_start{mirroredsolidus}} +\immutable\protected\def\Lfloormirrored {\math_fenced_fenced_stop {mirroredfloor}} \immutable\protected\def\Rfloormirrored {\math_fenced_fenced_start{mirroredfloor}} +\immutable\protected\def\Lceilingmirrored {\math_fenced_fenced_stop {mirroredceiling}} \immutable\protected\def\Rceilingmirrored {\math_fenced_fenced_start{mirroredceiling}} +\immutable\protected\def\Lmoustachemirrored {\math_fenced_fenced_stop {mirroredmoustache}} \immutable\protected\def\Rmoustachemirrored {\math_fenced_fenced_start{mirroredmoustache}} +\immutable\protected\def\Luppercornermirrored {\math_fenced_fenced_stop {mirroreduppercorner}} \immutable\protected\def\Ruppercornermirrored {\math_fenced_fenced_start{mirroreduppercorner}} +\immutable\protected\def\Llowercornermirrored {\math_fenced_fenced_stop {mirroredlowercorner}} \immutable\protected\def\Rlowercornermirrored {\math_fenced_fenced_start{mirroredlowercorner}} +\immutable\protected\def\Lgroupmirrored {\math_fenced_fenced_stop {mirroredgroup}} \immutable\protected\def\Rgroupmirrored {\math_fenced_fenced_start{mirroredgroup}} +\immutable\protected\def\Lopenbracketmirrored {\math_fenced_fenced_stop {mirroredopenbracket}} \immutable\protected\def\Ropenbracketmirrored {\math_fenced_fenced_start{mirroredopenbracket}} +\immutable\protected\def\Lnothingmirrored {\math_fenced_fenced_stop {mirrorednothing}} \immutable\protected\def\Rnothingmirrored {\math_fenced_fenced_start{mirrorednothing}} + +\definemathfence [interval] [\c!left="2997,\c!right="2998] +\definemathfence [openinterval] [interval] [\c!left="2998,\c!right="2998] +\definemathfence [leftopeninterval] [interval] [\c!left="2997,\c!right="2997] +\definemathfence [rightopeninterval] [interval] [\c!left="2998,\c!right="2998] + +\immutable\protected\def\Linterval {\math_fenced_fenced_start{interval}} +\immutable\protected\def\Lointerval {\math_fenced_fenced_start{openinterval}} +\immutable\protected\def\Llointerval {\math_fenced_fenced_start{leftopeninterval}} +\immutable\protected\def\Lrointerval {\math_fenced_fenced_start{rightopeninterval}} + +\immutable\protected\def\Rinterval {\math_fenced_fenced_stop {interval}} +\immutable\protected\def\Rointerval {\math_fenced_fenced_stop {openinterval}} +\immutable\protected\def\Rlointerval {\math_fenced_fenced_stop {leftopeninterval}} +\immutable\protected\def\Rrointerval {\math_fenced_fenced_stop {rightopeninterval}} + +% \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 + +\popoverloadmode + +\installcorenamespace{mathleft} +\installcorenamespace{mathright} +\installcorenamespace{mathmiddle} + +\pushoverloadmode + +\protected\def\left {\afterassignment\math_left \let\nexttoken} +\protected\def\right {\afterassignment\math_right \let\nexttoken} +\protected\def\middle{\afterassignment\math_middle\let\nexttoken} + +\popoverloadmode + +\let\leftorright\relax + +\newconditional\c_math_fenced_done +\newconditional\c_math_fenced_unknown \settrue\c_math_fenced_unknown + +\protected\def\installmathfencepair#1#2#3#4% + {\letcsname\??mathleft \normalmeaning#1\endcsname#2% + \letcsname\??mathright\normalmeaning#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\normalmeaning\nexttoken\endcsname + \expandafter\lastnamedcs + \else + \expandafter\math_unknown_left + \fi} + +\def\math_right + {\settrue\c_math_fenced_done + \ifcsname\??mathright\normalmeaning\nexttoken\endcsname + \expandafter\lastnamedcs + \else + \expandafter\math_unknown_right + \fi} + +\def\math_middle + {\settrue\c_math_fenced_done + \ifcsname\??mathmiddle\normalmeaning\nexttoken\endcsname + \expandafter\lastnamedcs + \else + \expandafter\math_unknown_middle + \fi} + +\protected\def\lfence#1% + {\settrue\c_math_fenced_done + \let\nexttoken#1% + \ifcsname\??mathleft\normalmeaning\nexttoken\endcsname + \expandafter\lastnamedcs + \else + \expandafter\math_unknown_left + \fi} + +\protected\def\rfence#1% + {\settrue\c_math_fenced_done + \let\nexttoken#1% + \ifcsname\??mathright\normalmeaning\nexttoken\endcsname + \expandafter\lastnamedcs + \else + \expandafter\math_unknown_right + \fi} + +\protected\def\mfence#1% + {\settrue\c_math_fenced_done + \let\nexttoken#1% + \ifcsname\??mathmiddle\normalmeaning\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 ) \Rparenthesismirrored ( \Lparenthesismirrored + +\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 + +\installmathfencepair ⦗ \Linterval ⦘ \Rinterval + +\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): + +\pushoverloadmode + +\aliased\let\lbrack \lbracket +\aliased\let\rbrack \rbracket +\aliased\let\lceiling \lceil +\aliased\let\rceiling \rceil +\aliased\let\lparenthesis\lparent +\aliased\let\rparenthesis\rparent +\aliased\let\lparen \lparent +\aliased\let\rparen \rparent + +% Just defined: + +\aliased\let\Lceil \Lceiling +\aliased\let\Rceil \Rceiling +\aliased\let\Lparent\Lparenthesis +\aliased\let\Rparent\Rparenthesis +\aliased\let\Lparen \Lparenthesis +\aliased\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 + +\installmathfencepair \linterval \Linterval \rinterval \Rinterval +%installmathfencepair \linterv \Linterval \rinterv \Rinterval +\installmathfencepair \lointerval \Linterval \rointerval \Rinterval +\installmathfencepair \llointerval \Llointerval \rlointerval \Rlointerval +\installmathfencepair \lrointerval \Lrointerval \rrointerval \Rrointerval + +\aliased\let\textlbar\lbar \aliased\let\mathlbar\Lbar +\aliased\let\textrbar\lbar \aliased\let\mathrbar\Rbar + +\immutable\protected\def\lbar{\mathortext\mathlbar\textlbar} +\immutable\protected\def\rbar{\mathortext\mathrbar\textrbar} + +% \setupmathfences[color=darkgreen] + +\permanent\protected\def\{{\mathortext\lbrace \letterleftbrace } % or maybe a chardef +\permanent\protected\def\}{\mathortext\rbrace \letterrightbrace } % or maybe a chardef +\permanent\protected\def\[{\mathortext\lbracket \letterleftbracket } % or maybe a chardef +\permanent\protected\def\]{\mathortext\rbracket \letterrightbracket } % or maybe a chardef +\permanent\protected\def\({\mathortext\lparenthesis\letterleftparenthesis } % or maybe a chardef +\permanent\protected\def\){\mathortext\rparenthesis\letterrightparenthesis} % or maybe a chardef +\permanent\protected\def\|{\mathortext\vert \letterbar } % or maybe a chardef +%permanent\protected\def\/{\mathortext\solidus \letterslash } % or maybe a chardef + +\installmathfencepair \{ \Lbrace \} \Rbrace +\installmathfencepair \[ \Lbracket \] \Rbracket +\installmathfencepair \( \Lparenthesis \) \Rparenthesis +\installmathfencepair \< \Langle \> \Rangle +\installmathfencepair \| \Lbar \| \Rbar + +\popoverloadmode + +%D As we have overloaded \type {\left} and \type {\right} we also need a more +%D clever version of the following: + +% 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 + +\protected\def\plainbigdelimiters % traditional method + {\bigmathdelimitermethod\plustwo} + +\plainbigdelimiters % is default for the moment but not so nice + +% \setconstant\bigmathdelimitermethod\plusone + +\installcorenamespace{mathbig} + +\setvalue{\??mathbig1}{0.85} +\setvalue{\??mathbig2}{1.15} +\setvalue{\??mathbig3}{1.45} +\setvalue{\??mathbig4}{1.75} + +\protected\def\choosemathbig#1#2% so we accept \big{||} as well + {{\naturalhbox\bgroup + \startimath + \ifcase\bigmathdelimitermethod + \math_fenced_step#2\relax + \or + \math_fenced_force_size\bigmathdelimitervariant{#1}\relax + \math_fenced_step#2\relax + \else + \math_fenced_step#2{\vpack to\csname\??mathbig#1\endcsname\bodyfontsize{}}% + \fi + \nulldelimiterspace\zeropoint\relax + \mathsurround\zeropoint + \stopimath + \egroup}} + +% needs testing: +% +% \protected\def\choosemathbig#1#2% so we accept \big{||} as well +% {{\naturalhbox\bgroup +% \startimath +% \ifcase\bigmathdelimitermethod +% \Uvextensible#2\relax +% \or +% \math_fenced_force_size\bigmathdelimitervariant{#1}\relax +% \Uvextensible#2\relax +% \else +% \scratchdimen.5\dimexpr\csname\??mathbig\number#1\endcsname\bodyfontsize+1.1\exheight\relax +% \Uvextensible\s!axis \s!depth \scratchdimen \s!height \scratchdimen #2\relax +% \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} + +\protected\def\mathdelimiterstep#1#2% + {\begingroup + \math_fenced_force_size\plusone{#1}% + \math_fenced_step#2\relax + \endgroup} + +\definemathcommand [big] {\choosemathbig1} +\definemathcommand [Big] {\choosemathbig2} +\definemathcommand [bigg] {\choosemathbig3} +\definemathcommand [Bigg] {\choosemathbig4} + +\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] +% +% \protected\def\Lintegral {\math_fenced_fenced_start{integral}} +% \protected\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 The nested fences recovery code is needed for mathml and the original +%D code can still be found in the mkiv file. + +\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 + +\protected\def\math_fences_auto_left #1{\c_attr_mathautofence\plusone #1\c_attr_mathautofence\attributeunsetvalue} +\protected\def\math_fences_auto_right #1{\c_attr_mathautofence\plustwo #1\c_attr_mathautofence\attributeunsetvalue} +\protected\def\math_fences_auto_middle#1{\c_attr_mathautofence\plusthree#1\c_attr_mathautofence\attributeunsetvalue} +\protected\def\math_fences_auto_both #1{\c_attr_mathautofence\plusfour #1\c_attr_mathautofence\attributeunsetvalue} + +\permanent\let\autofenceopen \math_fences_auto_left % for testing +\permanent\let\autofenceclose \math_fences_auto_right % for testing +\permanent\let\autofenceleft \math_fences_auto_left % for testing +\permanent\let\autofenceright \math_fences_auto_right % for testing +\permanent\let\autofencemiddle\math_fences_auto_middle % for testing +\permanent\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 + +\protected\def\enableautofences + {\clf_enableautofences + \glet\clf_enableautofences\relax % onlyonce anyway + \protected\gdef\enableautofences{\settrue\c_math_fences_auto}% + \enableautofences} + +\protected\def\disableautofences + {\setfalse\c_math_fences_auto} + +\protected\def\math_fences_used_left + {\ifconditional\c_math_fences_auto + \expandafter\math_fences_auto_left + \else + \expandafter\math_fences_normal_left + \fi} + +\protected\def\math_fences_used_right + {\ifconditional\c_math_fences_auto + \expandafter\math_fences_auto_right + \else + \expandafter\math_fences_normal_right + \fi} + +\protected\def\math_fences_used_middle + {\ifconditional\c_math_fences_auto + \expandafter\math_fences_auto_middle + \else + \expandafter\math_fences_normal_middle + \fi} + +\protected\def\math_fences_used_both + {\ifconditional\c_math_fences_auto + \expandafter\math_fences_auto_both + \else + \expandafter\math_fences_normal_both + \fi} + +\permanent\let\left \math_fences_used_left +\permanent\let\right \math_fences_used_right +\permanent\let\middle \math_fences_used_middle +\permanent\let\leftorright\math_fences_used_both + +% wrappers + +\permanent\protected\def\startcheckedfences + {\begingroup + \enableautofences} + +\permanent\protected\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 + \ifempty\currentmathfence + \doifelse{\mathfenceparameter\c!state}\v!auto\enableautofences\disableautofences + \fi +\to \everysetupmathfence + +\newconstant\c_math_fences_delimiters_mode \c_math_fences_delimiters_mode"16 % \numexpr"02+"04+"10\relax + +%protected\def\enableautofencemode {\mathdelimitersmode\plussix} % the shift (1) is too fragile +\protected\def\enableautofencemode {\mathdelimitersmode\c_math_fences_delimiters_mode} + +\protected\def\disableautofencemode{\mathdelimitersmode\zerocount} + +\appendtoks + \ifempty\currentmathfence + \doifelse{\mathfenceparameter\c!method}\v!auto\enableautofencemode\disableautofencemode + \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. + +\immutable\Umathchardef\braceld\zerocount \defaultmathfamily "FF07A +\immutable\Umathchardef\bracerd\zerocount \defaultmathfamily "FF07B +\immutable\Umathchardef\bracelu\zerocount \defaultmathfamily "FF07C +\immutable\Umathchardef\braceru\zerocount \defaultmathfamily "FF07D + +\protect diff --git a/tex/context/base/mkxl/math-for.mkxl b/tex/context/base/mkxl/math-for.mkxl new file mode 100644 index 000000000..e6ea402de --- /dev/null +++ b/tex/context/base/mkxl/math-for.mkxl @@ -0,0 +1,47 @@ +%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,setupformulaframed} + +\installcorenamespace{formula} +\installcorenamespace{subformula} +\installcorenamespace{formulaframed} +\installcorenamespace{formulaoption} + +\installcommandhandler \??formula {formula} \??formula +\installcommandhandler \??subformula {subformula} \??subformula % maybe just setuphandler (no childs used yet) +\installframedcommandhandler \??formulaframed {formulaframed} \??formulaframed + +\aliased\let\setupformulas \setupformula +\aliased\let\setupsubformulas\setupsubformula + +\appendtoks + \normalexpanded{\defineformulaframed[\currentformula][\currentformulaparent]}% +\to \everydefineformula + +\def\strc_formulas_option#1% + {\ifcsname\??formulaoption#1\endcsname + \lastnamedcs + \else + \font_basics_switchtobodyfont{#1}% for old time sake, might go away, only pt so maybe dimension and small test + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/math-frc.mkxl b/tex/context/base/mkxl/math-frc.mkxl new file mode 100644 index 000000000..b232868cd --- /dev/null +++ b/tex/context/base/mkxl/math-frc.mkxl @@ -0,0 +1,833 @@ +%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. + +\permanent\protected\def\topstrut{\vrule\s!width\zeropoint\s!height\strutht\s!depth\zeropoint\relax} +\permanent\protected\def\botstrut{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp\relax} + +\permanent\protected\def\mathtopstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\ht\scratchbox\s!depth\zeropoint\relax} +\permanent\protected\def\mathbotstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\dp\scratchbox\relax} + +%D This module is reimplemented in \MKIV\ style. + +\registerctxluafile{math-frc}{} + +%D \macros +%D {frac, xfrac, xxfrac} +%D +%D This is another one Tobias asked for. It replaces the primitive \type +%D {\over}. We also take the opportunity to handle math style restoring, +%D which makes sure units and chemicals come out ok. The \type {\frac} +%D macro kind of replaces the awkward \type {\over} primitive. Say that +%D we have the following formulas: +%D +%D \startbuffer[sample] +%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$ +%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$ +%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$ +%D \stopbuffer +%D +%D \typebuffer[sample] +%D +%D With the most straightforward definitions, we get: +%D +%D \startbuffer[code] +%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}} +%D +%D \def\frac {\dofrac\mathstyle} +%D \def\xfrac {\dofrac\scriptstyle} +%D \def\xxfrac{\dofrac\scriptscriptstyle} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D Since this does not work well, we can try: +%D +%D \startbuffer[code] +%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}} +%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D This for sure looks better than: +%D +%D \startbuffer[code] +%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}} +%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D So we stick to the next definitions (watch the local overloading of +%D \type {\xfrac}). +%D +%D In the meantime, in \LUATEX, we have better control over styles so the +%D following macros are different from the \MKII\ ones. + +% obsolete, is now c!mathstyle +% +% 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle +% +% $\mathfracmode0 \frac{1}{2}$ +% $\mathfracmode1 \frac{1}{2}$ +% $\mathfracmode2 \frac{1}{2}$ +% $\mathfracmode3 \frac{1}{2}$ +% $\mathfracmode4 \frac{1}{2}$ +% $\mathfracmode5 \frac{1}{2}$ +% +% we keep the constant for a while + +\setnewconstant\mathfracmode\zerocount + +\installcorenamespace{mathfractions} +\installcorenamespace{mathfractionstyle} +\installcorenamespace{mathfractionalternative} + +\installcommandhandler \??mathfractions {mathfraction} \??mathfractions + +\aliased\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 + \instance\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 + +\protected\def\math_fraction_set_distance_top + {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top + \relax} + +\protected\def\math_fraction_set_distance_bot + {\Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot + \relax} + +\protected\def\math_fraction_set_distance_all + {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top + \Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot + \relax} + +\appendtoks + \ifempty\currentmathfraction + \edef\m_math_fraction_distance_top{\mathfractionparameter\c!topdistance}% + \edef\m_math_fraction_distance_bot{\mathfractionparameter\c!bottomdistance}% + \ifempty\m_math_fraction_distance_top + \ifempty\m_math_fraction_distance_bot + \let\math_fraction_set_distance\relax + \else + \let\math_fraction_set_distance\math_fraction_set_distance_bot + \fi + \else + \ifempty\m_math_fraction_distance_bot + \let\math_fraction_set_distance\math_fraction_set_distance_top + \else + \let\math_fraction_set_distance\math_fraction_set_distance_all + \fi + \fi + \fi +\to \everysetupmathfraction + +% So far for control. + +\installcorenamespace{mathfractionstrut} + +\def\math_frac_no_strut + {\enforced\let\m_fractions_strut_top\relax + \enforced\let\m_fractions_strut_bot\relax} + +\setvalue{\??mathfractionstrut\v!yes}% + {\enforced\let\m_fractions_strut_top\mathstrut + \enforced\let\m_fractions_strut_bot\mathstrut} + +\setvalue{\??mathfractionstrut\v!math}% + {\enforced\let\m_fractions_strut_top\mathstrut + \enforced\let\m_fractions_strut_bot\mathstrut} + +\letvalue{\??mathfractionstrut\v!no}\math_frac_no_strut + +\setvalue{\??mathfractionstrut\v!tight}% + {\enforced\let\m_fractions_strut_top\mathbotstrut % indeed swapped name + \enforced\let\m_fractions_strut_bot\mathtopstrut} % indeed swapped name + +\math_frac_no_strut + +\newdimen\d_math_fraction_margin + +\protected\def\math_frac#1% + {\begingroup + \edef\currentmathfraction{#1}% + % + \edef\p_math_fraction_fences{\mathfractionparameter\c!fences}% + \ifempty\p_math_fraction_fences \else + \math_fenced_fenced_start\p_math_fraction_fences + \fi + % + \d_math_fraction_margin\mathfractionparameter\c!margin + % + \edef\p_math_fractions_color{\mathfractionparameter\c!color}% + % + \edef\p_math_fractions_strut{\mathfractionparameter\c!strut}% + \ifcsname\??mathfractionstrut\p_math_fractions_strut\endcsname + \lastnamedcs + \else + \math_frac_no_strut + \fi + % + \ifempty\p_math_fractions_color + \expandafter\math_frac_normal + \else + \expandafter\math_frac_colored + \fi} + +\protected\def\math_frac_wrapup + {\ifempty\p_math_fraction_fences \else + \math_fenced_fenced_stop\p_math_fraction_fences + \fi + \endgroup} + +\protected\def\math_frac_colored#1#2% + {\savecolor + \colo_helpers_activate\p_math_fractions_color + \math_frac_normal{\restorecolor#1}{\restorecolor#2}} + +\protected\def\math_frac_normal + {\expandnamespaceparameter\??mathfractionalternative\mathfractionparameter\c!alternative\v!inner} + +% we use utfchar anyway so we can as well do all at the lua end + +\def\math_frac_no_delim{0x2E} + +\def\math_frac_command + {\clf_mathfraction + {\mathfractionparameter\c!rule}% + \ifempty\p_math_fraction_fences + \mathfractionparameter\c!left \space + \mathfractionparameter\c!right\space + \else + \math_frac_no_delim\space + \math_frac_no_delim\space + \fi + \dimexpr\mathfractionparameter\c!rulethickness\relax + \relax} + +% Having a \withmarginornot{#1}{#2} makes not much sense nor do 4 tests or 4 redundant +% kerns (longer node lists plus possible interference). A split in normal and margin +% also makes testing easier. When left and right margins are needed we might merge the +% variants again. After all, these are not real installers. + +% the denominator is in cramped! + +\setvalue{\??mathfractionalternative\v!inner}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_inner_normal + \else + \expandafter\math_fraction_inner_margin + \fi} + +\setvalue{\??mathfractionalternative\v!outer}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_outer_normal + \else + \expandafter\math_fraction_outer_margin + \fi} + +\setvalue{\??mathfractionalternative\v!both}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_both_normal + \else + \expandafter\math_fraction_both_margin + \fi} + +% todo: store first state and reuse second time + +% \def\math_fraction_inner_normal#1#2% +% {\Ustack{% +% {% +% {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}% +% \math_frac_command +% {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}% +% }% +% }% +% \math_frac_wrapup} +% +% \def\math_fraction_outer_normal#1#2% +% {\Ustack{% +% \usemathstyleparameter\mathfractionparameter +% {% +% {\m_fractions_strut_top#1}% +% \math_frac_command +% {\m_fractions_strut_bot#2}% +% }% +% }% +% \math_frac_wrapup} +% +% \def\math_fraction_both_normal#1#2% +% {\Ustack{% +% \usemathstyleparameter\mathfractionparameter +% {% +% {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}% +% \math_frac_command +% {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}% +% }% +% }% +% \math_frac_wrapup} +% +% \def\math_fraction_inner_margin#1#2% +% {\Ustack{% +% {% +% {\kern\d_math_fraction_margin +% \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}% +% \kern\d_math_fraction_margin}% +% \math_frac_command +% {\kern\d_math_fraction_margin +% \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}% +% \kern\d_math_fraction_margin}% +% }% +% }% +% \math_frac_wrapup} +% +% \def\math_fraction_outer_margin#1#2% +% {\Ustack{% +% \usemathstyleparameter\mathfractionparameter +% {% +% {\kern\d_math_fraction_margin +% \m_fractions_strut_top#1% +% \kern\d_math_fraction_margin}% +% \math_frac_command +% {\kern\d_math_fraction_margin +% \m_fractions_strut_bot#2% +% \kern\d_math_fraction_margin}% +% }% +% }% +% \math_frac_wrapup} +% +% \def\math_fraction_both_margin#1#2% +% {\Ustack{% +% \usemathstyleparameter\mathfractionparameter +% {% +% {\kern\d_math_fraction_margin +% \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1% +% \kern\d_math_fraction_margin}% +% \math_frac_command +% {\kern\d_math_fraction_margin +% \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2% +% \kern\d_math_fraction_margin}% +% }% +% }% +% \math_frac_wrapup} + +\def\math_frac_command_u + {\clf_umathfraction + {\mathfractionparameter\c!rule}% + \ifx\p_math_fraction_fences\empty + \mathfractionparameter\c!left \space + \mathfractionparameter\c!right\space + \else + \math_frac_no_delim\space + \math_frac_no_delim\space + \fi + \dimexpr\mathfractionparameter\c!rulethickness\relax + \relax} + +\def\math_fraction_inner_normal#1#2% + {\Ustack{% forces num style + \math_frac_command_u + {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}% + {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}% + }% + \math_frac_wrapup} + +\def\math_fraction_outer_normal#1#2% + {\Ustack{% forces num style + \usemathstyleparameter\mathfractionparameter + \math_frac_command_u + {\m_fractions_strut_top#1}% + {\m_fractions_strut_bot#2}% + }% + \math_frac_wrapup} + +\def\math_fraction_both_normal#1#2% + {\Ustack{% forces num style + \usemathstyleparameter\mathfractionparameter + \math_frac_command_u + {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}% + {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}% + }% + \math_frac_wrapup} + +\def\math_fraction_inner_margin#1#2% + {\Ustack{% + {% + \math_frac_command_u + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}% + \kern\d_math_fraction_margin}% + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_outer_margin#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + \math_frac_command_u + {\kern\d_math_fraction_margin + \m_fractions_strut_top#1% + \kern\d_math_fraction_margin}% + {\kern\d_math_fraction_margin + \m_fractions_strut_bot#2% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_both_margin#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + \math_frac_command_u + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1% + \kern\d_math_fraction_margin}% + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\definemathfraction[xfrac] [\c!alternative=\v!inner,\c!mathstyle=\s!script] +\definemathfraction[xxfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] + +\let\normalxfrac\xfrac + +\protected\def\xfrac#1#2{\normalxfrac{\let\xfrac\xxfrac#1}{\let\xfrac\xxfrac#2}} + +%D Spacing (sensitive for definition of \triggermathstyle: + +% \ifcase\contextlmtxmode + +\permanent\protected\def\nomathfractiongaps {\normalexpanded{\math_no_fraction_gaps \mathstyletrigger\mathstyle}} % maybe collect settings +\permanent\protected\def\overlaymathfractiongaps{\normalexpanded{\math_overlay_fraction_gaps\mathstyletrigger\mathstyle}} % maybe collect settings + +\protected\def\math_no_fraction_gaps#1% + {\Umathfractionnumup #1\zeropoint + \Umathfractiondenomdown#1\zeropoint} + +\protected\def\math_overlay_fraction_gaps#1% + {\Umathfractionnumup #1\zeropoint + \Umathfractionnumvgap #1\zeropoint + %Umathfractionrule #1\zeropoint + \Umathfractiondenomvgap#1\zeropoint + \Umathfractiondenomdown#1\zeropoint} + +% \else + +% \protected\def\math_no_fraction_gaps +% {\Umathfractionnumup \mathstyle\zeropoint +% \Umathfractiondenomdown\mathstyle\zeropoint} +% +% \protected\def\math_overlay_fraction_gaps +% {\Umathfractionnumup \mathstyle\zeropoint +% \Umathfractionnumvgap \mathstyle\zeropoint +% %Umathfractionrule \mathstyle\zeropoint +% \Umathfractiondenomvgap\mathstyle\zeropoint +% \Umathfractiondenomdown\mathstyle\zeropoint} + +% \fi + +\installcorenamespace{mathfractiondistance} + +\letvalue{\??mathfractiondistance\v!none }\nomathfractiongaps +\letvalue{\??mathfractiondistance\v!no }\nomathfractiongaps +\letvalue{\??mathfractiondistance\v!overlay}\overlaymathfractiongaps + +\setupmathfractions + [\c!distance=\v!none] + +\appendtoks + \edef\p_distance{\rootmathfractionparameter\c!distance}% + \ifempty\p_distance\else + \ifcsname\??mathfractiondistance\p_distance\endcsname + \lastnamedcs + \fi + \fi +\to \everymathematics + +% theshold is new! + +\let\math_fraction_set_threshold_inline \relax +\let\math_fraction_set_threshold_display\relax + +\appendtoks + \math_fraction_set_threshold_inline + \math_fraction_set_threshold_display +\to \everymathematics + +\appendtoks + \ifempty\currentmathfraction + \edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% + \ifempty\p_threshold + \let\math_fraction_set_threshold_inline\relax + \orelse\ifx\p_threshold\v!auto + \let\math_fraction_set_threshold_inline\relax + \else + \let\math_fraction_set_threshold_inline\math_fraction_set_theshold_inline + \fi + \edef\p_threshold{\mathfractionparameter\c!displaythreshold}% + \ifempty\p_threshold + \let\math_fraction_set_threshold_display\relax + \orelse\ifx\p_threshold\v!auto + \let\math_fraction_set_threshold_display\relax + \else + \let\math_fraction_set_threshold_display\math_fraction_set_theshold_display + \fi + \fi +\to \everysetupmathfraction + +\def\math_fraction_set_theshold_inline + {\edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% + \Umathfractiondelsize\textstyle \p_threshold\dimexpr\textface\relax + \Umathfractiondelsize\scriptstyle \p_threshold\dimexpr\scriptface\relax + \Umathfractiondelsize\scriptscriptstyle\p_threshold\dimexpr\scriptscriptface\relax} + +\def\math_fraction_set_theshold_display + {\edef\p_threshold{\mathfractionparameter\c!displaythreshold}% + \Umathfractiondelsize\displaystyle \p_threshold\dimexpr\textface\relax} + +%D \macros +%D {dfrac, tfrac, frac, dbinom, tbinom, binom} +%D +%D \startbuffer +%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$ +%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$ +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer + +% $$ +% {{a}\over{b}} + +% {{a}\overwithdelims(){b}} + +% {{a}\atopwithdelims(){b}} + +% {{a}\abovewithdelims()\zeropoint{b}} + +% \left({{a}\over{b}}\right) +% $$ + +% \dorecurse {10} { % weird +% $$ {{a}\abovewithdelims()#1pt{b}} $$ +% } + +\definemathfraction[i:frac] [\c!alternative=\v!inner,\c!mathstyle=] % was script and then small but nothing needed +\definemathfraction[i:tfrac][\c!alternative=\v!inner,\c!mathstyle=\s!text] % was script (before luatex fix) +\definemathfraction[i:sfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] +\definemathfraction[i:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] + +\definemathfraction[d:frac] [\c!alternative=\v!inner,\c!mathstyle=\s!cramped] % was cramped,text +\definemathfraction[d:tfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!text}] % was cramped,script (before luatex fix) +\definemathfraction[d:sfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!scriptscript}] +\definemathfraction[d:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] + +%D \protected\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 + +\permanent\protected\def\frac {\csname\inlineordisplaymath id:frac\endcsname} +\permanent\protected\def\tfrac{\csname\inlineordisplaymath id:tfrac\endcsname} +\permanent\protected\def\sfrac{\csname\inlineordisplaymath id:sfrac\endcsname} +\permanent\protected\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}] + +\permanent\protected\def\ctxfrac{\csname\inlineordisplaymath id:frac\endcsname} +\permanent\protected\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}% + {\enforced\let\frac\amsfrac}% + {\enforced\let\frac\ctxfrac}% +\to \everysetupmathematics + +% \definemathfraction[ddfrac][\c!mathstyle=\s!display] +% \definemathfraction[ttfrac][\c!mathstyle=\s!text] +% \definemathfraction[ssfrac][\c!mathstyle=\s!script] + +% \protected\def\binom #1#2{{\Ustack {{#1}\normalabovewithdelims()\zeropoint{#2}}}} +% \protected\def\dbinom#1#2{{\displaystyle{{#1}\normalabovewithdelims()\zeropoint{#2}}}} +% \protected\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}} + +\definemathfraction + [binom] + [\c!alternative=\v!outer, + \c!rule=\v!no, + \c!left=0x28, + \c!right=0x29, + \c!mathstyle=\s!auto] + +\definemathfraction + [dbinom] + [binom] + [\c!mathstyle=\s!display] + +\definemathfraction + [tbinom] + [binom] + [\c!mathstyle=\s!text] + +%D \macros +%D {cfrac} +%D +%D \startbuffer +%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ +%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D Now we can align every combination we want: +%D +%D \startbuffer +%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ +%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ +%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$ +%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$ +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer + +\permanent\protected\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. + +\protected\def\splitfrac #1#2{{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}} +\protected\def\splitdfrac#1#2{{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}} + +%D For testing: + +% \protected\def\ShowMathFractions#1#2% +% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}} + +%D More fracking (for Alan): + +\protected\def\math_frac_colored_vulgar#1#2% + {\savecolor + \colo_helpers_activate\p_math_fractions_color + {\restorecolor#1}\Uskewed/{\restorecolor#2}} + +\protected\def\math_frac_normal_vulgar#1#2% + {{#1}\Uskewed/{#2}} + +\permanent\protected\def\vfrac#1#2% + {\bgroup + \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}% + \ifempty\p_math_fractions_color + \expandafter\math_frac_normal_vulgar + \else + \expandafter\math_frac_colored_vulgar + \fi + {#1}% + {#2}% + \egroup} + +\appendtoks + \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}% + \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}% + \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle + \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle + \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle + \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle + \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle + \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle +\to \everysetupmathfraction + +\setupmathfraction + [\s!vfrac] + [\c!hfactor=.2, + \c!vfactor=.1] + +\protect \endinput + +% I have no clue what \mthfrac and \mthsqrt are supposed to do but +% I guess that it can be done with tweaking luatex's math parameters. +% Otherwise I'll write something from scratch. + +% \def\math_stylebuilders_frac#1#2#3#4#5#6#7% +% {\begingroup +% \mathsurround\zeropoint +% \setbox0\hbox{$#1 #6$}% +% \setbox2\hbox{$#1 #7$}% +% \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi +% \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}% +% \mathord{\vcenter{{\offinterlineskip +% \hbox to \dimen0{\hss\box0\hss}% +% \kern\ht4% +% \hbox to \dimen0{\hss\copy4\hss}% +% \kern\ht4% +% \hbox to \dimen0{\hss\box2\hss}}}}% +% \endgroup} +% +% \def\math_stylebuilders_sqrt#1#2#3#4#5% +% {\begingroup +% \mathsurround\zeropoint +% \setbox0\hbox{$#1 #5$}% +% \ht0\dimexpr1.05\ht0+\onepoint\relax +% \dp0\dimexpr1.05\dp0+\onepoint\relax +% \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}% +% \delimitershortfall\zeropoint +% \nulldelimiterspace\zeropoint +% \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point? +% \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}% +% \endgroup} +% +% \def\mthfrac#1#2#3#4#5{\mathchoice +% {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}} +% +% \def\mthsqrt#1#2#3{\mathchoice +% {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}} + +% \protected\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]} +% \protected\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]} + +% used for prototyping \Uskewed +% +% \protected\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 +% } +% +% \protected\def\skewedfractionb#1#2{% +% \raise +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax$% +% \egroup +% \hbox to \zeropoint\bgroup +% \hss$\textstyle/$\hss +% \egroup +% \lower +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax\scriptstyle#2$% +% \egroup +% } +% +% $\skewedfractiona{1}{2}$ +% $\skewedfractionb{1}{2}$ diff --git a/tex/context/base/mkxl/math-inc.mkxl b/tex/context/base/mkxl/math-inc.mkxl new file mode 100644 index 000000000..c23684fd3 --- /dev/null +++ b/tex/context/base/mkxl/math-inc.mkxl @@ -0,0 +1,69 @@ +%D \module +%D [ file=math-inc, +%D version=2018.06.23, +%D title=\CONTEXT\ Math Macros, +%D subtitle=XML inclusion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Math Macros / XML inclusion} + +\registerctxluafile{math-inc}{} + +%D I had some doubt about including this in \CONTEXT\ but it might serve some users +%D anyway. It's always the question to what extent one can be really roundtrip. I +%D might improve it when I need it. + +% Talking about creating from a source ... June Lee's transcription of +% Close to You by Jacob Collier is an amazing example: +% +% https://www.youtube.com/watch?v=hdBVN-HMuqI + +\unprotect + +\definesymbol[mmlattachment][{\infofont\darkred mml}] +\definesymbol[mmlcomment] [{\infofont\darkblue mml}] + +\permanent\protected\def\lxml_add_mml_blob#1#2% + {\relax + \clf_xmlformulatobuffer\number\c_strc_formulas_n{temp-xml-export}% + #2% + [\c!symbol=#1,% + \c!space=\v!yes,% + \c!buffer=temp-xml-export,% + \c!name={formula-\number\c_strc_formulas_n.xml}]% + \relax} + +\permanent\protected\def\xmlattachmml + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \lxml_add_mml_blob{mmlattachment}\attachment + \dostoptagged + \fi \fi \fi} + +\permanent\protected\def\xmlcommentmml + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \lxml_add_mml_blob{mmlcomment}\comment + \dostoptagged + \fi \fi \fi} + +%D This kind of feature creep is not yet configurable, nor documented. + +\permanent\protected\def\xmladdmmlsource + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \inleftmargin{% + \lxml_add_mml_blob{mmlattachment}\attachment + \quad + \lxml_add_mml_blob{mmlcomment}\comment + }% + \dostoptagged + \fi \fi \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl new file mode 100644 index 000000000..7838d8fde --- /dev/null +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -0,0 +1,3006 @@ +%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 + +% a bit tricky way to set ... no (pseudo) registers but math hash values: +% +% \normalexpanded{\Umathlimitabovevgap\displaystyle=40\dimexpr\the\Umathlimitabovevgap\displaystyle\relax} + +% 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 +% +% \protected\def\Umathshow#1% +% {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}} + +%D This module provides namespaces for math fonts, thereby permitting mixed usage of +%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}{} +\registerctxluafile{math-dim}{} +\registerctxluafile{math-act}{} +\registerctxluafile{math-ext}{} +\registerctxluafile{math-vfu}{} +\registerctxluafile{math-ttv}{} +\registerctxluafile{math-map}{optimize} +\registerctxluafile{math-ren}{} +\registerctxluafile{math-noa}{autosuffix,optimize} +\registerctxluafile{math-tag}{autosuffix} +\registerctxluafile{math-fbk}{} +\registerctxluafile{math-dir}{} +\registerctxluafile{math-spa}{} + +%D A starter: +%D +%D \startbuffer +%D \mathsurround 10pt +%D \mathsurroundskip30pt +%D x $x + \ruledhbox{$x$} + x$ x +%D \stopbuffer +%D +%D \typebuffer +%D +%D \start \blank \getbuffer \blank \stop + +\newcount\mathnestinglevel + +\appendtoks + \advance\mathnestinglevel\plusone +\to \everymathematics + +%D A few compatibility helpers: + +\permanent\def\Umathbotaccent{\Umathaccent \s!bottom } +\permanent\def\Umathtopaccent{\Umathaccent \s!top } +\permanent\def\Umathaccents {\Umathaccent \s!both } % strange highlighting + +\ifdefined\Umathcharclass \else + \permanent\def\Umathcharclass{\numexpr\cldcontext{tex.getmathcode(token.scan_int())[1]}\relax} + \permanent\def\Umathcharfam {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[2]}\relax} + \permanent\def\Umathcharslot {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[3]}\relax} +\fi + +%D The attributes that we will use (todo: pack some into one but uglier code): + +\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[mathkernpairs] [public] +\definesystemattribute[mathbidi] [public] +\definesystemattribute[mathdomain] [public] +\definesystemattribute[mathcollapsing] [public] +\definesystemattribute[mathunstack] [public] + +\definesystemattribute[displaymath] [public] + +\mathflattenmode 31 + +\ifdefined\ordlimits\else + \let\ordlimits\limits +\fi + +\appendtoks + \c_attr_mathmode\plusone +\to \everydisplay + +\appendtoks + \c_attr_mathmode \plusone + \c_attr_displaymath\plusone +\to \everybeforedisplayformula + +\defaultmathfamily \zerocount % 255 + +\permanent\protected\def\resetmathattributes{\clf_resetmathattributes} + +% handy + +\newconditional\indisplaymath + +\appendtoks + \setfalse\indisplaymath +\to \everymath + +\appendtoks + \settrue\indisplaymath +\to \everydisplay + +\permanent\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} + +\permanent\protected\def\forcedisplaymath + {\ifmmode + \displaystyle + \settrue\indisplaymath + \fi} + +\permanent\protected\def\startforceddisplaymath + {\startimath + \displaystyle + \begingroup + \settrue\indisplaymath} + +\permanent\protected\def\stopforceddisplaymath + {\endgroup + \stopimath} + +\permanent\protected\def\startpickupmath % for the moment private + {\ifconditional\indisplaymath + \startforceddisplaymath + \let\stoppickupmath\stopforceddisplaymath + \else + \startimath + \let\stoppickupmath\stopimath + \fi} + +\let\stoppickupmath\relax + +% \protected\def\rawmathcharacter#1% slow but only for tracing +% {\begingroup +% \ifmmode +% \resetmathattributes\Uchar#1% +% \else +% \startimath\resetmathattributes\Uchar#1\stopimath +% \fi +% \endgroup} + +\permanent\protected\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 + +\permanent\protected\def\startmathematics % no grouping, if ever then also an optional second + {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop} + +\installmacrostack\currentmathematics + +\protected\def\math_mathematics_start_yes[#1]% + {\push_macro_currentmathematics + \edef\currentmathematics{#1}% check for valid + \the\everyswitchmathematics} + +\protected\def\math_mathematics_start_nop + {\push_macro_currentmathematics + \let\currentmathematics\empty + \the\everyswitchmathematics} + +\permanent\protected\def\stopmathematics + {\pop_macro_currentmathematics + \the\everyswitchmathematics} + +\definemathematics[\v!default] % not needed, but nicer when nesting back to normal + +% Now we redefine \type {\mathematics} and \type {\m}: + +\pushoverloadmode + + \permanent\protected\def\mathematics{\doifelsenextoptionalcs\math_m_yes\math_m_nop} + + \aliased\let\m \mathematics % we keep the simple versions + \aliased\let\math\mathematics % we keep the simple versions + +\popoverloadmode + +\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 + \ifcondition\validassignment{#1}% + \setupcurrentmathematics[#1]% + \else + \edef\currentmathematics{#1}% check for valid + \fi + \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 + \the\everyswitchmathematics\relax + \normalstartimath + #1% + \normalstopimath + \egroup + \ifdim\ht\scratchbox>\strutht + \math_inline_openup_start_yes + \orelse\ifdim\dp\scratchbox>\strutdp + \math_inline_openup_start_yes + \else + \math_inline_openup_start_nop + \fi + \unhbox\scratchbox % \normalstartimath#1\normalstopimath + \math_inline_openup_stop + \endgroup} + +\def\math_m_yes_text_normal#1% + {\the\everyswitchmathematics\relax + \normalstartimath + #1% + \normalstopimath + \endgroup} + +\def\math_m_nop#1% + {\relax + \ifmmode + #1% + \else + \normalstartimath + #1% + \normalstopimath + \fi} + +% 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 +\newcount \defaultprerelpenalty \defaultprerelpenalty -100 +\newcount \defaultprebinoppenalty \defaultprebinoppenalty -100 + +% we need to control these otherwise: +% +% \prerelpenalty \defaultprerelpenalty +% \prebinoppenalty\defaultprebinoppenalty + +\startsetups math:spacing:default + \thickmuskip \defaultthickmuskip + \medmuskip \defaultmedmuskip + \thinmuskip \defaultthinmuskip + \relpenalty \defaultrelpenalty + \binoppenalty \defaultbinoppenalty + \prebinoppenalty\maxdimen + \prerelpenalty \maxdimen +\stopsetups + +\startsetups math:spacing:split + \thickmuskip \defaultthickmuskip + \medmuskip \defaultmedmuskip + \thinmuskip \defaultthinmuskip + \relpenalty \defaultrelpenalty + \binoppenalty \defaultbinoppenalty + \prebinoppenalty\defaultprebinoppenalty + \prerelpenalty \defaultprerelpenalty +\stopsetups + +\startsetups math:spacing:half + \thickmuskip \halfthickmuskip + \medmuskip \halfmedmuskip + \thinmuskip \halfthinmuskip + \relpenalty \defaultrelpenalty + \binoppenalty \defaultbinoppenalty + \prebinoppenalty\maxdimen + \prerelpenalty \maxdimen +\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 + \prebinoppenalty\maxdimen + \prerelpenalty \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 + \prebinoppenalty\maxdimen + \prerelpenalty \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) + +\protected\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi} +\protected\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi} +\protected\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi} +\protected\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi} + +\installcorenamespace{mathstylealternative} % might become a setuphandler + +\protected\def\math_set_font_style_alternate#1% + {\ifcsname\??mathstylealternative\fontclass:#1\endcsname + \expandafter\math_set_font_alternate\lastnamedcs + \orelse\ifcsname\??mathstylealternative#1\endcsname + \expandafter\math_set_font_alternate\lastnamedcs + \fi} + +\permanent\tolerant\protected\def\setupmathrendering[#1]#*[#2]% the name might change + {\ifparameter#2\or + \getparameters[\??mathstylealternative#1:][#2]% + \else + \getparameters[\??mathstylealternative][#1]% + \fi} + +\appendtoks + \edef\p_stylealternative{\mathematicsparameter\c!stylealternative}% + \ifempty\p_stylealternative\else + \clf_presetmathalternate\defaultmathfamily{\p_stylealternative}% + \fi +\to \everymathematics + +% 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 + +% \enabletrackers[math.alternates] +% \setupbodyfont[lucidaot] +% +% \startTEXpage +% \setupmathematics[stylealternative={reset}]$x+\mathcal A$\par +% \setupmathematics[stylealternative={reset,calligraphic}]$x+\mathcal A$\par +% \setupmathematics[stylealternative={reset,italic}]$x+\mathcal A$\par +% \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$ +% \stopTEXpage + +% no longer needed now we have enforce so the next few lines will go + +\pushoverloadmode + \enforced\let\dotlessi\dotlessi + \enforced\let\dotlessj\dotlessj +\popoverloadmode + +\permanent\protected\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file +\permanent\protected\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file +\permanent\protected\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic +\permanent\protected\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic +\permanent\protected\def\mathdotlessi {\begingroup\mathdotless i\endgroup} +\permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup} + +\aliased\let\mathaltcal\mathaltcalligraphic +\aliased\let\mathaltit \mathaltitalic + +%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero} +\aliased\let\textdotlessi \dotlessi \permanent\protected\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi} +\aliased\let\textdotlessj \dotlessj \permanent\protected\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj} + +\appendtoks + %enforced\let\slashedzero\autoslashedzero + \enforced\let\dotlessi\autodotlessi + \enforced\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\setmathfontalternative \math_set_font_alternate +\let\setmathfontstylealternate \math_set_font_style_alternate +\let\setmathfontstylealternative\math_set_font_style_alternate + +\let\mathalternate \math_set_font_alternate + +\permanent\protected\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf} +\permanent\protected\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it} +\permanent\protected\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script} +\permanent\protected\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur} +\permanent\protected\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\s!blackboard} + +\permanent\protected\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf} +\permanent\protected\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf} +\permanent\protected\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\s!tf} + +\permanent\protected\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf} +\permanent\protected\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl +\permanent\protected\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} + +\permanent\protected\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf} +\permanent\protected\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl +\permanent\protected\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} + +\let\mathdefault\mathitalic + +\appendtoks + \edef\p_default{\mathematicsparameter\c!default}% + \ifx\p_default\v!normal + \enforced\let\mathdefault\mathupright + \else + \enforced\let\mathdefault\mathitalic + \fi +\to \everysetupmathematics + +\setupmathematics + [\c!default=\v!italic] + +\aliased\let\tfmath\mathtf % maybe a grouped command +\aliased\let\slmath\mathsl +\aliased\let\itmath\mathit + +\aliased\let\bfmath\mathbf +\aliased\let\bsmath\mathbs +\aliased\let\bimath\mathbi + +\aliased\let\Bbb\mathblackboard + +\permanent\protected\def\frak {\ifmmode\expandafter\mathfraktur \fi} +\permanent\protected\def\cal {\ifmmode\expandafter\mathscript \fi} +\permanent\protected\def\bbd {\ifmmode\expandafter\mathblackboard\fi} +\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard\fi} +\permanent\protected\def\fraktur {\ifmmode\expandafter\mathfraktur \fi} +\permanent\protected\def\gothic {\ifmmode\expandafter\mathfraktur \fi} + +\permanent\protected\def\mathcal #1{{\mathscript #1}} % for AMS compatibility +\permanent\protected\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility +\permanent\protected\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility + +\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\mathtf\else\normaltf\fi} +\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\mathbf\else\normalbf\fi} +\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\mathit\else\normalit\fi} +\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\mathsl\else\normalsl\fi} +\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\mathbi\else\normalbi\fi} +\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\mathbs\else\normalbs\fi} + +\permanent\protected\def\rm{\ifmmode\mathrm\else\normalrm\fi} +\permanent\protected\def\ss{\ifmmode\mathss\else\normalss\fi} +\permanent\protected\def\tt{\ifmmode\mathtt\else\normaltt\fi} + +\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent +\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent + +% 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 + \c_attr_mathrendering\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 + +\permanent\protected\def\boldsymbol + {\mathortext\mathboldsymbol\bold} + +%D Helpers + +\permanent\def\utfmathclass #1{\clf_utfmathclass {#1}} +\permanent\def\utfmathstretch#1{\clf_utfmathstretch{#1}} +\permanent\def\utfmathcommand#1{\clf_utfmathcommand{#1}} +\permanent\def\utfmathfiller #1{\clf_utfmathfiller {#1}} + +\permanent\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}} +\permanent\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}} +\permanent\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}} + +\permanent\protected\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}} +\permanent\protected\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}} +\permanent\protected\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}} +\permanent\protected\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}} +\permanent\protected\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}} + +\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent +\aliased\let\doifutfmathaboveelse \doifelseutfmathabove +\aliased\let\doifutfmathbelowelse \doifelseutfmathbelow +\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller +\aliased\let\doifutfmathlimopelse \doifelseutfmathlimop + +%D Not used that much: + +\installcorenamespace{mathcodecommand} + +\permanent\protected\def\mathlimop#1{\mathop{#1}} %no \limits +\permanent\protected\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath} +\permanent\protected\def\mathnolop#1{\mathop{#1}\nolimits} + +\let\mathnothing\firstofoneunexpanded +\let\mathalpha \firstofoneunexpanded + +\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 + +\permanent \def\mathcodenumber #1{\the\csname math#1code\endcsname} +\permanent\protected\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname} +\permanent \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi} + +% \startlines +% $\mathopnolimits{\rm d}x$ +% $\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} + +% todo: define these commands as frozen! + +\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning + {\ifparameter#3\or + \edef\nofmathcommandarguments{#3}% make this one m_arguments + \ifx\nofmathcommandarguments\v!one + \frozen\protected\defcsname\??mathcommand#1\endcsname##1{\mathcodecommand{#2}{#4{##1}}}% + \orelse\ifx\nofmathcommandarguments\v!two + \frozen\protected\defcsname\??mathcommand#1\endcsname##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}% + \else + \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}% + \fi + \orelse\ifparameter#2\or + \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}% + \else + \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{nothing}{#4}}% + \fi + \ifparameter#1\or % safeguard + \letcsname#1\expandafter\endcsname\csname\??mathcommand#1\endcsname + \fi} + +\permanent\protected\def\mathcommand#1% + {\begincsname\??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 + +\protected\def\math_strut_htdp#1% + {\s!height\fontcharht#1\c_math_strut + \s!depth \fontchardp#1\c_math_strut} + +\protected\def\math_strut_normal + {\vrule + \s!width \zeropoint + \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}% + \relax} + +\protected\def\math_strut_visual + {\hskip-.01\emwidth + \vrule + \s!width .02\emwidth + \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}% + \relax + \hskip-.01\emwidth} + +\permanent\protected\def\showmathstruts % let's not overload \math_strut_normal + {\enforced\let\math_strut\math_strut_visual} + +\let\math_strut\math_strut_normal + +% \protected\def\mathstrut{\mathcodecommand{nothing}{\math_strut}} + +\pushoverloadmode + + \definemathcommand [mathstrut] {\math_strut} + +\popoverloadmode + +%D We could have a arg variant \unknown\ but not now. + +\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} +\permanent\protected\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}} + +%D Moved from font-ini.mkiv: +%D +%D \macros +%D {mf,mbox,enablembox,mathop} +%D +%D Todo: + +\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen + +% \let\normalmathop\mathop % already defined + +% no longer needed as we no longer switch fonts +% +% \protected\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 ? + +\permanent\protected\def\normalmbox + {\normalhbox\bgroup + \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new + \dowithnextboxcs\math_mbox_finish\normalhbox} + +\def\math_mbox_finish + {\flushnextbox + \egroup} + +\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible + {\ifmmode\normalmbox\else\normalhbox\fi} + +\permanent\protected\def\enablembox + {\toksapp\everymathematics{\math_enable_mbox}} + +\permanent\def\math_enable_mbox % brrrr + {\enforced\let\hbox\mbox} + +\permanent\protected\def\snappedmath#1% sort of \struttedbox + {\dontleavehmode + \begingroup + \setbox\scratchbox\normalhbox\bgroup + \startimath#1\stopimath + \egroup + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \box\scratchbox + \endgroup} + +\permanent\protected\def\mtext#1% + {\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}} + +%D The next hack is needed needed for sine, cosine etc. + +\aliased\let\mathfunction\firstofoneunexpanded + +\let\math_tags_function \firstofoneunexpanded +\let\math_tags_functionlabeltext\mathlabeltext + +\let\math_tags_mo\firstofoneunexpanded +\let\math_tags_mi\firstofoneunexpanded + +\protected\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup} +\protected\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup} + +% Once this is stable we can store the number at the tex end which is +% faster. Functions getnumbers >= 1000. + +% \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=] + +\protected\def\math_mfunction_styled + {\begingroup + \usemathematicscolorparameter\c!functioncolor + \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}% + \ifempty\p_functionstyle + \expandafter\math_mfunction_styled_none + \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname + \doubleexpandafter\math_mfunction_styled_text + \else + \doubleexpandafter\math_mfunction_styled_math + \fi} + +\protected\def\math_mfunction_styled_text#1% + %{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}% + {\expandafter\mathoptext\expandafter{\lastnamedcs#1}% + \endgroup} + +\protected\def\math_mfunction_styled_math#1% + {\p_functionstyle + #1% + \endgroup} + +\protected\def\math_mfunction_styled_none#1% + {\mathupright + #1% + \endgroup} + +\permanent\protected\def\mfunction#1% + {\begingroup + \math_tags_mfunctiontxt{#1}\c_apply_function + \math_mfunction_styled{#1}% + \endgroup} + +\permanent\protected\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 + +\permanent\protected\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup} +\permanent\protected\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup} +\permanent\protected\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup} +\permanent\protected\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext + +\newconditional\c_apply_function + +\permanent\protected\def\math_tags_apply#1#2% + {\begingroup + \settrue\c_apply_function + #1% + \endgroup + \begingroup + % todo: auto () + #2% + \endgroup} + +\ifdefined\apply \else \aliased\let\apply\relax \fi + +\appendtoks + \enforced\let\math_tags_mfunctiontxt\clf_tagmfunctiontxt + \enforced\let\math_tags_mfunctionlab\clf_tagmfunctionlab + \enforced\let\math_tags_mo \math_tags_mo_indeed + \enforced\let\math_tags_mi \math_tags_mi_indeed + \enforced\let\math_tags_mn \math_tags_mn_indeed + \enforced\let\math_tags_ms \math_tags_ms_indeed +\to \everyenableelements + +\appendtoks + \enforced\let\mo \math_tags_mo + \enforced\let\mi \math_tags_mi + \enforced\let\mn \math_tags_mn + \enforced\let\ms \math_tags_ms + \enforced\let\apply\math_tags_apply +\to\everymathematics + +% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}} +% \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 +% +% \protected\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits} +% \protected\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}} +% \protected\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}} +% +% \protected\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 + +\permanent\protected\def\mscaledtext#1% + {\mathchoice + {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} + {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} + {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}} + {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}} + +\permanent\protected\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 + +\permanent\protected\def\activatemathcharacter#1% + {\appendtoks + \global\mathcode#1=\activemathcharcode + \to \activatedmathcharacters} + +\permanent\def\activatemathcharacters + {\the\activatedmathcharacters} + +% beware, not runtime, so has to happen at format generation + +\activatemathcharacter\circumflexasciicode +\activatemathcharacter\underscoreasciicode +\activatemathcharacter\ampersandasciicode + +\appendtoks + \edef\p_ampersand{\mathematicsparameter\s!ampersand}% + \ifx\p_ampersand\v!normal + \let\specialmathaligntab\normalmathaligntab + \else + \let\specialmathaligntab\mathampersand + \fi +\to \everysetupmathematics + +%D A simplified version of this code is: +%D +%D \starttyping +%D \catcode"26=12 +%D +%D \bgroup +%D \global\mathcode"26="8000 +%D +%D \catcode"26=4 +%D +%D \xdef\normalmathaligntab{&} +%D +%D \catcode"26=13 +%D +%D \global\everymath{\def&{\normalmathaligntab}} +%D \egroup +%D \stoptyping +%D +%D The following works okay: +%D +%D \starttyping +%D A & B +%D \stoptyping +%D +%D As does: +%D +%D \starttyping +%D $A \Umathchar"2"0"26 B$ +%D \stoptyping +%D +%D But the next code: +%D +%D \starttyping +%D $A \char"26 B$ +%D \stoptyping +%D +%D fails with: \type{Misplaced alignment tab character &} and here is the +%D reason. +%D +%D When we have a letter or other category a check happens for an active +%D character and when it has one then it gets expanded and fed back into the +%D scanner (sort of). +%D +%D A \type {\char} is also fed back as raw character and again when it's letter +%D of other goes through the same process. +%D +%D This means that we cannot have a definition like: +%D +%D \starttyping +%D \def\AND{\char"26\relax} +%D \stoptyping +%D +%D that can be used in math mode, which is why the cweb macros do: +%D +%D \starttyping +%D \def\AND{\def\AND{\mathchar"2026\relax}\AND} +%D \stoptyping +%D +%D Maybe we need an option to treat chars like chars. + +% \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 \glet\othercircumflextoken ^ } +{ \catcode\circumflexasciicode\superscriptcatcode \glet\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 +% +% \protected\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 + +% $\char26$ gives an error because it expands to an active character that +% then becomes an & which is then seen as an alignment character; anyway, +% even when we switch like this the different meaning only happens when +% we're in math mode which can be delayed till we're in a cell + +\bgroup + + \catcode\underscoreasciicode\activecatcode + \catcode\circumflexasciicode\activecatcode + \catcode\ampersandasciicode \activecatcode + + \glet\specialmathaligntab\normalmathaligntab + + \permanent\protected\gdef\obeymathcatcodes + {\let _\normalsubscript + \let ^\normalsuperscript + \def &\specialmathaligntab + } + + \doglobal\appendtoks + \enforced\let _\normalsubscript + \enforced\let ^\normalsuperscript + \enforced\let &\specialmathaligntab + \to \everymathematics + + % \permanent\protected\gdef\normalmathampersands + % {\let\specialmathaligntab\mathampersand} + +\egroup + +\newtoks\everydonknuthmode +\newtoks\everynonknuthmode + +\newconditional \knuthmode + +\aliased\let\nonknuthmode\relax % no longer needed in MkIV +\aliased\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) + +% \protected\def\enableasciimode +% {\ctxlua{resolvers.macros.enablecomment()}% +% \glet\enableasciimode\relax} +% +% \protected\def\asciimode +% {\catcodetable\txtcatcodes +% \enableasciimode +% \nonknuthmode} +% +% \protected\def\startasciimode +% {\pushcatcodetable +% \catcodetable\txtcatcodes +% \enableasciimode +% \nonknuthmode} +% +% \protected\def\stopasciimode +% {\popcatcodetable +% \ifconditional\knuthmode\else\donknuthmode\fi} + +\permanent\protected\def\enableasciimode + {\clf_enableasciimode} % relaxes itself + +\permanent\protected\def\asciimode + {\catcodetable\txtcatcodes + \clf_enableasciimode} + +\permanent\protected\def\startasciimode + {\pushcatcodetable + \catcodetable\txtcatcodes + \clf_enableasciimode} + +\permanent\protected\def\stopasciimode + {\popcatcodetable} + +%D Needed for unicode: + +\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}} + +%D Memory saver: + +\def\math_basics_check_compact + {\doifelse{\mathematicsparameter\c!compact}\v!yes + \enabledirectives\disabledirectives[math.virtual.optional]} + +\appendtoks + \ifempty\currentmathematics + \math_basics_check_compact % less tracing + \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 + +% We will use proper constants when we go numbers instead of XXX. + +\newconditional\c_math_right_to_left + +\installcorenamespace{mathaligndirection} + +\setvalue{\??mathaligndirection r2l}{\settrue\c_math_right_to_left} +\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left} + +\appendtoks + \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname + \lastnamedcs + \else + \setfalse\c_math_right_to_left + \fi +\to \everyswitchmathematics + +\protected\def\math_basics_synchronize_direction + {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi} + +% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode +% kludge now (should be a property of beginmath nodes and passed to callbacks). + +\appendtoks + \math_basics_synchronize_direction +\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}% still needed ? + \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi +\to \everysetupmathematics + +\appendtoks + \c_attr_mathbidi\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 + +\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax} +\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax} +\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax} + +\let\mathgreeknormal\mathgreekupright +\let\mathgreeknone \mathgreekdefault + +\appendtoks + \c_attr_mathgreek\c_math_greek_attribute +\to \everymathematics + +\setupmathematics + [\s!sygreek=\v!normal, + \s!lcgreek=\v!italic, + \s!ucgreek=\v!normal] % was: none + +%D Math collapsing (ligatures) + +\installcorenamespace{mathcollapsing} + +\setnewconstant\c_math_collapsing_attribute\attributeunsetvalue + +\letvalue{\??mathcollapsing 1}\plusone % specials +\letvalue{\??mathcollapsing 2}\plustwo % specials + mathlist +\letvalue{\??mathcollapsing 3}\plusthree % mathlist + specials +\letvalue{\??mathcollapsing\v!none }\attributeunsetvalue +\letvalue{\??mathcollapsing\v!reset}\attributeunsetvalue + +\def\math_collapsing_initialize + {\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else + \clf_initializemathcollapsing % one time + \glet\math_collapsing_initialize\relax + \fi} + +\appendtoks + \edef\p_collapsing{\mathematicsparameter\s!collapsing}% + \c_math_collapsing_attribute + \ifcsname\??mathcollapsing\p_collapsing\endcsname\lastnamedcs\else\attributeunsetvalue\fi + \relax +\to \everyswitchmathematics % only in mathematics + +\appendtoks + \math_collapsing_initialize + \c_attr_mathcollapsing\c_math_collapsing_attribute +\to \everymathematics + +\setupmathematics + [\s!collapsing=1] % so that we at least do primes + +%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 + \glet\math_italics_initialize\relax + \fi} + +\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 + \c_attr_mathitalics\c_math_italics_attribute +\to \everymathematics + +% \setupmathematics % done later +% [\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 Math kerns (experiment) + +\installcorenamespace{mathkernpairs} + +\setnewconstant\c_math_kernpairs_attribute\attributeunsetvalue % no real need for an extra constant + +\def\math_kernpairs_initialize + {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else + \clf_initializemathkernpairs % one time + \glet\math_kernpairs_initialize\relax + \fi} + +\appendtoks + \edef\p_kernpairs{\mathematicsparameter\s!kernpairs}% + \c_math_kernpairs_attribute\ifx\p_kernpairs\v!yes\plusone\else\attributeunsetvalue\fi\relax +\to \everyswitchmathematics % only in mathematics + +\appendtoks + \math_kernpairs_initialize + \c_attr_mathkernpairs\c_math_kernpairs_attribute +\to \everymathematics + +\setupmathematics + [\s!kernpairs=\v!no] + +%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 +% +% \protected\def\enablemathpunctuation {\settrue \automathpunctuation} +% \protected\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} +% +% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next} +% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next} +% +% \setnewconstant\c_math_comma "002C +% \setnewconstant\c_math_period "002E +% \setnewconstant\c_math_special"8000 +% +% \bgroup +% +% \catcode\c_math_comma \activecatcode +% \catcode\c_math_period\activecatcode +% +% \protected\gdef\math_punctuation_initialize_indeed +% {\mathcode\c_math_comma \c_math_special +% \mathcode\c_math_period\c_math_special +% \let,\math_punctuation_comma +% \let.\math_punctuation_period +% \c_attr_mathpunctuation\plustwo} +% +% \protected\gdef\math_punctuation_initialize_yes +% {\c_attr_mathpunctuation\plustwo} +% +% \protected\gdef\math_punctuation_initialize_nop +% {\c_attr_mathpunctuation\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}} +% +% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}} +% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}} +% +% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} +% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next} +% +% \let\math_punctuation_yes_comma \math_punctuation_all_comma +% \let\math_punctuation_yes_period\math_punctuation_nop_period +% +% 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_colon "003A +\setnewconstant\c_math_semicolon"003B +\setnewconstant\c_math_special "8000 + +% todo: use \Umathclass\c_math_comma\mathpunctcode etc for temporary switching + +\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} +\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_semicolon{\Umathcode\c_math_semicolon\mathordcode \zerocount\c_math_semicolon} +\def\math_set_p_semicolon{\Umathcode\c_math_semicolon\mathpunctcode\zerocount\c_math_semicolon} + +\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} + +\protected\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup} +\protected\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup} +\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup} + +% todo: use new lookahead stuff + +\protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} +\protected\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next} +\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next} + + \let\math_punctuation_yes_comma \math_punctuation_all_comma + \let\math_punctuation_yes_period \math_punctuation_nop_period + \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon + +\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} +\def\math_punctuation_semicolon_next{\begingroup\Umathcode\c_math_semicolon\ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_semicolon;\endgroup} + +\installcorenamespace {mathautopunctuation} + +\bgroup + + \catcode\c_math_comma \activecatcode + \catcode\c_math_period \activecatcode + \catcode\c_math_semicolon\activecatcode + + \setgvalue{\??mathautopunctuation\v!no}% + {\let,\math_punctuation_nop_comma + \let.\math_punctuation_nop_period + \let;\math_punctuation_nop_semicolon} + + % 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 + \let;\math_punctuation_nop_semicolon} + + \setgvalue{\??mathautopunctuation\v!all}% + {\let,\math_punctuation_all_comma + \let.\math_punctuation_all_period + \let;\math_punctuation_nop_semicolon} + + \setgvalue{\??mathautopunctuation comma}% + {\let,\math_punctuation_yes_comma + \let.\math_punctuation_yes_period + \let;\math_punctuation_nop_semicolon} + + \setgvalue{\??mathautopunctuation\v!yes\string,semicolon}% + {\let,\math_punctuation_yes_comma + \let.\math_punctuation_yes_period + \let;\math_punctuation_yes_semicolon} + + \setgvalue{\??mathautopunctuation comma\string,semicolon}% + {\let,\math_punctuation_yes_comma + \let.\math_punctuation_yes_period + \let;\math_punctuation_yes_semicolon} + + \setgvalue{\??mathautopunctuation\v!all\string,semicolon}% + {\let,\math_punctuation_all_comma + \let.\math_punctuation_all_period + \let;\math_punctuation_all_semicolon} + +\egroup + +% \appendtoks +% \global\mathcode\c_math_comma \c_math_special +% \global\mathcode\c_math_period \c_math_special +% \global\mathcode\c_math_semicolon\c_math_special +% \to \everyjob + +% \activatemathcharacter\c_math_comma +% \activatemathcharacter\c_math_period +% \activatemathcharacter\c_math_semicolon + +\appendtoks + \mathcode\c_math_comma \c_math_special + \mathcode\c_math_period \c_math_special + \mathcode\c_math_semicolon\c_math_special + \begincsname\??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 | comma | yes,semicolon | all,semicolon + +%D The consequences of setting this are as follows: +%D +%D \def\TestA#1#2#3% +%D {\ifnum#1=0 \type{#2}\else\setupmathematics[autopunctuation={#2}]$#3$\fi} +%D \def\TestB#1#2% +%D {\NC \TestA{#1}{no} {#2} +%D \NC \TestA{#1}{yes} {#2} +%D \NC \TestA{#1}{yes,semicolon}{#2} +%D \NC \TestA{#1}{all} {#2} +%D \NC \TestA{#1}{all,semicolon}{#2} +%D \NC \NR} +%D \starttabulate[|c|c|c|c|c|] +%D \TestB{0}{} +%D \TestB{1}{(1,2)=(1, 2)} +%D \TestB{1}{(1.2)=(1. 2)} +%D \TestB{1}{(1;2)=(1; 2)} +%D \stoptabulate + +%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 + +\permanent\def\uncramped#1% + {{\ifmathstyle + \or \displaystyle \or + \or \textstyle \or + \or \scriptstyle \or + \or \scriptscriptstyle \fi + #1}} + +\permanent\def\cramped#1% + {{\ifmathstyle + \crampeddisplaystyle \or \or % 0 -> 1 + \crampedtextstyle \or \or % 2 -> 3 + \crampedscriptstyle \or \or % 4 -> 5 + \crampedscriptscriptstyle \fi % 6 -> 7 + #1}} + +\permanent\def\triggermathstyle#1{\Ustyle\numexpr#1\relax} +%permanent\def\mathstyletrigger#1{\numexpr#1\relax} +\permanent\let\mathstyletrigger \firstofoneargument + +\permanent\def\triggeredmathstyleparameter#1% to bypass the relax + {\ifcase\numexpr\normalmathstyle\relax + #1\displaystyle \or % 0 + #1\crampeddisplaystyle \or % 1 + #1\textstyle \or % 2 + #1\crampedtextstyle \or % 3 + #1\scriptstyle \or % 4 + #1\crampedscriptstyle \or % 5 + #1\scriptscriptstyle \or % 6 + #1\crampedscriptscriptstyle \else + % error + \fi} + +\permanent\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\fam} % was \zerocount + +\permanent\def\somemathstylefont#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} + +\permanent\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\fam} % was \zerocount + +\permanent\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} + +\permanent\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} + +\permanent\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} + +% \permanent\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} + +\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle) + {{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax + display\or % 0 + crampeddisplay\or % 1 + text\or % 2 + crampedtext\or % 3 + script\or % 4 + crampedscript\or % 5 + scriptscript\or % 6 + crampedscriptscript\else % 7 + unknown\fi]}}} + +\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle} + +%D Handy too: + +\permanent\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle} +\permanent\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle} +\permanent\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle} + +%D Some dimension fun: + +\let\mathexheight \exheight % also in math-ini.mkiv +\def\mathemwidth {\Umathquad\normalmathstyle} % also in math-ini.mkiv + +%D A plain inheritance: + +\permanent\def\mathpalette#1#2% + {\mathchoice + {#1\displaystyle {#2}}% + {#1\textstyle {#2}}% + {#1\scriptstyle {#2}}% + {#1\scriptscriptstyle{#2}}} + +%D \macros +%D {cramedllap, crampedrlap, crampedclap} +%D +%D In many cases, one wants to use the \tex {clap} macro in math mode while using +%D subscripts. Normally, subscripts are in cramped mode, and these macros allow you +%D to go to 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 This used to be in \type {supp-math.mkxl}: + +\permanent\protected\def\crampedllap#1{\llap{\cramped#1}} +\permanent\protected\def\crampedrlap#1{\rlap{\cramped#1}} +\permanent\protected\def\crampedclap#1{\clap{\cramped#1}} + +%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 + +% \protected\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b} +% {\normalexpanded{\hbox\bgroup +% \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} + +\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b} + {\math_style_hbox{#1}} + +\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b} + {\normalexpanded{\hbox#1\bgroup + \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup} + +\permanent\protected\def\mathstylevbox#1% + {\normalexpanded{\vbox\bgroup + \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} + +\permanent\protected\def\mathstylevcenter#1% + {\normalexpanded{\vcenter\bgroup + \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} + +\permanent\protected\def\mathstylevcenteredhbox#1% + {\normalexpanded{\vcenter\bgroup\hbox\bgroup + \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} + +\permanent\protected\def\mathstylevcenteredvbox#1% + {\normalexpanded{\vcenter\bgroup\vbox\bgroup + \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} + +\permanent\protected\def\setmathsmalltextbox#1#2#% + {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}% + \setbox#1#2\bgroup + \font_basics_switchtobodyfont\m_math_text_choice_face + \let\next} + +\permanent\protected\def\setmathtextbox#1#2#% + {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% + \setbox#1#2\bgroup + \font_basics_switchtobodyfont\m_math_text_choice_face + \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 + +\permanent\def\triggerdisplaystyle + {\ifmathstyle + \displaystyle \or + \crampeddisplaystyle \or + \displaystyle \or + \crampeddisplaystyle \or + \displaystyle \or + \crampeddisplaystyle \or + \displaystyle \or + \crampeddisplaystyle \or + \fi} + +\permanent\def\triggertextstyle + {\ifmathstyle + \textstyle \or + \crampedtextstyle \or + \textstyle \or + \crampedtextstyle \or + \textstyle \or + \crampedtextstyle \or + \textstyle \or + \crampedtextstyle \else + \fi} + +\permanent\def\triggerscriptstyle + {\ifmathstyle + \scriptstyle \or + \crampedscriptstyle \or + \scriptstyle \or + \crampedscriptstyle \or + \scriptstyle \or + \crampedscriptstyle \or + \scriptstyle \or + \crampedscriptstyle \or + \fi} + +\permanent\def\triggerscriptscriptstyle + {\ifmathstyle + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \fi} + +\permanent\def\triggeruncrampedstyle + {\ifmathstyle + \or \displaystyle \or + \or \textstyle \or + \or \scriptstyle \or + \or \scriptscriptstyle \fi} + +\permanent\def\triggercrampedstyle + {\ifmathstyle + \crampeddisplaystyle \or \or + \crampedtextstyle \or \or + \crampedscriptstyle \or \or + \crampedscriptscriptstyle \fi} + +\permanent\def\triggersmallstyle + {\ifmathstyle + \scriptstyle \or + \crampedscriptstyle \or + \scriptstyle \or + \crampedscriptstyle \or + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \scriptscriptstyle \or + \crampedscriptscriptstyle \or + \fi} + +\permanent\def\triggeruncrampedsmallstyle + {\ifmathstyle + \scriptstyle \or + \scriptstyle \or + \scriptstyle \or + \scriptstyle \or + \scriptscriptstyle \or + \scriptscriptstyle \or + \scriptscriptstyle \or + \scriptscriptstyle \or + \fi} + +\permanent\def\triggercrampedsmallstyle + {\ifmathstyle + \crampedscriptstyle \or + \crampedscriptstyle \or + \crampedscriptstyle \or + \crampedscriptstyle \or + \crampedscriptscriptstyle \or + \crampedscriptscriptstyle \or + \crampedscriptscriptstyle \or + \crampedscriptscriptstyle \or + \fi} + +\permanent\def\triggerbigstyle + {\ifmathstyle + \displaystyle \or + \crampeddisplaystyle \or + \textstyle \or + \crampedtextstyle \or + \textstyle \or + \crampedtextstyle \or + \scriptstyle \or + \crampedscriptstyle \or + \fi} + +\permanent\def\triggeruncrampedbigstyle + {\ifmathstyle + \displaystyle \or + \displaystyle \or + \textstyle \or + \textstyle \or + \textstyle \or + \textstyle \or + \scriptstyle \or + \scriptstyle \or + \fi} + +\permanent\def\triggercrampedbigstyle + {\ifmathstyle + \crampeddisplaystyle \or + \crampeddisplaystyle \or + \crampedtextstyle \or + \crampedtextstyle \or + \crampedtextstyle \or + \crampedtextstyle \or + \crampedscriptstyle \or + \crampedscriptstyle \or + \fi} + +\newcount\c_math_saved_style + +\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup + {\c_math_saved_style\mathstyle} + +\permanent\protected\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 +} + +\permanent\tolerant\protected\def\setmathstyle[#1]#;#=% so we accept [] and {} + {\edef\m_math_style_asked{#1#2}% + \ifempty\m_math_style_asked \else + \math_style_set_indeed + \fi} + +\permanent\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} + +\permanent\protected\def\setupmathstyle[#1]% + {\edef\m_math_style_asked{#1}% + \ifempty\m_math_style_asked \else + \math_style_set_indeed + \fi} + +\permanent\protected\def\usemathstyleparameter#1% faster local variant + {\edef\m_math_style_asked{#1\c!mathstyle}% + \ifempty\m_math_style_asked \else + \math_style_set_indeed + \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} + +\permanent\tolerant\protected\def\definemathstyle[#1]#*[#2]% + {\c_math_styles_state_style \zerocount + \c_math_styles_state_cramped\zerocount + \c_math_styles_state_size \zerocount + \rawprocesscommacommand[#2]\math_style_collect + \letcsname\??mathstyle#1\normalexpanded{\endcsname\math_style_add_to_cache_choice}} + +\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 + \gletcsname\??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 + +\permanent\protected\def\startmathstyle[#1]% + {\edef\m_math_style_asked{#1}% + \ifempty\m_math_style_asked + \enforced\aliased\let\stopmathstyle\relax + \else + \bgroup + \math_style_set_indeed + \enforced\aliased\let\stopmathstyle\egroup + \fi} + +\aliased\let\stopmathstyle\relax + +\permanent\protected\def\startusemathstyleparameter#1% + {\edef\m_math_style_asked{#1\c!mathstyle}% + \ifempty\m_math_style_asked + \enforced\let\stopusemathstyleparameter\relax + \else + \bgroup + \math_style_set_indeed + \enforced\let\stopusemathstyleparameter\egroup + \fi} + +\aliased\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#2#% +% {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% +% \hbox#2\bgroup +% \font_basics_switchtobodyfont\m_math_text_choice_face +% #1% +% \let\next} + +% \def\math_text_choice_word#1#2#% +% {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% +% \hbox#2\bgroup +% \font_basics_switchtobodyfont\m_math_text_choice_face +% #1% +% \nospacing % \normalnospaces\plusone +% \let\next} + +%D We accept a low level box specification so that one can make helpers: +%D +%D \startbuffer +%D \startformula +%D \startalign[m=2,align={middle}] +%D \NC \text to 6cm{One\hfill} \NC a = 1 \NR +%D \NC \text to 6cm{One Two\hfill} \NC b = 2 \NR +%D \NC \text to 6cm{One Two Three\hfill} \NC c = 3 \NR +%D \stopalign +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\def\math_text_choice_font#1#2#% + {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% + \hbox#2\bgroup + \bgroup + \aftergroup\hss + \aftergroup\egroup + \hss + \font_basics_switchtobodyfont\m_math_text_choice_face + #1% + \let\next} + +\def\math_text_choice_word#1#2#% + {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% + \hbox#2\bgroup + \bgroup + \aftergroup\hss + \aftergroup\egroup + \hss + \font_basics_switchtobodyfont\m_math_text_choice_face + #1% + \nospacing % \normalnospaces\plusone + \let\next} + +% \ruledhbox{$\mathtext{abc ffi}$} +% \ruledhbox{$\mathword{abc ffi}$} + +% I need to decide: +% +%mathscriptboxmode \zerocount % no kerning +%mathscriptboxmode \plusone % lists +\mathscriptboxmode \plustwo % lists and boxes +\mathscriptcharmode \plusone % lists and boxes +%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo) +\mathrulethicknessmode\plusone % adaptive + +\permanent\protected\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox} +\permanent\protected\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox} + +\permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox} +\permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox} +\permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox} +\permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox} +\permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox} +\permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox} + +\permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox} +\permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox} +\permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox} +\permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox} +\permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox} +\permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox} + +%D Safeguard against redefinitions: + +\appendtoks + \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore +\to \everymathematics + +%D Because we may overload \type {\text} in other (structuring) macros, we say: + +\appendtoks + \enforced\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 + +% this can become an option: + +\protected\def\math_display_align_hack % I don't like the global, maybe we should push and pop + {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip + \math_openup\displayopenupvalue % was \math_openup\jot + \everycr{\noalign{\math_display_align_hack_indeed}}} + +\def\math_display_align_hack_remove_skip + {\ifdim\prevdepth>-\thousandpoint + \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax + \fi + \glet\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: + +\permanent\protected\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 + +% \protected\def\mathoptext#1{\mathop{\text{#1}}} + +\permanent\protected\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}% + \ifempty\p_setups\else + \directsetup\p_setups + \fi +\to \everyswitchmathematics + +% new: + +\permanent\protected\def\smallmathsymbol#1% + {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath + \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1% + \normalstopimath}}}}} + +% this should be a primitive: + +\permanent\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax} +\permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax} + +% experimental: + +%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} + +\protected\def\math_inline_openup_normal_start + {\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax + \scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax + \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax + \begingroup + \let\math_inline_openup_stop\math_inline_openup_normal_stop} + +\protected\def\math_inline_openup_normal_stop + {\endgroup + \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax} + +\protected\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} + +\protected\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} + +\permanent\protected\def\openedupimath + {\dontleavehmode + \begingroup + \ifmmode + \expandafter\openedupimath_math + \else + \expandafter\openedupimath_text + \fi} + +\protected\def\openedupimath_math#1% + {\setbox\scratchbox\mathstylehbox{#1}% + \ifdim\ht\scratchbox>\strutht + \math_inline_openup_start_yes + \orelse\ifdim\dp\scratchbox>\strutdp + \math_inline_openup_start_yes + \else + \math_inline_openup_start_nop + \fi + #1% + \math_inline_openup_stop + \endgroup} + +\protected\def\openedupimath_text#1% + {\setbox\scratchbox\hbox{\startimath#1\stopimath}% + \ifdim\ht\scratchbox>\strutht + \math_inline_openup_start_yes + \orelse\ifdim\dp\scratchbox>\strutdp + \math_inline_openup_start_yes + \else + \math_inline_openup_start_nop + \fi + \startimath + #1% + \stopimath + \math_inline_openup_stop + \endgroup} + +% Also handy, especially for units: +% +% 0x002B=plus 0x2212=minus 0x2013=endash + +\permanent\protected\def\mathplus {+} +\permanent\protected\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi} +\permanent\protected\def\mathplusminus{±} + +%D The \type {\displaywidth} is only known inside a display formula, so we need to catch +%D it when still zero. + +\permanent\def\checkeddisplaywidth % hsize if zero + {\dimexpr + \ifzeropt\displaywidth + \hsize + \else + \displaywidth + \fi + \relax} + +\permanent\def\maximizeddisplaywidth % larger than zero but within hsize + {\dimexpr + \ifzeropt\displaywidth + \hsize + \orelse\ifdim\displaywidth>\hsize + \hsize + \else + \displaywidth + \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 + \glet\math_domain_initialize\relax + \fi} + +\appendtoks + \edef\p_domain{\mathematicsparameter\c!domain}% + \ifempty\p_domain + \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 + \c_attr_mathdomain\c_math_domain_attribute +\to \everymathematics + +\setupmathematics + [\s!italics=3] % for the moment only this one makes sense .. still experimental + +%D For special purposed we set this one: + +\installcorenamespace{mathrules} + +\permanent\protected\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone} + +\appendtoks + \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname + \lastnamedcs + \else + \zerocount + \fi + \mathrulesfam\zerocount +\to \everymathematics + +%D Maybe: + +% \starttabulate[|||c|c|] +% \BC positive \BC negative \BC text \BC math \NC \NR +% \NC \tex {f1} \tex {hairspace} \tex{,} \NC \tex {b1} \tex {neghairspace} \NC {\darkred\vl}\f1{\darkblue\vl} \NC ${\darkred\vl}\f1{\darkblue\vl}$ \NC \NR +% \NC \tex {f2} \tex {thinspace} \tex{:} \NC \tex {b2} \tex {negthinspace} \tex{!} \NC {\darkred\vl}\f2{\darkblue\vl} \NC ${\darkred\vl}\f2{\darkblue\vl}$ \NC \NR +% \NC \tex {f3} \tex {medspace} \tex{;} \NC \tex {b3} \tex {negmedspace} \NC {\darkred\vl}\f3{\darkblue\vl} \NC ${\darkred\vl}\f3{\darkblue\vl}$ \NC \NR +% \NC \tex {f4} \tex {thickspace} \NC \tex {b4} \tex {negthickspace} \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR +% \NC \tex {f5} \tex {enspace} \NC \tex {b5} \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR +% \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR +% \stoptabulate + +% \protected\def\negenspace{\kern-.5\emwidth} +% \protected\def\negemspace{\kern- \emwidth} +% +% \protected\def\math_f#1% +% {\ifcase#1\or +% \hairspace +% \or +% \thinspace +% \or +% \medspace +% \or +% \thickspace +% \or +% \enspace +% \or +% \emspace +% \fi} +% +% \protected\def\math_b#1% +% {\ifcase#1\or +% \neghairspace +% \or +% \negthinspace +% \or +% \negmedspace +% \or +% \negthickspace +% \or +% \negenspace +% \or +% \negemspace +% \fi} +% +% \appendtoks +% \let\f\math_f +% \let\b\math_b +% \to \everymathematics + +%D Experiment + +\permanent\protected\def\math_scripts_stack + {\c_attr_mathunstack\attributeunsetvalue} + +\permanent\protected\def\math_scripts_unstack + {\clf_enablescriptunstacking + \c_attr_mathunstack\plusone} + +\ifdefined\stackscripts \else \aliased\let\stackscripts \relax \fi +\ifdefined\unstackscripts \else \aliased\let\unstackscripts\relax \fi + +\appendtoks + \enforced\let\stackscripts \math_scripts_stack + \enforced\let\unstackscripts\math_scripts_unstack +\to \everymathematics + +%D Expensive (tracing and inject) but a primitive (using factors) is tricky as we +%D want this frozen support. + +% \def\math_openup_parameter#1#2% +% {\ifzeropt#1\displaystyle \orelse\ifdim#1\displaystyle =\maxdimen\else\frozen#1\displaystyle #2#1\displaystyle \fi +% \ifzeropt#1\crampeddisplaystyle \orelse\ifdim#1\crampeddisplaystyle =\maxdimen\else\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi +% \ifzeropt#1\textstyle \orelse\ifdim#1\textstyle =\maxdimen\else\frozen#1\textstyle #2#1\textstyle \fi +% \ifzeropt#1\crampedtextstyle \orelse\ifdim#1\crampedtextstyle =\maxdimen\else\frozen#1\crampedtextstyle #2#1\crampedtextstyle \fi +% \ifzeropt#1\scriptstyle \orelse\ifdim#1\scriptstyle =\maxdimen\else\frozen#1\scriptstyle #2#1\scriptstyle \fi +% \ifzeropt#1\crampedscriptstyle \orelse\ifdim#1\crampedscriptstyle =\maxdimen\else\frozen#1\crampedscriptstyle #2#1\crampedscriptstyle \fi +% \ifzeropt#1\scriptscriptstyle \orelse\ifdim#1\scriptscriptstyle =\maxdimen\else\frozen#1\scriptscriptstyle #2#1\scriptscriptstyle \fi +% \ifzeropt#1\crampedscriptscriptstyle\orelse\ifdim#1\crampedscriptscriptstyle=\maxdimen\else\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi} + +% \def\mdim#1#2% +% {\ifcase\ifzeropt#1#2\plusone\orelse\ifdim#1#2=\maxdimen\plusone\else\zerocount\fi} +% +% \def\mdim +% {\afterassignment\mmdim\scratchdimen} +% +% \def\mmdim +% {\ifcase\ifzeropt\scratchdimen\plusone\orelse\ifdim\scratchdimen=\maxdimen\plusone\else\zerocount\fi} +% +% \def\math_openup_parameter#1#2% +% {\ifcondition\mdim#1\displaystyle \frozen#1\displaystyle #2\dimexpr#1\displaystyle \relax\fi +% \ifcondition\mdim#1\crampeddisplaystyle \frozen#1\crampeddisplaystyle #2\dimexpr#1\crampeddisplaystyle \relax\fi +% \ifcondition\mdim#1\textstyle \frozen#1\textstyle #2\dimexpr#1\textstyle \relax\fi +% \ifcondition\mdim#1\crampedtextstyle \frozen#1\crampedtextstyle #2\dimexpr#1\crampedtextstyle \relax\fi +% \ifcondition\mdim#1\scriptstyle \frozen#1\scriptstyle #2\dimexpr#1\scriptstyle \relax\fi +% \ifcondition\mdim#1\crampedscriptstyle \frozen#1\crampedscriptstyle #2\dimexpr#1\crampedscriptstyle \relax\fi +% \ifcondition\mdim#1\scriptscriptstyle \frozen#1\scriptscriptstyle #2\dimexpr#1\scriptscriptstyle \relax\fi +% \ifcondition\mdim#1\crampedscriptscriptstyle\frozen#1\crampedscriptscriptstyle#2\dimexpr#1\crampedscriptscriptstyle\relax\fi} + +% \ifmathparameter : 0=zero, 1=set, 2=unset (les stracing clutter this way) + +%D New stuff: +%D +%D \starttyping +%D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$ +%D \stoptyping + +\permanent\protected\def\mathopenupparameter#1#2% + {\ifmathparameter#1\displaystyle \or\frozen#1\displaystyle #2#1\displaystyle \fi + \ifmathparameter#1\crampeddisplaystyle \or\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi + \ifmathparameter#1\textstyle \or\frozen#1\textstyle #2#1\textstyle \fi + \ifmathparameter#1\crampedtextstyle \or\frozen#1\crampedtextstyle #2#1\crampedtextstyle \fi + \ifmathparameter#1\scriptstyle \or\frozen#1\scriptstyle #2#1\scriptstyle \fi + \ifmathparameter#1\crampedscriptstyle \or\frozen#1\crampedscriptstyle #2#1\crampedscriptstyle \fi + \ifmathparameter#1\scriptscriptstyle \or\frozen#1\scriptscriptstyle #2#1\scriptscriptstyle \fi + \ifmathparameter#1\crampedscriptscriptstyle\or\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi} + +%D New stuff: +%D +%D \startbuffer +%D $x\mathopen {!}+123+\mathclose {!}x$ +%D $x\tomathopen ! +123+\tomathclose ! x$ +%D $x\mathclose {!}+123+\mathopen {!}x$ +%D $x\tomathclose ! +123+\tomathopen ! x$ +%D $x ! +123+ ! x$ +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlines +%D \getbuffer +%D \stoplines + +\permanent\protected\def\tomathord {\Umathclass\zerocount} +\permanent\protected\def\tomathop {\Umathclass\plusone } % \mathinfix +\permanent\protected\def\tomathbin {\Umathclass\plustwo } +\permanent\protected\def\tomathrel {\Umathclass\plusthree} +\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix +\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix +\permanent\protected\def\tomathpunct{\Umathclass\plussix } + +%D Prescripts. These work in \CONTEXT\ because we have the super- and subscript +%D triggers enabled as active characters but when we would have +%D +%D \starttyping +%D \catcode\underscoreasciicode\subscriptcatcode +%D \catcode\circumflexasciicode\superscriptcatcode +%D \stoptyping +%D +%D we also need the next line to disable character escaping via \type {^} in +%D math mode: +%D +%D \startbuffer +%D \blank \hbox{ +%D \ruledhbox{${\tf X} ^1 _2 ^^3 __4$} +%D \ruledhbox{${\tf X} ^1 $} +%D \ruledhbox{${\tf X} _2 $} +%D \ruledhbox{${\tf X} ^^3 $} +%D \ruledhbox{${\tf X} __4$} +%D \ruledhbox{${\tf X} ^1 _2 $} +%D \ruledhbox{${\tf X} ^1 ^^3 $} +%D \ruledhbox{${\tf X} ^1 __4$} +%D \ruledhbox{${\tf X} _2 ^^3 $} +%D \ruledhbox{${\tf X} _2 __4$} +%D \ruledhbox{${\tf X} ^1 _2 ^^3 $} +%D \ruledhbox{${\tf X} ^1 _2 __4$} +%D \ruledhbox{${\tf X} _2 ^^3 $} +%D \ruledhbox{${\tf X} _2 ^^3 __4$} +%D \ruledhbox{${\tf X} ^^3 __4$} +%D } \blank +%D +%D \typebuffer \getbuffer + +\normalsupmarkmode\plusone % 2 also disable ^[^+] in text mode + +\protect \endinput + +% % not used (yet) +% +% \newtoks \everystartimath +% \newtoks \everystopimath +% +% \protected\def\startimath{\Ustartmath\the\everystartimath} +% \protected\def\stopimath {\the\everystopimath\Ustopmath} +% +% \protected\def\m% +% {\relax +% \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi} +% +% \protected\def\math_m_math#1% +% {\startimath#1\stopimath} +% +% \let\math_m_stay\firstofoneargument diff --git a/tex/context/base/mkxl/math-inl.mkxl b/tex/context/base/mkxl/math-inl.mkxl new file mode 100644 index 000000000..2c7284458 --- /dev/null +++ b/tex/context/base/mkxl/math-inl.mkxl @@ -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/tex/context/base/mkxl/math-int.mkxl b/tex/context/base/mkxl/math-int.mkxl new file mode 100644 index 000000000..4b3d63f2b --- /dev/null +++ b/tex/context/base/mkxl/math-int.mkxl @@ -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} +% +% \protected\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 +% \orelse\ifx\next\displaylimits +% \math_repeated_integral_correction +% \orelse\ifx\next\nolimits +% % nothing +% \orelse\ifcase\mathintlimitmode +% % nothing +% \else +% \math_repeated_integral_correction +% \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/tex/context/base/mkxl/math-mis.mkxl b/tex/context/base/mkxl/math-mis.mkxl new file mode 100644 index 000000000..a824c5933 --- /dev/null +++ b/tex/context/base/mkxl/math-mis.mkxl @@ -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. + +\permanent\protected\def\qedsymbol#1% + {\ifhmode + \unskip\nobreakspace\hfill#1\par + \orelse\ifmmode + #1\relax % leading \eqno removed + \else + \dontleavehmode\emptyhbox\hfill#1\par + \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] + +\permanent\protected\def\QED{\symbol[qed]} + +%D \macros +%D {boxed} +%D +%D [HH] Another macro that users might expect (slightly adapted): + +\permanent\protected\def\boxed % maybe obsolete + {\ifmmode\expandafter\mframed\else\expandafter\framed\fi} + +%D Something low level for scientific calculator notation: + +\permanent\protected\def\scinot#1#2% + {#1\times10^{#2}} + +\protect \endinput diff --git a/tex/context/base/mkxl/math-noa.lmt b/tex/context/base/mkxl/math-noa.lmt new file mode 100644 index 000000000..25e1823e2 --- /dev/null +++ b/tex/context/base/mkxl/math-noa.lmt @@ -0,0 +1,2399 @@ +if not modules then modules = { } end modules ['math-noa'] = { + version = 1.001, + optimize = true, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- beware: this is experimental code and there will be a more generic (attribute value +-- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will +-- start cleaning up as by then the bigger picture is clear and code has been used for +-- years; the main handlers will get some extensions) +-- +-- we will also make dedicated processors (faster) +-- +-- beware: names will change as we wil make noads.xxx.handler i.e. xxx +-- subnamespaces + +-- 20D6 -> 2190 +-- 20D7 -> 2192 + +-- todo: most is mathchar_code so we can have simple dedicated loops + +-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types) + +local next, tonumber = next, tonumber +local utfchar, utfbyte = utf.char, utf.byte +local formatters, gmatch = string.formatters, string.gmatch +local sortedhash = table.sortedhash +local insert, remove = table.insert, table.remove +local div, round = math.div, math.round +local bor, band = bit32.bor, bit32.band + +local fonts = fonts +local nodes = nodes +local node = node +local mathematics = mathematics +local context = context + +local otf = fonts.handlers.otf +local otffeatures = fonts.constructors.features.otf +local registerotffeature = otffeatures.register + +local privateattribute = attributes.private +local registertracker = trackers.register +local registerdirective = directives.register +local logreporter = logs.reporter +local setmetatableindex = table.setmetatableindex + +local colortracers = nodes.tracers.colors + +local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end) +local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end) +local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end) +local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end) +local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end) +local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end) +local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end) +local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end) +local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end) +local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end) +local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end) +local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end) +local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end) +local trace_families = false registertracker("math.families", function(v) trace_families = v end) +local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end) +local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end) + +local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end) + +local report_processing = logreporter("mathematics","processing") +local report_remapping = logreporter("mathematics","remapping") +local report_normalizing = logreporter("mathematics","normalizing") +local report_collapsing = logreporter("mathematics","collapsing") +local report_fixing = logreporter("mathematics","fixing") +local report_patching = logreporter("mathematics","patching") +local report_goodies = logreporter("mathematics","goodies") +local report_variants = logreporter("mathematics","variants") +local report_alternates = logreporter("mathematics","alternates") +local report_italics = logreporter("mathematics","italics") +local report_kernpairs = logreporter("mathematics","kernpairs") +local report_domains = logreporter("mathematics","domains") +local report_families = logreporter("mathematics","families") +local report_fences = logreporter("mathematics","fences") +local report_unstacking = logreporter("mathematics","unstack") + +local a_mathrendering = privateattribute("mathrendering") +local a_exportstatus = privateattribute("exportstatus") + +local nuts = nodes.nuts +local nodepool = nuts.pool +local tonut = nuts.tonut +local nutstring = nuts.tostring + +local setfield = nuts.setfield +local setlink = nuts.setlink +local setlist = nuts.setlist +local setnext = nuts.setnext +local setprev = nuts.setprev +local setchar = nuts.setchar +local setfam = nuts.setfam +local setsubtype = nuts.setsubtype +local setattr = nuts.setattr +local setattrlist = nuts.setattrlist +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth + +local getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getboth = nuts.getboth +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local getfont = nuts.getfont +local getfam = nuts.getfam +local getattr = nuts.getattr +local getattrs = nuts.getattrs +local getlist = nuts.getlist +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup +local getsubpre = nuts.getsubpre +local getsuppre = nuts.getsuppre + +local setnucleus = nuts.setnucleus +local setsub = nuts.setsub +local setsup = nuts.setsup +local setsubpre = nuts.setsubpre +local setsuppre = nuts.setsuppre + +local flush_node = nuts.flush +local copy_node = nuts.copy +local slide_nodes = nuts.slide +local set_visual = nuts.setvisual + +local mlist_to_hlist = nuts.mlist_to_hlist + +local new_kern = nodepool.kern +local new_submlist = nodepool.submlist +local new_noad = nodepool.noad +local new_delimiter = nodepool.delimiter +local new_fence = nodepool.fence + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontcharacters = fonthashes.characters +local fontitalics = fonthashes.italics + +local variables = interfaces.variables +local texsetattribute = tex.setattribute +local texgetattribute = tex.getattribute +local getfontoffamily = tex.getfontoffamily +local unsetvalue = attributes.unsetvalue +local implement = interfaces.implement + +local v_reset = variables.reset + +local chardata = characters.data + +noads = noads or { } -- todo: only here +local noads = noads + +noads.processors = noads.processors or { } +local processors = noads.processors + +noads.handlers = noads.handlers or { } +local handlers = noads.handlers + +local tasks = nodes.tasks +local enableaction = tasks.enableaction +local setaction = tasks.setaction + +local nodecodes = nodes.nodecodes +local noadcodes = nodes.noadcodes +local fencecodes = nodes.fencecodes + +local ordnoad_code = noadcodes.ord +local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits +local oplimitsnoad_code = noadcodes.oplimits +local opnolimitsnoad_code = noadcodes.opnolimits +local binnoad_code = noadcodes.bin +local relnode_code = noadcodes.rel +local opennoad_code = noadcodes.open +local closenoad_code = noadcodes.close +local punctnoad_code = noadcodes.punct +local innernoad_code = noadcodes.inner +local undernoad_code = noadcodes.under +local overnoad_code = noadcodes.over +local vcenternoad_code = noadcodes.vcenter +local ordlimitsnoad_code = noadcodes.ordlimits or oplimitsnoad_code + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char +----- style_code = nodecodes.style -- attr style +----- parameter_code = nodecodes.parameter -- attr style +local math_choice = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local leftfence_code = fencecodes.left +local middlefence_code = fencecodes.middle +local rightfence_code = fencecodes.right + +-- local mathclasses = mathematics.classes +-- local fenceclasses = { +-- [leftfence_code] = mathclasses.open, +-- [middlefence_code] = mathclasses.middle, +-- [rightfence_code] = mathclasses.close, +-- } + +-- this initial stuff is tricky as we can have removed and new nodes with the same address +-- the only way out is a free-per-page list of nodes (not bad anyway) + +-- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt +-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st + +local function process(start,what,n,parent) + + if n then + n = n + 1 + else + n = 0 + end + -- + local initial = start + -- + slide_nodes(start) -- we still miss a prev in noads -- fences test code + -- + while start do + local id = getid(start) + if trace_processing then + if id == noad_code then + report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)]) + elseif id == mathchar_code then + local char = getchar(start) + local font = getfont(start) + local fam = getfam(start) + report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char) + else + report_processing("%w%S",n*2,nutstring(start)) + end + end + local proc = what[id] + if proc then + -- report_processing("start processing") + local done, newstart, newinitial = proc(start,what,n,parent) -- prev is bugged: or getprev(start) + if newinitial then + initial = newinitial -- temp hack .. we will make all return head + if newstart then + start = newstart + -- report_processing("stop processing (new start)") + else + -- report_processing("quit processing (done)") + break + end + else + if newstart then + start = newstart + -- report_processing("stop processing (new start)") + else + -- report_processing("stop processing") + end + end + elseif id == noad_code then + -- single characters are like this + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then + break + elseif id == subbox_code or id == submlist_code then + local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !) + elseif id == fraction_code then + local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter + noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter + elseif id == math_choice then + local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list + elseif id == fence_code then + local noad = getfield(start,"delimiter") if noad then process(noad,what,n,start) end -- delimiter + elseif id == radical_code then + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter + noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list + elseif id == accent_code then + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list + -- elseif id == style_code then + -- -- has a next + -- elseif id == parameter_code then + -- -- has a next + -- else + -- -- glue, penalty, etc + end + start = getnext(start) + end + if not parent then + return initial -- only first level -- for now + end +end + +local function processnested(current,what,n) + local noad = nil + local id = getid(current) + if id == noad_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + elseif id == subbox_code or id == submlist_code then + noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !) + elseif id == fraction_code then + noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter + noad = getfield(current,"right") if noad then process(noad,what,n,current) end -- delimiter + elseif id == math_choice then + noad = getfield(current,"display") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list + elseif id == fence_code then + noad = getfield(current,"delimiter") if noad then process(noad,what,n,current) end -- delimiter + elseif id == radical_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter + noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list + elseif id == accent_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list + end +end + +local function processstep(current,process,n,id) + local noad = nil + local id = id or getid(current) + if id == noad_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + elseif id == subbox_code or id == submlist_code then + noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !) + elseif id == fraction_code then + noad = getfield(current,"num") if noad then process(noad,n,current) end -- list + noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list + noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter + noad = getfield(current,"right") if noad then process(noad,n,current) end -- delimiter + elseif id == math_choice then + noad = getfield(current,"display") if noad then process(noad,n,current) end -- list + noad = getfield(current,"text") if noad then process(noad,n,current) end -- list + noad = getfield(current,"script") if noad then process(noad,n,current) end -- list + noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list + elseif id == fence_code then + noad = getfield(current,"delimiter") if noad then process(noad,n,current) end -- delimiter + elseif id == radical_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter + noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list + elseif id == accent_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list + noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list + end +end + +local function processnoads(head,actions,banner) + if trace_processing then + report_processing("start %a",banner) + head = process(head,actions) + report_processing("stop %a",banner) + else + head = process(head,actions) + end + return head +end + +noads.process = processnoads +noads.processnested = processnested +noads.processouter = process + +-- experiment (when not present fall back to fam 0) -- needs documentation + +local unknowns = { } +local checked = { } -- simple case +local tracked = false trackers.register("fonts.missing", function(v) tracked = v end) +local cached = setmetatableindex("table") -- complex case + +local function errorchar(font,char) + local done = unknowns[char] + if done then + unknowns[char] = done + 1 + else + unknowns[char] = 1 + end + if tracked then + -- slower as we check each font too and we always replace as math has + -- more demands than text + local fake = cached[font][char] + if fake then + return fake + else + local kind, fake = fonts.checkers.placeholder(font,char) + if not fake or kind ~= "char" then + fake = 0x3F + end + cached[font][char] = fake + return fake + end + else + -- only simple checking, report at the end so one should take + -- action anyway ... we can miss a few checks but that is ok + -- as there is at least one reported + if not checked[char] then + if trace_normalizing then + report_normalizing("character %C is not available",char) + end + checked[char] = true + end + return 0x3F + end +end + +-- 0-2 regular +-- 3-5 bold +-- 6-8 pseudobold + +-- this could best be integrated in the remapper, and if we run into problems, we +-- might as well do this + +do + + local families = { } + local a_mathfamily = privateattribute("mathfamily") + local boldmap = mathematics.boldmap + + local familymap = { [0] = + "regular", + "regular", + "regular", + "bold", + "bold", + "bold", + "pseudobold", + "pseudobold", + "pseudobold", + } + + families[fraction_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[noad_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[mathchar_code] = function(pointer) + if getfam(pointer) == 0 then + local a = getattr(pointer,a_mathfamily) + if a and a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + local char = getchar(pointer) + local bold = boldmap[char] + local newa = a - 3 + if not bold then + if trace_families then + report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) + end + setfam(pointer,newa) + elseif not fontcharacters[getfontoffamily(newa)][bold] then + if trace_families then + report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) + end + if newa > 3 then + setfam(pointer,newa-3) + end + else + setattr(pointer,a_exportstatus,char) + setchar(pointer,bold) + if trace_families then + report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) + end + setfam(pointer,newa) + end + else + local char = getchar(pointer) + if not fontcharacters[getfontoffamily(a)][char] then + if trace_families then + report_families("no bold replacement for %C",char) + end + else + if trace_families then + report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) + end + setfam(pointer,a) + end + end + end + end + end + families[delimiter_code] = function(pointer) + if getfield(pointer,"small_fam") == 0 then + local a = getattr(pointer,a_mathfamily) + if a and a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + -- no bold delimiters in unicode + a = a - 3 + end + local char = getfield(pointer,"small_char") + local okay = fontcharacters[getfontoffamily(a)][char] + if okay then + setfield(pointer,"small_fam",a) + elseif a > 2 then + setfield(pointer,"small_fam",a-3) + end + local char = getfield(pointer,"large_char") + local okay = fontcharacters[getfontoffamily(a)][char] + if okay then + setfield(pointer,"large_fam",a) + elseif a > 2 then + setfield(pointer,"large_fam",a-3) + end + else + setfield(pointer,"small_fam",0) + setfield(pointer,"large_fam",0) + end + end + end + + -- will become: + + -- families[delimiter_code] = function(pointer) + -- if getfam(pointer) == 0 then + -- local a = getattr(pointer,a_mathfamily) + -- if a and a > 0 then + -- setattr(pointer,a_mathfamily,0) + -- if a > 5 then + -- -- no bold delimiters in unicode + -- a = a - 3 + -- end + -- local char = getchar(pointer) + -- local okay = fontcharacters[getfontoffamily(a)][char] + -- if okay then + -- setfam(pointer,a) + -- elseif a > 2 then + -- setfam(pointer,a-3) + -- end + -- else + -- setfam(pointer,0) + -- end + -- end + -- end + + families[mathtextchar_code] = families[mathchar_code] + + function handlers.families(head,style,penalties) + processnoads(head,families,"families") + return true -- not needed + end + +end + +-- character remapping + +do + + local a_mathalphabet = privateattribute("mathalphabet") + local a_mathgreek = privateattribute("mathgreek") + + local relocate = { } + + local remapalphabets = mathematics.remapalphabets + local fallbackstyleattr = mathematics.fallbackstyleattr + local setnodecolor = colortracers.set + + local function report_remap(tag,id,old,new,extra) + report_remapping("remapping %s in font (%s,%s) from %C to %C%s", + tag,id,fontdata[id].properties.fontname or "",old,new,extra) + end + + local function checked(pointer) + local char = getchar(pointer) + local font = getfont(pointer) + local data = fontcharacters[font] + if not data[char] then + local specials = characters.data[char].specials + if specials and (specials[1] == "char" or specials[1] == "font") then + local newchar = specials[#specials] + if trace_remapping then + report_remap("fallback",font,char,newchar) + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setattr(pointer,a_exportstatus,char) -- testcase: exponentiale + setchar(pointer,newchar) + return true + end + end + end + + -- We can optimize this if we really think that math is a bottleneck which it never + -- really is. + + relocate[mathchar_code] = function(pointer) + local g = getattr(pointer,a_mathgreek) or 0 + local a = getattr(pointer,a_mathalphabet) or 0 + -- local g, a = getattrs(pointer,a_mathgreek,a_mathalphabet) + -- if not a then a = 0 end + -- if not g then g = 0 end + local char = getchar(pointer) + local font = getfont(pointer) + local characters = fontcharacters[font] + if a > 0 or g > 0 then + if a > 0 then + -- not really critital but we could use properties + setattr(pointer,a_mathgreek,0) + end + if g > 0 then + -- not really critital but we could use properties + setattr(pointer,a_mathalphabet,0) + end + local newchar = remapalphabets(char,a,g) + if newchar then + local newchardata = characters[newchar] + if newchardata then + if trace_remapping then + report_remap("char",font,char,newchar,newchardata.commands and " (virtual)" or "") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setchar(pointer,newchar) + return true + else + local fallback = fallbackstyleattr(a) + if fallback then + local newchar = remapalphabets(char,fallback,g) + if newchar then + if characters[newchar] then + if trace_remapping then + report_remap("char",font,char,newchar," (fallback remapping used)") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setchar(pointer,newchar) + return true + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback character)") + end + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback remap character)") + end + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback style)") + end + end + elseif trace_remapping then + local chardata = characters[char] + if chardata and chardata.commands then + report_remap("char",font,char,char," (virtual)") + end + end + end + if not characters[char] then + setchar(pointer,errorchar(font,char)) + end + if trace_analyzing then + setnodecolor(pointer,"font:medi") + end + if check_coverage then + return checked(pointer) + end + end + + relocate[mathtextchar_code] = function(pointer) + if trace_analyzing then + setnodecolor(pointer,"font:init") + end + end + + relocate[delimiter_code] = function(pointer) + if trace_analyzing then + setnodecolor(pointer,"font:fina") + end + end + + function handlers.relocate(head,style,penalties) + processnoads(head,relocate,"relocate") + return true -- not needed + end + +end + +-- rendering (beware, not exported) + +do + + local render = { } + + local rendersets = mathematics.renderings.numbers or { } -- store + + render[mathchar_code] = function(pointer) + local attr = getattr(pointer,a_mathrendering) + if attr and attr > 0 then + local char = getchar(pointer) + local renderset = rendersets[attr] + if renderset then + local newchar = renderset[char] + if newchar then + local font = getfont(pointer) + local characters = fontcharacters[font] + if characters and characters[newchar] then + setchar(pointer,newchar) + setattr(pointer,a_exportstatus,char) + end + end + end + end + end + + function handlers.render(head,style,penalties) + processnoads(head,render,"render") + return true -- not needed + end + +end + +-- some resize options (this works ok because the content is +-- empty and no larger next will be forced) +-- +-- beware: we don't use \delcode but \Udelcode and as such have +-- no large_fam; also, we need to check for subtype and/or +-- small_fam not being 0 because \. sits in 0,0 by default +-- +-- todo: just replace the character by an ord noad +-- and remove the right delimiter as well + +do + + local a_mathsize = privateattribute("mathsize") -- this might move into other fence code + local resize = { } + + resize[fence_code] = function(pointer) + local subtype = getsubtype(pointer) + if subtype == leftfence_code or subtype == rightfence_code then + local a = getattr(pointer,a_mathsize) + if a and a > 0 then + local method = div(a,100) + local size = a % 100 + setattr(pointer,a_mathsize,0) + local delimiter = getfield(pointer,"delimiter") + local chr = getchar(delimiter) + if chr > 0 then + local fam = getfam(delimiter) + local id = getfontoffamily(fam) + if id > 0 then + local data = fontdata[id] + local char = mathematics.big(data,chr,size,method) + local ht = getheight(pointer) + local dp = getdepth(pointer) + if ht == 1 or dp == 1 then -- 1 scaled point is a signal + local chardata = data.characters[char] + if ht == 1 then + setheight(pointer,chardata.height) + end + if dp == 1 then + setdepth(pointer,chardata.depth) + end + end + if trace_fences then + report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size) + end + setchar(delimiter,char) + end + end + end + end + end + + function handlers.resize(head,style,penalties) + processnoads(head,resize,"resize") + return true -- not needed + end + +end + +-- still not perfect: + +do + + local a_autofence = privateattribute("mathautofence") + local autofences = { } + local dummyfencechar = 0x2E + + local function makefence(what,char) + local d = new_delimiter() -- todo: attr + local f = new_fence() -- todo: attr + if char then + local sym = getnucleus(char) + local chr = getchar(sym) + local fam = getfam(sym) + if chr == dummyfencechar then + chr = 0 + end + setchar(d,chr) + setfam(d,fam) + flush_node(sym) + end + setattrlist(d,char) + setattrlist(f,char) + setsubtype(f,what) + setfield(f,"delimiter",d) + setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what] + return f + end + + local function show(where,pointer) + print("") + local i = 0 + for n in nuts.traverse(pointer) do + i = i + 1 + print(i,where,nuts.tonode(n)) + end + print("") + end + + local function makelist(middle,noad,f_o,o_next,c_prev,f_c) +-- report_fences( +-- "middle %s, noad %s, open %s, opennext %s, closeprev %s, close %s", +-- middle or "?", +-- noad or "?", +-- f_o or "?", +-- o_next or "?", +-- c_prev or "?", +-- f_c or "?" +-- ) + local list = new_submlist() + setsubtype(noad,innernoad_code) + setnucleus(noad,list) + setlist(list,f_o) + setlink(f_o,o_next) -- prev of list is nil + setlink(c_prev,f_c) -- next of list is nil +-- show("list",f_o) + if middle and next(middle) then + local prev = f_o + local current = o_next + while current ~= f_c do + local midl = middle[current] + local next = getnext(current) + if midl then + local fence = makefence(middlefence_code,current) + setnucleus(current) + flush_node(current) + middle[current] = nil + -- replace_node + setlink(prev,fence,next) + prev = fence + else + prev = current + end + current = next + end + end + return noad + end + + -- relinking is now somewhat overdone + + local function convert_both(open,close,middle) + local o_next = getnext(open) + if o_next == close then + return close + else + local c_prev, c_next = getboth(close) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code,close) + makelist(middle,open,f_o,o_next,c_prev,f_c) + setnucleus(close) + flush_node(close) + -- open is now a list + setlink(open,c_next) + return open + end + end + + local function convert_open(open,last,middle) -- last is really last (final case) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code) + local o_next = getnext(open) + makelist(middle,open,f_o,o_next,last,nil) + -- open is now a list + setlink(open,l_next) + return open + end + + local function convert_close(first,close,middle) + local f_o = makefence(leftfence_code) + local f_c = makefence(rightfence_code,close) + local c_prev = getprev(close) + local f_next = getnext(first) + makelist(middle, close, f_o,f_next,c_prev,f_c) + -- close is now a list + if c_prev ~= first then + setlink(first,close) + end + return close + end + + local stacks = setmetatableindex("table") + + -- 1=open 2=close 3=middle 4=both + + local function processfences(pointer,n,parent) + local current = pointer + local last = pointer + local start = pointer + local done = false + local initial = pointer + local stack = nil + local middle = nil -- todo: use properties + while current do +-- show("before",pointer) + local id = getid(current) + if id == noad_code then + local a = getattr(current,a_autofence) + if a and a > 0 then + local stack = stacks[n] + setattr(current,a_autofence,0) -- hm, better use a property + local level = #stack + if a == 1 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"open","open") + end + insert(stack,current) + elseif a == 2 then + local open = remove(stack) + if open then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","both") + end + current = convert_both(open,current,middle) + elseif current == start then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","skip") + end + else + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","close") + end + current = convert_close(initial,current,middle) + if not parent then + initial = current + end + end + elseif a == 3 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"middle","middle") + end + if middle then + middle[current] = last + else + middle = { [current] = last } + end + elseif a == 4 then + if not stack or #stack == 0 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","open") + end + insert(stack,current) + else + local open = remove(stack) + if open then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","both") + end + current = convert_both(open,current,middle) + elseif current == start then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","skip") + end + else + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","close") + end + current = convert_close(initial,current,middle) + if not parent then + initial = current + end + end + end + end + done = true + else + processstep(current,processfences,n+1,id) + end + else + -- next at current level + processstep(current,processfences,n,id) + end +-- show("after",pointer) + last = current + current = getnext(current) + end + if done then + local stack = stacks[n] + local s = #stack + if s > 0 then + for i=1,s do + local open = remove(stack) + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,#stack,"flush","open") + end + last = convert_open(open,last,middle) + end +-- show("done",pointer) + end + end + end + + -- we can have a first changed node .. an option is to have a leading dummy node in math + -- lists like the par node as it can save a lot of mess + + local enabled = false + + implement { + name = "enableautofences", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.autofences") + enabled = true + end + } + + function handlers.autofences(head,style,penalties) + if enabled then -- tex.modes.c_math_fences_auto + -- inspect(nodes.totree(head)) + processfences(head,1) + -- inspect(nodes.totree(head)) + end + end + +end + +-- normalize scripts + +do + + local unscript = { } noads.processors.unscript = unscript + local superscripts = characters.superscripts + local subscripts = characters.subscripts + local fractions = characters.fractions + local replaced = { } + + local function replace(pointer,what,n,parent) + pointer = parent -- we're following the parent list (chars trigger this) + local next = getnext(pointer) + local start_super, stop_super, start_sub, stop_sub + local mode = "unset" + while next and getid(next) == noad_code do + local nextnucleus = getnucleus(next) + if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then + local char = getchar(nextnucleus) + local s = superscripts[char] + if s then + if not start_super then + start_super = next + mode = "super" + elseif mode == "sub" then + break + end + stop_super = next + next = getnext(next) + setchar(nextnucleus,s) + replaced[char] = (replaced[char] or 0) + 1 + if trace_normalizing then + report_normalizing("superscript %C becomes %C",char,s) + end + else + local s = subscripts[char] + if s then + if not start_sub then + start_sub = next + mode = "sub" + elseif mode == "super" then + break + end + stop_sub = next + next = getnext(next) + setchar(nextnucleus,s) + replaced[char] = (replaced[char] or 0) + 1 + if trace_normalizing then + report_normalizing("subscript %C becomes %C",char,s) + end + else + break + end + end + else + break + end + end + if start_super then + if start_super == stop_super then + setsup(pointer,getnucleus(start_super)) + else + local list = new_submlist() -- todo attr + setlist(list,start_super) + setsup(pointer,list) + end + if mode == "super" then + setnext(pointer,getnext(stop_super)) + end + setnext(stop_super) + end + if start_sub then + +-- if mode == "sub" then +-- local sup = getsup(pointer) +-- if sup and not getsub(pointer) then +-- local nxt = getnext(pointer) +-- local new = new_noad(pointer) +-- setnucleus(new,new_submlist()) +-- setlink(pointer,new,nxt) +-- pointer = new +-- end +-- end + + if start_sub == stop_sub then + setsub(pointer,getnucleus(start_sub)) + else + local list = new_submlist() -- todo attr + setlist(list,start_sub) + setsub(pointer,list) + end + if mode == "sub" then + setnext(pointer,getnext(stop_sub)) + end + setnext(stop_sub) + end + -- we could return stop + end + + unscript[mathchar_code] = replace -- not noads as we need to recurse + + function handlers.unscript(head,style,penalties) + processnoads(head,unscript,"unscript") + return true -- not needed + end + +end + +do + + local unstack = { } noads.processors.unstack = unstack + local enabled = false + local a_unstack = privateattribute("mathunstack") + + unstack[noad_code] = function(pointer) + if getattr(pointer,a_unstack) then + local sup = getsup(pointer) + local sub = getsub(pointer) + if sup and sub then + -- if trace_unstacking then + -- report_unstacking() -- todo ... what to show ... + -- end + local nxt = getnext(pointer) + local new = new_noad(pointer) + setnucleus(new,new_submlist()) + setsub(pointer) + setsub(new,sub) + setlink(pointer,new,nxt) + end + end + end + + function handlers.unstack(head,style,penalties) + if enabled then + processnoads(head,unstack,"unstack") + return true -- not needed + end + end + + implement { + name = "enablescriptunstacking", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.unstack") + enabled = true + end + } + +end + +do + + local function collected(list) + if list and next(list) then + local n, t = 0, { } + for k, v in sortedhash(list) do + n = n + 1 + t[n] = formatters["%C"](k) + end + return formatters["% t (n=%s)"](t,n) + end + end + + statistics.register("math script replacements", function() + return collected(replaced) + end) + + statistics.register("unknown math characters", function() + return collected(unknowns) + end) + +end + +-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$) +-- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$) + +-- todo: set alternate for specific symbols +-- todo: no need to do this when already loaded +-- todo: use a fonts.hashes.mathalternates + +do + + local last = 0 + + local known = setmetatableindex(function(t,k) + local v = bor(0,2^last) + t[k] = v + last = last + 1 + return v + end) + + local defaults = { + dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, + -- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet) + } + + local function initializemathalternates(tfmdata) + local goodies = tfmdata.goodies + local autolist = defaults -- table.copy(defaults) + + local function setthem(newalternates) + local resources = tfmdata.resources -- was tfmdata.shared + local mathalternates = resources.mathalternates + local alternates, attributes, registered, presets + if mathalternates then + alternates = mathalternates.alternates + attributes = mathalternates.attributes + registered = mathalternates.registered + else + alternates, attributes, registered = { }, { }, { } + mathalternates = { + attributes = attributes, + alternates = alternates, + registered = registered, + presets = { }, + resets = { }, + hashes = setmetatableindex("table") + } + resources.mathalternates = mathalternates + end + -- + for name, data in sortedhash(newalternates) do + if alternates[name] then + -- ignore + else + local attr = known[name] + attributes[attr] = data + alternates[name] = attr + registered[#registered+1] = attr + end + end + end + + if goodies then + local done = { } + for i=1,#goodies do + -- first one counts + -- we can consider sharing the attributes ... todo (only once scan) + local mathgoodies = goodies[i].mathematics + local alternates = mathgoodies and mathgoodies.alternates + if alternates then + if trace_goodies then + report_goodies("loading alternates for font %a",tfmdata.properties.name) + end + for k, v in next, autolist do + if not alternates[k] then + alternates[k] = v + end + end + setthem(alternates) + return + end + end + end + + if trace_goodies then + report_goodies("loading default alternates for font %a",tfmdata.properties.name) + end + setthem(autolist) + + end + + registerotffeature { + name = "mathalternates", + description = "additional math alternative shapes", + initializers = { + base = initializemathalternates, + node = initializemathalternates, + } + } + + -- local getalternate = otf.getalternate (runtime new method so ...) + + -- todo: not shared but copies ... one never knows + + local a_mathalternate = privateattribute("mathalternate") + local alternate = { } -- processors.alternate = alternate + local fontdata = fonts.hashes.identifiers + local fontresources = fonts.hashes.resources + + local function getalternate(fam,tag,current) + local resources = fontresources[getfontoffamily(fam)] + local attribute = unsetvalue + if resources then + local mathalternates = resources.mathalternates + if mathalternates then + local presets = mathalternates.presets + if presets then + local resets = mathalternates.resets + attribute = presets[tag] + if not attribute then + attribute = 0 + local alternates = mathalternates.alternates + for s in gmatch(tag,"[^, ]+") do + if s == v_reset then + resets[tag] = true + current = unsetvalue + else + local a = alternates[s] -- or known[s] + if a then + attribute = bor(attribute,a) + end + end + end + if attribute == 0 then + attribute = unsetvalue + end + presets[tag] = attribute + elseif resets[tag] then + current = unsetvalue + end + end + end + end + if attribute > 0 and current and current > 0 then + return bor(current,attribute) + else + return attribute + end + end + + local function presetalternate(fam,tag) + texsetattribute(a_mathalternate,getalternate(fam,tag)) + end + + implement { + name = "presetmathalternate", + actions = presetalternate, + arguments = { "integer", "string" } + } + + local function setalternate(fam,tag) + local a = texgetattribute(a_mathalternate) + local v = getalternate(fam,tag,a) + texsetattribute(a_mathalternate,v) + end + + implement { + name = "setmathalternate", + actions = setalternate, + arguments = { "integer", "string" } + } + + alternate[mathchar_code] = function(pointer) -- slow + local a = getattr(pointer,a_mathalternate) + if a and a > 0 then + setattr(pointer,a_mathalternate,0) + local fontid = getfont(pointer) + local resources = fontresources[fontid] + if resources then + local mathalternates = resources.mathalternates + if mathalternates then + local attributes = mathalternates.attributes + local registered = mathalternates.registered + local hashes = mathalternates.hashes + for i=1,#registered do + local r = registered[i] + if band(a,r) ~= 0 then + local char = getchar(pointer) + local alt = hashes[i][char] + if alt == nil then + local what = attributes[r] + alt = otf.getalternate(fontdata[fontid],char,what.feature,what.value) or false + if alt == char then + alt = false + end + hashes[i][char] = alt + end + if alt then + if trace_alternates then + local what = attributes[r] + report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U", + tostring(what.feature),tostring(what.value),getchar(pointer),alt) + end + setchar(pointer,alt) + break + end + end + end + end + end + end + end + + function handlers.alternates(head,style,penalties) + processnoads(head,alternate,"alternate") + return true -- not needed + end + +end + +-- italics: we assume that only characters matter +-- +-- = we check for correction first because accessing nodes is slower +-- = the actual glyph is not that important (we can control it with numbers) + +-- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on +-- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all +-- those heuristics. We want to deal with it ourselves also in the perspective of mixed math +-- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and +-- real ones. + +-- in opentype the italic correction of a limop is added to the width and luatex does +-- some juggling that we want to avoid but we need to do something here (in fact, we could +-- better fix the width of the character) + +do + + local a_mathitalics = privateattribute("mathitalics") + + local italics = { } + local default_factor = 1/20 + + local setcolor = colortracers.set + local resetcolor = colortracers.reset + local italic_kern = new_kern + + local c_positive_d = "trace:dg" + local c_negative_d = "trace:dr" + + local function insert_kern(current,kern) + local sub = new_submlist() -- todo: attr + local noad = new_noad() -- todo: attr + setlist(sub,kern) + setnext(kern,noad) + setnucleus(noad,current) + return sub + end + + registertracker("math.italics.visualize", function(v) + if v then + italic_kern = function(k) + local n = new_kern(k) -- todo: attr + set_visual(n,"italic") + return n + end + else + italic_kern = new_kern + end + end) + + local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) + + local visual = chardata[char].visual + + if method == 1 then + -- check on state + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + elseif method == 2 then + -- no check + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + elseif method == 3 then + -- check on visual + if visual == "it" or visual == "bi" then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + elseif method == 4 then + -- combination of 1 and 3 + local italics = fontitalics[font] + if italics and (visual == "it" or visual == "bi") then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + end + + end + + italics[mathchar_code] = function(pointer,what,n,parent) + local method = getattr(pointer,a_mathitalics) + if method and method > 0 and method < 100 then + local char = getchar(pointer) + local font = getfont(pointer) + local correction, visual = getcorrection(method,font,char) + if correction and correction ~= 0 then + local next_noad = getnext(parent) + if not next_noad then + if n == 1 then + -- only at the outer level .. will become an option (always,endonly,none) + if trace_italics then + report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) + end + if correction > 0 then + correction = correction + 100 + else + correction = correction - 100 + end + correction = round(correction) + setattr(pointer,a_mathitalics,correction) + setattr(parent,a_mathitalics,correction) + return -- so no reset later on + end + end + end + end + setattr(pointer,a_mathitalics,unsetvalue) + end + + function handlers.italics(head,style,penalties) + processnoads(head,italics,"italics") + return true -- not needed + end + + local enable = function() + enableaction("math", "noads.handlers.italics") + if trace_italics then + report_italics("enabling math italics") + end + -- we enable math (unless already enabled elsewhere) + typesetters.italics.enablemath() + enable = false + end + + -- best do this only on math mode (less overhead) + + function mathematics.setitalics(name) + if enable then + enable() + end + texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none + end + + function mathematics.getitalics(name) + if enable then + enable() + end + context(name and name ~= v_reset and tonumber(name) or unsetvalue) + end + + function mathematics.resetitalics() + texsetattribute(a_mathitalics,unsetvalue) + end + + implement { + name = "initializemathitalics", + actions = enable, + onlyonce = true, + } + + implement { + name = "setmathitalics", + actions = mathematics.setitalics, + arguments = "string", + } + + implement { + name = "getmathitalics", + actions = mathematics.getitalics, + arguments = "string", + } + + implement { + name = "resetmathitalics", + actions = mathematics.resetitalics + } + +end + +do + + -- math kerns (experiment) in goodies: + -- + -- mathematics = { + -- kernpairs = { + -- [0x1D44E] = { + -- [0x1D44F] = 400, -- 𝑎𝑏 + -- } + -- }, + -- } + + local a_kernpairs = privateattribute("mathkernpairs") + local kernpairs = { } + + local function enable() + enableaction("math", "noads.handlers.kernpairs") + if trace_kernpairs then + report_kernpairs("enabling math kern pairs") + end + enable = false + end + + implement { + name = "initializemathkernpairs", + actions = enable, + onlyonce = true, + } + + local hash = setmetatableindex(function(t,font) + local g = fontdata[font].goodies + local m = g and g[1] and g[1].mathematics + local k = m and m.kernpairs + t[font] = k + return k + end) + + -- no correction after prime because that moved to a superscript + + kernpairs[mathchar_code] = function(pointer,what,n,parent) + if getattr(pointer,a_kernpairs) == 1 then + local font = getfont(pointer) + local list = hash[font] + if list then + local first = getchar(pointer) + local found = list[first] + if found then + local next = getnext(parent) + if next and getid(next) == noad_code then + pointer = getnucleus(next) + if pointer then + if getfont(pointer) == font then + local second = getchar(pointer) + local kern = found[second] + if kern then + kern = kern * fonts.hashes.parameters[font].hfactor + if trace_kernpairs then + report_kernpairs("adding %p kerning between %C and %C",kern,first,second) + end + setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr + end + end + end + end + end + end + end + end + + function handlers.kernpairs(head,style,penalties) + processnoads(head,kernpairs,"kernpairs") + return true -- not needed + end + +end + +-- primes and such + +do + + -- is validpair stil needed? + + local a_mathcollapsing = privateattribute("mathcollapsing") + local collapse = { } + local mathlists = characters.mathlists + local validpair = { + [ordnoad_code] = true, + [opdisplaylimitsnoad_code] = true, + [oplimitsnoad_code] = true, + [opnolimitsnoad_code] = true, + [binnoad_code] = true, -- new + [relnode_code] = true, + [opennoad_code] = true, -- new + [closenoad_code] = true, -- new + [punctnoad_code] = true, -- new + [innernoad_code] = false, + [undernoad_code] = false, + [overnoad_code] = false, + [vcenternoad_code] = false, + [ordlimitsnoad_code] = true, + } + + local reported = setmetatableindex("table") + + collapse[mathchar_code] = function(pointer,what,n,parent) + + if parent and mathlists[getchar(pointer)] then + local found, last, lucleus, lsup, lsub, category + local tree = mathlists + local current = parent + while current and validpair[getsubtype(current)] do + local nucleus = getnucleus(current) -- == pointer + local sub = getsub(current) + local sup = getsup(current) + local char = getchar(nucleus) + if char then + local match = tree[char] + if match then + local method = getattr(current,a_mathcollapsing) + if method and method > 0 and method <= 3 then + local specials = match.specials + local mathlist = match.mathlist + local ligature + if method == 1 then + ligature = specials + elseif method == 2 then + ligature = specials or mathlist + else -- 3 + ligature = mathlist or specials + end + if ligature then + category = mathlist and "mathlist" or "specials" + found = ligature + last = current + lucleus = nucleus + lsup = sup + lsub = sub + end + tree = match + if sub or sup then + break + else + current = getnext(current) + end + else + break + end + else + break + end + else + break + end + end + if found and last and lucleus then + local id = getfont(lucleus) + local characters = fontcharacters[id] + local replace = characters and characters[found] + if not replace then + if not reported[id][found] then + reported[id][found] = true + report_collapsing("%s ligature %C from %s","ignoring",found,category) + end + elseif trace_collapsing then + report_collapsing("%s ligature %C from %s","creating",found,category) + end + setchar(pointer,found) + local l = getnext(last) + local c = getnext(parent) + if lsub then + setsub(parent,lsub) + setsub(last) + end + if lsup then + setsup(parent,lsup) + setsup(last) + end + while c ~= l do + local n = getnext(c) + flush_node(c) + c = n + end + setlink(parent,l) + end + end + end + + function noads.handlers.collapse(head,style,penalties) + processnoads(head,collapse,"collapse") + return true -- not needed + end + + local enable = function() + enableaction("math", "noads.handlers.collapse") + if trace_collapsing then + report_collapsing("enabling math collapsing") + end + enable = false + end + + implement { + name = "initializemathcollapsing", + actions = enable, + onlyonce = true, + } + +end + +do + -- inner under over vcenter + + local fixscripts = { } + local movesub = { + -- primes + [0x2032] = 0xFE932, + [0x2033] = 0xFE933, + [0x2034] = 0xFE934, + [0x2057] = 0xFE957, + -- reverse primes + [0x2035] = 0xFE935, + [0x2036] = 0xFE936, + [0x2037] = 0xFE937, + } + + mathematics.virtualize(movesub) + + local options_supported = tokens.defined("Unosuperscript") + + local function fixsupscript(parent,current,current_char,new_char) + if new_char ~= current_char and new_char ~= true then + setchar(current,new_char) + if trace_fixing then + report_fixing("fixing subscript, replacing superscript %U by %U",current_char,new_char) + end + else + if trace_fixing then + report_fixing("fixing subscript, superscript %U",current_char) + end + end + if options_supported then + setfield(parent,"options",0x08+0x22) + end + end + + -- local function movesubscript(parent,current_nucleus,oldchar,newchar) + -- local prev = getprev(parent) + -- if prev and getid(prev) == noad_code then + -- local psup = getsup(prev) + -- local psub = getsub(prev) + -- if not psup and not psub then + -- fixsupscript(prev,current_nucleus,oldchar,newchar) + -- local nucleus = getnucleus(parent) + -- local sub = getsub(parent) + -- setsup(prev,nucleus) + -- setsub(prev,sub) + -- local dummy = copy_node(nucleus) + -- setchar(dummy,0) + -- setnucleus(parent,dummy) + -- setsub(parent) + -- elseif not psup then + -- fixsupscript(prev,current_nucleus,oldchar,newchar) + -- local nucleus = getnucleus(parent) + -- setsup(prev,nucleus) + -- local dummy = copy_node(nucleus) + -- setchar(dummy,0) + -- setnucleus(parent,dummy) + -- end + -- end + -- end + + local function move_none_none(parent,prev,nuc,oldchar,newchar) + fixsupscript(prev,nuc,oldchar,newchar) + local sub = getsub(parent) + setsup(prev,nuc) + setsub(prev,sub) + local dummy = copy_node(nuc) + setchar(dummy,0) + setnucleus(parent,dummy) + setsub(parent) + end + + local function move_none_psub(parent,prev,nuc,oldchar,newchar) + fixsupscript(prev,nuc,oldchar,newchar) + setsup(prev,nuc) + local dummy = copy_node(nuc) + setchar(dummy,0) + setnucleus(parent,dummy) + end + + fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off + if parent then + local oldchar = getchar(pointer) + local newchar = movesub[oldchar] + if newchar then + local nuc = getnucleus(parent) + if pointer == nuc then + local sub = getsub(pointer) + local sup = getsup(pointer) + if sub then + if sup then + -- print("[char] sub sup") + else + -- print("[char] sub ---") + end + elseif sup then + -- print("[char] --- sup") + else + local prev = getprev(parent) + if prev and getid(prev) == noad_code then + local psub = getsub(prev) + local psup = getsup(prev) + if psub then + if psup then + -- print("sub sup [char] --- ---") + else + -- print("sub --- [char] --- ---") + move_none_psub(parent,prev,nuc,oldchar,newchar) + end + elseif psup then + -- print("--- sup [char] --- ---") + else + -- print("[char] --- ---") + move_none_none(parent,prev,nuc,oldchar,newchar) + end + else + -- print("no prev [char]") + end + end + else + -- print("[char]") + end + end + end + end + + function noads.handlers.fixscripts(head,style,penalties) + processnoads(head,fixscripts,"fixscripts") + return true -- not needed + end + +end + +-- variants + +do + + local variants = { } + local validvariants = { -- fast check on valid + [0x2229] = 0xFE00, [0x222A] = 0xFE00, + [0x2268] = 0xFE00, [0x2269] = 0xFE00, + [0x2272] = 0xFE00, [0x2273] = 0xFE00, + [0x228A] = 0xFE00, [0x228B] = 0xFE00, + [0x2293] = 0xFE00, [0x2294] = 0xFE00, + [0x2295] = 0xFE00, + [0x2297] = 0xFE00, + [0x229C] = 0xFE00, + [0x22DA] = 0xFE00, [0x22DB] = 0xFE00, + [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00, + [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00, + [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00, + [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, + } + + variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value + local char = getchar(pointer) + local selector = validvariants[char] + if selector then + local next = getnext(parent) + if next and getid(next) == noad_code then + local nucleus = getnucleus(next) + if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then + local variant + local tfmdata = fontdata[getfont(pointer)] + local mathvariants = tfmdata.resources.variants -- and variantdata + if mathvariants then + mathvariants = mathvariants[selector] + if mathvariants then + variant = mathvariants[char] + end + end + if variant then + setchar(pointer,variant) + setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup + if trace_variants then + report_variants("variant (%U,%U) replaced by %U",char,selector,variant) + end + else + if trace_variants then + report_variants("no variant (%U,%U)",char,selector) + end + end + setprev(next,pointer) + setnext(parent,getnext(next)) + flush_node(next) + end + end + end + end + + function handlers.variants(head,style,penalties) + processnoads(head,variants,"unicode variant") + return true -- not needed + end + +end + +-- for manuals + +do + + local classes = { } + local colors = { + [relnode_code] = "trace:dr", + [ordnoad_code] = "trace:db", + [binnoad_code] = "trace:dg", + [opennoad_code] = "trace:dm", + [closenoad_code] = "trace:dm", + [punctnoad_code] = "trace:dc", + -- [opdisplaylimitsnoad_code] = "", + -- [oplimitsnoad_code] = "", + -- [opnolimitsnoad_code] = "", + -- [ordlimitsnoad_code] = "", + -- [innernoad_code = "", + -- [undernoad_code] = "", + -- [overnoad_code] = "", + -- [vcenternoad_code] = "", + } + + local setcolor = colortracers.set + local resetcolor = colortracers.reset + + classes[mathchar_code] = function(pointer,what,n,parent) + local color = colors[getsubtype(parent)] + if color then + setcolor(pointer,color) + else + resetcolor(pointer) + end + end + + function handlers.classes(head,style,penalties) + processnoads(head,classes,"classes") + return true -- not needed + end + + registertracker("math.classes",function(v) + setaction("math","noads.handlers.classes",v) + end) + +end + +-- experimental + +do + + -- mathematics.registerdomain { + -- name = "foo", + -- parents = { "bar" }, + -- characters = { + -- [0x123] = { char = 0x234, class = binary }, + -- }, + -- } + + local domains = { } + local categories = { } + local numbers = { } + local a_mathdomain = privateattribute("mathdomain") + mathematics.domains = categories + local permitted = { + ordinary = ordnoad_code, + binary = binnoad_code, + relation = relnode_code, + punctuation = punctnoad_code, + inner = innernoad_code, + } + + function mathematics.registerdomain(data) + local name = data.name + if not name then + return + end + local attr = #numbers + 1 + categories[name] = data + numbers[attr] = data + data.attribute = attr + -- we delay hashing + return attr + end + + local enable + + enable = function() + enableaction("math", "noads.handlers.domains") + if trace_domains then + report_domains("enabling math domains") + end + enable = false + end + + function mathematics.setdomain(name) + if enable then + enable() + end + local data = name and name ~= v_reset and categories[name] + texsetattribute(a_mathdomain,data and data.attribute or unsetvalue) + end + + function mathematics.getdomain(name) + if enable then + enable() + end + local data = name and name ~= v_reset and categories[name] + context(data and data.attribute or unsetvalue) + end + + implement { + name = "initializemathdomain", + actions = enable, + onlyonce = true, + } + + implement { + name = "setmathdomain", + arguments = "string", + actions = mathematics.setdomain, + } + + implement { + name = "getmathdomain", + arguments = "string", + actions = mathematics.getdomain, + } + + local function makehash(data) + local hash = { } + local parents = data.parents + if parents then + local function merge(name) + if name then + local c = categories[name] + if c then + local hash = c.hash + if not hash then + hash = makehash(c) + end + for k, v in next, hash do + hash[k] = v + end + end + end + end + if type(parents) == "string" then + merge(parents) + elseif type(parents) == "table" then + for i=1,#parents do + merge(parents[i]) + end + end + end + local characters = data.characters + if characters then + for k, v in next, characters do + -- local chr = n.char + local cls = v.class + if cls then + v.code = permitted[cls] + else + -- invalid class + end + hash[k] = v + end + end + data.hash = hash + return hash + end + + domains[mathchar_code] = function(pointer,what,n,parent) + local attr = getattr(pointer,a_mathdomain) + if attr then + local domain = numbers[attr] + if domain then + local hash = domain.hash + if not hash then + hash = makehash(domain) + end + local char = getchar(pointer) + local okay = hash[char] + if okay then + local chr = okay.char + local cls = okay.code + if chr and chr ~= char then + setchar(pointer,chr) + end + if cls and cls ~= getsubtype(parent) then + setsubtype(parent,cls) + end + end + end + end + end + + function handlers.domains(head,style,penalties) + processnoads(head,domains,"domains") + return true -- not needed + end + +end + +-- just for me + +function handlers.showtree(head,style,penalties) + inspect(nodes.totree(tonut(head))) +end + +registertracker("math.showtree",function(v) + setaction("math","noads.handlers.showtree",v) +end) + +-- also for me + +do + + local applyvisuals = nuts.applyvisuals + local visual = false + + function handlers.makeup(head) + applyvisuals(head,visual) + end + + registertracker("math.makeup",function(v) + visual = v + setaction("math","noads.handlers.makeup",v) + end) + +end + +-- the normal builder + +do + + local force_penalties = false + + -- registertracker("math.penalties",function(v) + -- force_penalties = v + -- end) + + function builders.kernel.mlist_to_hlist(head,style,penalties) + return mlist_to_hlist(head,style,force_penalties or penalties) + end + + -- function builders.kernel.mlist_to_hlist(head,style,penalties) + -- local h = mlist_to_hlist(head,style,force_penalties or penalties) + -- inspect(nodes.totree(h,true,true,true)) + -- return h + -- end + + implement { + name = "setmathpenalties", + arguments = "integer", + actions = function(p) + force_penalties = p > 0 + end, + } + +end + +local actions = tasks.actions("math") -- head, style, penalties + +local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming + +function processors.mlist_to_hlist(head,style,penalties) + starttiming(noads) + head = actions(head,style,penalties) + stoptiming(noads) + return head +end + +callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list") + +-- tracing + +statistics.register("math processing time", function() + return statistics.elapsedseconds(noads) +end) diff --git a/tex/context/base/mkxl/math-pln.mkxl b/tex/context/base/mkxl/math-pln.mkxl new file mode 100644 index 000000000..c5d814fbe --- /dev/null +++ b/tex/context/base/mkxl/math-pln.mkxl @@ -0,0 +1,245 @@ +%D \module +%D [ file=math-pln, +%D version=2001.11.16, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Plain Helpers, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Here we collect some Plain \TEX\ leftovers. + +\writestatus{loading}{ConTeXt Math Macros / Plain Helpers} + +\unprotect + +% we need proper unicode: + +\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to + +% might change + +\protected\def\hrulefill{\leaders\hrule\hfill} +%protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill} + +% will move + +\def\oalign#1% + {\leavevmode % plain tex uses this + \vtop + {\baselineskip\zeroskip + \lineskip.25\exheight + \ialign{\alignmark\alignmark\crcr#1\crcr}}} + +\def\ooalign % chars over each other + {\lineskiplimit-\maxdimen + \oalign} + +% needs checking + +\def\choose{\atopwithdelims()} +\def\brack {\atopwithdelims[]} +\def\brace {\atopwithdelims\{\}} + +% needs checking + +\protected\def\buildrel#1\over#2% + {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}} + +\protected\def\bmod + {\nonscript + \mskip-\medmuskip + \mkern5mu + \mfunction{mod}% + \penalty900 + \mkern5mu + \nonscript + \mskip-\medmuskip} + +\protected\def\pmod#1% + {\allowbreak + \mkern18mu + (\mfunction{mod}\mskip\medmuskip#1)} + +\protected\def\cases#1% + {\left\{% + \mskip\thinmuskip + \vcenter + {\normalbaselines + \mathsurround\zeropoint + \ialign{% + \normalstartimath\alignmark\alignmark\hfil\normalstopimath + \aligntab + \quad\alignmark\alignmark\hfil + \crcr + #1% + \crcr}}% + \right.} + +\protected\def\matrix#1% + {\emptyhbox + \mskip\thinmuskip + \vcenter + {\normalbaselines + \mathsurround\zeropoint + \ialign{% + \hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil + \aligntab + \aligntab + \quad\hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil + \crcr + \mathstrut + \crcr + \noalign{\kern-\baselineskip} + #1\crcr + \mathstrut + \crcr + \noalign{\kern-\baselineskip}}}% + \mskip\thinmuskip} + +\protected\def\pmatrix#1% + {\left(\matrix{#1}\right)} + +% \protected\def\openup +% {\afterassignment\math_openup\scratchdimen=} +% +% \def\math_openup +% {\advance\lineskip \scratchdimen +% \advance\baselineskip \scratchdimen +% \advance\lineskiplimit\scratchdimen} + +\let\math_closeup\relax + +\protected\def\math_openup + {\afterassignment\math_openup_indeed\scratchdimen} + +\def\math_openup_indeed + {\protected\edef\math_closeup + {\lineskip \the\lineskip + \baselineskip \the\baselineskip + \lineskiplimit\the\lineskiplimit + \relax}% + \advance \lineskip \scratchdimen + \advance \baselineskip \scratchdimen + \advance \lineskiplimit \scratchdimen} + +\let\openup \math_openup +\def\closeup{\math_closeup} % dynamic + +\protected\def\displaylines#1% + {\the\mathdisplayaligntweaks + \tabskip\zeroskip + \halign + {\hbox to \displaywidth{% + \normalstartimath\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle\alignmark\alignmark\hfil\normalstopimath}\crcr + #1\crcr}} + +%D This comes from plain but I gave it a \CONTEXT\ touch: + +\permanent\def\math_border_NC_indeed + {\enforced\global\def\math_border_NC{\aligntab}} + +\aliased\let\math_border_NC\math_border_NC_indeed + +\permanent\def\math_border_NR + {\enforced\global\let\math_border_NC\math_border_NC_indeed + \cr} + +\protected\def\math_border_matrix#1#2#3% adapted plain + {\begingroup + % + \setbox\scratchbox\hbox\bgroup + \mr B% + \egroup + \scratchdimenone\wd\scratchbox + % + \scratchdimentwo.2\bodyfontsize + % + \mathsurround\zeropoint + % + \enforced\def\NC{\math_border_NC}% + \enforced\def\NR{\math_border_NR}% + % + \gdef\m_math_border_matrix + {\kern\scratchdimentwo + \glet\m_math_border_matrix\relax}% + % + \setbox\scratchboxone\vbox\bgroup + \everycr{\noalign\bgroup\m_math_border_matrix\egroup}% + \tabskip \zeroskip + \halign{% \ialign resets everycr + \startimath\alignmark\alignmark\stopimath + \hfil + \kern\dimexpr\scratchdimentwo+\scratchdimenone\relax + \aligntab + \thinspace + \hfil + \startimath\alignmark\alignmark\stopimath + \hfil + \aligntab + \aligntab + \quad + \hfil + \startimath\alignmark\alignmark\stopimath + \hfil + \crcr + \omit + \strut + \hfil + \crcr + \noalign{\kern-\baselineskip}% + #3\crcr + \omit + \strut + \cr}% + \egroup + \setbox\scratchboxtwo\vbox\bgroup + \unvcopy\scratchboxone + \global\setbox\globalscratchbox\lastbox + \egroup + \setbox\scratchboxtwo\hbox\bgroup + \unhbox\globalscratchbox + \unskip + \global\setbox\globalscratchbox\lastbox + \egroup + \setbox\scratchboxtwo\hbox\bgroup + \startimath + \kern\dimexpr\wd\globalscratchbox-\scratchdimenone\relax + \left#1\relax + \kern-\wd\globalscratchbox + \global\setbox\globalscratchbox\vbox\bgroup + \box\globalscratchbox + \kern\scratchdimentwo + \egroup + \vcenter\bgroup + \kern-\ht\globalscratchbox + \unvbox\scratchboxone + \kern-\baselineskip + \egroup + \thinspace + \right#2\relax + \stopimath + \egroup + \null + \thickspace + \vbox\bgroup + \kern\ht\globalscratchbox + \box\scratchboxtwo + \egroup + % + \endgroup} + +\permanent\protected\def\bordermatrix {\math_border_matrix()} +\permanent\protected\def\bbordermatrix{\math_border_matrix[]} + +\permanent\protected\def\startbordermatrix #1\stopbordermatrix {\math_border_matrix(){#1}} +\permanent\protected\def\startbbordermatrix#1\stopbbordermatrix{\math_border_matrix[]{#1}} + +\permanent\let\stopbordermatrix \relax +\permanent\let\stopbbordermatrix\relax + +\protect \endinput diff --git a/tex/context/base/mkxl/math-rad.mklx b/tex/context/base/mkxl/math-rad.mklx new file mode 100644 index 000000000..4196bd0f7 --- /dev/null +++ b/tex/context/base/mkxl/math-rad.mklx @@ -0,0 +1,269 @@ +%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 + +\permanent\protected\def\root#1\of{\rootradical{#1}} % #2 + +\protected\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree} % will be redefined + +\permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird + {\normalexpanded{\rootradical + {\normalunexpanded{#1}}% + {\noexpand\triggermathstyle{\number\normalmathstyle}% + \normalunexpanded{#2}}}} + +% experimental new keyword: (maybe keywords should come after the symbol) +% +% \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird +% {\Uroot style \normalmathstyle "0 "221A {#1}{#2}} + +\permanent\protected\def\rootwithdegree[#1]{\rootradical{#1}} +\permanent\protected\def\rootwithoutdegree {\rootradical {}} + +%D Even older stuff: + +% % is now a ordinary character +% +% \let\normalsurd\surd % \Uradical "0 "221A +% \permanent\protected\def\surd{\normalsurd{}} + +%D The real thing. If needed one can control matters with one of the many +%D \type {\Umath...} parameters. +%D +%D \starttyping +%D \def\R {\Umathradicaldegreeafter\textstyle0pt} +%D \def\RR{\Umathradicaldegreeafter\textstyle\dimexpr +%D \Umathradicaldegreeafter\textstyle+.1em\relax} +%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle\dimexpr +%D \Umathradicaldegreeafter\textstyle+.2em\relax} +%D +%D $ \sqrt[3]{5} \RR\sqrt[3]{5} \sqrt[3]{5} $\par +%D $ \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par +%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par +%D +%D \def\R {\Umathradicaldegreeafter\textstyle +%D 0pt} +%D \def\RR {\Umathradicaldegreeafter\textstyle +%D 0.95\Umathradicaldegreeafter\textstyle} +%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle +%D 0.9\Umathradicaldegreeafter\textstyle} +%D +%D $ \sqrt[3]{5} \RR\sqrt[3]{5} \sqrt[3]{5} $\par +%D $ \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par +%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par +%D +%D \def\RR {\mathopenupparameter\Umathradicaldegreeafter{.1}} +%D +%D $ \sqrt[3]{5} \RR\sqrt[3]{5} \sqrt[3]{5} $\par +%D $ \sqrt[3]{5} {\RR\sqrt[3]{5}} \sqrt[3]{5} $\par +%D \stoptyping + +\installcorenamespace{mathradical} +\installcorenamespace{mathradicalalternative} + +\installcommandhandler \??mathradical {mathradical} \??mathradical + +\setupmathradical + [\c!alternative=\v!normal, + \c!mpoffset=.25\exheight] + +\appendtoks + \frozen\instance\setuevalue{\currentmathradical}{\math_radical_handle{\currentmathradical}} +\to \everydefinemathradical + +\protected\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}% + \ifempty\p_color + \styledrootradical{\currentmathradicaldegree}{#body}% {} really needed as \rootradical expands first + \orelse\ifempty\currentmathradicaldegree + \pushcolor[\p_color]% + \styledrootradical{\currentmathradicaldegree}% + {\popcolor#body}% + \else + \pushcolor[\p_color]% + \styledrootradical{\popcolor\currentmathradicaldegree\pushcolor[\p_color]}% + {\popcolor#body}% + \fi} + +\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{minifun::math:radical:default}%{...} + draw + math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset) + % withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30 + withpen pencircle scaled OverlayLineWidth + % 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\the\dimexpr\triggeredmathstyleparameter\Umathfractionrule + % + \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=minifun::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 jugglers 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 + \frozen\instance\setuevalue{\currentmathornament}{\math_ornament_handle{\currentmathornament}}% +\to \everydefinemathornament + +\protected\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}% + % the width of the graphic determines the width of the final result + \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag + \hpack to \wd\scratchbox{\hss\box\nextbox\hss}% + \hskip-\wd\scratchbox + \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/tex/context/base/mkxl/math-scr.mkxl b/tex/context/base/mkxl/math-scr.mkxl new file mode 100644 index 000000000..555f549f1 --- /dev/null +++ b/tex/context/base/mkxl/math-scr.mkxl @@ -0,0 +1,58 @@ +%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) Spijkers (of the Math4All project +%D that we participate in), and used for typesetting the minus sign that is keyed +%D into scientific calculators. We use the monospaced signs, that we also define as +%D symbol, so that they can be overloaded. We can probably do it nicer now (in lmtx). + +\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}{-}] + +\permanent\protected\def\negative {\math_scripts_raised_symbol{negative}} +\permanent\protected\def\positive {\math_scripts_raised_symbol{positive}} +\permanent\protected\def\zeroamount{\math_scripts_raised_number{zeroamount}} + +%D How negative such a symbol looks is demonstrated in: $\negative 10^{\negative +%D 10^{\negative 10}}$. + +% \setuptextformulas % why here +% [\c!size=\v!normal] + +\protect \endinput diff --git a/tex/context/base/mkxl/math-stc.mklx b/tex/context/base/mkxl/math-stc.mklx new file mode 100644 index 000000000..1f9047394 --- /dev/null +++ b/tex/context/base/mkxl/math-stc.mklx @@ -0,0 +1,1377 @@ +%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 +%D rather special because the order in mathml matters, so we flush in [base under +%D over] order. We also do some analysis at the \TEX\ end (passing the right +%D variant). It's easy in the export to deal with it but in the pdf stream less +%D trivial as we don't actually analyze there. +%D +%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 +%D The width of the extensible need to adapt itself automatically. +%D \stopitem +%D \startitem +%D We need to be able to control horizontal and vertical offsets. +%D \stopitem +%D \startitem +%D We best have a math as well as a text variant (which is handy for chemistry). +%D \stopitem +%D \startitem +%D For historic reasons we need to deal with optional arguments in a special +%D (reverse) way. +%D \stopitem +%D \startitem +%D We need alternatives for extensibles on top, in the middle and at the bottom. +%D \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 +%D dimensions, but fillers (like \type {\rightarrowfil} don't work with \OPENTYPE\ +%D extensibles yet because there is no way to let them stretch like leaders. At some +%D point \LUATEX\ might provide a auto||fit||to||encapsulated||box and if not I will +%D cook up a \LUA\ 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 as well. +%D A nice evening job with Joe Bonamassa performing live on the big screen (real +%D 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_fallback + {\mathstylehbox to \scratchwidth{\usemathstackerscolorparameter\c!color + \hss + \hskip\mathstackersparameter\c!topoffset\relax % for manual italic correction + \ifcsname\??mathextensiblefallbacks\number\scratchunicode\endcsname + \lastnamedcs + \else + \Umathchar \fam \zerocount \scratchunicode + \fi + \hss}} + +\def\math_stackers_regular + {\mathstylehbox{\usemathstackerscolorparameter\c!color + \hskip\d_math_stackers_offset_l + \Umathaccent\fam\zerocount\scratchunicode + {\hskip\dimexpr\scratchwidth-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% + \hskip\d_math_stackers_offset_r + }} + +\def\math_stackers_stretch % we don't have that one yet + {\mathstylehbox{\usemathstackerscolorparameter\c!color + \hskip\d_math_stackers_offset_l + \Umathaccent\fam\zerocount\scratchunicode + {\hskip\dimexpr\hsize-\d_math_stackers_offset_l-\d_math_stackers_offset_r}% + \hskip\d_math_stackers_offset_r + }} + +% 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}% + {\hpack{\vrule\s!width\scratchwidth\s!height.1\mathexheight\s!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!mstackermid\empty\hbox\bgroup}% + \def\math_stackers_start_tagged_top{\dostarttagged\t!mstackertop\empty\hbox\bgroup}% + \def\math_stackers_start_tagged_bot{\dostarttagged\t!mstackerbot\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!voffset=.25\mathexheight, + \c!hoffset=\zeropoint, + \c!topoffset=\zeropoint, % for manual italic correction + \c!distance=\mathstackersparameter\c!voffset, % distance between symbol and base (can be different from voffset) + \c!minheight=\mathexheight, + \c!mindepth=\zeropoint, + \c!minwidth=.5\mathemwidth, + \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 + +\setupmathstackers + [\c!mp=math:stacker:\number\scratchunicode, + \c!mpheight=\mathcharht\scratchunicode, + \c!mpdepth=\mathchardp\scratchunicode, + \c!mpoffset=.25\mathexheight] + +\setvalue{\??mathstackersalternative\v!mp}% + {\normalexpanded{\math_stackers_mp_box + {\the\dimexpr\mathstackersparameter\c!mpheight}% + {\the\dimexpr\mathstackersparameter\c!mpdepth}% + {\the\dimexpr\mathstackersparameter\c!mpoffset}% + {\the\dimexpr\triggeredmathstyleparameter\Umathfractionrule}% + {\the\dimexpr\triggeredmathstyleparameter\Umathaxis}% + {\the\mathexheight}% + {\the\mathemwidth}% + }} + +\protected\def\math_stackers_mp_box#1#2#3#4#5#6#7% + {\hpack\bgroup % todo: add code key + tag + % we can speed up \mathexheight expansion a bit + \d_overlay_width \scratchwidth + \d_overlay_height #1\relax + \d_overlay_depth #2\relax + \d_overlay_offset #3\relax + \d_overlay_linewidth#4\relax + \edef\overlaylinecolor{\mathstackersparameter\c!color}% + \edef\p_mp{\mathstackersparameter\c!mp}% + \uniqueMPgraphic{\p_mp}{axis=#5,ex=#6,em=#7}% + \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 + \orelse\ifx\p_offset\v!min + % heads/tails - hoffset + \advance\scratchleftoffset -\scratchhoffset + \advance\scratchrightoffset-\scratchhoffset + \else % \v!normal + % hoffset + \scratchleftoffset\zeropoint + \scratchrightoffset\zeropoint + \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} + +\protected\def\math_stackers_triplet#method#category#codepoint#toptext#bottomtext% + {\begingroup + \edef\currentmathstackers{#category}% + \mathstackersparameter\c!left\relax + \dostarttagged\t!mstacker\currentmathstackers + \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi + {\edef\p_offset {\mathstackersparameter\c!offset}% + \edef\p_location {\mathstackersparameter\c!location}% + \edef\p_strut {\mathstackersparameter\c!strut}% + \edef\p_alternative{\mathstackersparameter\c!alternative}% + \edef\m_math_stackers_text_top {#toptext}% + \edef\m_math_stackers_text_bottom{#bottomtext}% + \ifparameter#bottomtext\or + \edef\p_order{\mathstackersparameter\c!order}% + \ifx\p_order\v!reverse + \swapmacros\m_math_stackers_text_top\m_math_stackers_text_bottom + \fi + \fi + \scratchleftoffset \zeropoint + \scratchrightoffset\zeropoint + \ifcase#method\relax + \math_stackers_check_unicode{#codepoint}% + \else + \edef\m_math_stackers_text_middle{#codepoint}% + \fi + \ifempty\m_math_stackers_text_top + \setbox\scratchboxone\emptyhbox + \else + \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}% + \fi + \ifempty\m_math_stackers_text_bottom + \setbox\scratchboxtwo\emptyhbox + \else + \setmathsmalltextbox\scratchboxtwo\hbox{\math_stackers_bottomtext}% + \fi + % + \ifcase#method\relax + % e.g. extensible + %\scratchwidth\wd + % \ifdim\wd\scratchboxone>\wd\scratchboxtwo + % \scratchboxone + % \else + % \scratchboxtwo + % \fi + %\relax + \scratchwidth\mathcharwd\scratchunicode + \ifdim\wd\scratchboxone>\scratchwidth + \scratchwidth\wd\scratchboxone + \orelse\ifdim\wd\scratchboxtwo>\scratchwidth + \scratchwidth\wd\scratchboxtwo + \fi + \else + \ifempty\m_math_stackers_text_middle + \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 + \orelse\ifdim\wd\scratchboxtwo>\wd\scratchboxthree + \scratchboxtwo + \else + \scratchboxthree + \fi + \relax + \fi + % + \scratchdimen\mathstackersparameter\c!minwidth\relax + \ifdim\scratchwidth<\scratchdimen + \scratchwidth\scratchdimen + \fi + \advance\scratchwidth2\scratchhoffset + % + \ifcase#method\relax + \dostarttagged\t!mstackermid\empty + \setbox\scratchboxthree\csname\??mathstackersalternative\p_alternative\endcsname + \dostoptagged + \fi + % + \ifdim\wd\scratchboxone<\scratchwidth + \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work + \fi + \ifdim\wd\scratchboxtwo<\scratchwidth + \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}% + \fi + \ifdim\wd\scratchboxthree<\scratchwidth + \setbox\scratchboxthree\hpack 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\hpack{\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_stop_group} + +\permanent\tolerant\protected\def\definemathextensible[#1]#*[#2]#*[#3]% category name unicode + {\ifarguments\or\or + \frozen\setuevalue{#1}{\math_stackers_auto_normal\noexpand\currentmathstackers{\number#2}}% + \or + \frozen\setuevalue{#2}{\math_stackers_auto_normal{#1}{\number#3}}% + \fi} + +\tolerant\protected\def\math_stackers_auto_normal#1#2#*[#3]#:#=#*#=% + {\begingroup + \scratchcounter#2\relax + \edef\currentmathstackers{\ifparameter#3\or#3\else#1\fi}% + \math_stackers_triplet\zerocount\currentmathstackers\scratchcounter{#4}{#5}% + \endgroup} + +%D A few direct accessors (in the meantime we redefined \mathextensible so we renamed the +%D following): + +\permanent\tolerant\protected\def\directmathextensible[#category]% + {\begingroup + \math_stackers_handle_extensible{\ifparameter#category\or#category\else\v!mathematics\fi}} % will be defined later on + +\permanent\tolerant\protected\def\directtextextensible[#category]% + {\begingroup + \math_stackers_handle_extensible{\ifparameter#category\or#category\else\v!text\fi}} % will be defined later on + +\aliased\let\mathstacker\directmathextensible +\aliased\let\textstacker\directtextextensible + +\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 + +\protected\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\ordlimits}% + \mathop\bgroup + \else + \let\math_stackers_stop_group\endgroup + \fi} + +\newconstant\c_math_stackers_top +\newconstant\c_math_stackers_bottom +\newconstant\c_math_stackers_codepoint +\newconstant\c_math_stackers_extracode +\newdimen \d_math_stackers_offset_l +\newdimen \d_math_stackers_offset_r + +\setupmathstackers[lt=\zeropoint,rt=\zeropoint,lb=\zeropoint,rb=\zeropoint] + +\tolerant\protected\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#spacer[#settings]#:#text% + {\math_stackers_start_group{#category}% + \c_math_stackers_top #top\relax + \c_math_stackers_bottom #bottom\relax + \c_math_stackers_codepoint#codepoint\relax + \c_math_stackers_extracode#codeextra\relax + \ifparameter#settings\or + \setupcurrentmathstackers[#settings]% + \fi + \mathstackersparameter\c!left\relax + \dostarttagged\t!mstacker\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\c_math_stackers_codepoint + % + \ifempty\math_stackers_middle + \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 + % + %\scratchunicode\c_math_stackers_codepoint + \ifcase\c_math_stackers_bottom + \d_math_stackers_offset_l\mathstackersparameter{lt}% + \d_math_stackers_offset_r\mathstackersparameter{rt}% + \orelse\ifcase\c_math_stackers_top + \d_math_stackers_offset_l\mathstackersparameter{lb}% + \d_math_stackers_offset_r\mathstackersparameter{rb}% + \else + \d_math_stackers_offset_l\mathstackersparameter{lt}% + \d_math_stackers_offset_r\mathstackersparameter{rt}% + \fi + \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname + \setbox\scratchboxthree\hpack to \scratchwidth{\hss\box\scratchboxthree\hss}% + % + \ifcase\c_math_stackers_extracode\else + \scratchunicode\c_math_stackers_extracode + \d_math_stackers_offset_l\mathstackersparameter{lb}% + \d_math_stackers_offset_r\mathstackersparameter{rb}% + \setbox\scratchboxone\csname\??mathstackersalternative\p_alternative\endcsname + \fi + % + \math_stackers_normalize_three + % analysis + \ifcase\c_math_stackers_bottom + \ifcase\c_math_stackers_top + \dosettagproperty\s!subtype\t!munderover + \else + \dosettagproperty\s!subtype\t!mover + \fi + \else + \ifcase\c_math_stackers_top + \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\c_math_stackers_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\c_math_stackers_top + \box\scratchboxtwo + \else + \box\scratchboxone + \fi + \egroup + \math_stackers_stop_tagged + \fi + \ifcase\c_math_stackers_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} + +\permanent\tolerant\protected\def\definemathoverextensible[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \frozen\setuevalue{#2}{\math_stackers_make_double\plusone \zerocount{#1}{\number#3}{0}}% + \else + \frozen\setuevalue{#1}{\math_stackers_make_double\plusone \zerocount\noexpand\currentmathstackers{\number#2}{0}}% + \fi} + +\permanent\tolerant\protected\def\definemathunderextensible[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \frozen\setuevalue{#2}{\math_stackers_make_double\zerocount\plusone{#1}{\number#3}{0}}% + \else + \frozen\setuevalue{#1}{\math_stackers_make_double\zerocount\plusone\noexpand\currentmathstackers{\number#2}{0}}% + \fi} + +\permanent\tolerant\protected\def\definemathdoubleextensible[#1]#*[#2]#*[#3]#*[#4]% + {\ifparameter#4\or + \frozen\setuevalue{#2}{\math_stackers_make_double\plusone \plusone{#1}{\number#3}{\number#4}}% + \else + \frozen\setuevalue{#1}{\math_stackers_make_double\plusone \plusone\noexpand\currentmathstackers{\number#2}{\number#3}}% + \fi} + +\permanent\tolerant\protected\def\definemathover[#category]#spacer[#command]#spacer[#topcode]% + {\frozen\setuvalue{#command}{\math_stackers_handle_direct\plusone\zerocount{#category}{#topcode}{0}}} + +\permanent\tolerant\protected\def\definemathunder[#category]#spacer[#command]#spacer[#bottomcode]% + {\frozen\setuvalue{#command}{\math_stackers_handle_direct\zerocount\plusone{#category}{#bottomcode}{0}}} + +\permanent\tolerant\protected\def\definemathdouble[#category]#spacer[#command]#spacer[#topcode]#spacer[#bottomcode]% + {\frozen\setuvalue{#command}{\math_stackers_handle_direct\plusone\plusone{#category}{#topcode}{#bottomcode}}} + +\permanent\tolerant\protected\def\mathover[#category]#spacer[#settings]#:#topcode#text% + {\begingroup + \edef\currentmathstackers{\ifparameter#category\or#category\else\v!top\fi}% + \ifparameter#settings\or + \setupcurrentmathstackers[#settings]% + \fi + \math_stackers_make_double\plusone\zerocount + {\currentmathstackers}% + {#topcode}% + {0}% + {#text}% + \endgroup} + +\permanent\tolerant\protected\def\mathunder[#category]#spacer[#settings]#:#bottomcode#text% + {\begingroup + \edef\currentmathstackers{\ifparameter#category\or#category\else\v!bottom\fi}% + \ifparameter#settings\or + \setupcurrentmathstackers[#settings]% + \fi + \math_stackers_make_double\zerocount\plusone + {\currentmathstackers}% + {#bottomcode}% + {0}% + {#text}% + \endgroup} + +\permanent\tolerant\protected\def\mathdouble[#category]#spacer[#settings]#:#topcode#bottomcode#text% + {\begingroup + \edef\currentmathstackers{\ifparameter#category\or#category\else\v!both\fi}% + \ifparameter#settings\or + \setupcurrentmathstackers[#settings]% + \fi + \math_stackers_make_double\plusone\plusone + {\currentmathstackers}% + {#topcode}% + {#bottomcode}% + {#text}% + \endgroup} + +\def\math_stackers_handle_direct#top#bottom#category#topcode#bottomcode#text% + {\begingroup + \math_stackers_make_double#top#bottom{#category}{#topcode}{#bottomcode}{#text}% + \endgroup} + +%D A relative new one is a combination of accents and text (as needed in mathml): + +\protected\def\math_stackers_make_double_text#where#category#codepoint#text#extra% + {\math_stackers_start_group{#category}% + \mathstackersparameter\c!left\relax + \dostarttagged\t!mstacker\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 + % + \ifempty\math_stackers_middle + \setbox\scratchboxthree\emptyhbox + \else + \setmathtextbox\scratchboxthree\hbox{\math_stackers_middletext}% + \fi + % + \ifcase#where\relax + \edef\m_math_stackers_text_top{#extra}% + \ifempty\math_stackers_top + \setbox\scratchboxone\emptyhbox + \else + \setmathsmalltextbox\scratchboxone\hbox{\math_stackers_toptext}% + \fi + \else + \edef\m_math_stackers_text_bottom{#extra}% + \ifempty\math_stackers_bottom + \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\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% + \fi + \ifdim\wd\scratchboxthree<\scratchwidth + \setbox\scratchboxthree\hpack 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} + +\permanent\tolerant\protected\def\definemathovertextextensible[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \frozen\setuevalue{#2}{\math_stackers_make_double_text\plusone{#1}{\number#3}}% + \else + \frozen\setuevalue{#1}{\math_stackers_make_double_text\plusone\noexpand\currentmathstackers{\number#2}}% + \fi} + +\permanent\tolerant\protected\def\definemathundertextextensible[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \frozen\setuevalue{#2}{\math_stackers_make_double_text\zerocount{#1}{\number#3}}% + \else + \frozen\setuevalue{#1}{\math_stackers_make_double_text\zerocount\noexpand\currentmathstackers{\number#2}}% + \fi} + +\permanent\tolerant\protected\def\mathovertext[#category]% + {\begingroup + \math_stackers_direct_double_text\plusone {\ifargument#category\or#category\else\v!top\fi}} + +\permanent\tolerant\protected\def\mathundertext[#category]% + {\begingroup + \math_stackers_direct_double_text\zerocount{\ifargument#category\or#category\else\v!bottom\fi}} + +\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. + +\permanent\tolerant\protected\def\mathtriplet[#category]#:#middletext#toptext#bottomtext% + {\begingroup + \math_stackers_triplet\plusone{\ifargument#category\or#category\else\currentmathstackers\fi}{#middletext}{#toptext}{#bottomtext}% + \endgroup} + +\permanent\tolerant\protected\def\definemathtriplet[#1]#*[#2]#*[#3]% category name default + {\ifarguments\or + \frozen\setuevalue{#1}{\math_stackers_auto_triplet_nop[\noexpand\currentmathstackers]}% + \or + \frozen\setuevalue{#2}{\math_stackers_auto_triplet_nop[#1]}% + \or + \frozen\setuevalue{#2}{\math_stackers_auto_triplet_yes[#1][#3]}% + \fi} + +\tolerant\protected\def\math_stackers_auto_triplet_yes[#1][#2]#*[#3]#:#=#*#=% [#2]% #2 gobble spaces + {\begingroup + \edef\currentmathstackers{#1}% + \def \m_math_stackers_text_middle{#2}% + \ifarguments#3\or\edef\currentmathstackers{#3}\fi + \math_stackers_triplet\plusone\currentmathstackers\m_math_stackers_text_middle{#4}{#5}% + \endgroup} + +\tolerant\protected\def\math_stackers_auto_triplet_nop[#1]#*[#2]#:#=#*#=#*#=% [#2]% #2 gobble spaces% + {\begingroup + \edef\currentmathstackers{#1}% + \ifarguments#2\or\edef\currentmathstackers{#2}\fi + \math_stackers_triplet\plusone\currentmathstackers{#3}{#4}{#5}% + \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 + +\immutable\protected\def\normaldoublebrace {\Umathaccents 0 \defaultmathfamily "23DE 0 \defaultmathfamily "23DF } +\immutable\protected\def\normaldoubleparent{\Umathaccents 0 \defaultmathfamily "23DC 0 \defaultmathfamily "23DD } + +% let's keep this + +\aliased\let\normaloverbrace \overbrace +\aliased\let\normalunderbrace \underbrace +\aliased\let\normaloverparent \overparent +\aliased\let\normalunderparent \underparent +\aliased\let\normaloverbracket \overbracket +\aliased\let\normalunderbracket \underbracket +\aliased\let\normalunderleftarrow \underleftarrow +\aliased\let\normaloverleftarrow \overleftarrow +\aliased\let\normalunderrightarrow\underrightarrow +\aliased\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\mathemwidth] % the default +\definemathstackers [\v!small] [\v!mathematics] [\c!hoffset=1\mathemwidth] +\definemathstackers [\v!medium] [\v!mathematics] [\c!hoffset=1.5\mathemwidth] +\definemathstackers [\v!big] [\v!mathematics] [\c!hoffset=2\mathemwidth] + +\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] + +%D We don't use overline and underline. This is one of the overlooked aspects of +%D unicode cq. opentype math: why treat rules different than e.g. arrows and +%D accents. It is a bit unfortunate that the opportunity to move math to new +%D technologies happened outside the tex domain (and/or some aspects were kept while +%D in fact they were side effects of limitations of traditional fonts). From the +%D unicode aware tex engines' implementation point of view things could have been +%D done a bit nicer but then: the community didn't seem to care too much and just +%D has to follow now. +%D +%D Anyhow, we use a character based approach so that at least we get unicode stuff +%D in the backend (okay, we still need to deal with some cut and paste issues but at +%D least we now know what we deal with. + +% alternatively we can move the original to FE* + +\definemathoverextensible [\v!vfenced] [overbar] ["FE33E] % ["203E] +\definemathunderextensible [\v!vfenced] [underbar] ["FE33F] % ["203E] +\definemathdoubleextensible [\v!vfenced] [doublebar] ["FE33E] ["FE33F] + +\definemathoverextensible [\v!vfenced] [overbrace] ["FE3DE] % ["023DE] +\definemathunderextensible [\v!vfenced] [underbrace] ["FE3DF] % ["023DF] +\definemathdoubleextensible [\v!vfenced] [doublebrace] ["FE3DE] ["FE3DF] + +\definemathoverextensible [\v!vfenced] [overparent] ["FE3DC] % ["023DC] +\definemathunderextensible [\v!vfenced] [underparent] ["FE3DD] % ["023DD] +\definemathdoubleextensible [\v!vfenced] [doubleparent] ["FE3DC] ["FE3DD] + +\definemathoverextensible [\v!vfenced] [overbracket] ["FE3B4] % ["023B4] +\definemathunderextensible [\v!vfenced] [underbracket] ["FE3B5] % ["023B5] +\definemathdoubleextensible [\v!vfenced] [doublebracket] ["FE3B4] ["FE3B5] + +% \protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} + +%D For mathml: + +\definemathdoubleextensible [\v!both] [overbarunderbar] ["FE33E] ["FE33F] +\definemathdoubleextensible [\v!both] [overbraceunderbrace] ["FE3DE] ["FE3DF] +\definemathdoubleextensible [\v!both] [overparentunderparent] ["FE3DC] ["FE3DD] +\definemathdoubleextensible [\v!both] [overbracketunderbracket] ["FE3B4] ["FE3B5] + +\definemathovertextextensible [\v!bothtext] [overbartext] ["FE33E] +\definemathundertextextensible [\v!bothtext] [underbartext] ["FE33F] +\definemathovertextextensible [\v!bothtext] [overbracetext] ["FE3DE] +\definemathundertextextensible [\v!bothtext] [underbracetext] ["FE3DF] +\definemathovertextextensible [\v!bothtext] [overparenttext] ["FE3DC] +\definemathundertextextensible [\v!bothtext] [underparenttext] ["FE3DD] +\definemathovertextextensible [\v!bothtext] [overbrackettext] ["FE3B4] +\definemathundertextextensible [\v!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\mathemwidth] + +\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 + +\immutable\protected\def\rightarrowfill {\math_stackers_hacked_fill \relbar \relbar \rightarrow} +\immutable\protected\def\leftarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \relbar } +\immutable\protected\def\rightoverleftarrowfill{\math_stackers_hacked_fill \ctxdoublearrowfillleftend\ctxdoublearrowfillmiddlepart\ctxdoublearrowfillrightend} +\immutable\protected\def\equalfill {\math_stackers_hacked_fill \Relbar \Relbar \Relbar} +\immutable\protected\def\Rightarrowfill {\math_stackers_hacked_fill \Relbar \Relbar \Rightarrow} +\immutable\protected\def\Leftarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Relbar} +\immutable\protected\def\Leftrightarrowfill {\math_stackers_hacked_fill \Leftarrow \Relbar \Rightarrow} +\immutable\protected\def\leftrightarrowfill {\math_stackers_hacked_fill \leftarrow \relbar \rightarrow} +\immutable\protected\def\mapstofill {\math_stackers_hacked_fill{\mapstochar\relbar} \relbar \rightarrow} +\immutable\protected\def\twoheadrightarrowfill {\math_stackers_hacked_fill \relbar \relbar \twoheadrightarrow} +\immutable\protected\def\twoheadleftarrowfill {\math_stackers_hacked_fill \twoheadleftarrow \relbar \relbar} +\immutable\protected\def\rightharpoondownfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoondown} +\immutable\protected\def\rightharpoonupfill {\math_stackers_hacked_fill \relbar \relbar \rightharpoonup} +\immutable\protected\def\leftharpoondownfill {\math_stackers_hacked_fill \leftharpoondown \relbar \relbar} +\immutable\protected\def\leftharpoonupfill {\math_stackers_hacked_fill \leftharpoonup \relbar \relbar} +\immutable\protected\def\hookleftfill {\math_stackers_hacked_fill \leftarrow \relbar {\relbar\joinrel\rhook}} +\immutable\protected\def\hookrightfill {\math_stackers_hacked_fill{\lhook\joinrel\relbar} \relbar \rightarrow} +\immutable\protected\def\relfill {\math_stackers_hacked_fill \relbar \relbar \relbar} +\immutable\protected\def\triplerelfill {\math_stackers_hacked_fill \equiv \equiv \equiv} + +% \permanent\protected\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}} +% \permanent\protected\def\doublebond{{\xequal}} +% \permanent\protected\def\triplebond{{\xtriplerel}} + +%D For the moment (needs checking): + +\permanent\tolerant\protected\def\defineextensiblefiller[#1]#*[#2]% + {\immutable\letcsname\??mathextensiblefallbacks\number#2\expandafter\endcsname\csname#1\endcsname + %\immutable\letcsname#1\expandafter\endcsname\csname#1\endcsname + } % huh? + +\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[Rightleftarrowfill] [.....] + +% These are fishy ... we need to check this because now these commands relax (there +% are some entries in char-def.) +% +% %definemathoverextensible [overbarfill] ["FE33E] +% %definemathunderextensible [underbarfill] ["FE33F] +% \definemathoverextensible [overbracefill] ["FE3DE] +% \definemathunderextensible [underbracefill] ["FE3DF] +% \definemathoverextensible [overparentfill] ["FE3DC] +% \definemathunderextensible [underparentfill] ["FE3DD] +% \definemathoverextensible [overbracketfill] ["FE3B4] +% \definemathunderextensible [underbracketfill] ["FE3B5] +% +% %defineextensiblefiller [overbarfill] ["FE33E] +% %defineextensiblefiller [underbarfill] ["FE33F] +% \defineextensiblefiller [overbracefill] ["FE3DE] +% \defineextensiblefiller [underbracefill] ["FE3DF] +% \defineextensiblefiller [overparentfill] ["FE3DC] +% \defineextensiblefiller [underparentfill] ["FE3DD] +% \defineextensiblefiller [overbracketfill] ["FE3B4] +% \defineextensiblefiller [underbracketfill] ["FE3B5] + +%D Extra: + +\permanent\protected\edef\singlebond{\mathematics{\mathsurround\zeropoint\char\number"002D\relax}} +\permanent\protected\edef\doublebond{\mathematics{\mathsurround\zeropoint\char\number"003D\relax}} +\permanent\protected\edef\triplebond{\mathematics{\mathsurround\zeropoint\char\number"2261\relax}} + +% \mathchardef\singlebond"002D +% \mathchardef\doublebond"003D +% \mathchardef\triplebond"2261 + +%D Also handy: + +\permanent\tolerant\protected\def\definemathunstacked[#1]#*[#2]#*[#3]% category name unicode + {\ifarguments\or\or + \frozen\setuevalue{#1}{\math_stackers_unstacked_normal\noexpand\currentmathstackers{\number#2}}% + \else + \frozen\setuevalue{#2}{\math_stackers_unstacked_normal{#1}{\number#3}}% + \fi} + +\protected\def\math_stackers_unstacked_normal#category#codepoint% + {\begingroup + \edef\currentmathstackers{#category}% + \edef\p_moffset{\mathstackersparameter\c!moffset}% + \ifempty\p_moffset \else + \mskip\p_moffset\relax + \fi + \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi + {\usemathstackerscolorparameter\c!color + \Umathchar\zerocount\defaultmathfamily#codepoint}% + \ifempty\p_moffset \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\;} + +% New (an example of using \mathexheight): + +\definemathstackers + [\v!symbol] + [\c!voffset=-.3\mathexheight, + \c!hoffset=\zeropoint, + \c!mathclass=ord, + \c!topoffset=.4\mathemwidth, % poor man's italic correction + \c!middlecommand=\mathematics] + +\definemathover[\v!symbol][interiorset]["2218] + +\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/tex/context/base/mkxl/math-tag.lmt b/tex/context/base/mkxl/math-tag.lmt new file mode 100644 index 000000000..eb58b5450 --- /dev/null +++ b/tex/context/base/mkxl/math-tag.lmt @@ -0,0 +1,596 @@ +if not modules then modules = { } end modules ['math-tag'] = { + version = 1.001, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- todo: have a local list with local tags that then get appended +-- todo: use tex.getmathcodes (no table) + +-- use lpeg matchers + +local find, match = string.find, string.match +local insert, remove, concat = table.insert, table.remove, table.concat + +local attributes = attributes +local nodes = nodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getid = nuts.getid +local getchar = nuts.getchar +local getfont = nuts.getfont +local getlist = nuts.getlist +local getfield = nuts.getfield +local getdisc = nuts.getdisc +local getsubtype = nuts.getsubtype +local getattr = nuts.getattr +local getattrlist = nuts.getattrlist +local setattr = nuts.setattr +----- getcomponents = nuts.getcomponents -- not really needed +local getwidth = nuts.getwidth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup + +local set_attributes = nuts.setattributes + +local nextnode = nuts.traversers.node + +local nodecodes = nodes.nodecodes + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char +local style_code = nodecodes.style -- attr style +local choice_code = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local accentcodes = nodes.accentcodes +local fencecodes = nodes.fencecodes + +local fixedtopaccent_code = accentcodes.fixedtop +local fixedbottomaccent_code = accentcodes.fixedbottom +local fixedbothaccent_code = accentcodes.fixedboth + +local leftfence_code = fencecodes.left +local middlefence_code = fencecodes.middle +local rightfence_code = fencecodes.right + +local kerncodes = nodes.kerncodes + +local fontkern_code = kerncodes.fontkern +local italickern_code = kerncodes.italickern + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local math_code = nodecodes.math + +local processnoads = noads.process + +local a_tagged = attributes.private('tagged') +local a_mathcategory = attributes.private('mathcategory') +local a_mathmode = attributes.private('mathmode') + +local tags = structures.tags + +local start_tagged = tags.start +local restart_tagged = tags.restart +local stop_tagged = tags.stop +local taglist = tags.taglist + +local chardata = characters.data + +local getmathcodes = tex.getmathcodes +local mathcodes = mathematics.codes +local ordinary_mathcode = mathcodes.ordinary +local variable_mathcode = mathcodes.variable + +local fromunicode16 = fonts.mappings.fromunicode16 +local fontcharacters = fonts.hashes.characters + +local report_tags = logs.reporter("structure","tags") + +local process + +local function processsubsup(start) + -- At some point we might need to add an attribute signaling the + -- super- and subscripts because TeX and MathML use a different + -- order. The mrows are needed to keep mn's separated. + local nucleus = getnucleus(start) + local sup = getsup(start) + local sub = getsub(start) + if sub then + if sup then + setattr(start,a_tagged,start_tagged("msubsup")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow", { subscript = true }) + process(sub) + stop_tagged() + start_tagged("mrow", { superscript = true }) + process(sup) + stop_tagged() + stop_tagged() + else + setattr(start,a_tagged,start_tagged("msub")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow") + process(sub) + stop_tagged() + stop_tagged() + end + elseif sup then + setattr(start,a_tagged,start_tagged("msup")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow") + process(sup) + stop_tagged() + stop_tagged() + else + process(nucleus) + end +end + +-- todo: check function here and keep attribute the same + +-- todo: variants -> original + +local actionstack = { } +local fencesstack = { } + +-- glyph nodes and such can happen in under and over stuff + +-- local function getunicode(n) -- instead of getchar +-- local char = getchar(n) +-- -- local font = getfontoffamily(getfield(n,"fam")) +-- local font = getfont(n) +-- local data = fontcharacters[font][char] +-- return data.unicode or char +-- end + +local function getunicode(n) -- instead of getchar + -- local char, font = isglyph(n) -- no, we have a mathchar + local char, font = getchar(n), getfont(n) + local data = fontcharacters[font][char] + return data.unicode or char -- can be a table but unlikely for math characters +end + +------------------- + +local content = { } +local found = false + +content[mathchar_code] = function() found = true end + +local function hascontent(head) + found = false + processnoads(head,content,"content") + return found +end + +-------------------- + +-- todo: use properties + +-- local function showtag(n,id,old) +-- local attr = getattr(n,a_tagged) +-- local curr = tags.current() +-- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)", +-- old and "before" or "after ", +-- nodecodes[id], +-- getattrlist(n), +-- attr or "?",attr and taglist[attr].tagname or "?", +-- curr or "?",curr and taglist[curr].tagname or "?" +-- ) +-- end + +process = function(start) -- we cannot use the processor as we have no finalizers (yet) + local mtexttag = nil + while start do + local id = getid(start) +-- showtag(start,id,true) + if id == glyph_code or id == disc_code then + if not mtexttag then + mtexttag = start_tagged("mtext") + end + setattr(start,a_tagged,mtexttag) + elseif mtexttag and id == kern_code and (getsubtype(start) == fontkern_code or getsubtype(start) == italickern_code) then -- italickern + setattr(start,a_tagged,mtexttag) + else + if mtexttag then + stop_tagged() + mtexttag = nil + end + if id == mathchar_code then + local char = getchar(start) + local code = getmathcodes(char) + local tag + if code == ordinary_mathcode or code == variable_mathcode then + local ch = chardata[char] + local mc = ch and ch.mathclass + if mc == "number" then + tag = "mn" + elseif mc == "variable" or not mc then -- variable is default + tag = "mi" + else + tag = "mo" + end + else + tag = "mo" + end + local a = getattr(start,a_mathcategory) + if a then + setattr(start,a_tagged,start_tagged(tag,{ mathcategory = a })) + else + setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory + end + stop_tagged() + -- showtag(start,id,false) + break -- okay? + elseif id == mathtextchar_code then -- or id == glyph_code + -- check for code + local a = getattr(start,a_mathcategory) + if a then + setattr(start,a_tagged,start_tagged("ms",{ mathcategory = a })) -- mtext + else + setattr(start,a_tagged,start_tagged("ms")) -- mtext + end + stop_tagged() + -- showtag(start,id,false) + break + elseif id == delimiter_code then + -- check for code + setattr(start,a_tagged,start_tagged("mo")) + stop_tagged() + -- showtag(start,id,false) + break + elseif id == style_code then + -- has a next + elseif id == noad_code then + -- setattr(start,a_tagged,tags.current()) + processsubsup(start) + elseif id == subbox_code or id == hlist_code or id == vlist_code then + -- keep an eye on subbox_code and see what ends up in there + local attr = getattr(start,a_tagged) + if not attr then + -- just skip + else + local specification = taglist[attr] + if specification then + local tag = specification.tagname + if tag == "formulacaption" then + -- skip + elseif tag == "mstacker" then + local list = getlist(start) + if list then + process(list) + end + else + if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then + tag = "mtext" + end + local text = start_tagged(tag) + setattr(start,a_tagged,text) + local list = getlist(start) + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) -- only the first node ? + else + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + -- + -- todo: have a local list with local tags that then get appended + -- + local tagdata = specification.taglist + local common = #tagdata + 1 + local function runner(list,depth) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + local keep = nil + -- local keep = { } -- win case we might need to move keep outside + for n, id, subtype in nextnode, list do + local mth = id == math_code and subtype + if mth == 0 then -- hm left_code + -- insert(keep,text) + keep = text + text = start_tagged("mrow") + common = common + 1 + end + local aa = getattr(n,a_tagged) + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa].taglist + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster + end + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text + end + cache[aa] = ac + end + setattr(n,a_tagged,ac) + else + setattr(n,a_tagged,text) + end + if id == hlist_code or id == vlist_code then + runner(getlist(n),depth+1) + elseif id == glyph_code then + -- this should not be needed + -- local components = getcomponents(n) -- unlikely set + -- if components then + -- runner(getcomponent,depth+1) + -- end + elseif id == disc_code then + -- this should not be needed + local pre, post, replace = getdisc(n) + if pre then + runner(pre,depth+1) + end + if post then + runner(post,depth+1) + end + if replace then + runner(replace,depth+1) + end + end + if mth == 1 then + stop_tagged() + -- text = remove(keep) + text = keep + common = common - 1 + end + end + end + runner(list,0) + end + stop_tagged() + end + end + end + elseif id == submlist_code then -- normally a hbox + local list = getlist(start) + if list then + local attr = getattr(start,a_tagged) + local last = attr and taglist[attr] + if last then + local tag = last.tagname + local detail = last.detail + if tag == "maction" then + if detail == "" then + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + elseif actionstack[#actionstack] == action then + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + else + insert(actionstack,action) + setattr(start,a_tagged,start_tagged("mrow",{ detail = action })) + process(list) + stop_tagged() + remove(actionstack) + end + elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then + -- looks like it gets processed twice + -- do we still end up here ? + setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute + process(list) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + end + else -- never happens, we're always document + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + end + end + elseif id == fraction_code then + local num = getfield(start,"num") + local denom = getfield(start,"denom") + local left = getfield(start,"left") + local right = getfield(start,"right") + if left then + setattr(left,a_tagged,start_tagged("mo")) + process(left) + stop_tagged() + end + setattr(start,a_tagged,start_tagged("mfrac")) + process(num) + process(denom) + stop_tagged() + if right then + setattr(right,a_tagged,start_tagged("mo")) + process(right) + stop_tagged() + end + elseif id == choice_code then + local display = getfield(start,"display") + local text = getfield(start,"text") + local script = getfield(start,"script") + local scriptscript = getfield(start,"scriptscript") + if display then + process(display) + end + if text then + process(text) + end + if script then + process(script) + end + if scriptscript then + process(scriptscript) + end + elseif id == fence_code then + local subtype = getsubtype(start) + local delim = getfield(start,"delimiter") + if subtype == leftfence_code then + -- left + local properties = { } + insert(fencesstack,properties) + setattr(start,a_tagged,start_tagged("mfenced",properties)) -- needs checking + if delim then + start_tagged("ignore") + local chr = getchar(delim) + if chr ~= 0 then + properties.left = chr + end + process(delim) + stop_tagged() + end + start_tagged("mrow") -- begin of subsequence + elseif subtype == middlefence_code then + -- middle + if delim then + start_tagged("ignore") + local top = fencesstack[#fencesstack] + local chr = getchar(delim) + if chr ~= 0 then + local mid = top.middle + if mid then + mid[#mid+1] = chr + else + top.middle = { chr } + end + end + process(delim) + stop_tagged() + end + stop_tagged() -- end of subsequence + start_tagged("mrow") -- begin of subsequence + elseif subtype == rightfence_code then + local properties = remove(fencesstack) + if not properties then + report_tags("missing right fence") + properties = { } + end + if delim then + start_tagged("ignore") + local chr = getchar(delim) + if chr ~= 0 then + properties.right = chr + end + process(delim) + stop_tagged() + end + stop_tagged() -- end of subsequence + stop_tagged() + else + -- can't happen + end + elseif id == radical_code then + local left = getfield(start,"left") + local degree = getfield(start,"degree") + if left then + start_tagged("ignore") + process(left) -- root symbol, ignored + stop_tagged() + end + if degree and hascontent(degree) then + setattr(start,a_tagged,start_tagged("mroot")) + processsubsup(start) + process(degree) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("msqrt")) + processsubsup(start) + stop_tagged() + end + elseif id == accent_code then + local subtype = getsubtype(start) + local accent = getfield(start,"accent") + local bot_accent = getfield(start,"bot_accent") + if bot_accent then + if accent then + setattr(start,a_tagged,start_tagged("munderover", { + accent = true, + top = getunicode(accent), + bottom = getunicode(bot_accent), + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(bot_accent) + process(accent) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("munder", { + accent = true, + bottom = getunicode(bot_accent), + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(bot_accent) + stop_tagged() + end + elseif accent then + setattr(start,a_tagged,start_tagged("mover", { + accent = true, + top = getunicode(accent), + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(accent) + stop_tagged() + else + processsubsup(start) + end + elseif id == glue_code then + -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) })) + setattr(start,a_tagged,start_tagged("mspace")) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] })) + stop_tagged() + end + end +-- showtag(start,id,false) + start = getnext(start) + end + if mtexttag then + stop_tagged() + end +end + +function noads.handlers.tags(head,style,penalties) + start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" }) + setattr(head,a_tagged,start_tagged("mrow")) +-- showtag(head,getid(head),true) + process(head) +-- showtag(head,getid(head),false) + stop_tagged() + stop_tagged() +end diff --git a/tex/context/base/mkxl/math-toy.mkxl b/tex/context/base/mkxl/math-toy.mkxl new file mode 100644 index 000000000..510872e3b --- /dev/null +++ b/tex/context/base/mkxl/math-toy.mkxl @@ -0,0 +1,54 @@ +%D \module +%D [ file=math-toy, +%D version=2020.08.31, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Toy 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 Math Macros / Toy} + +\unprotect + +%D Just an example: +%D +%D \starttyping +%D \enabletrackers[math.toysymbol] +%D +%D \definemathtoysymbol[Plus] [bin][+] +%D \definemathtoysymbol[Minus][bin][-] +%D \definemathtoysymbol[Equal][rel][=] +%D +%D $\dorecurse{199}{x_{#1} \ifodd#1\relax\Plus\else\Minus\fi} x_{200} \Equal n$ \blank +%D \stoptyping + +\permanent\tolerant\protected\def\definemathtoysymbol[#1]#*[#2]#*[#3]% + {\ifarguments\or\or\or + \setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}% + \fi} + +\protected\def\math_toy_define_symbol_traced#1#2% + {\normalexpanded{\discretionary class #1 % + {$\Ustyle\number\mathstyle \darkred #2$}% + {$\Ustyle\number\mathstyle \darkblue #2$}% + {$\Ustyle\number\mathstyle \darkgreen #2$}}} + +\protected\def\math_toy_define_symbol_normal#1#2% + {\normalexpanded{\discretionary class #1 % + {$\Ustyle\number\mathstyle #2$}% + {$\Ustyle\number\mathstyle #2$}% + {$\Ustyle\number\mathstyle #2$}}} + +\installtextracker + {math.toysymbol} + {\let\math_toy_define_symbol_indeed\math_toy_define_symbol_traced} + {\let\math_toy_define_symbol_indeed\math_toy_define_symbol_normal} + +\let\math_toy_define_symbol_indeed\math_toy_define_symbol_normal + +\protect diff --git a/tex/context/base/mkxl/meta-blb.mkxl b/tex/context/base/mkxl/meta-blb.mkxl new file mode 100644 index 000000000..247d3a34e --- /dev/null +++ b/tex/context/base/mkxl/meta-blb.mkxl @@ -0,0 +1,53 @@ +%D \module +%D [ file=meta-blb, +%D version=2018.04.12, +%D title=\METAPOST\ Graphics, +%D subtitle=Blobs, +%D author=Hans Hagen, +%D date=\ currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{MetaPost Graphics / Blobs} + +\registerctxluafile{meta-blb}{} + +\unprotect + +\permanent\protected\def\MPLIBgetblobscaledcm#1#2#3#4#5#6#7#8#9% + {\clf_mpgetblob\MPtextbox#1\relax + \setbox\MPbox\hpack\bgroup + \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}% + \vpack to \zeropoint\bgroup + \vss + \hpack to \zeropoint \bgroup + % \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}% + \fastsxsy{#8}{#9}{\box\MPtextbox}% + \hss + \egroup + \egroup + \egroup + \smashbox\MPbox + \box\MPbox} + +%D An example of usage: + +\definefontfeature[followtext][liga=no] + +\permanent\protected\def\MPLIBfollowtext#1#2% + {\begingroup + \scratchcounter#1\relax + \setbox\scratchbox\hbox{\addff{followtext}#2}% + \clf_MPLIBconvertfollowtext\scratchcounter\scratchbox + \endgroup} + +%D New: + +\newtoks\mpblobtext + +\permanent\protected\mpblobtext{\global\setbox\mptextbox\vbox{\clf_mpblobtext}} + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-fig.mkxl b/tex/context/base/mkxl/meta-fig.mkxl new file mode 100644 index 000000000..9ddd5e394 --- /dev/null +++ b/tex/context/base/mkxl/meta-fig.mkxl @@ -0,0 +1,71 @@ +%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 stand||alone||graphics, that is, +%D each graphic gets is own page. Because graphics are wrapped in a \type {\framed}, +%D you can add overlays to the graphic directly, and since the whole \CONTEXT\ +%D machinery is available, you can also add 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 definitions with the text +%D flow, since all settings are kept local. The page is clipped to the image size. + +\definefittingpage + [MPpage] + [\c!align=, + \c!command=\meta_process_graphic_command, + \c!instance=] + +\permanent\protected\def\setupMPpage + {\setupfittingpage[MPpage]} + +\protected\def\meta_process_graphic_command + {\doif{\fittingpageparameter\c!alternative}\v!offset + {\def\meta_relocate_graphic{\clf_setpageorigin\MPllx\MPlly\relax}}% + \meta_process_graphic_instance{\fittingpageparameter\c!instance}} + +%D \macros +%D {MPfigure} +%D +%D A bit out of place, here but nevertheless: + +\permanent\protected\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/tex/context/base/mkxl/meta-fnt.mkxl b/tex/context/base/mkxl/meta-fnt.mkxl new file mode 100644 index 000000000..690571c79 --- /dev/null +++ b/tex/context/base/mkxl/meta-fnt.mkxl @@ -0,0 +1,33 @@ +%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}{} + +\unprotect + +\permanent\tolerant\protected\def\definemetafont[#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/tex/context/base/mkxl/meta-fun.mkxl b/tex/context/base/mkxl/meta-fun.mkxl new file mode 100644 index 000000000..e30660392 --- /dev/null +++ b/tex/context/base/mkxl/meta-fun.mkxl @@ -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}{} + +\unprotect + +%D Just a few handy helpers: + +\ifdefined\MPtoks\else \newtoks\MPtoks \fi +\ifdefined\MPbox \else \newbox \MPbox \fi + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-grd.mkxl b/tex/context/base/mkxl/meta-grd.mkxl new file mode 100644 index 000000000..009149e46 --- /dev/null +++ b/tex/context/base/mkxl/meta-grd.mkxl @@ -0,0 +1,105 @@ +%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} + +\unprotect + +%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{meta:grd:basegrid} + begingroup ; + + save sc, dx, dy, wd, ht, ox, oy, ax, ay ; + + sc = \directdummyparameter\c!factor*\directdummyparameter\c!scale ; + dx = \MPdpar\directdummyparameter\c!dx*sc ; + dy = \MPdpar\directdummyparameter\c!dy*sc ; + wd = \directdummyparameter\c!nx*dx ; + ht = \directdummyparameter\c!ny*dy ; + ox = \MPdpar\directdummyparameter\c!xoffset\relax ; + oy = \MPdpar\directdummyparameter\c!yoffset\relax ; + + if "\directdummyparameter\c!align" = "\v!middle" : + ax = \MPdpar\directdummyparameter\c!dx/2 + ay = \MPdpar\directdummyparameter\c!dy/2 + else : + ax = 0 ; + ay = 0 ; + fi ; + + draw image ( + 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 ; + ) + withpen pencircle scaled \MPdpar\directdummyparameter\c!rulethickness\space + withcolor "\directdummyparameter\c!rulecolor" ; + + draw image ( + if \directdummyparameter\c!xstep > 0 : + for i=1 step \directdummyparameter\c!xstep until \directdummyparameter\c!nx : + draw thetextext.bot(decimal i,(i*dx-ax,oy)); + endfor ; + fi ; + if \directdummyparameter\c!ystep > 0 : + for i=1 step \directdummyparameter\c!ystep until \directdummyparameter\c!ny : + draw thetextext.lft(decimal i,(ox,i*dy-ay)) ; + endfor ; + fi ; + ) + withcolor "\directdummyparameter\c!color" ; + + endgroup ; +\stopuseMPgraphic + +\permanent\tolerant\protected\def\basegrid[#1]% + {\dontleavehmode + \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=.25\exheight,% + \c!xoffset=\directdummyparameter\c!offset,% + \c!yoffset=\directdummyparameter\c!offset,% + \c!align=,% + \c!color=\currentcolorname,% + \c!rulecolor=\currentcolorname,% + \c!rulethickness=\linewidth,% + #1]% + \usedummystyleandcolor\c!style\c!color + \setexpandeddummyparameter\c!dx{\directdummyparameter\c!dx\directdummyparameter\c!unit}% + \setexpandeddummyparameter\c!dy{\directdummyparameter\c!dy\directdummyparameter\c!unit}% + \useMPgraphic{meta:grd:basegrid}% + \egroup} + +\aliased\let\grid\basegrid + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-imp-experiments.mkxl b/tex/context/base/mkxl/meta-imp-experiments.mkxl new file mode 100644 index 000000000..644a8fff0 --- /dev/null +++ b/tex/context/base/mkxl/meta-imp-experiments.mkxl @@ -0,0 +1,358 @@ +%D \module +%D [ file=meta-imp-experiments, +%D version=2020.03.18, +%D title=\METAPOST\ Graphics, +%D subtitle=Experimental 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. + +%D This library implements some experimental functionality that eventually +%D might end up someplace else. + +\startluacode + + -- I decided to play with this kind of graphics after I read an article in a Dutch + -- popular science journal. It was an article about virusus in the mids of the time + -- when covid raged, so it also was a distraction. + + -- This is a typical case of first prototyping it in Lua using the 'context' command + -- to generate MetaPost code and when that worked okay do it the following way. The + -- way data is passed is a bit messy. + + do + + local function sum(t) + local n = 0 + for i=1,#t do + n = n + t[i] + end + return n + end + + local function checked(data) + if data then + local n = #data + for i=1,n do + data[i][i] = 0 + end + for i=1,n do + local di = data[i] + for j=i+1,n do + local dj = data[j] + local dji = dj[i] + if not dji then + dji = 0 + dj[i] = 0 + end + di[j] = dji + end + end + return data + else + return { } + end + end + + local data, list = nil, nil + + function mp.lmt_overlap_prepare() + data = checked(metapost.getparameter { "data" }) + list = { } + for i=1,#data do + list[i] = sum(data[i]) + end + end + + function mp.lmt_overlap_reset() + data = nil + list = nil + end + + function mp.lmt_overlap_n() + return #list + end + + function mp.lmt_overlap_data(i, j) + if j then + return data[i][j] + else + return list[i] + end + end + + local injectstring = mp.inject.string + + function mp.lmt_overlap_text(i, j) + injectstring(data[i][j] or "") + end + + function mp.lmt_overlap_label(i) + local labels = metapost.getparameter { "labels" } + injectstring(labels and labels[i] or "") + end + + function mp.lmt_overlap_color(i) + local colors = metapost.getparameter { "colors" } + injectstring(colors and colors[i] or "darkgray") + end + + function mp.lmt_overlap_total() + return sum(list) + end + + end +\stopluacode + +\startMPextensions + +presetparameters "overlap" [ + options = "paths,lines", + gap = 4, + subgap = 2, + offset = 8, + color = "darkgray", + alternative = "circular", + colors = { + "darkred", + "darkgreen", + "darkblue", + "darkyellow", + "darkmagenta", + "darkcyan" + }, +] ; + +def lmt_overlap = applyparameters "overlap" "lmt_do_overlap" enddef ; + +vardef lmt_do_overlap_circular = + + astep := 360 / steps ; + + p := fullcircle scaled steps ; + r := origin -- (2*steps,0) ; + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) ; + first := start ; + last := stop ; + for j=1 upto n: + if i <> j : + last := first + lua.mp.lmt_overlap_data(i,j) ; + a := p intersectionpoint (r rotated (first * astep + 0.1)) ; % the 0.1 is somehow needed, why + b := p intersectionpoint (r rotated (last * astep - 0.1)) ; % the 0.1 is somehow needed, why + qq[i][j] := (p cutafter b) cutbefore a ; + first := last + subgap ; + fi ; + endfor ; + start := stop + gap + (n - 1) * subgap ; + endfor ; + + if hasoption "options" "paths" : + + for i=1 upto n : + for j=1 upto n : + if i <> j : + q := qq[i][j] ; + freelabeloffset := getparameter "offset" ; + freelabel(lua.mp.lmt_overlap_text(i,j), point .5 along q, origin) ; + if i < j : + s := qq[j][i] ; + a := point length(q) of q ; + b := point 0 of s ; + c := point length(s) of s ; + d := point 0 of q ; + q := q & a .. controls origin and origin .. b & s & c .. controls origin and origin .. d -- cycle ; + fill q withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; + fi ; + fi ; + endfor ; + endfor ; + + fi ; + + if hasoption "options" "lines" : + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; + a := p intersectionpoint (r rotated (start * astep)) ; + b := p intersectionpoint (r rotated (stop * astep)) ; + q := (p cutbefore a) cutafter b ; + freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; + freelabel(lua.mp.lmt_overlap_label(i), point .5 along q, origin) ; + draw q withcolor white withpen pencircle scaled 5 ; + draw q withcolor getparameter "color" withpen pencircle scaled 5 ; + start := stop + gap + subgap ; + endfor ; + + fi ; + +enddef ; + +vardef lmt_do_overlap_linear = + astep := 1 ; % 1.25 + + p := origin -- (astep * steps,0) ; + r := origin -- (0,astep * steps) ; + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) ; + first := start ; + last := stop ; + for j=1 upto n: + if i <> j : + last := first + lua.mp.lmt_overlap_data(i,j) ; + qq[i][j] := (first * astep,0) -- (last * astep,0) ; + first := last + subgap ; + fi ; + endfor ; + start := stop + gap + (n - 1) * subgap ; + endfor ; + + if hasoption "options" "paths" : + + for i=1 upto n : + for j=1 upto n : + if i < j : + qq[i][j] := qq[i][j] { up } .. { down } qq[j][i] { up } .. { down} cycle ; + fill qq[i][j] withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; + fi ; + endfor ; + endfor ; + + for i=1 upto n : + for j=1 upto n : + if i < j : + t := thelabel(lua.mp.lmt_overlap_text(i,j), (center topboundary qq[i][j]) ) ; + fill boundingbox t enlarged (ExHeight/2) withcolor white ; + draw t ; + fi ; + endfor ; + endfor ; + + fi ; + + if hasoption "options" "lines" : + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; + q := (start * astep,0) -- (stop * astep,0) ; + freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; + label.bot(lua.mp.lmt_overlap_label(i), (point .5 along q) shifted (0,- freelabeloffset/4)) ; + draw q withcolor white withpen pencircle scaled 5 ; + draw q withcolor getparameter "color" withpen pencircle scaled 5 ; + start := stop + gap + subgap ; + endfor ; + + fi ; + +enddef ; + +vardef lmt_do_overlap = + image ( + + pushparameters "overlap" ; + + save p, q, r, s, qq, a, b, c, d, t, n, gap, subgap, steps, astep, start, stop, first, last ; + path p, q, r, s, qq[][] ; + pair a, b, c, d ; + picture t ; + numeric n, gap, subgap, steps, astep, start, stop, first, last ; + save freelabeloffset; freelabeloffset := 8 ; + interim linecap := butt; + interim linejoin := squared; + + lua.mp.lmt_overlap_prepare() ; + + n := lua.mp.lmt_overlap_n(); + gap := getparameter "gap" ; + subgap := getparameter "subgap" ; + steps := lua.mp.lmt_overlap_total() + (n * gap) + n * (n - 1) * subgap ; + + if ((getparameter "alternative") = "linear") or ((getparameter "alternative") = "line") : + lmt_do_overlap_linear ; + else : + lmt_do_overlap_circular ; + fi ; + + lua.mp.lmt_overlap_reset() ; + + popparameters ; + ) +enddef ; + +\stopMPextensions + +\continueifinputfile{meta-imp-experiments.mkxl} + +% \useMPlibrary[experiments] + +\usemodule[article-basic] + +\starttext + +% todo: datafile: { data = { }, labels = { } } + +% % data = { +% % { 0, 10, 30, 10, 20 }, +% % { 10, 0, 10, 20, 10 }, +% % { 30, 10, 0, 5, 15 }, +% % { 10, 20, 5, 0, 5 }, +% % { 20, 10, 15, 5, 0 } +% % }, +% % data = { +% % { 0 }, +% % { 10, 0 }, +% % { 30, 10, 0 }, +% % { 10, 20, 5, 0 }, +% % { 20, 10, 15, 5, 0 } +% % }, +% data = { +% { }, +% { 10 }, +% { 30, 10 }, +% { 10, 20, 5 }, +% { 20, 10, 15, 5 } +% }, + +\startbuffer +\startMPcode{doublefun} + draw lmt_overlap [ + alternative = "circular", + data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, + labels = { "one", "two", "three", "four", "five" } + ] ; +\stopMPcode +\stopbuffer + +\startlinecorrection[blank] + \getbuffer +\stoplinecorrection + +\startbuffer +\startMPcode{doublefun} + draw lmt_overlap [ + alternative = "linear", + data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, + labels = { "one", "two", "three", "four", "five" } + ] ; +\stopMPcode +\stopbuffer + +\startlinecorrection[blank] + \getbuffer +\stoplinecorrection + +\stoptext diff --git a/tex/context/base/mkxl/meta-imp-gamesymbols.mkxl b/tex/context/base/mkxl/meta-imp-gamesymbols.mkxl new file mode 100644 index 000000000..d79e59f69 --- /dev/null +++ b/tex/context/base/mkxl/meta-imp-gamesymbols.mkxl @@ -0,0 +1,349 @@ +%D \module +%D [ file=meta-imp-gamesymbols, +%D version=2019.10.10, +%D title=\METAPOST\ Graphics, +%D subtitle=Game 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 The \METAFUN\ code here is not optimal and efficient but as it serves as an +%D example I decided to keep it simple. Also, performance is not really an issue +%D here anyway. Inspired by the classic \quote {Concrete Mathematics} by Don Knuth +%D we define dice and dominos, which happen to be \UNICODE\ characters now. We +%D use this opportunity to demonstrate slightly different approached. + +%D Each dice gets it's own macro at the \METAPOST\ end. Watch how we use the \type +%D {simplefun} instance in combination with a calculation wrapper. This will just +%D execute the code and leave no traces in the text flow. The code itself is not +%D that spectacular: + +\startMPcalculation{simplefun} + + def DiceFrame = + pickup pencircle scaled 1/2 ; + draw unitsquare scaled 8 ; + pickup pencircle scaled 3/2 ; + enddef ; + + vardef DiceOne = + DiceFrame ; + draw (4,4) ; + enddef ; + vardef DiceTwoA = + DiceFrame ; + draw (2,6) ; draw (6,2) ; + enddef ; + vardef DiceTwoB = + DiceFrame ; + draw (6,6) ; draw (2,2) ; + enddef ; + vardef DiceTwo = + if hasoption "mpsfont" "option" "reverse" : + DiceTwoB + else : + DiceTwoA + fi ; + enddef ; + vardef DiceThreeA = + DiceFrame ; + draw (2,6) ; draw (4,4) ; draw (6,2) ; + enddef ; + vardef DiceThreeB = + DiceFrame ; + draw (6,6) ; draw (4,4) ; draw (2,2) ; + enddef ; + vardef DiceThree = + if hasoption "mpsfont" "option" "reverse" : + DiceThreeB + else : + DiceThreeA + fi ; + enddef ; + vardef DiceFour = + DiceFrame ; + draw (2,6) ; draw (6,6) ; draw (2,2) ; draw (6,2) ; + enddef ; + vardef DiceFive = + DiceFrame ; + draw (2,6) ; draw (6,6) ; draw (4,4) ; draw (2,2) ; draw (6,2) ; + enddef ; + vardef DiceSix = + DiceFrame ; + draw (2,6) ; draw (6,6) ; draw (2,4) ; draw (6,4) ; draw (2,2) ; draw (6,2) ; + enddef ; + + vardef DiceBad = + pickup pencircle scaled 1/2 ; + draw unitsquare scaled 8 ; + draw (1,7) -- (7,1) ; draw (1,1) -- (7,7) ; + enddef ; + + lmt_registerglyphs [ + name = "dice", + units = 12, + width = 8, + height = 8, + depth = 0, + usecolor = true, + ] ; + + lmt_registerglyph [ category = "dice", unicode = "0x2680", code = "DiceOne;" ] ; + lmt_registerglyph [ category = "dice", unicode = "0x2681", code = "DiceTwo;" ] ; + lmt_registerglyph [ category = "dice", unicode = "0x2682", code = "DiceThree;" ] ; + lmt_registerglyph [ category = "dice", unicode = "0x2683", code = "DiceFour;" ] ; + lmt_registerglyph [ category = "dice", unicode = "0x2684", code = "DiceFive;" ] ; + lmt_registerglyph [ category = "dice", unicode = "0x2685", code = "DiceSix;" ] ; + + lmt_registerglyph [ category = "dice", private = "invaliddice", code = "DiceBad;" ] ; + +\stopMPcalculation + +%D At the \TEX\ end we define three features. The reverse is just there for fun. The +%D digits features will map digits onto dice. + +\definefontfeature + [dice:normal] + [default] + [metapost={category=dice}] + +\definefontfeature + [dice:reverse] + [default] + [metapost={category=dice,option=reverse}] + +\definefontfeature + [dice:digits] + [dice:digits=yes] + +%D The mapping to dice happens here: + +\startluacode + + -- local invalid = fonts.helpers.privateslot("invaliddice") + + fonts.handlers.otf.addfeature("dice:digits", { + type = "substitution", + order = { "dice:digits" }, + nocheck = true, + data = { + [0x30] = "invaliddice", + [0x31] = 0x2680, + [0x32] = 0x2681, + [0x33] = 0x2682, + [0x34] = 0x2683, + [0x35] = 0x2684, + [0x36] = 0x2685, + [0x37] = "invaliddice", + [0x38] = "invaliddice", + [0x39] = "invaliddice", + }, + } ) + +\stopluacode + +%D An example is given at the the end of this file so we now move forward with +%D the dominos. + +\startMPcalculation{simplefun} + + %D Because there are so many dominos we predefine the shapes and then register + %D the lot in a loop. + + picture Dominos[] ; + + Dominos[0] := image() ; + Dominos[1] := image(draw(4,4);) ; + Dominos[2] := image(draw(2,6);draw(6,2);); + Dominos[3] := image(draw(2,6);draw(4,4);draw(6,2);); + Dominos[4] := image(draw(2,6);draw(6,6);draw(2,2);draw(6,2);); + Dominos[5] := image(draw(2,6);draw(6,6);draw(4,4);draw(2,2);draw(6,2);); + Dominos[6] := image(draw(2,6);draw(4,6);draw(6,6);draw(2,2);draw(4,2);draw(6,2);); + % Dominos[7] := Dominos[0] ; + % Dominos[8] := Dominos[0] ; + % Dominos[9] := Dominos[0] ; + + %D Defining the font properties is straightforward: + + lmt_registerglyphs [ + name = "dominos", + units = 12, + width = 16, + height = 8, + depth = 0, + usecolor = true, + ] ; + + %D We have horizontal dominos: + + def DrawDominoH(expr a, b) = + draw image ( + pickup pencircle scaled 1/2 ; + if (getparameterdefault "mpsfont" "color" "") = "black" : + fillup unitsquare xyscaled (16,8) ; + draw (8,.5) -- (8,7.5) withcolor white ; + pickup pencircle scaled 3/2 ; + draw Dominos[a] + withpen currentpen + withcolor white ; + draw Dominos[b] shifted (8,0) + withpen currentpen + withcolor white ; + else : + draw unitsquare xyscaled (16,8) ; + draw (8,0) -- (8,8) ; + pickup pencircle scaled 3/2 ; + draw Dominos[a] + withpen currentpen ; + draw Dominos[b] shifted (8,0) + withpen currentpen ; + fi ; + ) ; + enddef ; + + %D and vertical ones. We could use the above macro and rotate and shift and reflect + %D but why bother with it: + + def DrawDominoV(expr a, b) = % is H rotated and shifted + draw image ( + pickup pencircle scaled 1/2 ; + if (getparameterdefault "mpsfont" "color" "") = "black" : + fillup unitsquare xyscaled (8,16) ; + draw (.5,8) -- (7.5,8) withcolor white ; + pickup pencircle scaled 3/2 ; + draw Dominos[a] rotatedaround(center Dominos[a],90) + withpen currentpen + withcolor white ; + draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) + withpen currentpen + withcolor white ; + else : + draw unitsquare xyscaled (8,16) ; + draw (0,8) -- (8,8) ; + pickup pencircle scaled 3/2 ; + draw Dominos[a] rotatedaround(center Dominos[a],90) + withpen currentpen ; + draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8) + withpen currentpen ; + fi ; + ) ; + enddef ; + + %D We have two simple loops that define the horizontal range: + + save unicode ; numeric unicode ; unicode := 127025 ; % 1F031 + + for i=0 upto 6 : + for j=0 upto 6 : + lmt_registerglyph [ + category = "dominos", + unicode = unicode, + code = "DrawDominoH(" & decimal i & "," & decimal j & ");", + width = 16, + height = 8, + ] ; + unicode := unicode + 1 ; + endfor ; + endfor ; + + %D and the vertical range: + + save unicode ; numeric unicode ; unicode := 127075 ; + + for i=0 upto 6 : + for j=0 upto 6 : + lmt_registerglyph [ + category = "dominos", + unicode = unicode, + code = "DrawDominoV(" & decimal i & "," & decimal j & ");", + width = 8, + height = 16, + ] ; + unicode := unicode + 1 ; + endfor ; + endfor ; + + %D Now we're done at the \METAFUN\ end. + +\stopMPcalculation + +%D We predefine two features: + +\definefontfeature + [dominos:white] + [default] + [metapost={category=dominos}] + +\definefontfeature + [dominos:black] + [default] + [metapost={category=dominos,color=black}] + +\definefontfeature + [dominos:digits] + [dominos:digits=yes] + +%D This last feature is yet to be defined. We could deal with the invalid +%D dominos with some substitution trickery but let's keep it simple. + +\startluacode + + local ligatures = { } + local unicode = 127025 + + for i=0x30,0x36 do + for j=0x30,0x36 do + ligatures[unicode] = { i, j } + unicode = unicode + 1 ; + end + end + + fonts.handlers.otf.addfeature("dominos:digits", { + type = "ligature", + order = { "dominos:digits" }, + nocheck = true, + data = ligatures, + } ) + +\stopluacode + +\continueifinputfile{meta-imp-gamesymbols.mkxl} + +\starttext + + \definefont[DominoW][Serif*dominos:white] + \definefont[DominoB][Serif*dominos:black] + \definefont[DominoD][Serif*dominos:white,dominos:digits] + + \startTEXpage[offset=3pt] + \DominoW + \char"1F043\quad 🀱\quad + \char"1F052\quad 🀲\quad + \char"1F038\quad 🀳\quad + \darkgreen\char"1F049\quad \char"1F07B\quad + \DominoB + \char"1F087\quad + \char"1F088\quad + \char"1F089\quad + \DominoD + \darkred 12\quad56\quad64% + \stopTEXpage + + \definefont[DiceN][Serif*dice:normal] + \definefont[DiceR][Serif*dice:reverse] + \definefont[DiceD][Serif*dice:normal,dice:digits] + + \startTEXpage[offset=3pt] + \DiceN + \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% + \DiceN + \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}% + \DiceD + \darkblue 2\quad5\quad3\quad0 + \stopTEXpage + +\stoptext diff --git a/tex/context/base/mkxl/meta-imp-symbols.mkxl b/tex/context/base/mkxl/meta-imp-symbols.mkxl new file mode 100644 index 000000000..f88fd6f87 --- /dev/null +++ b/tex/context/base/mkxl/meta-imp-symbols.mkxl @@ -0,0 +1,99 @@ +%D \module +%D [ file=meta-imp-symbols, +%D version=2019.10.01, +%D title=\METAPOST\ Graphics, +%D subtitle=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 is an (experimental) prelude to more. + +\startMPcalculation{simplefun} + + pen SymbolPen ; SymbolPen := pencircle scaled 1/4 ; + + vardef SymbolBullet = fill unitcircle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x2022 • + vardef SymbolDash = draw (origin--right) scaled 3 shifted (1.5,3.0) withpen SymbolPen scaled 2 enddef ; % 0x2013 – + vardef SymbolTriangle = draw unittriangle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25B6 ⊳ + vardef SymbolCircle = fill unitcircle scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x2218 ∘ + vardef SymbolSquare = draw unitsquare scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25A1 □ + vardef SymbolDiamond = draw unitdiamond scaled 3 shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x22C4 ⋄ + vardef SymbolBlackTriangle = fillup unittriangle scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25B6 ▶ + vardef SymbolBlackSquare = fillup unitsquare scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25A0 ■ + vardef SymbolBlackDiamond = fillup unitdiamond scaled (3-1/16) shifted (1.5,1.5) withpen SymbolPen enddef ; % 0x25C6 ◆ + + vardef SymbolNotDef = + draw center unitcircle + scaled 3 + shifted (1.5,1.5) + withpen SymbolPen scaled 4 + enddef ; + + vardef SymbolStar = % 0x22C6 % ⋆ + SymbolNotDef + enddef ; + + vardef SymbolCheckmark = % 0x2713 ✓ + SymbolNotDef + enddef ; + + vardef SymbolAsterisk = % 0x2217 ∗ + SymbolNotDef + enddef ; + + % We could set code directly to the meaning of the macro. + + lmt_registerglyphs [ + name = "symbols", + units = 10, + usecolor = true, + width = 6, + height = 6, + depth = 0, + code = "SymbolNotDef ;", + ] ; + + lmt_registerglyph [ category = "symbols", unicode = "0x2022", code = "SymbolBullet ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x2013", code = "SymbolDash ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x22C6" ] ; % , code = "SymbolStar ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x22B3", code = "SymbolTriangle ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x2218", code = "SymbolCircle ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x25A1", code = "SymbolSquare ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x22C4", code = "SymbolDiamond ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x2713" ] ; % , code = "SymbolCheckmark ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x2217" ] ; % , code = "SymbolAsterisk ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x25B6", code = "SymbolBlackTriangle ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x25A0", code = "SymbolBlackSquare ;" ] ; + lmt_registerglyph [ category = "symbols", unicode = "0x25C6", code = "SymbolBlackDiamond ;" ] ; + +\stopMPcalculation + +\continueifinputfile{meta-imp-symbols.mkxl} + +\usemodule[article-basic] \setupbodyfont[pagella] + +\starttext + +\definefontfeature[metasymbols][metapost=symbols] + +\definefont[MyFont] [Serif*default,metasymbols sa 1] + +Some metasymbols: + +\startitem {\MyFont • □ ◆}\quad Regular rendering. \stopitem +\startitem {\MyFont\red • □ ◆}\quad Rendering with color. \stopitem +\startitem {\MyFont\blue\showglyphs • □ ◆}\quad Idem but with boundingboxes shown. \stopitem + +And some more: + +\startlines + • – ⋆ ⊳ ∘ □ ⋄ ✓ ∗ ▶ ■ ◆ + {\MyFont • – ⋆ ⊳ ∘ □ ⋄ ✓ ∗ ▶ ■ ◆} +\stoplines + +\stoptext diff --git a/tex/context/base/mkxl/meta-imp-threesix.mkxl b/tex/context/base/mkxl/meta-imp-threesix.mkxl new file mode 100644 index 000000000..56a400b45 --- /dev/null +++ b/tex/context/base/mkxl/meta-imp-threesix.mkxl @@ -0,0 +1,246 @@ +%D \module +%D [ file=meta-imp-threesix, +%D version=2019.00.00, +%D title=\METAPOST\ Graphics, +%D subtitle=Don Knuths ThreeSix font, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 design of the font is if course by Don Knuth and can be found in facs9b.ps. I +%D wish I was clever enough to understand all the good stuff in there. + +\startluacode + local unpack = unpack + local concat = table.concat + local gsub, gmatch, utfbyte = string.gsub, string.gmatch, utf.byte + + local font36 = { + ["0"] = [[00111100 01111110 11000011 11000011 11000011 11000011 01111110 00111100]], + ["1"] = [[00011100 11111100 11101100 00001100 00001100 00001100 11111111 11111111]], + ["2"] = [[00111110 01110011 01110011 00000011 00001110 00111000 11110001 11111111]], + ["3"] = [[01111110 01100110 00000110 00111100 00000110 11100111 11100111 01111110]], + ["4"] = [[00001110 00011110 00110110 01100110 11111111 11111111 00000110 00001110]], + ["5"] = [[01111110 01111110 01000000 01111100 01000111 00000011 11000111 11111110]], + ["6"] = [[01111110 01100110 11000000 11011100 11100110 11000011 01100011 01111110]], + ["7"] = [[11111111 11111111 10000111 10001110 00011100 00011100 00011100 00011100]], + ["8"] = [[01111110 01100110 01100110 00111100 11000011 11000011 11000011 01111110]], + ["9"] = [[01111110 11000110 11000011 01100111 00111011 00000011 01100110 01111110]], + ["A"] = [[000110000 000111000 001111100 001101100 011001110 011111110 010000110 111100111]], + ["B"] = [[1111100 1110110 0110110 0111100 0110011 0110011 1110011 1111100]], + ["C"] = [[01111101 11110011 11100001 11100001 11100000 11100000 11100001 01111110]], + ["D"] = [[11111100 11100010 01100011 01100011 01100011 01100011 11100010 11111100]], + ["E"] = [[1111111 1110001 0110101 0111100 0110100 0110001 1110001 1111111]], + ["F"] = [[11111111 11100001 01100101 01111100 01100100 01100000 11111000 11111000]], + ["G"] = [[01111010 11100110 11100010 11100000 11100111 11100010 11100010 01111100]], + ["H"] = [[11100111 11100111 01000010 01111110 01000010 01000010 11100111 11100111]], + ["I"] = [[1111111 1111111 0011000 0011000 0011000 0011000 1111111 1111111]], + ["J"] = [[01111111 01111111 00000110 00000110 11110110 01100110 01100110 00111100]], + ["K"] = [[11101110 11100100 01101000 01110000 01111000 01101100 11100110 11101111]], + ["L"] = [[111111000 111111000 011000000 011000000 011000000 011000011 111000011 111111111]], + ["M"] = [[1100000011 1110000111 0111111110 0100110010 0100110010 0100000010 1100000011 1100000011]], + ["N"] = [[11000011 11100011 01110010 01111010 01011110 01001110 11100110 11100010]], + ["O"] = [[01111110 11000011 11000011 11000011 11000011 11000011 11000011 01111110]], + ["P"] = [[11111110 11100011 01100011 01111110 01100000 01100000 11111000 11111000]], + ["Q"] = [[01111100 11000110 11000110 11000110 11000110 11001110 11000110 01111101]], + ["R"] = [[11111100 11100110 01100110 01111100 01101000 01100100 11100010 11100111]], + ["S"] = [[01111110 11100001 11100001 01111000 00011110 10000111 11000011 10111110]], + ["T"] = [[1111111111 1100110011 1100110011 0000110000 0000110000 0000110000 0001111000 0001111000]], + ["U"] = [[111101111 111101111 011000010 011000010 011000010 011000010 011000010 001111100]], + ["V"] = [[11111000111 11111000111 01110000010 00110000100 00111000100 00011001000 00001101000 00001110000]], + ["W"] = [[111000000111 111000000111 110000000010 011000000100 011001000100 001101101000 001101101000 000110110000]], + ["X"] = [[1111001110 1111000110 0001101000 0000110000 0000110000 0001011000 0110001111 0111001111]], + ["Y"] = [[111100011 111100011 011000010 001110100 000111000 000011000 001111110 001111110]], + ["Z"] = [[11111111 10000111 00001110 00011100 00111000 01110000 11100001 11111111]], + } + + local f_code = string.formatters["ThreeSix(%s);"] + local replace = { ["0"] = "N;", ["1"] = "Y;", [" "] = "L;" } + + local function remap(str) + -- permit abundant spacing (bonus) + str = gsub(str,"%s+", " ") + -- remap what we got to macro calls + str = gsub(str,".",replace) + -- return the result + return str + end + + function MP.registerthreesix(name) + fonts.dropins.registerglyphs { + name = name, + units = 12, + usecolor = true, + preamble = "InitializeThreeSix;", + } + for u, v in table.sortedhash(font36) do + local data = remap(v) + local ny = 8 + local nx = ((#v + 1) // ny) - 1 + local height = ny * 1.1 - 0.1 + local width = nx * 1.1 - 0.1 + fonts.dropins.registerglyph { + category = name, + unicode = utfbyte(u), + width = width, + height = height, + code = f_code(data), + } + end + end + MP.registerthreesix("fontthreesix") +\stopluacode + +\startMPcalculation{simplefun} + def InitializeThreeSix = + save Y, N, L, S ; + save shape, fillcolor, mypen, random, threesixpen, spread, hoffset ; + string shape, fillcolor, mypen ; boolean random ; pen threesixpen ; + shape := getparameterdefault "mpsfont" "shape" "circle" ; + random := hasoption "mpsfont" "random" "true" ; + fillcolor := getparameterdefault "mpsfont" "color" "" ; + mypen := getparameterdefault "mpsfont" "pen" "" ; + spread := getparameterdefault "mpsfont" "spread" 0 ; + hoffset := 12 * spread / 2 ; + threesixpen := pencircle + if mypen = "fancy" : + xscaled 1/20 yscaled 2/20 rotated 45 + else : + scaled 1/20 + fi ; + if shape == "square" : + def S = + unitsquare if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + elseif shape = "diamond" : + def S = + unitdiamond if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + else : + def S = + unitcircle if random : randomizedcontrols 1/20 fi + shifted (nx,ny) + enddef ; + fi ; + if fillcolor = "" : + def N = + nx := nx + dx ; + draw S ; + enddef ; + else : + def N = + nx := nx + dx ; + draw S withcolor "lightgray" ; + enddef ; + fi ; + if fillcolor = "random" : + def Y = + nx := nx + dx ; + fillup S withcolor white randomized (2/3,2/3,2/3) ; + enddef ; + elseif fillcolor = "" : + def Y = + nx := nx + dx ; + fillup S ; + enddef ; + else : + def Y = + nx := nx + dx ; + fillup S withcolor fillcolor ; + enddef ; + fi ; + def L = + nx := - dx ; + ny := ny + dy ; + enddef ; + enddef ; + + vardef ThreeSix (text code) = + save dx, dy, nx, ny ; + dx := 11/10 ; + dy := - 11/10 ; + nx := - dx ; + ny := 0 ; + pickup threesixpen ; + draw image (code) shifted (hoffset,-ny) ; + enddef ; +\stopMPcalculation + +\definefontfeature % black and white, with some spread + [fontthreesix] + [default] + [metapost=fontthreesix] + +\definefontfeature % color, with some spread + [fontthreesix-tweak] + [default] + [metapost={category=fontthreesix,spread=.1}] + +\definefontfeature % color, with some spread + [fontthreesix-color] + [default] + [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1}] + +\definefontfeature % color, tight + [fontthreesix-initial] + [metapost={category=fontthreesix,color=random,shape=circle}] % units? + +\definefont[DEKFontA][Serif*fontthreesix] +\definefont[DEKFontB][Serif*fontthreesix-color] +\definefont[DEKFontC][Serif*fontthreesix-initial] +\definefont[DEKFontD][Serif*fontthreesix-tweak] + +\continueifinputfile{meta-imp-threesix.mkxl} + +\starttext + +\definefontfeature % color, with some spread + [fontthreesix-color] + [default] + [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1,random=yes}] + +\definefont[DEKFontA][Serif*fontthreesix-color @ 200pt] +\definefont[DEKFontB][Serif*fontthreesix-color @ 60pt] + +% Or course: + +\startTEXpage + \DEKFontA TEX +\stopTEXpage + +\startTEXpage + \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX +\stopTEXpage + +% One of the \CONTEXT\ 2020 posters (inspired by NewYork State AC's press +% conferences as these keywords apply quite well to the audience of the +% meeting): + +% \startTEXpage[align={lohi,middle,nothyphenated},offset=20pt] +% \offinterlineskip \vskip10pt +% \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX \vskip60pt +% \DEKFontB TOUGH \vskip20pt +% SMART \vskip20pt +% UNITED \vskip20pt +% DISCIPLINED \vskip20pt +% LOVING \vskip10pt +% \stopTEXpage + +\startpagemakeup + \setupalign[middle,nothyphenated] + \offinterlineskip \vfil\vfil + \DEKFontA T\kern-0.05em\lower.75\exheight\hbox{E}\kern-.05emX \vfil\vfil\vfil + \DEKFontB TOUGH \vfil + SMART \vfil + UNITED \vfil + DISCIPLINED \vfil + LOVING \vfil +\stoppagemakeup + +\stoptext diff --git a/tex/context/base/mkxl/meta-ini.mkxl b/tex/context/base/mkxl/meta-ini.mkxl new file mode 100644 index 000000000..c715cbca5 --- /dev/null +++ b/tex/context/base/mkxl/meta-ini.mkxl @@ -0,0 +1,1387 @@ +%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. + +%D Some lmtx upgrading work needs to be done here. + +% 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}{} + +\unprotect + +\newtoks \everyMPgraphic % mp % public or not ? + +\appendtoks + \restoreendofline % see interferences-001.tex +\to \everyMPgraphic + +\mutable \def\MPruntimefile {mprun} +\mutable \def\currentMPformat {metafun} +\immutable\def\defaultMPinstance{metafun} + +\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 + +%D The next command is, of course, dedicated to Mojca, who needs it for gnuplot. +%D Anyway, the whole multiple engine mechanism is to keep her gnuplot from +%D interfering. + +\permanent\tolerant\protected\def\startMPdefinitions#=#:#2\stopMPdefinitions + {\let\m_meta_saved_instance\currentMPinstance + \edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \gtoksapp\t_meta_definitions{#2}% + \let\currentMPinstance\m_meta_saved_instance} + +\aliased\let\stopMPdefinitions\relax + +\permanent\tolerant\protected\def\startMPextensions#=#:#2\stopMPextensions % we could use buffers instead + {\clf_setmpextensions{#1}{#2}} + +\aliased\let\stopMPextensions\relax + +\permanent\protected\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled + {\gtoksapp\t_meta_initializations{#1}} + +\aliased\let\stopMPinitializations\relax + +\permanent\tolerant\protected\def\startMPinclusions[#1]#*#=#:#3\stopMPinclusions + {\let\m_meta_saved_instance\currentMPinstance % \pushmacro + \edef\currentMPinstance{#2}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \iftok{#1}{+}\else + \global\t_meta_inclusions\emptytoks + \fi + \gtoksapp\t_meta_inclusions{#3}% + \let\currentMPinstance\m_meta_saved_instance} % \popmacro + +\aliased\let\stopMPinclusions\relax + +% The next was broken since we added instances so it will go away! + +\permanent\tolerant\protected\def\MPinclusions[#1]#:#*#=#:#*#=% + {\let\m_meta_saved_instance\currentMPinstance + \iftok{#1}{+}\else + \global\t_meta_inclusions\emptytoks + \fi + \ifparameter#3\or + \edef\currentMPinstance{#2}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \gtoksapp\t_meta_inclusions{#3}% + \else + \let\currentMPinstance\defaultMPinstance + \gtoksapp\t_meta_inclusions{#2}% + \fi + \let\currentMPinstance\m_meta_saved_instance} + +% so far + +\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 + +\permanent\protected\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} + +\protected\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance :: + {\edef\currentMPgraphicname{#2}% + \ifempty\currentMPgraphicname + \edef\currentMPgraphicname{#1}% + \let\currentMPinstance\defaultMPinstance + \orelse\ifcsname\??mpdefinitions#1\endcsname + \edef\currentMPinstance{#1}% + \else + \let\currentMPinstance\defaultMPinstance + \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[minifun] [\s!format=minifun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[lessfun] [\s!format=metafun] +\defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double] +\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[simplefun] [\s!format=metafun,\c!method=\s!double] % maybe use minifun + +%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} + +\mutable\def\MPaskedfigure{false} + +\def\meta_flush_current_initializations + {\ifconditional\c_meta_include_initializations + \the\t_meta_initializations + \fi} + +\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 + \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}% + \ifempty\p_setups \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 + {\pushMPboundingbox + \setbox\b_meta_graphic\hpack\bgroup} + +\let\meta_relocate_graphic\relax % experimental hook + +\def\meta_process_graphic_stop + {\egroup + \meta_place_graphic + \meta_relocate_graphic + \popMPboundingbox} + +\protected\def\meta_process_graphic_instance#1% + {\edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \edef\currentMPformat{\MPinstanceparameter\s!format}% + \meta_process_graphic} + +\protected\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}% + namespace {\??graphicvariable\currentmpvariableclass:}% + \relax}% + \meta_process_graphic_stop + \meta_stop_current_graphic} + +\let\meta_process_graphic_figure_start\relax +\let\meta_process_graphic_figure_stop \relax + +\permanent\protected\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages + {\begingroup + \let\normal_meta_process_graphic_start\meta_process_graphic_start + \let\normal_meta_process_graphic_stop \meta_process_graphic_stop + \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} + +%D Calling up previously defined graphics. + +% \def\includeMPgraphic#1% gets expanded ! +% {\ifcsname\??mpgraphic#1\endcsname +% \csname\??mpgraphic#1\endcsname ; % ; is safeguard +% \fi} +% +% \protected\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: + +\permanent\def\includeMPgraphic#1% gets expanded ! + {\ifcsname\??mpgraphic#1\endcsname + \doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard + \fi} + +\let\meta_enable_include\relax + +%D Drawings (stepwise built): + +\newif\ifMPdrawingdone \MPdrawingdonefalse + +\permanent\protected\def\finalizeMPdrawing + {\MPdrawingdonetrue} + +\mutable\let\MPdrawingdata\empty + +\permanent\protected\def\resetMPdrawing + {\glet\MPdrawingdata\empty + \global\MPdrawingdonefalse} + +\permanent\protected\def\pushMPdrawing + {\globalpushmacro\MPdrawingdata + \glet\MPdrawingdata\empty} + +\permanent\protected\def\popMPdrawing + {\globalpopmacro\MPdrawingdata} + +\permanent\protected\def\getMPdrawing + {\ifMPdrawingdone + \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed? + \fi} + +\permanent\tolerant\def\startMPdrawing[#1]% todo: use pickup #: + {\meta_start_drawing#1} + +\def\meta_start_drawing#1#2\stopMPdrawing + {\relax + \bgroup + \meta_enable_include + \doifelse{#1}{-} + {\xdef\MPdrawingdata{\MPdrawingdata\detokenize{#2}}}% + {\xdef\MPdrawingdata{\MPdrawingdata#2}}% + \egroup} + +\aliased\let\stopMPdrawing\relax + +\permanent\def\MPdrawing#1% + {\relax + \bgroup + \meta_enable_include + \xdef\MPdrawingdata{\MPdrawingdata#1}% + \egroup} + +\permanent\protected\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less + {\gdefcsname\??mpclip#1\endcsname{#2}} + +\aliased\let\stopMPclip\relax + +\protected\def\meta_grab_clip_path#1#2#3% + {\begingroup + \d_overlay_width #2\relax + \d_overlay_height#3\relax + \edef\width {\the\d_overlay_width \space}% + \edef\height{\the\d_overlay_height\space}% + \edef\currentMPclip{#1}% + \ifcsname\??mpclip\currentMPclip\endcsname + \meta_grab_clip_path_yes + \else + \meta_grab_clip_path_nop + \fi + \endgroup} + +\def\meta_grab_clip_path_yes + {\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}% + width \d_overlay_width + height \d_overlay_height + \relax}% + \meta_stop_current_graphic} + +\def\meta_grab_clip_path_nop + {\clf_mpsetclippath + width \d_overlay_width + height \d_overlay_height + \relax} + +%D Since we want labels to follow the document settings, we also set the font +%D related variables. + +\permanent\protected\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 + +%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 background and buttons, +%D the need for passing settings arises. By (mis|)|using the local prefix that +%D belongs to \type {\framed}, we get a rather natural interface to backgrounds. To +%D prevent conflicts, we will use the \type {-} in \METAPOST\ specific variables, +%D 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 + +%D Currently the inheritance of backgrounds does not work and we might drop it +%D 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 ... + +\permanent\tolerant\protected\def\setupMPvariables[#1]#*[#2]% + {\ifarguments + \or + \getrawparameters[\??graphicvariable:][#1]% + \else + \getrawparameters[\??graphicvariable#1:][#2]% + \fi} + +\permanent\tolerant\protected\def\presetMPvariable[#1]#*[#2=#3]% + {\ifcsname\??graphicvariable#1:#2\endcsname \else + \defcsname\??graphicvariable#1:#2\endcsname{#3}% + \fi} + +\permanent\def\MPrawvar#1#2% no checking + {\begincsname\??graphicvariable#1:#2\endcsname} + +\permanent\def\MPvariable#1% todo: could be a framed chain + {\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname} + +\permanent\tolerant\protected\def\useMPvariables[#1]#*[#2]% + {\edef\currentmpvariableclass{#1}% + \meta_prepare_variables{#2}} + +\protected\def\meta_prepare_variables#1% + {\processcommalist[#1]\meta_prepare_variable} + +\protected\def\meta_prepare_variable#1% + {\edef\m_meta_current_variable_template + {\??graphicvariable\currentmpvariableclass:#1}% + \edef\m_meta_current_variable + {\begincsname\m_meta_current_variable_template\endcsname}% + \ifempty\m_meta_current_variable + \expandafter\meta_prepare_variable_nop + \else + \expandafter\meta_prepare_variable_yes + \fi} + +\protected\def\meta_prepare_instance_variables + {\expandafter\processcommalist\expandafter[\m_meta_instance_variables]\meta_prepare_instance_variable} + +\protected\def\meta_prepare_instance_variable#1% + {\edef\m_meta_current_variable_template + {\??graphicvariable\currentmpvariableclass:#1}% + \edef\m_meta_current_variable + {\ifcsname\m_meta_current_variable_template\endcsname + \lastnamedcs + \else + \begincsname\??graphicvariable\currentMPgraphicname:#1\endcsname + \fi}% + \ifempty\m_meta_current_variable + \expandafter\meta_prepare_variable_nop + \else + \expandafter\meta_prepare_variable_yes + \fi} + +\def\meta_prepare_variable_nop + {\expandafter\letcsname\m_meta_current_variable_template\endcsname\meta_prepare_variable_default} + +\def\meta_prepare_variable_color % we use the attribute so we dont' go through namedcolor (why not) + {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\MPcolor\m_meta_current_variable}} + +\def\meta_prepare_variable_number + {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\number\m_meta_current_variable}}% also accepts 0.number + +\def\meta_prepare_variable_dimension + {\expandafter\edefcsname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}} + +\def\meta_prepare_variable_yes + {\ifchkdim\m_meta_current_variable\or + \meta_prepare_variable_dimension + \orelse\ifchknum\m_meta_current_variable\or + \meta_prepare_variable_number + \else + \doifelsecolor\m_meta_current_variable + \meta_prepare_variable_color + \meta_prepare_variable_dimension + \fi} + +\aliased\let\MPvar \MPvariable +\aliased\let\setMPvariables\setupMPvariables + +%D \macros +%D {startuniqueMPgraphic, uniqueMPgraphic} +%D +%D This macros is probably of most use to myself, since I like to use graphics that +%D adapt themselves. The next \METAPOST\ kind of graphic is both unique and reused +%D when possible. +%D +%D \starttyping +%D \defineoverlay[example][\uniqueMPgraphic{test}] +%D +%D \startuniqueMPgraphic {test} +%D draw OverlayBox ; +%D \stopuniqueMPgraphic +%D +%D \startuniqueMPgraphic {test} +%D draw OverlayBox ; +%D \stopuniqueMPgraphic +%D \stoptyping + +% todo: frozen or not? + +\def\overlaystamp % watch the \MPcolor, since colors can be redefined + {\the\d_overlay_width :% + \the\d_overlay_height :% + \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 in determining the +%D uniqueness. In the next macro, the second, optional, argument is used to +%D guarantee the 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 convenient use in overlay +%D definitions, we use \type {{}} 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? + +\protected\def\meta_obey_box_depth + {\setbox\b_meta_graphic\hpack\bgroup + \raise\MPlly\box\b_meta_graphic + \egroup} + +\protected\def\meta_ignore_box_depth + {\normalexpanded + {\meta_obey_box_depth % hence the \protected + \wd\b_meta_graphic\the\wd\b_meta_graphic + \ht\b_meta_graphic\the\ht\b_meta_graphic + \dp\b_meta_graphic\the\dp\b_meta_graphic}} + +\protected\def\meta_obey_box_origin + {\setbox\b_meta_graphic\hpack\bgroup + \kern\MPllx\raise\MPlly\box\b_meta_graphic + \egroup} + +\permanent\protected\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth} +\permanent\protected\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth} +\permanent\protected\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin} +\permanent\protected\def\normalMPboxdepth{\let\meta_relocate_box\relax} + +\let\meta_relocate_box\relax + +\protected\def\meta_place_graphic % the converter also displaces so in fact we revert + {\meta_relocate_box + \box\b_meta_graphic} + +\protected\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens + {\MPllx#2\MPlly#3\MPurx#4\MPury#5% + \hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent + +\protected\def\meta_use_box + {\setunreferencedobject{MP}} + +\def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although, + {\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 + \lastnamedcs + \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 + \xdefcsname\??mpgraphic\overlaystamp:#1\endcsname{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}% + \csname\??mpgraphic\overlaystamp:#1\endcsname\empty + \fi + \endgroup} + +% todo: we partially expand + +\permanent\protected\def\startuniqueMPgraphic + {\dodoublegroupempty\meta_start_unique_graphic} + +\aliased\let\stopuniqueMPgraphic\relax + +\def\meta_start_unique_graphic#1% + {\normalexpanded{\meta_start_unique_graphic_indeed{#1}}} + +\permanent\protected\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic + {\gdefcsname\??mpgraphic#1\endcsname{\meta_handle_unique_graphic{#1}{#2}{#3}}} + +\permanent\tolerant\protected\def\uniqueMPgraphic#=#*#=% + {\meta_begin_graphic_group{#1}% + \setupMPvariables[#1][#2]% + \begincsname\??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}% + \ifempty\m_meta_instance_variables \else + \meta_prepare_instance_variables + \fi + \meta_enable_include % redundant + \meta_process_graphic{#3}% + \endgroup} + +\permanent\protected\def\startuseMPgraphic % todo, modernize + {\dodoublegroupempty\meta_start_use_graphic} + +\aliased\let\stopuseMPgraphic\relax + +\def\meta_start_use_graphic#1% + {\normalexpanded{\meta_start_use_graphic_indeed{#1}}} + +\protected\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic + {\gdefcsname\??mpgraphic#1\endcsname{\meta_handle_use_graphic{#1}{#2}{#3}}} + +\permanent\protected\def\startusableMPgraphic % redundant but handy % todo, modernize + {\dodoublegroupempty\meta_start_usable_graphic} + +\aliased\let\stopusableMPgraphic\relax + +\def\meta_start_usable_graphic#1% + {\normalexpanded{\meta_start_usable_graphic_indeed{#1}}} + +\protected\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic + {\gdefcsname\??mpgraphic#1\endcsname{\meta_handle_use_graphic{#1}{#2}{#3}}} + +\def\meta_handle_reusable_graphic#1#2#3% + {\begingroup + \edef\currentmpvariableclass{#1}% + \edef\m_meta_instance_variables{#2}% + \ifempty\m_meta_instance_variables \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 + \gdefcsname\??mpgraphic#1\endcsname{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}% + \csname\??mpgraphic#1\endcsname\empty + \endgroup} + +\permanent\protected\def\startreusableMPgraphic % todo, modernize + {\dodoublegroupempty\meta_start_reusable_graphic} + +\aliased\let\stopreusableMPgraphic\relax + +\def\meta_start_reusable_graphic#1% + {\normalexpanded{\meta_start_reusable_graphic_indeed{#1}}} + +\protected\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic + {\gdefcsname\??mpgraphic#1\endcsname{\meta_handle_reusable_graphic{#1}{#2}{#3}}} + +\permanent\tolerant\protected\def\useMPgraphic#=#*#=% + {\meta_begin_graphic_group{#1}% + \ifcsname\??mpgraphic#1\endcsname + \edef\usedMPgraphicname{#1}% + \orelse\ifcsname\??mpgraphic\currentMPgraphicname\endcsname + \let\usedMPgraphicname\currentMPgraphicname + \else + \let\usedMPgraphicname\empty + \fi + \ifempty\usedMPgraphicname + % message + \else + \doifsomething{#2}{\setupMPvariables[\usedMPgraphicname][#2]}% + \csname\??mpgraphic\usedMPgraphicname\endcsname + \fi + \meta_end_graphic_group} + +\aliased\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed +\aliased\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed + +%D \macros +%D {startuniqueMPpagegraphic,uniqueMPpagegraphic} +%D +%D Experimental. + +\def\m_meta_page_prefix{\doifelseoddpage oe} + +\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} + +\permanent\tolerant\protected\def\startuniqueMPpagegraphic % todo the modern way + {\dodoublegroupempty\meta_start_unique_page_graphic} + +\aliased\let\stopuniqueMPpagegraphic\relax + +\def\meta_start_unique_page_graphic#1% + {\normalexpanded{\meta_start_unique_page_graphic_indeed{#1}}} + +\protected\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage + {\gdefcsname\??mpgraphic o:#1\endcsname{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state + \gdefcsname\??mpgraphic e:#1\endcsname{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined + +\permanent\tolerant\protected\def\uniqueMPpagegraphic#=#=% + {\meta_begin_graphic_group{#1}% + \let\overlaystamp\overlaypagestamp + \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 +%D Since we need to feed \METAPOST\ with expanded dimensions, we introduce a +%D dedicated expansion engine. We redefine \type {\extendMPoverlaystamp} to + +\permanent\protected\def\extendMPoverlaystamp#1% + {\processcommalist[#1]\meta_extend_overlay_stamp} + +\def\meta_extend_overlay_stamp#1% + {\meta_prepare_instance_variable{#1}% + \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}} + +\permanent\protected\def\getMPdata {\clf_getMPdata} + \aliased\let\rawMPdata \clf_getMPdata % we need frozen at the lua end + +\permanent\protected\def\getMPstored{\clf_getMPstored} + \aliased\let\rawMPstored \clf_getMPstored % we need frozen at the lua end + +%D We need this trick because we need to make sure that the tex scanner sees +%D newlines and does not quit. Also, we do need to flush the buffer under a normal +%D catcode regime in order to expand embedded tex macros. As usual with buffers, +%D \type {#1} can be a list. + +\permanent\tolerant\protected\def\processMPbuffer[#1]% + {\meta_begin_graphic_group{#1}% + \meta_process_graphic{\clf_feedback{\currentMPgraphicname}}% + \meta_end_graphic_group} + +\permanent\tolerant\protected\def\runMPbuffer[#1]% + {\startnointerference\meta_process_buffer[#1]\stopnointerference} + +%D \macros +%D {startMPenvironment, resetMPenvironment} +%D +%D In order to synchronize the main \TEX\ run and the runs local to \METAPOST, +%D environments can be passed. + +\permanent\protected\def\startMPenvironment + {\begingroup + \catcode\endoflineasciicode\ignorecatcode + \meta_start_environment} + +\tolerant\def\meta_start_environment[#1]#:#2\stopMPenvironment + {\endgroup + \edef\m_meta_option{#1} + \ifx\m_meta_option\s!reset + \resetMPenvironment % reset mp toks + \orelse\ifx\m_meta_option\v!global + #2% % use in main doc too + \orelse\ifx\m_meta_option\!!plustoken + #2% % use in main doc too + \fi + \clf_mptexset{\detokenize{#2}}} + +\aliased\let\stopMPenvironment\relax + +\permanent\protected\def\resetMPenvironment + {\clf_mptexreset} + +\protected\def\useMPenvironmentbuffer[#1]% + {\clf_mptexsetfrombuffer{#1}} + +%D This command takes \type {[reset]} as optional 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: + +\permanent\tolerant\protected\def\startMPcode#=#:#2\stopMPcode + {\begingroup + \edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \let\currentMPgraphicname\empty + \edef\currentMPformat{\MPinstanceparameter\s!format}% + \meta_enable_include + \meta_process_graphic{#2}% + \endgroup} + +\aliased\let\stopMPcode\relax + +%D This one is not optimized because it's only used for small snippets, if it +%D is used at all. + +\permanent\tolerant\protected\def\MPcode#=#:#*#=% + {\ifparameter#1\or + \meta_begin_graphic_group{#1}% + \meta_enable_include + \meta_process_graphic{#2}% + \meta_end_graphic_group + \else + \let\currentMPinstance\defaultMPinstance + \meta_enable_include + \meta_process_graphic{#1}% + \fi} + +% 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] + +\mutable\let\MPruninstance\defaultMPinstance + +\permanent\protected\def\useMPrun#1#2% name n + {\begingroup + \def\MPaskedfigure{#2}% + \normalexpanded{\useMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}% + \endgroup} + +\permanent\tolerant\protected\def\startMPrun#=#:#2\stopMPrun + {\normalexpanded{\startuseMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}#2\stopuseMPgraphic} + +\aliased\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: + +\permanent\protected\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} + +\permanent\protected\def\setMPtext#1#2{\dodoglobal\edefcsname\??mptext#1\endcsname{\detokenize{#2}}} +\permanent \def\MPtext #1{\begincsname\??mptext#1\endcsname\empty} +\permanent \def\MPstring #1{"\begincsname\??mptext#1\endcsname\empty"} +\permanent \def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex} + +%D In order to communicate conveniently with the \TEX\ engine, we introduce some +%D typesetting variables. + +% \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 + +%D A dirty trick, ** in colo-ini.lua (mpcolor). We cannot use a vardef, because +%D that fails with spot colors. + +\startMPinitializations + def OverlayLineColor=\ifempty\overlaylinecolor black \else\MPcolor{\overlaylinecolor} \fi enddef; + def OverlayColor =\ifempty\overlaycolor 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 \c_attr_colormodel +% \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 + \enforced\let\#\letterhash + \enforced\let\_\letterunderscore + \enforced\let\&\letterampersand + \enforced\let\{\letteropenbrace + \enforced\let\}\letterclosebrace +\to \everyMPgraphic + +%D \macros +%D {PDFMPformoffset} +%D +%D In \PDF, forms are clipped and therefore we have to take precautions to get this +%D right. Since this is related to objects, we use the same offset as used there. + +\def\PDFMPformoffset{\objectoffset} + +\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 don't use the normal figure +%D inclusion macros any longer. + +\appendtoks + \externalfigurepostprocessors\emptytoks % safeguard +\to \everyinsertMPfile + +%D We also take care of disabling fancy figure features, that can terribly interfere +%D when dealing with symbols, background graphics and running (postponed) graphics. +%D You won't believe me if I tell you what funny side effects can occur. One took me +%D over a day to uncover when processing the screen version of the \METAFUN\ manual. + +\permanent\def\doifelseMPgraphic#1% + {\ifcsname\??mpgraphic #1\endcsname\expandafter\firstoftwoarguments \orelse + \ifcsname\??mpgraphic o:#1\endcsname\expandafter\firstoftwoarguments \orelse + \ifcsname\??mpgraphic e:#1\endcsname\expandafter\firstoftwoarguments \else + \expandafter\secondoftwoarguments\fi} + +\aliased\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 something changed. Here is +%D 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 + +\permanent\protected\def\startstaticMPfigure#1#2\stopstaticMPfigure + {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic} + +\permanent\tolerant\protected\def\startstaticMPgraphic#=#:#=#:#3\stopstaticMPgraphic + {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic} + +\aliased\let\stopstaticMPfigure \relax +\aliased\let\stopstaticMPgraphic\relax + +\permanent\tolerant\protected\def\usestaticMPfigure[#1]#*[#2]% + {\ifarguments\or + \reuseMPgraphic{\??mpstaticgraphic#1}% + \else + \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% + \fi} + +%D Goody for preventing overflows: + +%frozen\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} +\permanent\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax} + +%D There is no way to distinguish the black color that you get when you issue a +%D \type {draw} without color specification from a color that has an explicit black +%D specification unless you set the variable \type {defaultcolormodel} to 1. +%D Hoewever, in that case you cannot distinguish that draw from one with a \type +%D {withoutcolor} specification. This means that we have to provide multiple +%D variants of inheritance. +%D +%D In any case we need to tell the converter what the inherited color is to start +%D with. Case~3 is kind of unpredictable as it closely relates to the order in which +%D paths are flushed. If you want to inherit automatically from the surrounding, you +%D can best stick to 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 + \c_attr_colormodel\space + \c_attr_color\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 + +\permanent\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar +\permanent\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number +\permanent\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset + +\prependtoks \clf_mppushvariables \to \everybeforepagebody +\appendtoks \clf_mppopvariables \to \everyafterpagebody + +\aliased\let\MPpushvariables\clf_mppushvariables +\aliased\let\MPpopvariables \clf_mppopvariables + +%D We also provide an outputless run: + +\permanent\tolerant\protected\def\startMPcalculation#=#:#2\stopMPcalculation + {\begingroup + \setbox\nextbox\hpack\bgroup + \edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi + \let\currentMPgraphicname\empty + \edef\currentMPformat{\MPinstanceparameter\s!format}% + \meta_enable_include + \meta_process_graphic{#2;draw origin}% + \egroup + \endgroup} + +\aliased\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 {global} we +%D get the outer color automatically. If you change this setting, you should do it +%D grouped in order not to make other graphics 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 + +\mutable\let\MPdataMPYfile\empty + +\appendtoks + \edef\p_mpy{\directMPgraphicsparameter{mpy}}% + \ifempty\p_mpy \else + \let\MPdataMPYfile\p_mpy + \clf_registermpyfile{\p_mpy}% + \fi +\to \everysetupMPgraphics + +%D Some more helpers (see \type {meta-grd.mkiv} for an example of usage): + +\permanent\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty} +\permanent\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty} +\permanent\def\MPspar#1#2{"#1#2"} + +%D Done. + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-lua.mkxl b/tex/context/base/mkxl/meta-lua.mkxl new file mode 100644 index 000000000..e06677d5e --- /dev/null +++ b/tex/context/base/mkxl/meta-lua.mkxl @@ -0,0 +1,95 @@ +%D \module +%D [ file=meta-lua, +%D version=2012.07.23, +%D title=\METAPOST\ Integrated Graphics, +%D subtitle=Templates, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 Don't use this code yet. I use it in some experimental rendering of graphics +%D based on output from database queries. It's not that pretty but will be +%D considered when the (similar) lmx code is redone. Also, dropping the print +%D variant makes it nicer. This experiment is part of playing with several template +%D mechanisms. (Also see trac-lmx.) +%D +%D Note for myself: see if the (bar)chart code use in q2p can use this kind of +%D magic. Basically we then need a channel to data. + +\writestatus{loading}{MetaPost Library Graphics / Templates} + +\registerctxluafile{meta-lua}{} + +\continueifinputfile{meta-lua.mkiv} + +\starttext + +% conforming btex ... etex + +\startbuffer[test-a] + blua for i=1,100,5 do elua + draw fullcircle scaled (blua p(i) elua * cm) withcolor green withpen pencircle scaled 4 ; + blua end elua + + blua for i=1,100,10 do elua + draw fullcircle scaled (blua p(i) elua * cm) withcolor red withpen pencircle scaled 2 ; + blua end elua +\stopbuffer + +\startMPpage[offset=10pt] + input "mpstemplate://buffer?name=test-a" ; +\stopMPpage + +% conforming lmx + +\startbuffer[test-b] + + draw fullcircle scaled ( * cm) withcolor green withpen pencircle scaled 4 ; + + + + draw fullcircle scaled ( * cm) withcolor red withpen pencircle scaled 2 ; + +\stopbuffer + +\startMPpage[offset=10pt] + input "mpstemplate://buffer?name=test-b" ; +\stopMPpage + +\startMPpage[offset=10pt] + picture p[] ; % we can't input nested + input "mpstemplate://buffer?name=test-a&method=metapost" ; + p[1] := currentpicture ; currentpicture := nullpicture ; + input "mpstemplate://buffer?name=test-b&method=xml" ; + p[2] := currentpicture ; currentpicture := nullpicture ; + draw p[1] ysized 3cm ; + draw p[2] ysized 4cm shifted (4cm,0) ; +\stopMPpage + +% a mixture (using a wrapped input) + +\startMPpage[offset=10pt] + draw image (loadfile("mpstemplate://buffer?name=test-a&method=metapost")) ysized 3cm shifted (4cm,0cm) ; + draw image (loadfile("mpstemplate://buffer?name=test-b&method=xml")) ysized 3cm shifted (0cm,4cm) ; + draw loadimage ("mpstemplate://buffer?name=test-a&method=metapost") ysized 4cm shifted (4cm,4cm) ; + draw loadimage ("mpstemplate://buffer?name=test-b&method=xml") ysized 4cm shifted (0cm,0cm) ; +\stopMPpage + +% conforming myself + +\startluacode + context.startMPpage { offset = "10pt" } + for i=1,100,5 do + context("draw fullcircle scaled (%s * cm) withcolor green withpen pencircle scaled 4 ;",i) + end + for i=1,100,10 do + context("draw fullcircle scaled (%s * cm) withcolor red withpen pencircle scaled 2 ;",i) + end + context.stopMPpage() +\stopluacode + +\stoptext diff --git a/tex/context/base/mkxl/meta-mac.mkxl b/tex/context/base/mkxl/meta-mac.mkxl new file mode 100644 index 000000000..76b7396ae --- /dev/null +++ b/tex/context/base/mkxl/meta-mac.mkxl @@ -0,0 +1,45 @@ +%D \module +%D [ file=meta-scn, +%D version=2019.07.19, +%D title=\METAPOST\ Graphics, +%D subtitle=LMTX 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. + +\unprotect + +\permanent\protected\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}} +\permanent\protected\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}} +\permanent\protected\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}} + +\permanent\tolerant\protected\def\useMPmacro[#1]#*[#2]#*[#3]% + {\ifarguments\or + \let\currentMPinstance\defaultMPinstance + \meta_enable_include + \meta_process_graphic{lmt_#1;}% + \or + \doifelseassignment{#2} + {\let\currentMPinstance\defaultMPinstance + \meta_enable_include + \clf_lmt_parameters_preset{#1}[#2]% + \meta_process_graphic{lmt_#1;}% + \clf_lmt_parameters_reset{#1}}% + {\meta_begin_graphic_group{#1}% + \meta_enable_include + \meta_process_graphic{lmt_#1;}% + \meta_end_graphic_group}% + \or + \meta_begin_graphic_group{#1}% + \meta_enable_include + \clf_lmt_parameters_preset{#2}[#3]% + \meta_process_graphic{lmt_#2;}% + \clf_lmt_parameters_reset{#2}% + \meta_end_graphic_group + \fi} + +\protect diff --git a/tex/context/base/mkxl/meta-nod.mkxl b/tex/context/base/mkxl/meta-nod.mkxl new file mode 100644 index 000000000..a89901edb --- /dev/null +++ b/tex/context/base/mkxl/meta-nod.mkxl @@ -0,0 +1,241 @@ +%D \module +%D [ file=meta-nod, +%D version=2016.11.23, +%D title=\METAPOST\ Graphics, +%D subtitle=Nodes, +%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. + +\registerctxluafile{meta-nod}{} + +\unprotect + +\defineMPinstance + [nodes] + [\s!format=metafun, + \s!extensions=\v!yes, + \s!initializations=\v!yes, + \c!method=\s!double] + +\defineframed + [node] + [\c!frame=\v!off] + +\defineframed + [smallnode] + [node] + [\c!foregroundstyle=\small] + +% \startMPdefinitions{nodes} +% loadmodule "node" ; +% \stopMPdefinitions + +\protect + +%D This module provides a simple \TEX\ layer on top of the nodes library that is +%D preloaded in \METAFUN. More information can be found in the manual and article. +%D +%D We strongly advice to use the \METAPOST\ interface and only provide this \TEX\ +%D variant as proof of concept. There are no plans to extend this module because we +%D see no advantage in using a \TEX\ interface over a \METAPOST\ one. +%D +%D \startbuffer +%D \startnodes +%D \placenode[0,0]{A} +%D \placenode[1,0]{B} +%D \connectnodes [0,1] [option=doublearrow] +%D \stopnodes +%D +%D \startnodes[dx=2cm,rotation=45] +%D \placenode[0,0]{A} +%D \placenode[1,0]{B} +%D \placenode[1,1]{C} +%D \placenode[0,1]{D} +%D \connectnodes [0,2] [option=doublearrow,label=a,offset=.05] +%D \connectnodes [1,3] [option=doublearrows] +%D \stopnodes +%D +%D \startnodes[dx=2cm,dy=2cm] +%D \nodeMPcode{ahlength := 12pt ; ahangle := 30 ; ahvariant := 1 ;} +%D \mpcode{ahlength := 12pt ; ahangle := 30 ; ahvariant := 1 ;} +%D \placenode[0,1]{\node{A}} +%D \placenode[1,1]{\node{B}} +%D \placenode[0,0]{\node{C}} +%D \placenode[1,0]{\node{D}} +%D \connectnodes [0,3] [option=arrow,label={ }] +%D \connectnodes [1,2] [option=arrow] +%D \stopnodes +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection \getbuffer \stoplinecorrection + +\unprotect + +\installcorenamespace{metanodes} +\installcorenamespace{metanodesoption} +\installcorenamespace{metanodesalternative} +\installcorenamespace{metanodesposition} + +% todo: maybe instances + +\installparameterhandler \??metanodes {metanodes} +\installsetuphandler \??metanodes {metanodes} + +\setupmetanodes + [\c!option =, + \c!alternative =, + \c!offset =0, + \c!position =, + \c!label =, + \c!dx =2\emwidth, + \c!dy =2\emwidth, + \c!rotation =90, + \c!rulethickness =.5pt, + \c!command =] + +\newtoks\t_every_meta_nodes +\newtoks\t_meta_nodes + +%D Hm, we started out simple but it now quickly becomes the usual mess of \TEX, +%D \METAPOST\ and \LUA. Hard to understand. + +\newcount\c_meta_nodes_n + +\aliased\let\stopnodes\relax + +\permanent\tolerant\protected\def\startnodes[#1]#:#2\stopnodes + {\hpack\bgroup + \setupcurrentmetanodes[#1]% + \edef\p_meta_option{\metanodesparameter\c!option}% + \edef\p_meta_alternative{\metanodesparameter\c!alternative}% + \the\t_every_meta_nodes + \c_meta_nodes_n\zerocount + \t_meta_nodes\emptytoks + #2\removeunwantedspaces + % for alan, will be commented: + \writestatus{metanodes}{\detokenize\expandafter{\the\t_meta_nodes}}% + \clf_grph_nodes_initialize + \startMPcode + mfun_node_init(% + \the\dimexpr\metanodesparameter\c!dx\relax,% + \the\dimexpr\metanodesparameter\c!dy\relax,% + \metanodesparameter\c!rotation% + ) ; + \the\t_meta_nodes ; + mfun_node_flush ; + \stopMPcode + \clf_grph_nodes_reset + \egroup} + +\permanent\tolerant\protected\def\grph_nodes_node[#1]#*[#2]% + {\grph_nodes_node_indeed[#1][#2]} + +\def\grph_nodes_node_indeed[#1,#2][#3]#4% + {\begingroup + \setupcurrentmetanodes[#3]% + \edef\p_label{#4}% + \edef\p_reference{\metanodesparameter\c!reference}% + \ifx\p_reference\empty\else + \clf_grph_nodes_register{\p_reference}\c_meta_nodes_n\relax + \fi + \normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{% + mfun_node_make(\number#1,\number#2% + \ifx\p_label\empty + ,""% + \else + ,"\metanodesparameter\c!command{\p_label}"% + \fi + );% + }}% + \advance\c_meta_nodes_n\plusone} + +\appendtoks + \enforced\let\placenode\grph_nodes_node +\to \t_every_meta_nodes + +\permanent\tolerant\protected\def\grph_nodes_fromto[#1]#*[#2]% + {\grph_nodes_fromto_indeed[#1][#2]}% get rid of {n,m} % todo: we can use #_ or so + +\letvalue{\??metanodesposition }\empty +\setvalue{\??metanodesposition top}{.top} +\setvalue{\??metanodesposition bottom}{.bot} +\setvalue{\??metanodesposition left}{.lft} +\setvalue{\??metanodesposition right}{.rt} +\setvalue{\??metanodesposition upperleft}{.ulft} +\setvalue{\??metanodesposition topleft}{.ulft} +\setvalue{\??metanodesposition lefttop}{.ulft} +\setvalue{\??metanodesposition upperright}{.urt} +\setvalue{\??metanodesposition topright}{.urt} +\setvalue{\??metanodesposition righttop}{.urt} +\setvalue{\??metanodesposition lowerleft}{.llft} +\setvalue{\??metanodesposition bottomleft}{.llft} +\setvalue{\??metanodesposition leftbottom}{.llft} +\setvalue{\??metanodesposition lowerright}{.lrt} +\setvalue{\??metanodesposition bottomright}{.lrt} +\setvalue{\??metanodesposition rightbottom}{.lrt} + +\def\grph_nodes_fromto_indeed[#1,#2][#3]% we can't group because etoksapp doesn't like that + {\begingroup + \setupcurrentmetanodes[#3]% + \edef\p_label {\metanodesparameter\c!label}% + \edef\p_rulethickness{\metanodesparameter\c!rulethickness}% + \edef\p_command {\metanodesparameter\c!command}% better get an error early + \normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{% + \ifcsname\??metanodesalternative\metanodesparameter\c!alternative\endcsname + \lastnamedcs + \else + \csname\??metanodesalternative\endcsname + \fi + \space + mfun_nodes_fromto\begincsname\??metanodesposition\metanodesparameter\c!position\endcsname(% + \metanodesparameter\c!offset,% + % \number#1,\number#2% + \clf_grph_nodes_resolve{#1},\clf_grph_nodes_resolve{#2}% + \ifempty\p_label + ,""% + \else + ,"\ifempty\p_command\p_label\else\p_command{\p_label}\fi"% + \fi + )% + \space + \ifcsname\??metanodesoption\metanodesparameter\c!option\endcsname + \lastnamedcs + \else + \csname\??metanodesoption\endcsname + \fi + \space + \ifx\p_rulethickness\empty \else + withpen pencircle scaled \the\dimexpr\p_rulethickness\relax + \fi + ;% + }}} + +\setvalue{\??metanodesalternative }{draw} +\setvalue{\??metanodesalternative arrow}{drawarrow} +\setvalue{\??metanodesalternative doublearrow}{drawdblarrow} +\setvalue{\??metanodesalternative doublearrows}{drawdoublearrows} + +\setvalue{\??metanodesoption }{} +\setvalue{\??metanodesoption dashed}{dashed evenly} +\setvalue{\??metanodesoption dotted}{dashed withdots scaled .5} + +\appendtoks + \enforced\let\connectnodes\grph_nodes_fromto +\to \t_every_meta_nodes + +\permanent\protected\def\grph_nodes_code#1% + {\etoksapp\t_meta_nodes{#1}} + +\appendtoks + \enforced\let\nodeMPcode\grph_nodes_code + \enforced\let\mpcode \grph_nodes_code +\to \t_every_meta_nodes + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-pag.mkxl b/tex/context/base/mkxl/meta-pag.mkxl new file mode 100644 index 000000000..86de11eeb --- /dev/null +++ b/tex/context/base/mkxl/meta-pag.mkxl @@ -0,0 +1,26 @@ +%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 {core-mps} file, later changed +%D into \type {meta-ini}, but keeping them separate is cleaner. In the meantime not +%D that much is left here. + +\writestatus{loading}{MetaPost Graphics / Page Data Management} + +\unprotect + +\prependtoks + \calculatereducedvsizes % bah, this is really needed +\to \everyMPgraphic + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-pdf.mkxl b/tex/context/base/mkxl/meta-pdf.mkxl new file mode 100644 index 000000000..d53ff7780 --- /dev/null +++ b/tex/context/base/mkxl/meta-pdf.mkxl @@ -0,0 +1,95 @@ +%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}{} + +\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 traditional +%D method is in the MkII files and the older \MKIV\ method is kept in meta-pdh +%D files. The main conversion command is still the same but the scale parameters are +%D 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 and no +%D specials. This also means that you should use a modern \METAPOST\ or reprocess +%D graphics. The color control flags are also gone as we now integrate into the +%D regular colorspace handling (i.e.\ no longer independent configurations.) + +\permanent\def\PDFMPformoffset{\ifdefined\objectoffset\objectoffset\else\zeropoint\fi} % obsolete, will go + +\mutable\let\MPfilename\empty + +\permanent\protected\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/tex/context/base/mkxl/meta-pdh.mkxl b/tex/context/base/mkxl/meta-pdh.mkxl new file mode 100644 index 000000000..fa731868d --- /dev/null +++ b/tex/context/base/mkxl/meta-pdh.mkxl @@ -0,0 +1,717 @@ +%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}{} + +%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% + {\glet\MPwidth \!!zeropoint + \glet\MPheight \!!zeropoint + \glet\MPllx \!!zerocount + \glet\MPlly \!!zerocount + \glet\MPurx \!!zerocount + \glet\MPury \!!zerocount + \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi + \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi + \xdef\MPfilename {#1}} + +%D The main macro: + +\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 + \glet\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 +%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 : 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 + \glet\currentPDFresources\empty % kind of redundant +\to \MPstartresources + +% \appendtoks +% \collectPDFresources +% \glet\currentPDFresources\collectedPDFresources +% \to \MPstopresources + +\appendtoksonce + \the\everyPDFxform +\to \MPstopresources + +%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 +% {<>}% +% \immediate\pdfobj +% {<>}% +% \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}} + +We save the special variables on a stack. It's not that fast, but it make +implementing the special more convenient. + +%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 + +%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/tex/context/base/mkxl/meta-tex.mkxl b/tex/context/base/mkxl/meta-tex.mkxl new file mode 100644 index 000000000..9afbbe066 --- /dev/null +++ b/tex/context/base/mkxl/meta-tex.mkxl @@ -0,0 +1,239 @@ +%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}{} + +\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} + +\permanent\protected\def\startTeXtexts#1\stopTeXtexts + {#1} + +\aliased\let\stopTeXtexts\relax + +\permanent\tolerant\protected\def\TeXtext[#1]#:#2#3% contrary to mkii we don't process yet but we do expand + {\setxvalue{\??graphictextext#2}{\meta_textext_indeed{#1}{#3}}} + +\protected\def\meta_textext_indeed#1#2% + {\begingroup + \setbox\nextbox\hbox{#2}% + \ifcsname\??graphictexdepth#1\endcsname + \lastnamedcs + \else + \syst_boxes_lower_nextbox_dp + \fi + \box\nextbox + \endgroup} + +\permanent\def\getTeXtext#1% + {\begincsname\??graphictextext#1\endcsname} + +\letvalue{\??graphictexdepth d}\syst_boxes_lower_nextbox_dp +\letvalue{\??graphictexdepth \s!depth}\syst_boxes_lower_nextbox_dp +\letvalue{\??graphictexdepth n}\donothing +\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 + +\permanent\protected\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}} + +\permanent\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}}")} + +\permanent\protected\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: +% +% \protected\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}} + +\permanent\protected\def\MPexponent #1#2{\mathematics{#1\times10^{#2}}} +\permanent\protected\def\MPformatted #1#2{\clf_metapostformatted{#1}{#2}} +\permanent\protected\def\MPgraphformat#1#2{\clf_metapostgraphformat{#1}{#2}} + +%D Some new fun (but exprimental for a while): + +\permanent\protected\def\MPLIBoutlinetext#1#2#3% index kind text + {\begingroup + \setbox\scratchbox\hbox{#3}% + \clf_MPLIBconvertoutlinetext\numexpr#1\relax{#2}\scratchbox + \endgroup} + +%D For now here. We don't do the whole thing, because then one can as +%D well just export to pdf. We assume consistent integration. + +\definefontsynonym[serif-normal-normal] [\s!Serif] +\definefontsynonym[serif-normal-italic] [\s!SerifItalic] +\definefontsynonym[serif-normal-oblique][\s!SerifSlanted] +\definefontsynonym[serif-bold-normal] [\s!SerifBold] +\definefontsynonym[serif-bold-italic] [\s!SerifBoldItalic] +\definefontsynonym[serif-bold-oblique] [\s!SerifBoldSlanted] + +\definefontsynonym[sans-normal-normal] [\s!Sans] +\definefontsynonym[sans-normal-italic] [\s!SansItalic] +\definefontsynonym[sans-normal-oblique] [\s!SansSlanted] +\definefontsynonym[sans-bold-normal] [\s!SansBold] +\definefontsynonym[sans-bold-italic] [\s!SansBoldItalic] +\definefontsynonym[sans-bold-oblique] [\s!SansBoldSlanted] + +\definefontsynonym[mono-normal-normal] [\s!Mono] +\definefontsynonym[mono-normal-italic] [\s!MonoItalic] +\definefontsynonym[mono-normal-oblique] [\s!MonoSlanted] +\definefontsynonym[mono-bold-normal] [\s!MonoBold] +\definefontsynonym[mono-bold-italic] [\s!MonoBoldItalic] +\definefontsynonym[mono-bold-oblique] [\s!MonoBoldSlanted] + +\installcorenamespace {svgfamily} + +\setvalue{\??svgfamily }{serif} +\setvalue{\??svgfamily serif}{serif} +\setvalue{\??svgfamily sans}{sans} +\setvalue{\??svgfamily mono}{mono} + +%D This can't change because otherwise \type {\scale[width=4cm]{graphic}} fails. + +\permanent\protected\def\svgscaled#1% + {\fastsxsy{#1}{#1}\svgnormal} + +\permanent\protected\def\svgnormal#1#2#3#4% family weight style text + {\bgroup + \edef\p_family{#1}% + \ifx\p_family\empty\else + \edef\p_font{\ifcsname\??svgfamily#1\endcsname\lastnamedcs\else#1\fi-#2-#3}% + \predefinedfont[\s!spec:\p_font*\s!default\space @ 10bp]% + \fi + #4% + \egroup} + +\permanent\protected\def\svgcolored#1#2#3#4% r g b text + {\colored[r=#1,g=#2,b=#3]{#4}} + +\permanent\protected\def\svgplaced#1#2#3#4% dx dy width text + {\doifelsenothing{#3}% + {\hpack}% + {\hpack to #3}% + {\raise#2\onebasepoint\hbox{\kern#1\onebasepoint\relax#4}}} + +\newdimen\grph_svg_scratchwidth % maybe \startsvgpos etc + +\permanent\protected\def\svgposchar#1#2#3% dx dy char + {\setbox\scratchbox\hpack\bgroup + \raise#2\onebasepoint\hbox\bgroup + \kern\dimexpr#1\onebasepoint-\grph_svg_scratchwidth\relax + \char#3\relax + \egroup + \egroup + \advance\grph_svg_scratchwidth\wd\scratchbox + \box\scratchbox} + +\permanent\protected\def\svgchar#1% char + {\char#1\relax} + +\definelayer[svgmps][\c!method=\v!fit] + +\permanent\protected\def\svgstartlayer + {\resetlayer[svgmps]% + \setlayer[svgmps]\bgroup} + +\permanent\protected\def\svgstoplayer + {\egroup + \flushlayer[svgmps]} + +\permanent\protected\def\svgsetlayer#1#2% + {\setlayer[svgmps][\c!x=#1\onebasepoint,\c!y=#2\onebasepoint]} % {#3} + +\permanent\protected\def\svghashed#1% + {\clf_svghashed#1\relax} + +\protect \endinput diff --git a/tex/context/base/mkxl/meta-xml.mkxl b/tex/context/base/mkxl/meta-xml.mkxl new file mode 100644 index 000000000..bd93bda8c --- /dev/null +++ b/tex/context/base/mkxl/meta-xml.mkxl @@ -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/tex/context/base/mkxl/mlib-cnt.lmt b/tex/context/base/mkxl/mlib-cnt.lmt new file mode 100644 index 000000000..667384ed7 --- /dev/null +++ b/tex/context/base/mkxl/mlib-cnt.lmt @@ -0,0 +1,2022 @@ +if not modules then modules = { } end modules ['mlib-cnt'] = { + version = 1.001, + optimize = true, + 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", +} + +-- The only useful reference that I could find about this topic is in wikipedia: +-- +-- https://en.wikipedia.org/wiki/Marching_squares +-- +-- I derived the edge code from: +-- +-- https://physiology.arizona.edu/people/secomb/contours +-- +-- and also here: +-- +-- https://github.com/secomb/GreensV4 +-- +-- which has the banner: +-- +-- TWS, November 1989. Converted to C September 2007. Revised February 2009. +-- +-- and has a liberal licence. I optimized the code so that it runs a bit faster in Lua and +-- there's probably more room for optimization (I tried several variants). For instance I +-- don't use that many tables because access is costly. We don't have a compiler that does +-- some optimizing (even then the c code can probably be made more efficient). +-- +-- We often have the same node so it's cheaper to reuse the wsp tables and reconstruct +-- the point in the path then to alias the original point. We can be more clever: +-- straighten, but it's more work so maybe I will do that later; for now I only added +-- a test for equality. There are some experiments in this file too and not all might +-- work. It's a playground for me. +-- +-- The code is meant for metafun so it is not general purpose. The bitmap variant is +-- relatively fast and bitmaps compress well. When all is settled I might make a couple +-- of helpers in C for this purpose but not now. +-- +-- I removed optimization code (more aggressive flattening and such because it didn't really +-- pay off now that we use combined paths with just line segments. I also moved some other +-- code to a experimental copy. So we now only have the bare helpers needed here. + +-- Todo: look into zero case (lavel 1) for shapes ... omiting the background calculation +-- speeds up quite a bit. + +local next, type, tostring = next, type, tostring +local round, abs, min, max, floor = math.round, math.abs, math.min, math.max, math.floor +local concat, move = table.concat, table.move + +local bor = bit32.bor -- it's really time to ditch support for luajit + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local elapsedtime = statistics.elapsedtime + +local formatters = string.formatters +local setmetatableindex = table.setmetatableindex +local sortedkeys = table.sortedkeys +local sequenced = table.sequenced + +local metapost = metapost or { } +local mp = mp or { } + +local getparameterset = metapost.getparameterset + +local mpflush = mp.flush +local mpcolor = mp.color +local mpstring = mp.string +local mpdraw = mp.draw +local mpfill = mp.fill +local mpflatten = mp.flatten + +local report = logs.reporter("mfun contour") + +local version = 0.007 + +-- we iterate using integers so that we get a better behaviour at zero + +local f_function_n = formatters [ [[ + local math = math + local round = math.round + %s + return function(data,nx,ny,nxmin,nxmax,xstep,nymin,nymax,ystep) + local sx = nxmin + for mx=1,nx do + local dx = data[mx] + local x = sx * xstep + local sy = nymin + for my=1,ny do + local y = sy * ystep + dx[my] = %s + sy = sy + 1 + end + sx = sx + 1 + end + return 0 + end +]] ] + +local f_function_y = formatters [ [[ + local math = math + local round = math.round + local nan = NaN + local inf = math.huge + %s + return function(data,nx,ny,nxmin,nxmax,xstep,nymin,nymax,ystep,dnan,dinf,report) + local sx = nxmin + local er = 0 + for mx=nxmin,nxmax do + local dx = data[mx] + local x = sx * xstep + local sy = nymin + for my=nymin,nymax do + local y = sy * ystep + local n = %s + if n == nan then + er = er + 1 + if er < 10 then + report("nan at (%s,%s)",x,y) + end + n = dnan + elseif n == inf then + er = er + 1 + if er < 10 then + report("inf at (%s,%s)",x,y) + end + n = dinf + end + dx[my] = n + sy = sy + 1 + end + sx = sx + 1 + end + return er + end +]] ] + +local f_color = formatters [ [[ + local math = math + local min = math.min + local max = math.max + local n = %s + local minz = %s + local maxz = %s + + local color_value = 0 + local color_step = mp.lmt_color_functions.step + local color_shade = mp.lmt_color_functions.shade + + local function step(...) + return color_step(color_value,n,...) + end + local function shade(...) + return color_shade(color_value,n,...) + end + local function lin(l) + return l/n + end + %s + return function(l) + color_value = l + return %s + end +]] ] + +local inbetween = attributes and attributes.colors.helpers.inbetween + +mp.lmt_color_functions = { + step = function(l,n,r,g,b,s) + if not s then + s = 1 + end + local f = l / n + local r = s * 1.5 - 4 * abs(f-r) + local g = s * 1.5 - 4 * abs(f-g) + local b = s * 1.5 - 4 * abs(f-b) + return min(max(r,0),1), min(max(g,0),1), min(max(b,0),1) + end, + shade = function(l,n,one,two) + local f = l / n + local r = inbetween(one,two,1,f) + local g = inbetween(one,two,2,f) + local b = inbetween(one,two,3,f) + return min(max(r,0),1), min(max(g,0),1), min(max(b,0),1) + end, +} + +local f_box = formatters [ [[draw rawtexbox("contour",%s) xysized (%s,%s) ;]] ] + +local n_box = 0 + +-- todo: remove old one, so we need to store old hashes + +local nofcontours = 0 + +-- We don't want cosmetics like axis and labels to trigger a calculation, +-- especially a slow one. + +local hashfields = { + "xmin", "xmax", "xstep", "ymin", "ymax", "ystep", + "levels", "colors", "level", "preamble", "function", "functions", "color", "values", + "background", "foreground", "linewidth", "backgroundcolor", "linecolor", +} + +local function prepare(p) + local h = { } + for i=1,#hashfields do + local f = hashfields[i] + h[f] = p[f] + end + local hash = md5.HEX(sequenced(h)) + local name = formatters["%s-m-c-%03i.lua"](tex.jobname,nofcontours) + return name, hash +end + +local function getcache(p) + local cache = p.cache + if cache then + local name, hash = prepare(p) + local data = table.load(name) + if data and data.hash == hash and data.version == version then + p.result = data + return true + else + return false, hash, name + end + end + return false, nil, nil +end + +local function setcache(p) + local result = p.result + local name = result.name + if name then + if result.bitmap then + result.bitmap = nil + else + result.data = nil + end + result.color = nil + result.action = nil + result.cached = nil + io.savedata(name, table.fastserialize(result)) + else + os.remove((prepare(p))) + end +end + +function mp.lmt_contours_start() + + starttiming("lmt_contours") + + nofcontours = nofcontours + 1 + + local p = getparameterset() + + local xmin = p.xmin + local xmax = p.xmax + local ymin = p.ymin + local ymax = p.ymax + local xstep = p.xstep + local ystep = p.ystep + local levels = p.levels + local colors = p.colors + local nx = 0 + local ny = 0 + local means = setmetatableindex("number") + local values = setmetatableindex("number") + local data = setmetatableindex("table") + local minmean = false + local maxmean = false + + local cached, hash, name = getcache(p) + + local function setcolors(preamble,levels,minz,maxz,color,nofvalues) + if colors then + local function f(k) + return #colors[1] == 1 and 0 or { 0, 0, 0 } + end + setmetatableindex(colors, function(t,k) + local v = f(k) + t[k] = v + return v + end) + local c = { } + local n = 1 + for i=1,nofvalues do + c[i] = colors[n] + n = n + 1 + end + return c, f + else + local tcolor = f_color(levels,minz,maxz,preamble,color) + local colors = { } + local fcolor = load(tcolor) + if type(fcolor) ~= "function" then + report("error in color function, case %i: %s",1,color) + fcolor = false + else + fcolor = fcolor() + if type(fcolor) ~= "function" then + report("error in color function, case %i: %s",2,color) + fcolor = false + end + end + if not fcolor then + local color_step = mp.lmt_color_functions.step + fcolor = function(l) + return color_step(l,levels,0.25,0.50,0.75) + end + end + for i=1,nofvalues do + colors[i] = { fcolor(i) } + end + if attributes.colors.model == "cmyk" then + for i=1,#colors do + local c = colors[i] + colors[i] = { 1 - c[1], 1 - c[2], 1 - c[3], 0 } + end + end + return colors, fcolor + end + end + + if cached then + local result = p.result + local colors, color = setcolors( + p.preamble, + p.levels, + result.minz, + result.maxz, + p.color, + result.nofvalues + ) + result.color = color + result.colors = colors + result.cached = true + return + end + + local functioncode = p["function"] + local functionrange = p.range + local functionlist = functionrange and p.functions + local preamble = p.preamble + + if xstep == 0 then xstep = (xmax - xmin)/100 end + if ystep == 0 then ystep = (ymax - ymin)/100 end + + local nxmin = round(xmin/xstep) + local nxmax = round(xmax/xstep) + local nymin = round(ymin/ystep) + local nymax = round(ymax/ystep) + local nx = nxmax - nxmin + 1 + local ny = nymax - nymin + 1 + + local function executed(data,code) + local fcode = p.check and f_function_y or f_function_n + fcode = fcode(preamble,code) + fcode = load(fcode) + if type(fcode) == "function" then + fcode = fcode() + end + if type(fcode) == "function" then + local er = fcode( + data, nx, ny, + nxmin, nxmax, xstep, + nymin, nymax, ystep, + p.defaultnan, p.defaultinf, report + ) + if er > 0 then + report("%i errors in: %s",er,code) + end + return true + else + return false -- fatal error + end + end + + -- for i=1,nx do + -- data[i] = lua.newtable(ny,0) + -- end + + if functionlist then + + local datalist = { } + local minr = functionrange[1] + local maxr = functionrange[2] or minr + local size = #functionlist + + for l=1,size do + + local func = setmetatableindex("table") + if not executed(func,functionlist[l]) then + report("error in executing function %i from functionlist",l) + return + end + + local bit = l -- + 1 + + if l == 1 then + for i=1,nx do + local di = data[i] + local fi = func[i] + for j=1,ny do + local f = fi[j] + if f >= minr and f <= maxr then + di[j] = bit + else + di[j] = 0 + end + end + end + else + for i=1,nx do + local di = data[i] + local fi = func[i] + for j=1,ny do + local f = fi[j] + if f >= minr and f <= maxr then + di[j] = bor(di[j],bit) + end + end + end + end + + end + + -- we can simplify the value mess below + + elseif functioncode then + + if not executed(data,functioncode) then + report("error in executing function") + return -- fatal error + end + + else + + report("no valid function(s)") + return -- fatal error + + end + + minz = data[1][1] + maxz = minz + + for i=1,nx do + local d = data[i] + for j=1,ny do + local v = d[j] + if v < minz then + minz = v + elseif v > maxz then + maxz = v + end + end + end + + if functionlist then + + for i=minz,maxz do + values[i] = i + end + + levels = maxz + + minmean = minz + maxmean = maxz + + else + + local snap = (maxz - minz + 1) / levels + + for i=1,nx do + local d = data[i] + for j=1,ny do + local dj = d[j] + local v = round((dj - minz) / snap) + values[v] = values[v] + 1 + means [v] = means [v] + dj + d[j] = v + end + end + + local list = sortedkeys(values) + local count = values + local remap = { } + + values = { } + + for i=1,#list do + local v = list[i] + local m = means[v] / count[v] + remap [v] = i + values[i] = m + if not minmean then + minmean = m + maxmean = m + elseif m < minmean then + minmean = m + elseif m > maxmean then + maxmean = m + end + end + + for i=1,nx do + local d = data[i] + for j=1,ny do + d[j] = remap[d[j]] + end + end + + end + + -- due to rounding we have values + 1 so we can have a floor, ceil, round + -- option as well as levels -1 + + local nofvalues = #values + + local colors = setcolors( + p.preamble,levels,minz,maxz,p.color,nofvalues + ) + + p.result = { + version = version, + values = values, + nofvalues = nofvalues, + minz = minz, + maxz = maxz, + minmean = minmean, + maxmean = maxmean, + data = data, + color = color, + nx = nx, + ny = ny, + colors = colors, + name = name, + hash = hash, + islist = functionlist and true or false, + } + + report("index %i, nx %i, ny %i, levels %i", nofcontours, nx, ny, nofvalues) +end + +function mp.lmt_contours_stop() + local p = getparameterset() + local e = stoptiming("lmt_contours") + setcache(p) + p.result = nil + local f = p["function"] + local l = p.functions + report("index %i, %0.3f seconds for: %s", + nofcontours, e, "[ " .. concat(l or { f } ," ] [ ") .. " ]" + ) +end + +function mp.lmt_contours_bitmap_set() + local p = getparameterset() + local result = p.result + + local values = result.values + local nofvalues = result.nofvalues + local rawdata = result.data + local nx = result.nx + local ny = result.ny + local colors = result.colors + local depth = #colors[1] -- == 3 and "rgb" or "gray" + + -- i need to figure out this offset of + 1 + + local bitmap = graphics.bitmaps.new( + nx, ny, + (depth == 3 and "rgb") or (depth == 4 and "cmyk") or "gray", + 1, false, true + ) + + local palette = bitmap.index or { } -- has to start at 0 + local data = bitmap.data + local p = 0 + + if depth == 3 or depth == 4 then + for i=1,nofvalues do + local c = colors[i] + local r = round((c[1] or 0) * 255) + local g = round((c[2] or 0) * 255) + local b = round((c[3] or 0) * 255) + local k = depth == 4 and round((c[4] or 0) * 255) or nil + palette[p] = { + (r > 255 and 255) or (r < 0 and 0) or r, + (g > 255 and 255) or (g < 0 and 0) or g, + (b > 255 and 255) or (b < 0 and 0) or b, + k + } + p = p + 1 + end + else + for i=1,nofvalues do + local s = colors[i][1] + local s = round((s or 0) * 255) + palette[p] = ( + (s > 255 and 255) or (s < 0 and 0) or s + ) + p = p + 1 + end + end + + -- As (1,1) is the left top corner so we need to flip of we start in + -- the left bottom (we cannot loop reverse because we want a properly + -- indexed table. + + local k = 0 + for y=ny,1,-1 do + k = k + 1 + local d = data[k] + for x=1,nx do + d[x] = rawdata[x][y] - 1 + end + end + + result.bitmap = bitmap +end + +function mp.lmt_contours_bitmap_get() + local p = getparameterset() + local result = p.result + local bitmap = result.bitmap + local box = nodes.hpack(graphics.bitmaps.flush(bitmap)) + n_box = n_box + 1 + nodes.boxes.savenode("contour",tostring(n_box),box) + return f_box(n_box,bitmap.xsize,bitmap.ysize) +end + +function mp.lmt_contours_cleanup() + nodes.boxes.reset("contour") + n_box = 0 +end + +function mp.lmt_contours_edge_set() + local p = getparameterset() + local result = p.result + + if result.cached then return end + + local values = result.values + local nofvalues = result.nofvalues + local data = result.data + local nx = result.nx + local ny = result.ny + + local xmin = p.xmin + local xmax = p.xmax + local ymin = p.ymin + local ymax = p.ymax + local xstep = p.xstep + local ystep = p.ystep + + local wsp = { } + local edges = { } + + for value=1,nofvalues do + + local iwsp = 0 + local di = data[1] + local dc + local edge = { } + local e = 0 + -- the next loop is fast + for i=1,nx do + local di1 = data[i+1] + local dij = di[1] + local d = dij - value + local dij1 + for j=1,ny do + if j < ny then + dij1 = di[j+1] + dc = dij1 - value + if (d >= 0 and dc < 0) or (d < 0 and dc >= 0) then + iwsp = iwsp + 1 + local y = (d * (j+1) - dc * j) / (d - dc) + if i == 1 then + wsp[iwsp] = { i, y, 0, (i + (j-1)*nx) } + elseif i == nx then + wsp[iwsp] = { i, y, (i - 1 + (j-1)*nx), 0 } + else + local jx = (i + (j-1)*nx) + wsp[iwsp] = { i, y, jx - 1, jx } + end + end + end + if i < nx then + local dc = di1[j] - value + if (d >= 0 and dc < 0) or (d < 0 and dc >= 0) then + iwsp = iwsp + 1 + local x = (d * (i+1) - dc * i) / (d - dc) + if j == 1 then + wsp[iwsp] = { x, j, 0, (i + (j-1)*nx) } + elseif j == ny then + wsp[iwsp] = { x, j, (i + (j-2)*nx), 0 } + else + local jx = i + (j-1)*nx + wsp[iwsp] = { x, j, jx - nx, jx } + end + end + end + dij = dij1 + d = dc + end + di = di1 + end + -- the next loop takes time + for i=1,iwsp do + local wspi = wsp[i] + for isq=3,4 do + local nsq = wspi[isq] + if nsq ~= 0 then + local px = wspi[1] + local py = wspi[2] + local p = { px, py } + local pn = 2 + wspi[isq] = 0 + while true do + for ii=1,iwsp do + local w = wsp[ii] + local n1 = w[3] + local n2 = w[4] + if n1 == nsq then + local x = w[1] + local y = w[2] + if x ~= px or y ~= py then + pn = pn + 1 + p[pn] = x + pn = pn + 1 + p[pn] = y + px = x + py = y + end + nsq = n2 + w[3] = 0 + w[4] = 0 + if nsq == 0 then + if pn == 1 then + pn = pn + 1 + p[pn] = w + end + goto flush + end + elseif n2 == nsq then + local x = w[1] + local y = w[2] + if x ~= px or y ~= py then + pn = pn + 1 + p[pn] = x + pn = pn + 1 + p[pn] = y + px = x + py = y + end + nsq = n1 + w[3] = 0 + w[4] = 0 + if nsq == 0 then + goto flush + end + end + end + end + ::flush:: + e = e + 1 + edge[e] = p + if mpflatten then + mpflatten(p) + end + end + end + end + + + edges[value] = edge + + end + + result.edges = edges + +end + +function mp.lmt_contours_shade_set(edgetoo) + local p = getparameterset() + local result = p.result + + if result.cached then return end + + local values = result.values + local nofvalues = result.nofvalues + local data = result.data + local nx = result.nx + local ny = result.ny + local color = result.color + + local edges = setmetatableindex("table") + local shades = setmetatableindex("table") + + local sqtype = setmetatableindex("table") + + local xspoly = { 0, 0, 0, 0, 0, 0 } + local yspoly = { 0, 0, 0, 0, 0, 0 } + local xrpoly = { } + local yrpoly = { } + + local xrpoly = { } -- lua.newtable(2000,0) + local yrpoly = { } -- lua.newtable(2000,0) + + -- for i=1,2000 do + -- xrpoly[i] = 0 + -- yrpoly[i] = 0 + -- end + + -- Unlike a c compiler lua will not optimize loops to run in parallel so we expand + -- some of the loops and make sure we don't calculate when not needed. Not that nice + -- but not that bad either. Maybe I should just write this from scratch. + +-- local i = 0 +-- local j = 0 + + -- Analyze each rectangle separately. Overwrite lower colors + + -- Unrolling the loops and copying code and using constants is faster and doesn't + -- produce much more code in the end, also because we then can leave out the not + -- seen branches. One can argue about the foundit2* blobs but by stepwise optimizing + -- this is the result. + + shades[1] = { { 0, 0, nx - 1, 0, nx - 1, ny - 1, 0, ny - 1 } } + edges [1] = { { } } + + -- this is way too slow ... i must have messed up some loop .. what is this with value 1 + + for value=1,nofvalues do +-- for value=2,nofvalues do + + local edge = { } + local nofe = 0 + local shade = { } + local nofs = 0 + + for i=1,nx-1 do + local s = sqtype[i] + for j=1,ny-1 do + s[j] = 0 + end + end + + local nrp = 0 + + local function addedge(a,b,c,d) + nofe = nofe + 1 edge[nofe] = a + nofe = nofe + 1 edge[nofe] = b + nofe = nofe + 1 edge[nofe] = c + nofe = nofe + 1 edge[nofe] = d + end + while true do + -- search for a square of type 0 with >= 1 corner above contour level + local i + local j + local d0 = data[1] + local d1 = data[2] + for ii=1,nx do + local s = sqtype[ii] + for jj=1,ny do + if s[jj] == 0 then + if d0[jj] > value then i = ii j = jj goto foundit end + if d1[jj] > value then i = ii j = jj goto foundit end + local j1 = jj + 1 + if d1[j1] > value then i = ii j = jj goto foundit end + if d0[j1] > value then i = ii j = jj goto foundit end + end + end + d0 = d1 + d1 = data[ii+1] + end + break + ::foundit:: + -- initialize r-polygon (nrp seems to be 1 or 2) + nrp = nrp + 1 + + local first = true + local nrpoly = 0 + local nspoly = 0 + local nrpm = -nrp + -- this is the main loop + while true do + -- search for a square of type -nrp + if first then + first = false + if sqtype[i][j] == 0 then -- true anyway + goto foundit1 + end + end + for ii=1,nx do + local s = sqtype[ii] + for jj=1,ny do + if s[jj] == nrpm then + i = ii + j = jj + goto foundit1 + end + end + end + break + ::foundit1:: + while true do + + -- search current then neighboring squares for square type 0, with a corner in common with current square above contour level + + -- top/bottom ... a bit cheating here + + local i_l, i_c, i_r -- i left current right + local j_b, j_c, j_t -- j bottom current top + + local i_n = i + 1 -- i next (right) + local j_n = j + 1 -- j next (top) + + local i_p = i - 1 -- i previous (bottom) + local j_p = j - 1 -- j previous (right) + + local d_c = data[i] + local d_r = data[i_n] + + local sq + + i_c = i ; j_c = j ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then + if d_c[j_c] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit21 end + if d_c[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit22 end + if d_r[j_c] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit23 end + if d_r[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j_p ; j_t = j_n ; goto foundit24 end + end end + + i_c = i_n ; j_c = j ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then + if d_r[j_c] > value then i_l = i ; i_r = i_n + 1 ; j_b = j_p ; j_t = j_n ; d_c = d_r ; d_r = data[i_r] ; goto foundit21 end + if d_r[j_n] > value then i_l = i ; i_r = i_n + 1 ; j_b = j_p ; j_t = j_n ; d_c = d_r ; d_r = data[i_r] ; goto foundit22 end + end end + + i_c = i ; j_c = j_n ; if i_c < nx and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then + if d_c[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j ; j_t = j_n + 1 ; goto foundit21 end + if d_r[j_n] > value then i_l = i_p ; i_r = i_n ; j_b = j ; j_t = j_n + 1 ; goto foundit23 end + end end + + i_c = i_p ; j_c = j ; if i_c > 0 and j_c < ny then sq = sqtype[i_c] if sq[j_c] == 0 then + if d_c[j_c] > value then i_l = i_p - 1 ; i_r = i ; j_b = j_p ; j_t = j_n ; d_r = d_c ; d_c = data[i_p] ; goto foundit23 end + if d_c[j_n] > value then i_l = i_p - 1 ; i_r = i ; j_b = j_p ; j_t = j_n ; d_r = d_c ; d_c = data[i_p] ; goto foundit24 end + end end + + i_c = i ; j_c = j_p ; if i < nx and j_c > 0 then sq = sqtype[i_c] if sq[j_c] == 0 then + if d_c[j] > value then i_l = i_p ; i_r = i_n ; j_b = j_p - 1 ; j_t = j ; goto foundit22 end + if d_r[j] > value then i_l = i_p ; i_r = i_n ; j_b = j_p - 1 ; j_t = j ; goto foundit24 end + end end + + -- not found + + sqtype[i][j] = nrp + + break + + -- define s-polygon for found square (i_c,j_c) - may have up to 6 sides + + ::foundit21:: -- 1 2 3 4 + + sq[j_c] = nrpm + + xspoly[1] = i_l ; yspoly[1] = j_b + xspoly[2] = i_c ; yspoly[2] = j_b + if d_r[j_c] > value then -- dd2 + xspoly[3] = i_c ; yspoly[3] = j_c + if d_r[j_t] > value then -- dd3 + xspoly[4] = i_l ; yspoly[4] = j_c + if d_c[j_t] > value then -- dd4 + nspoly = 4 + else + xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 + end + elseif d_c[j_t] > value then -- dd4 + xspoly[4] = i_c ; yspoly[4] = j_c ; + xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 + else + xspoly[4] = i_l ; yspoly[4] = j_c ; nspoly = 4 + if edgetoo then addedge(i_c, j_c, i_l, j_c) end + end + elseif d_r[j_t] > value then -- dd3 + xspoly[3] = i_c ; yspoly[3] = j_b + xspoly[4] = i_c ; yspoly[4] = j_c + if d_c[j_t] > value then -- dd4 + xspoly[5] = i_l ; yspoly[5] = j_c ; nspoly = 5 + else + xspoly[5] = i_l ; yspoly[5] = j_c ; + xspoly[6] = i_l ; yspoly[6] = j_c ; nspoly = 6 + end + elseif d_c[j_t] > value then -- dd4 + if edgetoo then addedge(i_c, j_b, i_c, j_c) end + xspoly[3] = i_c ; yspoly[3] = j_c ; + xspoly[4] = i_l ; yspoly[4] = j_c ; nspoly = 4 + else + if edgetoo then addedge(i_c, j_b, i_l, j_c) end + xspoly[3] = i_l ; yspoly[3] = j_c ; nspoly = 3 + end + goto done + + ::foundit22:: -- 4 1 2 3 + + sq[j_c] = nrpm + + xspoly[1] = i_l ; yspoly[1] = j_c + xspoly[2] = i_l ; yspoly[2] = j_b + if d_c[j_c] > value then -- dd2 + xspoly[3] = i_c ; yspoly[3] = j_b + if d_r[j_c] > value then -- dd3 + xspoly[4] = i_c ; yspoly[4] = j_c + if d_r[j_t] > value then -- dd4 + nspoly = 4 + else + xspoly[5] = i_c ; yspoly[5] = j_c ; nspoly = 5 -- suspicious, the same + end + elseif d_r[j_t] > value then -- dd4 + xspoly[4] = i_c ; yspoly[4] = j_b ; + xspoly[5] = i_c ; yspoly[5] = j_c ; nspoly = 5 + else + if edgetoo then addedge(i_c, j_b, i_c, j_c) end + xspoly[4] = i_c ; yspoly[4] = j_c ; nspoly = 4 + end + elseif d_r[j_c] > value then -- dd3 + xspoly[3] = i_l ; yspoly[3] = j_b + xspoly[4] = i_c ; yspoly[4] = j_b + xspoly[5] = i_c ; yspoly[5] = j_c + if d_r[j_t] > value then -- dd4 + nspoly = 5 + else + xspoly[6] = i_c ; yspoly[6] = j_c ; nspoly = 6 + end + elseif d_r[j_t] > value then -- dd4 + if edgetoo then addedge(i_l, j_b, i_c, j_b) end + xspoly[3] = i_c ; yspoly[3] = j_b + xspoly[4] = i_c ; yspoly[4] = j_c ; nspoly = 4 + else + if edgetoo then addedge(i_l, j_b, i_c, j_c) end + xspoly[3] = i_c ; yspoly[3] = j_c ; nspoly = 3 + end + goto done + + ::foundit23:: -- 2 3 4 1 + + sq[j_c] = nrpm + + xspoly[1] = i_c ; yspoly[1] = j_b + xspoly[2] = i_c ; yspoly[2] = j_c + if d_r[j_t] > value then -- dd2 + xspoly[3] = i_l ; yspoly[3] = j_c + if d_c[j_t] > value then -- dd3 + xspoly[4] = i_l ; yspoly[4] = j_b + if d_c[j_c] > value then -- dd4 + nspoly = 4 + else + xspoly[5] = i_l ; yspoly[5] = j_b ; nspoly = 5 + end + elseif d_c[j_c] > value then -- dd4 + xspoly[4] = i_l ; yspoly[4] = j_c + xspoly[5] = i_l ; yspoly[5] = j_b ; nspoly = 5 + else + if edgetoo then addedge(i_l, j_c, i_l, j_b) end + xspoly[4] = i_l ; yspoly[4] = j_b ; nspoly = 4 + end + elseif d_c[j_t] > value then -- dd3 + xspoly[3] = i_c ; yspoly[3] = j_c + xspoly[4] = i_l ; yspoly[4] = j_c + xspoly[5] = i_l ; yspoly[5] = j_b + if d_c[j_c] > value then -- dd4 + nspoly = 5 + else + xspoly[6] = i_l ; yspoly[6] = j_b ; nspoly = 6 + end + elseif d_c[j_c] > value then -- dd4 + if edgetoo then addedge(i_c, j_c, i_l, j_c) end + xspoly[3] = i_l ; yspoly[3] = j_c ; + xspoly[4] = i_l ; yspoly[4] = j_b ; nspoly = 4 + else + if edgetoo then addedge(i_c, j_c, i_l, j_b) end + xspoly[3] = i_l ; yspoly[3] = j_b ; nspoly = 3 + end + goto done + + ::foundit24:: -- 3 4 1 2 + + sq[j_c] = nrpm + + xspoly[1] = i_c ; yspoly[1] = j_c + xspoly[2] = i_l ; yspoly[2] = j_c + if d_c[j_t] > value then -- dd2 + if d_c[j_c] > value then -- dd3 + xspoly[3] = i_l ; yspoly[3] = j_b + xspoly[4] = i_c ; yspoly[4] = j_b + if d_r[j_c] > value then -- dd4 + nspoly = 4 + else + xspoly[5] = i_c ; yspoly[5] = j_b ; nspoly = 5 + end + else + xspoly[3] = i_l ; yspoly[3] = j_b + if d_r[j_c] > value then -- dd4 + + local xv34 = (dd3*i_c-dd4*i_l)/(dd3 - dd4) -- probably i_l + print("4.4 : xv34",xv34,i_c,i_l) + + -- if edgetoo then addedge(i_l, j_b, xv34, j_b) end + xspoly[4] = xv34 ; yspoly[4] = j_b ; + xspoly[5] = i_c ; yspoly[5] = j_b ; nspoly = 5 + else + if edgetoo then addedge(i_l, j_b, i_c, j_b) end + xspoly[4] = i_c ; yspoly[4] = j_b ; nspoly = 4 + end + end + elseif d_c[j_c] > value then -- dd3 + xspoly[3] = i_l ; yspoly[3] = j_b + xspoly[4] = i_l ; yspoly[4] = j_b + xspoly[5] = i_c ; yspoly[5] = j_b + if d_r[j_c] > value then -- dd4 + nspoly = 5 + else + xspoly[6] = i_c ; yspoly[6] = j_b ; nspoly = 6 + end + elseif d_r[j_c] > value then -- dd4 + if edgetoo then addedge(i_l, j_c, i_l, j_b) end + xspoly[3] = i_l ; yspoly[3] = j_b + xspoly[4] = i_c ; yspoly[4] = j_b ; nspoly = 4 + else + if edgetoo then addedge(i_l, j_c, i_c, j_b) end + xspoly[3] = i_c ; yspoly[3] = j_b ; nspoly = 3 + end + -- goto done + + ::done:: + -- combine s-polygon with existing r-polygon, eliminating redundant segments + + if nrpoly == 0 then + -- initiate r-polygon + for i=1,nspoly do + xrpoly[i] = xspoly[i] + yrpoly[i] = yspoly[i] + end + nrpoly = nspoly + else + -- search r-polygon and s-polygon for one side that matches + -- + -- this is a bottleneck ... we keep this variant here but next go for a faster + -- alternative + -- + -- local ispoly, irpoly + -- for r=nrpoly,1,-1 do + -- local r1 + -- for s=1,nspoly do + -- local s1 = s % nspoly + 1 + -- if xrpoly[r] == xspoly[s1] and yrpoly[r] == yspoly[s1] then + -- if not r1 then + -- r1 = r % nrpoly + 1 + -- end + -- if xrpoly[r1] == xspoly[s] and yrpoly[r1] == yspoly[s] then + -- ispoly = s + -- irpoly = r + -- goto foundit3 + -- end + -- end + -- end + -- end + -- + -- local ispoly, irpoly + -- local xr1 = xrpoly[1] + -- local yr1 = yrpoly[1] + -- for r0=nrpoly,1,-1 do + -- for s0=1,nspoly do + -- if xr1 == xspoly[s0] and yr1 == yspoly[s0] then + -- if s0 == nspoly then + -- if xr0 == xspoly[1] and yr0 == yspoly[1] then + -- ispoly = s0 + -- irpoly = r0 + -- goto foundit3 + -- end + -- else + -- local s1 = s0 + 1 + -- if xr0 == xspoly[s1] and yr0 == yspoly[s1] then + -- ispoly = s0 + -- irpoly = r0 + -- goto foundit3 + -- end + -- end + -- end + -- end + -- xr1 = xrpoly[r0] + -- yr1 = yrpoly[r0] + -- end + -- + -- but ... + -- + local minx = xspoly[1] + local miny = yspoly[1] + local maxx = xspoly[1] + local maxy = yspoly[1] + for i=1,nspoly do + local y = yspoly[i] + if y < miny then + miny = y + elseif y > maxy then + maxy = y + end + local x = xspoly[i] + if x < minx then + minx = y + elseif x > maxx then + maxx = x + end + end + -- we can delay accessing y ... + local ispoly, irpoly + local xr1 = xrpoly[1] + local yr1 = yrpoly[1] + for r0=nrpoly,1,-1 do + if xr1 >= minx and xr1 <= maxx and yr1 >= miny and yr1 <= maxy then + local xr0 = xrpoly[r0] + local yr0 = yrpoly[r0] + for s0=1,nspoly do + if xr1 == xspoly[s0] and yr1 == yspoly[s0] then + if s0 == nspoly then + if xr0 == xspoly[1] and yr0 == yspoly[1] then + ispoly = s0 + irpoly = r0 + goto foundit3 + end + else + local s1 = s0 + 1 + if xr0 == xspoly[s1] and yr0 == yspoly[s1] then + ispoly = s0 + irpoly = r0 + goto foundit3 + end + end + end + end + xr1 = xr0 + yr1 = yr0 + else + xr1 = xrpoly[r0] + yr1 = yrpoly[r0] + end + end + -- + goto nomatch3 + ::foundit3:: + local match1 = 0 + local rpoly1 = irpoly + nrpoly + local spoly1 = ispoly - 1 + for i=2,nspoly-1 do + -- search for further matches nearby + local ir = (rpoly1 - i) % nrpoly + 1 + local is = (spoly1 + i) % nspoly + 1 + if xrpoly[ir] == xspoly[is] and yrpoly[ir] == yspoly[is] then + match1 = match1 + 1 + else + break -- goto nomatch1 + end + end + ::nomatch1:: + local match2 = 0 + local rpoly2 = irpoly - 1 + local spoly2 = ispoly + nspoly + for i=2,nspoly-1 do + -- search other way for further matches nearby + local ir = (rpoly2 + i) % nrpoly + 1 + local is = (spoly2 - i) % nspoly + 1 + if xrpoly[ir] == xspoly[is] and yrpoly[ir] == yspoly[is] then + match2 = match2 + 1 + else + break -- goto nomatch2 + end + end + ::nomatch2:: + -- local dnrpoly = nspoly - 2 - 2*match1 - 2*match2 + local dnrpoly = nspoly - 2*(match1 + match2 + 1) + local ispolystart = (ispoly + match1) % nspoly + 1 -- first node of s-polygon to include + local irpolyend = (rpoly1 - match1 - 1) % nrpoly + 1 -- last node of s-polygon to include + if dnrpoly ~= 0 then + local irpolystart = (irpoly + match2) % nrpoly + 1 -- first node of s-polygon to include + if irpolystart > irpolyend then + -- local ispolyend = (spoly1 - match2 + nspoly)%nspoly + 1 -- last node of s-polygon to include + if dnrpoly > 0 then + -- expand the arrays xrpoly and yrpoly + for i=nrpoly,irpolystart,-1 do + local k = i + dnrpoly + xrpoly[k] = xrpoly[i] + yrpoly[k] = yrpoly[i] + end + else -- if dnrpoly < 0 then + -- contract the arrays xrpoly and yrpoly + for i=irpolystart,nrpoly do + local k = i + dnrpoly + xrpoly[k] = xrpoly[i] + yrpoly[k] = yrpoly[i] + end + end + end + nrpoly = nrpoly + dnrpoly + end + if nrpoly < irpolyend then + for i=irpolyend,nrpoly+1,-1 do + -- otherwise these values get lost! + local k = i - nrpoly + xrpoly[k] = xrpoly[i] + yrpoly[k] = yrpoly[i] + end + end + local n = nspoly - 2 - match1 - match2 + if n == 1 then + local irpoly1 = irpolyend % nrpoly + 1 + local ispoly1 = ispolystart % nspoly + 1 + xrpoly[irpoly1] = xspoly[ispoly1] + yrpoly[irpoly1] = yspoly[ispoly1] + elseif n > 0 then + -- often 2 + for i=1,n do + local ii = i - 1 + local ir = (irpolyend + ii) % nrpoly + 1 + local is = (ispolystart + ii) % nspoly + 1 + xrpoly[ir] = xspoly[is] + yrpoly[ir] = yspoly[is] + end + end + ::nomatch3:: + end + end + end + + if nrpoly > 0 then + local t = { } + local n = 0 + for i=1,nrpoly do + n = n + 1 t[n] = xrpoly[i] + n = n + 1 t[n] = yrpoly[i] + end + if mpflatten then + mpflatten(t) -- maybe integrate + end + nofs = nofs + 1 + shade[nofs] = t + -- print(value,nrpoly,#t,#t-nrpoly*2) + end + + end + + edges [value+1] = edge + shades[value+1] = shade +-- edges [value] = edge +-- shades[value] = shade + end + + result.shades = shades + result.shapes = edges + +end + +-- accessors + +function mp.lmt_contours_nx (i) return getparameterset().result.nx end +function mp.lmt_contours_ny (i) return getparameterset().result.ny end + +function mp.lmt_contours_nofvalues() return getparameterset().result.nofvalues end +function mp.lmt_contours_value (i) return getparameterset().result.values[i] end + +function mp.lmt_contours_minz (i) return getparameterset().result.minz end +function mp.lmt_contours_maxz (i) return getparameterset().result.maxz end + +function mp.lmt_contours_minmean (i) return getparameterset().result.minmean end +function mp.lmt_contours_maxmean (i) return getparameterset().result.maxmean end + +function mp.lmt_contours_xrange () local p = getparameterset() mpstring(formatters["x = [%.3N,%.3N] ;"](p.xmin,p.xmax)) end +function mp.lmt_contours_yrange () local p = getparameterset() mpstring(formatters["y = [%.3N,%.3N] ;"](p.ymin,p.ymax)) end + +function mp.lmt_contours_format() + local p = getparameterset() + return mpstring(p.result.islist and "@i" or p.zformat or p.format) +end + +function mp.lmt_contours_function() + local p = getparameterset() + return mpstring(p.result.islist and concat(p["functions"], ", ") or p["function"]) +end + +function mp.lmt_contours_range() + local p = getparameterset() + local r = p.result.islist and p.range + if not r or #r == 0 then + return mpstring("") + elseif #r == 1 then + return mpstring(r[1]) + else + return mpstring(formatters["z = [%s,%s]"](r[1],r[2])) + end +end + +function mp.lmt_contours_edge_paths(value) + mpdraw(getparameterset().result.edges[value],true) + mpflush() +end + +function mp.lmt_contours_shape_paths(value) + mpdraw(getparameterset().result.shapes[value],false) + mpflush() +end + +function mp.lmt_contours_shade_paths(value) + mpfill(getparameterset().result.shades[value],true) + mpflush() +end + +function mp.lmt_contours_color(value) + local p = getparameterset() + local color = p.result.colors[value] + if color then + mpcolor(color) + end +end + +-- The next code is based on the wikipedia page. It was a bit tedius job to define the +-- coordinates but hupefully I made no errors. I rendered all shapes independently and +-- tripple checked bit one never knows ... + +-- maybe some day write from scatch, like this (axis are swapped): + +local d = 1/2 + +local paths = { + { 0, d, d, 0 }, + { 1, d, d, 0 }, + { 0, d, 1, d }, + { 1, d, d, 1 }, + { 0, d, d, 1, d, 0, 1, d }, -- saddle + { d, 0, d, 1 }, + { 0, d, d, 1 }, + { 0, d, d, 1 }, + { d, 0, d, 1 }, + { 0, d, d, 0, 1, d, d, 1 }, -- saddle + { 1, d, d, 1 }, + { 0, d, 1, d }, + { d, 0, 1, d }, + { d, 0, 0, d }, +} + +local function whatever(data,nx,ny,threshold) + local edges = { } + local e = 0 + local d0 = data[1] + for j=1,ny-1 do + local d1 = data[j+1] + local k = j + 1 + for i=1,nx-1 do + local v = 0 + local l = i + 1 + local c1 = d0[i] + if c1 < threshold then + v = v + 8 + end + local c2 = d0[l] + if c2 < threshold then + v = v + 4 + end + local c3 = d1[l] + if c3 < threshold then + v = v + 2 + end + local c4 = d1[i] + if c4 < threshold then + v = v + 1 + end + if v > 0 and v < 15 then + if v == 5 or v == 10 then + local a = (c1 + c2 + c3 + c4) / 4 + if a < threshold then + v = v == 5 and 10 or 5 + end + local p = paths[v] + e = e + 1 edges[e] = k - p[2] + e = e + 1 edges[e] = i + p[1] + e = e + 1 edges[e] = k - p[4] + e = e + 1 edges[e] = i + p[3] + e = e + 1 edges[e] = k - p[6] + e = e + 1 edges[e] = i + p[5] + e = e + 1 edges[e] = k - p[8] + e = e + 1 edges[e] = i + p[7] + else + local p = paths[v] + e = e + 1 edges[e] = k - p[2] + e = e + 1 edges[e] = i + p[1] + e = e + 1 edges[e] = k - p[4] + e = e + 1 edges[e] = i + p[3] + end + end + end + d0 = d1 + end + return edges +end + +-- todo: just fetch when needed, no need to cache + +function mp.lmt_contours_edge_set_by_cell() + local p = getparameterset() + local result = p.result + + if result.cached then return end + + local values = result.values + local nofvalues = result.nofvalues + local data = result.data + local nx = result.nx + local ny = result.ny + local lines = { } + result.lines = lines + for value=1,nofvalues do + lines[value] = whatever(data,ny,nx,value) + end +end + +function mp.lmt_contours_edge_get_cell(value) + mpdraw(getparameterset().result.lines[value]) + mpflush() +end + +local singles = { + { d, 0, 0, 0, 0, d }, -- 1 0001 + { d, 0, 0, d }, -- 2 0002 + { 1, d, 1, 0, d, 0 }, -- 3 0010 + { 1, d, 1, 0, 0, 0, 0, d }, -- 4 0011 + { 1, d, 1, 0, d, 0, 0, d }, -- 5 0012 + { 1, d, d, 0 }, -- 6 0020 + { 1, d, d, 0, 0, 0, 0, d }, -- 7 0021 + { 1, d, 0, d }, -- 8 0022 + { d, 1, 1, 1, 1, d }, -- 9 0100 + false, -- 10 0101 + false, -- 11 0102 + { d, 1, 1, 1, 1, 0, d, 0 }, -- 12 0110 + { d, 1, 1, 1, 1, 0, 0, 0, 0, d }, -- 13 0111 + { d, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 14 0112 + { d, 1, 1, 1, 1, d, d, 0 }, -- 15 0120 + { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, -- 16 0121 + { d, 1, 1, 1, 1, d, 0, d }, -- 17 0122 + { d, 1, 1, d }, -- 18 0200 + false, -- 19 0201 + false, -- 20 0202 + { d, 1, 1, d, 1, 0, d, 0 }, -- 21 0210 + { d, 1, 1, d, 1, 0, 0, 0, 0, d }, -- 22 0211 + false, -- 23 0212 + { d, 1, d, 0 }, -- 24 0220 + { d, 1, d, 0, 0, 0, 0, d }, -- 25 0221 + { d, 1, 0, d }, -- 26 0222 + { 0, 1, d, 1, 0, d }, -- 27 1000 + { 0, 1, d, 1, d, 0, 0, 0 }, -- 28 1001 + { 0, 1, d, 1, d, 0, 0, d }, -- 29 1002 + false, -- 30 1010 + { 0, 1, d, 1, 1, d, 1, 0, 0, 0 }, -- 31 1011 + { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, -- 32 1012 + false, -- 33 1020 + { 0, 1, d, 1, 1, d, d, 0, 0, 0 }, -- 34 1021 + { 0, 1, d, 1, 1, d, 0, d }, -- 35 1022 + { 0, 1, 1, 1, 1, d, 0, d }, -- 36 1100 + { 0, 1, 1, 1, 1, d, d, 0, 0, 0 }, -- 37 1101 + { 0, 1, 1, 1, 1, d, d, 0, 0, d }, -- 38 1102 + { 0, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 39 1110 + { 0, 1, 1, 1, 1, 0, 0, 0 }, -- 40 1111 + { 0, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 41 1112 + { 0, 1, 1, 1, 1, d, d, 0, 0, d }, -- 42 1120 + { 0, 1, 1, 1, 1, d, d, 0, 0, 0 }, -- 43 1121 + { 0, 1, 1, 1, 1, d, 0, d }, -- 44 1122 + { 0, 1, d, 1, 1, d, 0, d }, -- 45 1200 + { 0, 1, d, 1, 1, d, d, 0, 0, 0 }, -- 46 1201 + false, -- 47 1202 + { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, -- 48 1210 + { 0, 1, d, 1, 1, d, 1, 0, 0, 0 }, -- 49 1211 + false, -- 50 1212 + { 0, 1, d, 1, d, 0, 0, d }, -- 51 1220 + { 0, 1, d, 1, d, 0, 0, 0 }, -- 52 1221 + { 0, 1, d, 1, 0, d }, -- 53 1222 + { d, 1, 0, d }, -- 54 2000 + { d, 1, d, 0, 0, 0, 0, d }, -- 55 2001 + { d, 1, d, 0 }, -- 56 2002 + false, -- 57 2010 + { d, 1, 1, d, 1, 0, 0, 0, 0, d }, -- 58 2011 + { d, 1, 1, d, 1, 0, d, 0 }, -- 59 2012 + false, -- 60 2020 + false, -- 61 2021 + { d, 1, 1, d }, -- 62 2022 + { d, 1, 1, 1, 1, d, 0, d }, -- 63 2100 + { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, -- 64 2101 + { d, 1, 1, 1, 1, d, d, 0 }, -- 65 2102 + { d, 1, 1, 1, 1, 0, d, 0, 0, d }, -- 66 2110 + { d, 1, 1, 1, 1, 0, 0, 0, 0, d }, -- 67 2111 + { d, 1, 1, 1, 1, 0, d, 0 }, -- 68 2112 + false, -- 69 2120 + false, -- 70 2121 + { d, 1, 1, 1, 1, d }, -- 71 2122 + { 1, d, 0, d }, -- 72 2200 + { 1, d, d, 0, 0, 0, 0, d }, -- 73 2201 + { 1, d, d, 0 }, -- 74 2202 + { 1, d, 1, 0, d, 0, 0, d }, -- 75 2210 + { 1, d, 1, 0, 0, 0, 0, d }, -- 76 2211 + { 1, d, 1, 0, d, 0 }, -- 77 2212 + { d, 0, 0, d }, -- 78 2220 + { 0, d, 0, 0, d, 0 }, -- 79 2221 +} + +local sadles = { + false, false, false, false, false, false, false, false, false, + { { d, 1, 1, 1, 1, d }, { d, 0, 0, 0, 0, d }, { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, false, false, false }, -- 10 0101 + { { d, 1, 1, 1, 1, d }, { d, 0, 0, d }, { d, 1, 1, 1, 1, d, d, 0, 0, d }, false, false, false }, -- 11 0102 + false, false, false, false, false, false, false, + { { d, 1, 1, d }, { d, 0, 0, 0, 0, d }, { d, 1, 1, d, d, 0, 0, 0, 0, d }, false, false, false }, -- 19 0201 + { { d, 1, 1, d }, { d, 0, 0, d }, { d, 1, 1, d, d, 0, 0, d }, false, { d, 1, 0, d }, { 1, d, d, 0 } }, -- 20 0202 + false, false, + { false, false, { d, 1, 1, d, 1, 0, d, 0, 0, d }, false, { d, 1, 0,d, }, { 1, d, 1, 0,d, 0 } }, -- 23 0212 + false, false, false, false, false, false, + { { 0, 1, d, 1, 0, d }, { 1, d, 1, 0, d, 0 }, { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, false, false, false }, -- 30 1010 + false, false, + { { 1, 0, d, 0, 0, d, }, { 1, d, d, 0 }, { 0, 1, d, 1, 1, d, d, 0, 0, d }, false, false, false }, -- 33 1020 + false, false, false, false, false, false, false, false, false, false, false, false, false, + { false, false, { 0,1, d, 1, 1, d, d, 0, 0, d }, false, { 0,1, d, 1, 0, d }, {1, d, d, 0 } }, -- 47 1202 + false, false, + { false, false, { 0, 1, d, 1, 1, d, 1, 0, d, 0, 0, d }, false, { 0, 1, d, 1, 0, d }, { 1, d, 1, 0, d, 0 } }, -- 50 1212 + false, false, false, false, false, false, + { { d, 1, 0, d }, { 1, d, 1, 0, 0, d }, { d, 1, 1, d, 1, 0, d, 0, 0, d }, false, false, false }, -- 57 2010 + false, false, + { { d, 1, 0,d }, { 1, d, d, 0 }, { d, 1, 1, d, d, 0, 0, d }, false, { d, 1, 1, d }, { d, 0, 0, d } }, -- 60 2020 + { false, false, { d, 1, 1, d, d, 0, 0, 0, 0, d }, false, { d, 1, 1, d }, { d, 0, 0, 0, 0, d } }, -- 61 2021 + false, false, false, false, false, false, false, + { false, false, { d, 1, 1, 1, 1, d, d, 0, 0, d }, false, { d, 1, 1, 1, 1, d }, { d, 0,0,d } }, -- 69 2120 + { false, false, { d, 1, 1, 1, 1, d, d, 0, 0, 0, 0, d }, false, { d, 1, 1, 1, 1, d }, { d, 0, 0, 0, 0, d } }, -- 70 2121 +} + +local function whatever(data,nx,ny,threshold,background) + + if background then + + local llx = 1/2 + local lly = llx + local urx = ny + llx + local ury = nx + lly + + return { { llx, lly, urx, 0, urx, ury, 0, ury } } + + else + + local bands = { } + local b = 0 + + local function band(s,n,x,y) -- simple. no closure so fast + if n == 6 then + return { + x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], + } + elseif n == 8 then + return { + x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], + x - s[ 8], y + s[ 7], + } + elseif n == 10 then + return { + x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], + x - s[ 8], y + s[ 7], x - s[10], y + s[ 9], + } + elseif n == 4 then + return { + x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], + } + else -- 12 + return { + x - s[ 2], y + s[ 1], x - s[ 4], y + s[ 3], x - s[ 6], y + s[ 5], + x - s[ 8], y + s[ 7], x - s[10], y + s[ 9], x - s[12], y + s[11], + } + end + end + + local pp = { } + + local d0 = data[1] + for j=1,ny-1 do + local d1 = data[j+1] + local k = j + 1 + local p = false + for i=1,nx-1 do + local v = 0 + local l = i + 1 + local c1 = d0[i] + if c1 == threshold then + v = v + 27 + elseif c1 > threshold then + v = v + 54 + end + local c2 = d0[l] + if c2 == threshold then + v = v + 9 + elseif c2 > threshold then + v = v + 18 + end + local c3 = d1[l] + if c3 == threshold then + v = v + 3 + elseif c3 > threshold then + v = v + 6 + end + local c4 = d1[i] + if c4 == threshold then + v = v + 1 + elseif c4 > threshold then + v = v + 2 + end + if v > 0 and v < 80 then + if v == 40 then + -- a little optimization: full areas appended horizontally + if p then + p[4] = l -- i + 1 + p[6] = l -- i + 1 + else + -- x-0 y+1 x-1 y+1 x-1 y+0 x-0 y+0 + p = { j, i, j, l, k, l, k, i } + b = b + 1 ; bands[b] = p + end + else + local s = singles[v] + if s then + b = b + 1 ; bands[b] = band(s,#s,k,i) + else + local s = sadles[v] + if s then + local m = (c1 + c2 + c3 + c4) / 4 + if m < threshold then + local s1 = s[1] if s1 then b = b + 1 ; bands[b] = band(s1,#s1,i,j) end + local s2 = s[2] if s2 then b = b + 1 ; bands[b] = band(s2,#s2,i,j) end + elseif m == threshold then + local s3 = s[3] if s3 then b = b + 1 ; bands[b] = band(s3,#s3,i,j) end + local s4 = s[4] if s4 then b = b + 1 ; bands[b] = band(s4,#s4,i,j) end + else + local s5 = s[5] if s5 then b = b + 1 ; bands[b] = band(s5,#s5,i,j) end + local s6 = s[6] if s6 then b = b + 1 ; bands[b] = band(s6,#s6,i,j) end + end + end + end + p = false + end + else + p = false + end + end + d0 = d1 + end + return bands + end +end + +function mp.lmt_contours_edge_set_by_band(value) + local p = getparameterset() + local result = p.result + + if result.cached then return end + + local values = result.values + local nofvalues = result.nofvalues + local data = result.data + local nx = result.nx + local ny = result.ny + local bands = { } + result.bands = bands + for value=1,nofvalues do + bands[value] = whatever(data,ny,nx,value,value == 1) + end +end + +function mp.lmt_contours_edge_get_band(value) + mpfill(getparameterset().result.bands[value],true) + mpflush() +end + +-- Because we share some code surface plots also end up here. When working on the +-- contour macros by concidence I ran into a 3D plot in +-- +-- https://staff.science.uva.nl/a.j.p.heck/Courses/mptut.pdf +-- +-- The code is pure MetaPost and works quite well. With a bit of optimization +-- performance is also ok, but in the end a Lua solution is twice as fast and also +-- permits some more tweaking at no cost. So, below is an adaptation of an example +-- in the mentioned link. It's one of these cases where access to pseudo arrays +-- is slowing down MP. + +local sqrt, sin, cos = math.sqrt, math.sin, math.cos + +local f_fill_rgb = formatters["F (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N) ;"] +local f_draw_rgb = formatters["D (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor %.3F ;"] +local f_mesh_rgb = formatters["U (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N) ;"] +local f_fill_cmy = formatters["F (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N,0) ;"] +local f_draw_cmy = formatters["D (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor %.3F ;"] +local f_mesh_cmy = formatters["U (%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--C withcolor (%.3N,%.3N,%.3N,0) ;"] + +local f_function_n = formatters [ [[ + local math = math + local round = math.round + %s + return function(x,y) + return %s + end +]] ] + +local f_function_y = formatters [ [[ + local math = math + local round = math.round + local nan = NaN + local inf = math.huge + local er = 0 + %s + return function(x,y,dnan,dinf,report) + local n = %s + if n == nan then + er = er + 1 + if er < 10 then + report("nan at (%s,%s)",x,y) + end + n = dnan + elseif n == inf then + er = er + 1 + if er < 10 then + report("inf at (%s,%s)",x,y) + end + n = dinf + end + dx[my] = n + sy = sy + 1 + end + return n, er +end +]] ] + +local f_color = formatters [ [[ + local math = math + return function(f) + return %s + end +]] ] + +function mp.lmt_surface_do(specification) + -- + -- The projection and color brightness calculation have been inlined. We also store + -- differently. + -- + -- todo: ignore weird paths + -- + -- The prototype is now converted to use lmt parameter sets. + -- + local p = getparameterset("surface") + -- + local preamble = p.preamble or "" + local code = p.code or "return x + y" + local colorcode = p.color or "return f, f, f" + local linecolor = p.linecolor or 1 + local xmin = p.xmin or -1 + local xmax = p.xmax or 1 + local ymin = p.ymin or -1 + local ymax = p.ymax or 1 + local xstep = p.xstep or .1 + local ystep = p.ystep or .1 + local bf = p.brightness or 100 + local clip = p.clip or false + local lines = p.lines + local ha = p.snap or 0.01 + local hb = 2 * ha + -- + if lines == nil then lines = true end + -- + if xstep == 0 then xstep = (xmax - xmin)/100 end + if ystep == 0 then ystep = (ymax - ymin)/100 end + + local nxmin = round(xmin/xstep) + local nxmax = round(xmax/xstep) + local nymin = round(ymin/ystep) + local nymax = round(ymax/ystep) + local nx = nxmax - nxmin + 1 + local ny = nymax - nymin + 1 + -- + local xvector = p.xvector or { -0.7, -0.7 } + local yvector = p.yvector or { 1, 0 } + local zvector = p.zvector or { 0, 1 } + local light = p.light or { 3, 3, 10 } + -- + local xrx, xry = xvector[1], xvector[2] + local yrx, yry = yvector[1], yvector[2] + local zrx, zry = zvector[1], zvector[2] + local xp, yp, zp = light[1], light[2], light[3] + -- + local data = setmetatableindex("table") + local dx = (xmax - xmin) / nx + local dy = (ymax - ymin) / ny + local xt = xmin + -- + local minf, maxf + -- + -- similar as contours but no data loop here + -- + local fcode = load((p.check and f_function_y or f_function_n)(preamble,code)) + local func = type(fcode) == "function" and fcode() + if type(func) ~= "function" then + return false -- fatal error + end + -- + local ccode = load(f_color(colorcode)) + local color = type(ccode) == "function" and ccode() + if type(color) ~= "function" then + return false -- fatal error + end + -- + for i=0,nx do + local yt = ymin + for j=0,ny do + local zt = func(xt,yt) + -- projection from 3D to 2D coordinates + local x = xt * xrx + yt * yrx + zt * zrx + local y = xt * xry + yt * yry + zt * zry + local z = zt + -- numerical derivatives by central differences + local dfx = (func(xt+ha,yt) - func(xt-ha,yt)) / hb + local dfy = (func(xt,yt+ha) - func(xt,yt-ha)) / hb + -- compute brightness factor at a point + local ztp = zt - zp + local ytp = yt - yp + local xtp = xt - xp + local ztp = zt - zp + local ytp = yt - yp + local xtp = xt - xp + local ca = -ztp + dfy*ytp + dfx*xtp + local cb = sqrt(1+dfx*dfx+dfy*dfy) + local cc = sqrt(ztp*ztp + ytp*ytp + xtp*xtp) + local fac = bf*ca/(cb*cc*cc*cc) + -- addition: check range + if not minf then + minf = fac + maxf = fac + elseif fac < minf then + minf = fac + elseif fac > maxf then + maxf = fac + end + -- + data[i][j] = { x, y, fac } + -- + yt = yt + dy + end + xt = xt + dx + end + local result = { } + local r = 0 + local range = maxf - minf + local cl = linecolor or 1 + local enforce = attributes.colors.model == "cmyk" + for i=0,nx-1 do + for j=0,ny-1 do + -- points + local z1 = data[i] [j] + local z2 = data[i] [j+1] + local z3 = data[i+1][j+1] + local z4 = data[i+1][j] + -- color + local cf = z1[3] + if clip then + -- best clip here if needed + if cf < 0 then + cf = 0 + elseif cf > 1 then + cf = 1 + end + else + -- or remap when we want to + cf = (z1[3] - minf) / range + end + local z11 = z1[1] + local z12 = z1[2] + local z21 = z2[1] + local z22 = z2[2] + local z31 = z3[1] + local z32 = z3[2] + local z41 = z4[1] + local z42 = z4[2] + -- if lines then + -- -- fill first and draw then, previous shapes can be covered + -- else + -- -- fill and draw in one go to prevent artifacts + -- end + local cr, cg, cb = color(cf) + if not cr then cr = 0 end + if not cg then cg = 0 end + if not cb then cb = 0 end + if enforce then + cr, cg, cb = 1 - cr, 1 - cg, 1 - cb + r = r + 1 + if lines then + result[r] = f_fill_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) + r = r + 1 + result[r] = f_draw_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cl) + else + result[r] = f_mesh_cmy(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) + end + else + r = r + 1 + if lines then + result[r] = f_fill_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) + r = r + 1 + result[r] = f_draw_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cl) + else + result[r] = f_mesh_rgb(z11,z12,z21,z22,z31,z32,z41,z42,cr,cg,cb) + end + end + end + end + mp.direct(concat(result)) +end diff --git a/tex/context/base/mkxl/mlib-ctx.mkxl b/tex/context/base/mkxl/mlib-ctx.mkxl new file mode 100644 index 000000000..88f26c9ac --- /dev/null +++ b/tex/context/base/mkxl/mlib-ctx.mkxl @@ -0,0 +1,32 @@ +%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. + +\writestatus{loading}{MetaPost Library Graphics / Initializations} + +\registerctxluafile{mlib-fio}{autosuffix} +\registerctxluafile{mlib-run}{} +\registerctxluafile{mlib-ctx}{} +\registerctxluafile{mlib-lua}{autosuffix} +\registerctxluafile{mlib-mpf}{} +\registerctxluafile{mlib-scn}{autosuffix} +\registerctxluafile{mlib-mat}{autosuffix} +\registerctxluafile{mlib-ran}{autosuffix} +\registerctxluafile{mlib-lmp}{autosuffix} +\registerctxluafile{mlib-int}{autosuffix} +\registerctxluafile{mlib-lmt}{autosuffix} +\registerctxluafile{mlib-cnt}{autosuffix,optimize} +\registerctxluafile{mlib-svg}{autosuffix,optimize} + +\unprotect + +\protect \endinput diff --git a/tex/context/base/mkxl/mlib-fio.lmt b/tex/context/base/mkxl/mlib-fio.lmt new file mode 100644 index 000000000..4290537dd --- /dev/null +++ b/tex/context/base/mkxl/mlib-fio.lmt @@ -0,0 +1,191 @@ +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", +} + +local type = type +local find = string.find +local concat = table.concat + +local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end) + +local report_metapost = logs.reporter("metapost") +local report_terminal = logs.reporter("metapost","terminal") +local report_logger = logs.reporter("metapost","log") +local report_error = logs.reporter("metapost","error") + +mplib.realtimelogging = false + +local l, nl, dl = { }, 0, false +local t, nt, dt = { }, 0, false +local e, ne, de = { }, 0, false + +local function logger(target,str) + if target == 1 then + -- log + elseif target == 2 or target == 3 then + -- term + if str == "\n" then + mplib.realtimelogging = true + if nl > 0 then + report_logger(concat(l,"",1,nl)) + nl, dl = 0, false + elseif not dl then + report_logger("") + dl = true + end + else + nl = nl + 1 + l[nl] = str + end + elseif target == 4 then + report_error(str) + end +end + +local finders = { } +mplib.finders = finders -- also used in meta-lua.lua + +local new_instance = mplib.new + +local function validftype(ftype) + if ftype == "mp" then + return "mp" + else + return nil + end +end + +finders.file = function(specification,name,mode,ftype) + return resolvers.findfile(name,validftype(ftype)) +end + +local findtexfile = resolvers.findtexfile +local opentexfile = resolvers.opentexfile +local splitlines = string.splitlines + +local function writetoterminal(terminaldata,maxterm,d) + local t = type(d) + local n = 0 + if t == "string" then + d = splitlines(d) + n = #d + for i=1,#d do + maxterm = maxterm + 1 + terminaldata[maxterm] = d[i] + end + elseif t == "table" then + for i=1,#d do + local l = d[i] + if find(l,"[\n\r]") then + local s = splitlines(l) + local m = #s + for i=1,m do + maxterm = maxterm + 1 + terminaldata[maxterm] = s[i] + end + n = n + m + else + maxterm = maxterm + 1 + terminaldata[maxterm] = d[i] + n = 1 + end + end + end + if trace_terminal then + report_metapost("writing %i lines, in cache %s",n,maxterm) + end + return maxterm +end + +local function readfromterminal(terminaldata,maxterm,nowterm) + if nowterm >= maxterm then + terminaldata[nowterm] = false + maxterm = 0 + nowterm = 0 + if trace_terminal then + report_metapost("resetting, maxcache %i",#terminaldata) + end + return maxterm, nowterm, nil + else + if nowterm > 0 then + terminaldata[nowterm] = false + end + nowterm = nowterm + 1 + local s = terminaldata[nowterm] + if trace_terminal then + report_metapost("reading line %i: %s",nowterm,s) + end + return maxterm, nowterm, s + end +end + +local function fileopener() + + -- these can go into the table itself + + local terminaldata = { } + local maxterm = 0 + local nowterm = 0 + + local terminal = { + name = "terminal", + close = function() + -- terminal = { } + -- maxterm = 0 + -- nowterm = 0 + end, + reader = function() + local line + maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm) + return line + end, + writer = function(d) + maxterm = writetoterminal(terminaldata,maxterm,d) + end, + } + + return function(name,mode,kind) + if name == "terminal" then + -- report_metapost("opening terminal") + return terminal + elseif mode == "w" then + local f = io.open(name,"wb") + if f then + -- report_metapost("opening file %a for writing",full) + return { + name = full, + writer = function(s) return f:write(s) end, -- io.write(f,s) + close = function() f:close() end, + } + end + else + local full = findtexfile(name,validftype(ftype)) + if full then + -- report_metapost("opening file %a for reading",full) + return opentexfile(full) + end + end + end + +end + +local function finder(name,mode,kind) + return findtexfile(name,kind) +end + +function mplib.new(specification) + local openfile = fileopener() + specification.find_file = finder + specification.run_logger = logger + specification.open_file = openfile + specification.interaction = "silent" + specification.halt_on_error = true + local instance = new_instance(specification) + return instance, openfile("terminal") +end + +mplib.finder = finder diff --git a/tex/context/base/mkxl/mlib-int.lmt b/tex/context/base/mkxl/mlib-int.lmt new file mode 100644 index 000000000..86e2e5732 --- /dev/null +++ b/tex/context/base/mkxl/mlib-int.lmt @@ -0,0 +1,135 @@ +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 mpstring = mp.string +local mpboolean = mp.boolean +local getdimen = tex.getdimen +local getcount = tex.getcount +local getmacro = tokens.getters.macro +local get = tex.get +local emwidths = fonts.hashes.emwidths +local exheights = fonts.hashes.exheights + +local registerscript = metapost.registerscript + +local on_right_page = structures.pages.on_right +local is_odd_page = structures.pages.is_odd +local in_body_page = structures.pages.in_body +local page_fraction = structures.pages.fraction + +local function defaultcolormodel() -- can be helper + local colormethod = getcount("MPcolormethod") + return (colormethod == 0 or colormethod == 1) and 1 or 3 +end + +local t = os.date("*t") -- maybe this should be a very early on global + +registerscript("year", function() return t.year end) +registerscript("month", function() return t.month end) +registerscript("day", function() return t.day end) +registerscript("hour", function() return t.hour end) +registerscript("minute", function() return t.min end) +registerscript("second", function() return t.sec end) + +registerscript("PaperHeight", function() return getdimen("paperheight") * factor end) +registerscript("PaperWidth", function() return getdimen("paperwidth") * factor end) +registerscript("PrintPaperHeight", function() return getdimen("printpaperheight") * factor end) +registerscript("PrintPaperWidth", function() return getdimen("printpaperwidth") * factor end) +registerscript("TopSpace", function() return getdimen("topspace") * factor end) +registerscript("BottomSpace", function() return getdimen("bottomspace") * factor end) +registerscript("BackSpace", function() return getdimen("backspace") * factor end) +registerscript("CutSpace", function() return getdimen("cutspace") * factor end) +registerscript("MakeupHeight", function() return getdimen("makeupheight") * factor end) +registerscript("MakeupWidth", function() return getdimen("makeupwidth") * factor end) +registerscript("TopHeight", function() return getdimen("topheight") * factor end) +registerscript("TopDistance", function() return getdimen("topdistance") * factor end) +registerscript("HeaderHeight", function() return getdimen("headerheight") * factor end) +registerscript("HeaderDistance", function() return getdimen("headerdistance") * factor end) +registerscript("TextHeight", function() return getdimen("textheight") * factor end) +registerscript("FooterDistance", function() return getdimen("footerdistance") * factor end) +registerscript("FooterHeight", function() return getdimen("footerheight") * factor end) +registerscript("BottomDistance", function() return getdimen("bottomdistance") * factor end) +registerscript("BottomHeight", function() return getdimen("bottomheight") * factor end) +registerscript("LeftEdgeWidth", function() return getdimen("leftedgewidth") * factor end) +registerscript("LeftEdgeDistance", function() return getdimen("leftedgedistance") * factor end) +registerscript("LeftMarginWidth", function() return getdimen("leftmarginwidth") * factor end) +registerscript("LeftMarginDistance", function() return getdimen("leftmargindistance") * factor end) +registerscript("TextWidth", function() return getdimen("textwidth") * factor end) +registerscript("RightMarginDistance", function() return getdimen("rightmargindistance") * factor end) +registerscript("RightMarginWidth", function() return getdimen("rightmarginwidth") * factor end) +registerscript("RightEdgeDistance", function() return getdimen("rightedgedistance") * factor end) +registerscript("RightEdgeWidth", function() return getdimen("rightedgewidth") * factor end) +registerscript("InnerMarginDistance", function() return getdimen("innermargindistance") * factor end) +registerscript("InnerMarginWidth", function() return getdimen("innermarginwidth") * factor end) +registerscript("OuterMarginDistance", function() return getdimen("outermargindistance") * factor end) +registerscript("OuterMarginWidth", function() return getdimen("outermarginwidth") * factor end) +registerscript("InnerEdgeDistance", function() return getdimen("inneredgedistance") * factor end) +registerscript("InnerEdgeWidth", function() return getdimen("inneredgewidth") * factor end) +registerscript("OuterEdgeDistance", function() return getdimen("outeredgedistance") * factor end) +registerscript("OuterEdgeWidth", function() return getdimen("outeredgewidth") * factor end) +registerscript("PageOffset", function() return getdimen("pagebackgroundoffset") * factor end) +registerscript("PageDepth", function() return getdimen("pagebackgrounddepth") * factor end) +registerscript("LayoutColumns", function() return getcount("layoutcolumns") end) +registerscript("LayoutColumnDistance", function() return getdimen("layoutcolumndistance") * factor end) +registerscript("LayoutColumnWidth", function() return getdimen("layoutcolumnwidth") * factor end) +registerscript("SpineWidth", function() return getdimen("spinewidth") * factor end) +registerscript("PaperBleed", function() return getdimen("paperbleed") * factor end) + +registerscript("RealPageNumber", function() return getcount("realpageno") end) +registerscript("LastPageNumber", function() return getcount("lastpageno") end) + +registerscript("PageNumber", function() return getcount("pageno") end) +registerscript("NOfPages", function() return getcount("lastpageno") end) + +registerscript("SubPageNumber", function() return getcount("subpageno") end) +registerscript("NOfSubPages", function() return getcount("lastsubpageno") end) + +registerscript("CurrentColumn", function() return getcount("mofcolumns") end) +registerscript("NOfColumns", function() return getcount("nofcolumns") end) + +registerscript("BaseLineSkip", function() return get ("baselineskip",true) * factor end) +registerscript("LineHeight", function() return getdimen("lineheight") * factor end) +registerscript("BodyFontSize", function() return getdimen("bodyfontsize") * factor end) + +registerscript("TopSkip", function() return get ("topskip",true) * factor end) +registerscript("StrutHeight", function() return getdimen("strutht") * factor end) +registerscript("StrutDepth", function() return getdimen("strutdp") * factor end) + +registerscript("PageNumber", function() return getcount("pageno") end) +registerscript("RealPageNumber", function() return getcount("realpageno") end) +registerscript("NOfPages", function() return getcount("lastpageno") end) + +registerscript("CurrentWidth", function() return get ("hsize") * factor end) +registerscript("CurrentHeight", function() return get ("vsize") * factor end) + +registerscript("EmWidth", function() return emwidths [false] * factor end) +registerscript("ExHeight", function() return exheights[false] * factor end) + +registerscript("HSize", function() return get ("hsize") * factor end) +registerscript("VSize", function() return get ("vsize") * factor end) +registerscript("LastPageNumber", function() return getcount("lastpageno") end) + +registerscript("OverlayWidth", function() return getdimen("d_overlay_width") * factor end) +registerscript("OverlayHeight", function() return getdimen("d_overlay_height") * factor end) +registerscript("OverlayDepth", function() return getdimen("d_overlay_depth") * factor end) +registerscript("OverlayLineWidth", function() return getdimen("d_overlay_linewidth") * factor end) +registerscript("OverlayOffset", function() return getdimen("d_overlay_offset") * factor end) +registerscript("OverlayRegion", function() mpstring(getmacro("m_overlay_region")) end) +--------------("CurrentLayout", function() mpstring(getmacro("currentlayout")) end) + +-- should be direct +-- +-- registerscript("PageFraction", page_fraction) + +registerscript("PageFraction", function() return mpboolean(page_fraction()) end) +registerscript("OnRightPage", function() return mpboolean(on_right_page()) end) +registerscript("OnOddPage", function() return mpboolean(is_odd_page ()) end) +registerscript("InPageBody", function() return mpboolean(in_body_page ()) end) + +registerscript("defaultcolormodel", defaultcolormodel) diff --git a/tex/context/base/mkxl/mlib-lmp.lmt b/tex/context/base/mkxl/mlib-lmp.lmt new file mode 100644 index 000000000..ff9682e87 --- /dev/null +++ b/tex/context/base/mkxl/mlib-lmp.lmt @@ -0,0 +1,70 @@ +if not modules then modules = { } end modules ['mlib-lmp'] = { + 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", +} + +-- path relates stuff ... todo: use a stack (or numeric index to list) + +local type = type + +local aux = mp.aux +local mpnumeric = aux.numeric +local mppair = aux.pair + +local p = nil +local n = 0 + +local function mf_path_reset() + p = nil + n = 0 +end + +local scan = mp.scan +local scannumber = scan.number +local scanpath = scan.path + +local function mf_path_length() + p = scanpath() + n = p and #p or 1 + mpnumeric(n) +end + +local function mf_path_point() + local i = scannumber() + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[1],pi[2]) + end +end + +local function mf_path_left() + local i = scannumber() + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[5],pi[6]) + end +end + +local function mf_path_right() + local i = scannumber() + if i > 0 and i <= n then + local pn + if i == 1 then + pn = p[2] or p[1] + else + pn = p[i+1] or p[1] + end + mppair(pn[3],pn[4]) + end +end + +local registerscript = metapost.registerscript + +registerscript("pathreset", mf_path_reset) +registerscript("pathlengthof", mf_path_length) +registerscript("pathpointof", mf_path_point) +registerscript("pathleftof", mf_path_left) +registerscript("pathrightof", mf_path_right) diff --git a/tex/context/base/mkxl/mlib-lmt.lmt b/tex/context/base/mkxl/mlib-lmt.lmt new file mode 100644 index 000000000..f0b59248a --- /dev/null +++ b/tex/context/base/mkxl/mlib-lmt.lmt @@ -0,0 +1,153 @@ +if not modules then modules = { } end modules ['mlib-lmt'] = { + 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", +} + +-- todo: check for possible inject usage + +local type = type + +local aux = mp.aux +local mpdirect = aux.direct +local mppath = mp.path + +local scan = mp.scan +local scannumeric = scan.numeric +local scanpath = scan.path + +local getparameter = metapost.getparameter + +function mp.lmt_function_x(xmin,xmax,xstep,code,shape) -- experimental + local code = "return function(x) return " .. code .. " end" + local action = load(code) + local points = { } + local nofpoints = 0 + if action then + action = action() + end + if shape == "steps" then + local halfx = xstep / 2 + local lastx = xmin + local lasty = action(xmin) + for xi = xmin, xmax, xstep do + local yi = action(xi) + local xx = lastx + halfx + nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty } + nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi } + lastx = xi + lasty = yi + end + if points[nofpoints][1] ~= xmax then + local yi = action(xmax) + local xx = lastx + halfx + nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty } + nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi } + lastx = xi + lasty = yi + end + else + for xi = xmin, xmax, xstep do + nofpoints = nofpoints + 1 ; points[nofpoints] = { xi, action(xi) } + end + if points[nofpoints][1] ~= xmax then + nofpoints = nofpoints + 1 ; points[nofpoints] = { xmax, action(xmax) } + end + end + mppath(points,shape == "curve" and ".." or "--",false) +end + +function mp.lmt_mesh_set() + local mesh = getparameter { "mesh", "paths" } + structures.references.currentset.mesh = mesh +end + +function mp.lmt_mesh_update() + local mesh = getparameter { "paths" } or getparameter { "mesh", "paths" } + mesh[scannumeric()] = scanpath(true) +end + +-- moved here + +function mp.lmt_svg_include() + local labelfile = metapost.getparameter { "labelfile" } + if labelfile and labelfile ~= "" then + local labels = table.load(labelfile) -- todo: same path as svg file + if type(labels) == "table" then + for i=1,#labels do + metapost.remaptext(labels[i]) + end + end + end + local fontname = metapost.getparameter { "fontname" } + if fontname and fontname ~= "" then + local unicode = metapost.getparameter { "unicode" } + if unicode then + mpdirect ( + metapost.svgglyphtomp(fontname,math.round(unicode)) + ) + end + return + end + local colorfile = metapost.getparameter { "colormap" } + local colormap = false + if colorfile and colorfile ~= "" then + colormap = metapost.svgcolorremapper(colorfile) + end + local filename = metapost.getparameter { "filename" } + if filename and filename ~= "" then + mpdirect ( metapost.svgtomp { + data = io.loaddata(filename), + remap = true, + colormap = colormap, + id = filename, + } ) + else + local buffer = metapost.getparameter { "buffer" } + if buffer then + mpdirect ( metapost.svgtomp { + data = buffers.getcontent(buffer), + -- remap = true, + colormap = colormap, + id = buffer or "buffer", + } ) + else + local code = metapost.getparameter { "code" } + if code then + mpdirect ( metapost.svgtomp { + data = code, + colormap = colormap, + id = "code", + } ) + end + end + end +end + + +function mp.lmt_do_remaptext() + local parameters = metapost.scanparameters() + if parameters and parameters.label then + metapost.remaptext(parameters) + end +end + +do + + local dropins = fonts.dropins + local registerglyphs = dropins.registerglyphs + local registerglyph = dropins.registerglyph + + function mp.lmt_register_glyph() + registerglyph(metapost.getparameterset("mpsglyph")) + end + + function mp.lmt_register_glyphs() + registerglyphs(metapost.getparameterset("mpsglyphs")) + end + +end + +todecimal = xdecimal and xdecimal.new or tonumber -- bonus diff --git a/tex/context/base/mkxl/mlib-lua.lmt b/tex/context/base/mkxl/mlib-lua.lmt new file mode 100644 index 000000000..8721ed60c --- /dev/null +++ b/tex/context/base/mkxl/mlib-lua.lmt @@ -0,0 +1,168 @@ +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", +} + +local type = type +local insert, remove = table.insert, table.remove + +local scan = mp.scan +local inject = mp.inject + +local currentmpx = nil +local stack = { } + +local scan_next = mplib.scan_next +local scan_expression = mplib.scan_expression +local scan_token = mplib.scan_token +local scan_symbol = mplib.scan_symbol +local scan_numeric = mplib.scan_numeric +local scan_integer = mplib.scan_integer +local scan_boolean = mplib.scan_boolean +local scan_string = mplib.scan_string +local scan_pair = mplib.scan_pair +local scan_color = mplib.scan_color +local scan_cmykcolor = mplib.scan_cmykcolor +local scan_transform = mplib.scan_transform +local scan_path = mplib.scan_path +local scan_pen = mplib.scan_pen + +scan.next = function(k) return scan_next (currentmpx,k) end +scan.expression = function(k) return scan_expression(currentmpx,k) end +scan.token = function(k) return scan_token (currentmpx,k) end +scan.symbol = function(k,e) return scan_symbol (currentmpx,k,e) end +scan.numeric = function() return scan_numeric (currentmpx) end +scan.integer = function() return scan_integer (currentmpx) end +scan.boolean = function() return scan_boolean (currentmpx) end +scan.string = function() return scan_string (currentmpx) end +scan.pair = function(t) return scan_pair (currentmpx,t) end +scan.color = function(t) return scan_color (currentmpx,t) end +scan.cmykcolor = function(t) return scan_cmykcolor (currentmpx,t) end +scan.transform = function(t) return scan_transform (currentmpx,t) end +scan.path = function(t) return scan_path (currentmpx,t) end +scan.pen = function(t) return scan_pen (currentmpx,t) end + +local solvepath = mplib.solvepath +local getstatus = mplib.getstatus + +mp.solve = function(...) + return solvepath(currentmpx,...) +end + +local inject_path = mplib.inject_path +local inject_numeric = mplib.inject_numeric +local inject_pair = mplib.inject_pair +local inject_boolean = mplib.inject_boolean +local inject_integer = mplib.inject_integer +local inject_string = mplib.inject_string +local inject_color = mplib.inject_color +local inject_cmykcolor = mplib.inject_cmykcolor +local inject_transform = mplib.inject_transform +local inject_whatever = mplib.inject_whatever + +------.path = function(t,cycle,curled) return inject_path (currentmpx,t,cycle,curled) end +inject.numeric = function(n) return inject_numeric (currentmpx,n) end +inject.pair = function(x,y) return inject_pair (currentmpx,x,y) end +inject.boolean = function(b) return inject_boolean (currentmpx,b) end +inject.integer = function(i) return inject_integer (currentmpx,i) end +inject.string = function(s) return inject_string (currentmpx,s) end +inject.color = function(r,g,b) return inject_color (currentmpx,r,g,b) end +inject.cmykcolor = function(c,m,y,k) return inject_cmykcolor(currentmpx,c,m,y,k) end +inject.transform = function(x,y,xx,xy,yx,yy) return inject_transform(currentmpx,x,y,xx,xy,yx,yy) end +inject.whatever = function(...) return inject_whatever (currentmpx,...) end + +local function same(p,n) + local f = p[1] + local l = p[n] + local nf = #f + local nl = #l + if nf == nl then + for i=1,nf do + if f[i] ~= l[i] then + return false + end + end + return true + end + return false +end + +-- local p = mp.scan.path() +-- mp.inject.path(p,true,true) + +function inject.path(p,close,connector) + local curled = false + local n = #p + if p.close or p.cycle then + close = true + end + if n > 1 then + -- [ ../true | --/false | nil/auto ] + if connector == nil or connector == "auto" then + connector = #p[1] > 2 + end + if connector == false or connector == "--" then + curled = true + elseif connector == true or connector == ".." then + if close and not same(p,n) then + p[n+1] = p[1] + end + end + end + return inject_path(currentmpx,p,close,curled) +end + +-- bonus: + +scan .number = scan .numeric +inject.number = inject.numeric + +table.setmetatablecall(inject,function(t,...) + inject_whatever(currentmpx,...) +end) + +-- experiment + +function mp.autoinject(m) + local t = type(m) + if t == "table" then + local n = #t + if n == 2 then + inject_pair(currentmpx,m) + elseif n == 3 then + inject_color(currentmpx,m) + elseif n == 4 then + inject_cmykcolor(currentmpx,m) + elseif n == 6 then + inject_transform(currentmpx,m) + end + elseif t == "number" then + inject_numeric(currentmpx,m) + elseif t == "string" then + inject_string(currentmpx,m) + elseif t == "boolean" then + inject_boolean(currentmpx,m) + end +end + +function metapost.pushscriptrunner(mpx) + insert(stack,mpx) + currentmpx = mpx +end + +function metapost.popscriptrunner() + currentmpx = remove(stack,mpx) +end + +function metapost.currentmpx() + return currentmpx +end + +-- mplib.getstates(): zero is "normal" + +function metapost.currentmpxstatus() + return getstatus(currentmpx) or 0 +end diff --git a/tex/context/base/mkxl/mlib-mat.lmt b/tex/context/base/mkxl/mlib-mat.lmt new file mode 100644 index 000000000..3a63b32c7 --- /dev/null +++ b/tex/context/base/mkxl/mlib-mat.lmt @@ -0,0 +1,139 @@ +if not modules then modules = { } end modules ['mlib-mat'] = { + 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 scanners = mp.scan +local injectors = mp.inject + +local scannumeric = scanners.numeric +local scanpair = scanners.pair +local scancolor = scanners.color + +local mppair = injectors.pair or mp.pair + +local registerscript = metapost.registerscript + +local m = xmath +local c = xcomplex + +local m_acos = m.acos registerscript("m_acos", function() return m_acos (scannumeric()) end) +local m_acosh = m.acosh registerscript("m_acosh", function() return m_acosh (scannumeric()) end) +local m_asin = m.asin registerscript("m_asin", function() return m_asin (scannumeric()) end) +local m_asinh = m.asinh registerscript("m_asinh", function() return m_asinh (scannumeric()) end) +local m_atan = m.atan registerscript("m_atan", function() return m_atan (scannumeric()) end) +local m_atan2 = m.atan2 registerscript("m_atan2", function() return m_atan2 (scanpair ()) end) +local m_atanh = m.atanh registerscript("m_atanh", function() return m_atanh (scannumeric()) end) +local m_cbrt = m.cbrt registerscript("m_cbrt", function() return m_cbrt (scannumeric()) end) +local m_ceil = m.ceil registerscript("m_ceil", function() return m_ceil (scannumeric()) end) +local m_copysign = m.copysign registerscript("m_copysign", function() return m_copysign (scanpair ()) end) +local m_cos = m.cos registerscript("m_cos", function() return m_cos (scannumeric()) end) +local m_cosh = m.cosh registerscript("m_cosh", function() return m_cosh (scannumeric()) end) +local m_deg = m.deg registerscript("m_deg", function() return m_deg (scannumeric()) end) +local m_erf = m.erf registerscript("m_erf", function() return m_erf (scannumeric()) end) +local m_erfc = m.erfc registerscript("m_erfc", function() return m_erfc (scannumeric()) end) +local m_exp = m.exp registerscript("m_exp", function() return m_exp (scannumeric()) end) +local m_exp2 = m.exp2 registerscript("m_exp2", function() return m_exp2 (scannumeric()) end) +local m_expm1 = m.expm1 registerscript("m_expm1", function() return m_expm1 (scannumeric()) end) +local m_fabs = m.fabs registerscript("m_fabs", function() return m_fabs (scannumeric()) end) +local m_fdim = m.fdim registerscript("m_fdim", function() return m_fdim (scanpair ()) end) +local m_floor = m.floor registerscript("m_floor", function() return m_floor (scannumeric()) end) +local m_fma = m.fma registerscript("m_fma", function() return m_fma (scancolor ()) end) +local m_fmax = m.fmax registerscript("m_fmax", function() return m_fmax (scannumeric()) end) +local m_fmin = m.fmin registerscript("m_fmin", function() return m_fmin (scannumeric()) end) +local m_fmod = m.fmod registerscript("m_fmod", function() return m_fmod (scanpair ()) end) +local m_frexp = m.frexp registerscript("m_frexp", function() return m_frexp (scannumeric()) end) +local m_gamma = m.gamma registerscript("m_gamma", function() return m_gamma (scannumeric()) end) +local m_hypot = m.hypot registerscript("m_hypot", function() return m_hypot (scanpair ()) end) +local m_isfinite = m.isfinite registerscript("m_isfinite", function() return m_isfinite (scannumeric()) end) +local m_isinf = m.isinf registerscript("m_isinf", function() return m_isinf (scannumeric()) end) +local m_isnan = m.isnan registerscript("m_isnan", function() return m_isnan (scannumeric()) end) +local m_isnormal = m.isnormal registerscript("m_isnormal", function() return m_isnormal (scannumeric()) end) +local m_j0 = m.j0 registerscript("m_j0", function() return m_j0 (scannumeric()) end) +local m_j1 = m.j1 registerscript("m_j1", function() return m_j1 (scannumeric()) end) +local m_jn = m.jn registerscript("m_jn", function() return m_jn (scanpair ()) end) +local m_ldexp = m.ldexp registerscript("m_ldexp", function() return m_ldexp (scanpair ()) end) +local m_lgamma = m.lgamma registerscript("m_lgamma", function() return m_lgamma (scannumeric()) end) +local m_log = m.log registerscript("m_log", function() return m_log (scannumeric()) end) +local m_log10 = m.log10 registerscript("m_log10", function() return m_log10 (scannumeric()) end) +local m_log1p = m.log1p registerscript("m_log1p", function() return m_log1p (scannumeric()) end) +local m_log2 = m.log2 registerscript("m_log2", function() return m_log2 (scannumeric()) end) +local m_logb = m.logb registerscript("m_logb", function() return m_logb (scannumeric()) end) +local m_modf = m.modf registerscript("m_modf", function() return m_modf (scannumeric()) end) +local m_nearbyint = m.nearbyint registerscript("m_nearbyint", function() return m_nearbyint(scannumeric()) end) +local m_nextafter = m.nextafter registerscript("m_nextafter", function() return m_nextafter(scanpair ()) end) +local m_pow = m.pow registerscript("m_pow", function() return m_pow (scanpair ()) end) +local m_rad = m.rad registerscript("m_rad", function() return m_rad (scannumeric()) end) +local m_remainder = m.remainder registerscript("m_remainder", function() return m_remainder(scanpair ()) end) +local m_remquo = m.remquo registerscript("m_remquo", function() return m_remquo (scannumeric()) end) +local m_round = m.round registerscript("m_round", function() return m_round (scannumeric()) end) +local m_scalbn = m.scalbn registerscript("m_scalbn", function() return m_scalbn (scanpair ()) end) +local m_sin = m.sin registerscript("m_sin", function() return m_sin (scannumeric()) end) +local m_sinh = m.sinh registerscript("m_sinh", function() return m_sinh (scannumeric()) end) +local m_sqrt = m.sqrt registerscript("m_sqrt", function() return m_sqrt (scannumeric()) end) +local m_tan = m.tan registerscript("m_tan", function() return m_tan (scannumeric()) end) +local m_tanh = m.tanh registerscript("m_tanh", function() return m_tanh (scannumeric()) end) +local m_tgamma = m.tgamma registerscript("m_tgamma", function() return m_tgamma (scannumeric()) end) +local m_trunc = m.trunc registerscript("m_trunc", function() return m_trunc (scannumeric()) end) +local m_y0 = m.y0 registerscript("m_y0", function() return m_y0 (scannumeric()) end) +local m_y1 = m.y1 registerscript("m_y1", function() return m_y1 (scannumeric()) end) +local m_yn = m.yn registerscript("m_yn", function() return m_yn (scanpair ()) end) + +if not (c and c.sin) then + return +end + +local c_topair = c.topair +local c_new = c.new + +local c_sin = c.sin registerscript("c_sin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end) +local c_cos = c.cos registerscript("c_cos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end) +local c_tan = c.tan registerscript("c_tan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end) +local c_sinh = c.sinh registerscript("c_sinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end) +local c_cosh = c.cosh registerscript("c_cosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end) +local c_tanh = c.tanh registerscript("c_tanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end) + +local c_asin = c.asin registerscript("c_asin", function() return mppair(c_topair(c_sin (c_new(scanpair())))) end) +local c_acos = c.acos registerscript("c_acos", function() return mppair(c_topair(c_cos (c_new(scanpair())))) end) +local c_atan = c.atan registerscript("c_atan", function() return mppair(c_topair(c_tan (c_new(scanpair())))) end) +local c_asinh = c.asinh registerscript("c_asinh", function() return mppair(c_topair(c_sinh (c_new(scanpair())))) end) +local c_acosh = c.acosh registerscript("c_acosh", function() return mppair(c_topair(c_cosh (c_new(scanpair())))) end) +local c_atanh = c.atanh registerscript("c_atanh", function() return mppair(c_topair(c_tanh (c_new(scanpair())))) end) + +local c_sqrt = c.sqrt registerscript("c_sqrt", function() return mppair(c_topair(c_sqrt (c_new(scanpair())))) end) +local c_abs = c.abs registerscript("c_abs", function() return c_topair(c_abs (c_new(scanpair()))) end) +local c_arg = c.arg registerscript("c_arg", function() return c_topair(c_arg (c_new(scanpair()))) end) +local c_conj = c.conj registerscript("c_conj", function() return mppair(c_topair(c_conj (c_new(scanpair())))) end) +local c_exp = c.exp registerscript("c_exp", function() return mppair(c_topair(c_exp (c_new(scanpair())))) end) +local c_log = c.log registerscript("c_log", function() return mppair(c_topair(c_log (c_new(scanpair())))) end) +local c_proj = c.proj registerscript("c_proj", function() return mppair(c_topair(c_proj (c_new(scanpair())))) end) + +local c_erf = c.erf registerscript("c_erf", function() return mppair(c_topair(c_erf (c_new(scanpair())))) end) +local c_erfc = c.erfc registerscript("c_erfc", function() return mppair(c_topair(c_erfc (c_new(scanpair())))) end) +local c_erfcx = c.erfcx registerscript("c_erfcx", function() return mppair(c_topair(c_erfcx (c_new(scanpair())))) end) +local c_erfi = c.erfi registerscript("c_erfi", function() return mppair(c_topair(c_erfi (c_new(scanpair())))) end) +local c_dawson = c.dawson registerscript("c_dawson", function() return mppair(c_topair(c_dawson(c_new(scanpair())))) end) + +local c_voigt = c.voigt +local c_voigt_hwhm = c.voigt_hwhm + +registerscript("c_voigt", function() + return mppair(c_topair(c_voigt(c_new(scanpair()),c_new(scanpair()),c_new(scanpair())))) +end) + +registerscript("c_voigt_hwhm", function() + return mppair(c_topair(c_voigt_hwhm(c_new(scanpair()),c_new(scanpair())))) +end) + +local c_pow = c.pow registerscript("c_pow", function() return mppair(c_topair(c_pow(c_new(scanpair()),c_new(scanpair())))) end) +local c_add = c.add registerscript("c_add", function() return mppair(c_topair(c_add(c_new(scanpair()),c_new(scanpair())))) end) +local c_sub = c.sub registerscript("c_sub", function() return mppair(c_topair(c_sub(c_new(scanpair()),c_new(scanpair())))) end) +local c_mul = c.mul registerscript("c_mul", function() return mppair(c_topair(c_mul(c_new(scanpair()),c_new(scanpair())))) end) +local c_div = c.div registerscript("c_div", function() return mppair(c_topair(c_div(c_new(scanpair()),c_new(scanpair())))) end) + +local c_imag = c.imag registerscript("c_imag", function() return c_topair(c_imag(c_new(scanpair()))) end) +local c_real = c.real registerscript("c_real", function() return c_topair(c_real(c_new(scanpair()))) end) +local c_neg = c.neg registerscript("c_new", function() return c_topair(c_neg (c_new(scanpair()))) end) diff --git a/tex/context/base/mkxl/mlib-pdf.mkxl b/tex/context/base/mkxl/mlib-pdf.mkxl new file mode 100644 index 000000000..90a5b5a86 --- /dev/null +++ b/tex/context/base/mkxl/mlib-pdf.mkxl @@ -0,0 +1,162 @@ +%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 + +%D We use bit more code that needed because we want to limit the amount of boxing. + +\registerctxluafile{mlib-pdf}{} + +%D Some code is shared between MPLIB and MPS. The following variables are also +%D 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 + +\permanent\protected\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points + {\global\MPllx #1\onebasepoint + \global\MPlly #2\onebasepoint + \global\MPurx #3\onebasepoint + \global\MPury #4\onebasepoint + \global\MPwidth \dimexpr\MPurx-\MPllx\relax + \global\MPheight\dimexpr\MPury-\MPlly\relax} + +\permanent\protected\def\resetMPboundingbox + {\global\MPwidth \zeropoint + \global\MPheight\zeropoint + \global\MPllx \zeropoint + \global\MPlly \zeropoint + \global\MPurx \zeropoint + \global\MPury \zeropoint} + +\let\popMPboundingbox\relax + +\permanent\protected\def\pushMPboundingbox + {\enforced\permanent\protected\edef\popMPboundingbox + {\global\MPwidth \the\MPwidth + \global\MPheight\the\MPheight + \global\MPllx \the\MPllx + \global\MPlly \the\MPlly + \global\MPurx \the\MPurx + \global\MPury \the\MPury + \relax}} + +% we need to combine these + +\permanent\protected\def\repositionMPboxindeed + {\setbox\MPbox\hpack\bgroup + \kern-\MPllx + \raise-\MPlly + \box\MPbox + \egroup} + +\permanent\protected\def\repositionMPbox + {\ifzeropt\MPllx + \ifzeropt\MPlly + % okay + \else + \repositionMPboxindeed + \fi + \else + \repositionMPboxindeed + \fi} + +% combined + +\permanent\protected\def\finalizeMPbox + {\boxxoffset\MPbox-\MPllx\relax + \boxyoffset\MPbox\dimexpr\boxyoffset\MPbox-\MPheight-\MPlly\relax + \wd\MPbox\MPwidth + \ht\MPbox\MPheight} + +% MPLIB specific: + +\permanent\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded + +\permanent\protected\def\startMPLIBtoPDF#1#2#3#4% + {\meta_process_graphic_figure_start + \dostarttagged\t!mpgraphic\empty + \naturalhpack attr \imageattribute \plusone \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 + +\permanent\protected\def\stopMPLIBtoPDF + {\egroup + \finalizeMPbox + \box\MPbox + \egroup + \dostoptagged + \meta_process_graphic_figure_stop} + +\permanent\protected\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 + +\aliased\let\normalstartMPLIBtoPDF\startMPLIBtoPDF +\aliased\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF + +\permanent\protected\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF} +\permanent\protected\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage} + +% can become \permanent\protected\def\directMPgraphic#=#*#=% but best test first + +\permanent\protected\def\directMPgraphic + {\dodoublegroupempty\mlib_direct_graphic} + +\def\mlib_direct_graphic#1#2% makes pages (todo: make boxes) + {\meta_begin_graphic_group{#1}% + \enforced\let\startMPLIBtoPDF\directstartMPLIBtoPDF + \enforced\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/tex/context/base/mkxl/mlib-pps.mkxl b/tex/context/base/mkxl/mlib-pps.mkxl new file mode 100644 index 000000000..d010d9991 --- /dev/null +++ b/tex/context/base/mkxl/mlib-pps.mkxl @@ -0,0 +1,215 @@ +%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. + +% todo: remove MPenvironment code + +\unprotect + +\registerctxluafile{mlib-pps}{} + +%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 + +\permanent\protected\def\mlib_flush_environment + {%\writestatus\m!metapost{flushing environment}% + \clf_mptexget + \enforced\let\MPLIBflushenvironment\relax}% MPenvironments are depricated} + +\aliased\let\MPLIBflushenvironment\mlib_flush_environment + +\permanent\protected\def\MPLIBsetNtext#1% #2% box text + {\MPLIBflushenvironment + \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text + \meta_set_current_color + \enforced\let\MPLIBflushenvironment\mlib_flush_environment + \let\next} % gobble open brace + +\permanent\protected\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 ! + \enforced\let\MPLIBflushenvironment\mlib_flush_environment + \let\next} % gobble open brace + +\aliased\let\MPLIBsettext\MPLIBsetNtext + +\permanent\protected\def\MPLIBsetNtextX#1% #2% box text + {\MPLIBflushenvironment + \hbox\bgroup % text + \meta_set_current_color + \enforced\let\MPLIBflushenvironment\mlib_flush_environment + \let\next} + +\permanent\protected\def\MPLIBsetCtextX#1#2% #3% box colorspec text + {\MPLIBflushenvironment + \hbox\bgroup % text + \directcolored[#2]% + \meta_set_current_color % so, textcolor wins ! + \enforced\let\MPLIBflushenvironment\mlib_flush_environment + \let\next} + +\aliased\let\MPLIBsettextX\MPLIBsetNtextX + +\permanent\permanent\protected\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}}} + +\permanent\protected\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{\fastsxsy{\mlib_sx}{\mlib_sy}{\box\scratchbox}\hss}}} + +% horrible (we could inline scale and matrix code): + +\permanent\protected\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} + +% \putnextboxincache{hans}{1}\hbox{foo} +% +% \startMPcode +% draw boundingbox rawtexbox("hans",1) ; +% draw rawtexbox("hans",1) ; +% \stopMPcode + +\permanent\protected\def\MPLIBgetboxscaledcm#1#2% + {\begingroup + \copyboxfromcache{#1}{#2}\MPtextbox % can be \clf_ + \mlib_get_box_scaled_cm_next} + +\protected\def\mlib_get_box_scaled_cm_next#1#2#3#4#5#6#7#8% 1-6: sx,rx,ry,sy,tx,ty + {\setbox\MPbox\hpack\bgroup + \dotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}% + \vpack to \zeropoint\bgroup + \vss + \hpack to \zeropoint \bgroup + \fastsxsy{#7}{#8}{\raise\dp\MPtextbox\box\MPtextbox}% + \hss + \egroup + \egroup + \egroup + \smashbox\MPbox + \box\MPbox + \endgroup} + +\permanent\protected\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 + +\permanent\protected\def\MPLIBpositionwhd#1#2#3#4#5% bp ! + {\dosavepositionwhd{#1}\zerocount{#2\onebasepoint}{#3\onebasepoint}{#4\onebasepoint}{#5\onebasepoint}\zeropoint} + +\def\mlib_stop_group#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 + \setbox\scratchbox\hpack\bgroup + \kern-#3\onebasepoint + \box\scratchbox + \egroup + \saveboxresource + attr {/Group << /S /Transparency /I \ifnum#1=1 true \else false \fi /K \ifnum#2=1 true \else false \fi >>} + resources {\pdfbackendcurrentresources} + \scratchbox + \setbox\scratchbox\hpack\bgroup + \kern#3\onebasepoint + \kern-\onebasepoint + \useboxresource\lastsavedboxresourceindex + \egroup + \wd\scratchbox\zeropoint + \ht\scratchbox\zeropoint + \dp\scratchbox\zeropoint + \box\scratchbox + \endgroup} + +\aliased\let\MPLIBstopgroup\relax + +\permanent\protected\def\MPLIBstartgroup#1#2#3#4#5#6% isolated 0/1, knockout 0/1 llx lly urx ury + {\begingroup + \setbox\scratchbox\hpack\bgroup + \enforced\permanent\protected\def\MPLIBstopgroup{\mlib_stop_group{#1}{#2}{#3}{#4}{#5}{#6}}} + +% For now here ... will be cleaned up: + +\newtoks\mptexttoks +\newbox \mptextbox +\newtoks\mpoutlinetoks +\newtoks\mpgraphictexttoks + +\mptexttoks {\global\setbox\mptextbox\hbox{\clf_mptexttoks}} +\mpoutlinetoks {\global\setbox\mptextbox\vbox{\clf_mpoutlinetoks}} +\mpgraphictexttoks{\global\setbox\mptextbox\vbox{\clf_mpgraphictexttoks}} + +\protect \endinput diff --git a/tex/context/base/mkxl/mlib-ran.lmt b/tex/context/base/mkxl/mlib-ran.lmt new file mode 100644 index 000000000..cb8645e8d --- /dev/null +++ b/tex/context/base/mkxl/mlib-ran.lmt @@ -0,0 +1,237 @@ +if not modules then modules = { } end modules ['mlib-ran'] = { + 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 next = next +local ceil, floor, random, sqrt, cos, sin, pi, max, min = math.ceil, math.floor, math.random, math.sqrt, math.cos, math.sin, math.pi, math.min, math.max +local remove = table.remove + +-- Below is a bit of rainy saturday afternoon hobyism, while listening to Judith +-- Owens redisCOVERed (came there via Leland Sklar who I have on a few live blurays; +-- and who is also on YT). (Also nice: https://www.youtube.com/watch?v=GXqasIRaxlA) + +-- When Aditya pointed me to an article on mazes I ended up at poison distributions +-- which to me looks nicer than what I normally do, fill a grid and then randomize +-- the resulting positions. With some hooks this can be used for interesting patterns +-- too. A few links: +-- +-- https://bost.ocks.org/mike/algorithms/#maze-generation +-- https://extremelearning.com.au/ +-- https://www.jasondavies.com/maps/random-points/ +-- http://devmag.org.za/2009/05/03/poisson-disk-sampling + +-- The next function is quite close to what us discribed in the poisson-disk-sampling +-- link mentioned before. One can either use a one dimensional grid array or a two +-- dimensional one. The example code uses some classes dealing with points. In the +-- process I added some more control. + +-- we could do without the samplepoints list + +local function poisson(width, height, mindist, newpointscount, initialx, initialy) + local starttime = os.clock() + local cellsize = mindist / sqrt(2) + local nofwidth = ceil(width // cellsize) + local nofheight = ceil(height // cellsize) + local grid = lua.newtable(nofwidth,0) -- table.setmetatableindex("table") + local firstx = initialx or random() * width + local firsty = initialy or random() * height + local firstpoint = { firstx, firsty, 1 } + -- local samplepoints = { firstpoint } + local processlist = { firstpoint } + local nofprocesslist = 1 + local nofsamplepoints = 1 + local twopi = 2 * pi + + for i=1,nofwidth do + local g = lua.newindex(nofheight,false) + grid[i] = g + end + + local x = floor(firstx // cellsize) + 1 -- lua indices + local y = floor(firsty // cellsize) + 1 -- lua indices + + x = max(1, min(x, width - 1)) + y = max(1, min(y, height - 1)) + + grid[x][y] = firstpoint + + -- The website shows graphic for this 5*5 grid snippet, if we use a one dimentional + -- array then we could have one loop; a first version used a metatable trick so we + -- had grid[i+gx][j+gy] but we no we also return the grid, so ... we now just check. + + -- There is no need for the samplepoints list as we can get that from the grid but + -- instead we can store the index with the grid. + + while nofprocesslist > 0 do + local point = remove(processlist,random(1,nofprocesslist)) + nofprocesslist = nofprocesslist - 1 + for i=1,newpointscount do -- we start at 1 + local radius = mindist * (random() + 1) + local angle = twopi * random() + local nx = point[1] + radius * cos(angle) + local ny = point[2] + radius * sin(angle) + if nx > 1 and ny > 1 and nx <= width and ny <= height then -- lua indices + local gx = floor(nx // cellsize) + local gy = floor(ny // cellsize) + -- the 5x5 cells around the point + for i=-2,2 do + for j=-2,2 do + local cell = grid[i + gx] + if cell then + cell = cell[j + gy] + if cell and sqrt((cell[1] - nx)^2 + (cell[2] - ny)^2) < mindist then + goto next + end + end + end + end + -- local newpoint = { nx, ny } + nofprocesslist = nofprocesslist + 1 + nofsamplepoints = nofsamplepoints + 1 + local newpoint = { nx, ny, nofsamplepoints } + processlist [nofprocesslist] = newpoint + -- samplepoints[nofsamplepoints] = newpoint + grid[gx][gy] = newpoint + end + ::next:: + end + end + + return { + count = nofsamplepoints, + -- points = samplepoints, + grid = grid, + time = os.clock() - starttime, + } +end + +-- For now: + +local randomizers = utilities.randomizers or { } +utilities.randomizers = randomizers +randomizers.poisson = poisson + +-- The MetaFun interface: + +local formatters = string.formatters +local concat = table.concat + +local f_macro = formatters["%s(%N,%N);"] + +local f_macros = { + [2] = formatters["%s(%N,%N);"], + [3] = formatters["%s(%N,%N,%i);"], + [4] = formatters["%s(%N,%N,%i,%i);"], +} + +function grid_to_mp(t,f,n) + local grid = t.grid + local count = t.count + local result = { } + local r = 0 + local macro = f or "draw" + local runner = f_macros[n or 2] or f_macros[2] + for i=1,#grid do + local g = grid[i] + if g then + for j=1,#g do + local v = g[j] + if v then + r = r + 1 + result[r] = runner(macro,v[1],v[2],v[3],count) + end + end + end + end + return concat(result, " ") +end + +local getparameter = metapost.getparameter + +local function lmt_poisson() + local initialx = getparameter { "initialx" } + local initialy = getparameter { "initialy" } + local width = getparameter { "width" } + local height = getparameter { "height" } + local distance = getparameter { "distance" } + local count = getparameter { "count" } + + local result = poisson ( + width, height, distance, count, + initialx > 0 and initialx or false, + initialy > 0 and initialy or false + ) + + if result then + logs.report("poisson","w=%N, h=%N, d=%N, c=%N, n=%i, runtime %.3f", + width, height, distance, count, result.count, result.time + ) + end + + return result +end + +function mp.lmt_poisson_generate() + local result = lmt_poisson() + if result then + return grid_to_mp ( + result, + getparameter { "macro" }, + getparameter { "arguments" } + ) + end +end + +-- -- some playing around showed no benefit +-- +-- function points_to_mp(t,f) +-- local points = t.points +-- local count = t.count +-- local result = { } +-- local r = 0 +-- local macro = f or "draw" +-- local runner = f_macros[n or 2] or f_macros[2] +-- for i=1,count do +-- local v = points[i] +-- r = r + 1 +-- result[r] = runner(macro,v[1],v[2],v[3],count) +-- end +-- return concat(result, " ") +-- end +-- +-- local result = false +-- local i, j, n = 0, 0, 0 +-- +-- function mp.lmt_poison_start() +-- result = lmt_poisson() +-- end +-- +-- function mp.lmt_poisson_stop() +-- result = false +-- end +-- +-- function mp.lmt_poisson_count() +-- return result and result.count or 0 +-- end +-- +-- function mp.lmt_poisson_get(i) +-- if result then +-- return mp.pair(result.points[i]) +-- end +-- end +-- +-- function mp.lmt_poisson_generate() +-- mp.lmt_poisson_start() +-- if result then +-- return grid_to_mp ( +-- result, +-- getparameter { "macro" }, +-- getparameter { "arguments" } +-- ) +-- end +-- mp.lmt_poisson_stop() +-- end diff --git a/tex/context/base/mkxl/mlib-scn.lmt b/tex/context/base/mkxl/mlib-scn.lmt new file mode 100644 index 000000000..ff1cff0e3 --- /dev/null +++ b/tex/context/base/mkxl/mlib-scn.lmt @@ -0,0 +1,780 @@ +if not modules then modules = { } end modules ['mlib-scn'] = { + 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", +} + +-- Very experimental, for Alan and me. + +-- for i = 1 upto 32000 : % 0.062 +-- ts := 5mm / 20; +-- endfor ; +-- +-- for i = 1 upto 32000 : % 0.219 +-- ts := (getparameter "axis" "sy") / 20; +-- endfor ; +-- +-- for i = 1 upto 32000 : % 0.266 +-- ts := (getparameterx "axis" "sy") / 20; +-- endfor ; +-- +-- pushparameters "axis"; +-- for i = 1 upto 32000 : % 0.250 +-- ts := (getparameterx "sy") / 20; +-- endfor ; +-- popparameters; + +local type, next, rawget, getmetatable = type, next, rawget, getmetatable +local byte, gmatch = string.byte, string.gmatch +local insert, remove = table.insert, table.remove + +local mplib = mplib +local metapost = metapost + +local codes = mplib.getcodes() +local types = mplib.gettypes() + +table.hashed(codes) +table.hashed(types) + +metapost.codes = codes +metapost.types = types + +local setmetatableindex = table.setmetatableindex + +local scanners = mp.scan +local injectors = mp.inject + +local scannext = scanners.next +local scanexpression = scanners.expression +local scantoken = scanners.token +local scansymbol = scanners.symbol +local scannumeric = scanners.numeric +local scannumber = scanners.number +local scaninteger = scanners.integer +local scanboolean = scanners.boolean +local scanstring = scanners.string +local scanpair = scanners.pair +local scancolor = scanners.color +local scancmykcolor = scanners.cmykcolor +local scantransform = scanners.transform +local scanpath = scanners.path +local scanpen = scanners.pen + +local mpprint = mp.print +local injectnumeric = injectors.numeric +local injectstring = injectors.string +local injectboolean = injectors.boolean +local injectpair = injectors.pair +local injecttriplet = injectors.color +local injectquadruple = injectors.cmykcolor +local injecttransform = injectors.transform +local injectpath = injectors.path + +local report = logs.reporter("metapost") + +local semicolon_code = codes.semicolon +local equals_code = codes.equals +local comma_code = codes.comma +local colon_code = codes.colon +local leftbrace_code = codes.leftbrace +local rightbrace_code = codes.rightbrace +local leftbracket_code = codes.leftbracket +local rightbracket_code = codes.rightbracket +local leftdelimiter_code = codes.leftdelimiter +local rightdelimiter_code = codes.rightdelimiter +local numeric_code = codes.numeric +local string_code = codes.string +local capsule_code = codes.capsule +local nullary_code = codes.nullary +local tag_code = codes.tag +local definedmacro_code = codes.definedmacro + +local typescanners = nil +local tokenscanners = nil +local scanset = nil +local scanparameters = nil + +scanset = function() -- can be optimized, we now read twice + scantoken() + if scantoken(true) == rightbrace_code then + scantoken() + return { } + else + local l = { } + local i = 0 + while true do + i = i + 1 + local s = scansymbol(true) + if s == "{" then + l[i] = scanset() + elseif s == "[" then + local d = { } + scansymbol() + while true do + local s = scansymbol() + if s == "]" then + break; + elseif s == "," then + -- continue + else + local t = scantoken(true) + if t == equals_code or t == colon_code then + scantoken() + end + d[s] = tokenscanners[scantoken(true)]() + end + end + l[i] = d + else + local e = scanexpression(true) + l[i] = (typescanners[e] or scanexpression)() + end + if scantoken() == rightbrace_code then + break + else + -- whatever + end + end + return l + end +end + +local function scan_pair () return scanpair (true) end +local function scan_color () return scancolor (true) end +local function scan_cmykcolor() return scancmykcolor(true) end +local function scan_transform() return scantransform(true) end + +tokenscanners = { + [leftbrace_code] = scanset, + [numeric_code] = scannumeric, + [string_code] = scanstring, + [nullary_code] = scanboolean, -- todo +} + +typescanners = { + [types.known] = scannumeric, + [types.numeric] = scannumeric, + [types.string] = scanstring, + [types.boolean] = scanboolean, + [types.pair] = scan_pair, + [types.color] = scan_color, + [types.cmykcolor] = scan_cmykcolor, + [types.transform] = scan_transform, + [types.path] = scanpath, + [types.pen] = scanpen, +} + +table.setmetatableindex(tokenscanners,function() + local e = scanexpression(true) + return typescanners[e] or scanexpression +end) + +-- a key like 'color' has code 'declare' + +local function scanparameters(fenced) + local data = { } + local close = "]" + if not fenced then + close = ";" + elseif scansymbol(true) == "[" then + scansymbol() + else + return data + end + while true do + -- local s = scansymbol() + local s = scansymbol(false,false) + if s == close then + break; + elseif s == "," then + -- continue + else + local t = scantoken(true) + if t == equals_code or t == colon_code then + -- optional equal or : + scantoken() + end + local kind = scantoken(true) + if kind == leftdelimiter_code or kind == tag_code or kind == capsule_code then + kind = scanexpression(true) + data[s] = (typescanners[kind] or scanexpression)() + elseif kind == leftbracket_code then + data[s] = get_parameters(true) + else + data[s] = tokenscanners[kind]() + end + end + end + return data +end + +local namespaces = { } +local presets = { } +local passed = { } + +local function get_parameters(nested) + local data = { } + if nested or scansymbol(true) == "[" then + scansymbol() + else + return data + end + while true do + local s = scansymbol(false,false) + if s == "]" then + break; + elseif s == "," then + -- continue + else + local t = scantoken(true) + if t == equals_code or t == colon_code then + -- optional equal or : + scantoken() + end + local kind = scantoken(true) + if kind == leftdelimiter_code or kind == tag_code or kind == capsule_code then + kind = scanexpression(true) + data[s] = (typescanners[kind] or scanexpression)() + elseif kind == leftbracket_code then + data[s] = get_parameters(true) + else + data[s] = tokenscanners[kind]() + end + end + end + return data +end + +local function getparameters() + local namespace = scanstring() + -- same as below + local parameters = get_parameters() + local presets = presets[namespace] + local passed = passed[namespace] + if passed then + if presets then + setmetatableindex(passed,presets) + end + setmetatableindex(parameters,passed) + elseif presets then + setmetatableindex(parameters,presets) + end + namespaces[namespace] = parameters + -- +end + +local function applyparameters() + local saved = namespaces + local namespace = scanstring() + local action = scanstring() -- before we scan the parameters + -- same as above + local parameters = get_parameters() + local presets = presets[namespace] + local passed = passed[namespace] + if passed then + if presets then + setmetatableindex(passed,presets) + end + setmetatableindex(parameters,passed) + elseif presets then + setmetatableindex(parameters,presets) + end + namespaces[namespace] = parameters + -- till here + mpprint(action) + namespaces = saved +end + +local function presetparameters() + local namespace = scanstring() + local parent = nil + local t = scantoken(true) + if t == string_code then + parent = presets[scanstring()] + end + local p = get_parameters() + if parent then + setmetatableindex(p,parent) + end + presets[namespace] = p +end + +local function collectnames() + local l = { } -- can be reused but then we can't nest + local n = 0 + while true do + local t = scantoken(true) + -- (1) not really needed + if t == numeric_code then + n = n + 1 l[n] = scaninteger(1) + elseif t == string_code then + n = n + 1 l[n] = scanstring(1) + elseif t == nullary_code then + n = n + 1 l[n] = scanboolean(1) + elseif t == leftbracket_code then + scantoken() -- leftbacket + n = n + 1 l[n] = scaninteger(1) + scantoken() -- rightbacket + elseif t == leftdelimiter_code or t == tag_code or t == capsule_code then + t = scanexpression(true) + n = n + 1 l[n] = (typescanners[t] or scanexpression)() + else + break + end + end + return l, n +end + +local function get(v) + local t = type(v) + if t == "number" then + return injectnumeric(v) + elseif t == "boolean" then + return injectboolean(v) + elseif t == "string" then + return injectstring(v) + elseif t == "table" then + local n = #v + if type(v[1]) == "table" then + return injectpath(v) + elseif n == 2 then + return injectpair(v) + elseif n == 3 then + return injecttriplet(v) + elseif n == 4 then + return injectquadruple(v) + elseif n == 6 then + return injecttransform(v) + end + end + return injectnumeric(0) +end + +local stack = { } + +local function pushparameters() + local l, n = collectnames() + insert(stack,namespaces) + for i=1,n do + local n = namespaces[l[i]] + if type(n) == "table" then + namespaces = n + else + break + end + end +end + +local function popparameters() + local n = remove(stack) + if n then + namespaces = n + else + report("stack error") + end +end + +-- todo: + +local function getparameter() + local list, n = collectnames() + local v = namespaces + for i=1,n do + local l = list[i] + local vl = v[l] + if vl == nil then + if type(l) == "number" then + vl = v[1] + if vl == nil then + return injectnumeric(0) + end + else + return injectnumeric(0) + end + end + v = vl + end + if v == nil then + return injectnumeric(0) + else + return get(v) + end +end + +local function hasparameter() + local list, n = collectnames() + local v = namespaces + for i=1,n do + local l = list[i] + local vl = rawget(v,l) + if vl == nil then + if type(l) == "number" then + vl = rawget(v,1) + if vl == nil then + return injectboolean(false) + end + else + return injectboolean(false) + end + end + v = vl + end + if v == nil then + return injectboolean(false) + else + return injectboolean(true) + end +end + +local function hasoption() + local list, n = collectnames() + if n > 1 then + local v = namespaces + if n > 2 then + for i=1,n-1 do + local l = list[i] + local vl = v[l] + if vl == nil then + return injectboolean(false) + end + v = vl + end + else + v = v[list[1]] + end + if type(v) == "string" then + -- no caching .. slow anyway + local o = list[n] + if v == o then + return injectboolean(true) + end + for vv in gmatch(v,"[^%s,]+") do + for oo in gmatch(o,"[^%s,]+") do + if vv == oo then + return injectboolean(true) + end + end + end + end + end + return injectboolean(false) +end + +local function getparameterdefault() + local list, n = collectnames() + local v = namespaces + if n == 1 then + local l = list[1] + local vl = v[l] + if vl == nil then + -- maybe backtrack + local top = stack[#stack] + if top then + vl = top[l] + end + end + if vl == nil then + return injectnumeric(0) + else + return get(vl) + end + else + for i=1,n-1 do + local l = list[i] + local vl = v[l] + if vl == nil then + if type(l) == "number" then + vl = v[1] + if vl == nil then + return get(list[n]) + end + else + local last = list[n] + if last == "*" then + -- so, only when not pushed + local m = getmetatable(namespaces[list[1]]) + if n then + m = m.__index -- can also be a _m_ + end + if m then + local v = m + for i=2,n-1 do + local l = list[i] + local vl = v[l] + if vl == nil then + return injectnumeric(0) + end + v = vl + end + if v == nil then + return injectnumeric(0) + else + return get(v) + end + end + return injectnumeric(0) + else + return get(last) + end + end + end + v = vl + end + if v == nil then + return get(list[n]) + else + return get(v) + end + end +end + +local function getparametercount() + local list, n = collectnames() + local v = namespaces + for i=1,n do + v = v[list[i]] + if not v then + break + end + end + return injectnumeric(type(v) == "table" and #v or 0) +end + +local function getmaxparametercount() + local list, n = collectnames() + local v = namespaces + for i=1,n do + v = v[list[i]] + if not v then + break + end + end + local n = 0 + if type(v) == "table" then + local v1 = v[1] + if type(v1) == "table" then + n = #v1 + for i=2,#v do + local vi = v[i] + if type(vi) == "table" then + local vn = #vi + if vn > n then + n = vn + end + else + break; + end + end + end + + end + return injectnumeric(n) +end + +local validconnectors = { + [".."] = true, + ["..."] = true, + ["--"] = true, +} + +local function getparameterpath() + local list, n = collectnames() + local close = list[n] + if type(close) == "boolean" then + n = n - 1 + else + close = false + end + local connector = list[n] + if type(connector) == "string" and validconnectors[connector] then + n = n - 1 + else + connector = "--" + end + local v = namespaces + for i=1,n do + v = v[list[i]] + if not v then + break + end + end + if type(v) == "table" then + return injectpath(v,connector,close) + else + return injectpair(0,0) + end +end + +local function getparameterpen() + local list, n = collectnames() + local v = namespaces + for i=1,n do + v = v[list[i]] + if not v then + break + end + end + if type(v) == "table" then + return injectpath(v,"..",true) + else + return injectpair(0,0) + end +end + +local function getparametertext() + local list, n = collectnames() + local strut = list[n] + if type(strut) == "boolean" then + n = n - 1 + else + strut = false + end + local v = namespaces + for i=1,n do + v = v[list[i]] + if not v then + break + end + end + if type(v) == "string" then + return injectstring("\\strut " .. v) + else + return injectstring("") + end +end + +-- local function getparameteroption() +-- local list, n = collectnames() +-- local last = list[n] +-- if type(last) == "string" then +-- n = n - 1 +-- else +-- return false +-- end +-- local v = namespaces +-- for i=1,n do +-- v = v[list[i]] +-- if not v then +-- break +-- end +-- end +-- if type(v) == "string" and v ~= "" then +-- for s in gmatch(v,"[^ ,]+") do +-- if s == last then +-- return true +-- end +-- end +-- end +-- return false +-- end + +function metapost.scanparameters() +-- scantoken() -- we scan the semicolon + return get_parameters() +end + +metapost.registerscript("getparameters", getparameters) +metapost.registerscript("applyparameters", applyparameters) +metapost.registerscript("presetparameters", presetparameters) +metapost.registerscript("hasparameter", hasparameter) +metapost.registerscript("hasoption", hasoption) +metapost.registerscript("getparameter", getparameter) +metapost.registerscript("getparameterdefault", getparameterdefault) +metapost.registerscript("getparametercount", getparametercount) +metapost.registerscript("getmaxparametercount",getmaxparametercount) +metapost.registerscript("getparameterpath", getparameterpath) +metapost.registerscript("getparameterpen", getparameterpen) +metapost.registerscript("getparametertext", getparametertext) +--------.registerscript("getparameteroption", getparameteroption) +metapost.registerscript("pushparameters", pushparameters) +metapost.registerscript("popparameters", popparameters) + +function metapost.getparameter(list) + local n = #list + local v = namespaces + for i=1,n do + local l = list[i] + local vl = v[l] + if vl == nil then + return + end + v = vl + end + return v +end + +function metapost.getparameterset(namespace) + return namespace and namespaces[namespace] or namespaces +end + +function metapost.setparameterset(namespace,t) + namespaces[namespace] = t +end + +-- goodies + +metapost.registerscript("definecolor", function() + scantoken() -- we scan the semicolon + local s = get_parameters() + attributes.colors.defineprocesscolordirect(s) +end) + +-- tex scanners + +local scanners = tokens.scanners +local scanhash = scanners.hash +local scanstring = scanners.string +local scanvalue = scanners.value +local scaninteger = scanners.integer +local scanboolean = scanners.boolean +local scanfloat = scanners.float +local scandimension = scanners.dimension + +local definitions = { } + +local bpfactor = number.dimenfactors.bp +local comma = byte(",") +local close = byte("]") + +local scanrest = function() return scanvalue(comma,close) or "" end +local scandimension = function() return scandimension() * bpfactor end + +local scanners = { + ["integer"] = scaninteger, + ["number"] = scanfloat, + ["numeric"] = scanfloat, + ["boolean"] = scanboolean, + ["string"] = scanrest, + ["dimension"] = scandimension, +} + +interfaces.implement { + name = "lmt_parameters_define", + arguments = "string", + actions = function(namespace) + local d = scanhash() + for k, v in next, d do + d[k] = scanners[v] or scanrest + end + definitions[namespace] = d + end, +} + +interfaces.implement { + name = "lmt_parameters_preset", + arguments = "string", + actions = function(namespace) + passed[namespace] = scanhash(definitions[namespace]) + end, +} + +interfaces.implement { + name = "lmt_parameters_reset", + arguments = "string", + actions = function(namespace) + passed[namespace] = nil + end, +} diff --git a/tex/context/base/mkxl/mlib-svg.lmt b/tex/context/base/mkxl/mlib-svg.lmt new file mode 100644 index 000000000..4c4122476 --- /dev/null +++ b/tex/context/base/mkxl/mlib-svg.lmt @@ -0,0 +1,3277 @@ +if not modules then modules = { } end modules ['mlib-svg'] = { + version = 1.001, + optimize = true, + 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", +} + +-- Just a few notes: +-- +-- There is no real need to boost performance here .. we can always make a fast +-- variant when really needed. I will also do some of the todo's when I run into +-- proper fonts. I need to optimize this a bit but will do that once I'm satisfied +-- with the outcome and don't need more hooks and plugs. At some point I will +-- optimize the MetaPost part because now we probably have more image wrapping +-- than needed. +-- +-- As usual with these standards, things like a path can be very compact while the +-- rest is very verbose which defeats the point. This is a first attempt. There will +-- be a converter to MP as well as directly to PDF. This module was made for one of +-- the dangerous curves talks at the 2019 CTX meeting. I will do the font when I +-- need it (not that hard). +-- +-- The fact that in the more recent versions of SVG the older text related elements +-- are depricated and not even supposed to be supported, combined with the fact that +-- the text element assumes css styling, demonstrates that there is not so much as a +-- standard. It basically means that whatever technology dominates at some point +-- (probably combined with some libraries that at that point exist) determine what +-- is standard. Anyway, it probably also means that these formats are not that +-- suitable for long term archival purposes. So don't take the next implementation +-- too serious. So in the end we now have (1) attributes for properties (which is +-- nice and clean and what attributes are for, (2) a style attribute that needs to +-- be parsed, (3) classes that map to styles and (4) element related styles, plus a +-- kind of inheritance (given the limited number of elements sticking to only as +-- wrapper would have made much sense. Anyway, we need to deal with it. With all +-- these style things going on, one can wonder where it will end. Basically svg +-- became just a html element that way and less clean too. The same is true for +-- tspan, which means that text itself is nested xml. +-- +-- We can do a direct conversion to PDF but then we also loose the abstraction which +-- in the future will be used, and for fonts we need to spawn out to TeX anyway, so +-- the little overhead of calling MetaPost is okay I guess. Also, we want to +-- overload labels, share fonts with the main document, etc. and are not aiming at a +-- general purpose SVG converter. For going to PDF one can just use InkScape. +-- +-- Written with Anne Clark on speakers as distraction. +-- +-- Todo when I run into an example (but ony when needed and reasonable): +-- +-- var(color,color) +-- --color +-- currentColor : when i run into an example +-- a bit more shading +-- clip = [ auto | rect(llx,lly,urx,ury) ] (in svg) +-- xlink url ... whatever +-- masks +-- opacity per group (i need to add that to metafun first, inefficient pdf but +-- maybe filldraw can help here) +-- +-- Maybe in metafun: +-- +-- penciled n -> withpen pencircle scaled n +-- applied (...) -> transformed bymatrix (...) +-- withopacity n -> withtransparency (1,n) + +-- When testing mbo files: +-- +-- empty paths +-- missing control points +-- funny fontnames like abcdefverdana etc +-- paths representing glyphs but also with style specs +-- all kind of attributes +-- very weird and inefficient shading + +-- One can run into pretty crazy images, like lines that are fills being clipped +-- to some width. That's the danger of hiding yourself behind an interface I guess. + +local rawget, rawset, type, tonumber, tostring, next, setmetatable = rawget, rawset, type, tonumber, tostring, next, setmetatable + +local P, S, R, C, Ct, Cs, Cc, Cp, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cg, lpeg.Cf, lpeg.Carg + +local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local sqrt, abs = math.sqrt, math.abs +local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash +local gmatch, gsub, find, match, rep = string.gmatch, string.gsub, string.find, string.match, string.rep +local formatters, fullstrip = string.formatters, string.fullstrip +local utfsplit, utfbyte = utf.split, utf.byte + +local xmlconvert, xmlcollected, xmlcount, xmlfirst, xmlroot = xml.convert, xml.collected, xml.count, xml.first, xml.root +local xmltext, xmltextonly = xml.text, xml.textonly +local css = xml.css or { } -- testing + +local function xmlinheritattributes(c,pa) + local at = c.at + local dt = c.dt + if at and dt then + if pa then + setmetatableindex(at,pa) + end + for i=1,#dt do + local dti = dt[i] + if type(dti) == "table" then + xmlinheritattributes(dti,at) + end + end + else + -- comment of so + end +end + +xml.inheritattributes = xmlinheritattributes + +-- Maybe some day helpers will move to the metapost.svg namespace! + +metapost = metapost or { } +local metapost = metapost +local context = context + +local report = logs.reporter("metapost","svg") + +local trace = false trackers.register("metapost.svg", function(v) trace = v end) +local trace_text = false trackers.register("metapost.svg.text", function(v) trace_text = v end) +local trace_path = false trackers.register("metapost.svg.path", function(v) trace_path = v end) +local trace_result = false trackers.register("metapost.svg.result", function(v) trace_result = v end) +local trace_colors = false trackers.register("metapost.svg.colors", function(v) trace_colors = v end) + +local pathtracer = { + ["stroke"] = "darkred", + ["stroke-opacity"] = ".5", + ["stroke-width"] = ".5", + ["fill"] = "darkgray", + ["fill-opacity"] = ".75", +} + +-- This is just an experiment. Todo: reset hash etc. Also implement +-- an option handler. + +local svghash = false do + + local svglast = 0 + local svglist = false + + local function checkhash(t,k) + local n = svglast + 1 + svglast = n + svglist[n] = k + t[k] = n + return n + end + + function metapost.startsvghashing() + svglast = 0 + svglist = { } + svghash = setmetatableindex(checkhash) + end + + function metapost.stopsvghashing() + svglast = 0 + svglist = false + svghash = false + end + + interfaces.implement { + name = "svghashed", + arguments = "integer", + actions = function(n) + local t = svglist and svglist[n] + if t then + context(t) + end + end + } + +end + +-- We have quite some closures because otherwise we run into the local variable +-- limitations. It doesn't always look pretty now, sorry. I'll clean up this mess +-- some day (the usual nth iteration of code). +-- +-- Most of the conversion is rather trivial code till I ran into a file with arcs. A +-- bit of searching lead to the a2c javascript function but it has some puzzling +-- thingies (like sin and cos definitions that look like leftovers and possible +-- division by zero). Anyway, we can if needed optimize it a bit more. Here does it +-- come from: + +-- http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes +-- https://github.com/adobe-webplatform/Snap.svg/blob/b242f49e6798ac297a3dad0dfb03c0893e394464/src/path.js + +local a2c do + + local pi, sin, cos, tan, asin, abs = math.pi, math.sin, math.cos, math.tan, math.asin, math.abs + + local d120 = (pi * 120) / 180 + local pi2 = 2 * pi + + a2c = function(x1, y1, rx, ry, angle, large, sweep, x2, y2, f1, f2, cx, cy) + + if (rx == 0 or ry == 0 ) or (x1 == x2 and y1 == y2) then + return { x1, y1, x2, y2, x2, y2 } + end + + local recursive = f1 + local rad = pi / 180 * angle + local res = nil + local cosrad = cos(-rad) -- local cosrad = cosd(angle) + local sinrad = sin(-rad) -- local sinrad = sind(angle) + + if not recursive then + + x1, y1 = x1 * cosrad - y1 * sinrad, x1 * sinrad + y1 * cosrad + x2, y2 = x2 * cosrad - y2 * sinrad, x2 * sinrad + y2 * cosrad + + local x = (x1 - x2) / 2 + local y = (y1 - y2) / 2 + local xx = x * x + local yy = y * y + local h = xx / (rx * rx) + yy / (ry * ry) + + if h > 1 then + h = sqrt(h) + rx = h * rx + ry = h * ry + end + + local rx2 = rx * rx + local ry2 = ry * ry + local ry2xx = ry2 * xx + local rx2yy = rx2 * yy + local total = rx2yy + ry2xx -- otherwise overflow + + local k = total == 0 and 0 or sqrt(abs((rx2 * ry2 - rx2yy - ry2xx) / total)) + + if large == sweep then + k = -k + end + + cx = k * rx * y / ry + (x1 + x2) / 2 + cy = k * -ry * x / rx + (y1 + y2) / 2 + + f1 = (y1 - cy) / ry -- otherwise crash on a tiny eps + f2 = (y2 - cy) / ry -- otherwise crash on a tiny eps + + f1 = asin((f1 < -1.0 and -1.0) or (f1 > 1.0 and 1.0) or f1) + f2 = asin((f2 < -1.0 and -1.0) or (f2 > 1.0 and 1.0) or f2) + + if x1 < cx then f1 = pi - f1 end + if x2 < cx then f2 = pi - f2 end + + if f1 < 0 then f1 = pi2 + f1 end + if f2 < 0 then f2 = pi2 + f2 end + + if sweep ~= 0 and f1 > f2 then f1 = f1 - pi2 end + if sweep == 0 and f2 > f1 then f2 = f2 - pi2 end + + end + + if abs(f2 - f1) > d120 then + local f2old = f2 + local x2old = x2 + local y2old = y2 + f2 = f1 + d120 * ((sweep ~= 0 and f2 > f1) and 1 or -1) + x2 = cx + rx * cos(f2) + y2 = cy + ry * sin(f2) + res = a2c(x2, y2, rx, ry, angle, 0, sweep, x2old, y2old, f2, f2old, cx, cy) + end + + local c1 = cos(f1) + local s1 = sin(f1) + local c2 = cos(f2) + local s2 = sin(f2) + + local t = tan((f2 - f1) / 4) + local hx = 4 * rx * t / 3 + local hy = 4 * ry * t / 3 + + local r = { x1 - hx * s1, y1 + hy * c1, x2 + hx * s2, y2 - hy * c2, x2, y2, unpack(res or { }) } + + if not recursive then -- we can also check for sin/cos being 0/1 + cosrad = cos(rad) + sinrad = sin(rad) + -- cosrad = cosd(angle) + -- sinrad = sind(angle) + for i0=1,#r,2 do + local i1 = i0 + 1 + local x = r[i0] + local y = r[i1] + r[i0] = x * cosrad - y * sinrad + r[i1] = x * sinrad + y * cosrad + end + end + + return r + end + +end + +-- We share some patterns. + +local p_digit = lpegpatterns.digit +local p_hexdigit = lpegpatterns.hexdigit +local p_space = lpegpatterns.whitespace + +local factors = { + ["pt"] = 1.25, + ["mm"] = 3.543307, + ["cm"] = 35.43307, + ["px"] = 1, + ["pc"] = 15, + ["in"] = 90, + ["em"] = 12 * 1.25, + ["ex"] = 8 * 1.25, +} + +local percentage_r = 1/100 +local percentage_x = percentage_r +local percentage_y = percentage_r + +-- incredible: we can find .123.456 => 0.123 0.456 ... + +local p_command_x = C(S("Hh")) +local p_command_y = C(S("Vv")) +local p_command_xy = C(S("CcLlMmQqSsTt")) +local p_command_a = C(S("Aa")) +local p_command = C(S("Zz")) + +local p_optseparator = S("\t\n\r ,")^0 +local p_separator = S("\t\n\r ,")^1 +local p_number = (S("+-")^0 * (p_digit^0 * P(".") * p_digit^1 + p_digit^1 * P(".") + p_digit^1)) + * (P("e") * S("+-")^0 * p_digit^1)^-1 + +local function convert (n) n = tonumber(n) return n end +local function convert_r (n,u) n = tonumber(n) if u == true then return percentage_r * n elseif u then return u * n else return n end end +local function convert_x (n,u) n = tonumber(n) if u == true then return percentage_x * n elseif u then return u * n else return n end end +local function convert_y (n,u) n = tonumber(n) if u == true then return percentage_y * n elseif u then return u * n else return n end end +local function convert_vx(n,u) n = tonumber(n) if u == true then return percentage_x * n elseif u then return u * n else return n end end +local function convert_vy(n,u) n = - tonumber(n) if u == true then return percentage_y * n elseif u then return u * n else return n end end + +local p_unit = (P("p") * S("txc") + P("e") * S("xm") + S("mc") * P("m") + P("in")) / factors +local p_percent = P("%") * Cc(true) + +local c_number_n = C(p_number) +local c_number_u = C(p_number) * (p_unit + p_percent)^-1 + +local p_number_n = c_number_n / convert +local p_number_x = c_number_u / convert_x +local p_number_vx = c_number_u / convert_vx +local p_number_y = c_number_u / convert_y +local p_number_vy = c_number_u / convert_vy +local p_number_r = c_number_u / convert_r + +local function asnumber (s) return s and lpegmatch(p_number, s) or 0 end +local function asnumber_r (s) return s and lpegmatch(p_number_r, s) or 0 end +local function asnumber_x (s) return s and lpegmatch(p_number_x, s) or 0 end +local function asnumber_y (s) return s and lpegmatch(p_number_y, s) or 0 end +local function asnumber_vx(s) return s and lpegmatch(p_number_vx,s) or 0 end +local function asnumber_vy(s) return s and lpegmatch(p_number_vy,s) or 0 end + +local p_number_vx_t = Ct { (p_number_vx + p_separator)^1 } +local p_number_vy_t = Ct { (p_number_vy + p_separator)^1 } + +local zerotable = { 0 } + +local function asnumber_vx_t(s) return s and lpegmatch(p_number_vx_t,s) or zerotable end +local function asnumber_vy_t(s) return s and lpegmatch(p_number_vy_t,s) or zerotable end + +local p_numbersep = p_number_n + p_separator +local p_numbers = p_optseparator * P("(") * p_numbersep^0 * p_optseparator * P(")") +local p_fournumbers = p_numbersep^4 +local p_path = Ct ( ( + p_command_xy * (p_optseparator * p_number_vx * + p_optseparator * p_number_vy )^1 + + p_command_x * (p_optseparator * p_number_vx )^1 + + p_command_y * (p_optseparator * p_number_vy )^1 + + p_command_a * (p_optseparator * p_number_vx * + p_optseparator * p_number_vy * + p_optseparator * p_number_r * + p_optseparator * p_number_n * -- flags + p_optseparator * p_number_n * -- flags + p_optseparator * p_number_vx * + p_optseparator * p_number_vy )^1 + + p_command + + p_separator +)^1 ) + +-- We can actually use the svg color definitions from the tex end but maybe a user +-- doesn't want those replace the normal definitions. +-- +-- local hexhash = setmetatableindex(function(t,k) local v = lpegmatch(p_hexcolor, k) t[k] = v return v end) -- per file +-- local hexhash3 = setmetatableindex(function(t,k) local v = lpegmatch(p_hexcolor3,k) t[k] = v return v end) -- per file +-- +-- local function hexcolor (c) return hexhash [c] end -- directly do hexhash [c] +-- local function hexcolor3(c) return hexhash3[c] end -- directly do hexhash3[c] + +local colormap = false + +local function prepared(t) + if type(t) == "table" then + local mapping = t.mapping or { } + local mapper = t.mapper + local colormap = setmetatableindex(mapping) + if mapper then + setmetatableindex(colormap,function(t,k) + local v = mapper(k) + t[k] = v or k + return v + end) + end + return colormap + else + return false + end +end + +local colormaps = setmetatableindex(function(t,k) + local v = false + if type(k) == "string" then + v = prepared(table.load(k)) -- todo: same path as svg file + elseif type(k) == "table" then + v = prepared(k) + k = k.name or k + end + t[k] = v + return v +end) + +function metapost.svgcolorremapper(colormap) + return colormaps[colormap] +end + +-- todo: cache colors per image / remapper + +local colorcomponents, withcolor, thecolor, usedcolors do + + local svgcolors = { + aliceblue = 0xF0F8FF, antiquewhite = 0xFAEBD7, aqua = 0x00FFFF, aquamarine = 0x7FFFD4, + azure = 0xF0FFFF, beige = 0xF5F5DC, bisque = 0xFFE4C4, black = 0x000000, + blanchedalmond = 0xFFEBCD, blue = 0x0000FF, blueviolet = 0x8A2BE2, brown = 0xA52A2A, + burlywood = 0xDEB887, cadetblue = 0x5F9EA0, hartreuse = 0x7FFF00, chocolate = 0xD2691E, + coral = 0xFF7F50, cornflowerblue = 0x6495ED, cornsilk = 0xFFF8DC, crimson = 0xDC143C, + cyan = 0x00FFFF, darkblue = 0x00008B, darkcyan = 0x008B8B, darkgoldenrod = 0xB8860B, + darkgray = 0xA9A9A9, darkgreen = 0x006400, darkgrey = 0xA9A9A9, darkkhaki = 0xBDB76B, + darkmagenta = 0x8B008B, darkolivegreen = 0x556B2F, darkorange = 0xFF8C00, darkorchid = 0x9932CC, + darkred = 0x8B0000, darksalmon = 0xE9967A, darkseagreen = 0x8FBC8F, darkslateblue = 0x483D8B, + darkslategray = 0x2F4F4F, darkslategrey = 0x2F4F4F, darkturquoise = 0x00CED1, darkviolet = 0x9400D3, + deeppink = 0xFF1493, deepskyblue = 0x00BFFF, dimgray = 0x696969, dimgrey = 0x696969, + dodgerblue = 0x1E90FF, firebrick = 0xB22222, floralwhite = 0xFFFAF0, forestgreen = 0x228B22, + fuchsia = 0xFF00FF, gainsboro = 0xDCDCDC, ghostwhite = 0xF8F8FF, gold = 0xFFD700, + goldenrod = 0xDAA520, gray = 0x808080, green = 0x008000, greenyellow = 0xADFF2F, + grey = 0x808080, honeydew = 0xF0FFF0, hotpink = 0xFF69B4, indianred = 0xCD5C5C, + indigo = 0x4B0082, ivory = 0xFFFFF0, khaki = 0xF0E68C, lavender = 0xE6E6FA, + lavenderblush = 0xFFF0F5, lawngreen = 0x7CFC00, lemonchiffon = 0xFFFACD, lightblue = 0xADD8E6, + lightcoral = 0xF08080, lightcyan = 0xE0FFFF, lightgoldenrodyellow = 0xFAFAD2, lightgray = 0xD3D3D3, + lightgreen = 0x90EE90, lightgrey = 0xD3D3D3, lightpink = 0xFFB6C1, lightsalmon = 0xFFA07A, + lightseagreen = 0x20B2AA, lightskyblue = 0x87CEFA, lightslategray = 0x778899, lightslategrey = 0x778899, + lightsteelblue = 0xB0C4DE, lightyellow = 0xFFFFE0, lime = 0x00FF00, limegreen = 0x32CD32, + linen = 0xFAF0E6, magenta = 0xFF00FF, maroon = 0x800000, mediumaquamarine = 0x66CDAA, + mediumblue = 0x0000CD, mediumorchid = 0xBA55D3, mediumpurple = 0x9370DB, mediumseagreen = 0x3CB371, + mediumslateblue = 0x7B68EE, mediumspringgreen = 0x00FA9A, mediumturquoise = 0x48D1CC, mediumvioletred = 0xC71585, + midnightblue = 0x191970, mintcream = 0xF5FFFA, mistyrose = 0xFFE4E1, moccasin = 0xFFE4B5, + navajowhite = 0xFFDEAD, navy = 0x000080, oldlace = 0xFDF5E6, olive = 0x808000, + olivedrab = 0x6B8E23, orange = 0xFFA500, orangered = 0xFF4500, orchid = 0xDA70D6, + palegoldenrod = 0xEEE8AA, palegreen = 0x98FB98, paleturquoise = 0xAFEEEE, palevioletred = 0xDB7093, + papayawhip = 0xFFEFD5, peachpuff = 0xFFDAB9, peru = 0xCD853F, pink = 0xFFC0CB, + plum = 0xDDA0DD, powderblue = 0xB0E0E6, purple = 0x800080, red = 0xFF0000, + rosybrown = 0xBC8F8F, royalblue = 0x4169E1, saddlebrown = 0x8B4513, salmon = 0xFA8072, + sandybrown = 0xF4A460, seagreen = 0x2E8B57, seashell = 0xFFF5EE, sienna = 0xA0522D, + silver = 0xC0C0C0, skyblue = 0x87CEEB, slateblue = 0x6A5ACD, slategray = 0x708090, + slategrey = 0x708090, snow = 0xFFFAFA, springgreen = 0x00FF7F, steelblue = 0x4682B4, + tan = 0xD2B48C, teal = 0x008080, thistle = 0xD8BFD8, tomato = 0xFF6347, + turquoise = 0x40E0D0, violet = 0xEE82EE, wheat = 0xF5DEB3, white = 0xFFFFFF, + whitesmoke = 0xF5F5F5, yellow = 0xFFFF00, yellowgreen = 0x9ACD32, + } + + local f_rgb = formatters['withcolor svgcolor(%.3N,%.3N,%.3N)'] + local f_cmyk = formatters['withcolor svgcmyk(%.3N,%.3N,%.3N,%.3N)'] + local f_gray = formatters['withcolor svggray(%.3N)'] + local f_rgba = formatters['withcolor svgcolor(%.3N,%.3N,%.3N) withtransparency (1,%.3N)'] + local f_graya = formatters['withcolor svggray(%.3N) withtransparency (1,%.3N)'] + local f_name = formatters['withcolor "%s"'] + local f_svgrgb = formatters['svgcolor(%.3N,%.3N,%.3N)'] + local f_svgcmyk = formatters['svgcmyk(%.3N,%.3N,%.3N,%.3N)'] + local f_svggray = formatters['svggray(%.3N)'] + local f_svgname = formatters['"%s"'] + + local extract = bit32.extract + + local triplets = setmetatableindex(function(t,k) + -- we delay building all these strings + local v = svgcolors[k] + if v then + v = { extract(v,16,8)/255, extract(v,8,8)/255, extract(v,0,8)/255 } + else + v = false + end + t[k] = v + return v + end) + + local p_fraction = C(p_number) * C("%")^-1 / function(a,b) return tonumber(a) / (b and 100 or 255) end + local p_angle = C(p_number) * P("deg")^0 / function(a) return tonumber(a) end + local p_percent = C(p_number) * P("%") / function(a) return tonumber(a) / 100 end + local p_absolute = C(p_number) / tonumber + + local p_left = P("(") + local p_right = P(")") + local p_a = P("a")^-1 + local p_h_a_color = p_left + * p_angle + * p_separator * p_percent + * p_separator * p_percent + * p_separator^0 * p_absolute^0 + * p_right + + local colors = attributes.colors + local colorvalues = colors.values + local colorindex = attributes.list[attributes.private('color')] + local hsvtorgb = colors.hsvtorgb + local hwbtorgb = colors.hwbtorgb + local forcedmodel = colors.forcedmodel + + local p_splitcolor = + P("#") * C(p_hexdigit*p_hexdigit)^1 / function(r,g,b) + if not r then + return "gray", 0 + elseif not (g and b) then + return "gray", tonumber(r or "0", 16) / 255 or 0 + else + return "rgb", + tonumber(r or "0", 16) / 255 or 0, + tonumber(g or "0", 16) / 255 or 0, + tonumber(b or "0", 16) / 255 or 0 + end + end + + P("rgb") * p_a + * p_left * (p_fraction + p_separator)^-3 * (p_absolute + p_separator)^0 * p_right / function(r,g,b,a) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + P("cmyk") + * p_left * (p_absolute + p_separator)^0 * p_right / function(c,m,y,k) + return "cmyk", c or 0, m or 0, y or 0, k or 0 + end + + P("hsl") * p_a + * p_h_a_color / function(h,s,l,a) + local r, g, b = hsvtorgb(h,s,l,a) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + P("hwb") * p_a + * p_h_a_color / function(h,w,b,a) + local r, g, b = hwbtorgb(h,w,b) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + function metapost.svgsplitcolor(color) + if type(color) == "string" then + local what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) + if not what then + local t = triplets[color] + if t then + what, s1, s2, s3 = "rgb", t[1], t[2], t[3] + end + end + return what, s1, s2, s3, s4 + else + return "gray", 0, false + end + end + + local function registeredcolor(name) + local color = colorindex[name] + if color then + local v = colorvalues[color] + local t = forcedmodel(v[1]) + if t == 2 then + return "gray", v[2] + elseif t == 3 then + return "rgb", v[3], v[4], v[5] + elseif t == 4 then + return "cmyk", v[6], v[7], v[8], v[9] + else + -- + end + end + end + + -- we can have a fast check for #000000 + + local function validcolor(color) + if usedcolors then + usedcolors[color] = usedcolors[color] + 1 + end + if colormap then + local c = colormap[color] + local t = type(c) + if t == "table" then + local what = t[1] + if what == "rgb" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or 0, + tonumber(t[4]) or 0, + tonumber(t[4]) or false + elseif what == "cmyk" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or 0, + tonumber(t[4]) or 0, + tonumber(t[5]) or 0 + elseif what == "gray" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or false + end + elseif t == "string" then + color = c + end + end + local what, s1, s2, s3, s4 = registeredcolor(color) + if what then + return what, s1, s2, s3, s4 + end + what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) + if not what then + local t = triplets[color] + if t then + s1, s3, s3 = t[1], t[2], t[3] + what = "rgb" + end + end + return what, s1, s2, s3, s4 + end + + colorcomponents = function(color) + local what, s1, s2, s3, s4 = validcolor(color) + return s1, s2, s3, s4 -- so 4 means cmyk + end + + withcolor = function(color) + local what, s1, s2, s3, s4 = validcolor(color) + -- print(color,what, s1, s2, s3, s4) + if what == "rgb" then + if s4 then + if s1 == s2 and s1 == s3 then + return f_graya(s1,s4) + else + return f_rgba(s1,s2,s3,s4) + end + else + if s1 == s2 and s1 == s3 then + return f_gray(s1) + else + return f_rgb(s1,s2,s3) + end + end + elseif what == "cmyk" then + return f_cmyk(s1,s2,s3,s4) + elseif what == "gray" then + if s2 then + return f_graya(s1,s2) + else + return f_gray(s1) + end + end + return f_name(color) + end + + thecolor = function(color) + local what, s1, s2, s3, s4 = validcolor(color) + if what == "rgb" then + if s4 then + if s1 == s2 and s1 == s3 then + return f_svggraya(s1,s4) + else + return f_svgrgba(s1,s2,s3,s4) + end + else + if s1 == s2 and s1 == s3 then + return f_svggray(s1) + else + return f_svgrgb(s1,s2,s3) + end + end + elseif what == "cmyk" then + return f_cmyk(s1,s2,s3,s4) + elseif what == "gray" then + if s2 then + return f_svggraya(s1,s2) + else + return f_svggray(s1) + end + end + return f_svgname(color) + end + +end + +-- actually we can loop faster because we can go to the last one + +local grabpath, grablist do + + local f_moveto = formatters['(%N,%N)'] + local f_curveto_z = formatters['controls(%N,%N)and(%N,%N)..(%N,%N)'] + local f_curveto_n = formatters['..controls(%N,%N)and(%N,%N)..(%N,%N)'] + local f_lineto_z = formatters['(%N,%N)'] + local f_lineto_n = formatters['--(%N,%N)'] + + local m = { __index = function() return 0 end } + + grabpath = function(str) + local p = lpegmatch(p_path,str) or { } + local np = #p + local all = { entries = np, closed = false, curve = false } + if np == 0 then + return all + end + setmetatable(p,m) + local t = { } -- no real saving here if we share + local n = 0 + local a = 0 + local i = 0 + local last = "M" + local prev = last + local kind = "L" + local x, y = 0, 0 + local x1, y1 = 0, 0 + local x2, y2 = 0, 0 + local rx, ry = 0, 0 + local ar, al = 0, 0 + local as, ac = 0, nil + local mx, my = 0, 0 + while i < np do + i = i + 1 + local pi = p[i] + if type(pi) ~= "number" then + last = pi + i = i + 1 + pi = p[i] + end + -- most often + if last == "c" then + x1 = x + pi + i = i + 1 ; y1 = y + p[i] + i = i + 1 ; x2 = x + p[i] + i = i + 1 ; y2 = y + p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto curveto + elseif last == "l" then + x = x + pi + i = i + 1 ; y = y + p[i] + goto lineto + elseif last == "h" then + x = x + pi + goto lineto + elseif last == "v" then + y = y + pi + goto lineto + elseif last == "a" then + x1 = x + y1 = y + rx = pi + i = i + 1 ; ry = p[i] + i = i + 1 ; ar = p[i] + i = i + 1 ; al = p[i] + i = i + 1 ; as = p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto arc + elseif last == "s" then + if prev == "C" then + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else + x1 = x + y1 = y + end + x2 = x + pi + i = i + 1 ; y2 = y + p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto curveto + elseif last == "m" then + if n > 0 then + a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 + end + x = x + pi + i = i + 1 ; y = y + p[i] + goto moveto + elseif last == "z" then + goto close + -- less frequent + elseif last == "C" then + x1 = pi + i = i + 1 ; y1 = p[i] + i = i + 1 ; x2 = p[i] + i = i + 1 ; y2 = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto curveto + elseif last == "L" then + x = pi + i = i + 1 ; y = p[i] + goto lineto + elseif last == "H" then + x = pi + goto lineto + elseif last == "V" then + y = pi + goto lineto + elseif last == "A" then + x1 = x + y1 = y + rx = pi + i = i + 1 ; ry = p[i] + i = i + 1 ; ar = p[i] + i = i + 1 ; al = p[i] + i = i + 1 ; as = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto arc + elseif last == "S" then + if prev == "C" then + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else + x1 = x + y1 = y + end + x2 = pi + i = i + 1 ; y2 = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto curveto + elseif last == "M" then + if n > 0 then + a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 + end + x = pi ; + i = i + 1 ; y = p[i] + goto moveto + elseif last == "Z" then + goto close + -- very seldom + elseif last == "q" then + x1 = x + pi + i = i + 1 ; y1 = y + p[i] + i = i + 1 ; x2 = x + p[i] + i = i + 1 ; y2 = y + p[i] + goto quadratic + elseif last == "t" then + if prev == "C" then + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else + x1 = x + y1 = y + end + x2 = x + pi + i = i + 1 ; y2 = y + p[i] + goto quadratic + elseif last == "Q" then + x1 = pi + i = i + 1 ; y1 = p[i] + i = i + 1 ; x2 = p[i] + i = i + 1 ; y2 = p[i] + goto quadratic + elseif last == "T" then + if prev == "C" then + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else + x1 = x + y1 = y + end + x2 = pi + i = i + 1 ; y2 = p[i] + goto quadratic + else + goto continue + end + ::moveto:: + n = n + 1 ; t[n] = f_moveto(x,y) + last = last == "M" and "L" or "l" + prev = "M" + mx = x + my = y + goto continue + ::lineto:: + n = n + 1 ; t[n] = (n > 0 and f_lineto_n or f_lineto_z)(x,y) + prev = "L" + goto continue + ::curveto:: + n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)(x1,y1,x2,y2,x,y) + prev = "C" + goto continue + ::arc:: + ac = a2c(x1,y1,rx,ry,ar,al,as,x,y) + for i=1,#ac,6 do + n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)( + ac[i],ac[i+1],ac[i+2],ac[i+3],ac[i+4],ac[i+5] + ) + end + prev = "A" + goto continue + ::quadratic:: + n = n + 1 ; t[n] = (n > 0 and f_curveto_n or f_curveto_z)( + x + 2/3 * (x1-x ), y + 2/3 * (y1-y ), + x2 + 2/3 * (x1-x2), y2 + 2/3 * (y1-y2), + x2, y2 + ) + x = x2 + y = y2 + prev = "C" + goto continue + ::close:: + -- n = n + 1 ; t[n] = prev == "C" and "..cycle" or "--cycle" + n = n + 1 ; t[n] = "--cycle" + if n > 0 then + a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 + end + if i == np then + break + else + i = i - 1 + end + kind = prev + prev = "Z" + -- this is kind of undocumented: a close also moves back + x = mx + y = my + ::continue:: + end + if n > 0 then + a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 + end + if prev == "Z" then + all.closed = true + end + all.curve = (kind == "C" or kind == "A") + return all, p + end + + -- this is a bit tricky as what are points for a mark ... the next can be simplified + -- a lot + + grablist = function(p) + local np = #p + if np == 0 then + return nil + end + local t = { } + local n = 0 + local a = 0 + local i = 0 + local last = "M" + local prev = last + local kind = "L" + local x, y = 0, 0 + local x1, y1 = 0, 0 + local x2, y2 = 0, 0 + local rx, ry = 0, 0 + local ar, al = 0, 0 + local as, ac = 0, nil + local mx, my = 0, 0 + while i < np do + i = i + 1 + local pi = p[i] + if type(pi) ~= "number" then + last = pi + i = i + 1 + pi = p[i] + end + -- most often + if last == "c" then + x1 = x + pi + i = i + 1 ; y1 = y + p[i] + i = i + 1 ; x2 = x + p[i] + i = i + 1 ; y2 = y + p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto curveto + elseif last == "l" then + x = x + pi + i = i + 1 ; y = y + p[i] + goto lineto + elseif last == "h" then + x = x + pi + goto lineto + elseif last == "v" then + y = y + pi + goto lineto + elseif last == "a" then + x1 = x + y1 = y + rx = pi + i = i + 1 ; ry = p[i] + i = i + 1 ; ar = p[i] + i = i + 1 ; al = p[i] + i = i + 1 ; as = p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto arc + elseif last == "s" then + if prev == "C" then + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else + x1 = x + y1 = y + end + x2 = x + pi + i = i + 1 ; y2 = y + p[i] + i = i + 1 ; x = x + p[i] + i = i + 1 ; y = y + p[i] + goto curveto + elseif last == "m" then + x = x + pi + i = i + 1 ; y = y + p[i] + goto moveto + elseif last == "z" then + goto close + -- less frequent + elseif last == "C" then + x1 = pi + i = i + 1 ; y1 = p[i] + i = i + 1 ; x2 = p[i] + i = i + 1 ; y2 = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto curveto + elseif last == "L" then + x = pi + i = i + 1 ; y = p[i] + goto lineto + elseif last == "H" then + x = pi + goto lineto + elseif last == "V" then + y = pi + goto lineto + elseif last == "A" then + x1 = x + y1 = y + rx = pi + i = i + 1 ; ry = p[i] + i = i + 1 ; ar = p[i] + i = i + 1 ; al = p[i] + i = i + 1 ; as = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto arc + elseif last == "S" then + if prev == "C" then + x1 = 2 * x - x2 + y1 = 2 * y - y2 + else + x1 = x + y1 = y + end + x2 = pi + i = i + 1 ; y2 = p[i] + i = i + 1 ; x = p[i] + i = i + 1 ; y = p[i] + goto curveto + elseif last == "M" then + x = pi ; + i = i + 1 ; y = p[i] + goto moveto + elseif last == "Z" then + goto close + -- very seldom + elseif last == "q" then + x1 = x + pi + i = i + 1 ; y1 = y + p[i] + i = i + 1 ; x2 = x + p[i] + i = i + 1 ; y2 = y + p[i] + goto quadratic + elseif last == "t" then + if prev == "C" then + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else + x1 = x + y1 = y + end + x2 = x + pi + i = i + 1 ; y2 = y + p[i] + goto quadratic + elseif last == "Q" then + x1 = pi + i = i + 1 ; y1 = p[i] + i = i + 1 ; x2 = p[i] + i = i + 1 ; y2 = p[i] + goto quadratic + elseif last == "T" then + if prev == "C" then + x1 = 2 * x - x1 + y1 = 2 * y - y1 + else + x1 = x + y1 = y + end + x2 = pi + i = i + 1 ; y2 = p[i] + goto quadratic + else + goto continue + end + ::moveto:: + n = n + 1 ; t[n] = x + n = n + 1 ; t[n] = y + last = last == "M" and "L" or "l" + prev = "M" + mx = x + my = y + goto continue + ::lineto:: + n = n + 1 ; t[n] = x + n = n + 1 ; t[n] = y + prev = "L" + goto continue + ::curveto:: + n = n + 1 ; t[n] = x + n = n + 1 ; t[n] = y + prev = "C" + goto continue + ::arc:: + ac = a2c(x1,y1,rx,ry,ar,al,as,x,y) + for i=1,#ac,6 do + n = n + 1 ; t[n] = ac[i+4] + n = n + 1 ; t[n] = ac[i+5] + end + prev = "A" + goto continue + ::quadratic:: + n = n + 1 ; t[n] = x2 + n = n + 1 ; t[n] = y2 + x = x2 + y = y2 + prev = "C" + goto continue + ::close:: + n = n + 1 ; t[n] = mx + n = n + 1 ; t[n] = my + if i == np then + break + end + kind = prev + prev = "Z" + x = mx + y = my + ::continue:: + end + return t + end + +end + +-- todo: viewbox helper + +local s_wrapped_start = "draw image (" +local f_wrapped_stop = formatters[") shifted (0,%N) scaled %N ;"] + +local handletransform, handleviewbox do + + local sind = math.sind + + --todo: better lpeg + + local f_rotatedaround = formatters[" rotatedaround((%N,%N),%N)"] + local f_rotated = formatters[" rotated(%N)"] + local f_shifted = formatters[" shifted(%N,%N)"] + local f_slanted_x = formatters[" xslanted(%N)"] + local f_slanted_y = formatters[" yslanted(%N)"] + local f_scaled = formatters[" scaled(%N)"] + local f_xyscaled = formatters[" xyscaled(%N,%N)"] + local f_matrix = formatters[" transformed bymatrix(%N,%N,%N,%N,%N,%N)"] + + local s_transform_start = "draw image ( " + local f_transform_stop = formatters[")%s ;"] + + local function rotate(r,x,y) + if x then + return r and f_rotatedaround(x,-(y or x),-r) + elseif r then + return f_rotated(-r) + else + return "" + end + end + + local function translate(x,y) + if y then + return f_shifted(x,-y) + elseif x then + return f_shifted(x,0) + else + return "" + end + end + + local function scale(x,y) + if y then + return f_xyscaled(x,y) + elseif x then + return f_scaled(x) + else + return "" + end + end + + local function skewx(x) + if x then + return f_slanted_x(sind(-x)) + else + return "" + end + end + + local function skewy(y) + if y then + return f_slanted_y(sind(-y)) + else + return "" + end + end + + local function matrix(rx,sx,sy,ry,tx,ty) + return f_matrix(rx or 1, sx or 0, sy or 0, ry or 1, tx or 0, - (ty or 0)) + end + + -- How to deal with units here? Anyway, order seems to matter. + + local p_transform = Cf ( Ct("") * ( + lpegpatterns.whitespace^0 * Cg( + C("translate") * (p_numbers / translate) -- maybe xy + + C("scale") * (p_numbers / scale) + + C("rotate") * (p_numbers / rotate) + + C("matrix") * (p_numbers / matrix) + + C("skewX") * (p_numbers / skewx) + + C("skewY") * (p_numbers / skewy) + ) + )^1, rawset) + + handletransform = function(at) + local t = at.transform + if t then + local e = lpegmatch(p_transform,t) + if e then + e = concat({ + e.rotate or "", + e.skewX or "", + e.skewY or "", + e.scale or "", + e.translate or "", + e.matrix or "", + }, " ") + return s_transform_start, f_transform_stop(e), t + end + end + end + + handleviewbox = function(v) + if v then + local x, y, w, h = lpegmatch(p_fournumbers,v) + if h then + return x, y, w, h + end + end + end + +end + +local dashed do + + -- actually commas are mandate but we're tolerant + + local f_dashed_n = formatters[" dashed dashpattern (%s ) "] + local f_dashed_y = formatters[" dashed dashpattern (%s ) shifted (%N,0) "] + + local p_number = p_optseparator/"" * p_number_r + local p_on = Cc(" on ") * p_number + local p_off = Cc(" off ") * p_number + local p_dashed = Cs((p_on * p_off^-1)^1) + + dashed = function(s,o) + if not find(s,",") then + -- a bit of a hack: + s = s .. " " .. s + end + return (o and f_dashed_y or f_dashed_n)(lpegmatch(p_dashed,s),o) + end + +end + +do + + local handlers = { } + local process = false + local root = false + local result = false + local r = false + local definitions = false + local classstyles = false + local tagstyles = false + + local tags = { + ["a"] = true, + -- ["altgGlyph"] = true, + -- ["altgGlyphDef"] = true, + -- ["altgGlyphItem"] = true, + -- ["animate"] = true, + -- ["animateColor"] = true, + -- ["animateMotion"] = true, + -- ["animateTransform"] = true, + ["circle"] = true, + ["clipPath"] = true, + -- ["color-profile"] = true, + -- ["cursor"] = true, + ["defs"] = true, + -- ["desc"] = true, + ["ellipse"] = true, + -- ["filter"] = true, + -- ["font"] = true, + -- ["font-face"] = true, + -- ["font-face-format"] = true, + -- ["font-face-name"] = true, + -- ["font-face-src"] = true, + -- ["font-face-uri"] = true, + -- ["foreignObject"] = true, + ["g"] = true, + -- ["glyph"] = true, + -- ["glyphRef"] = true, + -- ["hkern"] = true, + ["image"] = true, + ["line"] = true, + ["linearGradient"] = true, + ["marker"] = true, + -- ["mask"] = true, + -- ["metadata"] = true, + -- ["missing-glyph"] = true, + -- ["mpath"] = true, + ["path"] = true, + -- ["pattern"] = true, + ["polygon"] = true, + ["polyline"] = true, + ["radialGradient"] = true, + ["rect"] = true, + -- ["script"] = true, + -- ["set"] = true, + ["stop"] = true, + ["style"] = true, + ["svg"] = true, + -- ["switch"] = true, + ["symbol"] = true, + ["text"] = true, + -- ["textPath"] = true, + -- ["title"] = true, + ["tspan"] = true, + ["use"] = true, + -- ["view"] = true, + -- ["vkern"] = true, + } + + local function handlechains(c) + if tags[c.tg] then + local at = c.at + local dt = c.dt + if at and dt then + -- at["inkscape:connector-curvature"] = nil -- cleare entry and might prevent table growth + local estyle = rawget(at,"style") + if estyle and estyle ~= "" then + for k, v in gmatch(estyle,"%s*([^:]+):%s*([^;]+);?") do + at[k] = v + end + end + local eclass = rawget(at,"class") + if eclass and eclass ~= "" then + for c in gmatch(eclass,"[^ ]+") do + local s = classstyles[c] + if s then + for k, v in next, s do + at[k] = v + end + end + end + end + local tstyle = tagstyles[tag] + if tstyle then + for k, v in next, tstyle do + at[k] = v + end + end + if trace_path and pathtracer then + for k, v in next, pathtracer do + at[k] = v + end + end + for i=1,#dt do + local dti = dt[i] + if type(dti) == "table" then + handlechains(dti) + end + end + end + end + end + + local handlestyle do + + -- It can also be CDATA but that is probably dealt with because we only + -- check for style entries and ignore the rest. But maybe we also need + -- to check a style at the outer level? + + local p_key = C((R("az","AZ","09","__","--")^1)) + local p_spec = P("{") * C((1-P("}"))^1) * P("}") + local p_valid = Carg(1) * P(".") * p_key + Carg(2) * p_key + local p_grab = ((p_valid * p_space^0 * p_spec / rawset) + p_space^1 + P(1))^1 + + local fontspecification = css.fontspecification + + handlestyle = function(c) + local s = xmltext(c) + lpegmatch(p_grab,s,1,classstyles,tagstyles) + for k, v in next, classstyles do + local t = { } + for k, v in gmatch(v,"%s*([^:]+):%s*([^;]+);?") do + if k == "font" then + local s = fontspecification(v) + for k, v in next, s do + t["font-"..k] = v + end + else + t[k] = v + end + end + classstyles[k] = t + end + for k, v in next, tagstyles do + local t = { } + for k, v in gmatch(v,"%s*([^:]+):%s*([^;]+);?") do + if k == "font" then + local s = fontspecification(v) + for k, v in next, s do + t["font-"..k] = v + end + else + t[k] = v + end + end + tagstyles[k] = t + end + end + + function handlers.style() + -- ignore + end + + end + + -- We can have root in definitions and then do a metatable lookup but use + -- is not used that often I guess. + + local function locate(id) + local res = definitions[id] + if res then + return res + end + local ref = gsub(id,"^url%(#(.-)%)$","%1") + local ref = gsub(ref,"^#","") + -- we can make a fast id lookup + local res = xmlfirst(root,"**[@id='"..ref.."']") + if res then + definitions[id] = res + end + return res + end + + -- also locate + + local function handleclippath(at) + local clippath = at["clip-path"] + + if not clippath then + return + end + + local spec = definitions[clippath] or locate(clippath) + + -- do we really need thsi crap + if not spec then + local index = match(clippath,"(%d+)") + if index then + spec = xmlfirst(root,"clipPath["..tostring(tonumber(index) or 0).."]") + end + end + -- so far for the crap + + if not spec then + report("unknown clip %a",clippath) + return + elseif spec.tg ~= "clipPath" then + report("bad clip %a",clippath) + return + end + + ::again:: + for c in xmlcollected(spec,"/(path|use|g)") do + local tg = c.tg + if tg == "use" then + local ca = c.at + local id = ca["xlink:href"] + if id then + spec = locate(id) + if spec then + local sa = spec.at + setmetatableindex(sa,ca) + if spec.tg == "path" then + local d = sa.d + if d then + local p = grabpath(d) + p.evenodd = sa["clip-rule"] == "evenodd" + p.close = true + return p, clippath + else + return + end + else + goto again + end + end + end + -- break + elseif tg == "path" then + local ca = c.at + local d = ca.d + if d then + local p = grabpath(d) + p.evenodd = ca["clip-rule"] == "evenodd" + p.close = true + return p, clippath + else + return + end + else + -- inherit? + end + end + end + + local s_shade_linear = ' withshademethod "linear" ' + local s_shade_circular = ' withshademethod "circular" ' + local f_shade_step = formatters['withshadestep ( withshadefraction %N withshadecolors(%s,%s) )'] + local f_shade_one = formatters['withprescript "sh_center_a=%N %N"'] + local f_shade_two = formatters['withprescript "sh_center_b=%N %N"'] + + local f_color = formatters['withcolor "%s"'] + local f_opacity = formatters['withtransparency (1,%N)'] + local f_pen = formatters['withpen pencircle scaled %N'] + + -- todo: gradient unfinished + -- todo: opacity but first we need groups in mp + + local function gradient(id) + local spec = definitions[id] -- no locate ! + if spec then + local kind = spec.tg + local shade = nil + local n = 1 + local a = spec.at + if kind == "linearGradient" then + shade = { s_shade_linear } + -- + local x1 = rawget(a,"x1") + local y1 = rawget(a,"y1") + local x2 = rawget(a,"x2") + local y2 = rawget(a,"y2") + if x1 and y1 then + n = n + 1 ; shade[n] = f_shade_one(asnumber_vx(x1),asnumber_vy(y1)) + end + if x2 and y2 then + n = n + 1 ; shade[n] = f_shade_one(asnumber_vx(x2),asnumber_vy(y2)) + end + -- + elseif kind == "radialGradient" then + shade = { s_shade_circular } + -- + local cx = rawget(a,"cx") -- x center + local cy = rawget(a,"cy") -- y center + local r = rawget(a,"r" ) -- radius + local fx = rawget(a,"fx") -- focal points + local fy = rawget(a,"fy") -- focal points + -- + if cx and cy then + -- todo + end + if r then + -- todo + end + if fx and fy then + -- todo + end + else + report("unknown gradient %a",id) + return + end + -- local gu = a.gradientUnits + -- local gt = a.gradientTransform + -- local sm = a.spreadMethod + local colora, colorb + -- startcolor ? + for c in xmlcollected(spec,"/stop") do + local a = c.at + local offset = rawget(a,"offset") + local colorb = rawget(a,"stop-color") + local opacity = rawget(a,"stop-opacity") + if colorb then + colorb = thecolor(colorb) + end + if not colora then + colora = colorb + end + -- what if no percentage + + local fraction = offset and asnumber_r(offset) + if not fraction then + -- offset = tonumber(offset) + -- for now + fraction = xmlcount(spec,"/stop")/100 + end + + if colora and colorb and color_a ~= "" and color_b ~= "" then + n = n + 1 ; shade[n] = f_shade_step(fraction,colora,colorb) + end + + colora = colorb + end + return concat(shade," ") + end + end + + local function drawproperties(stroke,at,opacity) + local p = at["stroke-width"] + if p then + p = f_pen(asnumber_r(p)) + end + local d = at["stroke-dasharray"] + if d == "none" then + d = nil + elseif d then + local o = at["stroke-dashoffset"] + if o and o ~= "none" then + o = asnumber_r(o) + else + o = false + end + d = dashed(d,o) + end + local c = withcolor(stroke) + local o = at["stroke-opacity"] or (opacity and at["opacity"]) + if o == "none" then + o = nil + elseif o then + o = asnumber_r(o) + if o and o ~= 1 then + o = f_opacity(o) + else + o = nil + end + end + return p, d, c, o + end + + local s_opacity_start = "draw image (" + local f_opacity_stop = formatters["setgroup currentpicture to boundingbox currentpicture withtransparency (1,%N)) ;"] + + local function sharedopacity(at) + local o = at["opacity"] + if o and o ~= "none" then + o = asnumber_r(o) + if o and o ~= 1 then + return s_opacity_start, f_opacity_stop(o) + end + end + end + + local function fillproperties(fill,at,opacity) + local c = c ~= "none" and (gradient(fill) or withcolor(fill)) or nil + local o = at["fill-opacity"] or (opacity and at["opacity"]) + if o and o ~= "none" then + o = asnumber_r(o) + if o == 1 then + return c + elseif o then + return c, f_opacity(o), o == 0 + end + end + return c + end + + -- todo: clip = [ auto | rect(llx,lly,urx,ury) ] + + local s_offset_start = "draw image ( " + local f_offset_stop = formatters[") shifted (%N,%N) ;"] + local s_rotation_start = "draw image ( " + local f_rotation_stop = formatters[") rotatedaround((0,0),-angle((%N,%N))) ;"] + local f_rotation_angle = formatters[") rotatedaround((0,0),-%N) ;"] + + local function offset(at) + local x = asnumber_vx(rawget(at,"x")) + local y = asnumber_vy(rawget(at,"y")) + if x ~= 0 or y ~= 0 then + return s_offset_start, f_offset_stop(x,y) + end + end + + local s_viewport_start = "draw image (" + local s_viewport_stop = ") ;" + local f_viewport_shift = formatters["currentpicture := currentpicture shifted (%03N,%03N);"] + local f_viewport_scale = formatters["currentpicture := currentpicture xysized (%03N,%03N);"] + local f_viewport_clip = formatters["clip currentpicture to (unitsquare xyscaled (%03N,%03N));"] + + local function viewport(x,y,w,h,noclip,scale) + r = r + 1 ; result[r] = s_viewport_start + return function() + local okay = w ~= 0 and h ~= 0 + if okay and scale then + r = r + 1 ; result[r] = f_viewport_scale(w,h) + end + if x ~= 0 or y ~= 0 then + r = r + 1 ; result[r] = f_viewport_shift(-x,y) + end + if okay and not noclip then + r = r + 1 ; result[r] = f_viewport_clip(w,-h) + end + + r = r + 1 ; result[r] = s_viewport_stop + end + end + + -- maybe forget about defs and just always locate (and then backtrack + -- over if needed) + + function handlers.defs(c) + for c in xmlcollected(c,"/*") do + local a = c.at + if a then + local id = rawget(a,"id") + if id then + definitions["#" .. id ] = c + definitions["url(#" .. id .. ")"] = c + end + end + end + end + + function handlers.symbol(c) + if uselevel == 0 then + local id = rawget(c.at,"id") + if id then + definitions["#" .. id ] = c + definitions["url(#" .. id .. ")"] = c + end + else + handlers.g(c) + end + end + + local uselevel = 0 + + function handlers.use(c) + local at = c.at + local id = rawget(at,"href") or rawget(at,"xlink:href") -- better a rawget + local res = locate(id) + if res then + -- width height ? + uselevel = uselevel + 1 + local boffset, eoffset = offset(at) + local btransform, etransform, transform = handletransform(at) + + if boffset then + r = r + 1 result[r] = boffset + end + + -- local clippath = at.clippath + + if btransform then + r = r + 1 result[r] = btransform + end + + local _transform = transform + local _clippath = clippath + at["transform"] = false + -- at["clip-path"] = false + + process(res,"/*") + + at["transform"] = _transform + -- at["clip-path"] = _clippath + + if etransform then + r = r + 1 ; result[r] = etransform + end + + if eoffset then + r = r + 1 result[r] = eoffset + end + + uselevel = uselevel - 1 + else + report("use: unknown definition %a",id) + end + end + + local f_no_draw = formatters['nodraw (%s)'] + local f_do_draw = formatters['draw (%s)'] + local f_no_fill_c = formatters['nofill (%s..cycle)'] + local f_do_fill_c = formatters['fill (%s..cycle)'] + local f_eo_fill_c = formatters['eofill (%s..cycle)'] + local f_no_fill_l = formatters['nofill (%s--cycle)'] + local f_do_fill_l = formatters['fill (%s--cycle)'] + local f_eo_fill_l = formatters['eofill (%s--cycle)'] + local f_do_fill = f_do_fill_c + local f_eo_fill = f_eo_fill_c + local f_no_fill = f_no_fill_c + local s_clip_start = 'draw image (' + local f_clip_stop_c = formatters[') ; clip currentpicture to (%s..cycle) ;'] + local f_clip_stop_l = formatters[') ; clip currentpicture to (%s--cycle) ;'] + local f_clip_stop = f_clip_stop_c + local f_eoclip_stop_c = formatters[') ; eoclip currentpicture to (%s..cycle) ;'] + local f_eoclip_stop_l = formatters[') ; eoclip currentpicture to (%s--cycle) ;'] + local f_eoclip_stop = f_eoclip_stop_c + + -- could be shared and then beginobject | endobject + + local function flushobject(object,at,c,o) + local btransform, etransform = handletransform(at) + local cpath = handleclippath(at) + + if cpath then + r = r + 1 ; result[r] = s_clip_start + end + + if btransform then + r = r + 1 ; result[r] = btransform + end + + r = r + 1 ; result[r] = f_do_draw(object) + + if c then + r = r + 1 ; result[r] = c + end + + if o then + r = r + 1 ; result[r] = o + end + + if etransform then + r = r + 1 ; result[r] = etransform + end + + r = r + 1 ; result[r] = ";" + + if cpath then + local f_done = cpath.evenodd + if cpath.curve then + f_done = f_done and f_eoclip_stop_c or f_clip_stop_c + else + f_done = f_done and f_eoclip_stop_l or f_clip_stop_l + end + r = r + 1 ; result[r] = f_done(cpath[1]) + end + end + + do + + local flush + + local f_linecap = formatters["interim linecap := %s ;"] + local f_linejoin = formatters["interim linejoin := %s ;"] + local f_miterlimit = formatters["interim miterlimit := %s ;"] + + local s_begingroup = "begingroup;" + local s_endgroup = "endgroup;" + + local linecaps = { butt = "butt", square = "squared", round = "rounded" } + local linejoins = { miter = "mitered", bevel = "beveled", round = "rounded" } + + local function startlineproperties(at) + local cap = at["stroke-linecap"] + local join = at["stroke-linejoin"] + local limit = at["stroke-miterlimit"] + cap = cap and linecaps [cap] + join = join and linejoins[join] + limit = limit and asnumber_r(limit) + if cap or join or limit then + r = r + 1 ; result[r] = s_begingroup + if cap then + r = r + 1 ; result[r] = f_linecap(cap) + end + if join then + r = r + 1 ; result[r] = f_linejoin(join) + end + if limit then + r = r + 1 ; result[r] = f_miterlimit(limit) + end + return function() + at["stroke-linecap"] = false + at["stroke-linejoin"] = false + at["stroke-miterlimit"] = false + r = r + 1 ; result[r] = s_endgroup + at["stroke-linecap"] = cap + at["stroke-linejoin"] = join + at["stroke-miterlimit"] = limit + end + end + end + + -- markers are a quite rediculous thing .. let's assume simple usage for now + + function handlers.marker() + -- todo: is just a def too + end + + -- kind of local svg ... so make a generic one + -- + -- todo: combine more (offset+scale+rotation) + + local function makemarker(where,c,x1,y1,x2,y2,x3,y3,parentat) + local at = c.at + local refx = rawget(at,"refX") + local refy = rawget(at,"refY") + local width = rawget(at,"markerWidth") + local height = rawget(at,"markerHeight") + local view = rawget(at,"viewBox") + local orient = rawget(at,"orient") + -- local ratio = rawget(at,"preserveAspectRatio") + local units = asnumber(at["markerUnits"] or parentat["stroke-width"]) or 1 + + local angx = 0 + local angy = 0 + local angle = 0 + + if where == "beg" then + if orient == "auto" then -- unchecked + -- no angle + angx = abs(x2 - x3) + angy = abs(y2 - y3) + elseif orient == "auto-start-reverse" then -- checked + -- points to start + angx = -abs(x2 - x3) + angy = -abs(y2 - y3) + elseif orient then -- unchecked + angle = asnumber_r(orient) + end + elseif where == "end" then + -- funny standard .. bug turned feature? + if orient == "auto" or orient == "auto-start-reverse" then + angx = abs(x1 - x2) + angy = abs(y1 - y2) + elseif orient then -- unchecked + angle = asnumber_r(orient) + end + elseif orient then -- unchecked + angle = asnumber_r(orient) + end + -- what wins: viewbox or w/h + + refx = asnumber_x(refx) + refy = asnumber_y(refy) + + width = (width and asnumber_x(width) or 3) * units + height = (height and asnumber_y(height) or 3) * units + + local x = 0 + local y = 0 + local w = width + local h = height + + -- kind of like the main svg + + r = r + 1 ; result[r] = s_offset_start + + local wrapupviewport +-- todo : better viewbox code + local xpct, ypct, rpct + if view then + x, y, w, h = handleviewbox(view) + end + + if width ~= 0 then + w = width + end + if height ~= 0 then + h = height + end + + if h then + xpct = percentage_x + ypct = percentage_y + rpct = percentage_r + percentage_x = w / 100 + percentage_y = h / 100 + percentage_r = (sqrt(w^2 + h^2) / sqrt(2)) / 100 + wrapupviewport = viewport(x,y,w,h,true,true) -- no clip + end + + -- we can combine a lot here: + + local hasref = refx ~= 0 or refy ~= 0 + local hasrot = angx ~= 0 or angy ~= 0 or angle ~= 0 + + local btransform, etransform, transform = handletransform(at) + + if btransform then + r = r + 1 ; result[r] = btransform + end + + if hasrot then + r = r + 1 ; result[r] = s_rotation_start + end + + if hasref then + r = r + 1 ; result[r] = s_offset_start + end + + local _transform = transform + at["transform"] = false + + handlers.g(c) + + at["transform"] = _transform + + if hasref then + r = r + 1 ; result[r] = f_offset_stop(-refx,refy) + end + + if hasrot then + if angle ~= 0 then + r = r + 1 ; result[r] = f_rotation_angle(angle) + else + r = r + 1 ; result[r] = f_rotation_stop(angx,angy) + end + end + + if etransform then + r = r + 1 ; result[r] = etransform + end + + if h then + percentage_x = xpct + percentage_y = ypct + percentage_r = rpct + if wrapupviewport then + wrapupviewport() + end + end + r = r + 1 ; result[r] = f_offset_stop(x2,y2) + + end + + -- do we need to metatable the attributes here? + + local function addmarkers(list,begmarker,midmarker,endmarker,at) + local n = #list + if n > 3 then + if begmarker then + local m = locate(begmarker) + if m then + makemarker("beg",m,false,false,list[1],list[2],list[3],list[4],at) + end + end + if midmarker then + local m = locate(midmarker) + if m then + for i=3,n-2,2 do + makemarker("mid",m,list[i-2],list[i-1],list[i],list[i+1],list[i+2],list[i+3],at) + end + end + end + if endmarker then + local m = locate(endmarker) + if m then + makemarker("end",m,list[n-3],list[n-2],list[n-1],list[n],false,false,at) + end + end + else + -- no line + end + end + + local function flush(shape,dofill,at,list,begmarker,midmarker,endmarker) + + local fill = dofill and (at["fill"] or "black") + local stroke = at["stroke"] or "none" + + local btransform, etransform = handletransform(at) + local cpath = handleclippath(at) + + if cpath then + r = r + 1 ; result[r] = s_clip_start + end + + local has_stroke = stroke and stroke ~= "none" + local has_fill = fill and fill ~= "none" + + local bopacity, eopacity + if has_stroke and has_fill then + bopacity, eopacity = sharedopacity(at) + end + + if bopacity then + r = r + 1 ; result[r] = bopacity + end + + if has_fill then + local color, opacity = fillproperties(fill,at,not has_stroke) + local f_xx_fill = at["fill-rule"] == "evenodd" and f_eo_fill or f_do_fill + if btransform then + r = r + 1 ; result[r] = btransform + end + r = r + 1 result[r] = f_xx_fill(shape) + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + r = r + 1 ; result[r] = etransform or ";" + end + + if has_stroke then + local wrapup = startlineproperties(at) + local pen, dashing, color, opacity = drawproperties(stroke,at,not has_fill) + if btransform then + r = r + 1 ; result[r] = btransform + end + r = r + 1 ; result[r] = f_do_draw(shape) + if pen then + r = r + 1 ; result[r] = pen + end + if dashing then + r = r + 1 ; result[r] = dashing + end + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + r = r + 1 ; result[r] = etransform or ";" + -- + if list then + addmarkers(list,begmarker,midmarker,endmarker,at) + end + -- + if wrapup then + wrapup() + end + end + + if eopacity then + r = r + 1 ; result[r] = eopacity + end + + if cpath then + r = r + 1 ; result[r] = (cpath.evenodd and f_eoclip_stop or f_clip_stop)(cpath[1]) + end + + end + + local f_rectangle = formatters['unitsquare xyscaled (%N,%N) shifted (%N,%N)'] + local f_rounded = formatters['roundedsquarexy(%N,%N,%N,%N) shifted (%N,%N)'] + local f_line = formatters['((%N,%N)--(%N,%N))'] + local f_ellipse = formatters['(fullcircle xyscaled (%N,%N) shifted (%N,%N))'] + local f_circle = formatters['(fullcircle scaled %N shifted (%N,%N))'] + + function handlers.line(c) + local at = c.at + local x1 = rawget(at,"x1") + local y1 = rawget(at,"y1") + local x2 = rawget(at,"x2") + local y2 = rawget(at,"y2") + + x1 = x1 and asnumber_vx(x1) or 0 + y1 = y1 and asnumber_vy(y1) or 0 + x2 = x2 and asnumber_vx(x2) or 0 + y2 = y2 and asnumber_vy(y2) or 0 + + flush(f_line(x1,y1,x2,y2),false,at) + end + + function handlers.rect(c) + local at = c.at + local width = rawget(at,"width") + local height = rawget(at,"height") + local x = rawget(at,"x") + local y = rawget(at,"y") + local rx = rawget(at,"rx") + local ry = rawget(at,"ry") + + width = width and asnumber_x(width) or 0 + height = height and asnumber_y(height) or 0 + x = x and asnumber_vx(x) or 0 + y = y and asnumber_vy(y) or 0 + + y = y - height + + if rx then rx = asnumber(rx) end + if ry then ry = asnumber(ry) end + + if rx or ry then + if not rx then rx = ry end + if not ry then ry = rx end + flush(f_rounded(width,height,rx,ry,x,y),true,at) + else + flush(f_rectangle(width,height,x,y),true,at) + end + end + + function handlers.ellipse(c) + local at = c.at + local cx = rawget(at,"cx") + local cy = rawget(at,"cy") + local rx = rawget(at,"rx") + local ry = rawget(at,"ry") + + cx = cx and asnumber_vx(cx) or 0 + cy = cy and asnumber_vy(cy) or 0 + rx = rx and asnumber_r (rx) or 0 + ry = ry and asnumber_r (ry) or 0 + + flush(f_ellipse(2*rx,2*ry,cx,cy),true,at) + end + + function handlers.circle(c) + local at = c.at + local cx = rawget(at,"cx") + local cy = rawget(at,"cy") + local r = rawget(at,"r") + + cx = cx and asnumber_vx(cx) or 0 + cy = cy and asnumber_vy(cy) or 0 + r = r and asnumber_r (r) or 0 + + flush(f_circle(2*r,cx,cy),true,at) + end + + local f_lineto_z = formatters['(%N,%N)'] + local f_lineto_n = formatters['--(%N,%N)'] + + local p_pair = p_optseparator * p_number_vx * p_optseparator * p_number_vy + local p_open = Cc("(") + local p_close = Carg(1) * P(true) / function(s) return s end + local p_polyline = Cs(p_open * (p_pair / f_lineto_z) * (p_pair / f_lineto_n)^0 * p_close) + local p_polypair = Ct(p_pair^0) + + local function poly(c,final) + local at = c.at + local points = rawget(at,"points") + if points then + local path = lpegmatch(p_polyline,points,1,final) + local list = nil + local begmarker = rawget(at,"marker-start") + local midmarker = rawget(at,"marker-mid") + local endmarker = rawget(at,"marker-end") + if begmarker or midmarker or endmarker then + list = lpegmatch(p_polypair,points) + end + flush(path,true,at,list,begmarker,midmarker,endmarker) + end + end + + function handlers.polyline(c) poly(c, ")") end + function handlers.polygon (c) poly(c,"--cycle)") end + + local s_image_start = "draw image (" + local s_image_stop = ") ;" + + function handlers.path(c) + local at = c.at + local d = rawget(at,"d") + if d then + local shape, l = grabpath(d) + local fill = at["fill"] or "black" + local stroke = at["stroke"] or "none" + local n = #shape + + local btransform, etransform = handletransform(at) + local cpath = handleclippath(at) + if cpath then + r = r + 1 ; result[r] = s_clip_start + end + + -- todo: image (nicer for transform too) + + if fill and fill ~= "none" then + local color, opacity = fillproperties(fill,at) + local f_xx_fill = at["fill-rule"] == "evenodd" + if shape.closed then + f_xx_fill = f_xx_fill and f_eo_fill or f_do_fill + elseif shape.curve then + f_xx_fill = f_xx_fill and f_eo_fill_c or f_do_fill_c + else + f_xx_fill = f_xx_fill and f_eo_fill_l or f_do_fill_l + end + if n == 1 then + if btransform then + r = r + 1 ; result[r] = btransform + end + r = r + 1 result[r] = f_xx_fill(shape[1]) + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + r = r + 1 ; result[r] = etransform or ";" + else + r = r + 1 ; result[r] = btransform or s_image_start + for i=1,n do + if i == n then + r = r + 1 ; result[r] = f_xx_fill(shape[i]) + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + else + r = r + 1 ; result[r] = f_no_fill(shape[i]) + end + r = r + 1 ; result[r] = ";" + end + r = r + 1 ; result[r] = etransform or s_image_stop + end + end + + if stroke and stroke ~= "none" then + local begmarker = rawget(at,"marker-start") + local midmarker = rawget(at,"marker-mid") + local endmarker = rawget(at,"marker-end") + if begmarker or midmarker or endmarker then + list = grablist(l) + end + local wrapup = startlineproperties(at) + local pen, dashing, color, opacity = drawproperties(stroke,at) + if n == 1 and not list then + if btransform then + r = r + 1 ; result[r] = btransform + end + r = r + 1 result[r] = f_do_draw(shape[1]) + if pen then + r = r + 1 ; result[r] = pen + end + if dashing then + r = r + 1 ; result[r] = dashing + end + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + r = r + 1 result[r] = etransform or ";" + else + r = r + 1 result[r] = btransform or "draw image (" + for i=1,n do + r = r + 1 result[r] = f_do_draw(shape[i]) + if pen then + r = r + 1 ; result[r] = pen + end + if dashing then + r = r + 1 ; result[r] = dashing + end + if color then + r = r + 1 ; result[r] = color + end + if opacity then + r = r + 1 ; result[r] = opacity + end + r = r + 1 ; result[r] = ";" + end + if list then + addmarkers(list,begmarker,midmarker,endmarker,at) + end + r = r + 1 ; result[r] = etransform or ") ;" + end + if wrapup then + wrapup() + end + end + + if cpath then + r = r + 1 ; result[r] = f_clip_stop(cpath[1]) + end + + end + end + + end + + -- kind of special + + do + + -- some day: + -- + -- specification = identifiers.jpg(data."string") + -- specification.data = data + -- inclusion takes from data + -- specification.data = false + + local f_image = formatters[ [[figure("%s") xysized (%N,%N) shifted (%N,%N)]] ] + + local nofimages = 0 + + function handlers.image(c) + local at = c.at + local im = rawget(at,"xlink:href") + if im then + local kind, data = match(im,"^data:image/([a-z]+);base64,(.*)$") + if kind == "png" then + -- ok + elseif kind == "jpeg" then + kind = "jpg" + else + kind = false + end + if kind and data then + local w = rawget(at,"width") + local h = rawget(at,"height") + local x = rawget(at,"x") + local y = rawget(at,"y") + w = w and asnumber_x(w) + h = h and asnumber_y(h) + x = x and asnumber_vx(x) or 0 + y = y and asnumber_vy(y) or 0 + nofimages = nofimages + 1 + local name = "temp-svg-image-" .. nofimages .. "." .. kind + local data = mime.decode("base64")(data) + io.savedata(name,data) + if not w or not h then + local info = graphics.identifiers[kind](data,"string") + if info then + -- todo: keep aspect ratio attribute + local xsize = info.xsize + local ysize = info.ysize + if not w then + if not h then + w = xsize + h = ysize + else + w = (h / ysize) * xsize + end + else + h = (w / xsize) * ysize + end + end + end + -- safeguard: + if not w then w = h or 1 end + if not h then h = w or 1 end + luatex.registertempfile(name) + -- done: + flushobject(f_image(name,w,h,x,y - h),at) + else + -- nothing done + end + end + end + + end + + -- these transform: g a text svg symbol + + do + + function handlers.a(c) + process(c,"/*") + end + + function handlers.g(c) -- much like flushobject so better split and share + local at = c.at + + local btransform, etransform, transform = handletransform(at) + local cpath, clippath = handleclippath(at) + + if cpath then + r = r + 1 ; result[r] = s_clip_start + end + + if btransform then + r= r + 1 result[r] = btransform + end + + local _transform = transform + local _clippath = clippath + at["transform"] = false + at["clip-path"] = false + + process(c,"/*") + + at["transform"] = _transform + at["clip-path"] = _clippath + + if etransform then + r = r + 1 ; result[r] = etransform + end + + if cpath then + local f_done = cpath.evenodd + if cpath.curve then + f_done = f_done and f_eoclip_stop_c or f_clip_stop_c + else + f_done = f_done and f_eoclip_stop_l or f_clip_stop_l + end + r = r + 1 ; result[r] = f_done(cpath[1]) + end + end + + -- this will never really work out + -- + -- todo: register text in lua in mapping with id, then draw mapping unless overloaded + -- using lmt_svglabel with family,style,weight,size,id passed + + -- nested tspans are messy: they can have displacements but in inkscape we also + -- see x and y (inner and outer element) + + -- The size is a bit of an issue. I assume that the specified size relates to the + -- designsize but we want to be able to use other fonts. + + do + + local f_styled = formatters["\\svgstyled{%s}{%s}{%s}{%s}"] + local f_colored = formatters["\\svgcolored{%.3N}{%.3N}{%.3N}{"] + local f_placed = formatters["\\svgplaced{%.3N}{%.3N}{}{"] + local f_poschar = formatters["\\svgposchar{%.3N}{%.3N}{%s}"] + local f_char = formatters["\\svgchar{%s}"] + + local f_scaled = formatters["\\svgscaled{%N}{%s}{%s}{%s}"] + local f_normal = formatters["\\svgnormal{%s}{%s}{%s}"] + local f_hashed = formatters["\\svghashed{%s}"] + + -- We move to the outer (x,y) and when we have an inner offset we + -- (need to) compensate for that outer offset. + + -- local f_text_scaled_svg = formatters['(svgtext("%s") scaled %N shifted (%N,%N))'] + -- local f_text_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] + -- local f_text_simple_svg = formatters['svgtext("%s")'] + + local anchors = { + ["start"] = "drt", + ["end"] = "dflt", + ["middle"] = "d", + } + + local f_text_normal_svg = formatters['(textext.%s("%s") shifted (%N,%N))'] + local f_text_simple_svg = formatters['textext.%s("%s")'] + + -- or just maptext + + local f_mapped_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] + local f_mapped_simple_svg = formatters['svgtext("%s")'] + + local cssfamily = css.family + local cssstyle = css.style + local cssweight = css.weight + local csssize = css.size + + local usedfonts = setmetatableindex(function(t,k) + local v = setmetatableindex("table") + t[k] = v + return v + end) + + local p_texescape = lpegpatterns.texescape + + -- For now as I need it for my (some 1500) test files. + + local function checkedfamily(name) + if find(name,"^.-verdana.-$") then + name = "verdana" + end + return name + end + + -- todo: only escape some chars and handle space + + local defaultsize = 10 + + local function collect(t,c,x,y,size,scale,family,tx,ty) + local at = c.at + local ax = rawget(at,"x") + local ay = rawget(at,"y") + local dx = rawget(at,"dx") + local dy = rawget(at,"dy") + local v_fill = at["fill"] + local v_family = at["font-family"] + local v_style = at["font-style"] + local v_weight = at["font-weight"] + local v_size = at["font-size"] + -- + ax = ax and asnumber_vx(ax) or x + ay = ay and asnumber_vy(ay) or y + dx = dx and asnumber_vx(dx) or 0 + dy = dy and asnumber_vy(dy) or 0 + -- + if v_family then v_family = cssfamily(v_family) end + if v_style then v_style = cssstyle (v_style) end + if v_weight then v_weight = cssweight(v_weight) end + if v_size then v_size = csssize (v_size,factors) end + -- + ax = ax - x + ay = ay - y + -- + local elayered = ax ~= 0 or ay ~= 0 or false + local eplaced = dx ~= 0 or dy ~= 0 or false + + local usedsize, usedscaled + + if elayered then + -- we're now at the outer level again so we need to scale + -- back to the outer level values + t[#t+1] = formatters["\\svgsetlayer{%0N}{%0N}{"](ax,-ay) + usedsize = v_size or defaultsize + usedscale = usedsize / defaultsize + else + -- we're nested so we can be scaled + usedsize = v_size or size + usedscale = (usedsize / defaultsize) / scale + end + -- + -- print("element ",c.tg) + -- print(" layered ",elayered) + -- print(" font size ",v_size) + -- print(" parent size ",size) + -- print(" parent scale",scale) + -- print(" used size ",usedsize) + -- print(" used scale ",usedscale) + -- + if eplaced then + t[#t+1] = f_placed(dx,dy) + end + -- + if not v_family then v_family = family end + if not v_weight then v_weight = "normal" end + if not v_style then v_style = "normal" end + -- + if v_family then + v_family = fonts.names.cleanname(v_family) + v_family = checkedfamily(v_family) + end + -- + usedfonts[v_family][v_weight][v_style] = true + -- +-- if usedscale == 1 then +-- t[#t+1] = f_normal( v_family,v_weight,v_style) +-- else + t[#t+1] = f_scaled(usedscale,v_family,v_weight,v_style) +-- end + t[#t+1] = "{" + -- + local ecolored = v_fill and v_fill ~= "" or false + if ecolored then + -- todo cmyk + local r, g, b = colorcomponents(v_fill) + if r and g and b then + t[#t+1] = f_colored(r,g,b) + else + ecolored = false + end + end + -- + local dt = c.dt + local nt = #dt + for i=1,nt do + local di = dt[i] + if type(di) == "table" then + -- can be a tspan (should we pass dx too) + collect(t,di,x,y,usedsize,usedscale,v_family) + else + if i == 1 then + di = gsub(di,"^%s+","") + end + if i == nt then + di = gsub(di,"%s+$","") + end + local chars = utfsplit(di) + if svghash then + di = f_hashed(svghash[di]) + elseif tx then + for i=1,#chars do + chars[i] = f_poschar( + (tx[i] or 0) - x, + (ty[i] or 0) - y, + utfbyte(chars[i]) + ) + end + di = "{" .. concat(chars) .. "}" + else + -- this needs to be texescaped ! and even quotes and newlines + -- or we could register it but that's a bit tricky as we nest + -- and don't know what we can expect here + -- di = lpegmatch(p_texescape,di) or di + for i=1,#chars do + chars[i] = f_char(utfbyte(chars[i])) + end + di = concat(chars) + end + t[#t+1] = di + end + end + -- + if ecolored then + t[#t+1] = "}" + end + -- + t[#t+1] = "}" + -- + if eplaced then + t[#t+1] = "}" + end + if elayered then + t[#t+1] = "}" + end + -- + return t + end + + local s_startlayer = "\\svgstartlayer " + local s_stoplayer = "\\svgstoplayer " + + function handlers.text(c) + local only = fullstrip(xmltextonly(c)) + -- if metapost.processing() then + local at = c.at + local x = rawget(at,"x") + local y = rawget(at,"y") + + local tx = asnumber_vx_t(x) + local ty = asnumber_vy_t(y) + + x = tx[1] or 0 -- catch bad x/y spec + y = ty[1] or 0 -- catch bad x/y spec + + local v_fill = at["fill"] + if not v_fill or v_fill == "none" then + v_fill = "black" + end + local color, opacity, invisible = fillproperties(v_fill,at) + local anchor = anchors[at["text-anchor"] or "start"] or "drt" + local r = metapost.remappedtext(only) + if r then + if x == 0 and y == 0 then + only = f_mapped_simple_svg(r.index) + else + only = f_mapped_normal_svg(r.index,x,y) + end + flushobject(only,at,color,opacity) + if trace_text then + report("text: %s",only) + end + elseif not invisible then -- can be an option + local scale = 1 + local textid = 0 + local result = { } + local nx = #tx + local ny = #ty + -- + result[#result+1] = s_startlayer + if nx > 1 or ny > 1 then + concat(collect(result,c,x,y,defaultsize,1,"serif",tx,ty)) + else + concat(collect(result,c,x,y,defaultsize,1,"serif")) + end + result[#result+1] = s_stoplayer + result = concat(result) + if x == 0 and y == 0 then + result = f_text_simple_svg(anchor,result) + else + result = f_text_normal_svg(anchor,result,x,y) + end + flushobject(result,at,color,opacity) + if trace_text then + report("text: %s",result) + end + elseif trace_text then + report("invisible text: %s",only) + end + -- elseif trace_text then + -- report("ignored text: %s",only) + -- end + end + + function metapost.reportsvgfonts() + for family, weights in sortedhash(usedfonts) do + for weight, styles in sortedhash(weights) do + for style in sortedhash(styles) do + report("used font: %s-%s-%s",family,weight,style) + end + end + end + end + + statistics.register("used svg fonts",function() + if next(usedfonts) then + -- also in log file + logs.startfilelogging(report,"used svg fonts") + local t = { } + for family, weights in sortedhash(usedfonts) do + for weight, styles in sortedhash(weights) do + for style in sortedhash(styles) do + report("%s-%s-%s",family,weight,style) + t[#t+1] = formatters["%s-%s-%s"](family,weight,style) + end + end + end + logs.stopfilelogging() + return concat(t," ") + end + end) + + end + + function handlers.svg(c,x,y,w,h,noclip,notransform,normalize) + local at = c.at + + local wrapupviewport + local bhacked + local ehacked + local wd = w + -- local ex, em + local xpct, ypct, rpct + + local btransform, etransform, transform = handletransform(at) + + if trace then + report("view: %s, xpct %N, ypct %N","before",percentage_x,percentage_y) + end + + local viewbox = at.viewBox + + if viewbox then + x, y, w, h = handleviewbox(viewbox) + if trace then + report("viewbox: x %N, y %N, width %N, height %N",x,y,w,h) + end + end + if not w or not h or w == 0 or h == 0 then + noclip = true + end + if h then + -- + -- em = factors["em"] + -- ex = factors["ex"] + -- factors["em"] = em + -- factors["ex"] = ex + -- + xpct = percentage_x + ypct = percentage_y + rpct = percentage_r + percentage_x = w / 100 + percentage_y = h / 100 + percentage_r = (sqrt(w^2 + h^2) / sqrt(2)) / 100 + if trace then + report("view: %s, xpct %N, ypct %N","inside",percentage_x,percentage_y) + end + wrapupviewport = viewport(x,y,w,h,noclip) + end + -- todo: combine transform and offset here + + -- some fonts need this (bad transforms + viewbox) + if v and normalize and w and wd and w ~= wd and w > 0 and wd > 0 then + bhacked = s_wrapped_start + ehacked = f_wrapped_stop(y or 0,wd/w) + end + if btransform then + r = r + 1 ; result[r] = btransform + end + if bhacked then + r = r + 1 ; result[r] = bhacked + end + local boffset, eoffset = offset(at) + if boffset then + r = r + 1 result[r] = boffset + end + + at["transform"] = false + at["viewBox"] = false + + process(c,"/*") + + at["transform"] = transform + at["viewBox"] = viewbox + + if eoffset then + r = r + 1 result[r] = eoffset + end + if ehacked then + r = r + 1 ; result[r] = ehacked + end + if etransform then + r = r + 1 ; result[r] = etransform + end + if h then + -- + -- factors["em"] = em + -- factors["ex"] = ex + -- + percentage_x = xpct + percentage_y = ypct + percentage_r = rpct + if wrapupviewport then + wrapupviewport() + end + end + if trace then + report("view: %s, xpct %N, ypct %N","after",percentage_x,percentage_y) + end + end + + end + + process = function(x,p) + for c in xmlcollected(x,p) do + local tg = c.tg + local h = handlers[c.tg] + if h then + h(c) + end + end + end + + -- For huge inefficient files there can be lots of garbage to collect so + -- maybe we should run the collector when a file is larger than say 50K. + + function metapost.svgtomp(specification,pattern,notransform,normalize) + local mps = "" + local svg = specification.data + if type(svg) == "string" then + svg = xmlconvert(svg) + end + if svg then + local c = xmlfirst(svg,pattern or "/svg") + if c then + root = svg + result = { } + r = 0 + definitions = { } + tagstyles = { } + classstyles = { } + colormap = specification.colormap + usedcolors = trace_colors and setmetatableindex("number") or false + for s in xmlcollected(c,"style") do -- can also be in a def, so let's play safe + handlestyle(c) + end + handlechains(c) + xmlinheritattributes(c) -- put this in handlechains + handlers.svg ( + c, + specification.x, + specification.y, + specification.width, + specification.height, + specification.noclip, + notransform, + normalize, + specification.remap + ) + if trace_result then + report("result graphic:\n %\n t",result) + end + if usedcolors and next(usedcolors) then + report("graphic %a uses colors: %s",specification.id or "unknown",table.sequenced(usedcolors)) + end + mps = concat(result," ") + root = false + result = false + r = false + definitions = false + tagstyles = false + classstyles = false + colormap = false + else + report("missing svg root element") + end + else + report("bad svg blob") + end + return mps + end + +end + +-- These helpers might move to their own module .. some day ... also they will become +-- a bit more efficient, because we now go to mp and back which is kind of redundant, +-- but for now it will do. + +do + + local bpfactor = number.dimenfactors.bp + + function metapost.includesvgfile(filename,offset) -- offset in sp + if lfs.isfile(filename) then + context.startMPcode("doublefun") + context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) + context.stopMPcode() + end + end + + function metapost.includesvgbuffer(name,offset) -- offset in sp + context.startMPcode("doublefun") + context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) + context.stopMPcode() + end + + interfaces.implement { + name = "includesvgfile", + actions = metapost.includesvgfile, + arguments = { "string", "dimension" }, + } + + interfaces.implement { + name = "includesvgbuffer", + actions = metapost.includesvgbuffer, + arguments = { "string", "dimension" }, + } + + function metapost.showsvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then + local comment = data.comment + local offset = data.pageoffset + local index = data.index + local first = math.max(index or 1,1) + local last = math.min(index or #dd,#dd) + for i=first,last do + local d = setmetatableindex( { + data = dd[i], + comment = comment and i or false, + pageoffset = offset or nil, + }, data) + metapost.showsvgpage(d) + end + elseif data.method == "code" then + context.startMPcode(doublefun) + context(metapost.svgtomp(data)) + context.stopMPcode() + else + context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } + context(metapost.svgtomp(data)) + local comment = data.comment + if comment then + context("draw boundingbox currentpicture withcolor .6red ;") + context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) + end + context.stopMPpage() + end + end + + function metapost.typesvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then + local index = data.index + if index and index > 0 and index <= #dd then + data = dd[index] + else + data = nil + end + end + if type(data) == "string" and data ~= "" then + buffers.assign("svgpage",data) + context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) + end + end + + function metapost.svgtopdf(data,...) + local mps = metapost.svgtomp(data,...) + if mps then + -- todo: special instance, only basics needed + local pdf = metapost.simple("metafun",mps,true,false,"svg") + if pdf then + return pdf + else + -- message + end + else + -- message + end + end + +end + +do + + local runner = sandbox.registerrunner { + name = "otfsvg2pdf", + program = "context", + template = "--batchmode --purgeall --runs=2 %filename%", + reporter = report_svg, + } + + -- By using an independent pdf file instead of pdf streams we can use resources and still + -- cache. This is the old method updated. Maybe a future version will just do this runtime + -- but for now this is the most efficient method. + + local decompress = gzip.decompress + local compress = gzip.compress + + function metapost.svgshapestopdf(svgshapes,pdftarget,report_svg) + local texname = "temp-otf-svg-to-pdf.tex" + local pdfname = "temp-otf-svg-to-pdf.pdf" + local tucname = "temp-otf-svg-to-pdf.tuc" + local nofshapes = #svgshapes + local pdfpages = { filename = pdftarget } + local pdfpage = 0 + local t = { } + local n = 0 + -- + os.remove(texname) + os.remove(pdfname) + os.remove(tucname) + -- + if report_svg then + report_svg("processing %i svg containers",nofshapes) + statistics.starttiming(pdfpages) + end + -- + -- can be option: + -- + -- n = n + 1 ; t[n] = "\\nopdfcompression" + -- + n = n + 1 ; t[n] = "\\starttext" + n = n + 1 ; t[n] = "\\setupMPpage[alternative=offset,instance=doublefun]" + -- + for i=1,nofshapes do + local entry = svgshapes[i] + local data = entry.data + if decompress then + data = decompress(data) or data + end + local specification = { + data = xmlconvert(data), + x = 0, + y = 1000, + width = 1000, + height = 1000, + noclip = true, + } + for index=entry.first,entry.last do + if not pdfpages[index] then + pdfpage = pdfpage + 1 + pdfpages[index] = pdfpage + local pattern = "/svg[@id='glyph" .. index .. "']" + n = n + 1 ; t[n] = "\\startMPpage" + n = n + 1 ; t[n] = metapost.svgtomp(specification,pattern,true,true) or "" + n = n + 1 ; t[n] = "\\stopMPpage" + end + end + end + n = n + 1 ; t[n] = "\\stoptext" + io.savedata(texname,concat(t,"\n")) + runner { filename = texname } + os.remove(pdftarget) + file.copy(pdfname,pdftarget) + if report_svg then + statistics.stoptiming(pdfpages) + report_svg("svg conversion time %s",statistics.elapsedseconds(pdfpages)) + end + os.remove(texname) + os.remove(pdfname) + os.remove(tucname) + return pdfpages + end + + function metapost.svgshapestomp(svgshapes,report_svg) + local nofshapes = #svgshapes + local mpshapes = { } + if report_svg then + report_svg("processing %i svg containers",nofshapes) + statistics.starttiming(mpshapes) + end + for i=1,nofshapes do + local entry = svgshapes[i] + local data = entry.data + if decompress then + data = decompress(data) or data + end + local specification = { + data = xmlconvert(data), + x = 0, + y = 1000, + width = 1000, + height = 1000, + noclip = true, + } + for index=entry.first,entry.last do + if not mpshapes[index] then + local pattern = "/svg[@id='glyph" .. index .. "']" + local mpcode = metapost.svgtomp(specification,pattern,true,true) or "" + if mpcode ~= "" and compress then + mpcode = compress(mpcode) or mpcode + end + mpshapes[index] = mpcode + end + end + end + if report_svg then + statistics.stoptiming(mpshapes) + report_svg("svg conversion time %s",statistics.elapsedseconds(mpshapes)) + end + return mpshapes + end + + function metapost.svgglyphtomp(fontname,unicode) + if fontname and unicode then + local id = fonts.definers.internal { name = fontname } + if id then + local tfmdata = fonts.hashes.identifiers[id] + if tfmdata then + local properties = tfmdata.properties + local svg = properties.svg + local hash = svg and svg.hash + local timestamp = svg and svg.timestamp + if hash then + local svgfile = containers.read(fonts.handlers.otf.svgcache,hash) + local svgshapes = svgfile and svgfile.svgshapes + if svgshapes then + if type(unicode) == "string" then + unicode = utfbyte(unicode) + end + local chardata = tfmdata.characters[unicode] + local index = chardata and chardata.index + if index then + for i=1,#svgshapes do + local entry = svgshapes[i] + if index >= entry.first and index <= entry.last then + local data = entry.data + if data then + local root = xml.convert(gzip.decompress(data) or data) + return metapost.svgtomp ( + { + data = root, + x = 0, + y = 1000, + width = 1000, + height = 1000, + noclip = true, + }, + "/svg[@id='glyph" .. index .. "']", + true, + true + ) + end + end + end + end + end + end + end + end + end + end + +end diff --git a/tex/context/base/mkxl/mult-aux.mkxl b/tex/context/base/mkxl/mult-aux.mkxl new file mode 100644 index 000000000..9c8613783 --- /dev/null +++ b/tex/context/base/mkxl/mult-aux.mkxl @@ -0,0 +1,1177 @@ +%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. + +%D A generalization of \MKIV-like inheritance. Just something to play with +%D (interface might change). The code here evolved in an email exchange between me +%D and Wolgang Schuster. + +\writestatus{loading}{ConTeXt Multilingual Macros / Helpers} + +\registerctxluafile{mult-aux}{} + +\unprotect + +\immutable\edef\??empty{\Uchar25} \immutable\letvalue{\Uchar25}\empty % hex 19 + +% \edef\s!parent{\Uchar29} % inlining  is ugly, a tiny bit faster, but neglectable on a run + +%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 + +%D Start of experimental code: especially tables can have many assignments and +%D although most time is spent in the typesetting anyway, we can squeeze out a +%D little bit. Of course having 500 rows of 50 columns each with some setting does +%D not happen that often. One should keep in mind that in the average document +%D having some 500 assignments is no exception but there we're talking of +%D neglectable runtime for them. Of course in the definitions below there is no real +%D gain, only in the generated \setup* commands. Another situation with many +%D assignments is \XML\ where we can pass attributes and normally don't do testing +%D 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 + +% KEEP THIS: +% +% \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,],^^^^0004} +% +% \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 +% \orelse\if]#1% +% \expandafter\gobbleoneargument +% \else +% \mult_interfaces_get_parameters_assign#1==\empty^^^^0004% +% % \expandafter\mult_interfaces_get_parameters_item % saves skipping when at end +% \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#0^^^^0004% +% {\ifx\empty#1\empty +% \expandafter\mult_interfaces_get_parameters_error +% \orelse\ifx#3\empty +% \expandafter\mult_interfaces_get_parameters_error +% \else +% \expandafter\mult_interfaces_adef % assignment def +% \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#0\csname#2#3\endcsname#0% +% {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue} +% +% \def\mult_interfaces_get_parameters_error_two#0\csname#2#3\endcsname#0% +% {\mult_interfaces_get_parameters_error_indeed{#2}{#3}} +% +% \def\mult_interfaces_get_parameters_assign#1=#2=#3#0^^^^0004% +% {\ifx\empty#1\empty +% \mult_interfaces_get_parameters_error_one +% \orelse\ifx#3\empty +% \mult_interfaces_get_parameters_error_two +% \else +% \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}% +% \fi +% \doubleexpandafter\mult_interfaces_get_parameters_item} +% +% \stopinterface +% +% \newif\ifassignment +% +% \def\mult_check_for_assignment_indeed#0=#2#0^^^^0004% +% {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi} +% +% \def\mult_check_for_assignment_indeed_begin_#0=#2#0^^^^0004% +% {\if#2^^^^0003} +% +% \def\mult_check_for_assignment#1% +% {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004} +% +% % End of experimental code. + +%D We keep the above as reference, btu from now on experiment with the following +%D implementation. In principle this one is faster, but because normally we don't +%D have that many assignments it doesn't get noticed. For instance, the \LUAMETATEX\ +%D manual does less than 6000 assignments and the payoff starts around a tenfold of +%D that. But \unknown\ it's less tracing, so that's another benefit. + +%D Watch out: we accept that a \[k=v,,k=v] will generate a case where a key can become +%D a comma and trigger a warning but we intercept that elsewhere. The alternative is +%D to skip to the comma first which takes more time. + +\let\m_mult_interfaces_namespace\empty + +\def\mult_interfaces_get_parameters#1[% + {\def\m_mult_interfaces_namespace{#1}% + \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed} + +\def\mult_interfaces_get_parameters_indeed#1]% + {\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments} + +\def\mult_interfaces_get_parameters_item#*#1,% + {\ifarguments \else + \mult_interfaces_get_parameters_item_okay#1,\ignorearguments + \expandafter\mult_interfaces_get_parameters_item + \fi} + +\def\mult_interfaces_get_parameters_item_okay#1=#2,% + {\ifarguments + % done + \or + \mult_interfaces_get_parameters_item_error + \else + \mult_interfaces_adef\m_mult_interfaces_namespace{#1}{#2}% + \fi} + +% \def\mult_interfaces_get_parameters_item_error#0#0#0#4#5% +% {\if,#5\else\mult_interfaces_get_parameters_error_indeed{#4}{#5}\fi} + +\def\mult_interfaces_get_parameters_item_error#-#-#-#1#2% + {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi} + +\startinterface english + + \def\mult_interfaces_get_parameters_item_okay#1=#2,% + {\ifarguments + % done + \or + \mult_interfaces_get_parameters_item_error + \else + \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}% + \fi} + + \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-% + {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi} + +\stopinterface + +%D Used? + +\def\mult_check_for_assignment_indeed#-=#1#-^^^^0004% + {\if#1^^^^0003\assignmentfalse\else\assignmenttrue\fi} + +\def\mult_check_for_assignment_indeed_begin_#-=#1#-^^^^0004% + {\if#1^^^^0003} + +\def\mult_check_for_assignment#1% + {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=^^^^0003^^^^0003^^^^0004} + +%D Beware, zero arguments is an assignment! + +\def\mult_aux_no_assignment_indeed#1=#2]{\ifcase\ifarguments\plusone\or\zerocount\else\plusone\fi} +\def\mult_aux_no_assignment#1]{\mult_aux_no_assignment_indeed#1\ignorearguments\relax} + +%D This can give wrong results when we pass e.g. \type{\c!format}, so either we need +%D to use the \type {\k!} ones, but these are not defined in the english interface +%D so from now on we assume that the low level ones are used with the symbolic names +%D and that only the high level setup commands are used with language specific +%D interfaces. + +% \startinterface english + \protected\def\mult_interfaces_let #1#2{\letcsname#1#2\endcsname} + \protected\def\mult_interfaces_lete#1#2{\letcsname#1#2\endcsname\empty} + \protected\def\mult_interfaces_def #1#2{\defcsname#1#2\endcsname} + \protected\def\mult_interfaces_edef#1#2{\edefcsname#1#2\endcsname} + \protected\def\mult_interfaces_gdef#1#2{\gdefcsname#1#2\endcsname} + \protected\def\mult_interfaces_xdef#1#2{\xdefcsname#1#2\endcsname} +% \stopinterface + +%D Do, we only interface the assignment definition: + +\protected\def\mult_interfaces_adef#1#2{\defcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} + +\startinterface english + \protected\def\mult_interfaces_adef#1#2{\defcsname#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 +% +% slower: \def#3##1{\csname\ifcsname#1#2:##1\endcsname\expandafter\csstring\lastnamedcs\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% + +%D pre-expansion can be a bit faster but handly any effect on a normal run so let's +%D go for saving some memory + +\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter} + +\protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% + {\frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% + \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + \frozen\edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ? + \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% + \frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack + \frozen\def#8##1{\begincsname#1#2:##1\endcsname}% + % TODO + \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}} + +\permanent\protected\def\installparameterhandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \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 direct#2parameter\endcsname + \expandafter\noexpand\csname letfrom#2parameter\endcsname}} % strict#2parameter is gone + +\protected\def\mult_interfaces_install_root_parameter_handler#1#2#3% + {\frozen\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root + \frozen\def#3##1{\begincsname#1:##1\endcsname}} + +\permanent\protected\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}} + +\protected\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9% + {\frozen\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? + \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + \frozen\def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}% + \frozen\def#6{#1#2:}% + \frozen\def#7##1{#1##1:}% + \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname#1#2:\s!parent\endcsname#1\fi}% + \frozen\protected\def#9##1{\edefcsname#1##1:\s!parent\endcsname{#1#2}}} + +\permanent\protected\def\installparameterhashhandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \immutable\letcsname#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}} + +%D In \MKIV\ we can probably use the english variant for all other languages too. + +% todo: inline the def/let + +% \startinterface english + \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% + {\frozen\protected\def#3##1{\defcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \frozen\protected\def#4##1{\edefcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \frozen\protected\def#5##1{\letcsname#1#2:##1\endcsname}% ##1 ##2 + \frozen\protected\def#6##1{\letcsname#1#2:##1\endcsname\empty}}% ##1 +% \stopinterface + +\permanent\protected\def\installparametersethandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \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 + +\protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4% + {\frozen\protected\def#2##1##2% style color + {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline) + \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi + \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch) + \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}% + \frozen\protected\def#3##1% style + {\edef\currentstyleparameter{#1{##1}}% this name is public + \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}% + \frozen\protected\def#4##1% color + {\edef\currentcolorparameter{#1{##1}}% this name is public + \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}} + +\permanent\protected\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\orelse\ifx#4\empty\else + \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}% + \edefcsname#1#4:\s!parent\endcsname{#2}% + \fi} + + \def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi} +\permanent\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname} +\permanent\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname} + +% we could have a \setcurrent... macro and then always make them a frozen +% but it might have a little impact on performance ... something to leave +% to when we're done with the transition (it's kind of massive) + +\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8% why is \expanded still needed in clones + {\newtoks#5% + \newtoks#6% + \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] + {\let#8#4% + % watch out: no \edef#4{##1} before the ifarguments because #1 can have macros + \ifarguments + \let#4\empty + \the#5% predefine + \let#7\empty + \letcsname#1#4:\s!chain\endcsname\empty + \edefcsname#1#4:\s!parent\endcsname{#3}% + \or + \edef#4{##1}% + \the#5% predefine + \let#7\empty + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% + \or + \edef#4{##1}% + \the#5% predefine + \relax + \ifhastok={##2}% + \let#7\empty + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% + \mult_interfaces_get_parameters{#1#4:}[##2]% + \else + \edef#7{##2}% + \ifempty#7% + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% + \else + \mult_check_for_parent{#1}{#3}#4#7% + \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \edefcsname#1#4:\s!parent\endcsname{#1##2}% + \fi + \fi + \or + \edef#4{##1}% + \the#5% predefine + \edef#7{##2}% + \mult_check_for_parent{#1}{#3}#4#7% + \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \edefcsname#1#4:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#4:}[##3]% + \fi + \the#6% + \let#4#8}} + +\permanent\protected\def\installdefinehandler#1#2#3% + {\mutable\letcsname current#2\endcsname\empty + \mutable\letcsname current#2parent\endcsname\empty + \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 everypreset#2\endcsname + \expandafter\noexpand\csname everydefine#2\endcsname + \expandafter\noexpand\csname current#2parent\endcsname + \expandafter\noexpand\csname saved_defined_#2\endcsname}} + +\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% + {\newtoks#4% + \newtoks#7% + \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it + \frozen\tolerant\protected\def#2[##1]##*[##2]% maybe helper + {\let#6#3% + \ifnum\lastarguments=\plustwo + \def#8####1% we will have a simple one as well + {\edef#3{####1}% + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#4}% + \processcommalist[##1]#8% + \else + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#4% + \fi + \let#3#6% + \the#7}} + +\permanent\protected\def\installsetuphandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \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}} + +\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value] +\let\doingrootsetuproot \plustwo % \setuplayout [key=value] +\let\doingrootsetnamed \plusthree % \setuplayout[name] +\let\doingrootsetroot \plusfour % \setuplayout + +\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3% + {\frozen\protected\def#3{\mult_interfaces_get_parameters{#1#2:}}} + +\protected\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% + {\newtoks#5% + \newconstant#2% + \newtoks#8% + \newtoks#9% + \frozen\tolerant\protected\def#4[##1]##*[##2]% maybe helper + {\ifarguments + % \setuplayout + \let#6#3% % previous becomes current + \let#3\empty % current becomes empty + #2\doingrootsetroot + \the#5% + \the#8% switchsetups + \or + \ifhastok={##1}% + % \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 + \ifempty#3% + \let#7#6% + #2\doingrootsetuproot + \the#5% + \the#8% switchsetups + \let#3#7% + \else + #2\doingrootsetnamed + \the#5% % we can check for previous vs current + \the#8% switchsetups + \fi + \fi + \or + % \setuplayout[whatever][key=value] + \let#7#3% + \let#6#3% + \edef#3{##1}% + #2\doingrootsetupnamed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#5% + \ifx#3#6\the#8\fi % only switchsetups if previous == current + \let#3#7% + \fi + #2\zerocount % mode is always zero at the end + \the#9}} + +\permanent\protected\def\installswitchsetuphandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \mutable\letcsname previous#2\endcsname\empty + \normalexpanded + {\mult_interfaces_install_switch_setup_handler_a + {\noexpand#1}% \??aa + \expandafter\noexpand\csname current#2\endcsname + \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 + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname previous#2\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname everyswitch#2\endcsname + \expandafter\noexpand\csname everysetup#2root\endcsname}} + +\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% + {\newtoks#4% + \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% + \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% + {\let#7#3% + \ifarguments + \let#3\empty + \the#5% + \or + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#4% + \or + \def#8####1% + {\edef#3{####1}% + #6% checks parent and sets if needed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#4}% + \processcommalist[##1]#8% + \or + \def#8####1% + {\edef#3{####1}% + \defcsname#1#3:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent + \the#4}% + \processcommalist[##1]#8% + \fi + \let#3#7}} + +\permanent\protected\def\installautosetuphandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \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}} + +\permanent\protected\def\installbasicparameterhandler#1#2% + {\installparameterhandler {#1}{#2}% + \installparameterhashhandler{#1}{#2}% + \installparametersethandler {#1}{#2}% + \installrootparameterhandler{#1}{#2}} + +\permanent\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installautosetuphandler {#1}{#2}} + +\permanent\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installautosetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\permanent\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installsetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\permanent\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installswitchsetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\permanent\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installautosetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\permanent\protected\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 the +%D speed||critical ones. Therefore there is no reason to stick to \type {\@@xxkey} +%D for the sake of performance. For this reason we also provide a direct variant. +%D This permits a more consistent treatment of namespaces. A \type +%D {\whateverparameter} call is three times slower and a \type +%D {\directwhateverparameter} call two times but for some 100K expansions we only +%D loose some .1 second which is neglectable given the small amount of expansions in +%D real runs. + +%D We don't need colons for such simple cases. + +\protected\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5% + {\frozen\def#3##1{\begincsname#1##1\endcsname}% + \frozen\def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% + \frozen\def#5##1{\begincsname#1##1\endcsname}} + +\permanent\protected\def\installdirectparameterhandler#1#2% + {\mutable\letcsname current#2\endcsname\empty + \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}} + +\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4% + {\newtoks#4% + \frozen\protected\def#2[##1]{\ifarguments\or\mult_interfaces_get_parameters#1[##1]\fi\the#4}% + \frozen\def#3{\mult_interfaces_get_parameters#1}} + +\permanent\protected\def\installdirectsetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_direct_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency) + \expandafter\noexpand\csname everysetup#2\endcsname}} + +% \startinterface english + \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% + {\frozen\protected\def#2##1{\defcsname#1##1\endcsname}% + \frozen\protected\def#3##1{\edefcsname#1##1\endcsname}% + \frozen\protected\def#4##1{\letcsname#1##1\endcsname}% + \frozen\protected\def#5##1{\letcsname#1##1\endcsname\empty}}% +% \stopinterface + +\permanent\protected\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}} + +\aliased\let\installdirectstyleandcolorhandler\installstyleandcolorhandler + +\permanent\protected\def\installdirectcommandhandler#1#2% + {\installdirectparameterhandler {#1}{#2}% + \installdirectsetuphandler {#1}{#2}% + \installdirectparametersethandler {#1}{#2}% + \installdirectstyleandcolorhandler{#1}{#2}} + +\permanent\protected\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 + +\permanent\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} + {\immutable\edefcsname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} + +\permanent\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance} + {\edefcsname#1#2:\s!parent\endcsname{#3#4}} + +%D Here is another experiment: + +\protected\def\mult_interfaces_install_action_handler#1#2#3% + {\frozen\tolerant\protected\defcsname#1\endcsname[##1]##*[##2]% + {\begingroup + \ifarguments + \let#2\empty + \or + %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004% + % \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments + % \edef#2{##1}% + % \else + % \let#2\empty + % #3[##1]% + % \fi + \ifhastok={##1}% + \let#2\empty + #3[##1]% + \else + \edef#2{##1}% + \fi + \or + \edef#2{##1}% + #3[##2]% + \fi + \directsetup{handler:action:#1}% + \endgroup}} + +\permanent\protected\def\installactionhandler#1% + {\mutable\letcsname current#1\endcsname\empty + \normalexpanded + {\mult_interfaces_install_action_handler + {#1}% + \expandafter\noexpand\csname current#1\endcsname + \expandafter\noexpand\csname setupcurrent#1\endcsname}} + +% First we had, in tune with the regular system variables: +% +% \starttyping +% \protected\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>} + +\permanent\protected\def\installnamespace#1% for modules and users + {\ifcsname ????#1\endcsname + \writestatus\m!system{duplicate user namespace '#1'}\wait + \else + \global\advance\c_mult_interfaces_n_of_namespaces\plusone + \immutable\edefcsname ????#1\endcsname{\v_interfaces_prefix_template}% + \fi} + +\permanent\protected\def\installcorenamespace#1% + {\ifcsname ??#1\endcsname + \writestatus\m!system{duplicate core namespace '#1'}\wait + \else + \global\advance\c_mult_interfaces_n_of_namespaces\plusone + \immutable\edefcsname ??#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} + +% 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 + +\permanent \def\dummyparameter #1{\begincsname\??dummy#1\endcsname} +\permanent \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname} +\permanent\protected\def\setdummyparameter #1{\defcsname\??dummy#1\endcsname} +\permanent\protected\def\setexpandeddummyparameter#1{\edefcsname\??dummy#1\endcsname} +\permanent\protected\def\letdummyparameter #1{\letcsname\??dummy#1\endcsname} + +\edef\mult_interfaces_dummy{\??dummy} % nor immutable + +\permanent\protected\def\getdummyparameters[#1% + {\if\noexpand#1]% + \expandafter\gobbleoneargument + \else + \let\m_mult_interfaces_namespace\mult_interfaces_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: + +\permanent\tolerant\protected\def\definenamespace[#1]#*[#2]% namespace settings + {\clf_definenamespace{#1}{#2}} + +\permanent\protected\def\listnamespaces + {\clf_listnamespaces} + +%D Helper: +%D +%D \starttyping +%D \showparentchain{@@am}{left} +%D \stoptyping + +\permanent\protected\def\showparentchain#1#2% + {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}} + +\def\mult_interfaces_show_parent_chain#1% + {#1 => % + \ifcsname#1:\s!parent\endcsname + \expandafter\mult_interfaces_show_parent_chain\lastnamedcs + \fi} + +%D Another helper (needs to be applied): + +\permanent\protected\def\doifelsecommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifcommandhandlerelse\doifelsecommandhandler + +\permanent\protected\def\doifcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +% another set of (fast) helpers (grep for usage): + +\permanent\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy + {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3} + +\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy + {#1\endcsname#1\else#2\fi\endcsname} + +\permanent\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy + {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} + +\permanent\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname + {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}} + +\def\syst_helpers_expand_checked_value#1#2% + {#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 + +\let\c_mult_set\relax + +\protected\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7% + {\newcount#3% + \let#6\empty + \protected\def#2% + {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname + \ifx\c_mult_set\relax + \expandafter\newtoks\c_mult_set + \letcsname#1_t_#6\endcsname\c_mult_set + \fi} + \frozen\protected\def#4##1% + {\pushmacro#6% + \advance#3\plusone + \edef#6{##1}% + \unprotect}% + \frozen\protected\def#5% + {\protect + \advance#3\minusone + \popmacro#6}% + \frozen\protected\def#7##1% + {\edef#6{##1}% + #2% + \the\c_mult_set\relax}} + +\permanent\protected\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}} + +\protected\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc + {\let#5#2% + \frozen\protected\def#2% + {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}% + \tolerant\protected\def#6[##1]##*[##2]% + {\ifarguments\or + #3\toksapp\c_mult_set{#7[##1]}% + \or + #3\toksapp\c_mult_set{#8[##1][##2]}% + \fi}} + +\permanent\protected\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 setup#4_\s!single\endcsname + \expandafter\noexpand\csname setup#4_\s!double\endcsname}} + +%D Another experiment: + +\protected\def\mult_interfaces_install_parent_injector#1#2#3#4% + {\frozen\protected\def#4##1% + {\ifempty#3% + \defcsname#1#2:\s!parent\endcsname{#1##1}% + \fi}} + +\permanent\protected\def\installparentinjector#1#2% + {\normalexpanded{\mult_interfaces_install_parent_injector + {\noexpand#1}% + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname current#2parent\endcsname + \expandafter\noexpand\csname inject#2parent\endcsname}} + +% The \LUA\ based variant is twice as fast as the above but as said, we don't use +% this one that often. It's more about less tracing than speed here. + +\permanent\protected\def\installmacrostack#1% + {\ifdefined#1\else\mutable\let#1\empty\fi + \protected\gdefcsname push_macro_\csstring#1\endcsname{\localpushmacro#1}% + \protected\gdefcsname pop_macro_\csstring#1\endcsname{\localpopmacro #1}} + +\permanent\protected\def\installglobalmacrostack#1% + {\ifdefined#1\else\mutable\glet#1\empty\fi + \protected\gdefcsname push_macro_\csstring#1\endcsname{\globalpushmacro#1}% + \protected\gdefcsname pop_macro_\csstring#1\endcsname{\globalpopmacro #1}} + +% \showmacrostack can be used to see if there are different entries + +% \unprotect +% +% \installcorenamespace {test} \installcommandhandler \??test {test} \??test +% \protected\def\TestMeA[#1]% +% {\edef\currenttest{#1} +% \edef\p_before{\testparameter\c!before}% +% \ifx\p_before\empty \relax \else \relax \fi} +% \protected\def\TestMeB[#1]% +% {\edef\currenttest{#1} +% \doifelsenothing{\testparameter\c!before}\relax\relax} +% \protected\def\TestMeC[#1]% +% {\edef\currenttest{#1} +% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi} +% \protected\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] +% \testfeatureonce{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502 +% \testfeatureonce{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530 +% \testfeatureonce{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487 +% \testfeatureonce{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493 +% \stoptext + +% There is no real demand for this ... even if this is two to three times as fast we +% only gain a few milliseconds: +% +% \starttyping +% \protected\def\foo#1{[foo:#1]} +% +% \installcommalistprocessor {foo} \foo +% \installcommalistprocessorcommand \processfoolist \foo +% +% \infofont +% +% \commalistprocessor{foo}[a,b,c,{x,y,z},d]\par +% \processfoolist[a, b, c, {x,y,z}, d]\par +% \processcommalist[{x,y,z}]\foo\blank +% +% \commalistprocessor{foo}[{x,y,z},a]\par +% \commalistprocessor{foo}[{x,y,z}]\par +% \processfoolist[{x,y,z},a]\par +% \processfoolist[{x,y,z}]\par +% \processcommalist[{x,y,z}]\foo\blank +% +% \protected\def\foo#1{} +% +% \testfeatureonce{400000}{\processfoolist [fixed,middle,bar]} \elapsedtime\quad +%%\testfeatureonce{400000}{\commalistprocessor{foo}[fixed,middle,bar]} \elapsedtime\quad +% \testfeatureonce{400000}{\processcommalist [fixed,middle,bar]\foo} \elapsedtime\quad +% \stoptyping +% +% For instance the luatex manual only has some 3000 calls. But I keep this around as one +% never knows when we might need it. + +\installcorenamespace{commalistprocessor} +\installcorenamespace{commalistprocessorwrap} +\installcorenamespace{commalistprocessorfirst} +\installcorenamespace{commalistprocessornext} +\installcorenamespace{commalistprocessoraction} + +\permanent\protected\def\installcommalistprocessor#1#2% 5 macro names overhead + {\protected\edefcsname\??commalistprocessor#1\endcsname[% + {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {} + \protected\edefcsname\??commalistprocessorwrap#1\endcsname##1]% + {\csname\??commalistprocessorfirst#1\endcsname##1,]} + \protected\edefcsname\??commalistprocessorfirst#1\endcsname\relax + {\csname\??commalistprocessornext#1\endcsname}% + \protected\edefcsname\??commalistprocessornext#1\endcsname + {\noexpand\futureexpandis]% + \noexpand\gobbleoneargument + \csname\??commalistprocessoraction#1\endcsname} + \protected\edefcsname\??commalistprocessoraction#1\endcsname##1,% + {\noexpand#2{##1}% + \csname\??commalistprocessornext#1\endcsname}} + +\permanent\protected\def\installcommalistprocessorcommand#1#2% \processor \action + {\edef\p_name{\csstring#2}% + \installcommalistprocessor\p_name{#2}% + \expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname} + +\permanent\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname} + +\protect \endinput diff --git a/tex/context/base/mkxl/mult-def.mkxl b/tex/context/base/mkxl/mult-def.mkxl new file mode 100644 index 000000000..13e22dade --- /dev/null +++ b/tex/context/base/mkxl/mult-def.mkxl @@ -0,0 +1,32 @@ +%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} + +\immutable\setvalue{\??multilingual czech}{cs} +\immutable\setvalue{\??multilingual german}{de} +\immutable\setvalue{\??multilingual english}{en} +\immutable\setvalue{\??multilingual french}{fr} +\immutable\setvalue{\??multilingual italian}{it} +\immutable\setvalue{\??multilingual dutch}{nl} +\immutable\setvalue{\??multilingual persian}{pe} +\immutable\setvalue{\??multilingual romanian}{ro} + +\permanent\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\lastnamedcs\else en\fi} +\permanent\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\lastnamedcs\else en\fi} + +\clf_setuserinterface{\userinterfacetag}{\userresponsestag} + +\protect \endinput diff --git a/tex/context/base/mkxl/mult-dim.mklx b/tex/context/base/mkxl/mult-dim.mklx new file mode 100644 index 000000000..0526b3775 --- /dev/null +++ b/tex/context/base/mkxl/mult-dim.mklx @@ -0,0 +1,156 @@ +%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 dimension setters. +%D +%D \starttyping +%D \assigndimension +%D {|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} + +\immutable\setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint} +\immutable\setvalue{\??dimensionnormal \empty }#value#dimension#small#medium#big{#dimension\zeropoint} +\immutable\setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax} +\immutable\setvalue{\??dimensionnormal \v!medium}#value#dimension#small#medium#big{#dimension=#medium\relax} +\immutable\setvalue{\??dimensionnormal \v!big }#value#dimension#small#medium#big{#dimension=#big\relax} +\immutable\setvalue{\??dimensionnormal-\v!small }#value#dimension#small#medium#big{#dimension=-#small\relax} +\immutable\setvalue{\??dimensionnormal-\v!medium}#value#dimension#small#medium#big{#dimension=-#medium\relax} +\immutable\setvalue{\??dimensionnormal-\v!big }#value#dimension#small#medium#big{#dimension=-#big\relax} +\immutable\letvalue{\??dimensionnormal\s!unknown}\assign_dimension_direct + +\permanent\protected\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 {|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}} + +\immutable\setvalue{\??dimensionalfa\v!none }#value#macro#small#medium#big{\let #macro\!!zerocount} +\immutable\setvalue{\??dimensionalfa\v!small }#value#macro#small#medium#big{\edef#macro{#small}} +\immutable\setvalue{\??dimensionalfa\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}} +\immutable\setvalue{\??dimensionalfa\v!big }#value#macro#small#medium#big{\edef#macro{#big}} +\immutable\letvalue{\??dimensionalfa\s!unknown}\assign_alpha_dimension_direct + +\permanent\protected\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 {|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}} + +\immutable\setvalue{\??dimensionvalue\v!small }#value#macro#small#medium#big{\edef#macro{#small}} +\immutable\setvalue{\??dimensionvalue\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}} +\immutable\setvalue{\??dimensionvalue\v!big }#value#macro#small#medium#big{\edef#macro{#big}} +\immutable\letvalue{\??dimensionvalue\s!unknown}\assign_value_direct + +\permanent\protected\def\assignvalue#value% + {\ifcsname\??dimensionvalue#value\endcsname + \expandafter\lastnamedcs + \else + \expandafter\assign_value_direct + \fi{#value}} + +%D \macros +%D {assignwidth} +%D +%D This one is used a few times. +%D +%D \starttyping +%D \assignwidth +%D {|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 ... + +\immutable\setvalue{\??dimensionwidth }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width + \setbox\b_assign_width\emptybox} +\immutable\setvalue{\??dimensionwidth\v!fit }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width + \setbox\b_assign_width\emptybox} +\immutable\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} +\immutable\setvalue{\??dimensionwidth\v!line }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width + \setbox\b_assign_width\emptybox} +\immutable\letvalue{\??dimensionwidth\s!unknown}\assign_width_direct + +\permanent\protected\def\assignwidth#value% + {\ifcsname\??dimensionwidth#value\endcsname + \expandafter\lastnamedcs + \else + \expandafter\assign_width_direct + \fi{#value}} + +\protect \endinput diff --git a/tex/context/base/mkxl/mult-ini.mkxl b/tex/context/base/mkxl/mult-ini.mkxl new file mode 100644 index 000000000..70db84b2d --- /dev/null +++ b/tex/context/base/mkxl/mult-ini.mkxl @@ -0,0 +1,805 @@ +%D \module +%D [ file=mult-ini, +%D version=2008.10.22, % 1996.06.01, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is a stripped down version of \type {mult-ini.tex}, which we keep +%D around as \type {mult-kep.tex} for sentimental reasons. There you will find some +%D more historic information. + +\writestatus{loading}{ConTeXt Multilingual Macros / Initialization} + +\unprotect + +\registerctxluafile{mult-ini}{} +\registerctxluafile{mult-fmt}{initexonly} + +%D \macros +%D [constanten,variabelen,commands] +%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!} +%D +%D In the system modules we introduced some prefixed constants, variables (both +%D macros) and registers. Apart from a tremendous saving in terms of memory and a +%D gain in speed we use from now on prefixes when possible for just another reason: +%D consistency and multi||linguality. Systematically using prefixed macros enables +%D us to implement a multi||lingual user interface. Redefining these next set of +%D prefixes therefore can have desastrous results. +%D +%D \startlinecorrection +%D \starttable[|c|c|c|] +%D \HL +%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR +%D \HL +%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR +%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\FR +%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR +%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR +%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR +%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR +%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR +%D \HL +%D \stoptable +%D \stoplinecorrection +%D +%D In the single||lingual version we used \type {!}, \type {!!}, \type {!!!} and +%D \type {!!!!}. In the meantime some of these are obsolete (we had some 12 +%D originally). + +\immutable\def\c!prefix!{c!} +\immutable\def\k!prefix!{k!} +\immutable\def\e!prefix!{e!} +\immutable\def\f!prefix!{f!} % for the moment we keep this one +\immutable\def\m!prefix!{m!} +\immutable\def\s!prefix!{s!} +\immutable\def\v!prefix!{v!} +\immutable\def\t!prefix!{t!} + +%D \macros +%D [constants,variables,commands] +%D {@@,??} +%D +%D Variables generated by the system can be recognized on their prefix \type {@@}. +%D They are composed of a command (class) specific tag, which can be recognized on +%D \type {??}, and a system constant, which has the prefix \type {c!}. We'll se some +%D more of this. + +\immutable\def\??prefix {??} +\immutable\def\@@prefix {@@} + +%D Just to be complete we repeat some of the already defined system constants here. +%D Maybe their prefix \type {\s!} now falls into place. + +\def\s!next {next} \def\s!default {default} +\def\s!dummy {dummy} \def\s!unknown {unknown} + +\def\s!do {do} \def\s!dodo {dodo} + +\def\s!complex {complex} \def\s!start {start} +\def\s!simple {simple} \def\s!stop {stop} + +\def\s!true {true} +\def\s!false {false} + +%D The word \type {height} takes 6~token memory cells. The control sequence \type +%D {\height} on the other hand uses only one. Knowing this, we can improve the +%D performance of \TEX, both is terms of speed and memory usage, by using control +%D sequences instead of the words written in full. +%D +%D Where in the \ASCII\ file the second lines takes nine extra characters, \TEX\ +%D saves us 13~tokens. +%D +%D \starttyping +%D \hrule width 10pt height 2pt depth 1pt +%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt +%D \stoptyping +%D +%D One condition is that we have defined \type {\s!height}, \type {\s!width} and +%D \type {\s!depth} as respectively \type {height}, \type {width} and \type {depth}. +%D Using this scheme therefore only makes sense when a token sequence is used more +%D than once. Savings like this should of course be implemented in english, just +%D because \TEX\ is english. + +\def\s!width {width} +\def\s!height {height} +\def\s!depth {depth} +\def\s!spread {spread} +\def\s!plus {plus} +\def\s!minus {minus} +\def\s!to {to} + +\def\s!fil {fil} +\def\s!fill {fill} +\def\s!filll {filll} + +\def\s!attr {attr} +\def\s!axis {axis} +\def\s!both {both} +\def\s!bottom {bottom} +\def\s!left {left} +\def\s!options {options} +\def\s!orientation{orientation} +\def\s!reverse {reverse} +\def\s!right {right} +\def\s!top {top} +\def\s!xmove {xmove} +\def\s!xoffset {xoffset} +\def\s!ymove {ymove} +\def\s!yoffset {yoffset} + +%D \macros + +%D {defineinterfaceconstant, +%D defineinterfacevariable, +%D defineinterfaceelement, +%D definesystemvariable, +%D definesystemconstant, +%D definemessageconstant, +%D definefileconstant} +%D +%D The first part of this module is dedicated to dealing with multi||lingual +%D constants and variables. When \CONTEXT\ grew bigger and bigger in terms of bytes +%D and used string space, we switched to predefined constants. At the cost of more +%D hash table entries, the macros not only becase more compact, they became much +%D faster too. Maybe an even bigger advantage was that mispelling could no longer +%D lead to problems. Even a multi||lingual interface became possible. +%D +%D Constants |<|we'll introduce the concept of variables later on|>| are preceded by +%D a type specific prefix, followed by a \type {!}. To force consistency, we provide +%D a few commands for defining such constants. +%D +%D \starttyping +%D \defineinterfaceconstant {name} {meaning} +%D \defineinterfacevariable {name} {meaning} +%D \defineinterfaceelement {name} {meaning} +%D \stoptyping +%D +%D Which is the same as: +%D +%D \starttyping +%D \def\c!name{meaning} +%D \def\v!name{meaning} +%D \def\e!name{meaning} +%D \stoptyping + +%permanent\protected\def\defineinterfaceconstant#1#2{\immutable\defcsname\c!prefix!#1\endcsname{#2}} +\permanent\protected\def\defineinterfacevariable#1#2{\immutable\defcsname\v!prefix!#1\endcsname{#2}} +\permanent\protected\def\defineinterfaceelement #1#2{\immutable\defcsname\e!prefix!#1\endcsname{#2}} + +%D Next come some interface independant constants: +%D +%D \starttyping +%D \definefileconstant {name} {meaning} +%D \stoptyping + +\permanent\protected\def\definefileconstant#1#2{\immutable\defcsname\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 + +\permanent\protected\def\definesystemconstant #1{\immutable\defcsname\s!prefix!#1\endcsname{#1}} +\permanent\protected\def\definemessageconstant#1{\immutable\defcsname\m!prefix!#1\endcsname{#1}} + +%D For now here: + +\permanent\protected\def\definetagconstant #1{\immutable\defcsname\t!prefix!#1\endcsname{#1}} +\permanent\protected\def\aliastagconstant #1#2{\aliased \letcsname\t!prefix!#1\expandafter\endcsname\csname\t!prefix!#2\endcsname} + +%D In a parameter driven system, some parameters are shared by more system +%D components. In \CONTEXT\ we can distinguish parameters by a unique prefix. Such a +%D prefix is defined with: +%D +%D \starttyping +%D \definesystemvariable {name} +%D \stoptyping + +\permanent\protected\def\definesystemvariable#1{\immutable\edefcsname\??prefix#1\endcsname{\@@prefix#1}} + +\definesystemvariable{ms} + +%D \macros +%D {selectinterface, +%D defaultinterface, currentinterface, currentresponses} +%D +%D With \type {\selectinterface} we specify the language we are going to use. The +%D system asks for the language wanted, and defaults to \type {\currentinterface} +%D when we just give \type {enter}. By default the message system uses the current +%D interface language, but \type {\currentresponses} can specify another language +%D too. +%D +%D Because we want to generate formats directly too, we do not ask for interface +%D specifications when these are already defined (like in cont-nl.tex and alike). + +\ifdefined\defaultinterface + + \permanent\protected\def\selectinterface + {\writestatus{interface}{defining \currentinterface\space interface}% + %writeline + \writestatus{interface}{using \currentresponses\space messages}% + %\writeline + \enforced\permanent\let\selectinterface\relax} + +\else + + \def\defaultinterface{english} + + \permanent\overloaded\protected\def\selectinterface + {\enforced\permanent\protected\def\selectinterface##1##2% + {\bgroup + \endlinechar\minusone + \global\read16 to ##1 + \egroup + \doifnothing\currentinterface{\let##1=##2}% + \doifundefined{\s!prefix!##1}{\let##1=##2}}% + \selectinterface\currentinterface\defaultinterface + \writestatus{interface}{defining \currentinterface\space interface}% + %\writeline + \selectinterface\currentresponses\currentinterface + \writestatus{interface}{using \currentresponses\space messages}% + %\writeline + \enforced\permanent\let\selectinterface\relax} + +\fi + +\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi +\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi + +%D \macros +%D {startinterface} +%D +%D Sometimes we want to define things only for specific interface languages. This +%D can be done by means of the selector: +%D +%D \starttyping +%D \startinterface language +%D +%D language specific definitions & commands +%D +%D \stopinterface +%D \stoptyping + +\permanent\protected\def\startinterface #1 + {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}} + +\aliased\let\stopinterface\relax + +%D \macros +%D {startmessages, +%D getmessage, +%D showmessage, +%D makemessage} +%D +%D A package as large as \CONTEXT\ can hardly function without a decent message +%D mechanism. Due to its multi||lingual interface, the message subsystem has to be +%D multi||lingual too. A major drawback of this feature is that we have to code +%D messages. As a result, the source becomes less self documented. On the other +%D hand, consistency will improve. +%D +%D Because the overhead in terms of entries in the (already exhausted) hash table +%D has to be minimal, messages are packed in libraries. We can extract a message +%D from such a library in three ways: +%D +%D \starttyping +%D \getmessage {library} {tag} +%D \showmessage {library} {tag} {data} +%D \makemessage {library} {tag} {data} +%D \stoptyping +%D +%D The first command gets the message \type {tag} from the \type {library} +%D specified. The other commands take an extra argument: a list of items to be +%D inserted in the message text. While \type {\showmessage} shows the message at the +%D terminal, the other commands generate the message as text. Before we explain the +%D \type {data} argument, we give an example of a library. +%D +%D \starttyping +%D \startmessages english library: alfa +%D title: something +%D 1: first message +%D 2: second (--) message -- +%D \stopmessages +%D \stoptyping +%D +%D The first message is a simple one and can be shown with: +%D +%D \starttyping +%D \showmessage {alfa} {1} {} +%D \stoptyping +%D +%D The second message on the other hand needs some extra data: +%D +%D \starttyping +%D \showmessage {alfa} {2} {and last,to you} +%D \stoptyping +%D +%D This message is shown as: +%D +%D \starttyping +%D something : second (and last) message to you +%D \stoptyping +%D +%D As we can see, the title entry is shown with the message. The data fields are +%D comma separated and are specified in the message text by \type {--}. +%D +%D It is not required to define all messages in a library at once. We can add +%D messages to a library in the following way: +%D +%D \starttyping +%D \startmessages english library: alfa +%D 10: tenth message +%D \stopmessages +%D \stoptyping +%D +%D Because such definitions can take place in different modules, the system gives a +%D warning when a tag occurs more than once. The first occurrence takes preference +%D over later ones, so we had better use a save offset, as shown in the example. As +%D we can see, the title field is specified only the first time! +%D +%D Because we want to check for duplicate tags, the macros are a bit more +%D complicated than neccessary. The \NEWLINE\ token is used as message separator. +%D +%D For internal purposes one can use \type {\setmessagetext}, which puts the message +%D text asked for in \type {\currentmessagetext}. +%D +%D These will become obsolete: + +\permanent\protected\def\startmessages #1 library: #2 % + {\begingroup + \ifcsname\m!prefix!#2\endcsname\else\immutable\setgvalue{\m!prefix!#2}{#2}\fi + \catcode\endoflineasciicode\othercatcode + \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} + +\def\mult_messages_start_yes#1#2\stopmessages + {\clf_setinterfacemessages{#1}{#2}% + \endgroup} + +\def\mult_messages_start_nop#1#2\stopmessages + {\endgroup} + +\let\stopmessages\relax + +\permanent\protected\def\setinterfacemessage#1#2#3% + {\ifcsname\m!prefix!#1\endcsname\else\immutable\setgvalue{\m!prefix!#1}{#1}\fi + \clf_setinterfacemessage{#1}{#2}{#3}} + +\pushoverloadmode + +\permanent\protected\def\setmessagetext #1#2{\relax\edef\currentmessagetext{\clf_getmessage{#1}{#2}}} +\permanent\protected\def\getmessage #1#2{\relax\clf_getmessage{#1}{#2}} +\permanent\protected\def\doifelsemessage #1#2{\relax\clf_doifelsemessage{#1}{#2}} +\permanent\protected\def\showmessage #1#2#3{\relax\clf_showmessage{#1}{#2}{#3}} +\permanent\protected\def\writestatus #1#2{\relax\clf_writestatus{#1}{#2}} +\permanent\protected\def\message {\relax\clf_message} + +\popoverloadmode + +\aliased\let\doifmessageelse\doifelsemessage + +\permanent\protected\def\inlinemessage #1{\dontleavehmode{\tttf#1}} +\permanent\protected\def\displaymessage#1{\blank\inlinemessage{#1}\blank} + +\permanent\let\getsetupstring\clf_getsetupstring +\permanent\let\rawsetupstring\clf_rawsetupstring + +%D For old times sake: + +\aliased\let\showwarning\showmessage + +%D \macros +%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue +%D +%D We already defined these auxiliary macros in the system modules. Starting with +%D this module however, we have to take multi||linguality a bit more serious. +%D +%D In due time, when we exclusively use the parameter handler code, we can drop the +%D backmapping (\type{\c!k...}) and make \type {\c!c...} similar to \type {\v!...}. +%D In that case we can simply the following setters. + +\pushoverloadmode + +\permanent\protected\def\doletvalue #1#2{\letcsname #1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetvalue #1#2{\defcsname #1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetevalue #1#2{\edefcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetgvalue #1#2{\gdefcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetxvalue #1#2{\xdefcsname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\doresetvalue #1#2{\letcsname #1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} +\permanent\protected\def\doignorevalue#1#2#3{\letcsname #1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} + +\permanent\protected\def\docopyvalue#1#2#3% + {\ifcsname\k!prefix!#3\endcsname + \defcsname#1\csname\k!prefix!#3\endcsname\expandafter\endcsname\expandafter + {\csname#2\csname\k!prefix!#3\endcsname\endcsname}% + \else + \defcsname#1#3\expandafter\endcsname\expandafter + {\csname#2#3\endcsname}% + \fi} + +\startinterface english + + \permanent\protected\def\doletvalue #1#2{\letcsname #1#2\endcsname} + \permanent\protected\def\dosetvalue #1#2{\defcsname #1#2\endcsname} + \permanent\protected\def\dosetevalue #1#2{\edefcsname#1#2\endcsname} + \permanent\protected\def\dosetgvalue #1#2{\gdefcsname#1#2\endcsname} + \permanent\protected\def\dosetxvalue #1#2{\xdefcsname#1#2\endcsname} + \permanent\protected\def\doresetvalue #1#2{\letcsname #1#2\endcsname\empty} + \permanent\protected\def\doignorevalue#1#2#3{\letcsname #1#2\endcsname\empty} + + \permanent\protected\def\docopyvalue#1#2#3% + {\defcsname#1#3\expandafter\endcsname\expandafter + {\csname#2#3\endcsname}} + +\stopinterface + +\popoverloadmode + +%D We can now redefine some messages that will be introduced in the multi||lingual +%D system module. + +\permanent\protected\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}} +\permanent\protected\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}} +\permanent\protected\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}} + +%D \CONTEXT\ is a parameter driven package. This means that users instruct the +%D system by means of variables, values and keywords. These instructions take the +%D form: +%D +%D \starttyping +%D \setupsomething[some variable=some value, another one=a keyword] +%D \stoptyping +%D +%D or by keyword only: +%D +%D \starttyping +%D \dosomething[this way,that way,no way] +%D \stoptyping +%D +%D Because the same variables can occur in more than one setup command, we have to +%D be able to distinguish them. This is achieved by assigning them a unique prefix. +%D +%D Imagine a setup command for boxed text, that enables us to specify the height and +%D width of the box. Behide the scenes the command +%D +%D \starttyping +%D \setupbox [width=12cm, height=3cm] +%D \stoptyping +%D +%D results in something like +%D +%D \starttyping +%D \ {12cm} +%D \ {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 \ {21.0cm} +%D \ {27.9cm} +%D \stoptyping +%D +%D The prefixes \type {} and \type {} are hidden from users and can +%D therefore be language independant. Variables on the other hand, differ for each +%D language: +%D +%D \starttyping +%D \ {} +%D \ {} +%D \ {} +%D \stoptyping +%D +%D In this example we can see that the assigned values or keywords are language +%D dependant too. This will be a complication when defining multi||lingual setup +%D files. +%D +%D A third phenomena is that variables and values can have a similar meaning. +%D +%D \starttyping +%D \ {} +%D \ {12cm} +%D \stoptyping +%D +%D A (minor) complication is that where in english we use \type {}, in dutch +%D we find both \type {} and \type {}. This means that when we use +%D some sort of translation table, we have to distinguish between the variables at +%D the left side and the fixed values at the right. +%D +%D The same goes for commands that are composed of different user supplied and/or +%D language specific elements. In english we can use: +%D +%D \starttyping +%D \
+%D \ +%D \stoptyping +%D +%D But in dutch we have the following: +%D +%D \starttyping +%D \ +%D \ +%D \stoptyping +%D +%D These subtle differences automatically lead to a solution where variables, +%D values, elements and other components have a similar logical name (used in +%D macro's) but a different meaning (supplied by the user). +%D +%D Our solution is one in which the whole system is programmed in terms of +%D identifiers with language specific meanings. In such an implementation, each +%D fixed variable is available as: +%D +%D \starttyping +%D \ +%D \stoptyping +%D +%D This means that for instance: +%D +%D \starttyping +%D \setupbox[width=12cm] +%D \stoptyping +%D +%D expands to something like: +%D +%D \starttyping +%D \def\boxwidth{12cm} +%D \stoptyping +%D +%D because we don't want to recode the source, a setup command in another language +%D has to expand to this variable, so: +%D +%D \starttyping +%D \setupblock[width=12cm] +%D \stoptyping +%D +%D has to result in the definition of \type {\boxwidth} too. This method enables us +%D to build compact, fast and readable code. +%D +%D An alternative method, which we considered using, uses a more indirect way. In +%D this case, both calls generate a different variable: +%D +%D \starttyping +%D \def\boxwidth {12cm} +%D \def\boxbreedte {12cm} +%D \stoptyping +%D +%D And because we don't want to recode those megabytes of already developed code, +%D this variable has to be called with something like: +%D +%D \starttyping +%D \valueof\box\width +%D \stoptyping +%D +%D where \type {\valueof} takes care of the translation of \type {width} or \type +%D {breedte} to \type {width} and combining this with \type {box} to \type +%D {\boxwidth}. +%D +%D One advantage of this other scheme is that, within certain limits, we can +%D implement an interface that can be switched to another language at will, while +%D the current approach fixes the interface at startup. There are, by the way, other +%D reasons too for not choosing this scheme. Switching user generated commands is +%D for instance impossible and a dual interface would therefore give a strange mix +%D of languages. +%D +%D Now let's work out the first scheme. Although the left hand of the assignment is +%D a variable from the users point of view, it is a constant in terms of the system. +%D Both \type {width} and \type {breedte} expand to \type {width} because in the +%D source we only encounter \type {width}. Such system constants are presented as +%D +%D \starttyping +%D \c!width +%D \stoptyping +%D +%D This constant is always equivalent to \type {width}. As we can see, we use \type +%D {c!} to mark this one as constant. Its dutch counterpart is: +%D +%D \starttyping +%D breedte +%D \stoptyping +%D +%D When we interpret a setup command each variable is translated to it's \type{c!} +%D counterpart. This means that \type {breedte} and \type{width} expand to \type +%D {breedte} and \type {\c!width} which both expand to \type {width}. That way user +%D variables become system constants. +%D +%D The interpretation is done by means of a general setup command \type +%D {\getparameters} that we introduced in the system module. Let us define some +%D simple setup command: +%D +%D \starttyping +%D \protected\def\setupbox[#1]% +%D {\getparameters[\??bx][#1]} +%D \stoptyping +%D +%D This command can be used as: +%D +%D \starttyping +%D \setupbox [width=3cm, height=1cm] +%D \stoptyping +%D +%D Afterwards we have two variables \type {\@@bxwidth} and \type {\@@bxheight} which +%D have the values \type {3cm} and \type {1cm} assigned. These variables are a +%D combinatiom of the setup prefix \type {\??bx}, which expands to \type {@@bx} and +%D the translated user supplied variables \type {width} and \type {height} or \type +%D {breedte} and \type {hoogte}, depending on the actual language. In dutch we just +%D say: +%D +%D \starttyping +%D \stelblokin [breedte=3cm,hoogte=1cm] +%D \stoptyping +%D +%D and get ourselves \type {\@@bxwidth} and \type {\@@bxheight} too. In the source +%D of \CONTEXT, we can recognize constants and variables on their leading \type +%D {c!}, \type {v!} etc., prefixes on \type {??} and composed variables on \type +%D {@@}. +%D +%D We already saw that user supplied keywords need some special treatment too. This +%D time we don't translate the keyword, but instead use in the source a variable +%D which meaning depends on the interface language. +%D +%D \starttyping +%D \v!left +%D \stoptyping +%D +%D Which can be used in macro's like: +%D +%D \starttyping +%D \processaction +%D [\@@bxlocation] +%D [ \v!left=>\dosomethingontheleft, +%D \v!middle=>\dosomthinginthemiddle, +%D \v!right=>\dosomethingontheright] +%D \stoptyping +%D +%D Because variables like \type {\@@bxlocation} can have a lot of meanings, +%D including tricky expandable tokens, we cannot translate this meaning when we +%D compare. This means that \type {\@@bxlocation} can be \type {left} of \type +%D {links} of whatever meaning suits the language. But because \type {\v!left} also +%D has a meaning that suits the language, we are able to compare. +%D +%D Although we know it sounds confusing we want to state two important +%D characteristics of the interface as described: +%D +%D \startnarrower \em +%D user variables become system constants +%D \stopnarrower +%D +%D and +%D +%D \startnarrower \em +%D user constants (keywords) become system variables +%D \stopnarrower +%D +%D The \type {\c!internal} is a left over from the time that the user interface +%D documents were not using a specification alongside a keyword specification but +%D used a shared file in which case we need to go in both directions. + +% temporary mkiv hack (we can best just store the whole table in memory) + +\permanent\overloaded\protected\def\setinterfaceconstant#1#2% + {\clf_setinterfaceconstant{#1}{#2}% + \immutable\defcsname\c!prefix!#1\endcsname{#1}} + +\permanent\overloaded\protected\def\setinterfacevariable#1#2% + {\clf_setinterfacevariable{#1}{#2}% + \immutable\defcsname\v!prefix!#1\endcsname{#2}} + +%D \macros +%D {defineinterfaceconstant} +%D +%D Next we redefine a previously defined macro to take care of interface translation +%D too. It's a bit redundant, because in these situations we could use the +%D c||version, but for documentation purposes the x||alternative comes in handy. + +\permanent\overloaded\protected\def\defineinterfaceconstant#1#2% + {\immutable\defcsname\c!prefix!#1\endcsname{#2}} + +%D \macros +%D {startelements} +%D +%D Due to the object oriented nature of \CONTEXT, we also need to define the +%D elements that are used to build commands. +%D +%D Such elements sometimes are the same in different languages, but mostly they +%D differ. Things can get even confusing when we look at for instance the setup +%D commands. In english we say \type{\setup}, but in dutch we have: \type +%D {\stelin}. Such split elements are no problem, because we just define two +%D elements. When no second part is needed, we use a \type {-}: + +\permanent\overloaded\protected\def\setinterfaceelement#1#2% + {\clf_setinterfaceelement{#1}{#2}% + \ifcsname\e!prefix!#1\endcsname + \doifnotvalue{\e!prefix!#1}{#2}{\enforced\immutable\setvalue{\e!prefix!#1}{#2}}% + \else + \enforced\immutable\setvalue{\e!prefix!#1}{#2}% + \fi} + +\permanent\protected\def\setinterfacecommand#1#2% \frozen ? \permanent ? + {\doifnot{#1}{#2}% todo: let when already defined + {\defcsname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}} + +%D We just ignore these: + +\permanent\protected\def\startvariables{\gobbleuntil\stopvariables} \aliased\let\stopvariables\relax +\permanent\protected\def\startconstants{\gobbleuntil\stopconstants} \aliased\let\stopconstants\relax +\permanent\protected\def\startelements {\gobbleuntil\stopelements } \aliased\let\stopelements \relax +\permanent\protected\def\startcommands {\gobbleuntil\stopcommands } \aliased\let\stopcommands \relax + +%D For at the \LUA\ end (experiment): + +\def\ui_c#1#2{\immutable\gdefcsname\c!prefix!#1\endcsname{#1}% + \immutable\gdefcsname\k!prefix!#2\endcsname{#1}} % backmapping from non english +\def\ui_s #1{\immutable\gdefcsname\c!prefix!#1\endcsname{#1}% + \immutable\gdefcsname\k!prefix!#1\endcsname{#1}} % backmapping from non english +\def\ui_v#1#2{\immutable\gdefcsname\v!prefix!#1\endcsname{#2}} +\def\ui_e#1#2{\immutable\gdefcsname\e!prefix!#1\endcsname{#2}} +\def\ui_a#1#2{\frozen\protected\def#2{#1}} % will go away + +\startinterface english + + \def\ui_c#1#2{\immutable\gdefcsname\c!prefix!#1\endcsname{#1}} + \def\ui_s #1{\immutable\gdefcsname\c!prefix!#1\endcsname{#1}} + +\stopinterface + +%D So much for the basic multi||lingual interface commands. The macro's can be +%D enhanced with more testing facilities, but for the moment they suffice. + +\ifdefined\zwnj \else \immutable\edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv +\ifdefined\zwj \else \immutable\edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv + +%D \macros +%D {contextversion, contextversionnumber, contextversionno, +%D contextbanner, showcontextbanner, formatversion} +%D +%D Out of convenience we define the banners here. This might move to the \LUA\ end. + +\pushoverloadmode + +\permanent\overloaded\def\contextbanner + {ConTeXt \space + ver: \contextversion \space \contextmark \space \space + fmt: \formatversion \space \space + int: \currentinterface/\currentresponses} + +\permanent\overloaded\protected\def\showcontextbanner + {\writestatus\m!system\empty + \writestatus\m!system\contextbanner + \writestatus\m!system\empty} + +\immutable\overloaded\edef\formatversion + {\the\normalyear.\the\normalmonth.\the\normalday} + +\newcount\contextversionno + +\ifx\contextversion\undefined + \immutable\edef\contextversion{\the\normalyear.\the\normalmonth.\the\normalday\space 00:00} +\fi + +\permanent\overloaded\protected\def \contextversionnumber #1.#2.#3 #4:#5\relax{#1#2#3} + \contextversionno \expandafter\contextversionnumber\contextversion\relax +\immutable\overloaded \edef\contextversionnumber {\the\contextversionno\space\contextmark} + +\popoverloadmode + +%D \macros +%D {everydump} +%D +%D This one is only used when we generate the format. + +% \ifx\undefined\everydump +% \newtoks\everydump +% \def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump} +% \fi + +% \appendtoks \showcontextbanner \to \everydump + +\protect \endinput diff --git a/tex/context/base/mkxl/mult-prm.mkxl b/tex/context/base/mkxl/mult-prm.mkxl new file mode 100644 index 000000000..2ec763c39 --- /dev/null +++ b/tex/context/base/mkxl/mult-prm.mkxl @@ -0,0 +1,117 @@ +%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. + +% local all = table.load("mult-prm.lua") +% local tex = table.tohash(all.tex) +% for k, v in next, all do +% if k ~= "tex" then +% local h = table.tohash(v) +% for k, v in next, h do +% tex[k] = nil +% end +% all[k] = table.sortedkeys(h) +% end +% end +% all.tex = table.sortedkeys(tex) +% print((string.gsub(table.serialize(all,true),' "','\n "'))) + +\startluacode + + context.starttext() + + local missing = { + tex = { + -- todo: differenced between luatex and luametatex + }, + etex = { + -- todo: differenced between luatex and luametatex + }, + luatex = { + -- todo: differenced between luatex and luametatex + }, + pdftex = { -- maybe not complete + "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "pdfadjustspacing", + "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", + "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", + "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", + "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", + "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", + "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", + "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", + "pdfignoreddimen", "pdfignoreunknownimages", "pdfimageaddfilename", + "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", + "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", + "pdfinclusionerrorlevel", "pdfinfo", "pdfinfoomitdate", + "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", + "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages", + "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", + "pdfmapfile", "pdfmapline", "pdfmajorversion", "pdfminorversion", "pdfnames", + "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfrecompress", + "pdfobjcompresslevel", "pdfoutline", "pdfoutput", "pdfpageattr", + "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", + "pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode", + "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", + "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", + "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", + "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", + "pdfsuppressoptionalinfo", "pdfsuppressptexinfo", "pdftexbanner", + "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", + "pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate", + "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", + "pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage", + "pdfomitcidset", "pdfomitcharset", + }, + aleph = { -- we don't bother + "Alephminorversion", "Alephrevision", "Alephversion", + }, + omega = { -- we don't bother + "Omegaminorversion", "Omegarevision", "Omegaversion", + }, + xetex = { -- we don't bother + "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 , tex.extraprimitives("core","tex") ) ), + etex = table.sorted( table.merged( missing.etex , tex.extraprimitives("etex") ) ), + pdftex = table.sorted( table.merged( missing.pdftex, { } ) ), + luatex = table.sorted( table.merged( missing.luatex, tex.extraprimitives("luatex") ) ), + aleph = table.sorted( table.merged( missing.aleph , { } ) ), + omega = table.sorted( table.merged( missing.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/tex/context/base/mkxl/mult-sys.mkxl b/tex/context/base/mkxl/mult-sys.mkxl new file mode 100644 index 000000000..38355f4cb --- /dev/null +++ b/tex/context/base/mkxl/mult-sys.mkxl @@ -0,0 +1,602 @@ +%D \module +%D [ file=mult-sys, +%D version=1996.06.01, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=System, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In boring module we define a lot of obscure but useful system constants. +%D By doing so we save lots of memory while at the same time we prevent +%D ourself making typing errors. + +\writestatus{loading}{ConTeXt Multilingual Macros / System} + +\unprotect + +%D This file is mostly the same as the \MKII\ variant but we keep extending +%D \MKIV, so it was bout time to have a dedicated variant. +%D +%D The constants are grouped in such a way that there is a minimal change of +%D conflicts. +%D +%D \starttyping +%D \definesystemconstants {word} +%D \definemessageconstant {word} +%D \stoptyping +%D +%D This commands generate \type{\s!word} and \type{\m!word}. + +\definesystemconstant {hans} +\definesystemconstant {taco} +\definesystemconstant {wolfgang} + +%D First we define some system constants used for both the multi||lingual +%D interface and multi||linguag typesetting. + +% definesystemconstant {slovene} +% definesystemconstant {cz} +% definesystemconstant {vn} + +\definesystemconstant {afrikaans} \definesystemconstant {af} +\definesystemconstant {ancientgreek} \definesystemconstant {agr} +\definesystemconstant {ancientlatin} \definesystemconstant {ala} +\definesystemconstant {arabic} \definesystemconstant {ar} +\definesystemconstant {bokmal} \definesystemconstant {nb} +\definesystemconstant {catalan} \definesystemconstant {ca} +\definesystemconstant {chinese} \definesystemconstant {cn} +\definesystemconstant {croatian} \definesystemconstant {hr} +\definesystemconstant {czech} \definesystemconstant {cs} +\definesystemconstant {danish} \definesystemconstant {da} +\definesystemconstant {dutch} \definesystemconstant {nl} +\definesystemconstant {english} \definesystemconstant {en} +\definesystemconstant {estonian} \definesystemconstant {et} +\definesystemconstant {esperanto} % \definesystemconstant {eo} +\definesystemconstant {farsi} \definesystemconstant {fa} % just persian +\definesystemconstant {finnish} \definesystemconstant {fi} +\definesystemconstant {french} \definesystemconstant {fr} +\definesystemconstant {gbenglish} \definesystemconstant {gb} +\definesystemconstant {german} \definesystemconstant {de} +\definesystemconstant {greek} \definesystemconstant {gr} +\definesystemconstant {hebrew} \definesystemconstant {he} +\definesystemconstant {yiddish} \definesystemconstant {yi} +\definesystemconstant {hungarian} \definesystemconstant {hu} +\definesystemconstant {italian} \definesystemconstant {it} +\definesystemconstant {japanese} \definesystemconstant {ja} +\definesystemconstant {korean} \definesystemconstant {kr} +\definesystemconstant {latin} \definesystemconstant {la} +\definesystemconstant {lithuanian} \definesystemconstant {lt} +\definesystemconstant {malayalam} \definesystemconstant {ml} +\definesystemconstant {norwegian} \definesystemconstant {no} +\definesystemconstant {nynorsk} \definesystemconstant {nn} +\definesystemconstant {persian} \definesystemconstant {pe} +\definesystemconstant {polish} \definesystemconstant {pl} +\definesystemconstant {portuguese} \definesystemconstant {pt} +\definesystemconstant {romanian} \definesystemconstant {ro} +\definesystemconstant {russian} \definesystemconstant {ru} +\definesystemconstant {slovak} \definesystemconstant {sk} +\definesystemconstant {slovenian} \definesystemconstant {sl} +\definesystemconstant {spanish} \definesystemconstant {es} +\definesystemconstant {swedish} \definesystemconstant {sv} +\definesystemconstant {thai} \definesystemconstant {th} % mojca mentioned it at BT2013 but we need more info +\definesystemconstant {turkish} \definesystemconstant {tr} +\definesystemconstant {turkmen} \definesystemconstant {tk} +\definesystemconstant {ukenglish} \definesystemconstant {uk} +\definesystemconstant {ukrainian} \definesystemconstant {ua} +\definesystemconstant {usenglish} \definesystemconstant {us} +\definesystemconstant {vietnamese} \definesystemconstant {vi} + +%D Left|-|overs: + +\defineinterfaceconstant {HL} {HL} +\defineinterfaceconstant {VL} {VL} +\defineinterfaceconstant {NL} {NL} + +%D For proper \UNICODE\ support we need a few font related constants. + +\definesystemconstant {action} +\definesystemconstant {all} +\definesystemconstant {ampersand} +\definesystemconstant {ascii} +\definesystemconstant {attribute} +\definesystemconstant {attr} +\definesystemconstant {author} +\definesystemconstant {auto} +\definesystemconstant {axis} +\definesystemconstant {a} +\definesystemconstant {bf} +\definesystemconstant {big} +\definesystemconstant {binary} +\definesystemconstant {bi} +\definesystemconstant {blackboard} +\definesystemconstant {black} +\definesystemconstant {BoldItalic} +\definesystemconstant {BoldSlanted} +\definesystemconstant {Bold} +\definesystemconstant {bold} +\definesystemconstant {both} +\definesystemconstant {bottomfloat} +\definesystemconstant {bottom} +\definesystemconstant {box} +\definesystemconstant {bp} +\definesystemconstant {bs} +\definesystemconstant {b} +\definesystemconstant {calligraphy} +\definesystemconstant {Calligraphy} +\definesystemconstant {Caps} +\definesystemconstant {casual} +\definesystemconstant {Casual} +\definesystemconstant {catcodes} +\definesystemconstant {catcodetable} +\definesystemconstant {cc} +\definesystemconstant {cg} +\definesystemconstant {chain} +\definesystemconstant {check} +\definesystemconstant {child} +\definesystemconstant {cite} +\definesystemconstant {class} +\definesystemconstant {clone} +\definesystemconstant {cmyk} +\definesystemconstant {cm} +\definesystemconstant {code} +\definesystemconstant {collapsing} +\definesystemconstant {command} +\definesystemconstant {compare} +\definesystemconstant {complex} +\definesystemconstant {counter} +\definesystemconstant {cramped} +\definesystemconstant {current} +\definesystemconstant {c} +\definesystemconstant {data} +\definesystemconstant {dd} +\definesystemconstant {decimal} +\definesystemconstant {DefaultFont} +\definesystemconstant {default} +\definesystemconstant {depth} +\definesystemconstant {designsize} +\definesystemconstant {direction} +\definesystemconstant {display} +\definesystemconstant {document} +\definesystemconstant {dodo} +\definesystemconstant {done} +\definesystemconstant {double} +\definesystemconstant {do} +\definesystemconstant {dtp} +\definesystemconstant {dummy} +\definesystemconstant {d} +\definesystemconstant {edge} +\definesystemconstant {effect} +\definesystemconstant {empty} +\definesystemconstant {em} +\definesystemconstant {environment} +\definesystemconstant {extensions} +\definesystemconstant {external} +\definesystemconstant {ex} +\definesystemconstant {e} +\definesystemconstant {fallbacks} +\definesystemconstant {fallback} +\definesystemconstant {false} +\definesystemconstant {fax} +\definesystemconstant {features} +\definesystemconstant {file} +\definesystemconstant {filll} +\definesystemconstant {fill} +\definesystemconstant {fil} +\definesystemconstant {first} +\definesystemconstant {float} +\definesystemconstant {font} +\definesystemconstant {forget} +\definesystemconstant {format} +\definesystemconstant {fraktur} +\definesystemconstant {full} +\definesystemconstant {f} +\definesystemconstant {global} +\definesystemconstant {goodies} +\definesystemconstant {gray} +\definesystemconstant {handler} +\definesystemconstant {handwriting} +\definesystemconstant {Handwriting} +\definesystemconstant {hascaption} +\definesystemconstant {haslevel} +\definesystemconstant {hasnumber} +\definesystemconstant {hasparent} +\definesystemconstant {hassuffix} +\definesystemconstant {hastitle} +\definesystemconstant {head} +\definesystemconstant {height} +\definesystemconstant {hw} +\definesystemconstant {hyphenmin} +\definesystemconstant {indeed} +\definesystemconstant {initializations} +\definesystemconstant {insert} % maybe insertclass +\definesystemconstant {integral} +\definesystemconstant {internal} +\definesystemconstant {in} +\definesystemconstant {italics} +\definesystemconstant {Italic} +\definesystemconstant {italic} +%definesystemconstant {it} +\definesystemconstant {itemgroupcolumns} +\definesystemconstant {kernpairs} +\definesystemconstant {language} +\definesystemconstant {lcgreek} +\definesystemconstant {lefthyphenchar} +\definesystemconstant {lefthyphenmin} +\definesystemconstant {leftpage} +\definesystemconstant {left} +\definesystemconstant {level} +\definesystemconstant {ligatures} +\definesystemconstant {line} +\definesystemconstant {link} +\definesystemconstant {list} +\definesystemconstant {local} +\definesystemconstant {lua} +\definesystemconstant {mapping} +\definesystemconstant {map} +\definesystemconstant {margintext} +\definesystemconstant {margin} +\definesystemconstant {marker} +\definesystemconstant {MathBold} % not used +\definesystemconstant {MathRomanBold} +\definesystemconstant {MathRoman} +\definesystemconstant {math} +\definesystemconstant {Math} % not used +\definesystemconstant {mblr} +\definesystemconstant {mbrl} +\definesystemconstant {mb} +\definesystemconstant {middle} +\definesystemconstant {minus} +\definesystemconstant {mixedcolumn} +\definesystemconstant {mi} % maybe some day a special default vector +\definesystemconstant {mkii} +\definesystemconstant {mkiv} +\definesystemconstant {mm} +\definesystemconstant {mnem} % kind of generic short tag +\definesystemconstant {mode} +\definesystemconstant {MonoBoldItalic} +\definesystemconstant {MonoBoldSlanted} +\definesystemconstant {MonoBold} +\definesystemconstant {MonoCaps} +\definesystemconstant {MonoItalic} +\definesystemconstant {MonoSlanted} +\definesystemconstant {Mono} +\definesystemconstant {mono} +\definesystemconstant {mrlr} +\definesystemconstant {mrrl} +\definesystemconstant {mr} +\definesystemconstant {multi} +\definesystemconstant {name} +\definesystemconstant {next} +\definesystemconstant {nocite} +\definesystemconstant {nodepth} +\definesystemconstant {noheight} +\definesystemconstant {nomath} +\definesystemconstant {none} +\definesystemconstant {normal} +\definesystemconstant {Normal} +\definesystemconstant {nowidth} +\definesystemconstant {numbering} +\definesystemconstant {number} +\definesystemconstant {options} +\definesystemconstant {ord} +\definesystemconstant {orientation} +\definesystemconstant {otr} +\definesystemconstant {pagefloat} +\definesystemconstant {page} +\definesystemconstant {paragraph} +\definesystemconstant {parent} +\definesystemconstant {patterns} +\definesystemconstant {pc} +\definesystemconstant {pickup} +\definesystemconstant {plural} +\definesystemconstant {plus} +%definesystemconstant {pt} +\definesystemconstant {realpage} +\definesystemconstant {register} +\definesystemconstant {Regular} +\definesystemconstant {regular} +\definesystemconstant {rel} +\definesystemconstant {reset} +\definesystemconstant {reverse} +\definesystemconstant {rgb} +\definesystemconstant {righthyphenchar} +\definesystemconstant {righthyphenmin} +\definesystemconstant {rightpage} +\definesystemconstant {right} +\definesystemconstant {rm} +\definesystemconstant {rname} +\definesystemconstant {rscale} +\definesystemconstant {SansBoldItalic} +\definesystemconstant {SansBoldSlanted} +\definesystemconstant {SansBold} +\definesystemconstant {SansCaps} +\definesystemconstant {SansItalic} +\definesystemconstant {SansSlanted} +\definesystemconstant {Sans} +\definesystemconstant {sans} +\definesystemconstant {scriptscript} +\definesystemconstant {script} +\definesystemconstant {sc} +\definesystemconstant {second} +\definesystemconstant {section} +\definesystemconstant {SerifBoldItalic} +\definesystemconstant {SerifBoldSlanted} +\definesystemconstant {SerifBold} +\definesystemconstant {SerifCaps} +\definesystemconstant {SerifItalic} +\definesystemconstant {SerifSlanted} +\definesystemconstant {Serif} +\definesystemconstant {serif} +\definesystemconstant {setups} +\definesystemconstant {setup} +\definesystemconstant {set} +\definesystemconstant {themaintextcolor} +\definesystemconstant {simple} +\definesystemconstant {Simple} +\definesystemconstant {single} +\definesystemconstant {singular} +\definesystemconstant {size} +\definesystemconstant {slanted} +\definesystemconstant {Slanted} +%definesystemconstant {sl} +\definesystemconstant {smallcaps} +\definesystemconstant {small} +\definesystemconstant {somewhere} +\definesystemconstant {special} +\definesystemconstant {spec} +\definesystemconstant {spot} +\definesystemconstant {spread} +\definesystemconstant {sp} +\definesystemconstant {ss} +\definesystemconstant {start} +\definesystemconstant {stop} +\definesystemconstant {subpage} +\definesystemconstant {subtype} +\definesystemconstant {sub} +\definesystemconstant {Support} +\definesystemconstant {sygreek} +\definesystemconstant {symbol} +\definesystemconstant {system} % not yet interfaces messages +\definesystemconstant {text} +\definesystemconstant {tex} +\definesystemconstant {tf} +\definesystemconstant {third} +\definesystemconstant {topfloat} +\definesystemconstant {top} +\definesystemconstant {to} +\definesystemconstant {traditional} +\definesystemconstant {triple} +\definesystemconstant {true} +\definesystemconstant {tt} +\definesystemconstant {Type} +\definesystemconstant {ucgreek} +\definesystemconstant {uncramped} +\definesystemconstant {unexpanded} +\definesystemconstant {Unicode} +\definesystemconstant {unknown} +\definesystemconstant {userdata} +\definesystemconstant {userpage} +\definesystemconstant {user} +\definesystemconstant {vfrac} +\definesystemconstant {white} +\definesystemconstant {width} +\definesystemconstant {xml} +\definesystemconstant {xmove} +\definesystemconstant {xoffset} +\definesystemconstant {xx} +\definesystemconstant {x} +\definesystemconstant {ymove} +\definesystemconstant {yoffset} + +%D As the name of their define command states, the next set of constants is used in +%D the message macro's. + +\definemessageconstant {backend} +\definemessageconstant {check} +\definemessageconstant {chemicals} +\definemessageconstant {colors} +\definemessageconstant {columns} +\definemessageconstant {fields} +\definemessageconstant {figures} +\definemessageconstant {files} +\definemessageconstant {floatblocks} +\definemessageconstant {fonts} +\definemessageconstant {handlings} +\definemessageconstant {interactions} +\definemessageconstant {javascripts} +\definemessageconstant {languages} +\definemessageconstant {layouts} +\definemessageconstant {lua} +\definemessageconstant {metapost} +\definemessageconstant {publications} +\definemessageconstant {references} +\definemessageconstant {regimes} +\definemessageconstant {structures} +\definemessageconstant {symbols} +\definemessageconstant {system} +\definemessageconstant {textblocks} +\definemessageconstant {verbatims} +\definemessageconstant {versions} + +%D When we use numbers and dimensions the same applies as with the keywords like +%D \type {width} and \type {plus} mentioned earlier. + +\immutable\def\!!ten {10} +\immutable\def\!!twelve {12} +\immutable\def\!!hundred {100} +\immutable\def\!!thousand {1000} +\immutable\def\!!tenthousand {10000} +\immutable\def\!!maxcard {65536} +\immutable\def\!!medcard {32768} + +\immutable\def\!!zeropoint {0pt} +\immutable\def\!!onepoint {1pt} +\immutable\def\!!twopoint {2pt} +\immutable\def\!!threepoint {3pt} +\immutable\def\!!fourpoint {4pt} +\immutable\def\!!fivepoint {5pt} +\immutable\def\!!sixpoint {6pt} +\immutable\def\!!sevenpoint {7pt} +\immutable\def\!!eightpoint {8pt} +\immutable\def\!!ninepoint {9pt} +\immutable\def\!!tenpoint {10pt} +\immutable\def\!!elevenpoint {11pt} +\immutable\def\!!twelvepoint {12pt} +\immutable\def\!!fourteenpointfour {14.4pt} + +\immutable\def\!!plustoken {+} % todo: \??plustoken +\immutable\def\!!minustoken {-} % todo: \??minustoken + +\immutable\def\__unknown__ {\string\\//} % unlikely value + +%D Variables are composed of a command specific tag and a user supplied variable +%D (system constant). The tag \type {du} for instance is available as \type {\??du} +%D and expands to \type {@@du} in composed variables. + +\definesystemvariable {du} % dummy, will stay + +% bibl: + +\definesystemvariable {pv} % PublicationVariable +\definesystemvariable {pb} % PuBlication + +% needs checking (namespaces now) + +\definesystemvariable {fw} % simpleFonts by Wolfgang + +% old pragma + +\definesystemvariable {kt} % KonTakten +\definesystemvariable {kw} % KontaktWaarde +\definesystemvariable {st} % STickers +\definesystemvariable {km} % KenMerk + +% mkii + +\definesystemvariable {xf} % XML File (xtag) +\definesystemvariable {xp} % XML Processing (xtag, so still needed) +\definesystemvariable {fo} % xml FO (xtag) +\definesystemvariable {fx} % FoXet + +% mkiv + +%D Next we define some language independant one letter variables and keywords. We can +%D actually make these system variables. + +\defineinterfaceconstant {x} {x} +\defineinterfaceconstant {y} {y} +\defineinterfaceconstant {w} {w} +\defineinterfaceconstant {h} {h} +\defineinterfaceconstant {s} {s} +\defineinterfaceconstant {t} {t} + +\defineinterfaceconstant {a} {a} % can go +\defineinterfaceconstant {b} {b} % can go +\defineinterfaceconstant {c} {c} % can go +\defineinterfaceconstant {d} {d} % can go +\defineinterfaceconstant {e} {e} % can go +\defineinterfaceconstant {f} {f} % can go + +%defineinterfaceconstant {s} {s} +\defineinterfaceconstant {r} {r} +\defineinterfaceconstant {g} {g} +%defineinterfaceconstant {b} {b} +%defineinterfaceconstant {c} {c} +\defineinterfaceconstant {m} {m} +%defineinterfaceconstant {y} {y} +\defineinterfaceconstant {k} {k} +%defineinterfaceconstant {a} {a} % alternative +%defineinterfaceconstant {t} {t} % transparency +\defineinterfaceconstant {p} {p} % percentage +%defineinterfaceconstant {h} {h} +%defineinterfaceconstant {s} {s} +\defineinterfaceconstant {v} {v} + +\defineinterfaceconstant {rgb} {rgb} +\defineinterfaceconstant {cmyk} {cmyk} +\defineinterfaceconstant {mp} {mp} + +\defineinterfacevariable {rgb} {rgb} +\defineinterfacevariable {cmyk} {cmyk} +\defineinterfacevariable {mp} {mp} + +\defineinterfacevariable {s} {s} + +\defineinterfacevariable {a} {a} +\defineinterfacevariable {b} {b} +\defineinterfacevariable {c} {c} +\defineinterfacevariable {d} {d} + +%D Special purpose variables: + +\immutable\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi} + +%D The names of files and their extensions are fixed. \CONTEXT\ uses as less +%D files as possible. Utility files can be recognized by the first two +%D characters of the extension: \type {tu}. + +%definefileconstant {utilityfilename} {texutil} +%definefileconstant {blockextension} {tub} +%definefileconstant {figureextension} {tuf} +%definefileconstant {inputextension} {tui} +%definefileconstant {outputextension} {tuo} % tup for previous run +%definefileconstant {optionextension} {top} +%definefileconstant {temporaryextension} {tmp} +%definefileconstant {patternsextension} {pat} +%definefileconstant {hyphensextension} {hyp} +%definefileconstant {fontmapextension} {map} +\definefileconstant {bibextension} {bbl} + +%D These files are loaded at start||up. They may contain system specific setups (or +%D calls to other files), old macro's, to garantee compatibility and new macro's noy +%D yet present in the format. + +\definefileconstant {sysfilename} {cont-sys.mkxl} +\definefileconstant {newfilename} {cont-new.mkxl} +\definefileconstant {locfilename} {cont-loc.mkxl} +\definefileconstant {expfilename} {cont-exp.mkxl} +\definefileconstant {fntfilename} {cont-fnt.mkxl} % not yet used +\definefileconstant {gdsfilename} {cont-fnt.lfg} % not yet used + +%D The setup files for the language, font, color and special subsystems have a common +%D prefix. This means that we have at most three characters for unique filenames. + +\definefileconstant {colo_run} {colo-run} +\definefileconstant {font_run} {font-run} +\definefileconstant {page_run} {page-run} +\definefileconstant {symb_run} {symb-run} +\definefileconstant {publ_tra} {publ-tra} + +%D For figure inclusion we need(ed): + +%defineinterfaceconstant {tif} {tif} +%defineinterfaceconstant {eps} {eps} +%defineinterfaceconstant {mps} {mps} +%defineinterfaceconstant {jpg} {jpg} +%defineinterfaceconstant {pdf} {pdf} +%defineinterfaceconstant {png} {png} +%defineinterfaceconstant {avi} {avi} +%defineinterfaceconstant {mov} {mov} +%defineinterfaceconstant {svg} {svg} +\defineinterfaceconstant {tex} {tex} % Also gone? +%defineinterfaceconstant {tmp} {tmp} +%defineinterfaceconstant {cld} {cld} + +%D A careful reader will have noticed that in the module \type {mult-ini} we defined +%D \type {\selectinterface}. We were not yet able to actually select an interface, +%D because we still had to define the constants and variables. Now we've done so, +%D selection is permitted. + +\selectinterface + +%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT. + +\definemessageconstant {addresses} +\definemessageconstant {documents} + +\protect \endinput diff --git a/tex/context/base/mkxl/node-aux.lmt b/tex/context/base/mkxl/node-aux.lmt new file mode 100644 index 000000000..d952ec41b --- /dev/null +++ b/tex/context/base/mkxl/node-aux.lmt @@ -0,0 +1,396 @@ +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 = nodes +local context = context + +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 par_code = nodecodes.par + +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 getattr = nuts.getattr +local getboth = nuts.getboth +local getprev = nuts.getprev +local getwidth = nuts.getwidth +local setwidth = nuts.setwidth +local getboxglue = nuts.getboxglue +local setboxglue = nuts.setboxglue + +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 setattrlist = nuts.setattrlist + +local traversers = nuts.traversers +local nextnode = traversers.node +local nextglyph = traversers.glyph + +local flush_node = nuts.flush +local flush_list = nuts.flush_list +local hpack_nodes = nuts.hpack +local unset_attribute = nuts.unset_attribute +local first_glyph = nuts.first_glyph +local copy_node = nuts.copy +local find_tail = nuts.tail +local getbox = nuts.getbox +local count = nuts.count +local isglyph = nuts.isglyph + +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") + +local function takebox(id) + local box = getbox(id) + if box then + local list = getlist(box) + setlist(box,nil) + local copy = copy_node(box) + if list then + setlist(copy,list) + end + texsetbox(id,false) + 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) + flush_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) + flush_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, id in nextnode, head do + setattr(n,attr,value) + 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, id in nextnode, head do + if not getattr(n,attr) then + setattr(n,attr,value) + end + 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, id in nextnode, head do + setattr(n,attr,unsetvalue) + 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) + +function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 + if untagged then + return first_glyph(n) + else + for g in nextglyph ,n do + return g + end + end +end + +local function firstcharinbox(n) + local l = getlist(getbox(n)) + if l then + for g, c in nextglyph, l do + return c + 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 + setattrlist(n,attr) + end + if head then + setlink(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) -- 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, id, subtype in nextnode, start do + if id == wantedid then + if not wantedsubtype or subtype == 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 + +local function rehpack(n,width) + local head = getlist(n) + local size = width or getwidth(n) + local temp = hpack_nodes(head,size,"exactly") + setwidth(n,size) + local set, order, sign = getboxglue(temp) + setboxglue(n,set,order,sign) + setlist(temp) + flush_node(temp) + return n +end + +nuts.rehpack = rehpack + +function nodes.rehpack(n,...) + rehpack(tonut(n),...) +end + +do + + local parcodes = nodes.parcodes + local hmodepar_code = parcodes.hmode_par + local vmodepar_code = parcodes.vmode_par + + local getnest = tex.getnest + local getsubtype = nuts.getsubtype + + function nuts.setparproperty(action,...) + local tail = tonut(getnest().tail) + while tail do + if getid(tail) == par_code then + local s = getsubtype(tail) + if s == hmodepar_code or s == vmodepar_code then + return action(tail,...) + else + -- something is wrong here + end + end + tail = getprev(tail) + end + end + + local getsubtype = nodes.getsubtype + + function nodes.start_of_par(n) + local s = getsubtype(n) + return s == hmodepar_code or s == vmodepar_code + end + +end diff --git a/tex/context/base/mkxl/node-bck.mkxl b/tex/context/base/mkxl/node-bck.mkxl new file mode 100644 index 000000000..e37d65b1c --- /dev/null +++ b/tex/context/base/mkxl/node-bck.mkxl @@ -0,0 +1,92 @@ +%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. + +\unprotect + +\registerctxluafile{node-bck}{optimize} + +% \backgroundvbox[green] {\input tufte } \par +% \backgroundvbox[blue] {\input ward } \par +% \backgroundvbox[red] {\input knuth } \par +% \backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par + +\permanent\def\colorattr#1% + {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname + \node_backgrounds_thecolorattr{\currentcolorprefix#1}% + \orelse\ifcsname\??colorattribute#1\endcsname + \node_backgrounds_thecolorattr{#1}% + \fi} + +\def\node_backgrounds_thecolorattr#1% + {attr \colormodelattribute \c_attr_colormodel + attr \colorattribute \lastnamedcs + attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized + +\permanent\def\thecolorattr#1% + {attr \colormodelattribute \c_attr_colormodel + attr \colorattribute \csname\??colorattribute#1\endcsname + attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized + +\permanent\def\backgroundcolorattr#1% + {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname + \node_backgrounds_thebackgroundcolorattr{\currentcolorprefix#1}% + \orelse\ifcsname\??colorattribute#1\endcsname + \node_backgrounds_thebackgroundcolorattr{#1}% + \fi} + +\permanent\def\thebackgroundcolorattr#1% + {attr \backgroundattribute \plusone + attr \colormodelattribute \c_attr_colormodel + attr \colorattribute \csname\??colorattribute#1\endcsname + attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized + +\def\node_backgrounds_thebackgroundcolorattr#1% + {attr \backgroundattribute \plusone + attr \colormodelattribute \c_attr_colormodel + attr \colorattribute \lastnamedcs + attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized + +\permanent\def\thealignbackgroundcolorattr#1% + {attr \alignbackgroundattribute \plusone + attr \colormodelattribute \c_attr_colormodel + attr \colorattribute \csname\??colorattribute#1\endcsname + attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized + +\permanent\protected\def\backgroundhbox{\node_backgrounds_boxes_add\hbox} +\permanent\protected\def\backgroundvbox{\node_backgrounds_boxes_add\vbox} +\permanent\protected\def\backgroundvtop{\node_backgrounds_boxes_add\vtop} +\permanent\protected\def\backgroundline{\dontleavehmode\node_backgrounds_boxes_add\hbox} + +% \def\node_backgrounds_boxes_add#1[#2]% +% {\begingroup +% \clf_enablebackgroundboxes +% \dousecolorparameter{#2}% +% \normalexpanded{\endgroup#1 +% attr \backgroundattribute \plusone +% attr \colormodelattribute \the\c_attr_colormodel +% attr \colorattribute \the\c_attr_color +% attr \transparencyattribute \the\c_attr_transparency}} +% +% more efficient: + +\def\node_backgrounds_boxes_add#1[#2]% + {\clf_enablebackgroundboxes + #1\backgroundcolorattr{#2}} + +\protect \endinput diff --git a/tex/context/base/mkxl/node-cmp.lmt b/tex/context/base/mkxl/node-cmp.lmt new file mode 100644 index 000000000..21fd700f0 --- /dev/null +++ b/tex/context/base/mkxl/node-cmp.lmt @@ -0,0 +1,237 @@ +if not modules then modules = { } end modules ['node-cmp'] = { + 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 a LuaTeX compatibility module. The code below is no longer +-- present in node-met or node-aux. These functions are rarely used. + +if node.count then + return +end + +local type = type + +local node = node +local direct = node.direct +local todirect = direct.tovaliddirect +local tonode = direct.tonode + +local count = direct.count +local length = direct.length +local slide = direct.slide + +function node.count(id,first,last) + return count(id,first and todirect(first), last and todirect(last) or nil) +end + +function node.length(first,last) + return length(first and todirect(first), last and todirect(last) or nil) +end + +function node.slide(n) + if n then + n = slide(todirect(n)) + if n then + return tonode(n) + end + end + return nil +end + +local hyphenating = direct.hyphenating +local ligaturing = direct.ligaturing +local kerning = direct.kerning + +-- kind of inconsistent + +function node.hyphenating(first,last) + if first then + local h, t = hyphenating(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end +end + +function node.ligaturing(first,last) + if first then + local h, t = ligaturing(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end +end + +function node.kerning(first,last) + if first then + local h, t = kerning(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end + end + +local protect_glyph = direct.protect_glyph +local unprotect_glyph = direct.unprotect_glyph +local protect_glyphs = direct.protect_glyphs +local unprotect_glyphs = direct.unprotect_glyphs + +function node.protect_glyphs(first,last) + protect_glyphs(todirect(first), last and todirect(last) or nil) +end + +function node.unprotect_glyphs(first,last) + unprotect_glyphs(todirect(first), last and todirect(last) or nil) +end + +function node.protect_glyph(first) + protect_glyph(todirect(first)) +end + +function node.unprotect_glyph(first) + unprotect_glyph(todirect(first)) +end + +local flatten_discretionaries = direct.flatten_discretionaries +local check_discretionaries = direct.check_discretionaries +local check_discretionary = direct.check_discretionary + +function node.flatten_discretionaries(first) + local h, count = flatten_discretionaries(todirect(first)) + return tonode(h), count +end + +function node.check_discretionaries(n) + check_discretionaries(todirect(n)) +end + +function node.check_discretionary(n) + check_discretionary(todirect(n)) +end + +local hpack = direct.hpack +local vpack = direct.vpack +local list_to_hlist = direct.mlist_to_hlist + +function node.hpack(head,...) + local h, badness = hpack(head and todirect(head) or nil,...) + return tonode(h), badness +end + +function node.vpack(head,...) + local h, badness = vpack(head and todirect(head) or nil,...) + return tonode(h), badness +end + +function node.mlist_to_hlist(head,...) + return tonode(mlist_to_hlist(head and todirect(head) or nil,...)) +end + +local end_of_math = direct.end_of_math +local find_attribute = direct.find_attribute +local first_glyph = direct.first_glyph + +function node.end_of_math(n) + if n then + n = end_of_math(todirect(n)) + if n then + return tonode(n) + end + end + return nil +end + +function node.find_attribute(n,a) + if n then + local v, n = find_attribute(todirect(n),a) + if n then + return v, tonode(n) + end + end + return nil +end + +function node.first_glyph(first,last) + local n = first_glyph(todirect(first), last and todirect(last) or nil) + return n and tonode(n) or nil +end + +local dimensions = direct.dimensions +local rangedimensions = direct.rangedimensions +local effective_glue = direct.effective_glue + +function node.dimensions(a,b,c,d,e) + if type(a) == "userdata" then + a = todirect(a) + if type(b) == "userdata" then + b = todirect(b) + end + return dimensions(a,b) + else + d = todirect(d) + if type(e) == "userdata" then + e = todirect(e) + end + return dimensions(a,b,c,d,e) + end + return 0, 0, 0 +end + +function node.rangedimensions(parent,first,last) + return rangedimenensions(todirect(parent),todirect(first),last and todirect(last)) +end + +function node.effective_glue(list,parent) + return effective_glue(list and todirect(list) or nil,parent and todirect(parent) or nil) +end + +local uses_font = direct.uses_font +local has_glyph = direct.has_glyph +local protrusion_skippable = direct.protrusion_skippable +local make_extensible = direct.make_extensible + +function node.uses_font(n,f) + return uses_font(todirect(n),f) +end + +function node.has_glyph(n) + return has_glyph(todirect(n)) +end + +function node.protrusion_skippable(n) + return protrusion_skippable(todirect(n)) +end + +function node.make_extensible(...) + local n = make_extensible(...) + return n and tonode(n) or nil +end + +local last_node = direct.last_node + +function node.last_node() + local n = last_node() + return n and tonode(n) or nil +end + +local is_zero_glue = direct.is_zero_glue +local getglue = direct.getglue +local setglue = direct.setglue + +function node.is_zero_glue(n) + return is_zero_glue(todirect(n)) +end + +function node.get_glue(n) + return get_glue(todirect(n)) +end + +function node.set_glue(n) + return set_glue(todirect(n)) +end + +node.family_font = tex.getfontoffamily diff --git a/tex/context/base/mkxl/node-fin.mkxl b/tex/context/base/mkxl/node-fin.mkxl new file mode 100644 index 000000000..183e02429 --- /dev/null +++ b/tex/context/base/mkxl/node-fin.mkxl @@ -0,0 +1,78 @@ +%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} + +\unprotect + +\registerctxluafile{node-shp}{optimize} +% \registerctxluafile{node-fin}{autosuffix,optimize} % we might generalize this one +\registerctxluafile{node-fin}{optimize} % we might generalize this one + +\permanent\protected\def\finalizeobjectbox #1{\clf_finalizebox#1\relax} +\permanent\protected\def\finalizeshipoutbox#1{\clf_finalizebox#1\relax} + +% Experimental (for Aditya): + +\permanent\protected\def\cleanupbox#1{\clf_cleanupbox#1\relax} + +% Tricky stuff: this might become obsolete. It is about time to check this out +% now (after more than a decade)! The few times that we need this we can better +% copy some of the sensitive attributes (mostly color). + +\definesystemattribute[trigger][public] + +\newcount\c_syst_attr_trigger + +\permanent\edef\startinheritattributes{\c_attr_trigger\plusone} +\permanent\edef\stopinheritattributes {\c_attr_trigger\attributeunsetvalue} + +\permanent\def\syst_attr_trigger_copy_yes{\afterassignment\syst_attr_trigger_copy_indeed\c_syst_attr_trigger} +\permanent\def\syst_attr_trigger_dump_yes{\afterassignment\syst_attr_trigger_dump_indeed\c_syst_attr_trigger} + +\def\syst_attr_trigger_copy_indeed + {\ifvbox\c_syst_attr_trigger + \vpack attr \triggerattribute \plusone {\unvcopy\c_syst_attr_trigger}% + \else + \hpack attr \triggerattribute \plusone {\unhcopy\c_syst_attr_trigger}% + \fi} + +\def\syst_attr_trigger_dump_indeed + {\ifvbox\c_syst_attr_trigger + \vpack attr \triggerattribute \plusone {\unvbox\c_syst_attr_trigger}% + \else + \hpack attr \triggerattribute \plusone {\unhbox\c_syst_attr_trigger}% + \fi} + +\permanent\protected\def\enableattributeinheritance + {\clf_enablestatetriggering + \enforced\let\attributedcopy\syst_attr_trigger_copy_yes + \enforced\let\attributedbox \syst_attr_trigger_dump_yes} + +\permanent\protected\def\disableattributeinheritance + {\clf_disablestatetriggering + \enforced\let\attributedcopy\copy + \enforced\let\attributedbox \box} + +\disableattributeinheritance + +\installtexdirective + {attributes.inheritance} + {\enableattributeinheritance} + {\disableattributeinheritance} + +% \appendtoks +% \enableattributeinheritance % might become default +% \to\everyjob + +\protect \endinput diff --git a/tex/context/base/mkxl/node-gcm.lmt b/tex/context/base/mkxl/node-gcm.lmt new file mode 100644 index 000000000..8b09fb82b --- /dev/null +++ b/tex/context/base/mkxl/node-gcm.lmt @@ -0,0 +1,112 @@ +if not modules then modules = { } end modules ['node-gmc'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring + +local nodes = nodes +local ligature_code = nodes.glyphcodes.ligature +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local copy_node = nuts.copy +local flush_list = nuts.flush_list +local count = nuts.count +local isglyph = nuts.isglyph +local getprop = nuts.getprop +local setprop = nuts.setprop + +local fastcopy = table.fastcopy + +local report_error = logs.reporter("node-aux:error") + +local function set_components(base,list) + local t = { } + local n = 0 + local l = list + while list do + local char = isglyph(list) + if char then + n = n + 1 + t[n] = char + end + list = getnext(list) + end + -- was forgotten: + flush_list(l) + -- + setprop(base,"components",n > 0 and t or false) +end + +local function get_components(base) + return getprop(base,"components") +end + +local function copy_no_components(base) + local copy = copy_node(base) + setprop(copy,"components",false) -- no metatable lookup! + return copy +end + +local function copy_only_glyphs(base) + local t = getprop(base,"components") -- also metatable + if t then + return fastcopy(t) + end +end + +local function do_count(t,marks) + local n = 0 + if t then + for i=1,#t do + local c = t[i] + if type(c) == "table" then + n = n + do_count(t,marks) + elseif not marks[c] then + n = n + 1 + else + --marks don't count + end + end + end + return n +end + +-- start is a mark and we need to keep that one + +local done = false + +local function count_components(base,marks) + local char = isglyph(base) + if char then + if getsubtype(base) == ligature_code then + if not done then + logs.report("fonts","!") + logs.report("fonts","! check count_components with mkiv !") + logs.report("fonts","!") + done = true + end + local t = getprop(base,"components") + if t then + return do_count(t,marks) + end + elseif not marks[char] then + return 1 + end + end + return 0 +end + +nuts.set_components = set_components +nuts.get_components = get_components +nuts.copy_only_glyphs = copy_only_glyphs +nuts.copy_no_components = copy_no_components +nuts.count_components = count_components + +nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end +nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt new file mode 100644 index 000000000..5cce9030d --- /dev/null +++ b/tex/context/base/mkxl/node-ini.lmt @@ -0,0 +1,280 @@ +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-- +

Most of the code that had accumulated here is now separated in modules.

+--ldx]]-- + +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-- +

Access to nodes is what gives its power. Here we implement a +few helper functions. These functions are rather optimized.

+--ldx]]-- + +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 getvalues = node.values + +tex.magicconstants = { -- we use tex.constants for something else + running = -1073741824, -- null_flag + maxdimen = 1073741823, -- max_dimen + trueinch = 4736286, +} + +local listcodes = mark(getsubtypes("list")) +local rulecodes = mark(getsubtypes("rule")) +local dircodes = mark(getsubtypes("dir")) +local glyphcodes = mark(getsubtypes("glyph")) +local disccodes = mark(getsubtypes("disc")) +local gluecodes = mark(getsubtypes("glue")) +local boundarycodes = mark(getsubtypes("boundary")) +local penaltycodes = mark(getsubtypes("penalty")) +local kerncodes = mark(getsubtypes("kern")) +local mathcodes = mark(getsubtypes("math")) +local noadcodes = mark(getsubtypes("noad")) +local radicalcodes = mark(getsubtypes("radical")) +local accentcodes = mark(getsubtypes("accent")) +local fencecodes = mark(getsubtypes("fence")) +----- fractioncodes = mark(getsubtypes("fraction")) +local parcodes = mark(getsubtypes("par")) + +local fillvalues = mark(getvalues("fill")) +local dirvalues = mark(getvalues("dir")) + +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 = allocate { + literal = 0x1, [0x1] = "literal", + latelua = 0x2, [0x2] = "latelua", + userdefined = 0x3, [0x3] = "userdefined", + savepos = 0x4, [0x4] = "savepos", + save = 0x5, [0x5] = "save", + restore = 0x6, [0x6] = "restore", + setmatrix = 0x7, [0x7] = "setmatrix", + open = 0x8, [0x8] = "open", + close = 0x9, [0x9] = "close", + write = 0xA, [0xA] = "write", +} + +local usercodes = allocate { + [ 97] = "attribute", -- a + [100] = "number", -- d + [102] = "float", -- f + [108] = "lua", -- l + [110] = "node", -- n + [115] = "string", -- s + [116] = "token" -- t +} + +local noadoptions = allocate { + set = 0x08, + unused_1 = 0x00 + 0x08, + unused_2 = 0x01 + 0x08, + axis = 0x02 + 0x08, + no_axis = 0x04 + 0x08, + exact = 0x10 + 0x08, + left = 0x11 + 0x08, + middle = 0x12 + 0x08, + right = 0x14 + 0x08, +} + +local literalvalues = allocate { + [0] = "origin", + [1] = "page", + [2] = "always", + [3] = "raw", + [4] = "text", + [5] = "font", + [6] = "special", +} + +gluecodes = allocate(swapped(gluecodes,gluecodes)) +dircodes = allocate(swapped(dircodes,dircodes)) +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)) +disccodes = allocate(swapped(disccodes,disccodes)) +accentcodes = allocate(swapped(accentcodes,accentcodes)) +fencecodes = allocate(swapped(fencecodes,fencecodes)) +parcodes = allocate(swapped(parcodes,parcodes)) +rulecodes = allocate(swapped(rulecodes,rulecodes)) +usercodes = allocate(swapped(usercodes,usercodes)) +noadoptions = allocate(swapped(noadoptions,noadoptions)) + +dirvalues = allocate(swapped(dirvalues,dirvalues)) +literalvalues = allocate(swapped(literalvalues,literalvalues)) +fillvalues = allocate(swapped(fillvalues,fillvalues)) + +nodes.gluecodes = gluecodes +nodes.dircodes = dircodes +nodes.boundarycodes = boundarycodes +nodes.noadcodes = noadcodes +nodes.whatcodes = whatcodes +nodes.listcodes = listcodes +nodes.glyphcodes = glyphcodes +nodes.kerncodes = kerncodes +nodes.penaltycodes = penaltycodes +nodes.mathcodes = mathcodes +nodes.disccodes = disccodes +nodes.accentcodes = accentcodes +nodes.radicalcodes = radicalcodes +nodes.fencecodes = fencecodes +nodes.parcodes = parcodes +nodes.rulecodes = rulecodes +nodes.usercodes = usercodes + +nodes.noadoptions = noadoptions +nodes.fillvalues = fillvalues +nodes.fillcodes = fillvalues -- for now +nodes.dirvalues = dirvalues +nodes.literalvalues = literalvalues + +nodes.nodecodes = nodecodes + +-- local subtypes = allocate { +-- [nodecodes.glue] = gluecodes, +-- [nodecodes.dir] = dircodes, +-- [nodecodes.boundary] = boundarycodes, +-- [nodecodes.noad] = noadcodes, +-- [nodecodes.whatsit] = whatcodes, +-- [nodecodes.glyph] = glyphcodes, +-- [nodecodes.kern] = kerncodes, +-- [nodecodes.penalty] = penaltycodes, +-- [nodecodes.math] = mathcodes, +-- [nodecodes.disc] = disccodes, +-- [nodecodes.accent] = accentcodes, +-- [nodecodes.radical] = radicalcodes, +-- [nodecodes.fence] = fencecodes, +-- [nodecodes.par] = parcodes, +-- [nodecodes.rule] = rulecodes, + +-- [nodecodes.vlist] = listcodes, +-- [nodecodes.hlist] = listcodes, + +-- -- [nodecodes.list] = listcodes, + +-- -- [nodecodes.parameter] = parametercodes, +-- -- [nodecodes.user] = usercodes, +-- } + +-- for k in next, table.sortedkeys(subtypes) do +-- local v = nodecodes[k] +-- print(k,v) +-- if k and subtypes[k] then +-- subtypes[v] = subtypes[k] +-- end +-- end + +local subtypes = allocate { + glue = gluecodes, + dir = dircodes, + boundary = boundarycodes, + noad = noadcodes, + whatsit = whatcodes, + glyph = glyphcodes, + kern = kerncodes, + penalty = penaltycodes, + math = mathcodes, + disc = disccodes, + accent = accentcodes, + radical = radicalcodes, + fence = fencecodes, + par = parcodes, + rule = rulecodes, + + vlist = listcodes, + hlist = listcodes, + + -- list = listcodes, + + -- parameter = parametercodes, + -- user = usercodes, +} + +for k, v in table.sortedhash(subtypes) do + local i = nodecodes[k] + if i and not subtypes[i] then + subtypes[i] = v + end +end + +nodes.subtypes = subtypes + +-- a few more friendly aliases: + +nodes.skipcodes = gluecodes +nodes.directioncodes = dircodes +nodes.whatsitcodes = whatcodes +nodes.discretionarycodes = disccodes + +nodes.directionvalues = dirvalues +nodes.literalvalues = literalvalues + +glyphcodes.glyph = glyphcodes.character + +gluecodes.parfillrightskip = gluecodes.parfillrightskip or gluecodes.parfillskip +gluecodes.parfillskip = gluecodes.parfillskip or gluecodes.parfillrightskip + +listcodes.row = listcodes.alignment +listcodes.column = listcodes.alignment + +kerncodes.kerning = kerncodes.fontkern +kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new + +literalvalues.direct = literalvalues.always + +nodes.noadoptions = { + set = 0x08, + unused_1 = 0x00 + 0x08, + unused_2 = 0x01 + 0x08, + axis = 0x02 + 0x08, + no_axis = 0x04 + 0x08, + exact = 0x10 + 0x08, + left = 0x11 + 0x08, + middle = 0x12 + 0x08, + right = 0x14 + 0x08, +} + +-- We use the real node code numbers. + +local texsetintegervalue = tex.setintegervalue + +for i=0,nodecodes.glyph do + texsetintegervalue(nodecodes[i] .. "nodecode",i,"immutable") +end +for i=0,#gluecodes do + texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable") +end + +-- tex.set("internalcodesmode",1) -- obsolete diff --git a/tex/context/base/mkxl/node-ini.mkxl b/tex/context/base/mkxl/node-ini.mkxl new file mode 100644 index 000000000..4cb322448 --- /dev/null +++ b/tex/context/base/mkxl/node-ini.mkxl @@ -0,0 +1,56 @@ +%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-cmp}{autosuffix} +\registerctxluafile{node-ini}{autosuffix} +\registerctxluafile{node-met}{} +\registerctxluafile{node-nut}{autosuffix} +\registerctxluafile{node-res}{} +%registerctxluafile{node-ppt}{} % experimental, not used so probably useless +\registerctxluafile{node-aux}{autosuffix} +\registerctxluafile{node-gcm}{autosuffix} +\registerctxluafile{node-tst}{} +\registerctxluafile{node-tra}{} % we might split it off (module) +\registerctxluafile{node-snp}{autosuffix} +\registerctxluafile{node-tsk}{} +\registerctxluafile{node-tex}{autosuffix} +\registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used +\registerctxluafile{node-pro}{} +\registerctxluafile{node-ser}{autosuffix} +\registerctxluafile{node-ext}{} +\registerctxluafile{node-acc}{} % experimental +%registerctxluafile{node-prp}{} % makes no sense (yet) +\registerctxluafile{node-scn}{} +\registerctxluafile{node-syn}{} +\registerctxluafile{node-par}{autosuffix} + +%D This might go away (needs checking anyway, very old code): + +\newcount\c_node_tracers_show_box % box number + +\permanent\protected\def\shownextnodes{\afterassignment\node_tracers_show_next\c_node_tracers_show_box} +\permanent\protected\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))}} + +\permanent\protected\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}} +\permanent\protected\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/node-mig.lmt b/tex/context/base/mkxl/node-mig.lmt new file mode 100644 index 000000000..c19913509 --- /dev/null +++ b/tex/context/base/mkxl/node-mig.lmt @@ -0,0 +1,134 @@ +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 nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getid = nuts.getid +local getlist = nuts.getlist +local getpost = nuts.getpost +local getprop = nuts.getprop + +local setprop = nuts.setprop +local setlink = nuts.setlink +local setlist = nuts.setlist +local setpost = nuts.setpost + +local count = nuts.count +local migrate = nuts.migrate + +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 = false +local migrate_marks = false +local t_inserts = 0 +local t_marks = 0 +local t_sweeps = 0 + +local trialtypesetting = context.trialtypesetting + +function nodes.handlers.migrate(head,where) + if head and not trialtypesetting() and where == "alignment" then + if trace_migrations then + report_nodes("migration sweep %a",where) + end + local current = head + while current do + local id = getid(current) + if (id == vlist_code or id == hlist_code or id == insert_code) and not getprop(current,"migrated") then + setprop(current,"migrated",true) + local list = getlist(current) + if list then + t_sweeps = t_sweeps + 1 + local h, first, last = migrate(list,migrate_inserts,migrate_marks) + if first then + if trace_migrations then + local ni = count(insert_code,first) + local nm = count(mark_code,first) + t_inserts = t_inserts + ni + t_marks = t_marks + nm + report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a", + t_sweeps,nodecodes[id],ni,nm,where) + + end + local p, t = getpost(current) + if p then + setlink(t,first) + else + setpost(current,first) + end + end + end + end + current = getnext(current) + end + end + return head +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) + +-- Since we started with mkiv we had it as experiment but it is about time +-- to have a more formal interface .. it's still optional due to possible +-- side effects. + +local enableaction = nodes.tasks.enableaction +local disableaction = nodes.tasks.disableaction +local texsetcount = tex.setcount + +local migrations = { } +nodes.migrations = migrations +local enabled = false + +local function check() + if migrate_marks or migrate_inserts then + if not enabled then + enableaction("mvlbuilders", "nodes.handlers.migrate") + enabled = true + texsetcount("automigrationmode",3) + end + else + if enabled then + disableaction("mvlbuilders", "nodes.handlers.migrate") + enabled = false + texsetcount("automigrationmode",0) + end + end +end + +function migrations.setmarks(v) + migrate_marks = v + check() +end + +function migrations.setinserts(v) + migrate_inserts = v + check() +end diff --git a/tex/context/base/mkxl/node-mig.mkxl b/tex/context/base/mkxl/node-mig.mkxl new file mode 100644 index 000000000..420140e6f --- /dev/null +++ b/tex/context/base/mkxl/node-mig.mkxl @@ -0,0 +1,44 @@ +%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 \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}{autosuffix} + +\aliased\let\automigrateinserts\donothing +\aliased\let\automigratemarks \donothing + +\protect diff --git a/tex/context/base/mkxl/node-nut.lmt b/tex/context/base/mkxl/node-nut.lmt new file mode 100644 index 000000000..6b9dd803e --- /dev/null +++ b/tex/context/base/mkxl/node-nut.lmt @@ -0,0 +1,579 @@ +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" +} + +-- Some comments anbout going nuts can be found in the mkiv file with the +-- suffix "lua", including some timing and musings. We copy the direct table +-- (1) because that's what we did while things evolved and (2) because we +-- also add some more helpers. + +local type, rawget = type, rawget + +local nodes = nodes +local direct = node.direct + +local fastcopy = table.fastcopy + +local nodecodes = nodes.nodecodes +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph + +local tonode = direct.tonode +local tonut = direct.todirect + +local is_node = direct.is_node +local is_nut = direct.is_direct + +local d_remove_node = direct.remove +local d_flush_node = direct.flush_node +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 +local d_traverse = direct.traverse +local d_setlink = direct.setlink +local d_getboth = direct.getboth + +local nuts = { + check_discretionaries = direct.check_discretionaries, + copy = direct.copy, + copy_list = direct.copy_list, + copy_node = direct.copy, + copy_only = direct.copy_only or direct.copy, + count = direct.count, + current_attributes = direct.current_attributes, + delete = direct.delete, + dimensions = direct.dimensions, + effective_glue = direct.effective_glue, + end_of_math = direct.end_of_math, + exchange = direct.exchange, + find_attribute = direct.find_attribute, + first_glyph = direct.first_glyph, + flatten_discretionaries = direct.flatten_discretionaries, + flush = d_flush_node, + flush_components = direct.flush_components, + flush_list = direct.flush_list, + flush_node = direct.flush_node, + free = direct.free, + getsynctexfields = direct.get_synctex_fields, + getattr = direct.get_attribute, + getattrs = direct.get_attributes, + getattributelist = direct.getattributelist, + getattrlist = direct.getattributelist, + getboth = d_getboth, + getbox = direct.getbox, + getboxglue = direct.getglue, + getchar = direct.getchar, + getcomponents = direct.getcomponents, + getdata = direct.getdata, + getdepth = direct.getdepth, + getdir = direct.getdir, + getdirection = direct.getdirection, + getdisc = direct.getdisc, + getdiscretionary = direct.getdisc, + getexpansion = direct.getexpansion, + getfam = direct.getfam, + getfield = direct.getfield, + getfont = direct.getfont, + getglue = direct.getglue, + getglyphdata = direct.getglyphdata, + getheight = direct.getheight, + getid = d_getid, + getkern = direct.getkern, + getlang = direct.getlanguage,-- will become obsolete + getlanguage = direct.getlanguage, + getleader = direct.getleader, + getlist = d_getlist, + getnext = d_getnext, + getnormalizedline = direct.getnormalizedline, + getnucleus = direct.getnucleus, + getoffsets = direct.getoffsets, + getorientation = direct.getorientation, + getoptions = direct.getoptions, + getpenalty = direct.getpenalty, + getpost = direct.getpost, + getpre = direct.getpre, + getprev = d_getprev, + getreplace = direct.getreplace, + getruledata = direct.getdata, -- obsolete when we have the split + getscript = direct.setscript, + getshift = direct.getshift, + getstate = direct.getstate, + getsub = direct.getsub, + getsubpre = direct.getsubpre, + getsubtype = direct.getsubtype, + getsup = direct.getsup, + getsuppre = direct.getsuppre, + getsurround = direct.getkern, + gettotal = direct.gettotal, + getvalue = direct.getdata, -- obsolete + getwhd = direct.getwhd, + getwidth = direct.getwidth, + has_attribute = direct.has_attribute, + has_dimensions = direct.has_dimensions, + has_field = direct.has_field, + has_glyph = direct.has_glyph or direct.first_glyph, + hpack = direct.hpack, + hyphenating = direct.hyphenating, + insert_after = d_insert_after, + insert_before = d_insert_before, + is_direct = is_direct, + is_node = is_node, + is_nut = direct.is_direct, + is_zero_glue = direct.is_zero_glue, + ischar = direct.is_char, + isglyph = direct.is_glyph, + kerning = direct.kerning, + last_node = direct.last_node, + length = direct.length, + ligaturing = direct.ligaturing, + migrate = direct.migrate, + mlist_to_hlist = direct.mlist_to_hlist, + new = direct.new, + protect_glyph = direct.protect_glyph, + protect_glyphs = direct.protect_glyphs, + protrusion_skippable = direct.protrusion_skippable, + rangedimensions = direct.rangedimensions, + getglyphdimensions = direct.getglyphdimensions, + getkerndimension = direct.getkerndimension, + remove = d_remove_node, + reverse = direct.reverse, + set_attribute = direct.set_attribute, + setattr = direct.set_attribute, + setattrs = direct.set_attributes, + setattributelist = direct.setattributelist, + setattrlist = direct.setattributelist, + setboth = direct.setboth, + setbox = direct.setbox, + setboxglue = direct.setglue, + setchar = direct.setchar, + setcomponents = direct.setcomponents, + setdata = direct.setdata, + setdepth = direct.setdepth, + setdir = direct.setdir, + setdirection = direct.setdirection, + setdisc = direct.setdisc, + setdiscretionary = direct.setdisc, + setexpansion = direct.setexpansion, + setfam = direct.setfam, + setfield = direct.setfield, + setfont = direct.setfont, + setglue = direct.setglue, + setglyphdata = direct.setglyphdata, + setheight = direct.setheight, + setkern = direct.setkern, + setlang = direct.setlanguage, + setlanguage = direct.setlanguage, + setleader = direct.setleader, + setlink = d_setlink, + setlist = direct.setlist, + setnext = direct.setnext, + setnucleus = direct.setnucleus, + setoffsets = direct.setoffsets, + setorientation = direct.setorientation, + setoptions = direct.setoptions, + setpenalty = direct.setpenalty, + setpost = direct.setpost, + setpre = direct.setpre, + setprev = direct.setprev, + setreplace = direct.setreplace, + setruledata = direct.setdata, -- obsolete when we have the split + setscript = direct.getscript, + setshift = direct.setshift, + setsplit = direct.setsplit, + setstate = direct.setstate, + setsub = direct.setsub, + setsubpre = direct.setsubpre, + setsubtype = direct.setsubtype, + setsup = direct.setsup, + setsuppre = direct.setsuppre, + setsurround = direct.setkern, + setsynctexfields = direct.set_synctex_fields, + setvalue = direct.setdata, -- obsolete + setwhd = direct.setwhd, + setwidth = direct.setwidth, + slide = d_slide, + start_of_par = direct.start_of_par, + tail = d_find_tail, + takeattr = direct.unset_attribute, -- ? + tonode = tonode, + tonut = tonut, + tostring = direct.tostring, + traverse = d_traverse, + traverse_char = direct.traverse_char, + traverse_glyph = direct.traverse_glyph, + traverse_id = direct.traverse_id, + traverse_list = direct.traverse_list, + traverse_content = direct.traverse_content, + unprotect_glyph = direct.unprotect_glyph, + unprotect_glyphs = direct.unprotect_glyphs, + unset_attribute = direct.unset_attribute, + usedlist = direct.usedlist, + uses_font = direct.uses_font, + vpack = direct.vpack, + writable_spec = direct.writable_spec, + write = direct.write, + append = direct.append, +} + +nodes.nuts = nuts + +nodes.is_node = is_node +nodes.is_direct = is_nut +nodes.is_nut = is_nut + +nodes.tonode = tonode +nodes.tonut = tonut + +function nuts.delete(head,current) + return d_remove_node(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 prev or next then + d_setlink(prev,new,next) + end + if head then + if head == current then + head = new + end + d_flush_node(current) + return head, new + else + d_flush_node(current) + return new + end +end + +local function countall(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 + countall(list) -- self counts too + else + n = n + 1 + end + else + n = n + 1 + end + stack = d_getnext(stack) + end + return n +end + +nuts.countall = countall + +function nodes.countall(stack,flat) + return countall(tonut(stack),flat) +end + +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(...) -- slides ! + 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 "" +end + +function nuts.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end +function nuts.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end + +nodes.vianuts = nuts.vianuts +nodes.vianodes = nuts.vianodes + +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_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 + +-- this might move + +local propertydata = direct.get_properties_table(true) + +local getattr = nuts.getattr +local setattr = nuts.setattr + +nodes.properties = { + data = propertydata, +} + +-- experimental code with respect to copying attributes has been removed +-- as it doesn't pay of (most attributes are only accessed once anyway) + +function nuts.getprop(n,k) + local p = propertydata[n] + if p then + if k then + return p[k] + else + return p + end + end +end + +function nuts.rawprop(n,k) + local p = rawget(propertydata,n) + if p then + if k then + return p[k] + else + return p + end + end +end + +function nuts.setprop(n,k,v) + local p = propertydata[n] + if p then + p[k] = v + else + propertydata[n] = { [k] = v } + end +end + +function nuts.theprop(n) + local p = propertydata[n] + if not p then + p = { } + propertydata[n] = p + end + return p +end + + +function nuts.isdone(n,k) + local p = propertydata[n] + if not p then + propertydata[n] = { [k] = true } + return false + end + local v = p[k] + if v == nil then + propertydata[n] = { [k] = true } + return false + end + return v +end + +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 diff --git a/tex/context/base/mkxl/node-par.lmt b/tex/context/base/mkxl/node-par.lmt new file mode 100644 index 000000000..af3125d23 --- /dev/null +++ b/tex/context/base/mkxl/node-par.lmt @@ -0,0 +1,48 @@ +if not modules then modules = { } end modules ['node-par'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local sequencers = utilities.sequencers + +-- This are called a lot! + +local actions = nodes.tasks.actions("everypar") + +local function everypar(head) + starttiming(builders) + head = actions(head) + stoptiming(builders) + return head +end + +callbacks.register("insert_par",everypar,"after paragraph start") + +local actions = sequencers.new { + name = "paragraph", + arguments = "mode,indented", + returnvalues = "indented", + results = "indented", +} + +sequencers.appendgroup(actions,"before") -- user +sequencers.appendgroup(actions,"system") -- private +sequencers.appendgroup(actions,"after" ) -- user + +local function paragraph(mode,indented) + local runner = actions.runner + if runner then + starttiming(builders) + indented = runner(mode,indented) + stoptiming(builders) + end + return indented +end + +callbacks.register("begin_paragraph",paragraph,"before paragraph start") diff --git a/tex/context/base/mkxl/node-rul.mkxl b/tex/context/base/mkxl/node-rul.mkxl new file mode 100644 index 000000000..72201ac71 --- /dev/null +++ b/tex/context/base/mkxl/node-rul.mkxl @@ -0,0 +1,611 @@ +%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 formal definitions are: +%D +%D \showsetup{underbar} +%D \showsetup{underbars} +%D \showsetup{overbar} +%D \showsetup{overbars} +%D \showsetup{overstrike} +%D \showsetup{overstrikes} +%D +%D \showsetup{setupbars} +%D +%D Units can be any normal \TEX\ unit: +%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}{optimize} + +\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 + +\aliased\let\setupbars\setupbar + +\appendtoks + \ifempty\currentbar + \the\t_node_rules_checklist + \else + \node_rules_define + \fi +\to \everysetupbar + +\appendtoks + \ifcsname\??barindex\currentbar\endcsname + \lastnamedcs\zerocount + \else + \expandafter\newcount\csname\??barindex\currentbar\endcsname + \fi + % \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}% + \normalexpanded{\t_node_rules_checklist{\the\t_node_rules_checklist\relax\node_rules_redefine{\currentbar}}}% + % \etoksapp\t_node_rules_checklist{\node_rules_redefine{\currentbar}}% + \node_rules_define + \frozen\instance\setuevalue\currentbar{\node_rules_direct{\currentbar}}% +\to \everydefinebar + +\newbox\b_node_rules + +\protected\def\node_rules_define + {\edef\p_node_rules_color{\barparameter\c!color}% + \edef\p_node_text{\barparameter\c!text}% + \ifx\p_node_text\empty\else + \setbox\b_node_rules\hbox{\p_node_text}% + \fi + \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 + empty {\barparameter\c!empty}% + \ifx\p_node_text\empty\else + % not that useful and efficient, more for testing something + text \b_node_rules + repeat {\barparameter\c!repeat}% + \fi + \relax}} + +\protected\def\node_rules_redefine#1% + {\def\currentbar{#1}\node_rules_define} + +\protected\def\node_rules_direct#1% + {\groupedcommand + {\node_rules_set{#1}\barparameter\c!left}% + {\relax\barparameter\c!right}} + +\permanent\protected\def\inlinebar[#1]% + {\node_rules_direct{#1}} + +% \protected\def\inlinecurrentbar +% {\node_rules_direct{\currentbar}} + +% store in properties + +\permanent\protected\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 + % maybe: \usebarstyleandcolor\c!textgroundstyle\c!textcolor + % 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 + \c_attr_ruled\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} + +\permanent\protected\def\resetbar + {\c_attr_ruled\attributeunsetvalue} + +\permanent\protected\def\nobar + {\groupedcommand + {\resetbar\barparameter\c!left}% + {\relax\barparameter\c!right}} + +\permanent\protected\def\startbar[#1]% + {\begingroup + \node_rules_set{#1}% + \ignorespaces + \barparameter\c!left} + +\permanent\protected\def\stopbar + {\removeunwantedspaces + \barparameter\c!right + \endgroup} + +\permanent\protected\def\setbar[#1]% + {\node_rules_set{#1}} + +\aliased\let\directsetbar\node_rules_set + +% ungrouped + +\newcount\c_node_rules_nesting % todo: same as colors + +\permanent\protected\def\pushbar[#1]% + {\global\advance\c_node_rules_nesting\plusone + \edefcsname\??barstack\number\c_node_rules_nesting\endcsname{\c_attr_ruled\the\c_attr_ruled}% + \node_rules_set{#1}} + +\permanent\protected\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!empty=, % new: yes = hide text + \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] + +\pushoverloadmode + +\aliased\let\normalmathoverbar \overbar +\aliased\let\normalmathunderbar \underbar +\aliased\let\normalmathoverstrike \overstrike +\aliased\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] + +\definebar + [\v!hiddenbar] + [\v!underbar] + [\c!continue=\v!yes, + \c!empty=\v!yes, + \c!left=\zwj, + \c!right=\zwj] + +% \setupbar[\v!overstrike][continue=all] + +% we want these always so ... + +\ifdefined\normalmathunderbar + \enforced\permanent\expandafter\let\expandafter\normaltextunderbar\csname\v!underbar\endcsname + \enforced\permanent\protected\def\underbar{\mathortext\normalmathunderbar\normaltextunderbar} +\else + \enforced\permanent\expandafter\let\expandafter\underbar\csname\v!underbar\endcsname +\fi + +\ifdefined\normalmathoverbar + \enforced\permanent\expandafter\let\expandafter\normaltextoverbar\csname\v!overbar\endcsname + \enforced\permanent\protected\def\overbar{\mathortext\normalmathoverbar\normaltextoverbar} +\else + \enforced\permanent\expandafter\let\expandafter\overbar\csname\v!overbar\endcsname +\fi + +\ifdefined\normalmathunderstrike + \enforced\permanent\expandafter\let\expandafter\normaltextunderstrike\csname\v!understrike\endcsname + \enforced\permanent\protected\def\understrike{\mathortext\normalmathunderstrike\normaltextunderstrike} +\else + \enforced\permanent\expandafter\let\expandafter\understrike\csname\v!understrike\endcsname +\fi + +\ifdefined\normalmathoverstrike + \enforced\permanent\expandafter\let\expandafter\normaltextoverstrike\csname\v!overstrike\endcsname + \enforced\permanent\protected\def\overstrike{\mathortext\normalmathoverstrike \normaltextoverstrike} +\else + \enforced\permanent\expandafter\let\expandafter\overstrike\csname\v!overstrike\endcsname +\fi + +\enforced\permanent\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname +\enforced\permanent\expandafter\let\expandafter\underbars \csname\v!underbars \endcsname +\enforced\permanent\expandafter\let\expandafter\overbars \csname\v!overbars \endcsname + +\enforced\permanent\protected\def\setupunderbar[#1]% too incompatible for the moment + {} + +\popoverloadmode + +%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} + path p ; p := (0,RuleDepth) -- (RuleWidth,RuleDepth) ; + numeric l ; l := arclength(p); + l := l mod RuleThickness/4; + draw + p + shifted (l,RuleFactor*RuleOffset) + dashed dashpattern(off 2RuleThickness+l on 0 off 2RuleThickness) + 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 + \ifempty\currentshift + \the\t_node_shifts_checklist + \else + \node_shifts_define + \fi +\to \everysetupshift + +\appendtoks + \ifcsname\??shiftindex\currentshift\endcsname + \lastnamedcs\zerocount + \else + \expandafter\newcount\csname\??shiftindex\currentshift\endcsname + \fi + \normalexpanded{\t_node_shifts_checklist{\the\t_node_shifts_checklist\node_shifts_redefine{\currentshift}}}% order ? + \node_shifts_define + \setuevalue\currentshift{\node_shifts_direct{\currentshift}}% +\to \everydefineshift + +\protected\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}} + +\protected\def\node_shifts_redefine#1% + {\def\currentshift{#1}\node_shifts_define} + +\protected\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 + \clf_enableshifts % will be relaxed + \c_attr_shifted\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}} % weird feature that i probably needed once + +\permanent\protected\def\startshift[#1]% + {\begingroup + \node_shifts_set{#1}% + \ignorespaces} + +\permanent\protected\def\stopshift + {\removeunwantedspaces + \endgroup} + +% \protected\def\node_shifts_direct#1% +% {\doisolatedgroupedalign{\node_shifts_set{#1}}\donothing} + +\protected\def\node_shifts_direct#1% + {\groupedcommand + {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}\ignorespaces} + {\removeunwantedspaces\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: + +\protected\def\dostartisolation{\signalcharacter} +\protected\def\dostopisolation {\signalcharacter} +\protected\def\doisolator {\signalcharacter} + +\protected\def\dosetupisolatedalign#1% + {\doisolator + \setupalign[#1]\relax} + +\protected\def\doisolatedgroupedalign#1#2% + {\groupedcommand + {\begingroup\dostartisolation\begingroup#1} + {#2\endgroup\dostopisolation\endgroup}} + +%D More rules. + +% The following code rocks and was written with the Toto Live in Poland bluray +% in loop mode on my 5.1 surround development setup (the Toto lineup with Simon +% Phillips on drums). The Amsterdam concert is equally energizing. + +\installcorenamespace{linefiller} +\installcorenamespace{linefillerindex} +\installcorenamespace{linefillerattribute} + +\installcommandhandler \??linefiller {linefiller} \??linefiller + +\definesystemattribute[linefiller][public] + +\newtoks\t_node_linefiller_checklist + +\let\c_node_linefiller_index\relax % temporary synonym + +\aliased\let\setuplinefillers\setuplinefiller + +\appendtoks + \ifempty\currentlinefiller + \the\t_node_linefiller_checklist + \else + \node_linefiller_define + \fi +\to \everysetuplinefiller + +\appendtoks + \ifcsname\??linefillerindex\currentlinefiller\endcsname + \lastnamedcs\zerocount + \else + \expandafter\newcount\csname\??linefillerindex\currentlinefiller\endcsname + \fi + \etoksapp\t_node_linefiller_checklist{\t_node_linefiller_checklist\node_linefiller_redefine{\currentlinefiller}}% + \node_linefiller_define +\to \everydefinelinefiller + +\protected\def\node_linefiller_define + {\edef\p_node_rules_color{\linefillerparameter\c!color}% + \setevalue{\??linefillerattribute\currentlinefiller}{\number + \clf_definelinefiller + %method \linefillerparameter\c!method + location {\linefillerparameter\c!location}% + scope {\linefillerparameter\c!scope}% + mp {\includeMPgraphic{\linefillerparameter\c!mp}}% + ma \thecolormodelattribute + ca \thecolorattribute\p_node_rules_color + ta \thetransparencyattribute\p_node_rules_color + height \dimexpr\linefillerparameter\c!height\relax + depth \dimexpr\linefillerparameter\c!depth\relax + distance \dimexpr\linefillerparameter\c!distance\relax + threshold \dimexpr\linefillerparameter\c!threshold\relax + rulethickness \dimexpr\linefillerparameter\c!rulethickness\relax + \relax}} + +\protected\def\node_linefiller_redefine#1% + {\def\currentlinefiller{#1}\node_linefiller_define} + +\protected\def\node_linefiller_set#1% todo: check parent ! todo: move attr etc to lua + {\def\currentlinefiller{#1}% + \expandafter\let\expandafter\c_node_linefiller_index\csname\??linefillerindex#1\endcsname + \advance\c_node_linefiller_index\plusone + \clf_enablelinefillers + \c_attr_linefiller\numexpr + \plusthousand*\c_node_linefiller_index + +\csname\??linefillerattribute#1\ifcsname\??linefiller#1:\number\c_node_linefiller_index\s!parent\endcsname:\number\c_node_linefiller_index\fi\endcsname + \relax} + +\permanent\tolerant\protected\def\startlinefiller[#1]#*[#2]% + {\begingroup + \par + \def\currentlinefiller{#1}% + \ifargument#1\or + % we need to update settings + \setuplinefiller[#1][#2]% no \setupcurrentlinefiller as we need to update settings + \fi + \node_linefiller_set{#1}% + \linefillerparameter\c!before + \usealignparameter\linefillerparameter + \uselinefillerstyleandcolor\c!textstyle\c!textcolor} % bars have foregroundcolor + +\permanent\protected\def\stoplinefiller + {\par + \linefillerparameter\c!after + \endgroup} + +\permanent\protected\def\setlinefiller[#1]% + {\node_linefiller_set{#1}} + +\setuplinefillers + [%c!method=0, + %c!mp=, + \c!location=\v!both, + \c!scope=\v!local, + \c!distance=\zeropoint, + \c!threshold=\zeropoint, + \c!rulethickness=\linewidth, + \c!height=\linewidth, + \c!depth=\zeropoint, + %\c!textcolor=, + %\c!textstyle=, + %\c!align=, + %\c!before=, + %\c!after=, + \c!color=] + +\definelinefiller + [filler] + [\c!height=.75\exheight, + %\c!mp=rules:filler:demo, + %\c!threshold=.25\emwidth, + \c!distance=.25\emwidth, + \c!rulethickness=.25\exheight] + +%D Bonus: +%D +%D \starttyping +%D \startuseMPgraphic{foo} +%D fill unitsquare +%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) +%D shifted (-ExHeight/8,ExHeight/16) +%D withcolor RuleColor ; +%D \stopuseMPgraphic +%D +%D \definelinefiller[foo][mp=foo,color=darkred] +%D +%D \linefillerhbox[foo]{OEPS} +%D \stoptyping + +\protected\def\node_backgrounds_filler_box#1#2[#3]% + {\bgroup + \clf_enablebackgroundboxes + \dowithnextbox{% + \node_linefiller_set{#3}% already sets the attribute + #1% + attr \backgroundattribute \plusone + % attr \linefillerattribute \the\c_attr_linefiller + {\box\nextbox}% + \egroup}% + #2} + +\permanent\protected\def\linefillerhbox{\node_backgrounds_filler_box\hpack\hbox} +\permanent\protected\def\linefillervbox{\node_backgrounds_filler_box\vpack\vbox} +\permanent\protected\def\linefillervtop{\node_backgrounds_filler_box\tpack\vtop} + +%D Bonus: + +\permanent\protected\def\autorule{\clf_autorule} % todo: public implementor + +\protect \endinput diff --git a/tex/context/base/mkxl/node-ser.lmt b/tex/context/base/mkxl/node-ser.lmt new file mode 100644 index 000000000..0d7f3ccad --- /dev/null +++ b/tex/context/base/mkxl/node-ser.lmt @@ -0,0 +1,285 @@ +if not modules then modules = { } end modules ['node-ser'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring +local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize +local formatters, format, rep = string.formatters, string.format, string.rep + +local allocate = utilities.storage.allocate + +local context = context +local nodes = nodes +local node = node + +local getfields = node.fields + +local traverse = nodes.traverse +local is_node = nodes.is_node + +local nodecodes = nodes.nodecodes +local subtypes = nodes.subtypes + +local tonode = nodes.tonode +local tonut = nodes.tonut + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist + +local f_char = formatters["%U"] +local f_attr = formatters[""] +local f_recurse = formatters[""] + +-- flat : don't use next, but indexes +-- verbose : also add type + +local canbezero = { + integer = true, + dimension = true, + number = true, +} + +local canbelist = { + attribute = "", + node = "", + token = "", + attribute_list = "", + node_list = "", + token_list = "", +} + +local canbeignored = { + prev = "" +} + +local canbechar = { + char = true, + small_char = true, + large_char = true, +} + +local fieldtypes = table.setmetatableindex(function(t,k) + local v = getfields(k,true) or false + t[k] = v + return v +end) + +nodes.fieldtypes = fieldtypes + +local function astable(n) + n = tonode(n) + if n then + local fields = fieldtypes[n.id] + if fields then + local result = { } + for field, fieldtype in sortedhash(fields) do + local value = n[field] + if value then + if canbeignored[field] then + value = nil + elseif canbezero[fieldtype] and value == 0 then + value = nil + elseif canbelist[fieldtype] then + value = canbelist[fieldtype] + end + if value then + result[field] = value + end + end + end + local id = n.id + if id then + id = nodecodes[id] + result.id = id + local subtype = n.subtype + if subtype then + local subtypes = subtypes[id] + if subtypes then + result.subtype = subtypes[subtype] + end + end + end + return result + end + end +end + +nodes.astable = astable + +setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end) + +local function to_table(n,flat,verbose,noattributes,done) + local d = tonut(n) + if done[d] then + return f_recurse(d) + else + done[d] = true + local fields = fieldtypes[n.id] + if fields then + local result = { } + for field, fieldtype in sortedhash(fields) do + local value = n[field] + if value then + if fieldtype == "attribute_list" or fieldtype == "attribute" then + if noattributes then + result[value] = canbeignored[value] + else + result[value] = to_table(value,flat,verbose,noattributes,done) + end + elseif canbeignored[field] then + result[value] = canbeignored[value] + elseif not verbose and canbezero[fieldtype] and value == 0 then + value = nil + elseif canbelist[fieldtype] then + if flat then + result[value] = canbelist[value] + else + result[value] = to_table(value,flat,verbose,noattributes,done) + end + end + if value then + result[field] = value + end + end + end + if verbose then + local id = result.id + if id then + id = nodecodes[id] + result.id = id + local subtype = result.subtype + if subtype then + local subtypes = subtypes[id] + if subtypes then + result.subtype = subtypes[subtype] + end + end + end + for k, v in next, canbechar do + local v = result[k] + if v then + result[k] = f_char(v) + end + end + end + return result + end + end +end + +local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true + if n then + local d = { } + if flat then + local t, tn = { }, 0 + while n do + tn = tn + 1 + local nt = to_table(n,flat,verbose,noattributes,d) + t[tn] = nt + nt.next = nil + nt.prev = nil + n = n.next + end + done = nil + return t + else + local t = to_table(n,flat,verbose,noattributes,d) + local n = n.next + if n then + t.next = totable(n,flat,verbose,noattributes,d) + end + return t + end + else + return { } + end +end + +nodes.totable = function(n,...) return totable(tonode(n),...) end +nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list + +local function key(k) + return ((type(k) == "number") and "["..k.."]") or k +end + +function nodes.serialize(root,flat,verbose,noattributes,name) + return serialize(totable(tonode(root),flat,verbose,noattributes),name) +end + +function nodes.serializebox(n,flat,verbose,noattributes,name) + return serialize(totable(tex.box[n],flat,verbose,noattributes),name) +end + +function nodes.visualizebox(n,flat,verbose,noattributes,name) + context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name) +end + +function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway + head = tonode(head) + if not n then + context.starttyping(true) + end + while head do + local id = head.id + context(rep(" ",n or 0) .. tostring(head) .. "\n") + if id == hlist_code or id == vlist_code then + nodes.list(head.list,(n or 0)+1) + end + head = head.next + end + if not n then + context.stoptyping(true) + end +end + +function nodes.print(head,n) + head = tonode(head) + while head do + local id = head.id + logs.writer(string.formatters["%w%S"],n or 0,head) + if id == hlist_code or id == vlist_code then + nodes.print(head.list,(n or 0)+1) + end + head = head.next + end +end + +-- quick hack, nicer is to have a proper expand per node type already prepared + +local function apply(n,action) + while n do + action(n) + local id = n.id + if id == hlist_code or id == vlist_code then + apply(n.list,action) + end + n = n.next + end +end + +nodes.apply = apply + +local nuts = nodes.nuts +local getid = nuts.getid +local getlist = nuts.getlist +local getnext = nuts.getnext + +local function apply(n,action) + while n do + action(n) + local id = getid(n) + if id == hlist_code or id == vlist_code then + local list = getlist(n,action) + if list then + apply(list,action) + end + end + n = getnext(n) + end +end + +nuts.apply = apply diff --git a/tex/context/base/mkxl/node-snp.lmt b/tex/context/base/mkxl/node-snp.lmt new file mode 100644 index 000000000..8c0237a5c --- /dev/null +++ b/tex/context/base/mkxl/node-snp.lmt @@ -0,0 +1,69 @@ +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 status = status + +local nodeusage = nodes.pool and nodes.pool.usage +local nodestock = nodes.pool and nodes.pool.stock +local clock = os.gettimeofday or os.clock -- should go in environment +local lasttime = clock() +local samples = { } + +function snapshots.takesample(comment) + if nodeusage then + local c = clock() + samples[#samples+1] = { + nodes = nodeusage(), + stock = nodestock(), + texcallbacks = status.getcallbackstate(), + mpcallbacks = mplib.getcallbackstate(), + backendcallbacks = backends.getcallbackstate(), + luavariables = status.getluastate(), + texvariables = status.gettexstate(), + comment = comment, + variables = { + lasttime = c, + elapsed = c - lasttime, + }, + memories = { + pool = status.getpoolstate(), + hash = status.gethashstate(), + lookup = status.getlookupstate(), + node = status.getnodestate(), + token = status.gettokenstate(), + buffer = status.getbufferstate(), + input = status.getinputstate(), + file = status.getfilestate(), + nest = status.getneststate(), + parameter = status.getparameterstate(), + save = status.getsavestate(), + expand = status.getexpandstate(), + read = status.getreadstate(), + font = status.getfontstate(), + language = status.getlanguagestate(), + mark = status.getmarkstate(), + sparse = status.getsparsestate(), + }, + } + end +end + +function snapshots.getsamples() + return samples -- one return value ! +end + +function snapshots.resetsamples() + samples = { } +end diff --git a/tex/context/base/mkxl/node-tex.lmt b/tex/context/base/mkxl/node-tex.lmt new file mode 100644 index 000000000..aae084740 --- /dev/null +++ b/tex/context/base/mkxl/node-tex.lmt @@ -0,0 +1,39 @@ +if not modules then modules = { } end modules ['node-tex'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +builders = builders or { } +local kernel = builders.kernel or { } +builders.kernel = kernel + +local nuts = nodes.nuts + +local hyphenate = language.hyphenate + +local hyphenating = nuts.hyphenating +local ligaturing = nuts.ligaturing +local kerning = nuts.kerning + +function kernel.hyphenation(head) + return (hyphenate(head)) -- nodes ! +end + +function kernel.hyphenating(head) + return (hyphenating(head)) +end + +function kernel.ligaturing(head) + return (ligaturing(head)) +end + +function kernel.kerning(head) + return (kerning(head)) +end + +callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") +callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere") +callbacks.register('kerning' , false, "normal kerning routine, called elsewhere") diff --git a/tex/context/base/mkxl/norm-ctx.mkxl b/tex/context/base/mkxl/norm-ctx.mkxl new file mode 100644 index 000000000..5cee04935 --- /dev/null +++ b/tex/context/base/mkxl/norm-ctx.mkxl @@ -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: + +\aliased\let\ordordspacing \Umathordordspacing +\aliased\let\ordopspacing \Umathordopspacing +\aliased\let\ordbinspacing \Umathordbinspacing +\aliased\let\ordrelspacing \Umathordrelspacing +\aliased\let\ordopenspacing \Umathordopenspacing +\aliased\let\ordclosespacing \Umathordclosespacing +\aliased\let\ordpunctspacing \Umathordpunctspacing +\aliased\let\ordinnerspacing \Umathordinnerspacing +\aliased\let\opordspacing \Umathopordspacing +\aliased\let\opopspacing \Umathopopspacing +\aliased\let\opbinspacing \Umathopbinspacing +\aliased\let\oprelspacing \Umathoprelspacing +\aliased\let\opopenspacing \Umathopopenspacing +\aliased\let\opclosespacing \Umathopclosespacing +\aliased\let\oppunctspacing \Umathoppunctspacing +\aliased\let\opinnerspacing \Umathopinnerspacing +\aliased\let\binordspacing \Umathbinordspacing +\aliased\let\binopspacing \Umathbinopspacing +\aliased\let\binbinspacing \Umathbinbinspacing +\aliased\let\binrelspacing \Umathbinrelspacing +\aliased\let\binopenspacing \Umathbinopenspacing +\aliased\let\binclosespacing \Umathbinclosespacing +\aliased\let\binpunctspacing \Umathbinpunctspacing +\aliased\let\bininnerspacing \Umathbininnerspacing +\aliased\let\relordspacing \Umathrelordspacing +\aliased\let\relopspacing \Umathrelopspacing +\aliased\let\relbinspacing \Umathrelbinspacing +\aliased\let\relrelspacing \Umathrelrelspacing +\aliased\let\relopenspacing \Umathrelopenspacing +\aliased\let\relclosespacing \Umathrelclosespacing +\aliased\let\relpunctspacing \Umathrelpunctspacing +\aliased\let\relinnerspacing \Umathrelinnerspacing +\aliased\let\openordspacing \Umathopenordspacing +\aliased\let\openopspacing \Umathopenopspacing +\aliased\let\openbinspacing \Umathopenbinspacing +\aliased\let\openrelspacing \Umathopenrelspacing +\aliased\let\openopenspacing \Umathopenopenspacing +\aliased\let\openclosespacing \Umathopenclosespacing +\aliased\let\openpunctspacing \Umathopenpunctspacing +\aliased\let\openinnerspacing \Umathopeninnerspacing +\aliased\let\closeordspacing \Umathcloseordspacing +\aliased\let\closeopspacing \Umathcloseopspacing +\aliased\let\closebinspacing \Umathclosebinspacing +\aliased\let\closerelspacing \Umathcloserelspacing +\aliased\let\closeopenspacing \Umathcloseopenspacing +\aliased\let\closeclosespacing\Umathcloseclosespacing +\aliased\let\closepunctspacing\Umathclosepunctspacing +\aliased\let\closeinnerspacing\Umathcloseinnerspacing +\aliased\let\punctordspacing \Umathpunctordspacing +\aliased\let\punctopspacing \Umathpunctopspacing +\aliased\let\punctbinspacing \Umathpunctbinspacing +\aliased\let\punctrelspacing \Umathpunctrelspacing +\aliased\let\punctopenspacing \Umathpunctopenspacing +\aliased\let\punctclosespacing\Umathpunctclosespacing +\aliased\let\punctpunctspacing\Umathpunctpunctspacing +\aliased\let\punctinnerspacing\Umathpunctinnerspacing +\aliased\let\innerordspacing \Umathinnerordspacing +\aliased\let\inneropspacing \Umathinneropspacing +\aliased\let\innerbinspacing \Umathinnerbinspacing +\aliased\let\innerrelspacing \Umathinnerrelspacing +\aliased\let\inneropenspacing \Umathinneropenspacing +\aliased\let\innerclosespacing\Umathinnerclosespacing +\aliased\let\innerpunctspacing\Umathinnerpunctspacing +\aliased\let\innerinnerspacing\Umathinnerinnerspacing + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-bar.mkxl b/tex/context/base/mkxl/pack-bar.mkxl new file mode 100644 index 000000000..c6a111531 --- /dev/null +++ b/tex/context/base/mkxl/pack-bar.mkxl @@ -0,0 +1,94 @@ +%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 experimental code). +%D It could be in scrn-bar but it's static. In the meantime the interface has been +%D 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} \??positionbar + +\setuppositionbar + [\c!min=\plusone, + \c!max=\plusone, + \c!n=\plusone + \c!text=?, + \c!width=\emwidth, + \c!height=\strutheight, + \c!depth=\strutdepth] + +\permanent\protected\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}} + +\permanent\protected\def\verticalpositionbar[#1]% + {\vbox to \vsize + {\hsize\positionbarparameter\c!width + \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}} + +\permanent\protected\def\horizontalgrowingbar[#1]% + {\hpack to \hsize + {\setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \vrule\s!width\zeropoint\s!height\positionbarparameter\c!height\s!depth\positionbarparameter\c!depth + \leaders\vrule\hskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill + \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} + +\permanent\protected\def\verticalgrowingbar[#1]% + {\vpack to \vsize + {\hsize\positionbarparameter\c!width + \setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \hrule\s!width\positionbarparameter\c!width\s!height\zeropoint\s!depth\zeropoint + \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill + \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-bck.mklx b/tex/context/base/mkxl/pack-bck.mklx new file mode 100644 index 000000000..3c15beb5f --- /dev/null +++ b/tex/context/base/mkxl/pack-bck.mklx @@ -0,0 +1,245 @@ +%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 backgrounds. As it is +%D still used WS adapted the code to the new command handler methods so that it gets +%D a second life. So 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 means that texts is +%D to be collected and split over pages. To show what can be done, we provide this +%D part of the documentation with some gray background and a red frame. Both the +%D background and frame can have all characteristics 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. The main problem with +%D this kind of functionality is to get 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 be used +%D 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 + \frozen\setuevalue{\e!start\currentbackground}{\pack_backgrounds_start [\currentbackground]}% + \frozen\setuevalue{\e!stop \currentbackground}{\pack_backgrounds_stop }% + \frozen\setuevalue {\currentbackground}{\pack_backgrounds_direct[\currentbackground]}% +\to \everydefinebackground + +\protected\def\pack_backgrounds_start[#tag]% + {\endgraf + \begingroup + \def\currentbackground{#tag}% + \doifelse{\backgroundparameter\c!state}\v!start + \pack_backgrounds_start_indeed + \pack_backgrounds_start_ignore} + +\tolerant\def\pack_backgrounds_start_indeed[#settings]% + {\setupcurrentbackground[#settings,\c!state=\v!start,\c!offset=\v!overlay]% + \let\pack_backgrounds_stop\pack_backgrounds_stop_indeed + \setbox\scratchboxone\vbox\bgroup + \strut + \vskip-2\lineheight + \strut + \blank[\v!disable] + \leftskip \backgroundparameter\c!leftoffset + \rightskip\backgroundparameter\c!rightoffset} + +\tolerant\def\pack_backgrounds_start_ignore[#settings]% + {\let\pack_backgrounds_stop\pack_backgrounds_stop_ignore} + +\let\pack_backgrounds_stop\relax + +\protected\def\pack_backgrounds_stop_indeed % we shoul duse the fast background variant of framed + {\endgraf + \removelastskip + \strut + \vskip-2\lineheight + \strut + % safeguard added + \ifdim\dimexpr\pagetotal+2\lineheight\relax>\pagegoal + \page + \fi + % till here + \egroup + \scratchdistance\leftskip % new ** + \forgetall + \ifinsidefloat + \backgroundsplitmode\zerocount + \fi + \ifcase\backgroundsplitmode + \inheritedbackgroundframed{\box\scratchboxone}% + \or + \hskip\scratchdistance + \inheritedbackgroundframed{\box\scratchboxone}% + \else + \splitmaxdepth\boxmaxdepth + \splittopskip\topskip + \doloop + {\ifzeropt\pagetotal % empty page + \scratchdimen\textheight + \backgroundsplitmode\plusone % split to max height + \else + \setbox\scratchdimentwo\vbox{\backgroundparameter\c!before}% + \scratchdimen\dimexpr\pagegoal-\ht\scratchdimentwo-\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\ht\scratchboxone>\scratchdimen % larger than page + \setbox\scratchdimentwo\vsplit\scratchboxone to \scratchdimen + \else + \setbox\scratchdimentwo\box\scratchboxone + \backgroundsplitmode\zerocount % no split + \fi + \setbox\scratchdimentwo\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split + {\vskip\backgroundparameter\c!topoffset + \unvcopy\scratchdimentwo + \prevdepth\dp\scratchdimentwo + \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\scratchdistance % new ** + \fi + \inheritedbackgroundframed{\box\scratchdimentwo}% + \stoplinecorrection + \ifcase\backgroundsplitmode % no split + \backgroundparameter\c!after + \else % some split + \page_otr_fill_and_eject_page % no \page ! + \fi + \else + \page + \fi + \ifdim\ht\scratchboxone>\zeropoint \else + \exitloop + \fi}% + \fi + \endgroup + \endgraf} + +\protected\def\pack_backgrounds_stop_ignore + {\endgroup + \endgraf} + +\protected\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 + \permanent\expandafter\let\expandafter\startbackground\csname\e!start\v!background\endcsname + \permanent\expandafter\let\expandafter\stopbackground \csname\e!stop \v!background\endcsname + \permanent\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 + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-box.mkxl b/tex/context/base/mkxl/pack-box.mkxl new file mode 100644 index 000000000..7221f7a5f --- /dev/null +++ b/tex/context/base/mkxl/pack-box.mkxl @@ -0,0 +1,1114 @@ +%D \module +%D [ file=pack-box, +%D version=2002.04.12, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Boxes, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Boxes} + +%D This module contains all kind of macros for moving content around. Many +%D macros here come from other modules, but depencies made it more clear +%D to isolate them. We invite users to document the macros. They can be +%D handy shortcuts for otherwise complex tasks. + +\unprotect + +%D We need to set the size, else we get dimensions depending on the content, +%D which in itself is ok, but can lead to loops due to rounding errors (happened +%D in demo-obv). + +% \definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] + +\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] + +\permanent\protected\def\internaltextoverlay#1% will become more generic and installable + {\startoverlay % i.e. probably an overlay by itself + {\positionregionoverlay\textanchor{\v!text#1}}% see later + {\composedlayer {\v!text#1}}% + \stopoverlay} + +\defineoverlay[\v!text-2][\internaltextoverlay{-2}] +\defineoverlay[\v!text-1][\internaltextoverlay{-1}] +\defineoverlay[\v!text+1][\internaltextoverlay{+1}] +\defineoverlay[\v!text+2][\internaltextoverlay{+2}] + +\installcorenamespace {anchor} + +% produces a box too +% +% \anchor[text-1][preset=lefttop][framed settings]{HELLO WORLD} + +\permanent\tolerant\protected\def\defineanchor[#1]#*[#2]#*[#3]#*[#4]% name targetlayer layersetting framedsetting + {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}} + +\def\pack_anchors_process_defined#1#2#3% + {\tolerant\def\pack_anchors_process_defined_indeed[##1]##*[##2]% + {\ifarguments + \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}% + \or + \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}% + \or + \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}% + \fi + \next}% picks up a box + \pack_anchors_process_defined_indeed} + +\permanent\protected\def\anchor[#1]% + {\begingroup + \edef\currentanchor{#1}% + \ifcsname\??anchor\currentanchor\endcsname + \expandafter\lastnamedcs + \else + \expandafter\pack_anchor_notdefined + \fi} + +\tolerant\def\pack_anchor_notdefined[#1]#*[#2]% + {\ifarguments + \expandafter\gobbletwoarguments + \or + \expandafter\pack_anchor_notdefined_one + \else + \expandafter\pack_anchor_notdefined_two + \fi{#1}{#2}} + +\def\pack_anchor_notdefined_one #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#1}}\vbox} +\def\pack_anchor_notdefined_two #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#2}}\vbox} +\def\pack_anchors_process_indeed#1#2#3{\dowithnextbox{\pack_anchors_process_finish {#1}{#2}{#3}}\vbox} + +\newbox \b_pack_anchors +\newdimen\d_pack_anchors_width +\newdimen\d_pack_anchors_height +\newdimen\d_pack_anchors_depth + +% \definelayer[anchor] + +\newcount\c_pack_anchors_n +\newtoks \t_pack_anchors_flush + +\protected\def\pack_anchors_register#1#2% + {\global\advance\c_pack_anchors_n\plusone + \pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]% + \putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors +% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}% + \doglobal\appendetoks + \pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}% + \to \t_pack_anchors_flush + \glet\pack_anchors_flush_all\pack_anchors_flush_all_indeed} + +\protected\def\pack_anchors_flush#1#2#3% + {\doifelseboxincache\v!anchor{#1} + {\doifelsereferencefound{\v!layer:\v!anchor:#1} + {\ifnum\currentreferencerealpage=\realpageno\relax + \setlayer[#2][#3,\c!position=\v!no]{\directboxfromcache\v!anchor{#1}}% + \else + \donetrue + \fi + }\donetrue}% + \donetrue}% + +\protected\def\pack_anchors_flush_all_indeed + {\donefalse + \the\t_pack_anchors_flush + \ifdone\else + \global\t_pack_anchors_flush\emptytoks + \glet\pack_anchors_flush_all\relax + \fi} + +\let\pack_anchors_flush_all\relax + +\appendtoks + \pack_anchors_flush_all +\to \everybeforepagebody + +\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy + {\checkpositionoverlays + \setbox\b_pack_anchors\box\nextbox + \framed % could be a predefined framed but used seldom + [\c!offset=\v!overlay,\c!frame=\v!off,#3] + {\pack_anchors_register{#1}{#2}% + \novrule % hm, not needed as we frame the size (but kind of default) + \s!width \wd\b_pack_anchors + \s!height\ht\b_pack_anchors + \s!depth \dp\b_pack_anchors}% + \endgroup} + +% \setlayeranchored[text-1][preset=lefttop]{HELLO WORLD} produces a simple (empty) hbox +% synchronizes per page + +\permanent\tolerant\protected\def\setlayeranchored[#1]#*[#2]% + {\begingroup + \ifarguments + \dowithnextbox + {\endgroup}% + \else + \dowithnextbox + {\checkpositionoverlays + \setbox\b_pack_anchors\box\nextbox + \dontleavehmode\hpack{\pack_anchors_register{#1}{#2}}% + \endgroup}% + \fi + \hbox} + +% collectors + +\installcorenamespace{collectorbox} +\installcorenamespace{collector} + +\installcommandhandler \??collector {collector} \??collector + +\setupcollector + [\c!state=\v!start, + \c!x=\zeropoint, + \c!y=\zeropoint, + \c!offset=\zeropoint, + \c!rotation=, % geen 0 ! + \c!hoffset=\zeropoint, + \c!voffset=\zeropoint, + \c!location=rb, + \c!corner=] + +\appendtoks + \ifcsname\??collectorbox\currentcollector\endcsname \else + \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname + \fi +\to \everydefinecollector + +\permanent\protected\def\resetcollector[#1]% + {\ifcsname\??collectorbox#1\endcsname + \global\setbox\lastnamedcs\emptybox + \fi} + +\newconditional\c_pack_boxes_collector_valid_box + +\let\b_pack_boxes_collector\scratchbox + +\def\pack_boxes_collector_check_box#1% + {\edef\currentcollector{#1}% + \ifcsname\??collectorbox\currentcollector\endcsname + \settrue\c_pack_boxes_collector_valid_box + \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs + \else + \setfalse\c_pack_boxes_collector_valid_box + \writestatus{collector}{unknown collector \currentcollector}% + \fi} + +\permanent\tolerant\protected\def\setcollector[#1]#*[#2]% todo: keep reference point + {\bgroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \setupcurrentcollector[#2]% + \expandafter\pack_boxes_collector_yes + \else + \expandafter\pack_boxes_collector_nop + \fi} + +\def\pack_boxes_collector_yes + {\forgetall + \dontcomplain + \dowithnextboxcs\pack_boxes_collector_finish\hbox} + +\let\pack_boxes_collector_nop\egroup + +\installcorenamespace{collectorcorners} + +\setvalue{\??collectorcorners\v!middle}% + {\ifdim\d_pack_layers_x_size>\zeropoint + \advance\d_pack_layers_x_position.5\d_pack_layers_x_size + \fi + \ifdim\d_pack_layers_y_size>\zeropoint + \advance\d_pack_layers_y_position.5\d_pack_layers_y_size + \fi} + +\setvalue{\??collectorcorners\v!bottom}% + {\ifdim\d_pack_layers_y_size>\zeropoint + \advance\d_pack_layers_y_position-\d_pack_layers_y_size + \d_pack_layers_y_position-\d_pack_layers_y_position + \fi} + +\setvalue{\??collectorcorners\v!right}% + {\ifdim\d_pack_layers_x_size>\zeropoint + \advance\d_pack_layers_x_position-\d_pack_layers_x_size + \d_pack_layers_x_position-\d_pack_layers_x_position + \fi} + +\def\pack_boxes_collector_check_corner#1% + {\ifcsname\??collectorcorners#1\endcsname + \lastnamedcs + \fi} + +\def\pack_boxes_collector_finish + {\edef\p_collector_rotation{\collectorparameter\c!rotation}% + \edef\p_collector_corner {\collectorparameter\c!corner}% + \ifempty\p_collector_rotation \else + \setbox\nextbox\hpack + {\rotate + [\c!location=\v!high, + \c!rotation=\p_collector_rotation] + {\box\nextbox}}% + \fi + \d_pack_layers_x_size\wd\b_pack_boxes_collector + \d_pack_layers_y_size\htdp\b_pack_boxes_collector + \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax + \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax + \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner + \setbox\nextbox\hpack + {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}% + \boxmaxdepth\zeropoint % really needed, nice example + \global\advance\boxhdisplacement\d_pack_layers_x_position + \ifdim\boxhdisplacement<\zeropoint + \global\setbox\b_pack_boxes_collector\hpack + {\kern-\boxhdisplacement + \box\b_pack_boxes_collector}% + \fi + \global\advance\boxvdisplacement\d_pack_layers_y_position + \ifdim\boxvdisplacement<\zeropoint + \global\setbox\b_pack_boxes_collector\hpack + {\lower-\boxvdisplacement + \box\b_pack_boxes_collector}% + \fi + \d_pack_layers_x_size\wd\b_pack_boxes_collector + \d_pack_layers_y_size\htdp\b_pack_boxes_collector + \global\setbox\b_pack_boxes_collector\hpack + {\box\b_pack_boxes_collector + \kern\dimexpr + -\d_pack_layers_x_size + +\d_pack_layers_x_position + \ifdim\boxhdisplacement<\zeropoint + -\boxhdisplacement + \fi + \relax + \lower\d_pack_layers_y_position\hpack + {\ifdim\boxvdisplacement<\zeropoint + \lower-\boxvdisplacement + \fi + \box\nextbox}}% + % combine height and depth into depth only (later flushed as height) + \global\setbox\b_pack_boxes_collector\hpack + {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}% + % just to be sure + \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size + \wd\b_pack_boxes_collector\d_pack_layers_x_size + \fi + \egroup} + +\permanent\protected\def\flushcollector[#1]% + {\bgroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \edef\p_collector_state{\collectorparameter\c!state}% + \ifx\p_collector_state\v!stop \else + \vpack{\hpack{\raise + \dp\b_pack_boxes_collector + \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}% + \fi + \fi + \egroup} + +\permanent\protected\def\composedcollector#1% no [], handy as argument + {\flushcollector[#1]} + +\permanent\tolerant\protected\def\adaptcollector[#1]#*[#2]% % a typical case where \global\wd looks better in the code + {\begingroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \letcollectorparameter\c!voffset\zeropoint + \letcollectorparameter\h!voffset\zeropoint + \setupcurrentcollector[#2]% + \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax + \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax + \fi + \endgroup} + +%\definecollector[test] +%\setcollector[test] +% [location=rb] +% {\externalfigure[koe][frame=on,width=3cm]} +%\setcollector[test] +% [corner={right,bottom},location={left,top}] +% {\framed{gans}} +%\composedcollector{test} + +\definecollector + [caption] + +\permanent\tolerant\protected\def\collectedtext[#1]#*[#2]% for captions + {\pack_boxes_collector_text[#1][#2]} + +\def\pack_boxes_collector_text[#1][#2]#3% #3 is mandate so no tolerant here, so still two step + {\bgroup + \dowithnextbox + {\setcollector + [caption] + {\box\nextbox}% + \setcollector + [caption][#1]% + {\letdummyparameter\c!style\empty + \letdummyparameter\c!color\empty + \getdummyparameters[#2]% + \dousestyleparameter{\directdummyparameter\c!style}% + \setupinterlinespace + \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}% + \composedcollector{caption}% + \egroup}% + \hbox} + +% \collectedtext +% [corner={right,bottom},location={left,top}] +% [background=color,backgroundcolor=white,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \collectedtext +% [rotation=90,corner={right,bottom},location={right,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \collectedtext +% [rotation=90,corner={left,bottom},location={left,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} + +\installcorenamespace {layeredtext} +\installcorenamespace {layeredtextlayer} +\installcorenamespace {layeredtextframed} + +\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext + +\newdimen\d_pack_layeredtexts_width +\newdimen\d_pack_layeredtexts_height + +\definelayer % private + [\??layeredtextlayer] + +\setuplayer % private + [\??layeredtextlayer] + [\c!width=\d_pack_layeredtexts_width, + \c!height=\d_pack_layeredtexts_height] + +\defineframed % private + [\??layeredtextframed] + [\c!offset=\v!overlay, + \c!frame=\v!off, + \c!background={\v!foreground,\??layeredtextlayer}, + \c!width=\d_pack_layeredtexts_width, + \c!height=\d_pack_layeredtexts_height] + +\setuplayeredtext % public (the attached data, usually small stuff, not the main thing) + [\c!frame=\v!overlay, + \c!color=, + \c!style=, + \c!foregroundcolor=\layeredtextparameter\c!color, + \c!foregroundstyle=\layeredtextparameter\c!style] + +\permanent\tolerant\protected\def\placelayeredtext[#1]#*[#2]#*[#3]#4% tag layersettings content(framed)settings content + {\bgroup + \edef\currentlayeredtext{#1}% + \checklayeredtextparent % bonus + \setupcurrentlayeredtext[#3]% + \dowithnextbox + {\d_pack_layeredtexts_width \wd\nextbox + \d_pack_layeredtexts_height\ht\nextbox + \begingroup % preserve \nextbox + \setlayer + [\??layeredtextlayer]% + [#2]% + {\setfalse\fontattributeisset + \uselayeredtextstyleparameter\c!style + \ifconditional\fontattributeisset + \setupinterlinespace + \fi + \inheritedlayeredtextframed{#4}}% + \endgroup + \placeframed[\??layeredtextframed]{\flushnextbox}% + \egroup}% + \hbox} + +\permanent\protected\def\layeredtext + {\placelayeredtext[]} + +% \layeredtext +% [corner={right,bottom},location={left,top}] +% [background=color,backgroundcolor=white,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \layeredtext +% [rotation=90,corner={right,bottom},location={right,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \layeredtext +% [rotation=90,corner={left,bottom},location={left,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} + +\permanent\tolerant\protected\def\ornamenttext[#1]#*[#2]% takes another argument + {\bgroup + \doifelseassignment{#1} + {\letdummyparameter\c!alternative\v!a + \getdummyparameters[#1]% + \doifelse{\directdummyparameter\c!alternative}\v!a + {\egroup\collectedtext}% + {\egroup\layeredtext }% + [#1][#2]}% + {\egroup\getvalue{#1}}} + +\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]% + {\setuvalue{#1}{\pack_ornament_text[#2][#3]}} + +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={right,top}, +% hoffset=-.25ex] +% [frame=on,background=color,backgroundcolor=red,offset=0pt] +% +% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={right,top}, +% hoffset=-.25ex,alternative=b] +% [frame=on,background=color,backgroundcolor=red,offset=0pt] +% +% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={left,top}, +% hoffset=.25ex,voffset=.25ex,alternative=a] +% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] +% +% \affiliation{photo}{\externalfigure[molen][width=3cm]} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={left,top}, +% hoffset=.25ex,voffset=.25ex,alternative=b] +% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] +% +% \affiliation{drawing}{\externalfigure[hakker][width=3cm]} + +\newcount\c_pack_boxes_bleeds + +\installcorenamespace {bleeding} + +\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding + +\setupbleeding + [\c!location=l, + \c!stretch=\v!yes, + \c!width=3cm, + \c!height=3cm, + \c!offset=2mm, + \c!page=\v!no, + \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset + \c!hoffset=\scratchoffset] % which often saves one resolve + +\permanent\def\bleedwidth {\the\hsize} % these are global ! +\permanent\def\bleedheight{\the\vsize} % these are global ! + +\newconditional\c_pack_boxes_l +\newconditional\c_pack_boxes_r +\newconditional\c_pack_boxes_t +\newconditional\c_pack_boxes_b + +\installcorenamespace{bleedinglocation} + +\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint} +\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint} +\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint} +\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint} +\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} + +\permanent\tolerant\protected\def\bleed[#1]% + {\hbox\bgroup + \global\advance\c_pack_boxes_bleeds\plusone + % + \enforced\permanent\xdef\bleedwidth {\the\hsize}% + \enforced\permanent\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 + % + \enforced\permanent\xdef\bleedwidth{\the\dimexpr + \ifdone + \ifconditional\c_pack_boxes_l + \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition + \orelse\ifconditional\c_pack_boxes_r + \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked + \else + \scratchwidth + \fi + \else + \scratchwidth + \fi+\scratchhoffset + \relax}% + \enforced\permanent\xdef\bleedheight{\the\dimexpr + \ifdone + \ifconditional\c_pack_boxes_t + \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked + \orelse\ifconditional\c_pack_boxes_b + \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition + \MPh\currentbgposition % not checked (\MPh added) + \else + \scratchheight + \fi + \else + \scratchheight + \fi+\scratchvoffset + \relax}% + \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox} + +\def\pack_boxes_bleed_settings + {\hsize\bleedwidth + \vsize\bleedheight} + +\def\pack_boxes_bleed_finish + {\doif{\bleedingparameter\c!page}\v!yes + {\setbox\nextbox\topskippedbox{\box\nextbox}}% + \setbox\nextbox\hpack to \scratchwidth + {\ifconditional\c_pack_boxes_l\hss\fi + \box\nextbox + \ifconditional\c_pack_boxes_r\hss\fi}% + \ifconditional\c_pack_boxes_b + \setbox\nextbox\hpack + {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}% + \fi + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\zeropoint + \ifdone + \hpos\currentbgposition{\box\nextbox}% + \else + \box\nextbox + \fi + \egroup} + +\defineexternalfigure + [bleed] % should be \v!bleed + [\c!width=\bleedwidth, + \c!height=\bleedheight] + +% \placefigure[left]{none} +% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure[left]{none} +% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure[right]{none} +% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure +% [top,none] +% {} % no caption +% {\bleed +% [hoffset=-\backspace, +% voffset=3mm, +% width=0cm, +% height=6\lineheight, +% page=yes, % correct for topskip +% location=lt] +% {\externalfigure[koe][bleed][frame=on]}} + +% \setlayerframed[layer id][layer settings][framed setting]{data} +% \setlayerframed[layer id][combined settings]{data} + +% tricky: offsets apply to both the layer and the framed; it makes sense to +% only apply the offset to ... + +\permanent\tolerant\protected\def\setlayerframed[#1]#*[#2]#*[#3] + {\ifarguments + % error + \or + \expandafter\pack_layers_set_framed_s + \or + \expandafter\pack_layers_set_framed_d + \or + \expandafter\pack_layers_set_framed_t + \fi[#1][#2][#3]} + +\def\pack_layers_set_framed_s[#1][#2][#3]% + {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]% + \normalframedwithsettings[\c!location=\v!normal]} % different kind of location + +\def\pack_layers_set_framed_d[#1][#2][#3]% + {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]% + \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location + +\def\pack_layers_set_framed_t[#1][#2][#3]% + {\setlayer[#1][#2]% + \normalframedwithsettings[#3]} + +\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#3]% + {\bgroup + \letdummyparameter\c!align\empty + \letdummyparameter\c!width\hsize + \letdummyparameter\c!color\empty + \letdummyparameter\c!style\empty + \getdummyparameters[#3]% + \dowithnextboxcontent + {\forgetall + \hsize\directdummyparameter\c!width + \usealignparameter\directdummyparameter + \dousestyleparameter{\directdummyparameter\c!style}} + {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color + \egroup}% + \vtop} + +% \setupbackgrounds +% [page] +% [background=pagefigures] +% +% \definelayer +% [pagefigures] +% [x=-2mm, +% y=-2mm, +% width=\paperwidth, +% height=\paperheight] +% +% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}] +% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}] +% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}] +% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}] +% \definelayerpreset [middle] [corner=middle,location=middle] +% +% \setlayer[pagefigures][preset=lefttop] +% \setlayer[pagefigures][preset=righttop] +% \setlayer[pagefigures][preset=leftbottom] +% \setlayer[pagefigures][preset=rightbottom] + +\definelayerpreset + [\v!left\v!top] + [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}] + +\definelayerpreset + [\v!right\v!top] + [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}] + +\definelayerpreset + [\v!left\v!bottom] + [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}] + +\definelayerpreset + [\v!right\v!bottom] + [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}] + +\definelayerpreset + [\v!middle] + [\c!corner=\v!middle,\c!location=\v!middle] + +\definelayerpreset + [\v!middle\v!top] + [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth] + +\definelayerpreset + [\v!middle\v!bottom] + [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth] + +\definelayerpreset + [\v!middle\v!left] + [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight] + +\definelayerpreset + [\v!middle\v!right] + [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight] + +% left and right hanging: + +\definelayerpreset + [\v!left\v!top\v!left] + [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}] + +\definelayerpreset + [\v!right\v!top\v!right] + [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}] + +\installcorenamespace{alignedboxes} + +\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish} +\permanent\tolerant\protected\def\aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox} + +\def\pack_boxes_aligned_finish + {\ifcsname\??alignedboxes\serializedcommalist\endcsname + \expandafter\lastnamedcs + \else + \expandafter\middlebox + \fi{\flushnextbox}% + \egroup} + +\letvalue{\??alignedboxes }\middlebox +\letvalue{\??alignedboxes\v!middle }\middlebox +\letvalue{\??alignedboxes\v!middle\v!middle}\middlebox +\letvalue{\??alignedboxes\v!left }\leftbox +\letvalue{\??alignedboxes\v!left \v!top }\lefttopbox +\letvalue{\??alignedboxes\v!left \v!bottom}\leftbottombox +\letvalue{\??alignedboxes\v!right }\rightbox +\letvalue{\??alignedboxes\v!right \v!top }\righttopbox +\letvalue{\??alignedboxes\v!right \v!bottom}\rightbottombox +\letvalue{\??alignedboxes\v!bottom }\bottombox +\letvalue{\??alignedboxes\v!bottom\v!left }\bottomleftbox +\letvalue{\??alignedboxes\v!bottom\v!right }\bottomrightbox +\letvalue{\??alignedboxes\v!top }\topbox +\letvalue{\??alignedboxes\v!top \v!left }\topleftbox +\letvalue{\??alignedboxes\v!top \v!right }\toprightbox +\letvalue{\??alignedboxes\v!line }\baselinemiddlebox % \v!grid is taken +\letvalue{\??alignedboxes\v!line \v!left }\baselineleftbox +\letvalue{\??alignedboxes\v!line \v!middle}\baselinemiddlebox +\letvalue{\??alignedboxes\v!line \v!right }\baselinerightbox +\letvalue{\??alignedboxes c}\middlebox +\letvalue{\??alignedboxes l}\leftbox +\letvalue{\??alignedboxes r}\rightbox +\letvalue{\??alignedboxes b}\bottombox +\letvalue{\??alignedboxes t}\topbox +\letvalue{\??alignedboxes lt}\lefttopbox +\letvalue{\??alignedboxes lb}\leftbottombox +\letvalue{\??alignedboxes rt}\righttopbox +\letvalue{\??alignedboxes rb}\rightbottombox +\letvalue{\??alignedboxes tl}\topleftbox +\letvalue{\??alignedboxes bl}\bottomleftbox +\letvalue{\??alignedboxes tr}\toprightbox +\letvalue{\??alignedboxes br}\bottomrightbox +\letvalue{\??alignedboxes m}\middlebox +\letvalue{\??alignedboxes g}\baselinemiddlebox +\letvalue{\??alignedboxes gl}\baselineleftbox +\letvalue{\??alignedboxes gc}\baselinemiddlebox +\letvalue{\??alignedboxes gr}\baselinerightbox + +% left/right/top/bottomoffset -> dimensions change +% x/y | method=fixed -> dimensions don't change + +\installcorenamespace{offsetbox} + +\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox + +\setupoffsetbox + [\c!x=\zeropoint, + \c!y=\zeropoint, + \c!width=\wd\nextbox, + \c!height=\ht\nextbox, + \c!depth=\dp\nextbox, + \c!location=, + \c!leftoffset=\zeropoint, + \c!rightoffset=\zeropoint, + \c!topoffset=\zeropoint, + \c!bottomoffset=\zeropoint, + \c!method=] + +\aliased\let\setupoffset\setupoffsetbox + +\permanent\tolerant\protected\def\offsetbox[#1]% + {\bgroup + \pack_boxes_offset_check[#1]% + \dowithnextboxcs\pack_boxes_offsetfinish} + +\permanent\tolerant\protected\def\offset[#1]% + {\bgroup + \pack_boxes_offset_check[#1]% + \dowithnextboxcs\pack_boxes_offsetfinish\hbox} + +\newcount\c_pack_boxes_offset_level + +\def\pack_boxes_offset_check + {\advance\c_pack_boxes_offset_level\plusone + \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}% + \checkoffsetboxparent + \setupcurrentoffsetbox} + +\def\pack_boxes_offsetfinish + {\donefalse + \scratchxposition \offsetboxparameter\c!x + \scratchyposition \offsetboxparameter\c!y + \scratchleftoffset \offsetboxparameter\c!leftoffset + \scratchrightoffset \offsetboxparameter\c!rightoffset + \scratchtopoffset \offsetboxparameter\c!topoffset + \scratchbottomoffset\offsetboxparameter\c!bottomoffset + \relax % really needed + \ifzeropt\scratchleftoffset \else\donetrue\fi + \ifzeropt\scratchrightoffset \else\donetrue\fi + \ifzeropt\scratchtopoffset \else\donetrue\fi + \ifzeropt\scratchbottomoffset\else\donetrue\fi + \ifdone + \edef\p_method{\offsetboxparameter\c!method}% + \ifx\p_method\v!fixed % new + \ifzeropt\scratchleftoffset + \ifzeropt\scratchrightoffset \else + \scratchxposition-\scratchrightoffset + \scratchrightoffset\zeropoint + \fi + \else + \scratchxposition\scratchleftoffset + \scratchleftoffset\zeropoint + \fi + \ifzeropt\scratchtopoffset + \ifzeropt\scratchbottomoffset \else + \scratchyposition-\scratchbottomoffset + \scratchbottomoffset\zeropoint + \fi + \else + \scratchyposition\scratchtopoffset + \scratchtopoffset\zeropoint + \fi + \donefalse + \fi + \fi + \ifdone + \setbox\nextbox\vpack + {\forgetall % already done + \offinterlineskip + \kern\scratchtopoffset + \hpack + {\kern\scratchleftoffset + \box\nextbox + \kern\scratchrightoffset}% + \kern\scratchbottomoffset}% + \ht\nextbox\htdp\nextbox + \dp\nextbox\zeropoint + \fi + \scratchwidth \offsetboxparameter\c!width + \scratchheight\offsetboxparameter\c!height + \scratchdepth \offsetboxparameter\c!depth + \edef\p_location{\offsetboxparameter\c!location}% + \setbox\nextbox\hpack + {\kern\scratchxposition + \lower\scratchyposition\hpack + {\ifempty\p_location + \box\nextbox + \else + \alignedbox[\p_location]\hpack{\box\nextbox}% + \fi}}% + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\scratchdepth + \box\nextbox + \egroup} + +%D \starttyping +%D \framed[offset=overlay]{\offset[leftoffset=1cm] +%D {\framed[offset=overlay]{\offset[rightoffset=1cm] +%D {\externalfigure[koe][width=1cm]}}}} +%D +%D \blank +%D +%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank +%D \stoptyping + +% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid] +% +% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte + +% Some old code: +% +% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf +% +% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf +% +% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf + +\def\pack_boxes_tabbed#1#2#3#4% + {\dontleavehmode + \begingroup + \setbox\scratchbox\hpack{#3}% + \hpack to \wd\scratchbox{#1#4#2}% + \endgroup} + +\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss} +\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss \relax} +\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss \hss} + +\let\mtabbed\ctabbed + +% to be documented + +\permanent\protected\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{} + {\hpack\bgroup + \letdummyparameter\c!width \zeropoint + \letdummyparameter\c!height\zeropoint + \letdummyparameter\c!depth \zeropoint + \getdummyparameters[#1]% + \setbox\scratchbox\emptyhbox + \wd\scratchbox\directdummyparameter\c!width + \ht\scratchbox\directdummyparameter\c!height + \dp\scratchbox\directdummyparameter\c!depth + \box\scratchbox + \egroup} + +% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]} + +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} + +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} + +\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize + {\bgroup + \forgetall + \scratchcounter#1\relax + \scratchwidth #2\relax + \scratchheight #3\relax + \dowithnextboxcs\pack_boxes_background_image\hbox} + +\def\pack_boxes_background_image + {\offinterlineskip + \ifcase\scratchcounter + % just one + \else + \scratchdimen\scratchwidth \divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax + \scratchdimen\scratchheight\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax + % to be considered: methods + \ifcase\scratchcounter + \or % x and y + \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% + \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% + \or % x + \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% + \or % y + \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% + \fi + \fi + \ifdim\wd\nextbox>\scratchwidth + \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}% + \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% + \fi + \ifdim\ht\nextbox>\scratchheight + \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}% + \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% + \fi + \box\nextbox + \egroup} + +\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize + {\bgroup + \forgetall + \scratchcounter#1\relax + \scratchwidth #2\relax + \scratchheight #3\relax + \dowithnextboxcs\pack_boxes_background_image_fill\hbox} + +\def\pack_boxes_background_image_fill + {\offinterlineskip + \setbox\nextbox\hpack\bgroup + \ifdim\scratchwidth>\scratchheight + \scale[\c!width=\the\scratchwidth]{\box\nextbox}% + \else + \scale[\c!height=\the\scratchheight]{\box\nextbox}% + \fi + \egroup + \ifdim\wd\nextbox>\scratchwidth + \setbox\nextbox\hpack to \scratchwidth + {\ifcase\scratchcounter + \hss\box\nextbox\hss + \or + \box\nextbox\hss + \or + \hss\box\nextbox + \else + \hss\box\nextbox\hss + \fi}% + \setbox\nextbox\hpack + {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% + \fi + \ifdim\ht\nextbox>\scratchheight + \setbox\nextbox\vpack to \scratchheight + {\ifcase\scratchcounter + \vss\box\nextbox\vss + \or + \box\nextbox\vss + \or + \vss\box\nextbox + \else + \vss\box\nextbox\vss + \fi}% + \setbox\nextbox\hpack + {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% + \fi + \box\nextbox + \egroup} + +\permanent\protected\def\overlayimage#1% + {\vpack to \overlayheight\bgroup + \vss + \hpack to \overlaywidth\bgroup + \hss + \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]% + \hss + \egroup + \vss + \egroup} + +\permanent\protected\def\clippedoverlayimage#1% + {\clip + [\c!width=\overlaywidth,\c!height=\overlayheight] + {\overlayimage{#1}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-com.mkxl b/tex/context/base/mkxl/pack-com.mkxl new file mode 100644 index 000000000..034035f35 --- /dev/null +++ b/tex/context/base/mkxl/pack-com.mkxl @@ -0,0 +1,954 @@ +%D \module +%D [ file=pack-com, % used to be in core-mis, +%D version=20120111, +%D title=\CONTEXT\ Packing Macros, +%D subtitle=Combinations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Combinations} + +\unprotect + +% \startfloatcombination will be redone ... we can decouple the floatcontent +% and caption and pass them to combinations so that we get better fit when the +% caption is wider than the float, testcase: +% +% \startfloatcombination [2*2] +% \placefigure[local]{alpha}{\externalfigure[cow.pdf][width=1cm]}% +% \placefigure[local]{beta} {\externalfigure[cow.pdf][width=2cm]}% +% \placefigure[local]{gamma}{\externalfigure[cow.pdf][width=3cm]} +% \placefigure[local]{delta}{\externalfigure[cow.pdf][width=4cm]} +% \stopfloatcombination + +%D We could of course map combinations onto one of the table mechanisms but as it +%D has served us well for ages we keep this one. The code has been cleaned up a bit +%D and mkiv'd. +%D +%D Okay ... I might luafy this one eventually. + +% \startcombination {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2] \combination {alpha} {a} \combination{beta} {b} \stopcombination + +%D We do support some structure but the order matters and currently it's only window +%D dressing: + +%D \starttyping +%D \let\startcontent\bgroup +%D \let\stopcontent \egroup +%D \let\startcaption\bgroup +%D \let\stopcaption \egroup +%D \stoptyping +%D +%D Of course we should have started with more structure as it would simply the code. +%D +%D \starttyping +%D \startcombination +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D Some cow. +%D \stopcaption +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D The same cow. +%D \stopcaption +%D \stopcombination +%D \stoptyping + +\ifdefined\dotagcombination \else \let\dotagcombination\relax \fi + +\newsystemmode{combination} + +\appendtoks + \globalresetsystemmode{combination}% +\to \everyinsidefloat + +\newcount\c_pack_combinations_nesting % local + +\newcount\c_pack_combinations_x % global +\newcount\c_pack_combinations_y % global +\newcount\c_pack_combinations_max % global + +\newdimen\d_pack_combinations_ht % global + +\newbox \b_pack_combinations_captions % global % can go +\newbox \b_pack_combinations_temp % global % can go +\newbox \b_pack_combinations_content % local +\newbox \b_pack_combinations_caption % local + +\installcorenamespace{combination} + +\installcommandhandler \??combination {combination} \??combination + +\initializeboxstack{\??combination captions} +\initializeboxstack{\??combination temp} + +\newcount\c_pack_combinations_x_saved +\newcount\c_pack_combinations_y_saved +\newcount\c_pack_combinations_max_saved + +\newdimen\d_pack_combinations_ht_saved + +\newbox \b_pack_combinations_captions_saved +\newbox \b_pack_combinations_temp_saved +\newbox \b_pack_combinations_content_saved +\newbox \b_pack_combinations_caption_saved + +\setfalse\c_strc_constructions_define_commands + +\def\pack_combinations_push + {\advance\c_pack_combinations_nesting\plusone + \ifnum\c_pack_combinations_nesting>\plusone + \c_pack_combinations_x_saved \c_pack_combinations_x + \c_pack_combinations_y_saved \c_pack_combinations_y + \c_pack_combinations_max_saved\c_pack_combinations_max + \d_pack_combinations_ht_saved \d_pack_combinations_ht + \setbox\b_pack_combinations_captions_saved\box\b_pack_combinations_captions + \setbox\b_pack_combinations_temp_saved \box\b_pack_combinations_temp + \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content + \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption + \else + \globalsetsystemmode{combination}% why global + \fi} + +\def\pack_combinations_pop + {\ifnum\c_pack_combinations_nesting>\plusone + \global\c_pack_combinations_x \c_pack_combinations_x_saved + \global\c_pack_combinations_y \c_pack_combinations_y_saved + \global\c_pack_combinations_max\c_pack_combinations_max_saved + \global\d_pack_combinations_ht \d_pack_combinations_ht_saved + \global\setbox\b_pack_combinations_captions\box\b_pack_combinations_captions_saved + \global\setbox\b_pack_combinations_temp \box\b_pack_combinations_temp_saved + \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved + \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved + \else + \globalresetsystemmode{combination}% why global + \fi + \advance\c_pack_combinations_nesting\minusone} + +\definelabel + [\v!combination] % handy for configuring + [\c!numberconversion=\v!character, + \c!text=] + +\settrue\c_strc_constructions_define_commands + +\setupcombination + [\c!width=\v!fit, + \c!height=\v!fit, + \c!distance=\emwidth, + \c!location=\v!bottom, % can be something {top,left} + \c!before=\blank, + \c!after=, + \c!inbetween={\blank[\v!medium]}, + %\c!style=, + %\c!color=, + \c!nx=2, % new + \c!ny=1, % new + \c!align=\v!middle] + +\let\setupcombinations\setupcombination % for the moment (we might distinguish) + +\installcorenamespace{combinationlocation} +\installcorenamespace{combinationalternative} + +\appendtoks + \setfalse\c_strc_constructions_define_commands + \normalexpanded + {\definelabel + [\v!combination:\currentcombination]% + [\v!combination\ifempty\currentcombinationparent\else:\currentcombinationparent\fi]}% + [\s!counter=\currentcombination,\c!levels=1]% + \settrue\c_strc_constructions_define_commands +\to \everydefinecombination + +\setvalue{\??combinationlocation\v!left }{\let\m_pack_combinations_leftfiller\relax} +\setvalue{\??combinationlocation\v!right }{\let\m_pack_combinations_rightfiller\relax} +\setvalue{\??combinationlocation\v!top }{\let\m_pack_combinations_valigner\depthonlybox} +\setvalue{\??combinationlocation\v!middle}{\let\m_pack_combinations_valigner\halfwaybox} + +\def\pack_combinations_location_reset + {\let\m_pack_combinations_rightfiller\hfil + \let\m_pack_combinations_leftfiller \hfil + \let\m_pack_combinations_valigner \firstofoneargument} + +\pack_combinations_location_reset + +\def\pack_combinations_location_step#1% + {\csname\??combinationlocation#1\endcsname} + +% formally ok: +% +% \protected\def\stopcombination +% {\egroup +% \egroup} +% +% more robust: +% +% \protected\def\stopcombination +% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries +% \egroup +% \egroup} +% +% even better: +% +% \protected\def\stopcombination +% {\bgroup +% \scratchtoks{{}}% +% \dorecurse\c_pack_combinations_y +% {\toksapp{{}{}}}% +% \expandafter\egroup\the\scratchtoks +% \egroup +% \dostoptagged +% \egroup} +% +% faster + +\ifdefined\startcontent \else \aliased\let\startcontent\relax \fi +\ifdefined\stopcontent \else \aliased\let\stopcontent \relax \fi +\ifdefined\startcaption \else \aliased\let\startcaption\relax \fi +\ifdefined\stopcaption \else \aliased\let\stopcaption \relax \fi + +\protected\def\pack_common_content_start{\bgroup\ignorespaces} +\protected\def\pack_common_content_stop {\removeunwantedspaces\egroup} +\protected\def\pack_common_caption_start{\bgroup\ignorespaces} +\protected\def\pack_common_caption_stop {\removeunwantedspaces\egroup} + +\newtoks\everycombination + +\permanent\protected\def\stopcombination + {\bgroup\normalexpanded{\egroup{}\ntimes{{}{}}\c_pack_combinations_y}% brr + \dostoptagged + \egroup + \pack_combinations_pop + \egroup} + +\permanent\tolerant\protected\def\startcombination[#1]#*[#2]% can be simplified + {\bgroup % so we can grab a group + \pack_combinations_push + \edef\currentcombination{#1}% + \edef\currentcombinationspec{#2}% + \ifempty\currentcombinationspec + \ifcondition\validassignment{#1}% + \let\currentcombination\empty + \setupcurrentcombination[#1]% + \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% + \else + \doifelseinstring{*}\currentcombination + {\edef\currentcombinationspec{\currentcombination*\plusone*}% + \let\currentcombination\empty} + {\doifelsenumber\currentcombination + {\edef\currentcombinationspec{\currentcombination*\plusone*}% + \let\currentcombination\empty} + {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}% + \fi + \else + \ifcondition\validassignment{#2}% + \setupcurrentcombination[#2]% + \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% + \else + \edef\currentcombinationspec{\currentcombinationspec*\plusone*}% + \fi + \fi + % + \forgetall + % + \the\everycombination + % + \enforced\let\startcontent\pack_common_content_start + \enforced\let\stopcontent \pack_common_content_stop + \enforced\let\startcaption\pack_common_caption_start + \enforced\let\stopcaption \pack_common_caption_stop + % + \edef\p_height {\combinationparameter\c!height}% + \edef\p_width {\combinationparameter\c!width}% + \edef\p_location{\combinationparameter\c!location}% + \edef\p_distance{\combinationparameter\c!distance}% + % + \pack_combinations_location_reset + \rawprocesscommacommand[\p_location]\pack_combinations_location_step + % + \dostarttaggedchained\t!combination\currentcombination\??combination + \vbox \ifx\p_height\v!fit\else to \p_height \fi \bgroup + \let\combination\empty % permits \combination{}{} handy for cld + \normalexpanded{\pack_combinations_start_indeed[\currentcombinationspec]}} + +\let\pack_combinations_check_x_y\relax + +\protected\def\pack_combinations_start_indeed[#1*#2*#3]% + {\global\c_pack_combinations_x#1\relax + \global\c_pack_combinations_y#2\relax + \setexpandedcombinationparameter\c!nx{\the\c_pack_combinations_x}% in case we access it + \setexpandedcombinationparameter\c!ny{\the\c_pack_combinations_y}% in case we access it + \pack_combinations_check_x_y + \dotagcombination + \global\setbox\b_pack_combinations_captions\emptybox + \global\c_pack_combinations_max\c_pack_combinations_x + \multiply\c_pack_combinations_y\c_pack_combinations_x + \tabskip\zeropoint + \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup % repetitive preamble + \aligntab + \m_pack_combinations_leftfiller + \alignmark\alignmark + \m_pack_combinations_rightfiller + \aligntab + \tabskip\zeropoint \s!plus 1fill % \fillskip + \alignmark\alignmark + \cr + \pack_combinations_pickup} + +%D I've first considered using a constructor directly but it's more overhead and +%D some settings conflict with already used combination settings so instead we plug +%D in labels. This also permits extensions later on. + +\appendtoks + \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}% +\to \everydefinecombination + +\def\pack_combinations_pickup + {\dostarttagged\t!combinationpair\empty % better make this text + \dostarttagged\t!combinationcontent\empty + \assumelongusagecs\pack_combinations_pickup_content_indeed} + +\def\pack_combinations_pickup_content_indeed + {\dowithnextboxcs\pack_combinations_pickup_content\hbox} + +\def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box + {\dostoptagged + \setbox\b_pack_combinations_content\box\nextbox + \dostarttagged\t!combinationcaption\empty + \expandnamespacemacro\??combinationalternative\p_pack_combinations_alternative\v!text} + +\setvalue{\??combinationalternative\v!text}% + {\assumelongusagecs\pack_combinations_alternative_text_indeed} + +\setvalue{\??combinationalternative\v!label}% + {\assumelongusagecs\pack_combinations_alternative_label_indeed} + +\def\pack_combinations_alternative_text_indeed + {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup + \afterassignment\pack_combinations_caption_first + \let\nexttoken=} + +\def\pack_combinations_alternative_label_indeed + {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup + \hsize\wd\b_pack_combinations_content + \usealignparameter\combinationparameter + \usecombinationstyleandcolor\c!style\c!color + \begstrut + \normalexpanded{\strc_labels_command[\v!combination\ifempty\currentcombination\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\ifempty\currentcombination\else:\currentcombination\fi}{1}}% + \fi + \fi +\to \everycombination + +\def\pack_combinations_pickup_caption + {\dostoptagged + \dostoptagged + \setbox\b_pack_combinations_caption\box\nextbox + \pack_combinations_pickup_package_pair} + +\def\pack_combinations_caption_first + {\futurelet\nexttoken\pack_combinations_caption_second} + +\def\pack_combinations_caption_second + {\ifx\nexttoken\egroup + % the caption is empty + \orelse\ifx\nexttoken\stopcaption + % the caption is empty (new per 2014-05-24) + \else + % todo: \p_pack_combinations_alternative\v!none: no style, strut etc + \hsize\wd\b_pack_combinations_content + \usealignparameter\combinationparameter + \usecombinationstyleandcolor\c!style\c!color + \bgroup + \aftergroup\endstrut + \aftergroup\egroup + \begstrut + \fi} + +\def\pack_combinations_pickup_package_pair % we need to store the caption row + {\vbox + {\forgetall + \m_pack_combinations_valigner{\box\b_pack_combinations_content}% + % we need to save the caption for a next alignment line + \pack_combinations_save_caption}% + \unless\ifnum\c_pack_combinations_y>\plusone + \global\advance\c_pack_combinations_y\minusone + \global\advance\c_pack_combinations_x\minusone + \ifcase\c_pack_combinations_x + \doubleexpandafter\pack_combinations_pickup_package_pair_a + \else + \doubleexpandafter\pack_combinations_pickup_package_pair_b + \fi + \else + \singleexpandafter\pack_combinations_pickup_package_pair_c + \fi} + +\def\pack_combinations_pickup_package_pair_a + {\cr + \pack_combinations_flush_captions + \noalign + {\forgetall + \global\setbox\b_pack_combinations_captions\emptybox + \nointerlineskip + \combinationparameter\c!after + \combinationparameter\c!before + \vss + \nointerlineskip}% + \global\c_pack_combinations_x\c_pack_combinations_max + \pack_combinations_pickup} + +\def\pack_combinations_pickup_package_pair_b + {\aligntab + \aligntab + \aligntab + \kern\p_distance + \aligntab + \pack_combinations_pickup} + +\def\pack_combinations_pickup_package_pair_c + {\cr + \pack_combinations_flush_captions + \egroup} + +\installcorenamespace{combinationcaption} + +\def\pack_combinations_save_caption + {\ifdim\htdp\b_pack_combinations_caption>\d_pack_combinations_ht + \global\d_pack_combinations_ht\htdp\b_pack_combinations_caption + \fi + \savebox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}{\box\b_pack_combinations_caption}} + +\def\pack_combinations_flush_captions + {\noalign + {\ifdim\d_pack_combinations_ht>\zeropoint + \nointerlineskip % indeed + \combinationparameter\c!inbetween + \global\c_pack_combinations_x\c_pack_combinations_max + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes + \else + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop + \fi}% + \pack_combinations_flush_captions_indeed + \crcr} + +\def\pack_combinations_flush_captions_yes + {\vpack to \d_pack_combinations_ht\bgroup + \foundbox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}% + \vss + \egroup + \global\advance\c_pack_combinations_x\minusone + \ifnum\c_pack_combinations_x>\zerocount % \c_pack_combinations_max + \expandafter\pack_combinations_flush_captions_yes_followup + \else + \global\d_pack_combinations_ht\zeropoint + \initializeboxstack{\??combinationcaption:\number-\c_pack_combinations_nesting}% + \fi} + +\let\pack_combinations_flush_captions_nop\donothing + +\def\pack_combinations_flush_captions_yes_followup + {\aligntab + \aligntab + \aligntab + \aligntab + \pack_combinations_flush_captions_indeed} + +%D \macros +%D {startfloatcombination} +%D +%D \setupexternalfigures[directory={../sample}] +%D \startbuffer +%D \placefigure +%D [left,none] +%D {} +%D {\startfloatcombination[2*2] +%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]} +%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]} +%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]} +%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]} +%D \stopfloatcombination} +%D +%D \input tufte +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\protected\def\pack_combinations_float_hack_a#1% + {\strc_floats_build_box_separate_split{#1}% + \box\b_strc_floats_separate_content} + +\protected\def\pack_combinations_float_hack_b#1% + {\box\b_strc_floats_separate_caption} + +\permanent\tolerant\protected\def\startfloatcombination[#1]#*[#2]% + {\ifinsidefloat\else\dontleavehmode\fi % tricky, floatcombinations fail to align well otherwise + \vbox\bgroup + \strc_floats_build_box_separate_set + %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature + \postcenterfloatmethod\zerocount + \forcelocalfloats + \enforced\permanent\protected\def\stopfloatcombination{\pack_combinations_stop_float{#1}}} + +\aliased\let\stopfloatcombination\relax + +\def\pack_combinations_float_check_x_y + {\ifnum\numexpr\c_pack_combinations_x*\c_pack_combinations_y\relax<\noflocalfloats\relax + \global\c_pack_combinations_x\noflocalfloats + \global\c_pack_combinations_y\plusone + \fi + \let\pack_combinations_check_x_y\relax}% + +\def\pack_combinations_stop_float#1% + {\scratchtoks\emptytoks + \dorecurse\noflocalfloats + {\appendetoks + {\pack_combinations_float_hack_a{\recurselevel}}% + {\pack_combinations_float_hack_b{\recurselevel}}% + \to\scratchtoks}% brrr + \let\pack_combinations_check_x_y\pack_combinations_float_check_x_y + \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination + \resetlocalfloats + \egroup} + +%D \macros +%D {definepairedbox, setuppairedbox, placepairedbox} +%D +%D Paired boxes, formally called legends, but from now on a legend is just an +%D instance, are primarily meant for typesetting some text alongside an +%D illustration. Although there is quite some variation possible, the functionality +%D is kept simple, if only because in most cases such pairs are typeset sober. +%D +%D The location specification accepts a pair, where the first keyword specifies the +%D arrangement, and the second one the alignment. The first key of the location pair +%D is one of \type {left}, \type {right}, \type {top} or \type {bottom}, while the +%D second key can also be \type {middle}. +%D +%D The first box is just collected in an horizontal box, but the second one is a +%D vertical box that gets passed the bodyfont and alignment settings. +%D +%D In many cases the table builders can be used instead, but as this mechanism is a +%D traditional \CONTEXT\ one we keep it around. + +%D \macros +%D {setuplegend, placelegend} +%D +%D It makes sense to typeset a legend to a figure in \TEX\ and not in a drawing +%D package. The macro \type {\placelegend} combines a figure (or something else) and +%D its legend. This command is just a paired box. +%D +%D The legend is placed according to \type {location}, being \type {bottom} or \type +%D {right}. The macro macro is used as follows. +%D +%D \starttyping +%D \placefigure +%D {whow} +%D {\placelegend +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend +%D {\externalfigure[cow]} +%D {\starttabulate[|l|l|l|l|] +%D \NC 1 \NC head \NC 3 \NC tail \NC \NR +%D \NC 2 \NC legs \NC \NC \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {head \par legs \par tail}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {\startitemize[packed] +%D \item head \item legs \item tail \item belly \item horns +%D \stopitemize}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2,width=.8\hsize] +%D {\externalfigure[cow]} +%D {\startitemize[packed] +%D \item head \item legs \item tail \item belly \item horns +%D \stopitemize}} +%D +%D \def\MytTestTwo#1#2% +%D {\placefigure +%D {whow} +%D {\placelegend[location={#1,#2}] +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}}} +%D +%D \def\MytTestOne#1{\processcommalist[left,right,top,bottom]{\MytTestTwo{#1}}} +%D +%D \processcommalist[left,right,top,bottom,middle]\MytTestOne +%D \stoptyping +%D +%D More structure is also possible (the order matters!): +%D +%D \starttyping +%D \startplacefigure[title=whow] +%D \startplacelegend[location={bottom,middle},color=red] +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D \starttabulate[|l|l|] +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate +%D \stopcaption +%D \stopplacelegend +%D \stopplacefigure +%D \stoptyping + +% todo: natural size + +\newsystemmode{pairedbox} + +\appendtoks + \globalresetsystemmode{pairedbox}% +\to \everyinsidefloat + +\installcorenamespace {pairedbox} + +\installcommandhandler \??pairedbox {pairedbox} \??pairedbox + +\setuppairedbox + [\c!n=1, + \c!distance=\bodyfontsize, + %\c!before=, + %\c!after=, + %\c!color=, + %\c!style=, + \c!inbetween={\blank[\v!medium]}, + \c!width=\hsize, + \c!height=\vsize, + \c!maxwidth=\textwidth, % \makeupwidth, + \c!maxheight=\textheight, % \makeupheight, + %\c!bodyfont=, + %\c!align=, + \c!location=\v!bottom] + +% watch the hsize/vsize tricks + +\newbox \b_pack_pairedboxes_first +\newbox \b_pack_pairedboxes_second +\newdimen\s_pack_pairedboxes_size + +\appendtoks + \frozen\instance\setuevalue{\e!setup\currentpairedbox\e!endsetup}{\setuppairedbox [\currentpairedbox]}% + \frozen\instance\setuevalue{\e!place\currentpairedbox }{\placepairedbox [\currentpairedbox]}% one argument is mandate anyway + \frozen\instance\setuevalue{\e!start\e!place\currentpairedbox }{\startplacepairedbox[\currentpairedbox]}% one argument is mandate anyway + \frozen\instance\setuevalue{\e!stop\e!place \currentpairedbox }{\stopplacepairedbox }% +\to \everydefinepairedbox + +\permanent\tolerant\protected\def\startplacepairedbox[#1]#*[#2]% + {\bgroup + \edef\currentpairedbox{#1}% + \setupcurrentpairedbox[#2]% + \pairedboxparameter\c!before + \bgroup + \edef\p_location{\pairedboxparameter\c!location}% + \edef\p_n {\pairedboxparameter\c!n}% + % + \enforced\let\startcontent\pack_common_content_start + \enforced\let\stopcontent \pack_common_content_stop + \enforced\let\startcaption\pack_common_caption_start + \enforced\let\stopcaption \pack_common_caption_stop + % + \globalsetsystemmode{pairedbox}% + \pack_pairedboxes_before + \assumelongusagecs\pack_pairedboxes_first_pickup} + +\permanent\protected\def\stopplacepairedbox{} % we just pick up two boxes + +\aliased\let\placepairedbox\startplacepairedbox % we just pick up two boxes + +\def\pack_pairedboxes_first_pickup + {\dowithnextboxcs\pack_pairedboxes_first\hbox + \bgroup + \let\next=} + +\def\pack_pairedboxes_first + {\pack_pairedboxes_between + \assumelongusagecs\pack_pairedboxes_second_pickup} + +\def\pack_pairedboxes_second_pickup + {\dowithnextboxcs\pack_pairedboxes_second\vbox + \bgroup + \pack_pairedboxes_inside_second + \let\next=} + +\def\pack_pairedboxes_second + {\pack_pairedboxes_after + \egroup + \pairedboxparameter\c!after + \egroup} + +\newconditional\c_pack_pairedboxes_horizontal \settrue\c_pack_pairedboxes_horizontal + +\installcorenamespace{pairedboxnature} +\installcorenamespace{pairedboxalign} + +\let\pack_pairedboxes_fill_top \relax +\let\pack_pairedboxes_fill_bottom\relax + +\setvalue{\??pairedboxnature\v!left}% + {\settrue\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_left} + +\setvalue{\??pairedboxnature\v!right}% + {\settrue\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_right} + +\setvalue{\??pairedboxnature\v!top}% + {\setfalse\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_fill_top\relax + \let\pack_pairedboxes_fill_bottom\vss + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_top} + +\setvalue{\??pairedboxnature\v!bottom}% + {\setfalse\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_fill_top\vss + \let\pack_pairedboxes_fill_bottom\relax + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_bottom} + +\def\pack_pairedboxes_flush_left + {\box\b_pack_pairedboxes_second + \kern\pairedboxparameter\c!distance + \box\b_pack_pairedboxes_first} + +\def\pack_pairedboxes_flush_right + {\box\b_pack_pairedboxes_first + \kern\pairedboxparameter\c!distance + \box\b_pack_pairedboxes_second} + +\def\pack_pairedboxes_flush_top + {\box\b_pack_pairedboxes_second + \endgraf + \nointerlineskip + \pairedboxparameter\c!inbetween + \box\b_pack_pairedboxes_first} + +\def\pack_pairedboxes_flush_bottom + {\box\b_pack_pairedboxes_first + \endgraf + \nointerlineskip + \pairedboxparameter\c!inbetween + \box\b_pack_pairedboxes_second} + +\setvalue{\??pairedboxalign\v!left}% 0 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\hss + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!right}% 1 + {\let\pack_pairedboxes_align_l\hss + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!high}% 2 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\vss} + +\setvalue{\??pairedboxalign\v!low}% 3 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\vss + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!middle}% 4 + {\let\pack_pairedboxes_align_l\hss + \let\pack_pairedboxes_align_r\hss + \let\pack_pairedboxes_align_t\vss + \let\pack_pairedboxes_align_b\vss} + +\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }} +\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}} + +\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}} +\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}} + +\def\pack_pairedboxes_before + {\ifempty\p_location + \csname\??pairedboxnature\v!left \endcsname + \csname\??pairedboxalign \v!middle\endcsname + \else + \getfromcommacommand[\p_location][1]% + \csname\??pairedboxnature + \ifcsname\??pairedboxnature\commalistelement\endcsname\commalistelement\else\v!left\fi + \endcsname + \getfromcommacommand[\p_location][2]% + \csname\??pairedboxalign + \ifcsname\??pairedboxalign\commalistelement\endcsname\commalistelement\else\v!middle\fi + \endcsname + \fi} + +\def\pack_pairedboxes_between + {\usebodyfontparameter\pairedboxparameter + \setbox\b_pack_pairedboxes_first\box\nextbox + \ifconditional\c_pack_pairedboxes_horizontal + \pack_pairedboxes_between_horizontal + \else + \pack_pairedboxes_between_vertical + \fi + \ifnum\p_n>\plusone + \setrigidcolumnhsize\hsize{\pairedboxparameter\c!distance}\p_n + \fi} + +\def\pack_pairedboxes_between_horizontal + {\scratchdistance\pairedboxparameter\c!distance + \scratchwidth\pairedboxparameter\c!maxwidth\relax + \setlocalhsize + \hsize\dimexpr\availablehsize-\wd\b_pack_pairedboxes_first-\scratchdistance\relax + \hsize\pairedboxparameter\c!width\relax % can be \hsize + \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\scratchdistance\relax + \ifdim\dimexpr\hsize+\scratchdimen\relax>\scratchwidth + \hsize\dimexpr\scratchwidth-\scratchdimen\relax + \fi} + +\def\pack_pairedboxes_between_vertical + {\scratchwidth\pairedboxparameter\c!maxwidth\relax + \hsize\wd\b_pack_pairedboxes_first + \hsize\pairedboxparameter\c!width\relax % can be \hsize + \ifdim\hsize>\scratchwidth\relax + \hsize\scratchwidth + \fi} + +\def\pack_pairedboxes_after + {\setbox\b_pack_pairedboxes_second\vpack + {\ifnum\p_n>\plusone + \rigidcolumnbalance\nextbox + \else + \box\nextbox + \fi}% + \ifconditional\c_pack_pairedboxes_horizontal + \pack_pairedboxes_pack_horizontal + \else + \pack_pairedboxes_pack_vertical + \fi} + +\def\pack_pairedboxes_pack_horizontal + {\dontleavehmode\hbox\bgroup + \forgetall + \s_pack_pairedboxes_size\ht + \ifdim\ht\b_pack_pairedboxes_first>\ht\b_pack_pairedboxes_second + \b_pack_pairedboxes_first + \else + \b_pack_pairedboxes_second + \fi + \vsize\s_pack_pairedboxes_size + \ifdim\s_pack_pairedboxes_size<\pairedboxparameter\c!height\relax % can be \vsize + \s_pack_pairedboxes_size\pairedboxparameter\c!height + \fi + \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax + \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight + \fi + \pack_pairedbox_valign\b_pack_pairedboxes_first + \pack_pairedbox_valign\b_pack_pairedboxes_second + \pack_pairedboxes_flush + \egroup} + +\def\pack_pairedboxes_pack_vertical + {\dontleavehmode\vpack\bgroup + \forgetall + \s_pack_pairedboxes_size\wd + \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second + \b_pack_pairedboxes_first + \else + \b_pack_pairedboxes_second + \fi + \pack_pairedbox_halign\b_pack_pairedboxes_first + \pack_pairedbox_halign\b_pack_pairedboxes_second + \s_pack_pairedboxes_size\ht\b_pack_pairedboxes_second + \vsize\s_pack_pairedboxes_size + \ifdim\ht\b_pack_pairedboxes_second<\pairedboxparameter\c!height\relax % can be \vsize + \s_pack_pairedboxes_size\pairedboxparameter\c!height\relax % \relax needed + \fi + \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax % todo: totale hoogte + \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed + \fi + \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second + \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size + {\pack_pairedboxes_fill_top + \box\b_pack_pairedboxes_second + \pack_pairedboxes_fill_bottom}% \kern\zeropoint + \fi + \pack_pairedboxes_flush + \egroup} + +\def\pack_pairedboxes_inside_second + {\forgetall + \setupalign[\pairedboxparameter\c!align]% + \usepairedboxstyleandcolor\c!style\c!color + \tolerantTABLEbreaktrue % hm. + \blank[\v!disable]% use fast one + \everypar{\begstrut}} % also flushers here (see bTABLE) + +\definepairedbox[\v!legend] + +\permanent\protected\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox} +\permanent\protected\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox} + +\def\pack_topofeachother_one{\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox} +\def\pack_sidebyside_one {\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox} + +\def\pack_topofeachother_two{\setbox\scratchboxtwo\box\nextbox + \halign{\hss\alignmark\alignmark\hss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% + \egroup\egroup} +\def\pack_sidebyside_two {\setbox\scratchboxtwo\box\nextbox + \valign{\vss\alignmark\alignmark\vss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% + \egroup\egroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-cut.mkxl b/tex/context/base/mkxl/pack-cut.mkxl new file mode 100644 index 000000000..08a5eab11 --- /dev/null +++ b/tex/context/base/mkxl/pack-cut.mkxl @@ -0,0 +1,164 @@ +%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 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 the marks as well as +%D 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 + +\mutable\let\cutmarksymbol \relax +\mutable\let\cutmarktoptext \empty +\mutable\let\cutmarkbottomtext \empty +\mutable\let\cutmarkhoffset \empty +\mutable\let\cutmarkvoffset \empty +\mutable\def\cutmarklength {2\bodyfontsize} +\mutable\def\cutmarkrulethickness{\onepoint} + +\permanent\protected\def\horizontalcuts + {\hpack to \d_pack_cutmarks_width + {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\hfill}% + \unskip}} + +\permanent\protected\def\verticalcuts + {\vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + {\hsize\cutmarklength + \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\vfill}% + \unskip}} + +\permanent\protected\def\baselinecuts + {\ifdim\d_pack_cutmarks_depth>\zeropoint + \vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + {\hsize\dimexpr\cutmarklength/2\relax + \vskip\zeropoint\s!plus\d_pack_cutmarks_height + \vrule\s!height\cutmarkrulethickness\s!width\hsize + \vskip\zeropoint\s!plus\d_pack_cutmarks_depth}% + \fi} + +\permanent\protected\def\cutmarksymbols#1% + {\hpack to \d_pack_cutmarks_width + {\setbox\scratchbox\hbox to \cutmarklength + {\hss\infofont\cutmarksymbol\hss}% + \hss + \vpack to \cutmarklength + {\scratchdimen\dimexpr\cutmarklength/2\relax + \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi + \vss + \hbox to \d_pack_cutmarks_width + {\llap{\copy\scratchbox\hskip\scratchskip}% + \hskip\scratchdimen\hss + \infofont#1% + \hss\hskip\scratchdimen + \rlap{\hskip\scratchskip\copy\scratchbox}}% + \vss}% + \hss}} + +\permanent\protected\def\makecutbox#1% + {\bgroup + \d_pack_cutmarks_height\ht#1% + \d_pack_cutmarks_depth \dp#1% + \d_pack_cutmarks_width \wd#1% + \setbox#1\hpack + {\dontcomplain + \forgetall + \boxmaxdepth\maxdimen + \offinterlineskip + \scratchdimen\dimexpr\cutmarklength/2\relax + \hsize\d_pack_cutmarks_width + \setbox\scratchbox\vpack + {\setbox\scratchbox\hpack{\horizontalcuts}% + \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi + \tlap{\copy\scratchbox\vskip\scratchskip}% + \hpack to \d_pack_cutmarks_width + {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi + \setbox\scratchbox\hpack{\verticalcuts}% + \llap{\copy\scratchbox\hskip\scratchskip}% + \ifdim\d_pack_cutmarks_depth=\zeropoint + \hfill + \else + \bgroup + \setbox\scratchbox\hpack{\baselinecuts}% + \llap{\copy\scratchbox\hskip\scratchskip}% + \hfill + \rlap{\hskip\scratchskip\copy\scratchbox}% + \egroup + \fi + \rlap{\hskip\scratchskip\copy\scratchbox}}% + \blap{\vskip\scratchskip\copy\scratchbox}}% + \ht\scratchbox\d_pack_cutmarks_height + \dp\scratchbox\d_pack_cutmarks_depth + \wd\scratchbox\zeropoint + \startcolor[\defaulttextcolor]% + \box\scratchbox + \ifx\cutmarksymbol\relax \else + \setbox\scratchbox\vpack + {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi + \vskip-\dimexpr\scratchskip+\cutmarklength\relax + \hpack{\cutmarksymbols\cutmarktoptext}% + \vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax + \hpack{\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} + +\permanent\protected\def\cuthbox{\hpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\hbox} +\permanent\protected\def\cutvbox{\vpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vbox} +\permanent\protected\def\cutvtop{\tpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vtop} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-fen.mkxl b/tex/context/base/mkxl/pack-fen.mkxl new file mode 100644 index 000000000..8fa74b884 --- /dev/null +++ b/tex/context/base/mkxl/pack-fen.mkxl @@ -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 + +\permanent\protected\def\installleftframerenderer#1#2% + {\setvalue{\??framedleft\v!on#1}{\whateverleftframe{#2}}% + \letcsname\??framedleft\v!off#1\expandafter\endcsname\csname\??framedleft\v!on#1\endcsname} + +\permanent\protected\def\installrightframerenderer#1#2% + {\setvalue{\??framedright\v!on#1}{\whateverrightframe{#2}}% + \letcsname\??framedright\v!off#1\expandafter\endcsname\csname\??framedright\v!on#1\endcsname} + +\permanent\protected\def\installtopframerenderer#1#2% + {\setvalue{\??framedtop\v!on#1}{\whatevertopframe{#2}}% + \letcsname\??framedtop\v!off#1\expandafter\endcsname\csname\??framedtop\v!on#1\endcsname} + +\permanent\protected\def\installbottomframerenderer#1#2% + {\setvalue{\??framedbottom\v!on#1}{\whateverbottomframe{#2}}% + \letcsname\??framedbottom\v!off#1\expandafter\endcsname\csname\??framedbottom\v!on#1\endcsname} + +\ifdefined \pack_framed_overlay_initialize_indeed + + \aliased\let\setinstalledframedimensions\pack_framed_overlay_initialize_indeed + +\else + + \permanent\protected\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 + +\permanent\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} + +\permanent\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} + +\permanent\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} + +\permanent\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/tex/context/base/mkxl/pack-lyr.mkxl b/tex/context/base/mkxl/pack-lyr.mkxl new file mode 100644 index 000000000..e85b3c185 --- /dev/null +++ b/tex/context/base/mkxl/pack-lyr.mkxl @@ -0,0 +1,772 @@ +%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 the output routine, but +%D future extensions may depend on a more close cooperation. +%D +%D First we overload a macro from \type {pack-rul}. From now on we accept a +%D (optional) argument: the specific layer it will go in. This means that we can +%D move an overlay from one background to the other using the dimensions of the +%D parent. + +\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi + +\pushoverloadmode + +\permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#2]#*[#3]% overlay [layer] content + {\ifnum\lastarguments=\plusthree + %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp + \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}% + \else + \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% + \fi + \processcommalist[#1]\pack_framed_define_overlay_indeed} + +\popoverloadmode + +%D We use the command handler code. The previous, more direct parameter handling was +%D 25\% faster when no parameters were passed when adding content to a layer. +%D However, when we pass for instance a preset, the new methos is some 10\% faster +%D and it happens that in most cases we do pass some parameters. It would be +%D interesting to see if we can push the preset in between the regular chain but it +%D could also lead to 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 the data that goes +%D into a layer, is typeset immediately. Each layer automatically gets an associated +%D overlay, which can be used in any background assignment. +%D +%D After a layer is defined, you can change its 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 \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode + +\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 needed anyway). + +\def\pack_layers_reset_box#1% + {\ifcsname\??layerbox#1\endcsname + %\global\setbox\csname\??layerbox#1\endcsname\emptybox + \global\setbox\lastnamedcs\emptybox + \fi} + +\permanent\protected\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 \type {position} is +%D set, relative positioning is used, with the current point as reference point. +%D Otherwise the topleft corner is used as reference point. +%D +%D \starttyping +%D \setlayer [identifier] [optional parameters] {data} +%D \stoptyping + +\permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right + {\edef\currentlayerwidth {\thelayerwidth {#2#1}}% + \edef\currentlayerheight{\thelayerheight{#2#1}}} + +\permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi} +\permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi} + +\permanent\tolerant\protected\def\setlayer[#1]#*[#2]#*[#3]% #4 == box do \fi is ok + {\bgroup + \nofarguments\lastarguments + \checkpositionoverlays % otherwise funny regions + \edef\currentlayer{#1}% + \edef\p_pack_layers_state{\layerparameter\c!state}% + \ifx\p_pack_layers_state\v!stop + \dowithnextboxcs\egroup\hbox % no pack ? + \orelse\ifnum\nofarguments=\plusthree + \edef\m_pack_layers_target{#2}% + \pack_layers_set_indeed{#3}% + \orelse\ifhastok={#2}% + \let\m_pack_layers_target\empty + \pack_layers_set_indeed{#2}% + \else + \edef\m_pack_layers_target{#2}% + \pack_layers_set_indeed\empty + \fi} + +\def\pack_layers_set_indeed#1% + {\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 + \dowithnextbox{\pack_layers_set_finish{#1}}\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 + \orelse\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 + \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}% wrong one + \edef\m_pack_layers_region{\layerparameter\c!region}% + \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{layering}{region: \m_pack_layers_region=>\MPxywhd\m_pack_layers_region}% + % \writestatus {}{anchor: \m_pack_layers_anchor=>\MPxywhd\m_pack_layers_anchor}% + % \writestatus {}{offset: \c!dx,\c!dy =>\lastlayerxpos,\lastlayerypos}% + \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 + \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 + \glet\lastlayerxpos\!!zeropoint + \glet\lastlayerypos\!!zeropoint + \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions + \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions + \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions + \edef\m_pack_layers_page{\layerparameter\c!page}} + +\permanent\tolerant\protected\def\definelayerpreset[#1]#*[#2]% + {\ifarguments + \or + \letvalue{\??layerpreset#1}\empty + \orelse\ifhastok={#2}% + \setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}% + \else + \setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}% + \fi} + +\def\pack_layers_set_content#1% + {\layerwidth \layerparameter\c!width % global (local later) + \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 + \ifempty\p_pack_layers_rotation \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 + \ifx\p_pack_layers_position\v!yes + \pack_layers_set_last_position_yes + \else + \pack_layers_set_last_position_nop + \fi + % + \ifempty\m_pack_layers_page \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 + % or maybe instead of the \vskip + % \raise-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_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 not even that +%D complicated. It mainly comes down to skipping to the right place and placing a +%D box on top of or below the existing content. In the case of position tracking, +%D another reference point is chosen. + +%D \macros +%D {doifelselayerdata} + +\permanent\def\doifelselayerdata#1% + {\ifcsname\??layerbox#1\endcsname + %\ifvoid\csname\??layerbox#1\endcsname + \ifvoid\lastnamedcs + \doubleexpandafter\secondoftwoarguments + \else + \doubleexpandafter\firstoftwoarguments + \fi + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflayerdataelse\doifelselayerdata + +%D \macros +%D {flushlayer} +%D +%D When we flush a layer, we flush both the main one and the page dependent one +%D (when defined). This feature is more efficient in \ETEX\ since there testing for +%D an undefined macro does not takes hash space. + +% todo: setups before flush, handy hook + +\permanent\protected\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 + \orelse\ifx\p_pack_layers_state\v!next + \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up + \orelse\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 + \endgroup} + +% optimized + +\def\pack_layers_flush_single + {\ifcsname\??layerbox\currentlayer\endcsname + \ifvoid\lastnamedcs + \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else + \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi + \else + \chardef\b_layer_one\lastnamedcs + \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else + \chardef\b_layer_two\lastnamedcs + \startoverlay + {\pack_layers_flush_indeed\plusone \currentlayer \b_layer_one}% + {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}% + \stopoverlay + \fi + \else + \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one + \fi + \fi + \orelse\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs + % nothing + \else + \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi} + +% less optimized: + +\def\pack_layers_flush_double#1% + {\startoverlay + {\ifcsname\??layerbox\currentlayer\endcsname + \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox#1\currentlayer\endcsname + \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi}% + \stopoverlay} + +\let\pack_layers_top_fill \relax +\let\pack_layers_bottom_fill\vss + +\def\pack_layers_flush_indeed#1#2#3% + {\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 + \orelse\ifx\p_pack_layers_state\v!repeat + \settrue\c_pack_layers_repeated + \else + \setfalse\c_pack_layers_repeated + \fi + \fi + \fi + %chardef\b_layers\csname\??layerbox#2\endcsname % trick + \let\b_layers#3% + % we need to copy in order to retain the negative offsets for a next + % stage of additions, i.e. llx/lly accumulate in repeat mode and the + % compensation may differ each flush depending on added content + \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 + % and maybe 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}% +% + \ifx\p_pack_layers_method\v!overlay \wd\nextbox\d_overlay_width\fi + \box\nextbox +% + \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}% + \ifempty\p_pack_layers_region\else + \anch_mark_tagged_box\nextbox\p_pack_layers_region % was \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 when we use it as +%D parameter. This name also suits better to other layering commands. + +\permanent\protected\def\composedlayer#1{\flushlayer[#1]} + +\permanent\protected\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}}} + +\aliased\let\placelayer\flushlayer + +%D \macros +%D {setMPlayer} +%D +%D The following layer macro uses the positions that are 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 + +\mutable\def\MPlayerwidth {\hsize} +\mutable\def\MPlayerheight{\vsize} + +\permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[#3]% + {\edef\MPlayerwidth {\MPw{#2}}% + \edef\MPlayerheight{\MPh{#2}}% + \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]} + +\permanent\tolerant\protected\def\getMPlayer[#1]#*[#2]% + {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument + +%D Watch out, a redefinition: + +\ifdefined\settextpagecontent \else + \writestatus\m!system{error in page-lyr.tex} \wait +\fi + +\definelayer + [OTRTEXT] + +\setuplayer + [OTRTEXT] + [\c!width=\innermakeupwidth, + \c!height=\textheight] + +\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr + +\overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr + +\permanent\overloaded\protected\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/tex/context/base/mkxl/pack-mis.mklx b/tex/context/base/mkxl/pack-mis.mklx new file mode 100644 index 000000000..5c63f533c --- /dev/null +++ b/tex/context/base/mkxl/pack-mis.mklx @@ -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 [settings] + +\installcorenamespace{placement} + +\installcommandhandler \??placement {placement} \??placement + +\appendtoks + \frozen\instance\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] + +\permanent\protected\def\placement[#tag]% + {\pack_placement{#tag}} + +\protected\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}% + \ifempty\p_grid + \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 + \orelse\ifx\p_margin\v!yes + \noindent + \fi} + +\protect \endinput + diff --git a/tex/context/base/mkxl/pack-mrl.mkxl b/tex/context/base/mkxl/pack-mrl.mkxl new file mode 100644 index 000000000..f9736aa74 --- /dev/null +++ b/tex/context/base/mkxl/pack-mrl.mkxl @@ -0,0 +1,844 @@ +%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} \??blackrules + +\permanent\protected\def\blackrule + {\hpack\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 + \orelse\ifx\p_depth\v!max + \setstrut + \fi + \useblackrulesstyleandcolor\c!style\c!color + \ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname + \lastnamedcs + \else + \vrule + \fi + \ifx\p_width \v!max\s!width \emwidth\orelse\ifempty\p_width \else\s!width \p_width \fi + \ifx\p_height\v!max\s!height\strutht\orelse\ifempty\p_height\else\s!height\p_height\fi + \ifx\p_depth \v!max\s!depth \strutdp\orelse\ifempty\p_depth \else\s!depth \p_depth \fi + \egroup} + +\setupblackrules + [\c!width=\emwidth, + \c!height=\exheight, + \c!depth=\zeropoint, + \c!color=] + +%D \macros +%D {blackrules} +%D +%D One can call for a sequence of black rules, if needed 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. + +\permanent\tolerant\protected\def\blackrules[#1]% probably never used + {\hpack\bgroup + \ifarguments\or\setupcurrentblackrules[#1]\fi + \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 % why not just check distance + \ifnum\scratchcounter=\plusone + \scratchdistance\zeropoint + \else + \scratchwidth\dimexpr(\scratchwidth-\scratchcounter\scratchdistance+\scratchdistance)/\scratchcounter\relax + \fi + \fi + \useblackrulesstyleandcolor\c!style\c!color + % a typical case of where we can use a simple loop or even a leaders + \dorecurse\scratchcounter\pack_black_rules_step + \unskip + \egroup} + +\def\pack_black_rules_step + {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname + \lastnamedcs + \else + \vrule + \fi + \s!width \scratchwidth + \s!height\scratchheight + \s!depth \scratchdepth + \relax + \ifzeropt\scratchdistance\else + \hskip\scratchdistance + \fi} + +\installcorenamespace{blackruletype} + +\setvalue{\??blackruletype mp}% + {\frule + type {mp}% + data {\includeMPgraphic{\directblackrulesparameter\c!mp}} + line \dimexpr\directblackrulesparameter\c!rulethickness\relax + } + +\letvalue{\??blackruletype\s!no }\novrule +%letvalue{\??blackruletype\s!yes}\vrule + +\setupblackrules + [\c!n=3, + \c!rulethickness=\linewidth, + \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} + +\protected\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} + +\permanent\tolerant\protected\def\vl[#1]% + {\pack_rule_vl_indeed{#1}{#1}{#1}} + +\permanent\tolerant\protected\def\hl[#1]% + {\dontleavehmode + \hbox + {\vrule + \s!width #1\emwidth + \s!height\linewidth + \s!depth \zeropoint}} + +\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 + +\permanent\protected\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 + \ifzeropt\linewidth + \c_pack_thinrules_type\zerocount + \orelse\ifx\p_frame\v!on + \c_pack_thinrules_type\expandnamespaceparameter\??thinrulealternatives\directthinrulesparameter\c!alternative\v!b\relax + \else + \c_pack_thinrules_type\zerocount + \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} + +\permanent\protected\def\hairline % can be overloaded + {\endgraf + \thinrule + \endgraf} + +\permanent\tolerant\protected\def\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 + \ifempty\p_inbetween + \softbreak % \ifhmode \hskip \parfillskip \break \fi + \else + \endgraf + \nowhitespace + \p_inbetween + \fi + \fi}% + \fi + \fi + \ifempty\p_after + \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] + +% can be done nicer with futureexpandis + +\permanent\tolerant\protected\def\textrule[#1]% + {\ifarguments + \expandafter\pack_textrule_nop + \else + \expandafter\pack_textrule_yes + \fi[#1]} + +\def\pack_textrule_yes[#1]% + {\expandnamespacevalue\??textrulealternatives{#1}\v!bottom} + +\tolerant\def\pack_textrule_nop[#1]#:#=% + {\ifparameter#2\or + \expandafter\pack_textrule_nop_indeed_yes + \else + \expandafter\pack_textrule_nop_indeed_nop + \fi[#1]{#2}} + +\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_yes{#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_yes#1% + {\noindent % this will force side floats to be calculated + \bgroup + \setbox\scratchbox\hpack to \availablehsize + {\scratchwidth \directtextrulesparameter\c!rulethickness\relax + \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax + \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax + \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 + \box\scratchbox + %\carryoverpar + \egroup} + +\def\pack_textrule_with_text_nop#1% + {\ifhmode + \endgraf + \fi + \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on + \pack_textrule_correct_depth_yes + \pack_textrule_correct_depth_nop + \nointerlineskip + \noindent\naturalvpack % was \dontleavehmode + {\color[\directtextrulesparameter\c!rulecolor] + {\hrule + \s!depth \directtextrulesparameter\c!rulethickness + \s!height\zeropoint + \s!width \availablehsize}}} + +\def\pack_textrule_correct_depth_yes + {\vskip\dimexpr + \strutdp +.5\exheight + \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} + \pack_textrule_with_text_nop + \pack_textrule_with_text_yes + {#1}% + \ifvmode + \prevdepth\zeropoint + \fi} + +%D The grouped commands also supports bodyfont switching: + +\permanent\protected\def\starttextrule#1% + {\bgroup + \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}% + \csname\??textrulealternatives\v!top\endcsname{#1}% + \bgroup + \usebodyfontparameter\directtextrulesparameter} + +\permanent\protected\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=] + +\permanent\tolerant\protected\def\fillinrules[#1]#:#=#*#=% + {\endgraf + \begingroup + \setupcurrentfillinrules[#1]% + \let\pack_fillinrules_rule\thinrules + \directfillinrulesparameter\c!before + \setupcurrentthinrules + [\c!n=\directfillinrulesparameter\c!n, + \c!interlinespace=\directfillinrulesparameter\c!interlinespace, + \c!before=, + \c!after=]% + \scratchdistance\directfillinrulesparameter\c!distance\relax + \noindent + \iftok{#2}\emptytoks\else + \edef\p_width{\directfillinrulesparameter\c!width}% + \ifx\p_width\v!fit + \scratchdistance\zeropoint + \hbox + \orelse\ifx\p_width\v!broad + \hbox + \else + \hbox to \directfillinrulesparameter\c!width + \fi + \bgroup + \usefillinrulesstyleandcolor\c!style\c!color + \strut + #2% + \hfill\directfillinrulesparameter\c!separator + \hskip\scratchdistance + \egroup + \fi + \setupwhitespace[\v!big]% + \ignorespaces + \pack_fillinrules_rule + \iftok{#3}\emptytoks\else + \kern\scratchdistance + \usefillinrulesstyleandcolor\c!style\c!color + #3% + \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} + +\permanent\tolerant\protected\def\fillintext[#1]#:#=#*#=% + {\endgraf + \begingroup + \setupcurrentfillinrules[#1]% + \def\pack_fillinrules_rule{\unhbox\nextbox\unskip}% + \dowithnextbox{\pack_fillinrules_indeed{#2}{\hfill#3}}% + \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 \fillinline \input reich \par +%D \fillinline[margin=0cm] \input reich \par +%D \stopbuffer +%D +%D \startexample +%D \getbuffer +%D \stopexample +%D +%D which was typeset by saying: +%D +%D \typebuffer +%D +%D The two commands that take care of this are: +%D +%D \showsetup{fillinline} +%D \showsetup{setupfillinlines} +%D +%D Contrary to older implementations we now use the wrapper. + +\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] + +\protected\def\pack_fillinline_before#1% + {} + +\protected\def\pack_fillinline_after#1% + {\begingroup + \setupcurrentfillinlines[#1]% + \ifhmode\unskip\hfill\fi + \scratchdistance\directfillinlinesparameter\c!distance + \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax + \scratchwidth \dimexpr\directfillinlinesparameter\c!width-\scratchdistance\relax + \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else + \expandafter\rlap + \fi + {\kern\scratchdistance + \blackrule + [\c!color=\directfillinlinesparameter\c!color, + \c!width=\scratchwidth, + \c!height=\scratchheight, + \c!depth=\scratchheight]}% + \frozen\advance\rightskip \directfillinlinesparameter\c!margin\relax + \frozen\parfillskip\zeropoint\relax + \endgroup} + +\permanent\tolerant\protected\def\fillinline[#1]% + {\registerparwrapper + {fillinline}% + {\pack_fillinline_before{#1}}% + {\pack_fillinline_after {#1}% + \unregisterparwrapper{fillinline}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-obj.lmt b/tex/context/base/mkxl/pack-obj.lmt new file mode 100644 index 000000000..f021339b4 --- /dev/null +++ b/tex/context/base/mkxl/pack-obj.lmt @@ -0,0 +1,305 @@ +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-- +

We save object references in the main utility table. jobobjects are +reusable components.

+--ldx]]-- + +local context = context +local codeinjections = backends.codeinjections +local ctx_doifelse = commands.doifelse + +local report = logs.reporter("objects") +local trace = false trackers.register("objects",function(v) trace = v end) + +local nuts = nodes.nuts + +local setlink = nuts.setlink +local getlist = nuts.getlist +local setbox = nuts.setbox + +local new_latelua = nuts.pool.latelua + +local settexdimen = tokens.setters.dimen + +local getcount = tex.getcount + +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 data = { number, page } + tobesaved[tag] = data + collected[tag] = data +end + +local function saveobjectspec(specification) + local tag = specification.tag + local data = { specification.number, specification.page } + tobesaved[tag] = data + collected[tag] = data +end + +local function setobject(tag,number,page) + 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 = "2 strings", +-- } +-- +-- implement { +-- name = "objectpage", +-- actions = { getobjectpage, context }, +-- arguments = "2 strings", +-- } +-- +-- 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, +} + +local objects = objects + +function objects.register(ns,id,b,referenced,offset,mode) + local n = objects.n + 1 + objects.n = n + nodes.handlers.finalizebox(b) + if mode == 0 then + -- tex + data[ns][id] = { + codeinjections.registerboxresource(b), -- a box number + offset, + referenced or false, + mode, + } + else + -- box (backend) + data[ns][id] = { + codeinjections.registerboxresource(b,offset), -- a box number + false, + referenced, + mode, + } + end + if trace then + report("registering object %a (n=%i)",id,n) + end +end + +function objects.restore(ns,id) -- why not just pass a box number here too (ok, we also set offset) + local d = data[ns][id] + if d then + local index = d[1] + local offset = d[2] + local status = d[3] + local mode = d[4] + local hbox = codeinjections.restoreboxresource(index) -- a nut ! + if status then + local list = getlist(hbox) + local page = new_latelua { + action = saveobjectspec, + tag = ns .. "::" .. id, + number = index, + page = getcount("realpageno"), + } + -- list is a rule + setlink(list,page) + end + setbox("objectbox",hbox) + settexdimen("objectoff",offset or 0) + else + setbox("objectbox",nil) + settexdimen("objectoff",0) -- for good old times + end + if trace then + report("restoring object %a",id) + end +end + +function objects.dimensions(index) + local d = data[ns][id] + if d then + return codeinjections.boxresourcedimensions(d[1]) + else + return 0, 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,getcount("realpageno")) +end + +function objects.found(ns,id) + return data[ns][id] +end + +implement { + name = "registerreferencedobject", + arguments = { "string", "string", "integer", true, "dimension", "integer" }, + actions = objects.register, +} + +implement { + name = "registerobject", + arguments = { "string", "string", "integer", false, "dimension", "integer" }, + actions = objects.register, +} + +implement { + name = "restoreobject", + arguments = "2 strings", + actions = objects.restore, +} + +implement { + name = "doifelseobjectfound", + arguments = "2 arguments", + public = true, + protected = true, + actions = function(ns,id) + ctx_doifelse(data[ns][id]) + -- ctx_doifelse(objects.reference(ns,id)) + end, +} + +implement { + name = "doifelseobjectreferencefound", + arguments = "2 arguments", + public = true, + protected = true, + actions = function(ns,id) + -- ctx_doifelse(data[ns][id]) + ctx_doifelse(objects.reference(ns,id)) + end, +} + +implement { + name = "getobjectreference", + arguments = { "argument", "argument", "csname" }, + public = true, + protected = true, + actions = function(ns,id,target) + setmacro(target,objects.reference(ns,id),"global") + end +} + +implement { + name = "getobjectreferencepage", + arguments = { "argument", "argument", "csname" }, + public = true, + protected = true, + actions = function(ns,id,target) + setmacro(target,objects.page(ns,id),"global") + end +} + +implement { + name = "getobjectdimensions", + arguments = "2 arguments", + public = true, + protected = true, + actions = function(ns,id) + local object = data[ns][id] + local w, h, d, o = 0, 0, 0, 0 + if object then + w, h, d, o = codeinjections.boxresourcedimensions(object[1]) + end + settexdimen("objectwd",w or 0) + settexdimen("objectht",h or 0) + settexdimen("objectdp",d or 0) + settexdimen("objectoff",o or #objects > 2 and object[2] or 0) + end +} + +-- for the moment here: + +implement { + name = "registerbackendsymbol", + arguments = { "string", "integer" }, + actions = function(...) + codeinjections.registersymbol(...) + end +} diff --git a/tex/context/base/mkxl/pack-obj.mkxl b/tex/context/base/mkxl/pack-obj.mkxl new file mode 100644 index 000000000..751434db0 --- /dev/null +++ b/tex/context/base/mkxl/pack-obj.mkxl @@ -0,0 +1,168 @@ +%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}{autosuffix} + +%D \macros +%D {setobject,getobject,ifinobject} +%D +%D Boxes can be considered reuable objects. Traditionally once passed to the \DVI\ +%D file, such objects cannot be reused. In \PDF\ however, reusing is possible and +%D sometimes even a necessity. Therefore, \CONTEXT\ supports reusable objects and +%D \LUATEX\ has native support for so called box resources. +%D +%D The first application of objects in \CONTEXT\ concerned \METAPOST\ graphics and +%D fill||in form fields. Reusing resources can save lots of bytes and sometimes also +%D 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. Although the +%D implementation in \MKIV\ is somewhat different the principles have not changed. + +\installcorenamespace {objects} + +\newif \ifinobject +\newbox \objectbox + +\def\objectoffset{1cm} + +\newdimen\objectoff \permanent\def\objectmargin{\the\objectoff} +\newdimen\objectwd \permanent\def\objectwidth {\the\objectwd} +\newdimen\objectht \permanent\def\objectheight{\the\objectht} +\newdimen\objectdp \permanent\def\objectdepth {\the\objectdp} + +%D If I have time I will use the unreferenced variant for e.g. mp reuse. This can be +%D rewritten in \LUA\ anyway. + +\permanent\protected\def\setreferencedobject #1#2{\begingroup\synctexpause\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}} +\permanent\protected\def\settightreferencedobject #1#2{\begingroup\synctexpause\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}} +\permanent\protected\def\setunreferencedobject #1#2{\begingroup\synctexpause\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}} +\permanent\protected\def\settightunreferencedobject#1#2{\begingroup\synctexpause\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}} + +\aliased\let\setobject \setreferencedobject +\aliased\let\settightobject\settightreferencedobject + +%D We can get subtle differences in boundingboxes but both methods work ok. + +\newconstant\c_pack_objects_offset_mode % 0=tex 1=box + +\protected\def\pack_objects_set_yes#1#2% + {\ifcase\c_pack_objects_offset_mode + \ifzeropt\objectoff + \pack_objects_package_nop\nextbox + \else + \pack_objects_package_yes\nextbox + \fi + \else + \pack_objects_package_nop\nextbox + \fi + \clf_registerreferencedobject{#1}{#2}\objectbox\objectoff\c_pack_objects_offset_mode + \synctexresume + \endgroup} + +\protected\def\pack_objects_set_nop#1#2% + {\ifcase\c_pack_objects_offset_mode + \ifzeropt\objectoff + \pack_objects_package_nop\nextbox + \else + \pack_objects_package_yes\nextbox + \fi + \else + \pack_objects_package_nop\nextbox + \fi + \clf_registerobject{#1}{#2}\objectbox\objectoff\c_pack_objects_offset_mode + \synctexresume + \endgroup} + +\def\pack_objects_package_nop#1% we pack because otherwise \ruledhbox is still tight + {\setbox\objectbox\hpack{\box#1}} + +\def\pack_objects_package_yes#1% + {\objectwd\dimexpr\wd#1+2\objectoff\relax + \objectht\dimexpr\ht#1+ \objectoff\relax + \objectdp\dimexpr\dp#1+ \objectoff\relax + \setbox\objectbox\hpack + {\hskip\objectoff + \box#1}% + \wd\objectbox\objectwd + \ht\objectbox\objectht + \dp\objectbox\objectdp} + +\permanent\protected\def\getobject#1#2% + {\begingroup + \synctexpause + \clf_restoreobject{#1}{#2}% + \ifzeropt\objectoff\else + \objectoff-\objectoff + \pack_objects_package_yes\objectbox + \fi + \box\objectbox + \synctexresume + \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 {\objectheight} and \type +%D {\objectdepth} as well as \type {\objectoffset}. + +% \getobjectdimensions #1#2 % defined at the lua end + +%D \macros +%D {doifobjectfoundelse,doifobjectreferencefoundelse} +%D +%D To prevent redundant definition of objects, one can use the next tests: +%D +%D \starttyping +%D \doifobjectfoundelse{class}{object}{do then}{do else} +%D \doifobjectreferencefoundelse{class}{object}{do then}{do else} +%D \stoptyping + +\immutable\def\defaultobjectreference{0} +\immutable\def\defaultobjectpage {\realfolio} + +% \getobjectreference {#1}{#2\csname % define at the lua end +% \getobjectreferencepage {#1}{#2\csname % define at the lua end +% \doifelseobjectfound {#1}{#2} % defined atthe lua end +% \doifelseobjectreferencefound {#1}{#2} % defined atthe lua end + +\aliased\let\dogetobjectreference \getobjectreference % for now, will go away +\aliased\let\dogetobjectreferencepage\getobjectreferencepage % for now, will go away + +\aliased\let\doifobjectfoundelse \doifelseobjectfound +\aliased\let\doifobjectreferencefoundelse\doifelseobjectreferencefound + +%D For the moment here: + +\mutable\let\lastpredefinedsymbol\empty % some day we can do more at the lua end + +\permanent\protected\def\predefinesymbol[#1]% + {\begingroup + \xdef\lastpredefinedsymbol{#1}% + \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting + \getobjectreference{SYM}{#1}\m_back_object_reference + \clf_registerbackendsymbol{#1}\m_back_object_reference\relax + \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-ori.lmt b/tex/context/base/mkxl/pack-ori.lmt new file mode 100644 index 000000000..a786b19ef --- /dev/null +++ b/tex/context/base/mkxl/pack-ori.lmt @@ -0,0 +1,70 @@ +if not modules then modules = { } end modules ['pack-ori'] = { + 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" +} + +local context = context +local implement = interfaces.implement +local variables = interfaces.variables + +local settings_to_array = utilities.parsers.settings_to_array + +local orientation = { + [variables.up] = 0x000, + [variables.left] = 0x001, + [variables.down] = 0x002, + [variables.right] = 0x003, + [variables.top] = 0x004, + [variables.bottom] = 0x005, +} +local vertical = { + [variables.line] = 0x000, + [variables.top] = 0x010, + [variables.bottom] = 0x020, + [variables.middle] = 0x030, +} +local horizontal = { + [variables.middle] = 0x000, + [variables.flushleft] = 0x100, + [variables.flushright] = 0x200, + [variables.left] = 0x300, + [variables.right] = 0x400, +} + +implement { + name = "toorientation", + public = true, + arguments = { + { + { "horizontal", "string" }, + { "vertical", "string" }, + { "orientation", "string" }, + } + }, + actions = function(t) + local n = 0 + local m = t.horizontal if m then n = n | (horizontal [m] or 0) end + local m = t.vertical if m then n = n | (vertical [m] or 0) end + local m = t.orientation if m then n = n | (orientation[m] or 0) end + -- logs.report("orientation","0x%03X : %s",n,table.sequenced(t)) + context(n) + end, +} + +implement { + name = "stringtoorientation", + public = true, + arguments = "string", + actions = function(s) + local n = 0 + local t = settings_to_array(s) + local m = t[1] if m then n = n | (horizontal [m] or 0) end + local m = t[2] if m then n = n | (vertical [m] or 0) end + local m = t[3] if m then n = n | (orientation[m] or 0) end + -- logs.report("orientation","0x%03X : %s",n,s) + context(n) + end, +} diff --git a/tex/context/base/mkxl/pack-ori.mkxl b/tex/context/base/mkxl/pack-ori.mkxl new file mode 100644 index 000000000..4365db3ac --- /dev/null +++ b/tex/context/base/mkxl/pack-ori.mkxl @@ -0,0 +1,97 @@ +%D \module +%D [ file=pack-ori, % was experimental +%D version=2019.07.30, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Anchoring, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Anchoring} + +\registerctxluafile{pack-ori}{autosuffix} + +\unprotect + +%D Possible options are: +%D +%D \starttabulate[|T|T|] +%D \NC orientation \NC up left down right top bottom +%D \NC vertical \NC line top bottom middle +%D \NC horizontal \NC middle flushleft flushright left right +%D \stoptabulate + +\installcorenamespace{orientation} +\installcorenamespace{orientations} + +\installcommandhandler \??orientation {orientation} \??orientation + +\setuporientation + [\c!orientation=\v!normal, + \c!horizontal=\v!normal, + \c!vertical=\v!normal] + +\appendtoks + \expandafter\chardef\csname\??orientations\currentorientation\endcsname\toorientation + orientation {\orientationparameter\c!orientation} + horizontal {\orientationparameter\c!horizontal} + vertical {\orientationparameter\c!vertical} + \relax\relax +\to \everydefineorientation + +\defineorientation[\v!normal] + +\defineorientation[\v!up] [\c!orientation=\v!up] +\defineorientation[\v!down] [\c!orientation=\v!down] +\defineorientation[\v!left] [\c!orientation=\v!left] +\defineorientation[\v!right] [\c!orientation=\v!right] +\defineorientation[\v!top] [\c!orientation=\v!top] +\defineorientation[\v!bottom][\c!orientation=\v!bottom] + +%D There will be some more helpers here. + +\permanent\def\theorientation#1% + {\numexpr + \ifcsname\??orientations#1\endcsname + \lastnamedcs + \else + \zerocount + \fi + \relax} + +\permanent\def\autoorientation#1% + {\numexpr + \ifcsname\??orientations#1\endcsname + \lastnamedcs + \else + \auto_orientation{#1}% + \fi + \relax} + +%D The \type {\immediateassignment} and \type {\immediateassigned} primitives are +%D kind of obsolete and might be dropped (if not already) from \LUAMETATEX. Local +%D scanning is, although it is a bit slower, more general. We didn't really need and +%D use these primitives in \CONTEXT\ anyway, apart from some playing around with +%D some full expansion, which made no sense in the end so it was dropped. When +%D things get that hairy it's often a good reason to look into \LUA\ variants. + +\def\auto_orientation#1% + %{\immediateassignment\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}% % quite fast + {\beginlocalcontrol\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}\endlocalcontrol % good enough + %{\localcontrolled{\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}}% % a bit slower + \csname\??orientations#1\endcsname} + +\permanent\protected\def\doifelseorientation#1% + {\ifcsname\??orientations#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +% \def\iforientationcsname#1{\ifcsname\??orientations} + +\protect \endinput diff --git a/tex/context/base/mkxl/pack-pos.mkxl b/tex/context/base/mkxl/pack-pos.mkxl new file mode 100644 index 000000000..025232eb3 --- /dev/null +++ b/tex/context/base/mkxl/pack-pos.mkxl @@ -0,0 +1,160 @@ +%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 + +\permanent\tolerant\protected\def\startpositioning[#1]#*[#2]% + {\bgroup + \ifparameters + \let\currentpositioning\empty + \or + \ifhastok={#1}% + \let\currentpositioning\empty + \setupcurrentpositioning[#1]% + \else + \edef\currentpositioning{#1}% + \fi + \or + \edef\currentpositioning{#1}% + \setupcurrentpositioning[#2]% + \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} + +\permanent\protected\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} + +\protected\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}} + +\permanent\tolerant\protected\def\position[#1]#*(#2,#3)% + {\bgroup + \ifparameter#1\or + \setupcurrentpositioning[#1]% + \fi + \removeunwantedspaces + \dowithnextbox{\pack_positioning_position_indeed{#2}{#3}}\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/tex/context/base/mkxl/pack-rul.lmt b/tex/context/base/mkxl/pack-rul.lmt new file mode 100644 index 000000000..3fa179604 --- /dev/null +++ b/tex/context/base/mkxl/pack-rul.lmt @@ -0,0 +1,248 @@ +if not modules then modules = { } end modules ['pack-rul'] = { + version = 1.001, + optimize = true, + 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-- +

An explanation is given in the history document mk.

+--ldx]]-- + +-- we need to be careful with display math as it uses shifts + +-- \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 context = context + +local nodecodes = nodes.nodecodes +local listcodes = nodes.listcodes + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist + +local boxlist_code = listcodes.box +local linelist_code = listcodes.line +local equationlist_code = listcodes.equation + +local texsetdimen = tex.setdimen +local texsetcount = tex.setcount + +local implement = interfaces.implement + +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getlist = nuts.getlist +local setlist = nuts.setlist +local getwhd = nuts.getwhd +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getdirection = nuts.getdirection +local setshift = nuts.setshift +local setwidth = nuts.setwidth +local getwidth = nuts.getwidth +local setboxglue = nuts.setboxglue +local getboxglue = nuts.getboxglue + +local hpack = nuts.hpack +local getdimensions = nuts.dimensions +local flush_node = nuts.flush + +local traversers = nuts.traversers +local nexthlist = traversers.hlist +local nextvlist = traversers.vlist +local nextlist = traversers.list + +local checkformath = false + +directives.register("framed.checkmath",function(v) checkformath = v end) -- experiment + +-- beware: dir nodes and pseudostruts can end up on lines of their own + +local function doreshapeframedbox(n) + local box = getbox(n) + local noflines = 0 + local nofnonzero = 0 + local firstheight = nil + local lastdepth = nil + local lastlinelength = 0 + local minwidth = 0 + local maxwidth = 0 + local totalwidth = 0 + local averagewidth = 0 + local boxwidth = getwidth(box) + -- if boxwidth ~= 0 and getsubtype(box) == vlist_code then + if boxwidth ~= 0 then + local list = getlist(box) + if list then + local hdone = false + for n, id, subtype, list in nextlist, list do -- no dir etc needed + local width, height, depth = getwhd(n) + if not firstheight then + firstheight = height + end + lastdepth = depth + noflines = noflines + 1 + if list then + if id == hlist_code then + if subtype == boxlist_code or subtype == linelist_code then + lastlinelength = getdimensions(list) + else + lastlinelength = width + end + hdone = true + else + lastlinelength = width + -- vdone = true + end + if lastlinelength > maxwidth then + maxwidth = lastlinelength + end + if lastlinelength < minwidth or minwidth == 0 then + minwidth = lastlinelength + end + if lastlinelength > 0 then + nofnonzero = nofnonzero + 1 + end + totalwidth = totalwidth + lastlinelength + end + end + if not firstheight then + -- done) + elseif maxwidth ~= 0 then + if hdone then + for h, id, subtype, list in nextlist, list do + if list and id == hlist_code then + -- called a lot so maybe a simple case is needed + if subtype == boxlist_code or subtype == linelist_code then + -- getdirection is irrelevant here so it will go + -- somehow a parfillskip also can get influenced + local p = hpack(list,maxwidth,'exactly',getdirection(h)) -- multiple return value + local set, order, sign = getboxglue(p) + setboxglue(h,set,order,sign) + setlist(p) + flush_node(p) + elseif checkformath and subtype == equationlist_code then + -- display formulas use a shift + if nofnonzero == 1 then + setshift(h,0) + end + end + setwidth(h,maxwidth) + end + end + end + -- if vdone then + -- for v in nextvlist, list do + -- local width = getwidth(n) + -- if width > maxwidth then + -- setwidth(v,maxwidth) + -- end + -- end + -- end + setwidth(box,maxwidth) + averagewidth = noflines > 0 and totalwidth/noflines or 0 + else -- e.g. empty math {$ $} or \hbox{} or ... + setwidth(box,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) -- traverse_list + local box = getbox(n) + local noflines = 0 + local firstheight = nil + local lastdepth = nil + if getwidth(box) ~= 0 then + local list = getlist(box) + if list then + for n in nexthlist, list do + local width, height, depth = getwhd(n) + if not firstheight then + firstheight = height + end + lastdepth = depth + noflines = noflines + 1 + end + for n in nextvlist, list do + local width, height, depth = getwhd(n) + if not firstheight then + firstheight = height + end + lastdepth = depth + noflines = noflines + 1 + end + end + end + 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 = getwidth(box) + 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 + for n, subtype in nexthlist, list do -- no dir etc needed + local l = getlist(n) + if l then + if subtype == boxlist_code or subtype == linelist_code then + lastlinelength = getdimensions(l) + else + lastlinelength = getwidth(n) + end + if lastlinelength > maxwidth then + maxwidth = lastlinelength + end + end + end + for n, subtype in nextvlist, list do -- no dir etc needed + local l = getlist(n) + if l then + lastlinelength = getwidth(n) + if lastlinelength > maxwidth then + maxwidth = lastlinelength + end + end + end + return maxwidth +end + +nodes.maxboxwidth = maxboxwidth + +implement { + name = "themaxboxwidth", + actions = function(n) context("%rsp",maxboxwidth(getbox(n))) end, -- r = rounded + arguments = "integer" +} diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl new file mode 100644 index 000000000..28fed1c51 --- /dev/null +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -0,0 +1,3001 @@ +%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}{autosuffix,optimize} + +\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 + +\permanent\tolerant\protected\def\setuplinewidth[#1]% + {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}} + +%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 + {\enforced\let\framedparameter \pack_framed_framedparameter + \enforced\let\framedparameterhash\pack_framed_framedparameterhash + \enforced\let\setupcurrentframed \pack_framed_setupcurrentframed + \inframedtrue} + +%D A helper: + +\permanent\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax} + +%D Inheritance: + +\permanent\protected\def\installinheritedframed#1% + {\normalexpanded{\mult_interfaces_install_inherited_framed + \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 + +\protected\def\mult_interfaces_install_inherited_framed#1#2#3#4#5#6#7#8#9% + {\enforced\frozen\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% + \enforced\frozen\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root + \frozen\instance\protected\def#8% + {\bgroup + \bgroup + \inframedtrue + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% + \pack_framed_process_indeed}% + \frozen\instance\protected\def#9% + {\bgroup + \inframedtrue + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% + \pack_framed_process_box_indeed}} + +\permanent\protected\def\installframedcommandhandler#1#2#3% + {\installcommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +\permanent\protected\def\installframedautocommandhandler#1#2#3% + {\installautocommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +\permanent\protected\def\installsimpleframedcommandhandler#1#2#3% + {\installsimplecommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +% for regular framed + +\setupframed + [\c!width=\v!fit, + \c!height=\v!broad, + %\c!minheight=\zeropoint, + %\c!lines=, + \c!offset=.25\exheight, % \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!anchoring=, + \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] + +\permanent\protected\def\definesimplifiedframed[#1]% no settings + {\defineframed[#1][\??simplifiedframed]% + \enforced\letcsname#1\endcsname\undefined} + +\letcsname\??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_anchoring \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_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 + {\raise\d_framed_target_dp\hpack{\frule + type fill + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_backgroundradius\space + corner {\p_framed_backgroundcorner} + \relax}} + +\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 + \orelse\ifx\p_framed_frame\v!on + \pack_framed_stroked_box_round + \fi} + +% \pack_framed_stroked_box_normal % later + +\def\pack_framed_stroked_box_round + {\raise\d_framed_target_dp\hpack{\frule + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_frameradius\space + corner {\p_framed_framecorner} + \relax}} + +% 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 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}% + \ifempty\p_framed_backgroundcolor \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. + +\newdimen\d_overlay_width +\newdimen\d_overlay_height +\newdimen\d_overlay_depth +\newdimen\d_overlay_offset +\newdimen\d_overlay_linewidth + +\let\m_overlay_region\empty + +% expandable ... in a future version the space will go (in mp one can use Overlay*) + +\mutable \def\overlaywidth {\the\d_overlay_width \space} % We preset the variables +\mutable \def\overlayheight {\the\d_overlay_height \space} % to some reasonable default +\mutable \def\overlaydepth {\the\d_overlay_depth \space} % values. +\mutable \def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) +\mutable \def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. +\mutable \def\overlayregion {\m_overlay_region} + +\mutable \def\overlayradius {\framedparameter\c!frameradius} +\mutable \def\overlaycolor {\framedparameter\c!backgroundcolor} +\mutable \def\overlaylinecolor {\framedparameter\c!framecolor} +%mutable \edef\overlaycorner {\framedparameter\c!backgroundcorner} +%mutable \edef\overlayradius {\framedparameter\c!backgroundradius} + +\permanent\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} +\permanent\def\usedoverlayheight {\dimexpr\d_overlay_height \relax} +\permanent\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} +\permanent\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} +\permanent\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax} + +%D The next register is used to initialize overlays. + +\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 + +\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded + {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% + \processcommalist[#1]\pack_framed_define_overlay_indeed} + +\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions + {\bgroup % redundant grouping + \setlayoutcomponentattribute{\v!overlay:#1}% + \setbox\scratchbox\hbox \layoutcomponentboxattribute{\the\everyoverlay#2}% + \boxxoffset\scratchbox-.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width + \boxyoffset\scratchbox-.5\dimexpr\ht\scratchbox-\d_framed_target_ht+\d_framed_target_dp\relax % not \d_overlay_height ! + \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} + +\permanent\protected\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: + +\permanent\def\doifelseoverlay#1% only tests external overlays + {\ifcsname\??overlay#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\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 + \orelse\ifcsname\??overlay\m_framed_background\endcsname + \expandafter\pack_framed_process_background_indeed_external\lastnamedcs + \fi} + +\def\pack_framed_process_background_indeed_internal#1% % : in name + {\bgroup + \setbox\b_framed_extra\hpack\bgroup + \ifzeropt\framedbackgroundoffset\else + \kern-\framedbackgroundoffset + \fi + \hbox\bgroup#1\egroup + \egroup + \wd\b_framed_extra\zeropoint + \ht\b_framed_extra\framedbackgroundheight + \dp\b_framed_extra\framedbackgrounddepth + \box\b_framed_extra + \egroup} + +\def\pack_framed_process_background_indeed_external + {\pack_framed_overlay_initialize + \pack_framed_process_background_indeed_internal} + +\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground) + {\edef\m_framed_background{#1}% + \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_set_region % experiment + {\ifx\m_overlay_region\v!yes + \edef\m_overlay_region{\reservedautoregiontag}% + \fi} + +\def\pack_framed_add_region % experiment + {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} + +\def\pack_framed_add_background + {\setbox\b_framed_normal\hpack % 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 + \ifempty\p_framed_component + \resetlayoutcomponentattribute + \else + \setlayoutcomponentattribute{\v!background:\p_framed_component}% + \fi + \let\foregroundbox\pack_framed_background_box_content + \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay + \the\everybackgroundbox % moved + \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it + \box\b_framed_normal + \hss + \egroup}} + +\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 + % We expand these once: + \edef\overlaycolor {\framedparameter\c!backgroundcolor}% + \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers + % + \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\hpack + {\kern-\d_framed_frameoffset + \raise\scratchdimen + \hpack{\ifempty\overlaylinecolor\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_opened + {\setbox\scratchbox\vpack \bgroup + \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname + \nointerlineskip % new (needed for fences) + \hpack \bgroup + \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname + \novrule + \s!width \d_framed_target_wd + \s!height\d_framed_target_ht + \s!depth \d_framed_target_dp + \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname + \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_closed + {\hpack\bgroup + \scratchdimen.5\d_framed_linewidth + \hskip\scratchdimen + \clf_framedoutline + \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax + \dimexpr\d_framed_target_ht-\scratchdimen\relax + \dimexpr\d_framed_target_dp-\scratchdimen\relax + \d_framed_linewidth + \relax + \egroup} + +\def\pack_framed_stroked_box_normal + {\ifx\p_framed_frame\v!closed + \pack_framed_stroked_box_normal_closed + \else + \pack_framed_stroked_box_normal_opened + \fi} + +\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} +\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} +\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} +\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_is_overlaid +\newconditional\c_framed_has_frame +\newconditional\c_framed_has_extra_offset +\newconditional\c_framed_text_location_none + +\newconstant \c_framed_has_strut % 0=relaxes 1=pseudostruts 2=realstruts + +%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{.25\exheight} + +\installcorenamespace{regularframedlevel} + +\permanent\protected\def\installregularframed#1% + {\defineframed[#1]} + +\permanent\protected\def\presetlocalframed[#1]% + {\defineframed[#1]} + +% \presetlocalframed[\??framed] + +\newcount\c_pack_framed_nesting + +\permanent\tolerant\protected\def\framed[#1]% + {\bgroup + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here !, seldom no argument so no need to optimize + \pack_framed_process_indeed} + +\permanent\tolerant\protected\def\startframed[#1]#*[#2]% + {\bgroup + \ifarguments + \pack_framed_initialize + \bgroup + \or + \ifhastok={#1}% + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here ! + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \fi + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#2]% here ! + \fi + \pack_framed_process_indeed + \bgroup + \ignorespaces} + +% till here + +\permanent\protected\def\stopframed + {\removeunwantedspaces + \egroup} + +\permanent\protected\def\normalframedwithsettings[#1]% + {\bgroup + \advance\c_pack_framed_nesting\plusone + \letcsname\??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 dimensions can be +%D set, only frames and backgrounds. + +%% \protected\def\fastlocalframed[#1]#2[#3]#4% 3-4 + +\permanent\protected\def\fastlocalframed[#1]#*[#2]#3% + {\bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \setbox\b_framed_normal\hbox{#3}% + \iftrialtypesetting \else + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_region + \fi + \fi + \setupcurrentframed[#2]% + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds + \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds + \edef\p_framed_frame{\framedparameter\c!frame}% + \edef\p_framed_background{\framedparameter\c!background}% + % not here, in calling macro: setups + \pack_framed_remove_depth + \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else + \ifempty\p_framed_rulethickness\else + \d_framed_linewidth\p_framed_rulethickness\relax + \fi + \pack_framed_add_outline % real or invisible frame + \fi + \ifempty\p_framed_background \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 + \iftrialtypesetting\orelse\ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \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. + +\protected\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) + {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2 + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_region + \fi + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds + \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds + \edef\p_framed_frame{\framedparameter\c!frame}% + \edef\p_framed_background{\framedparameter\c!background}% + \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else + \ifempty\p_framed_rulethickness \else + \d_framed_linewidth\p_framed_rulethickness\relax + \fi + \pack_framed_add_outline % real or invisible frame + \fi + \ifempty\p_framed_background \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 + \ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \box\b_framed_normal + \egroup} + +\protected\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 + +\permanent\tolerant\protected\def\localframed[#1]#*[#2]% + {\bgroup + \bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \setupcurrentframed[#2]% here ! + \pack_framed_process_indeed} + +\permanent\protected\def\directlocalframed[#1]% no optional + {\bgroup + \bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \pack_framed_process_indeed} + +\aliased\let\localframedwithsettings\localframed + +% done + +\defineinterfaceconstant {fr!analyze} {fr:analyze} % private option + +\let\delayedbegstrut\relax +\let\delayedendstrut\relax +\let\delayedstrut \relax + +\let\localoffset\empty +\let\localwidth \empty +\let\localheight\empty +\let\localformat\empty +\let\localstrut \empty + +\protected\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}% + \ifempty\p_framed_foregroundstyle\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\p_strut {\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_anchoring {\framedparameter\c!anchoring}% + % + \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 + \orelse\ifx\p_framed_frame\v!none % no frame, no framewidth + \setfalse\c_framed_has_frame + \else + \settrue\c_framed_has_frame + \fi + \ifconditional\c_framed_has_frame + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% + \ifempty\p_framed_rulethickness\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 + % + \ifempty\localformat + \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}% + \ifempty\p_framed_lines + \orelse\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 + % 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\p_strut\endcsname + \lastnamedcs + \else + \framed_offset_alternative_unknown + \fi + % the next check could move to strutalternative + \ifcase\c_framed_has_strut % none (not even noindent) + \enforced\let\localbegstrut\relax + \enforced\let\localendstrut\relax + \enforced\let\localstrut \relax + \or % no / overlay + \enforced\let\localbegstrut\pseudobegstrut + \enforced\let\localendstrut\pseudoendstrut + \enforced\let\localstrut \pseudostrut + \else + \enforced\let\localbegstrut\begstrut + \enforced\let\localendstrut\endstrut + \enforced\let\localstrut \strut + \fi + \ifx\p_framed_autostrut\v!yes + \enforced\let\delayedbegstrut\relax + \enforced\let\delayedendstrut\relax + \enforced\let\delayedstrut \relax + \else + \enforced\let\delayedbegstrut\localbegstrut + \enforced\let\delayedendstrut\localendstrut + \enforced\let\delayedstrut \localstrut + \enforced\let\localbegstrut \relax + \enforced\let\localendstrut \relax + \enforced\let\localstrut \relax + \fi + \ifconditional\c_framed_has_height + \enforced\let\\\pack_framed_vboxed_newline + \ifconditional\c_framed_has_width + \enforced\let\hairline\pack_framed_vboxed_hairline + \ifconditional\c_framed_has_format + \let\next\pack_framed_format_format_yes + \else + \let\next\pack_framed_format_format_nop + \fi + \else + \enforced\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 + \orelse\ifconditional\c_framed_has_width + \ifconditional\c_framed_has_format + \enforced\let\\\pack_framed_vboxed_newline + \enforced\let\hairline\pack_framed_vboxed_hairline + \let\next\pack_framed_format_format_width + \else + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline + \let\next\pack_framed_format_format_hsize + \fi + \else + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline + \let\next\pack_framed_format_format_no_size + \fi + \pack_framed_check_extra_offsets + \edef\p_framed_background{\framedparameter\c!background}% +% \ifempty\p_framed_background +% \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 + \ifempty\p_framed_orientation + \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}% + {\c_framed_has_strut\plusone} + +\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} + +\setvalue{\??framedstrutalternative\v!none}% not even pseudo struts + {\c_framed_has_strut\zerocount} + +% offsets + +\setvalue{\??framedoffsetalternative\v!none}% + {\setfalse\c_framed_has_offset + \c_framed_has_strut\plusone + \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 + \c_framed_has_strut\plusone + \settrue\c_framed_is_overlaid + \d_framed_local_offset\zeropoint} + +% \setvalue{\??framedoffsetalternative\v!strut}% +% {\setfalse\c_framed_has_offset +% \c_framed_has_strut\plustwo +% \settrue\c_framed_is_overlaid +% \d_framed_local_offset\zeropoint} + +\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000 + {\settrue \c_framed_has_offset + \c_framed_has_strut\plustwo + \setfalse\c_framed_is_overlaid + \let\localoffset\defaultframeoffset + \letframedparameter\c!offset\defaultframeoffset % brrr + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +\def\framed_offset_alternative_unknown + {\settrue \c_framed_has_offset + \c_framed_has_strut\plustwo + \setfalse\c_framed_is_overlaid + \let\defaultframeoffset\localoffset + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +\letvalue{\??framedoffsetalternative\s!unknown}\framed_offset_alternative_unknown + +% 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% + \ifempty\checkedframeoffset \zeropoint\orelse + \ifx\checkedframeoffset\v!overlay\zeropoint\orelse + \ifx\checkedframeoffset\v!none \zeropoint\orelse + \ifx\checkedframeoffset\v!frame \zeropoint\orelse + \ifx\checkedframeoffset\v!default\zeropoint\else + #2% + \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 + \orelse\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_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}} + +\def\pack_framed_reverse_box + {\ifvbox\b_framed_normal + \edef\p_linedirection{\framedparameter\c!linedirection}% + \ifx\p_linedirection\v!reverse + \reversevboxcontent\b_framed_normal + \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}% + \fi + \fi} + +\protected\def\pack_framed_finish + {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down + \pack_framed_locator_before\p_framed_location + \ifconditional\c_framed_has_format + %\ifconditional\c_framed_has_height \else + % \edef\p_profile{\framedparameter\c!profile}% + % \ifempty\p_profile\else + % \pack_framed_profile_box + % \fi + %\fi + \ifempty\p_framed_anchoring\else + \pack_framed_reverse_box + \fi + \ifx\p_framed_autowidth\v!force + \pack_framed_finish_a + \orelse\ifx\localwidth\v!fit + \ifx\p_framed_autowidth\v!yes + \pack_framed_finish_a + \else + \pack_framed_finish_b + \fi + \orelse\ifx\localwidth\v!fixed + \pack_framed_finish_b + \else + \pack_framed_finish_c + \fi + \ifconditional\c_framed_has_height \else + \edef\p_profile{\framedparameter\c!profile}% + \ifempty\p_profile\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 + \else + \edef\p_framed_minheight{\framedparameter\c!minheight}% + \ifempty\p_framed_minheight \else + \ifdim\ht\b_framed_normal<\p_framed_minheight + \ht\b_framed_normal\p_framed_minheight + \fi + \fi + \fi + \edef\p_framed_empty{\framedparameter\c!empty}% + \ifx\p_framed_empty\v!yes + \pack_framed_fake_box + \fi + \ifempty\p_framed_anchoring\else + \pack_framed_handle_anchoring + \fi + \pack_framed_stop_orientation % moved here at 2014-05-25 + \iftrialtypesetting \else + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_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\relax + \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 + % better: \pushmacro\\postprocessframebox etc + \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 + \ifempty\p_framed_background \else + \edef\p_framed_component{\framedparameter\c!component}% + \pack_framed_add_background + \fi + \fi + \pack_framed_locator_after\p_framed_location + \iftrialtypesetting \else + \ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \fi + \box\b_framed_normal + \global\frameddimensionstate % global so to be used directly afterwards ! + \ifconditional\c_framed_has_width + \ifconditional\c_framed_has_height \plusthree \else \plusone \fi + \else + \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi + \fi + \egroup + \egroup} + +%D Anchoring is experimental and was prototyped around the ctx meeting in 2018 but +%D never mede it into the core yet. It operates independent of the orientation +%D mechanism already present. It's a rather efficient feature. Best is to use +%D predefined orientations, like: +%D +%D \starttyping +%D \defineorientation[leftflushleft] [orientation=left,horizontal=flushleft] +%D +%D \framed [anchoring={leftflushleft}] {anchoring} +%D \stoptyping +%D +%D But this also works: +%D +%D \starttyping +%D \framed [anchoring={flushleft,top,up}] {anchoring} +%D \stoptyping +%D +%D When an anchoring is given (use \type {normal} for the default) you can also +%D use the \type {xanchor} and \type {yanchor} offsets. + +% because we mess with the width later on, we need double wrapping: + +\def\pack_framed_handle_anchoring + {\scratchcounter\autoorientation\p_framed_anchoring\relax + \edef\p_xanchor{\framedparameter\c!xanchor}% + \edef\p_yanchor{\framedparameter\c!yanchor}% + \setbox\b_framed_normal\hpack{\hpack % here + % using the keyword approachs works ok, don't mess with orientation + % directly here using \boxorientation ... it doesn't work that well + \s!orientation\scratchcounter + \ifempty\p_xanchor\else \s!xoffset \p_xanchor\fi + \ifempty\p_yanchor\else \s!yoffset \p_yanchor\fi + {\box\b_framed_normal}}} + +\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{\begincsname\??framedlocatorbefore#1\endcsname} +\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname} + +\newdimen\d_framed_locator_ht +\newdimen\d_framed_locator_dp +\newdimen\d_framed_locator_lo +\newdimen\d_framed_locator_ro + +\def\pack_framed_locator_set#1% + {\d_framed_locator_ht\dimexpr + #1+\d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!toffset + \relax + \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax} + +\def\pack_framed_locator_set_lo + {\global\d_framed_locator_lo\dimexpr + \d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!loffset + \relax} + +\def\pack_framed_locator_set_ro + {\global\d_framed_locator_ro\dimexpr + \d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!roffset + \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_locator_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}} % why do we pack .. dange of loosing? + +\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}} % why do we pack .. dange of loosing? + +\installframedlocator \v!low + {} + {\pack_framed_locator_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_locator_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}} % why do we pack .. dange of loosing? + +\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}} % why do we pack .. dange of loosing? + +\installframedlocator \v!lohi % maybe also \v!center + {\pack_framed_locator_before\v!middle} + {\pack_framed_locator_after \v!middle} + +\installframedlocator \v!bottom + {} + {\pack_framed_locator_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}} % why do we pack .. dange of loosing? + +\installframedlocator \v!keep % retains height/depth + {\pack_framed_remove_depth} + {\pack_framed_restore_depth} + +\newdimen\d_framed_formula + +\installframedlocator \v!formula % private, will become a more generic name + {} + {\pack_framed_locator_set\d_framed_formula + \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}} % why do we pack .. danger of loosing? + +% 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 + \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. + +\permanent\tolerant\protected\def\inframed[#1]{\framed[\c!location=\v!low,#1]} + +%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background, +%D but no content, so actually we have a sort of phantom framed box. + +%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 + +\protected\def\pack_framed_math_strut + {\Ustartmath + \triggermathstyle\c_framed_mstyle + \vphantom{(}% + \Ustopmath} + +\installcorenamespace{mathframed} + +\installframedcommandhandler \??mathframed {mathframed} \??mathframed + +\newcount\c_pack_framed_mathframed +\newtoks \t_pack_framed_mathframed + +\appendtoks + \frozen\instance\setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}% +\to \everydefinemathframed + +\protected\def\pack_framed_mathframed#1% + {\begingroup + \edef\currentmathframed{#1}% + \dosingleempty\pack_framed_mathframed_indeed} + +\def\pack_framed_math_pos + {\global\advance\c_pack_framed_mathframed\plusone + \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}% + \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}% + \xypos\pack_framed_mc_two} + +\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here + {\setupcurrentmathframed[#1]% + \c_framed_mstyle\normalmathstyle + \edef\m_framed_location{\mathframedparameter\c!location}% + \ifx\m_framed_location\v!mathematics + \enforced\let\normalstrut\pack_framed_math_pos + \orelse\ifx\m_framed_location\v!low\else + \enforced\let\normalstrut\pack_framed_math_strut + \fi + \inheritedmathframedframed\bgroup + \Ustartmath + \triggermathstyle\c_framed_mstyle + \the\t_pack_framed_mathframed + #2% + \Ustopmath + \egroup + \endgroup} + +\appendtoks + \mathraggedstatus\plustwo % makes \startalign work + \eqalignmode \zerocount % makes \startalign fit +\to \t_pack_framed_mathframed + +\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 + +\permanent\protected\def\doformatonelinerbox % beware: assumes explicit preceding bgroup + {\ifconditional\raggedonelinerstate + \expandafter\dodoformatonelinerbox + \else + \expandafter\nodoformatonelinerbox + \fi} + +\permanent\protected\def\dodoformatonelinerbox + {\afterassignment\redoformatonelinerbox + \setbox\nextbox\hbox} % maybe \hpack + +\permanent\protected\def\redoformatonelinerbox + {\aftergroup\dododoformatonelinerbox + \ignorespaces} + +\permanent\protected\def\dododoformatonelinerbox + {\hpack to \hsize % was \hbox + {\ifcase\raggedstatus\or\hss\or\hss \fi + \unhbox\nextbox \removeunwantedspaces + \ifcase\raggedstatus\or \or\hss\or\hss\fi}% + \egroup} + +\permanent\protected\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}% + \ifempty\p_framed_foregroundcolor\else\dousecolorparameter\p_framed_foregroundcolor\fi} + +\def\pack_framed_do_setups + {\ifempty\p_framed_setups \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 + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom + \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 + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\vss + \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 + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\vss + \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 + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom + \doformatonelinerbox} + +\def\pack_framed_format_format_vsize + {\vbox to \d_framed_height % no vpack .. maybe grid + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \vsize\d_framed_height + \pack_framed_do_setups + \vss + \atendofgroup\vss + \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 + \atendofgroup\hss + \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 \unprotect +%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 \protect +%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. + +\protected\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth + {\begingroup + \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi + \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax + \par + \nointerlineskip + \kern\scratchoffset + \dontleavehmode + \hrule\s!height\d_framed_linewidth\s!depth\zeropoint + \par + \kern-\d_framed_linewidth + \dontleavehmode + \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% + \hfill + \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}% + \par + \nointerlineskip + \kern\scratchoffset + \nointerlineskip + \endgraf + \nointerlineskip + \localbegstrut + \endgroup} + +\protected\def\pack_framed_hboxed_hairline % use framed dimen + {\bgroup + \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi + \ifconditional\c_framed_has_height + \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. + +\protected\def\pack_framed_vboxed_newline + {\endgraf\ignorespaces} + +\protected\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<>} +%D \showsetup{<>} +%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 + \frozen\instance\setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}% + \frozen\instance\setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }% + \frozen\instance\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} + +\protected\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}}} + +% todo: sort out first/lastline ht/dp + +\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 % \vpack + \startboxedcontent + \hsize\localhsize + % \insidefloattrue % ? better + \usebodyfontparameter\framedtextparameter + % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used + \letframedtextparameter\c!strut\v!no + \inheritedframedtextframed\bgroup + \enforced\let\\\endgraf + \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 + \framedtextparameter\c!inner + \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] + +\protected\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 + \orelse\ifinsidefloat + \egroup + \box\b_framed_normal + \else + \egroup + \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}% + \fi + \egroup} + +%D We define the general (and original) case by just saying: + +\def\pack_framed_text_check % messy dependency + {\localhsize\hsize + \ifinsidefloat \orelse \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} + +\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. + +\tolerant\protected\def\pack_framed_text_direct[#1]#*[#2]% + {\bgroup + \edef\currentframedtext{#1}% + \usebodyfontparameter\framedtextparameter + \setupcurrentframedtext[#1]% + \edef\p_framed_text_strut{\framedtextparameter\c!strut}% + \letframedtextparameter\c!strut\v!no + \inheritedframedtextframed\bgroup + \blank[\v!disable]% + \enforced\let\\\endgraf + \useframedtextstyleandcolor\c!style\c!color + \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 + \framedtextparameter\c!inner + \ifx\p_framed_text_strut\v!no + \let\pack_framed_strut\relax + \else + \let\pack_framed_strut\strut + \fi + \bgroup + \aftergroup\pack_framed_text_stop_direct + \afterassignment\ignorespaces + \afterassignment\pack_framed_strut + \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 + \frozen\instance\setuevalue{\currentframed}{\pack_framed_defined_process[\currentframed]}% +\to \everydefineframed + +\newcount\c_temp_framed_crap + +\permanent\tolerant\protected\def\pack_framed_defined_process[#1]#*[#2]% official (not much checking, todo: parent) + {\bgroup + \ifcsname\??regularframedlevel#1\endcsname + %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname + \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 + \defcsname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed + \bgroup + \edef\currentframed{#1>\the\c_pack_framed_temp}% + \pack_framed_initialize + \setupcurrentframed[#2]% here ! + \pack_framed_process_indeed} + +\aliased\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] + +\permanent\let\stopframedcontent\relax + +\permanent\tolerant\protected\def\startframedcontent[#1]% + {\bgroup + \edef\currentframedcontent{#1}% + \ifx\currentframedcontent\v!off + \enforced\let\stopframedcontent\egroup + \else + \checkframedcontentparent + \enforced\let\stopframedcontent\pack_framed_stop_content_indeed + \expandafter\pack_framed_start_content_indeed + \fi} + +\def\pack_framed_start_content_indeed + {\setbox\b_framed_normal\hpack\bgroup + \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 + \vpack\bgroup + \vskip\scratchtopoffset + \vbox\bgroup + \forgetall + \blank[\v!disable]} + +\protected\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: + +\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 + +%D Fast enough for most cases (we could do a massive \type {\ifhastok} instead): + +\permanent\protected\def\doifelseframed#1% + {\iftok{#1\c!frame }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!topframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!bottomframe}{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!leftframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!rightframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!background } {}\expandafter\secondoftwoarguments + \else \expandafter\firstoftwoarguments\fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-app.mkxl b/tex/context/base/mkxl/page-app.mkxl new file mode 100644 index 000000000..77a3bf2d6 --- /dev/null +++ b/tex/context/base/mkxl/page-app.mkxl @@ -0,0 +1,205 @@ +%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 + \frozen\instance\setuevalue{\e!start\currentfittingpage}{\startfittingpage[\currentfittingpage]}% + \frozen\instance\setuevalue{\e!stop \currentfittingpage}{\stopfittingpage}% +\to \everydefinefittingpage + +\permanent\tolerant\protected\def\startfittingpage[#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} + +\protected\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 + \enforced\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}]% + \normalexpanded{\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} + +\permanent\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}): + +%D \starttyping +%D \startTEXpage[align=normal,width=900pt,autowidth=force] +%D \framed[width=800pt,frame=off]{\number\dimexpr800pt}\par +%D \input tufte\par +%D \stopTEXpage +%D \stoptyping +%D +%D Beware: the width is the textwidth! + +\definefittingpage + [TEXpage] + [\c!align=\v!normal] % needed, else problems ! + +\permanent\protected\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. + +\permanent\tolerant\protected\def\startTEXstream[#1]% old code, to be redone + {\page + \enableoutputstream[tex]} + +\permanent\protected\def\stopTEXstream + {\disableoutputstream + \startTEXpage % [\c!align=\v!normal] + \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. + +\permanent\def\TEXapplicationfilename{\jobname-texapplication.tex} + +\permanent\protected\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 + +\permanent\tolerant\protected\def\startpagefigure[#1]#*[#2]% + {\bgroup + \setupexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay,#2]% + \startTEXpage[\c!offset=\namedexternalfigureparameter{\v!page:\v!figure}\c!offset,\c!align=\v!normal]% + \externalfigure[#1]\ignorespaces} % so we can put some text below the graphic + +\permanent\protected\def\stoppagefigure + {\stopTEXpage + \egroup} + +\permanent\tolerant\protected\def\pagefigure[#1]#*[#2]% + {\page_figures_start[#1][#2]\stoppagefigure} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-bck.mkxl b/tex/context/base/mkxl/page-bck.mkxl new file mode 100644 index 000000000..71036e3e4 --- /dev/null +++ b/tex/context/base/mkxl/page-bck.mkxl @@ -0,0 +1,703 @@ +%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 + +\permanent\protected\def\initializepagebackgrounds + {\setfalse\c_page_backgrounds_new + \setfalse\c_page_backgrounds_new_right + \setfalse\c_page_backgrounds_new_left + \setfalse\c_page_backgrounds_some} + +%D We keep calculations and checks to a minimum and also try to minimize +%D the amount of tracing due to expansion. + +\let\currentotrbackground\empty + +%D This is the only spot where we have a low level dependency on the way +%D parent chains are defined but we want the speed. + +\protected\def\page_backgrounds_check_background + {\ifcsname\??framed\currentotrbackground:\c!background\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifempty\page_background_temp + \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{\letcsname\currentotrbackground\endcsname\relax } +\def\page_backgrounds_set_nop{\letcsname\currentotrbackground\endcsname\undefined} + +\protected\def\page_backgrounds_check#1% + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \page_backgrounds_check_background} + +\permanent\def\doifelsesomebackground#1% + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifsomebackgroundelse\doifelsesomebackground + +\permanent\def\doifsomebackground#1% + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +%D The background mechanism falls back on the \type {\framed} macro. This means +%D that all normal frame and overlay features can be used. + +\def\page_backgrounds_add_to_box#1% area + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\page_backgrounds_add_to_box_indeed + \else + \expandafter\gobblefourarguments + \fi#1} + +%D We don't need the dimensions here as this is a real framed but the question is: +%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only +%D for hidden). + +\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero + {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}% + \ifempty\p_page_backgrounds_setups \else + \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! + \fi + % #2 has the right dimensions already + \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground) + + +%D There are quite some backgrounds. At the bottom layer, there is the {\em paper} +%D background. This one is only used for special purposes, like annotations to +%D documents. + +\def\page_backgrounds_add_to_print#1% + {\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight} + +%D The page backgrounds can be put behind the {\em left page}, the {\em right page} +%D or {\em each page}. As with the paper background, these are calculated on each +%D page. + +\def\page_backgrounds_add_to_paper#1% + {\doifbothsidesoverruled + {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% + {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% + {\page_backgrounds_add_to_box\v!leftpage #1\paperwidth\paperheight}% + \page_backgrounds_add_to_box\v!page#1\paperwidth\paperheight} + +%D Then there are the 25 areas that make up the layout: {\em top, header, text, +%D footer, bottom} times {\em left edge, left margin, text, right margin, right +%D edge}. These are only recalculated when they change or when the \type {status} +%D is set to \type {repeat}. + +\newbox\leftbackground % todo: rename +\newbox\rightbackground % todo: rename + +%D Finaly there is an aditional {\em text} background, again useful for special +%D purposes only. This one is calculated each time. The hidden backgrounds are not +%D meant for users! + +\newconditional\c_page_backgrounds_hidden_enabled + +\def\page_backgrounds_add_to_text#1% + {\ifconditional\c_page_backgrounds_hidden_enabled + \page_backgrounds_add_to_box\v!hidden#1\makeupwidth\textheight % mine ! + \fi + \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight} + +%D The next couple of macros implement the area backgrounds. As said, these are +%D cached in dedicated boxes. The offsets and depth of the page are used for +%D alignment purposes. + +%newdimen\pageoffset % bleed +%newdimen\pagedepth % built-in + +%D We need a bit more clever mechanism in order to handle layers well. This means +%D that we cannot calculate both background at the same time since something may +%D have changed halfway a page. + +%D Margin swapping has been simplified: see mkii code in case of regression. +%D Calculation is delayed till the page anyway so the state is known. + +\def\page_backgrounds_recalculate + {\global\settrue\c_page_backgrounds_new} + +\def\page_backgrounds_set_boxes + {\ifconditional\c_page_backgrounds_new + \page_backgrounds_set_boxes_r + \fi + \doifbothsides + \page_backgrounds_set_boxes_a + \page_backgrounds_set_boxes_b + \page_backgrounds_set_boxes_c + \ifx\p_page_backgrounds_state\v!repeat\else + \global\setfalse\c_page_backgrounds_new + \fi} + +\def\page_backgrounds_set_boxes_r + {\global\settrue\c_page_backgrounds_new_right + \global\settrue\c_page_backgrounds_new_left + \global\setbox\leftbackground\emptybox + \global\setbox\rightbackground\emptybox} + +\def\page_backgrounds_set_boxes_a + {\ifconditional\c_page_backgrounds_new_left + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\leftbackground % \conditionalfalse + \global\setfalse\c_page_backgrounds_new_left + \global\setfalse\c_page_backgrounds_new_right + \fi} + +\def\page_backgrounds_set_boxes_b + {\ifconditional\c_page_backgrounds_new_left + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\leftbackground + \global\setfalse\c_page_backgrounds_new_left + \fi} + +\def\page_backgrounds_set_boxes_c + {\ifconditional\c_page_backgrounds_new_right + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\rightbackground + \global\setfalse\c_page_backgrounds_new_right + \fi} + +\def\page_backgrounds_add_to_main#1% todo: dimension spec + {\ifconditional\c_page_backgrounds_some + \page_backgrounds_set_boxes + \setbox#1\vpack + {\offinterlineskip + \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}% + \box#1}% + \fi} + +\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE +\newdimen\pagebackgroundvoffset +\newdimen\pagebackgroundoffset % used elsewhere +\newdimen\pagebackgrounddepth +\newdimen\pagebackgroundcompensation + +\def\page_backgrounds_set_offsets % used in menus (we can use ifcsname's here) + {\ifconditional\c_page_backgrounds_some \ifconditional\c_page_backgrounds_new + \page_backgrounds_set_offsets_indeed % indirect, less tracing + \fi \fi} + +\def\page_backgrounds_set_offsets_indeed + {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname + \page_backgrounds_set_offsets_yes + \orelse\ifcsname\??layoutbackgrounds\v!text\endcsname + \page_backgrounds_set_offsets_yes + \else + \page_backgrounds_set_offsets_nop + \fi} + +\def\page_backgrounds_set_offsets_nop + {\global\pagebackgroundhoffset \zeropoint + \global\pagebackgroundvoffset \zeropoint + \global\pagebackgrounddepth \zeropoint + \global\pagebackgroundcompensation\zeropoint} + +\def\page_backgrounds_set_offsets_yes + {\global\pagebackgroundoffset \d_page_backgrounds_depth + \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax + \ifzeropt\pagebackgroundcompensation + \page_backgrounds_set_offsets_nop + \else + \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname + \global\pagebackgroundhoffset\zeropoint + \orelse\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname + \global\pagebackgroundhoffset\zeropoint + \else + \global\pagebackgroundhoffset\pagebackgroundcompensation + \fi + \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname + \global\pagebackgroundvoffset\zeropoint + \global\pagebackgrounddepth \zeropoint + \orelse\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname + \global\pagebackgroundvoffset\zeropoint + \global\pagebackgrounddepth \zeropoint + \else + \global\pagebackgroundvoffset\pagebackgroundcompensation + \global\pagebackgrounddepth \d_page_backgrounds_depth + \fi + \fi} + +\appendtoks + \page_backgrounds_set_offsets +\to \everybeforepagebody + +\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins + +%D The swapping here is pretty nasty! Maybe we should find another way some day but +%D for now we tweak. + +\def\page_backgrounds_set_box#1% #2% + {\global\setbox#1\vpack + {\dontcomplain + \swapmargins + \ifconditional\swapbackgroundmargins + \doifelsemarginswap \donothing + {\enforced\swapcsvalues\v!rightmargin\v!leftmargin + \enforced\swapcsvalues\v!rightedge \v!leftedge}% + \fi + \calculatereducedvsizes + \offinterlineskip + % \ifconditional#2\relax + % \doswapmargins % hm, this one gets nilled in \swapmargins anyway + % \fi + \ifdim\topheight>\zeropoint + \kern\dimexpr-\topheight-\topdistance\relax + \page_backgrounds_set_box_row\v!top\topheight + \kern\topdistance + \fi + \ifdim\headerheight>\zeropoint + \page_backgrounds_set_box_row\v!header\headerheight + \kern\headerdistance + \fi + \ifdim\textheight>\zeropoint + \page_backgrounds_set_box_row\v!text\textheight + \fi + \ifdim\footerheight>\zeropoint + \kern\footerdistance + \page_backgrounds_set_box_row\v!footer\footerheight + \fi + \ifdim\bottomheight>\zeropoint + \kern\bottomdistance + \page_backgrounds_set_box_row\v!bottom\bottomheight + \fi + \vfilll}% + \smashbox#1} + +\def\page_backgrounds_set_box_row#1#2% maybe helper + {\setbox\scratchbox\vpack to #2 + \bgroup\hpack\bgroup + \goleftonpage + \ifdim\leftedgewidth>\zeropoint + \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname + \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2% + \else + \kern\leftedgewidth + \fi + \kern\leftedgedistance + \fi + \ifdim\leftmarginwidth>\zeropoint + \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname + \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2% + \else + \kern\leftmarginwidth + \fi + \kern\leftmargindistance + \fi + \ifcsname\??layoutbackgrounds#1\v!text\endcsname + \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2% + \else + \kern\makeupwidth + \fi + \ifdim\rightmarginwidth>\zeropoint + \kern\rightmargindistance + \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname + \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2% + \else + \kern\rightmarginwidth + \fi + \fi + \ifdim\rightedgewidth>\zeropoint + \kern\rightedgedistance + \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname + \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2% + \else + \kern\rightedgewidth + \fi + \fi + \egroup\egroup + \wd\scratchbox\zeropoint + \box\scratchbox\relax} + +% these are fake framed .. maybe it's nicer to honor foreground here as well +% but it's probably a slow downer + +\def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height + {\begingroup + \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}% + \ifempty\p_page_backgrounds_setups \else + \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! + \fi + \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}% + \ifempty\p_page_backgrounds_command + \expandafter\page_backgrounds_set_box_cell_nop + \else + \expandafter\page_backgrounds_set_box_cell_yes + \fi#3#4% + \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox + \endgroup} + +\def\page_backgrounds_set_box_cell_nop#1#2% + {\setbox\scratchbox\emptyvbox + \wd\scratchbox#1% + \ht\scratchbox#2} + +\def\page_backgrounds_set_box_cell_yes#1#2% + {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}% + \dp\scratchbox\zeropoint} + +%D The background mechanism is quite demanding in terms or resources. We used to +%D delay these definitions till runtime usage, but since today's \TEX's are large, +%D we now do the work on forehand. +%D +%D \starttyping +%D \setupbackgrounds [settings] +%D \setupbackgrounds [paper,page,text,..] [settings] +%D \setupbackgrounds [top,...] [leftedge,...] [settings] +%D \stoptyping +%D +%D \showsetup{setupbackgrounds} +%D +%D Because the number of arguments runs from one to three, we need to check +%D for it. + +\newtoks\everybackgroundssetup + +\permanent\tolerant\protected\def\setupbackgrounds[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreeoptionals + \or + \expandafter\page_backgrounds_setup_basics + \or + \expandafter\page_backgrounds_setup_single + \or + \expandafter\page_backgrounds_setup_double + \fi[#1][#2][#3]} + +\newdimen\d_page_backgrounds_offset +\newdimen\d_page_backgrounds_depth + +\appendtoks + \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}% + \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }% + \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }% + \global\d_page_backgrounds_offset\ifempty\p_offset\zeropoint\else\p_page_backgrounds_offset\fi + \global\d_page_backgrounds_depth \ifempty\p_depth \zeropoint\else\p_page_backgrounds_depth \fi + \global\pagebackgroundoffset\d_page_backgrounds_offset\relax + \global\pagebackgrounddepth \d_page_backgrounds_depth \relax + \ifx\p_page_backgrounds_state\v!stop + \global\setfalse\c_page_backgrounds_new + \else + \global\settrue \c_page_backgrounds_new + \fi +\to \everybackgroundssetup + +\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage} +\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage} +\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge} + +\protected\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up + {\global\settrue\c_page_backgrounds_some + \def\page_backgrounds_setup_step##1% + {\doifelseinset{##1}\v_page_backgrounds_double_set + {\page_backgrounds_setup_and_check{##1}{#3}} + {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}% + \processcommacommand[#2]\page_backgrounds_setup_step_nested}}% + \processcommacommand[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup} + +\protected\def\page_backgrounds_setup_single[#1][#2][#3]% + {\global\settrue\c_page_backgrounds_some + \doifelsecommon{#1}\v_page_backgrounds_single_set + {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}% + \processcommacommand[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup}% + {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}} + +\protected\def\page_backgrounds_setup_basics[#1][#2][#3]% + {\setupframed[\??layoutbackgrounds][#1]% + \the\everybackgroundssetup} + +\protected\def\page_backgrounds_setup_and_check#1#2% tag settings + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \setupframed[\currentotrbackground][#2]% + \page_backgrounds_check_background} + +%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level +%D framed object associated. + +\definesimplifiedframed[\??layoutbackgrounds\v!paper] +\definesimplifiedframed[\??layoutbackgrounds\v!page] +\definesimplifiedframed[\??layoutbackgrounds\v!leftpage] +\definesimplifiedframed[\??layoutbackgrounds\v!rightpage] + +\definesimplifiedframed[\??layoutbackgrounds\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!hidden] + +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge] + +\setupbackgrounds + [\v!page] + [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere + \c!depth=\zeropoint] + +%D General setup: + +\setupbackgrounds + [\c!state=\c!start] + +%D The hidden layer can be populated by extending the following comma separated +%D list. This only happens in core modules. + +% todo page-2 .. page+2 achter pagina -> bleed +% spread-2 .. spread+2 achter spread -> spread (repeat 2 times) + +\permanent\protected\def\enablehiddenbackground + {\global\settrue\c_page_backgrounds_hidden_enabled + \global\settrue\c_page_backgrounds_some + \page_backgrounds_recalculate} + +\permanent\protected\def\disablehiddenbackground + {\global\setfalse\c_page_backgrounds_hidden_enabled} + +\def\hiddenbackgroundlist + {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2} + +\defineoverlay[\v!text-2][\positionregionoverlay\textanchor{\v!text-2}] % no new anchor, we share text +\defineoverlay[\v!text-1][\positionregionoverlay\textanchor{\v!text-1}] +\defineoverlay[\v!text+1][\positionregionoverlay\textanchor{\v!text+1}] +\defineoverlay[\v!text+2][\positionregionoverlay\textanchor{\v!text+2}] + +\setupbackgrounds + [\v!hidden] + [\c!background=\hiddenbackgroundlist] + +%D Because we haven't really set up backgrounds yet, we set the main efficiency +%D switch to false. + +\setfalse\c_page_backgrounds_some + +%D Sometimes you have a document wide (page) background but need to overload it +%D locally. In such case (at least in my experience) the only values that get set +%D are the background and backgroundcolor (if set at all). A full inheritance chain +%D would complicate things because then we need to use named backgrounds which in +%D turn will make this mechanism slower. I considered independent local backgrounds +%D but that also complicates the code (not that much) but isolation means that we +%D need to set more parameters each time. The following simple approach proabbly +%D suits most usage. +%D +%D \starttyping +%D \starttext +%D \setupbackgrounds[page][background=color,backgroundcolor=red] +%D \input tufte \page +%D \setupbackgrounds[page][background=,backgroundcolor=] +%D \input tufte \page +%D \setupbackgrounds[page][background=color,backgroundcolor=red] +%D \input tufte \page +%D \pushbackground[page] +%D \setupbackgrounds[page][background=color,backgroundcolor=green] +%D \input tufte \page +%D \popbackground +%D \input tufte \page +%D \stoptext +%D \stoptyping + +\permanent\protected\def\pushbackground[#1]% + {\pushmacro\popbackground + \edef\currentotrbackground{\??layoutbackgrounds#1}% + \enforced\permanent\protected\edef\popbackground + {\setupframed + [\currentotrbackground] + [\c!background=\namedframedparameter{\currentotrbackground}\c!background, + \c!backgroundcolor=\namedframedparameter{\currentotrbackground}\c!backgroundcolor]% + \page_backgrounds_check_background + \popmacro\popbackground}% + \setupframed + [\currentotrbackground] + [\c!background=,\c!backgroundcolor=]% + \page_backgrounds_check_background} + +\permanent\let\popbackground\relax + +\protect \endinput + +% %D The next series is used in local (for instance floating) backgrounds. +% +% \installsimplifiedframed{\??layoutbackgrounds\v!local} +% +% \getparameters +% [\??layoutbackgrounds\v!local] +% [\c!component=local, +% \c!background=\localbackgroundlist] +% +% \def\localbackgroundlist +% {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2} +% +% \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] % todo share +% \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}] +% \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}] +% \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}] +% +% \def\page_backgrounds_add_local_to_box +% {\ifconditional\c_page_backgrounds_hidden_enabled +% \expandafter\page_backgrounds_add_local_to_box_indeed +% \else +% \expandafter\gobbleoneargument +% \fi} +% +% \def\page_backgrounds_add_local_to_box_indeed#1% +% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}% +% \global\advance\localpositionnumber\plusone} % afterwards ! +% +% \let\page_backgrounds_add_local_to_box\gobbleoneargument + +% Test how previous macro behaves with depth: +% +% \startcolumnset +% \input tufte +% \placefigure{none}{\framed[lines=5]{xxx}} +% \input tufte +% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate} +% \input tufte +% \stopcolumnset + diff --git a/tex/context/base/mkxl/page-box.mklx b/tex/context/base/mkxl/page-box.mklx new file mode 100644 index 000000000..9b6868b04 --- /dev/null +++ b/tex/context/base/mkxl/page-box.mklx @@ -0,0 +1,289 @@ +%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 skipping tokens which is nicer for +%D tracing. Centering the paper area on the print area is determined by the \type +%D {top}, \type {bottom}, \type {left} and \type {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% + \orelse\ifdim\printpaperwidth>\wd#box\relax + \page_boxes_apply_center_indeed#box% + \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 + {\unless\ifzeropt\topoffset + \expandafter\page_boxes_apply_offset_indeed + \orelse\ifzeropt\backoffset + \expandafter\gobbleoneargument + \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 + \orelse\ifnum\layoutparameter\c!ny>\plusone + \expandafter\page_boxes_apply_replicate_indeed + \else + \expandafter\gobbleoneargument + \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} + +\aliased\let\page_boxes_apply_negate\negatecolorbox + +\def\page_boxes_apply_negate_print#box% + {\ifconditional\c_page_target_print_negate + \page_boxes_apply_negate#box% + \orelse\ifconditional\c_page_target_paper_negate + \page_boxes_apply_negate#box% + \fi} + +\let\p_page_layouts_scale\relax +\let\p_page_layouts_sx \relax +\let\p_page_layouts_sy \relax + +\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 + \vkern\topspace + \hkern\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}% + \box#1}% + \dp#1\zeropoint} + +%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#2% + {\scratchdepth\dp#2% + \dp#2\strutdepth + \anch_mark_flow_only{#2}% + \dp#2\scratchdepth + #1#2} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-brk.mkxl b/tex/context/base/mkxl/page-brk.mkxl new file mode 100644 index 000000000..a8fe10d87 --- /dev/null +++ b/tex/context/base/mkxl/page-brk.mkxl @@ -0,0 +1,483 @@ +%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 + \orelse\ifcsname\??pagebreaks\page_breaks_current_option\endcsname + \expandafter\page_breaks_handle\lastnamedcs + \else + \page_breaks_unknown + \fi} + +\def\page_breaks_handle_direct#1% + {\begincsname\??pagebreakmethod#1\endcsname} + +\permanent\protected\def\installpagebreakmethod#1#2% low level definer + {\setvalue{\??pagebreakmethod#1}{#2}} + +\aliased\let\installpagebreakhandler\installpagebreakmethod % will go + +\permanent\tolerant\protected\def\definepagebreak[#1]#*[#2]% + {\setvalue{\??pagebreaks#1}{#2}} + +\appendtoks + \flushnotes +\to \everybeforepagebreak + +\permanent\tolerant\protected\def\pagebreak[#1] + {\par % else no vertical penalties, 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 + \ifparameter#1\or + \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} + +\aliased\let\page\pagebreak + +\permanent\protected\def\usepageparameter#1% + {\edef\m_page_breaks_asked{#1\c!page}% + \ifx\m_page_breaks_asked\empty\else + \pagebreak[\m_page_breaks_asked]% + \fi} + +\permanent\protected\def\dousepageparameter#1% + {\edef\m_page_breaks_asked{#1}% + \ifx\m_spac_align_asked\empty\else + \pagebreak[\m_page_breaks_asked]% + \fi} + +\permanent\protected\def\resetpagebreak % used elsewhere too + {\global\settrue\c_page_breaks_enabled} + +\permanent\protected\def\simplifypagebreak % to be used grouped ! + {\enforced\permanent\protected\def\pagebreak[##1]{\goodbreak}} + +\protected\def\disablepagebreaks % to be used grouped ! + {\enforced\let\page_breaks_process\gobbleoneoptional} + +\installpagebreakmethod \s!dummy + {\page_otr_command_flush_all_floats + \page_otr_command_next_page + \page_otr_insert_dummy_page} + +\installpagebreakmethod \v!frame + {\page + \begingroup + \showframe + \page[\v!empty] + \endgroup} + +\protected\def\page_breaks_unknown % how often called ? + {\doifelseinstring{+}\page_breaks_current_option + {\page_otr_command_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_command_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_command_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_command_flush_all_floats + \page_otr_command_next_page_and_inserts + \doifbothsidesoverruled\donothing\page_reset_marks_and_insert_dummy\donothing} + +\installpagebreakmethod \v!right + {\page_otr_command_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 + \ifcase\modulonumber\plusfour\realpageno\else + \page_breaks_handle_direct\v!yes + \doloop + {\ifcase\modulonumber\plusfour\realpageno\relax + \exitloop + \else + \page_breaks_handle_direct\v!empty + \fi}% + \fi + \fi} + +\installpagebreakmethod \v!last + {\page_otr_command_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} + +\installpagebreakmethod{xy}% for Mojca + {\page_breaks_handle_direct\v!yes + \scratchcounterone \numexpr\rootlayouttargetparameter\c!nx*\rootlayouttargetparameter\c!ny\relax + \scratchcountertwo \luaexpr{math.mod(\the\realpageno-1,\the\scratchcounterone)}\relax + \scratchcounterthree\numexpr\scratchcounterone-\scratchcountertwo\relax + \dorecurse\scratchcounterthree{\page_breaks_handle_direct\v!empty}} + +% 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 + \orelse\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname + %\expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname + \lastnamedcs + \orelse\ifcsname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname + \lastnamedcs + \fi} + +\def\page_breaks_columns_handle_direct#1% + {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname} + +\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action + {\setvalue{\??columnbreakmethod#1:#2}{#3}} + +\aliased\let\installcolumnbreakhandler\installcolumnbreakmethod % will go + +\permanent\tolerant\protected\def\definecolumnbreak[#1]#*[#2]% + {\setvalue{\??columnbreaks#1}{#2}} + +%D So, page ornaments are reset after a pagebreak command, unless set! + +\permanent\tolerant\protected\def\columnbreak[#1]% + {\par % else no vertical penalties + \begingroup + \the\everybeforecolumnbreak + \ifparameter#1\or + \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} + +\aliased\let\column\columnbreak + +\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 + +\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} + +\permanent\tolerant\protected\def\checkpage[#1]#*[#2]% + {\relax % needed before \if + \endgraf + \triggerpagebuilder + \relax + \ifconditional\c_page_breaks_enabled + \begingroup + \edef\currentpagechecker{#1}% + \setupcurrentpagechecker[#2]% + \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 + \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 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 + \orelse\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 + \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] + +\permanent\tolerant\protected\def\testpage [#1]#*[#2]{\normalexpanded{\checkpage[\s!unknown:1][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} % +\permanent\tolerant\protected\def\testpageonly[#1]#*[#2]{\normalexpanded{\checkpage[\s!unknown:2][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} % no penalties added to the mvl +\permanent\tolerant\protected\def\testpagesync[#1]#*[#2]{\normalexpanded{\checkpage[\s!unknown:3][\c!lines=#1,\c!offset=\ifparameter#2\or#2\else\zeropoint\fi]}} % force sync + +%D Test column breaks. + +\permanent\tolerant\protected\def\testcolumn[#1]#*[#2]% + {\ifdefined\page_otr_command_test_column + \ifparameter#2\or + \page_otr_command_test_column[#1][#2]% + \else + \page_otr_command_test_column[#1][\zeropoint]% + \fi + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-col.mkxl b/tex/context/base/mkxl/page-col.mkxl new file mode 100644 index 000000000..5634589fa --- /dev/null +++ b/tex/context/base/mkxl/page-col.mkxl @@ -0,0 +1,163 @@ +%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. + +%D DO WE STILL NEED THESE? + +\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 % already in core-ini.mkiv +\newcount\mofcolumns \mofcolumns\plusone + +\newconstant\columndirection % 0:lr 1:rl + +\setnewconstant\maxnofcolumns 50 +\setnewconstant\allocatednofcolumns 0 + +\newdimen\columnwidth +\newdimen\columndistance + +%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} + +\permanent\protected\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} + +\mutable\def\currentcolumn{1} + +\immutable\def\firstcolumnbox {\columntextbox\plusone} +\immutable\def\currentcolumnbox{\columntextbox\mofcolumns} +\immutable\def\lastcolumnbox {\columntextbox\nofcolumns} + +\immutable\def\firsttopcolumnbox {\columntopbox \plusone} +\immutable\def\currenttopcolumnbox{\columntopbox \mofcolumns} +\immutable\def\lasttopcolumnbox {\columntopbox \nofcolumns} + +\permanent\def\columntextbox#1{\csname\??columntext \number#1\endcsname} +\permanent\def\columnfootbox#1{\csname\??columnfooter\number#1\endcsname} +\permanent\def\columntopbox #1{\csname\??columntop \number#1\endcsname} +\permanent\def\columnbotbox #1{\csname\??columnbottom\number#1\endcsname} + +\permanent\protected\def\columnsettextbox{\global\setbox\columntextbox} +\permanent\protected\def\columnsetfootbox{\global\setbox\columnfootbox} +\permanent\protected\def\columnsettopbox {\global\setbox\columntopbox} +\permanent\protected\def\columnsetbotbox {\global\setbox\columnbotbox} + +\permanent\protected\def\columngettextbox {\copy\columntextbox} +\permanent\protected\def\columngetfootbox {\copy\columnfootbox} +\permanent\protected\def\columngettopbox {\copy\columntopbox} +\permanent\protected\def\columngetbotbox {\copy\columnbotbox} + +\permanent\protected\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}} +\permanent\protected\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}} +\permanent\protected\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}} +\permanent\protected\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. + +\permanent\protected\def\dohandleallcolumnscs#1{\let\page_columns_action #1\page_columns_all_indeed} +\permanent\protected\def\dohandleallcolumns #1{\def\page_columns_action{#1}\page_columns_all_indeed} + +\permanent\protected\def\dohandlerevcolumnscs#1{\let\page_columns_action #1\page_columns_rev_indeed} +\permanent\protected\def\dohandlerevcolumns #1{\def\page_columns_action{#1}\page_columns_rev_indeed} + +\permanent\protected\def\dohandlemidcolumnscs#1{\let\page_columns_action #1\page_columns_mid_indeed} +\permanent\protected\def\dohandlemidcolumns #1{\def\page_columns_action{#1}\page_columns_mid_indeed} + +\protected\def\page_columns_all_indeed + {\mofcolumns\plusone + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_all_next + \fi} + +\protected\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} + +\protected\def\page_columns_rev_indeed + {\mofcolumns\nofcolumns + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns>\plusone + \expandafter\page_columns_rev_prev + \fi} + +\protected\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} + +\protected\def\page_columns_mid_indeed + {\mofcolumns\plustwo + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_mid_next + \fi} + +\protected\def\page_columns_mid_next + {\edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \advance\mofcolumns\plusone + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_mid_next + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-com.mkxl b/tex/context/base/mkxl/page-com.mkxl new file mode 100644 index 000000000..a7d8aaba7 --- /dev/null +++ b/tex/context/base/mkxl/page-com.mkxl @@ -0,0 +1,180 @@ +%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=]} + +\protected\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}} + +\protected\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}} + +\permanent\protected\setvalue{\e!start\v!pagecomment}% + {\global\settrue\c_page_comment_enabled + \grabbufferdatadirect\v!pagecomment{\e!start\v!pagecomment}{\e!stop\v!pagecomment}} + +\aliased\letcsname\e!stop\v!pagecomment\endcsname\relax + +\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/tex/context/base/mkxl/page-cst.mkxl b/tex/context/base/mkxl/page-cst.mkxl new file mode 100644 index 000000000..a033d740b --- /dev/null +++ b/tex/context/base/mkxl/page-cst.mkxl @@ -0,0 +1,789 @@ +%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}{} + +\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 + \frozen\instance\setuevalue{\e!start\currentpagegrid}{\startpagegrid[\currentpagegrid]}% + \frozen\instance\setuevalue{\e!stop \currentpagegrid}{\stoppagegrid}% + \clf_definecolumnset { + name {\currentpagegrid}% + }% +\to \everydefinepagegrid + +\newdimen\d_page_grd_column_width +\newdimen\d_page_grd_max_height +\newdimen\d_page_grd_max_width +\newdimen\d_page_grd_distance + +\newdimen\d_page_grd_reserved_height +\newdimen\d_page_grd_reserved_width +\newcount\c_page_grd_reserved_state + +\newdimen\d_page_grd_gap_height + +\newcount\c_page_grd_n_of_left +\newcount\c_page_grd_n_of_right +\newcount\c_page_grd_n_of_rows +\newcount\c_page_grd_first_column +\newcount\c_page_grd_last_column + +\newbox \b_page_grd_collected +\newbox \b_page_grd_column_rest +\newbox \b_page_grd_column + +%D All the parameters are mandate! + +\permanent\tolerant\protected\def\setuppagegridlines[#1]#*[#2]#*[#3]#*[#4]% id page col value + {\clf_setcolumnsetlines{name {#1} page #2 column #3 value #4}} + +\permanent\tolerant\protected\def\setuppagegridstart[#1]#*[#2]#*[#3]#*[#4]% id page col value + {\clf_setcolumnsetstart{name {#1} page #2 column #3 value #4}} + +\protected\def\page_grd_check + {\dorecurse{\numexpr\pagegridparameter\c!nleft+\pagegridparameter\c!nright} + {\page_grd_check_column{##1}}} + +\protected\def\page_grd_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 + \ifempty\p_distance\else + distance \p_distance + \fi + \ifempty\p_width\orelse\ifx\p_width\v!auto\else + width \p_width + \fi + }} + +\appendtoks + \dorecurse{\numexpr\pagegridparameter\c!nleft+\pagegridparameter\c!nright}% + {\chaintocurrentpagegrid{\currentpagegrid:#1}}% +\to \everydefinepagegrid + +\permanent\tolerant\protected\def\startpagegrid[#1]#*[#2]% + {\bgroup + \let\page_grd_start\page_grd_start_dummy + \ifarguments + \let\currentpagegrid\empty + \or + \ifhastok={#1}% + \let\currentpagegrid\empty + \setupcurrentpagegrid[#1]% + \else + \def\currentpagegrid{#1}% + \fi + \or + \edef\currentpagegrid{#1}% + \setupcurrentpagegrid[#2]% + \fi + \usepageparameter\pagegridparameter + \c_page_grd_n_of_left \pagegridparameter\c!nleft\relax + \c_page_grd_n_of_right\pagegridparameter\c!nright\relax + \c_page_grd_n_of_rows \pagegridparameter\c!lines\relax + \d_page_grd_max_width \pagegridparameter\c!maxwidth\relax + \d_page_grd_max_height\pagegridparameter\c!maxheight\relax + \d_page_grd_distance \pagegridparameter\c!distance\relax + % + \ifcase\c_page_grd_n_of_rows + \getrawnoflines{\dimexpr\d_page_grd_max_height-\strutheight+\topskip\relax}% + \c_page_grd_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_grd_n_of_rows + nofleft \c_page_grd_n_of_left + nofright \c_page_grd_n_of_right + lineheight \strutht + linedepth \strutdp + \ifx\p_width\v!auto + % sets \d_page_grd_column_width + \else + width \p_width + \fi + distance \d_page_grd_distance + maxwidth \d_page_grd_max_width + }% + % + \page_grd_check + % + \clf_flushcolumnsetareas{\currentpagegrid}\relax + \setupoutputroutine[\s!pagegrid]% + \page_grd_command_set_hsize + \page_grd_command_set_vsize + % + \columnwidth \d_page_grd_column_width + \columndistance\d_page_grd_distance + \nofcolumns \c_page_grd_n_of_left % not always ok + \textwidth \d_page_grd_column_width % kind of redundant but we had it so ... + % + }%\begingroup} + +\def\page_grd_start_dummy[#1][#2]% + {\let\page_grd_stop\egroup} + +\permanent\protected\def\stoppagegrid + {\page_grd_stop} + +\def\page_grd_stop + {\endgraf % needed, else wrong vsize in one par case + \vfill % otherwise weird \placenotes[endnotes] + \page_grd_command_set_vsize % needed + \penalty\c_page_otr_eject_penalty + \page_grd_command_flush_page + \page_otr_fill_and_eject_page + \page_grd_command_set_vsize % why here + \egroup + \page_otr_command_set_vsize + \page_otr_command_set_hsize} + +\permanent\protected\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} + +\permanent\tolerant\protected\def\setpagegrid[#1]% + {\begingroup + \letdummyparameter\c!c\zerocount + \letdummyparameter\c!r\zerocount + \letdummyparameter\c!method\v!here + \letdummyparameter\c!option\v!none + \getdummyparameters[#1]% + \dowithnextboxcs\page_grd_set_indeed\hbox} + +\def\page_grd_set_indeed + {\clf_checkcolumnset { + name {\currentpagegrid} + c \dummyparameter\c!c + r \dummyparameter\c!r + box \nextbox + method {\dummyparameter\c!method} + option {\dummyparameter\c!option} + }% + \ifcase\c_page_grd_reserved_state + \setbox\nextbox\vpack to \d_page_grd_reserved_height \bgroup + \vss + \hpack to \d_page_grd_reserved_width \bgroup + \box\nextbox + \hss + \egroup + \vss + \egroup + \wd\nextbox\d_page_grd_reserved_width + \clf_putincolumnset { + name {\currentpagegrid} + box \nextbox + }% + \fi + \endgroup} + + +\protected\def\page_grd_command_set_vsize + {\clf_setvsizecolumnset{\currentpagegrid}% + \ifdim\d_page_grd_gap_height<\lineheight + \page_grd_command_flush_page + \page_otr_fill_and_eject_page + \fi + \global\vsize\d_page_grd_gap_height + \pagegoal\vsize} + +\protected\def\page_grd_command_set_hsize + {\clf_sethsizecolumnset{\currentpagegrid}% + \hsize\d_page_grd_column_width + \textwidth\d_page_grd_column_width} + +\protected\def\page_grd_command_routine + {\ifvoid\normalpagebox \else + \clf_addtocolumnset{\currentpagegrid}\normalpagebox + \fi + \page_grd_command_set_vsize + \page_grd_command_flush_saved_floats + \page_grd_command_set_vsize + \ifdim\d_page_grd_gap_height<\lineheight + \page_grd_command_flush_page + \fi + \page_grd_command_set_vsize + \clf_flushcolumnsetrest {\currentpagegrid}\normalpagebox + \ifvoid\normalpagebox \else + \unvbox\normalpagebox + \fi} + +\installoutputroutine\synchronizepagegrid + {\ifvoid\normalpagebox\else + \clf_addtocolumnset{\currentpagegrid}\normalpagebox + \page_grd_command_set_vsize + \clf_flushcolumnsetrest{\currentpagegrid}\normalpagebox + \ifvoid\normalpagebox \else + \unvbox\normalpagebox + \fi + \fi} + +% todo line numbers and marks + +\protected\def\page_grd_command_flush_page_column#1% + {\privatescratchcounter#1\relax % or just currentcolumn as in page-col.mkiv + \clf_flushcolumnsetcolumn{\currentpagegrid}\privatescratchcounter + \anch_mark_column_box\b_page_grd_column\privatescratchcounter + \page_marks_synchronize_column\c_page_grd_first_column\c_page_grd_last_column\privatescratchcounter\b_page_grd_column + \ifnum\privatescratchcounter>\c_page_grd_n_of_left + \advance\privatescratchcounter-\c_page_grd_n_of_left + \page_lines_add_numbers_to_box\b_page_grd_column\privatescratchcounter\c_page_grd_n_of_right\plustwo + \else + \page_lines_add_numbers_to_box\b_page_grd_column\privatescratchcounter\c_page_grd_n_of_left\plustwo + \fi + \begingroup + \edef\currentpagegrid{\currentpagegrid:#1}% + \inheritedpagegridframedbox\box\b_page_grd_column + \endgroup} + +\protected\def\page_grd_command_flush_page + {\deactivatecolor % puzzling, try ungrouped color \red or so + \setbox\b_page_grd_collected\hpack\bgroup + \clf_preparecolumnsetflush{\currentpagegrid}% + \letpagegridparameter\c!region\currentpagegrid + \doifelse{\pagegridparameter\c!direction}\v!reverse + {\dostepwiserecurse\c_page_grd_last_column\c_page_grd_first_column\minusone + {\page_grd_command_flush_page_column{##1}% + \ifnum##1>\plusone + \kern\namedpagegridparameter{\currentpagegrid:##1}\c!distance\relax + \fi}}% + {\dostepwiserecurse\c_page_grd_first_column\c_page_grd_last_column\plusone + {\page_grd_command_flush_page_column{##1}% + \ifnum##1<\c_page_grd_last_column + \kern\namedpagegridparameter{\currentpagegrid:##1}\c!distance\relax + \fi}}% + \clf_finishcolumnsetflush{\currentpagegrid}% + \egroup + \page_otr_construct_and_shipout\box\b_page_grd_collected\zerocount % three arguments + \clf_flushcolumnsetareas{\currentpagegrid}\relax + \page_grd_command_flush_saved_floats} + +% slow but robust + +\protected\def\page_grd_command_next_progress + {\strut + \page_grd_command_flush_all_floats + \page_otr_eject_page + \ifcase\clf_columnsetnoto\else + \expandafter\page_grd_command_next_progress + \fi} + +\protected\def\page_grd_command_handle_column + {\ifcase\clf_columnsetgoto{\currentpagegrid}{\page_breaks_columns_current_option}\relax\else + \expandafter\page_grd_command_next_progress + \fi} + +\installcolumnbreakmethod\s!pagegrid\s!unknown {\page_grd_command_handle_column} +\installcolumnbreakmethod\s!pagegrid\v!yes {\page_grd_command_handle_column} + +\protected\def\page_grd_command_next_page + {\ifcase\clf_columnsetgoto{\currentpagegrid}{\v!page}\relax\else + \page_grd_command_flush_page + \fi} + +\protected\def\page_grd_command_next_page_and_inserts + {\page_grd_command_flush_all_floats + \page_grd_command_next_page} + +\let\page_grd_command_flush_all_floats\page_one_command_flush_all_floats +\let\page_grd_command_package_contents\page_one_command_package_contents + +\protected\def\page_grd_command_flush_saved_floats + {\ifconditional\c_page_floats_flushing \else + \ifconditional\c_page_floats_some_waiting + \page_grd_command_flush_saved_floats_indeed + \fi + \fi} + +\protected\def\page_grd_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_grd_reserved_state + \page_grd_place_float_here_indeed + \page_grd_command_set_vsize % needed + \ifconditional\c_page_floats_some_waiting + \doubleexpandafter\page_grd_command_flush_saved_floats_indeed + \fi + \else + \page_floats_resave\s!text + \fi} + +% needs checking + +\protected\def\page_grd_command_flush_floats + {\wait\global\settrue\c_page_floats_flushing + \ifconditional\c_page_floats_some_waiting + \par + \page_grd_command_flush_floats_indeed + \fi + \global\savednoffloats\zerocount + \global\setfalse\c_page_floats_some_waiting + \global\setfalse\c_page_floats_flushing} + +\def\page_grd_command_flush_floats_indeed % much in common with OTRSET + {\ifconditional\c_page_floats_some_waiting + \ifconditional\c_page_floats_compress_flushed + \page_floats_collect\s!text\hsize\d_page_floats_compress_distance + \ifcase\nofcollectedfloats + \page_floats_get + % \or + % \page_floats_get + \else + \setfalse\c_page_floats_center_box % not needed as we do call directly + \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}% + \fi + \else + \page_floats_get + \fi + \doplacefloatbox + \expandafter\page_grd_command_flush_floats_indeed + \fi} + +% so far + +\protected\def\page_grd_command_check_if_float_fits + {\clf_checkcolumnset { + name {\currentpagegrid} + method {\floatmethod} + % c \zerocount + % r \zerocount + box \floatbox + }% + \ifcase\c_page_grd_reserved_state + \global\settrue\c_page_floats_room + \else + \global\setfalse\c_page_floats_room + \fi} + +\protected\def\page_grd_place_float_here_indeed + {\setbox\floatbox\vpack to \d_page_grd_reserved_height \bgroup + \vss + \hpack to \d_page_grd_reserved_width \bgroup + % \hss % no + \box\floatbox + \hss + \egroup + \vss + \egroup + \clf_putincolumnset { + name {\currentpagegrid} + box \floatbox + }} + +\def\page_grd_place_float_slot + {% safeguard + \ifempty\floatmethod + \let\floatmethod\v!here + \fi + % synchronize + \penalty\c_page_otr_eject_penalty + % push + \setbox\savedfloatbox\box\floatbox + \page_grd_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} + \ifempty\floatcolumn \else + c \floatcolumn + \fi + \ifempty\floatrow \else + r \floatrow + \fi + box \floatbox + }% + \ifcase\c_page_grd_reserved_state + \page_grd_place_float_here_indeed + \else + \page_floats_save\s!text + \nonoindentation + \fi + \fi} + +\def\page_grd_place_float_fixed % todo: fallback on here + {\ifempty\floatcolumn + \let\floatmethod\v!here + \orelse\ifempty\floatrow + \let\floatmethod\v!here + \else + \let\floatmethod\v!fixed + \fi + \page_grd_place_float_slot} + +\def\page_grd_place_float_force + {% synchronize + \penalty\c_page_otr_eject_penalty + \clf_checkcolumnset { + name {\currentpagegrid} + method {\floatmethod} + box \floatbox + }% + \ifcase\c_page_grd_reserved_state + \page_grd_place_float_here_indeed + \else + \page_floats_save\s!text + \nonoindentation + \fi} + +\def\page_grd_place_float_page {\page_grd_place_float_slot} % todo: fallback on here + +\def\page_grd_place_float_here {\let\floatmethod\v!here\page_grd_place_float_slot} +\def\page_grd_place_float_top {\page_grd_place_float_slot} +\def\page_grd_place_float_bottom{\page_grd_place_float_slot} + +\installfloatmethod \s!pagegrid \v!here \page_grd_place_float_here +\installfloatmethod \s!pagegrid \v!force \page_grd_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_grd_place_float_top +\installfloatmethod \s!pagegrid \v!bottom \page_grd_place_float_bottom +%installfloatmethod \s!pagegrid \v!auto +%installfloatmethod \s!pagegrid \v!margin +%installfloatmethod \s!pagegrid \v!opposite +\installfloatmethod \s!pagegrid \v!page \page_grd_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_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!lrtb \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!tbrl \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!rltb \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!fxtb \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!btlr \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!lrbt \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!btrl \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!rlbt \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!fxbt \page_grd_place_float_slot +\installfloatmethod \s!pagegrid \s!fixd \page_grd_place_float_fixed + +\protected\def\page_grd_command_side_float_output + {} % nothing, reset anyway + +\protected\def\page_grd_command_flush_side_floats + {\page_sides_forget_floats} + +\protected\def\page_grd_command_synchronize_side_floats + {\page_sides_forget_floats} + +\protected\def\page_grd_command_synchronize_hsize + {\page_grd_command_set_hsize} + +\protected\def\page_grd_command_flush_all_floats + {\page_one_command_flush_all_floats} + +\defineoutputroutine + [\s!pagegrid] + [\s!page_otr_command_routine =\page_grd_command_routine, + \s!page_otr_command_package_contents =\page_grd_command_package_contents, + \s!page_otr_command_set_vsize =\page_grd_command_set_vsize, + \s!page_otr_command_set_hsize =\page_grd_command_set_hsize, % tricky, goes wrong + \s!page_otr_command_synchronize_hsize =\page_grd_command_synchronize_hsize, + \s!page_otr_command_next_page =\page_grd_command_next_page, + \s!page_otr_command_next_page_and_inserts =\page_grd_command_next_page_and_inserts, + % \s!page_otr_command_set_top_insertions =\page_grd_command_set_top_insertions, + % \s!page_otr_command_set_bottom_insertions =\page_grd_command_set_bottom_insertions, + % \s!page_otr_command_flush_top_insertions =\page_grd_command_flush_top_insertions, + % \s!page_otr_command_flush_bottom_insertions=\page_grd_command_flush_bottom_insertions, + \s!page_otr_command_check_if_float_fits =\page_grd_command_check_if_float_fits, + % \s!page_otr_command_set_float_hsize =\page_grd_command_set_float_hsize, + % \s!page_otr_command_flush_float_box =\page_grd_command_flush_float_box, + \s!page_otr_command_synchronize_side_floats=\page_grd_command_synchronize_side_floats, + \s!page_otr_command_side_float_output =\page_grd_command_side_float_output, + \s!page_otr_command_flush_floats =\page_grd_command_flush_floats, + \s!page_otr_command_flush_side_floats =\page_grd_command_flush_side_floats, + \s!page_otr_command_flush_saved_floats =\page_grd_command_flush_saved_floats, + \s!page_otr_command_flush_all_floats =\page_grd_command_flush_all_floats, + % \s!page_otr_command_flush_margin_blocks =\page_grd_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_grd_span_width, + \c!indenting=, + \c!indentnext=\v!yes, + \c!default=\v!here, + \c!alternative=\v!a] + +\newdimen\d_page_grd_span_width + +\permanent\tolerant\protected\def\startpagegridspan[#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 + \def\page_grd_span_stop{\page_grd_span_stop_indeed{#2}}% + \usepagegridspanstyleandcolor\c!style\c!color + \pagegridspanparameter\c!before + \ignorespaces} + +\protected\def\page_grd_span_stop_indeed#1% + {\removeunwantedspaces + \par + \verticalstrut + \kern-2\struttotal + \verticalstrut + \endgraf + \pagegridspanparameter\c!after + \egroup\egroup + \setpagegrid[#1]{\box\scratchbox}% + % todo: push into slot + \egroup + \endgraf} + +\permanent\protected\def\stoppagegridspan % indirectness permits aliasing + {\page_grd_span_stop} + +\permanent\def\pagegridspanwidth#1% assumes equal distances + {\the\dimexpr + #1\d_page_grd_column_width + +#1\d_page_grd_distance + - \d_page_grd_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 + +\permanent\tolerant\protected\def\setuppagegridareatext[#1]#*[#2]% + {\edef\currentpagegridarea{#1}% + \setpagegridareaparameter\c!text{#2}} + +% maybe move the left/right correction to the tex end or the offset to lua + +\protected\def\page_grd_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} + +\aliased\let\setpagegridarea\page_grd_set_area + +% state start | repeat + +%D The old one, for now: + +\aliased\let\definecolumnset \definepagegrid +\aliased\let\setupcolumnset \setuppagegrid +\aliased\let\setupcolumnsetlines \setuppagegridlines +\aliased\let\setupcolumnsetstart \setuppagegridstart +\aliased\let\startcolumnset \startpagegrid +\aliased\let\stopcolumnset \stoppagegrid +\aliased\let\definecolumnsetspan \definepagegridspan +\aliased\let\setupcolumnsetspan \setuppagegridspan +\aliased\let\startcolumnsetspan \startpagegridspan +\aliased\let\stopcolumnsetspan \stoppagegridspan +\aliased\let\columnsetspanwidth \pagegridspanwidth +\aliased\let\definecolumnsetarea \definepagegridarea +\aliased\let\setupcolumnsetarea \setuppagegridarea +\aliased\let\setupcolumnsetareatext\setuppagegridareatext + +%D It ends here. + +\protect \endinput diff --git a/tex/context/base/mkxl/page-fac.mkxl b/tex/context/base/mkxl/page-fac.mkxl new file mode 100644 index 000000000..03fa98217 --- /dev/null +++ b/tex/context/base/mkxl/page-fac.mkxl @@ -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} + +\permanent\protected\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} + +\permanent\protected\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/tex/context/base/mkxl/page-ffl.mkxl b/tex/context/base/mkxl/page-ffl.mkxl new file mode 100644 index 000000000..1ba4bf01d --- /dev/null +++ b/tex/context/base/mkxl/page-ffl.mkxl @@ -0,0 +1,247 @@ +%D \module +%D [ file=page-ffl, +%D version=2018.01.04, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Facing 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 / Facing floats} + +%D The code below comes from a module made for Thomas Schmitz and is now part of the +%D core. A simple example is given here: +%D +%D \starttyping +%D \definefacingfloat +%D [whatever] +%D +%D \setupfacingfloat +%D [whatever] +%D [style=bold, +%D width=frame, +%D offset=10pt, +%D color=white] +%D +%D \setupfacingfloat +%D [whatever:left] +%D [background=color, +%D backgroundcolor=red] +%D +%D \setupfacingfloat +%D [whatever:right] +%D [background=color, +%D backgroundcolor=green] +%D +%D \startfacingfloat[whatever] +%D {\dorecurse{10}{\samplefile{tufte} }} +%D {\dorecurse{10}{\samplefile{ward} }} +%D {\dorecurse{10}{\samplefile{tufte} }} +%D {\dorecurse{10}{\samplefile{ward} }} +%D \stopfacingfloat +%D +%D \startfacingfloat[whatever] +%D \startcontent \dorecurse{10}{\samplefile{tufte} } \stopcontent +%D \startcontent \dorecurse{10}{\samplefile{ward} } \stopcontent +%D \startcontent \dorecurse{10}{\samplefile{tufte} } \stopcontent +%D \startcontent \dorecurse{10}{\samplefile{ward} } \stopcontent +%D \stopfacingfloat +%D +%D \dorecurse{10}{\samplefile{sapolsky} } +%D \stoptyping +%D +%D The idea is to flush related floats more or less in parallel. + +\unprotect + +% width: +% +% -- fit : do nothing +% -- dimension : use that +% -- frame : use hsize minus frame offsets (based on preroll) + +\installcorenamespace {facingfloat} + +\installframedcommandhandler \??facingfloat {facingfloat} \??facingfloat + +\setupfacingfloat + [\c!spaceinbetween=\v!big, + \c!inbetween={\blank[\v!big]}, + \c!width=\v!fit, + %\c!style, + %\c!color, + \c!page=\v!left] + +\appendtoks + \ifx\currentfacingfloatparent\empty + \normalexpanded{\definefacingfloat[\currentfacingfloat:\v!left ][\currentfacingfloat]}% + \normalexpanded{\definefacingfloat[\currentfacingfloat:\v!right][\currentfacingfloat]}% + \fi +\to \everydefinefacingfloat + +\newcount\c_strc_floats_facing_saved +\newcount\c_strc_floats_facing_flushed + +\newbox\b_strc_floats_facing_l +\newbox\b_strc_floats_facing_r + +\let\m_strc_floats_state\relax + +\protected\def\strc_floats_facing_flush + {\ifnum\c_strc_floats_facing_flushed<\c_strc_floats_facing_saved + \ifodd\c_strc_floats_facing_flushed + \ifodd\realpageno + \strc_floats_facing_flush_indeed + \doifelsependingpagecontent\relax{\null\page}% + \fi + \else + \ifodd\realpageno\else + \strc_floats_facing_flush_indeed + \doifelsependingpagecontent\relax{\null\page}% + \fi + \fi + \fi} + +\def\strc_floats_facing_flush_indeed + {\global\advance\c_strc_floats_facing_flushed\plusone + \floatingpenalty\zerocount + \insert\namedinsertionnumber\s!topfloat\bgroup + \forgetall + \ifconditional\c_page_one_top_of_insert + \ifconditional\c_page_one_correct_top_insert + \topskipcorrection % [xx] new: see icare topbleed + \kern-\lineskip + \par + \prevdepth\maxdimen + \fi + \fi + \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_facing_flushed}% + \vkern\s_page_one_between_top_insert + \egroup + \ifnum\c_strc_floats_facing_saved=\c_strc_floats_facing_flushed + \global\c_strc_floats_facing_saved \zerocount + \global\c_strc_floats_facing_flushed\zerocount + \resetboxesincache{\currentfacingfloat}% + \fi} + +\let\flushfacingfloats\strc_floats_facing_flush + +\protected\def\strc_floats_facing_setup + {\edef\currentfacingfloat{\currentfacingfloat:\m_strc_floats_state}% + \usefacingfloatstyleandcolor\c!style\v!color} + +\protected\def\strc_floats_facing_collect + {\ifx\m_strc_floats_state\v!left + \ifvoid\nextbox\orelse\ifzeropt\wd\nextbox\else + \ifvoid\b_strc_floats_facing_l + \setbox\b_strc_floats_facing_l\box\nextbox + \else + \setbox\b_strc_floats_facing_l\vbox\bgroup + \unvbox\b_strc_floats_facing_l + \facingfloatparameter\c!inbetween + \unvbox\nextbox + \egroup + \fi + \fi + \let\m_strc_floats_state\v!right + \orelse\ifx\m_strc_floats_state\v!right + \ifvoid\nextbox\orelse\ifzeropt\wd\nextbox\else + \ifvoid\b_strc_floats_facing_r + \setbox\b_strc_floats_facing_r\box\nextbox + \else + \setbox\b_strc_floats_facing_r\vbox\bgroup + \unvbox\b_strc_floats_facing_r + \facingfloatparameter\c!inbetween + \unvbox\nextbox + \egroup + \fi + \fi + \let\m_strc_floats_state\v!left + \else + \let\m_strc_floats_state\v!left + \fi} + +\protected\def\strc_floats_facing_handle + {\doifnextbgroupelse + \strc_floats_facing_handle_indeed + \strc_floats_facing_wrap_up} + +\protected\def\strc_floats_facing_handle_indeed + {\dowithnextboxcontent + \strc_floats_facing_setup + {\strc_floats_facing_collect\strc_floats_facing_handle} + \vbox} + +\permanent\protected\def\startfacingfloat[#1]% + {\begingroup + % todo: \usepageparameter +% \edef\p_page{\facingfloatparameter\c!page}% +% \ifx\p_page\empty\else +% \page[\p_page]% +% \fi + % + \edef\currentfacingfloat{#1}% + \edef\p_width{\facingfloatparameter\c!width}% + \letfacingfloatparameter\c!width\v!fit + \ifx\p_width\v!frame + \setbox\scratchbox\hpack{\inheritedfacingfloatframed{}}% + \advance\hsize-\wd\scratchbox + \orelse\ifx\p_width\v!fit + % whatever + \else + \hsize\p_width + \fi + \enforced\let\startcontent\bgroup + \enforced\let\stopcontent\egroup + \let\m_strc_floats_state\v!left + \strc_floats_facing_handle} + +\permanent\protected\def\stopfacingfloat + {\endgroup} + +\protected\def\strc_floats_facing_wrap_up + {\edef\p_spaceinbetween{\facingfloatparameter\c!spaceinbetween}% + \ifx\p_spaceinbetween\empty + \scratchdimen\zeropoint + \else + \setbox\scratchbox\vbox{\directvspacing\p_spaceinbetween}% + \scratchdimen\htdp\scratchbox + \fi + \ifvoid\b_strc_floats_facing_l\else + \page_postprocessors_linenumbers_box\b_strc_floats_facing_l + \fi + \ifvoid\b_strc_floats_facing_r\else + \page_postprocessors_linenumbers_box\b_strc_floats_facing_r + \fi + \doloop{% + \strc_floats_facing_flush_wrap\b_strc_floats_facing_l\v!left + \strc_floats_facing_flush_wrap\b_strc_floats_facing_r\v!right + \ifvoid\b_strc_floats_facing_l\relax\ifvoid\b_strc_floats_facing_r\relax + \exitloop + \fi\fi}} + +\def\strc_floats_facing_flush_wrap#1#2% + {\ifvoid#1\relax + % todo + \else + \begingroup + \setbox\scratchbox\vsplit#1 upto \textheight + \setbox\scratchbox\hpack\bgroup + \edef\currentfacingfloat{\currentfacingfloat:#2}% + \inheritedfacingfloatframed{\box\scratchbox}% + \egroup + \ifdim\ht\scratchbox<\dimexpr\textheight-\scratchdimen\relax + \setbox\scratchbox\vbox{\box\scratchbox\directvspacing\p_spaceinbetween}% + \else + \setbox\scratchbox\vbox to \textheight{\box\scratchbox\vss}% + \fi + \global\advance\c_strc_floats_facing_saved\plusone + \putboxincache{\currentfacingfloat}{\number\c_strc_floats_facing_saved}\scratchbox + \endgroup + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-flt.mkxl b/tex/context/base/mkxl/page-flt.mkxl new file mode 100644 index 000000000..bc287da7d --- /dev/null +++ b/tex/context/base/mkxl/page-flt.mkxl @@ -0,0 +1,326 @@ +%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 also float +%D related code in \type {strc-flt.mkiv}. + +\registerctxluafile{page-flt}{} + +\unprotect + +\defineinsertion[\s!topfloat] +\defineinsertion[\s!bottomfloat] +\defineinsertion[\s!pagefloat] + +\newdimen \d_page_floats_inserted_bottom +\newdimen \d_page_floats_inserted_top +\newdimen \d_page_floats_inserted_page +\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 +\newcount \c_page_floats_n_of_page \c_page_floats_n_of_page \plustwo + +\newconstant\c_page_floats_insertions_topskip_mode % 1 = no topskip + +\def\page_floats_report_total + {\showmessage\m!floatblocks4% + {\the\totalnoffloats + \ifx\floatlocationmethod\empty + \ifx\floatlocation\empty\else,\floatlocation\fi + \else + ,\floatlocationmethod + \fi}} + +\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_compress_flushed \settrue\c_page_floats_compress_flushed + +\newdimen \d_page_floats_compress_distance + +%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 +\newdimen\maxcollectedfloatstotal % 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 + +\protected\def\page_floats_flush#1#2% + {\clf_flushfloat{#1}#2\relax + \the\everyfloatscheck} + +\protected\def\page_floats_flush_by_label#1#2% + {\clf_flushlabeledfloat{#1}{#2}\relax + \the\everyfloatscheck} + +\protected\def\page_floats_save#1% + {\clf_savefloat{#1}\relax + \the\everyfloatscheck} + +\protected\def\page_floats_resave#1% + {\clf_resavefloat{#1}\relax + \the\everyfloatscheck} + +\protected\def\page_floats_push_saved + {\clf_pushfloat + \the\everyfloatscheck} + +\protected\def\page_floats_pop_saved + {\clf_popfloat + \the\everyfloatscheck} + +\protected\def\page_floats_get_info#1% + {\clf_consultfloat{#1}} + +\protected\def\page_floats_if_else#1% + {\clf_doifelsestackedfloats{#1}} + +\protected\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 + +\protected\def\page_floats_save_page_float#1#2% + {\clf_savespecificfloat{#1}{specification{#2}}\relax} + +\protected\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 + +\permanent\tolerant\protected\def\placenamedfloat[#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]} + +\permanent\tolerant\protected\def\placefloatwithsetups[#1]#*[#2]#*[#3]#:#4% + {\def\floatsetupcaption{#4}% + \def\floatsetupcontent{\copy\nextbox}% + \def\floatsetupwidth {\wd\nextbox}% + \def\floatsetupheight {\ht\nextbox}% + \enforced\permanent\protected\def\placesetupfloat[##1]% + {\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (protected) + \dowithnextbox{\setups[#1]}\vbox} + +%D The following code is in transition as we don't want to break the current single +%D column, multi column, and columnset mechanism. +%D +%D First we reimplement some helpers. + +\def\page_floats_get_used_hsize{\hsize} + +\protected\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<\page_floats_get_used_hsize + \global\setbox\floatbox\hpack to \page_floats_get_used_hsize{\hss\box\floatbox\hss}% + \orelse\ifinsidecolumns + % retain special alignments + \ifdim\wd\floatbox>\makeupwidth + \wd\floatbox\makeupwidth + \fi + \fi + \fi + \else + \global\savednoffloats\zerocount + \global\setbox\floatbox\emptybox + \fi} + +\protected\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 + +\permanent\protected\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} + +\let\m_page_otr_checked_page_float\relax + +\protected\def\page_floats_flush_page_floats % used in postpone + {\edef\m_page_otr_checked_page_float{\clf_checkedpagefloat}% + \ifx\m_page_otr_checked_page_float\empty + % nothing + \orelse\ifx\m_page_otr_checked_page_float\v!empty + \emptyhbox \page_otr_fill_and_eject_page % why not dummy_page + \else + \page_floats_flush_page_floats_indeed\m_page_otr_checked_page_float + \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) +% +% \permanent\protected\def\uncenteredfloatbox +% {\ifconditional\c_page_floats_center_box +% \ifhbox\floatbox\relax % remove centering +% \ifdim\wd\floatbox=\hsize +% \ifhbox\floatbox +% \setbox\scratchbox\hbox +% {\unhbox\floatbox +% \unskip\unskip +% \global\setbox\globalscratchbox\lastbox}% +% \box\globalscratchbox +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi} diff --git a/tex/context/base/mkxl/page-flw.mkxl b/tex/context/base/mkxl/page-flw.mkxl new file mode 100644 index 000000000..ef92b9b52 --- /dev/null +++ b/tex/context/base/mkxl/page-flw.mkxl @@ -0,0 +1,178 @@ +%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 spacing is +%D the driving force here). It's an old mechanism used for playing with stepping +%D through document threads. As it's a simple and effective mechanism we keep it +%D around. It's not to be confused with 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 + +\newcount\b_page_textflow_box + +\permanent\def\textflowcollector#1% + {\begincsname\??textflowbox#1\endcsname} + +\permanent\protected\def\doifelsetextflowcollector#1% + {\ifcsname\??textflowbox#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifelsetextflow#1% + {\unless\ifcsname\??textflowbox#1\endcsname + \expandafter\secondoftwoarguments + \orelse\ifvoid\csname\??textflowbox#1\endcsname + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doiftextflowcollectorelse\doifelsetextflowcollector +\aliased\let\doiftextflowelse \doifelsetextflow + +\permanent\protected\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 + \enforced\permanent\protected\def\stoptextflow{\endgraf\egroup\endgroup}% + \else + \enforced\aliased\let\stoptextflow\endgroup + \fi} + +\aliased\let\stoptextflow\relax + +\permanent\protected\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 + \orelse\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 + \endgroup} + +\protect \endinput + +% \setuppapersize [A6] +% \setupbodyfont [pagella, 12pt] +% +% \definetextflow [even] [width=\textwidth] +% \definetextflow [odd] [width=\textwidth] +% +% \starttextflow [even] \dorecurse{15}{\input bryson} \stoptextflow +% \starttextflow [odd] \dorecurse {5}{\input knuth } \stoptextflow +% +% \starttext +% +% \doloop { +% \ifodd\realpageno +% \doiftextflowelse{odd} { +% \bgroup +% \vsize\dimexpr\textheight-\strutdp\relax +% \flushtextflow{odd} +% \egroup +% } { +% \null +% } +% \page +% \else +% \doiftextflowelse{even} { +% \bgroup +% \vsize\dimexpr\textheight-\strutdp\relax +% \flushtextflow{even} +% \egroup +% } { +% \null +% } +% \page +% \fi +% \doiftextflowelse{even}\donothing{\doiftextflowelse{odd}\donothing\exitloop} +% } +% +% \stoptext + diff --git a/tex/context/base/mkxl/page-imp.mkxl b/tex/context/base/mkxl/page-imp.mkxl new file mode 100644 index 000000000..6ccab3e4e --- /dev/null +++ b/tex/context/base/mkxl/page-imp.mkxl @@ -0,0 +1,1410 @@ +%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 really user +%D friendly). + +\newtoks\t_page_text_data + +\permanent\protected\def\starttextdata#1\stoptextdata + {\glet\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed + \globaladdtotoks\t_page_text_data{#1}} + +\aliased\let\stoptextdata\relax + +\def\page_shipouts_flush_text_data_indeed + {\vsmashed{\the\t_page_text_data}% + \global\t_page_text_data\emptytoks + \glet\page_shipouts_flush_text_data\relax} + +\let\page_shipouts_flush_text_data\relax + +\prependtoks + \page_shipouts_flush_text_data +\to \everylastshipout + +%D Problem: we need to apply the finalizers to a to be shipped out page (as we can +%D have positioning involved). However, we can also add stuff in the imposition, +%D like cropmarks. Fortunately we do that with metapost so colors etc are dealt with +%D at that end. + +% \starttypen +% \def\pagestoshipout{1,3,5} +% \stoptypen + +\installcorenamespace{shipoutmethod} +\installcorenamespace{layoutarranger} +\installcorenamespace{layoutarrangeoption} + +\newcount \shippedoutpages +\newcount \combinedpagescounter +\newconstant \whichpagetoshipout % 0=all 1=odd 2=even +\newbox \shipoutscratchbox +\setnewconstant\shipoutfinalizemethod\plusone + +\mutable\let\pagestoshipout\empty % {1,3,6} + +\permanent\protected\def\shipoutrange#1#2% + {\begingroup + \scratchtoks\emptytoks + \dostepwiserecurse{#1}{\numexpr#2-\plusone\relax}\plusone{\etoksapp\scratchtoks{##1,}}% + \xdef\pagestoshipout{\the\scratchtoks,\number#2}% + \doglobal\appendtoks + \ifnum\realpageno>\numexpr#2+\plusone\relax + \global\everypar{\normalend}% + \fi + \to\everyaftershipout + \endgroup} + +\permanent\protected\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) + +\aliased\let\installpagehandler\installshipoutmethod % will go + +\permanent\protected\def\invokepagehandler#1% + {\expandnamespacevalue\??shipoutmethod{#1}\v!normal} + +\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 % not nice ... needs thinking + \page_shipouts_handle{#1}% + \else + \setbox\shipoutscratchbox\hpack + {#1}% just in case there are objects there, hook for testing (will go away) + \page_shipouts_handle + {\finalizeshipoutbox\shipoutscratchbox + \box\shipoutscratchbox}% + \fi + \setnextrealpageno % so this comes before \everyaftershipout so in fact: + \the\everyaftershipout % at this point we're already on the next realpage + \ifcase\c_page_boxes_flush_n\else + \page_boxes_flush_after + \fi} + +\def\page_shipouts_ignore#1% + {\begingroup + \writestatus\m!system + {\ifarrangingpages arranged \fi page + \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace + not flushed}% + % \setbox\scratchbox\hpack + % {#1}% no finalize + \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} + +%D Also in normal \MKIV\ we nos use the indirect way so that we benefit from timing +%D and tracing. + +\def\page_shipout_show_box{\showbox diagnose} + +\protected\def\page_shipout_box#1% + {\ifcase\tracingoutput\else + \page_shipout_show_box#1\relax + \fi + \clf_shipoutpage#1\relax + \global\setbox#1\emptybox + \global\deadcycles\zerocount} + +\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}% finalizes + \ifcase\shipoutfinalizemethod + \finalizeshipoutbox\shipoutscratchbox + \fi + \setbox\shipoutscratchbox\vpack + {\scratchdimen\clf_shipoutoffset\relax + \ifdim\scratchdimen=\zeropoint\else + \offinterlineskip + \vkern\scratchdimen + \hkern\scratchdimen + \fi + \hpack + {\page_otr_flush_every_stuff + \page_otr_flush_special_content + \box\shipoutscratchbox}}% + \page_shipout_box\shipoutscratchbox % takes a box number! + \else + \page_shipouts_ignore{#1}% + \fi} + +\newconditional\c_page_shipouts_use_objects \settrue\c_page_shipouts_use_objects + +\installcorenamespace {arrangedpage} + +\def\page_shipouts_arrange#1% + {\begingroup + \setbox\shipoutscratchbox\hpack + {#1}% finalizes + \setbox\shipoutscratchbox\hpack + {\page_otr_flush_every_stuff + \page_otr_flush_special_content + \box\shipoutscratchbox}% + % + \ifconditional\c_page_shipouts_use_objects + \setobject\??arrangedpage{\the\realpageno}\hpack{\box\shipoutscratchbox}% + \setbox\shipoutscratchbox\hpack{\getobject\??arrangedpage{\the\realpageno}}% + \fi + % + \pusharrangedpage\shipoutscratchbox + \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 + +\mutable\def\arrangedrotationO{0} +\mutable\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} + +\permanent\protected\def\doinstallarrangedoption#1#2% + {\setvalue{\??layoutarrangeoption#1}{#2}} + +\permanent\def\doinstalledarrangedoption#1% + {\ifcsname\??layoutarrangeoption#1\endcsname + \lastnamedcs + \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} + +\permanent\protected\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 + \ifdefined\handlearrangedpage\else + \global\arrangingpagesfalse + \fi + \setuppapersize + \ifarrangingpages + \ifconditional\c_page_shipouts_use_objects\else + \clf_disablejobsave + \clf_synctexdisable + %\disabledirective[job.save]% + \fi + \fi + \fi} + +\permanent\protected\def\installpagearrangement #1 % will change, no space + {\setgvalue{\??layoutarranger#1}} + +\permanent\def\checkinstalledpagearrangement#1% can be empty: aaa,,bbb + {\begincsname\??layoutarranger#1\endcsname} + +\aliased\let\poparrangedpages \relax +\aliased\let\pusharrangedpage \relax +\aliased\let\handlearrangedpage\relax + +\permanent\protected\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% + \enforced\permanent\glet\pusharrangedpage #6% + \enforced\permanent\glet\poparrangedpages #7% + \enforced\permanent\glet\handlearrangedpage#8} + +\installpagearrangement {\v!normal} + {\global\arrangingpagesfalse} + +%D (WS:) Watch out with 2UP and A4/A5: +%D +%D \definepapersize [A4] [width=210mm,height=297mm] +%D \definepapersize [A5] [width=148mm,height=210mm] +%D +%D 297 mm - 2 * 148 mm = 1 mm +%D +%D This is only visible when we have a full background. + +\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} + +\permanent\protected\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} + +\permanent\protected\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}} + +\permanent\protected\def\gotonextarrangepage + {\global\advance\arrangeno \plusone + \def\pagecutmarksymbol{\the\arrangeno}} + +\permanent\protected\def\outputarrangedbox#1% + {\begingroup + \forgetall % somehow we're back and need to redo this + \dontcomplain + \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 ... + +\permanent\protected\def\reportarrangedpage#1% + {\showmessage\m!system{23}{\the\realpageno.\the\pageno\ifnum\subpageno>0 .\the\subpageno\fi,\number#1}} + +\permanent\protected\def\advancearrangedpageN + {\global\advance\arrangedpageN\plusone} + +% TOP + +% 32/16/8/4/SIDE + +\permanent\protected\def\poparrangedpagesAB + {\ifnum\arrangedpageN>\zerocount + \paperwidth\arrangedpageX\paperwidth + \paperheight\arrangedpageY\paperheight + \outputarrangedbox\arrangedpageA + \outputarrangedbox\arrangedpageB + \global\arrangedpageN\zerocount + \fi} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\pusharrangedpageFOURA{\pusharrangedpageFOURdo01} +\permanent\protected\def\pusharrangedpageFOURB{\pusharrangedpageFOURdo10} + +\permanent\protected\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} + +\permanent\protected\def\pusharrangedpageSIDETOP#1% + {\advancearrangedpageN + \reportarrangedpage\arrangedpageN + \ifcase\arrangedpageN + \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1 + \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2 + \poparrangedpages + \fi} + +\permanent\protected\def\handlearrangedpageSIDE + {\wd\arrangedpageA\paperwidth + \wd\arrangedpageB\paperwidth + \global\setbox\arrangedpageA\hpack + {\box\arrangedpageA\box\arrangedpageB}% + \ht\arrangedpageA\paperheight} + +\permanent\protected\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 + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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}}} + +\permanent\protected\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} + +\permanent\protected\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: + +\permanent\protected\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 + +\permanent\protected\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 + +\permanent\protected\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 + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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] + +\permanent\protected\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} + +\permanent\protected\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} +% +% \permanent\protected\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} +% +% \permanent\protected\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 + +\permanent\protected\protected\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} + +\permanent\protected\protected\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} + +\permanent\protected\tolerant\def\definepageshift[#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} + +\permanent\tolerant\protected\def\setuppageshift[#1]#*[#2]#*[#3]% page|paper horizontal vertical + {\ifarguments\or + \setuppageshift[\v!page][#1][#1]% + \or + \doifelseinset{#1}{\v!page,\v!paper} + {\setuppageshift[#1][#2][#2]} + {\setuppageshift[\v!page][#1][#2]}% + \or + %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}% + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-inf.mkxl b/tex/context/base/mkxl/page-inf.mkxl new file mode 100644 index 000000000..251e0c046 --- /dev/null +++ b/tex/context/base/mkxl/page-inf.mkxl @@ -0,0 +1,124 @@ +%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 + +\mutable\let\currentversioninfo\empty +\mutable\let\currentversiontext\empty + +\aliased\let\version\setupversion + +\let\page_info_add_to_box\gobbleoneargument + +\permanent\tolerant\protected\def\setupversion[#1]% + {\the\everyresetversion + \doifelseassignment{#1}% + {\getdummyparameters[\c!alternative=,\c!text=,#1]% + \edef\currentversioninfo{\dummyparameter\c!alternative}% + \edef\currentversiontext{\dummyparameter\c!text}}% + {\edef\currentversioninfo{#1}% + \let \currentversiontext\empty}% + \ifcsname\??layoutinfo\currentversioninfo\endcsname + \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} + +\protected\def\page_info_place_info % at the bottom of the page + {\begincsname\??layoutinfo\currentversioninfo\endcsname} + +\permanent\protected\def\installversioninfo#1#2% + {\setvalue{\??layoutinfo#1}{#2}} + +\permanent\protected\def\includeversioninfo#1% + {\begincsname\??layoutinfo#1\endcsname} + +\installversioninfo\v!final + {\let\currentversioninfo\empty + \let\page_info_add_to_box\gobbleoneargument} + +\installversioninfo\v!concept + {\vskip6\points + \hbox to \makeupwidth + {\infofont + \rlap{\v!concept:\space\currentdate}% + \hss + \currentversiontext + \hss + \llap{\page_adapts_status_info}}} + +\installversioninfo\v!file + {\vskip6\points + \hbox to \makeupwidth + {\infofont + \getmessage\m!system{27}:\space\currentdate\quad + \donefalse + \doif\currentproject\currentproduct{\doif\currentproduct\currentcomponent\donetrue}% + \ifdone + \donefalse + \else + \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 + \fi + \ifdone \else \space\v!file :\space\jobname \space \fi + \hss + \currentversiontext + \quad + \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 + \hkern\texthoffset % brrrr + \vbox to \zeropoint{\vss\page_info_place_info}% + \vkern\bodyfontsize}% + \dp\b_page_versions\zeropoint + \wd\b_page_versions\scratchdimen + \setbox#1\hpack{\box#1\hkern-\scratchdimen\box\b_page_versions}} + +\setupversion % resets + [\v!final] + +\let\page_info_add_to_box\gobbleoneargument + +\protect \endinput diff --git a/tex/context/base/mkxl/page-ini.mkxl b/tex/context/base/mkxl/page-ini.mkxl new file mode 100644 index 000000000..481e5abd5 --- /dev/null +++ b/tex/context/base/mkxl/page-ini.mkxl @@ -0,0 +1,376 @@ +%D \module +%D [ file=page-ini, +%D version=2000.10.20, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Initializations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Initializations} + +\registerctxluafile{page-ini}{} + +%D The \type {\processpage} command has become obsolete. It's original +%D purpose was to flush only parts of a document but nowadays we have +%D project structure and modes. This is just one of those very early +%D features that no longer makes sense. + +%D The \type {\couplepage} command has become obsolete. It's original +%D purpose was to provide hooks for printer directives (like choosing +%D different paper trays). + +\unprotect + +%D Shipout control. + +\newcount\nofshipouts + +\appendtoks + \global\advance\nofshipouts\plusone +\to \everyaftershipout + +\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled + +\protected\def\page_otr_shipout % not used at all + {\ifconditional\c_otr_shipout_enabled + \expandafter\page_otr_shipout_yes + \else + \expandafter\page_otr_shipout_nop + \fi} + +\aliased\let\page_otr_shipout_yes\normalshipout + +\protected\def\page_otr_shipout_nop + {\writestatus\m!system{ignoring shipout of real page \the\realpageno}% + \global\advance\realpageno\minusone % else no flush of resources + \dowithnextbox{\deadcycles\zerocount}} + +% We don't support direct user \shipouts (weird: this does not work, bug?) +% +% \let\shipout\page_otr_shipout_nop + +%D Building pages. + +\newbox\pagebox + +% \ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi +% \ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi +% \ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi + +\newtoks\t_page_postprocessors_box +\newtoks\t_page_postprocessors_page +\newtoks\t_page_postprocessors_column + +\newconstant\b_page_postprocessor + +\def\page_apply_postprocessors_box#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_box} + +\def\page_apply_postprocessors_page#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_page} + +\def\page_apply_postprocessors_column#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_column} + +%D Floats. + +\def\page_otr_flush_all_floats + {%\flushnotes already done + \ifconditional\c_page_floats_some_waiting + \page_otr_command_flush_all_floats + \fi} + +\def\page_otr_insert_dummy_page + {\par + \ifvmode + \page_otr_flush_all_floats + \fixedspace + \vfill + \page_otr_command_next_page + \fi} + +\def\page_otr_flush_pending_content + {\vkern\zeropoint\relax + \ifvoid\normalpagebox \else + \unvbox\normalpagebox + \penalty\outputpenalty + \fi} + +\newconstant\c_page_postponed_mode % \c_page_postponed_mode\plusone +\newbox \b_page_otr_saved + +\installoutputroutine\savepagecontent + {\global\setbox\b_page_otr_saved\box\normalpagebox} + +\permanent\protected\def\flushpagecontent + {\ifvoid\b_page_otr_saved\else\unvbox\b_page_otr_saved\fi} + +% Test case: assumes one group level for output routine, todo: +% a toks. +% +% \starttext +% +% \startbuffer[makeup] +% \startpagemakeup[pagestate=start,page=no] +% \color[red]{ +% \vfill +% \dorecurse{3}{ +% \samplefile{klein} +% \vfill +% } +% } +% \stoppagemakeup +% \stopbuffer +% +% \startcolor[green] +% \dorecurse{10}{ +% \dontleavehmode{\bf 1:#1:} \samplefile{sapolsky}\par +% } +% \stopcolor +% +% \startpostponing % [+3] +% \getbuffer[makeup] +% \stoppostponing +% +% \startcolor[blue] +% \dorecurse{25}{ +% \dontleavehmode{\bf 2:#1:} \samplefile{sapolsky}\par +% } +% \stopcolor +% +% \stoptext + +\def\page_otr_construct_and_shipout#1#2#3% + {\forgetall + \page_boxes_shipout{\page_boxes_constructed_page#1#2}% \hbox removed + \page_otr_flush_pending_content + % not really needed, replaced by \flushsavedfloats + \page_otr_check_for_pending_inserts + % but does not hurt either (we're still in the otr!) + \inpagebodytrue % needed for enabling \blank ! brrr + \pagebodymode\plusone % todo: \plustwo when spread + \page_otr_command_flush_saved_floats + \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns + \strc_pagenumbers_increment_counters % should hook into an every + \page_adapts_synchronize + \page_otr_check_for_pending_inserts + \page_otr_command_flush_facing_floats + \page_floats_flush_page_floats % before postponed blocks + \page_spread_flush % defined later + \ifnum#3=\plusone + % this is tricky! we need to make sure we are in the output group + \ifnum\c_page_postponed_mode=\plusone + \aftergroup\page_postponed_blocks_flush + \else + \page_postponed_blocks_flush + \fi + \else + \page_postponed_blocks_flush + \fi} + +% Can't we get rid of this hackery? It's used in some widgets +% stuff so probably not. + +\newbox\b_page_otr_special + +\def\page_otr_flush_special_content + {\ifvoid\b_page_otr_special \else + \box\b_page_otr_special + \fi} + +\def\page_otr_add_special_content + {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox} + +\def\page_otr_add_special_content_indeed + {\wd\nextbox\zeropoint + \ht\nextbox\zeropoint + \dp\nextbox\zeropoint + \global\setbox\b_page_otr_special\hbox + {%\hskip-\maxdimen % not here, fails in acrobat (clips) + \box\b_page_otr_special\box\nextbox}}% was \unhbox, is now box again + +\let\flushatshipout\page_otr_add_special_content + +\maxdeadcycles=1000 + +\newtoks\afterpage \newtoks\aftereverypage +\newtoks\beforepage \newtoks\beforeeverypage + +\newif\ifarrangingpages \arrangingpagesfalse + +\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off + +% \appendtoks +% \ifcase\pageornamentstate \or +% \pageornamentstate\zerocount +% \fi +% \to \everyaftershipout + +\appendtoks + \ifcase\pageornamentstate \or + \global\pageornamentstate\zerocount + \fi +\to \everyaftershipout + +% Mark synchronization + +\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages + +\def\page_marks_synchronize_page#1% box + {\strc_markings_synchronize\v!page{#1}{\ifconditional\c_page_marks_building_successive_pages\v!keep\fi}} + +\def\page_marks_synchronize_column#1#2#3#4% first last column box + {\ifnum#3=#1\relax + \strc_markings_synchronize{\number#3,\v!column:\number#3,\v!first,\v!column:\v!first}{#4}{}% + \orelse\ifnum#3=#2\relax + \strc_markings_synchronize{\number#3,\v!column:\number#3,\v!last, \v!column:\v!last }{#4}{}% + \else + \strc_markings_synchronize{\number#3,\v!column:\number#3 }{#4}{}% + \fi} + +% Page body building + +\newconditional\c_page_boxes_save_page_body +\newbox \b_page_boxes_saved_page_body + +\def\page_boxes_constructed_page_body#1#2% + {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup + \boxmaxdepth\maxdimen % new + \dontcomplain + \page_marks_synchronize_page {#2}% we could consider doing this for \pagebox (needs testing) + \page_boxes_construct_content \pagebox{#1}{#2}% + \page_backgrounds_add_to_main \pagebox + \page_boxes_apply_offsets \pagebox + \page_info_add_to_box \pagebox + \ifcase\pageornamentstate + \page_backgrounds_add_to_paper \pagebox + \fi + \anch_positions_register_page \pagebox + \ifarrangingpages + \page_boxes_apply_shift_paper \pagebox % \v!paper + \else + \page_boxes_apply_clip_paper \pagebox + \page_marks_add_page \pagebox + \page_boxes_apply_replicate \pagebox + \page_boxes_apply_scale \pagebox + \page_boxes_apply_mirror_paper \pagebox + \page_boxes_apply_orientate_paper \pagebox + \page_marks_add_more \pagebox + \page_boxes_apply_center \pagebox + \page_backgrounds_add_to_print \pagebox + \page_boxes_apply_mirror_print \pagebox + \page_boxes_apply_orientate_print \pagebox + \page_boxes_apply_shift_print \pagebox % \v!page + \page_boxes_apply_offset \pagebox + \page_boxes_apply_negate_print \pagebox + \fi + \box\pagebox + \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi} + +\appendtoks + \restoreglobalbodyfont + \pickupattributes +\to \everybeforepagebody + +% if we really need this ... we need to bypass \permanent + +% \ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed? +% +% \prependtoks +% \let\nextbox\nestednextbox +% \to \everybeforepagebody + +\def\page_boxes_constructed_page#1#2% + {\vpack\bgroup % intercept spurious spaces + \the\everybeforepagebody + \starttextproperties + \checkmarginblocks + \the\beforeeverypage + \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% + \inpagebodytrue + \pagebodymode\plusone % todo: \plustwo when spread + \page_boxes_constructed_page_body#1#2% + \normalexpanded{\global\afterpage \emptytoks\the\afterpage }% + \the\aftereverypage + \resetpagebreak + \resetlayouttextlines % will go to \aftereverypage + \stoptextproperties + \the\everyafterpagebody + \egroup} + +\permanent\def\doifelsetopofpage + {\ifdim\pagegoal=\maxdimen + \expandafter\firstoftwoarguments + \orelse\ifdim\pagegoal=\vsize + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiftopofpageelse\doifelsetopofpage + +% %D Idea: +% +% \newinsert\thispageinsert % <- installinsertion +% +% \def\flushatthispage +% {\bgroup +% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}% +% \hbox} +% +% \appendtoks +% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi +% \to \everyshipout + +% not yet in i-* file + +\installcorenamespace{markedpage} + +% todo: just define at the lua end ... less hassle + +\permanent\tolerant\protected\def\markpage [#1]#*[#2]{\clf_markpage {#1}{#2}} +\permanent \def\markedpages [#1]{\clf_markedpages {#1}} % expandable +\permanent\protected \def\doifelsemarkedpage#1{\clf_doifelsemarkedpage{#1}} +\permanent\protected \def\startmarkpages [#1]{\clf_startmarkpages {#1}} +\permanent\protected \def\stopmarkpages {\clf_stopmarkpages } + +%D Experimental: + +\newconstant\c_page_force_strut_depth_trace_mode + +\installtextracker + {otr.forcestrutdepth} + {\c_page_force_strut_depth_trace_mode\plusone} + {\c_page_force_strut_depth_trace_mode\zerocount} + +\installoutputroutine\forcestrutdepth + {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode + \unvbox\normalpagebox} + +\installoutputroutine\forcestrutdepthplus % experimental + {\clf_forcestrutdepthplus\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode + \unvbox\normalpagebox} + +% maybe better: +% +% \installoutputroutine\doforcestrutdepth +% {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode +% \unvbox\normalpagebox} +% +% \protected\def\forcestrutdepth +% {\par\ifvmode\ifinner\else\doforcestrutdepth\fi\fi} + +% Also experimental: + +\permanent\protected\def\doifelsependingpagecontent{\clf_doifelsependingpagecontent} +% \permanent\protected\let\doifelsependingpagecontent\clf_doifelsependingpagecontent + +\protect \endinput diff --git a/tex/context/base/mkxl/page-inj.mklx b/tex/context/base/mkxl/page-inj.mklx new file mode 100644 index 000000000..19f01e6d3 --- /dev/null +++ b/tex/context/base/mkxl/page-inj.mklx @@ -0,0 +1,228 @@ +%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 on +%D postponing but the content does not end up in the regular page flow, so it's +%D closer to page figures but without the usual page builder. +%D +%D This module is following the mkvi way of rendering setups and configuration and +%D is somewhat experimental. Probably more alternatives will be added. This could +%D become a delayed loaded module at some point (no real consequences). + +\unprotect + +\registerctxluafile{page-inj}{} + +\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_indeed + {\scrn_canvas_synchronize_set{\pageinjectionparameter\c!width}{\pageinjectionparameter\c!height}% + \invokepagehandler\v!normal{\inheritedpageinjectionframed{\texsetup\p_page_injectionalternative_rederingsetup}}% + \scrn_canvas_synchronize_reset} + +\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 + \page_injections_flush_indeed + \endgroup} + +\permanent\tolerant\protected\def\pageinjection[#1]#*[#2]% name parameters | settings parameters | name | parameters + {\begingroup + \ifhastok={#1}% + \ifhastok={#2}% + \page_injections_direct_settings_parameters{#1}{#2}% + \else + \page_injections_direct_parameters{#1}% + \fi + \else + \ifhastok={#2}% + \page_injections_direct_name_parameters{#1}{#2}% + \else + \page_injections_direct_name{#1}% + \fi + \fi} + +\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% + {\ifempty\p_page_injections_page + \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 + \forgetparindent + \dontcomplain + \setconstant\shipoutfinalizemethod\zerocount % this is messy + \page_injections_flush_indeed + \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!setups]% 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/tex/context/base/mkxl/page-ins.mkxl b/tex/context/base/mkxl/page-ins.mkxl new file mode 100644 index 000000000..cb6e3e3f4 --- /dev/null +++ b/tex/context/base/mkxl/page-ins.mkxl @@ -0,0 +1,209 @@ +%D \module +%D [ file=page-ins, +%D version=2002.04.16, % was core-ins +%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}{} + +\unprotect + +%D Because we need to deal with inserts at the \LUA\ end as well, we provide a +%D proper installer. + +\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] + +\newconstant\insertionmigrationmode + +\def\page_inserts_check_anchoring + {\edef\p_anchoring{\namedinsertionparameter\empty\c!anchoring}% + \insertionmigrationmode\ifx\p_anchoring\v!auto\plusone\else\zerocount\fi + \clf_setinsertmigration{\p_anchoring}} + +\appendtoks + \ifx\currentinsertionparent\empty + \page_inserts_check_anchoring + \fi +\to \everysetupinsertion + +\setupinsertion + [\c!anchoring=\v!auto] + +\appendtoks + \page_inserts_check_anchoring +\to \everystarttext % or \everyjob + +\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. + +\permanent\protected\def\setcurrentinsertion#1% + {\edef\currentinsertion{#1}% + \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname} + +\permanent\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname} + +\protected\def\page_inserts_synchronize_registers + {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname} + +% for practical reasons we still set these elsewhere but that might change 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} +% \floatingpenalty\zerocount + +\appendtoks + \ifx\currentinsertionparent\empty \else + \page_inserts_synchronize_registers + \fi +\to \everysetupinsertion + +\protected\def\page_inserts_process#1% beware, this adapts currentinsertion ! + {\edef\currentinsertion{#1}% + \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname + \doprocessinsert\currentinsertionnumber} % old method + +\permanent\protected\def\processinsertions + {\the\t_page_inserts_list} + +\permanent\protected\def\synchronizeinsertions + {\let\doprocessinsert\page_inserts_synchronize + \processinsertions} + +\protected\def\page_inserts_synchronize#1% yes or no + {\ifvoid#1\else + \insert#1{\unvbox#1}% + \fi} + +\permanent\protected\def\doifelseinsertion#1% + {\ifcsname\??insertionnumber#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifinsertionelse\doifelseinsertion + +% \protected\def\startinsertion[#1]% +% {\insert\csname\??insertionnumber#1\endcsname\bgroup} +% +% \protected\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 + \letcsname\??insertionnumber\currentinsertion\expandafter\endcsname + \csname\??insertionnumber\currentinsertionparent\endcsname + \fi +\to \everydefineinsertion + +\appendtoks + \ifx\currentinsertionparent\empty \else + \clf_setupinsertion + {\currentinsertion} + {% + location {\insertionparameter\c!location}% + }% + \relax + \fi +\to \everysetupinsertion + +\protected\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} +% +% \protected\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} +% +% \protected\def\saveinsertionbox#1% hm, actually unknown +% {\global\setbox\csname\??insertionbackup\string#1\endcsname +% \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi} +% +% \protected\def\restoreinsertionbox#1% +% {\ifvoid\backupinsertion#1\else % if void, we keep the content +% \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname +% \fi} +% +% \protected\def\eraseinsertionbackup#1% +% {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox} +% +% \protected\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} +% +% \protected\def\restoreinsertiondata#1% +% {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname +% \global\count#1\count\csname\??insertionbackup\string#1\endcsname +% \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-lay.mkxl b/tex/context/base/mkxl/page-lay.mkxl new file mode 100644 index 000000000..230315a03 --- /dev/null +++ b/tex/context/base/mkxl/page-lay.mkxl @@ -0,0 +1,1623 @@ +%D \module +%D [ file=page-lay, +%D version=2000.10.20, % copied from main-001 +%D title=\CONTEXT\ Page Macros, +%D subtitle=Layout Specification, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Layout Specification} + +%D Before you start wondering why some of the page related modules skip upward or +%D left in order to place elements, you must realize that the reference point is the +%D top left corner of the main typesetting area. One reason for this choice is that +%D it suited some viewers that displayed page areas. Another reason is that margins, +%D edges and top and bottom areas are kind of virtual, while the header, text and +%D footer areas normally determine the text flow. + +\unprotect + +%D The dimensions related to layout areas are represented by real dimensions. + +\newdimen\paperheight \paperheight = 297mm +\newdimen\paperwidth \paperwidth = 210mm +\newdimen\paperoffset \paperoffset = \zeropoint +\newdimen\paperbleed \paperbleed = \zeropoint +\newdimen\spinewidth \spinewidth = \zeropoint + +\newdimen\printpaperheight \printpaperheight = \paperheight +\newdimen\printpaperwidth \printpaperwidth = \paperwidth + +\newdimen\makeupheight % calculated +\newdimen\makeupwidth % calculated + +\newdimen\textheight % calculated +\newdimen\textwidth % calculated + +\newdimen\topspace \topspace = 2cm +\newdimen\backspace \backspace = \topspace +\newdimen\cutspace \cutspace = \zeropoint +\newdimen\bottomspace \bottomspace = \zeropoint + +\newdimen\headerheight \headerheight = 2cm +\newdimen\footerheight \footerheight = \headerheight + +\newdimen\topoffset \topoffset = \zeropoint +\newdimen\backoffset \backoffset = \topoffset + +\newdimen\leftmarginwidth \leftmarginwidth = 3cm +\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth + +\newdimen\leftedgewidth \leftedgewidth = 3cm +\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth + +\newdimen\topheight \topheight = \zeropoint +\newdimen\bottomheight \bottomheight = \topheight + +\newcount\layoutlines \layoutlines = \zerocount +\newcount\layoutcolumns \layoutcolumns = \zerocount +\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint +\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint + +\newdimen\totaltextwidth + +%D The next series of dimensions are complemented by left and rights ones. + +\newdimen\margindistance +\newdimen\edgedistance +\newdimen\marginwidth +\newdimen\edgewidth + +%D Because a distance does not really makes sense when there is no area, we use a +%D zero distance in case there is no area. + +%D The horizontal distances are: + +\newdimen\leftedgedistance +\newdimen\rightedgedistance +\newdimen\leftmargindistance +\newdimen\rightmargindistance + +%D The vertical distances are: + +\newdimen\topdistance +\newdimen\headerdistance +\newdimen\textdistance +\newdimen\footerdistance +\newdimen\bottomdistance + +\newdimen\textovershoot % available in pagebuilder + +%D We need to calculate the extra distances: + +\newdimen\naturalmarginwidth +\newdimen\naturaledgewidth +\newdimen\naturalmargindistance +\newdimen\naturaledgedistance +\newdimen\naturalleftedgedistance +\newdimen\naturalrightedgedistance +\newdimen\naturalleftmargindistance +\newdimen\naturalrightmargindistance +\newdimen\naturaltopdistance +\newdimen\naturalheaderdistance +\newdimen\naturaltextdistance +\newdimen\naturalfooterdistance +\newdimen\naturalbottomdistance + +%D Now we've come to the setup and definition commands. + +\installcorenamespace{layout} +\installcorenamespace{layoutlocation} +\installcorenamespace{layoutalternative} +\installcorenamespace{layoutcolumn} +\installcorenamespace{layoutmethod} + +\installswitchcommandhandler \??layout {layout} \??layout + +\appendtoks + \doifnothing{\directlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}% +\to \everydefinelayout + +\appendtoks + \ifcase\layoutsetupmode + % can't happen + \or % \setuplayout[name][key=value] + \ifx\previouslayout\currentlayout + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \let\currentlayout\currentlayout + \page_layouts_synchronize + \page_layouts_check_next + \fi + \or % \setuplayout[key=value] + % we can inherit so we always synchronize + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \let\currentlayout\previouslayout + \page_layouts_synchronize + \page_layouts_check_next + \or % \setuplayout[name] + \ifx\currentlayout\v!reset + \let\currentlayout\empty + \fi + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \glet\currentlayout\currentlayout % global + \page_layouts_synchronize + \page_layouts_check_next + \or % \setuplayout (reverts to main layout) + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \glet\currentlayout\empty % global + \page_layouts_synchronize + \page_layouts_check_next + \fi +\to \everysetuplayout + +\permanent\def\doifelselayoutdefined#1% + {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflayoutdefinedelse\doifelselayoutdefined + +\permanent\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi} + +% \newconditional\reverselayout + +\def\page_layouts_set_dimensions + {\global\naturalmarginwidth \layoutparameter\c!margin + \global\naturaledgewidth \layoutparameter\c!edge + \global\naturalmargindistance \layoutparameter\c!margindistance + \global\naturaledgedistance \layoutparameter\c!edgedistance + \global\naturalleftedgedistance \layoutparameter\c!leftedgedistance + \global\naturalrightedgedistance \layoutparameter\c!rightedgedistance + \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance + \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance + \global\naturaltopdistance \layoutparameter\c!topdistance + \global\naturalheaderdistance \layoutparameter\c!headerdistance + \global\naturaltextdistance \layoutparameter\c!textdistance + \global\naturalfooterdistance \layoutparameter\c!footerdistance + \global\naturalbottomdistance \layoutparameter\c!bottomdistance + % + \global\marginwidth \naturalmarginwidth + \global\edgewidth \naturaledgewidth + \global\margindistance \naturalmargindistance + \global\edgedistance \naturaledgedistance + % + \global\leftedgedistance \layoutdistance\leftedgewidth \naturalleftedgedistance + \global\rightedgedistance \layoutdistance\rightedgewidth \naturalrightedgedistance + \global\leftmargindistance \layoutdistance\leftmarginwidth \naturalleftmargindistance + \global\rightmargindistance \layoutdistance\rightmarginwidth\naturalrightmargindistance + \global\topdistance \layoutdistance\topheight \naturaltopdistance + \global\headerdistance \layoutdistance\headerheight \naturalheaderdistance + \global\textdistance \naturaltextdistance + \global\footerdistance \layoutdistance\footerheight \naturalfooterdistance + \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance} + +\def\page_layouts_set_distances % local in \setreducedvsize + {\headerdistance\layoutdistance\headerheight\naturalheaderdistance + \footerdistance\layoutdistance\footerheight\naturalfooterdistance} + +% these are wrong in the running text, assumes some swapping, needs a cleanup + +\newtoks\extralayoutcalculations + +\def\page_layouts_calculate_extras + {\the\extralayoutcalculations} + +\newtoks\everyswapmargins % watch the order ! + +\appendtoks + \enforced\swapcsvalues\leftmargindistance\rightmargindistance + \enforced\swapcsvalues\leftedgedistance \rightedgedistance + \enforced\swapcsvalues\leftmarginwidth \rightmarginwidth + \enforced\swapcsvalues\leftedgewidth \rightedgewidth + % + \enforced\swapcsvalues\leftmargintotal \rightmargintotal + \enforced\swapcsvalues\leftedgetotal \rightedgetotal + \enforced\swapcsvalues\leftsidetotal \rightsidetotal + \enforced\swapcsvalues\leftcombitotal \rightcombitotal + \enforced\swapcsvalues\innermargintotal \outermargintotal + \enforced\swapcsvalues\inneredgetotal \outeredgetotal + \enforced\swapcsvalues\innercombitotal \outercombitotal + \enforced\swapcsvalues\innersidetotal \outersidetotal +\to \everyswapmargins + +%D The papersize macros have a long history and we don't want to change the commands +%D so they keep looking a bit complex. + +%D \macros +%D {definepapersize} +%D +%D Before we start calculating layout dimensions, we will first take care of paper +%D sizes. The first argument can be either an assignment (for defaults) or an +%D identifier, in which case the second argument is an assignment. +%D +%D \showsetup{definepapersize} +%D +%D Yet undocumented, let's see if it gets noticed. +%D +%D \starttyping +%D \definepapersize[main] [A4] [A4] +%D \definepapersize[extra][A4,landscape][A4,landscape] +%D +%D \starttext +%D \setuppapersize[main] +%D Page 1. \page +%D Page 2. \page +%D \setuppapersize[extra] +%D Page 2 \page +%D \setuppapersize[main] +%D Page 3. \page +%D Page 4. \page +%D \adaptpapersize[extra] +%D Page 5. \page +%D Page 6. \page +%D \stoptext +%D \stoptyping +%D +%D \macros +%D {setuppaper,setuppapersize} +%D +%D When setting up the papersize on which to typeset and print, we can also +%D determine some more characteristics. +%D +%D \showsetup{setuppapersize} +%D +%D We keep track of these features with the following +%D variables. + +\installcorenamespace{layouttarget} +\installcorenamespace{layoutpaper} +\installcorenamespace{layoutprint} +\installcorenamespace{layoutcurrent} + +\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler + +\newconditional\c_page_target_paper_mirror +\newconstant \c_page_target_paper_orientation +\newconstant \c_page_target_paper_reverse +\newconditional\c_page_target_paper_landscape +\newconditional\c_page_target_paper_negate + +\newconditional\c_page_target_print_mirror +\newconstant \c_page_target_print_orientation +\newconstant \c_page_target_print_reverse +\newconditional\c_page_target_print_landscape +\newconditional\c_page_target_print_negate +\newconditional\c_page_target_print_doublesided + +\let\v_page_target_left_fill \relax +\let\v_page_target_right_fill \relax +\let\v_page_target_top_fill \relax +\let\v_page_target_bottom_fill\relax + +\let\papersize \empty +\let\printpapersize\empty + +\def\v_page_target_top {\namedlayouttargetparameter\papersize\c!top } +\def\v_page_target_bottom {\namedlayouttargetparameter\papersize\c!bottom} +\def\v_page_target_left {\namedlayouttargetparameter\papersize\c!left } +\def\v_page_target_right {\namedlayouttargetparameter\papersize\c!right } +\def\v_page_target_method {\rootlayouttargetparameter \c!method} +\def\v_page_target_scale {\rootlayouttargetparameter \c!scale } +\def\v_page_target_nx {\numexpr\rootlayouttargetparameter \c!nx \relax} +\def\v_page_target_ny {\numexpr\rootlayouttargetparameter \c!ny \relax} +\def\v_page_target_dx {\dimexpr\rootlayouttargetparameter \c!dx \relax} +\def\v_page_target_dy {\dimexpr\rootlayouttargetparameter \c!dy \relax} +\def\v_page_target_width {\dimexpr\rootlayouttargetparameter \c!width \relax} +\def\v_page_target_height {\dimexpr\rootlayouttargetparameter \c!height \relax} +\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter \c!topspace \relax} +\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter \c!backspace\relax} +\def\v_page_target_offset {\dimexpr\rootlayouttargetparameter \c!offset \relax} + +\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax} + +%D Normally we will not use this command directly but for now it works out okay. In +%D the future we might use more of the related commands. + +\setuplayouttarget + [% these are rather special + \c!nx=1, + \c!ny=1, + \c!dx=\zeropoint, + \c!dy=\zeropoint, + \c!topspace=\zeropoint, + \c!backspace=\zeropoint, + \c!width=\zeropoint, + \c!height=\zeropoint, + % + \c!method=\v!normal, + \c!option=\v!max, + \c!alternative=\v!normal, + % + \c!scale=1, + \c!offset=\zeropoint, + % + \c!top=, + \c!bottom=, + \c!left=, + \c!right=, + % + \c!location=] + +% \definepapersize[name][A4][A3] +% \definepapersize[name][settings] + +\permanent\tolerant\protected\def\definepapersize[#1]#*[#2]#*[#3]% + {\edef\currentlayouttarget{#1}% + \ifempty\currentlayouttarget + % invalid target + \orelse\ifhastok={#2}% + \definelayouttarget[#1][#2]% + \else + \setevalue{\??layoutpaper#1}{#2}% + \ifparameter#3\or + \setevalue{\??layoutprint#1}{#3}% + \else + \setevalue{\??layoutprint#1}{#2}% + \fi + \fi} + +\appendtoks + \letvalue{\??layoutcurrent\currentlayouttarget}\relax +\to \everydefinelayouttarget + +%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi} +%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi} + +\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi} +\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi} + +% \setuppaper [page=A4,paper=A3] % the k/v variant, changes the current page mapping +% \setuppapersize[A4][a=b,c=d] % the k/v variant, changes nothing, just settings +% \setuppapersize[A4][A3] % changes the current page mapping + +\let\page_paper_reinstate\relax +\let\page_paper_restore \relax + +\permanent\tolerant\protected\def\setuppapersize[#1]#*[#2]% + {\ifarguments + \page_paper_restore + \orelse\ifhastok={#1}% + \page_paper_setup_size_settings[#1]% + \orelse\ifhastok={#2}% + \page_paper_setup_size_settings_by_name[#1][#2]% + \else + \page_paper_setup_size_change_size[#1][#2]% + \fi} + +\protected\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size + {\let\currentlayouttarget\empty + \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% + \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% + \setupcurrentlayouttarget[#1]% + \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% + \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% + \ifx\m_layouttarget_paper_saved\m_layouttarget_paper + \ifx\m_layouttarget_print_saved\m_layouttarget_print + % we didn't change the size, maybe only sx or sy or so + \else + \page_paper_setup_size_settings_recalibrate + \fi + \else + \page_paper_setup_size_settings_recalibrate + \fi} + +\def\page_paper_setup_size_settings_recalibrate + {\ifempty\m_layouttarget_paper + % forget about it + \else + \ifempty\m_layouttarget_print + \let\m_layouttarget_print\m_layouttarget_paper + \fi + \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]% + \fi + \letlayouttargetparameter\c!page \papersize + \letlayouttargetparameter\c!paper\printpapersize} + +\protected\def\page_paper_setup_size_settings_by_name[#1][#2]% + {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}% + \setuplayouttarget[#2]} + +\protected\def\page_paper_setup_size_change_size[#1][#2]% + {\doifelsenothing{#2} + {\page_paper_set_current[#1][#1]} + {\page_paper_set_current[#1][#2]}} + +\permanent\let\setuppaper\page_paper_setup_size_settings + +\permanent\protected\def\adaptpapersize + {\glet\page_paper_reinstate\page_paper_restore + \setuppapersize} + +\appendtoks + \page_paper_reinstate + \glet\page_paper_reinstate\relax +\to \everyaftershipout + +\protected\def\page_paper_set_restore#1#2% + {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}} + +\protected\def\page_paper_set_current[#1][#2]% + {\normalexpanded{\page_paper_set_current_indeed + [\page_paper_the_paper_size{#1}]% + [\page_paper_the_print_size{#2}]}} + +\protected\def\page_paper_reset_paper + {\global\setfalse\c_page_target_paper_landscape + \global\setfalse\c_page_target_paper_mirror + \global\setfalse\c_page_target_paper_negate + \global\c_page_target_paper_orientation\uprotationangle + \global\c_page_target_paper_reverse \uprotationangle} + +\protected\def\page_paper_reset_print + {\global\setfalse\c_page_target_print_landscape + \global\setfalse\c_page_target_print_mirror + \global\setfalse\c_page_target_print_negate + \global\c_page_target_print_orientation\uprotationangle + \global\c_page_target_print_reverse \uprotationangle} + +\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper +\letvalue{\??layoutprint\v!reset}\page_paper_reset_print + +\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape} +\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror} +\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate} +\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} +\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} +\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle + \global\c_page_target_paper_reverse \zerocount} +\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle + \global\c_page_target_paper_reverse \rightrotationangle} + +\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape} +\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror} +\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate} +\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} +\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} +\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle + \global\c_page_target_print_reverse \zerocount} +\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle + \global\c_page_target_print_reverse \rightrotationangle} + +%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi} +%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi} + +\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname} +\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname} + +\protected\def\page_paper_identify_target#1% + {\ifcsname\??layoutcurrent#1\endcsname + \edef\currentlayouttarget{#1}% + \fi} + +\newdimen\d_page_minimum_paper_size \d_page_minimum_paper_size\luaexpr{math.pi}\onebasepoint + +\protected\def\page_paper_set_current_indeed[#1][#2]% + {\edef\m_page_asked_paper{#1}% can be the restores + \edef\m_page_asked_print{#2}% + % + \page_paper_set_restore\m_page_asked_paper\m_page_asked_print + % + % locate page target + \let\currentlayouttarget\empty + \page_paper_reset_paper + \processcommacommand[\m_page_asked_paper]\page_paper_identify_target + \ifempty\currentlayouttarget + \let\currentlayouttarget\currentpage + \fi + \glet\papersize\currentlayouttarget + \page_paper_reset_paper + \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option + \global\paperwidth \layouttargetparameter\c!width \relax + \global\paperheight\layouttargetparameter\c!height\relax + \ifdim\paperwidth<\d_page_minimum_paper_size + \global\paperwidth\d_page_minimum_paper_size + \fi + \ifdim\paperheight<\d_page_minimum_paper_size + \global\paperheight\d_page_minimum_paper_size + \fi + \ifconditional\c_page_target_paper_landscape + \enforced\global\swapcsvalues\paperwidth\paperheight + \fi + \ifinpagebody % local freeze + \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}% + \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}% + \fi + % + \page_paper_set_offsets + % locate paper target + \page_paper_reset_print + \processcommacommand[\m_page_asked_print]\page_paper_identify_target + \glet\printpapersize\currentlayouttarget + \page_paper_reset_print + \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option + \global\printpaperwidth \layouttargetparameter\c!width \relax + \global\printpaperheight\layouttargetparameter\c!height\relax + \ifdim\printpaperwidth<\onepoint + \global\printpaperwidth\paperwidth + \fi + \ifdim\printpaperheight<\onepoint + \global\printpaperheight\paperheight + \fi + \ifconditional\c_page_target_print_landscape + \enforced\global\swapcsvalues\printpaperwidth\printpaperheight + \fi + % this check can be confusing, so we've added the possibility + % to bypass this test: \setuppapersize[option=fit] + \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}% + \ifx\m_page_asked_option\v!max % \v!fit is + \begingroup + % we need to pre-swap else we get the wrong paper size + \ifnum\c_page_target_paper_orientation=\rightrotationangle + \enforced\swapcsvalues\paperwidth\paperheight + \orelse\ifnum\c_page_target_paper_orientation=\leftrotationangle + \enforced\swapcsvalues\paperwidth\paperheight + \fi + \ifnum\c_page_target_print_orientation=\rightrotationangle + \enforced\swapcsvalues\printpaperwidth\printpaperheight + \orelse\ifnum\c_page_target_print_orientation=\leftrotationangle + \enforced\swapcsvalues\printpaperwidth\printpaperheight + \fi + \ifdim\paperheight>\printpaperheight + \global\printpaperheight\paperheight + \writestatus\m!system{print height forced to paper height}% + \fi + \ifdim\paperwidth>\printpaperwidth + \global\printpaperwidth\paperwidth + \writestatus\m!system{print width forced to paper width}% + \fi + \endgroup + \fi + %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}% + \page_layouts_synchronize + % new but we assume \setuplayout + \scrn_canvas_synchronize_only} + +\ifdefined\scrn_canvas_synchronize_only \else + \let\scrn_canvas_synchronize_only\relax +\fi + +\ifdefined\page_paper_set_offsets \else + + \def\page_paper_set_offsets % will move + {\global\paperoffset\v_page_target_offset + \global\advance\paperwidth -2\paperoffset + \global\advance\paperheight-2\paperoffset} + +\fi + +\ifdefined\synchronizegridsnapping \else + \let\synchronizegridsnapping\relax +\fi + +\let\p_page_layouts_width \empty +\let\p_page_layouts_height\empty + +\def\page_layouts_synchronize + {\setups[\layoutparameter\c!preset]\relax + \global\leftmarginwidth \layoutparameter\c!leftmargin + \global\rightmarginwidth\layoutparameter\c!rightmargin + \global\leftedgewidth \layoutparameter\c!leftedge + \global\rightedgewidth \layoutparameter\c!rightedge + \global\headerheight \layoutparameter\c!header + \global\footerheight \layoutparameter\c!footer + \global\bottomheight \layoutparameter\c!bottom + \global\topheight \layoutparameter\c!top + \global\backspace \layoutparameter\c!backspace + \global\topspace \layoutparameter\c!topspace + \page_layouts_set_dimensions + \synchronizegridsnapping + \usesetupsparameter\layoutparameter % depends on gridsnapping ! + \synchronizewhitespace + \synchronizeblank + \setupinterlinespace[\v!reset]% \synchronizegloballinespecs + \global\cutspace\layoutparameter\c!cutspace\relax + \edef\p_page_layouts_width{\layoutparameter\c!width}% + \ifx\p_page_layouts_width\v!middle + \ifzeropt\cutspace + \global\cutspace\backspace + \fi + \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax + \orelse\ifx\p_page_layouts_width\v!fit + \ifzeropt\cutspace + \global\cutspace\backspace + \fi + \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax + \scratchdimen\dimexpr\backspace + -\leftedgewidth -\leftedgedistance + -\leftmarginwidth-\leftmargindistance\relax + \ifdim\scratchdimen<\zeropoint + \scratchdimen\zeropoint + \fi + \global\advance\makeupwidth\dimexpr + -\rightmargindistance-\rightmarginwidth + -\rightedgedistance -\rightedgewidth + -\scratchdimen\relax + \else + \global\makeupwidth\p_page_layouts_width\relax + \ifzeropt\cutspace + \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax + % \else + % A kind of inconsistent specification, but used + % in for instance s-pre-19.tex; the cutspace is + % used only for determining some kind of right + % margin; don't use this in doublesided mode + \fi + \fi + \scratchdimen\layoutparameter\c!bottomspace\relax + %\ifzeropt\scratchdimen + % \scratchdimen\topspace + %\fi + \global\bottomspace\layoutparameter\c!bottomspace\relax + \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty + \ifcase\layoutlines + \edef\p_page_layouts_height{\layoutparameter\c!height}% + \ifx\p_page_layouts_height\v!middle + \ifzeropt\bottomspace + \global\bottomspace\topspace + \fi + \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax + \orelse\ifx\p_page_layouts_height\v!fit + \ifzeropt\bottomspace + \global\bottomspace\topspace + \fi + \global\makeupheight\dimexpr\paperheight-\bottomspace\relax + \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax + \ifdim\scratchdimen<\zeropoint + \scratchdimen\zeropoint + \fi + \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax + \else + \global\makeupheight\layoutparameter\c!height\relax + \ifzeropt\bottomspace + \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax + % \else + % inconsistent specification + \fi + \fi + \else + % beware, when the bodyfont changes (switched) this will change as well; implementing + % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set + % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we + % stick to the current method (after a night of experimenting ...2003/10/13) + \global\makeupheight\dimexpr + \layoutparameter\c!lines\lineheight-\strutheight+\topskip+ + \headerdistance+\headerheight+\footerdistance+\footerheight\relax + \fi + \backoffset\layoutparameter\c!horoffset\relax + \topoffset \layoutparameter\c!veroffset\relax + \ifdim\makeupwidth<\onepoint + \global\makeupwidth\onepoint + \fi + \ifdim\makeupheight<\onepoint + \global\makeupheight\onepoint + \fi + % handy in page builder + \global\totaltextwidth\dimexpr + \leftedgetotal + +\leftmargintotal + +\makeupwidth + +\rightmargintotal + +\rightedgetotal + \relax + % \page_layouts_check_next % here ? + \page_layouts_check_direction + \page_layouts_calculate_extras + \page_target_check_centering + \calculatehsizes + \calculatevsizes + \page_layouts_check_pseudo_columns + \page_backgrounds_recalculate} + +\def\page_layouts_check_direction + {\edef\p_direction{\layoutparameter\c!direction}% + \ifx\p_direction\v!reverse + \enforced\global\swapcsvalues\naturalleftedgedistance \naturalrightedgedistance + \enforced\global\swapcsvalues\naturalleftmargindistance\naturalrightmargindistance + \enforced\global\swapcsvalues\leftedgedistance \rightedgedistance + \enforced\global\swapcsvalues\leftmargindistance \rightmargindistance + \enforced\global\swapcsvalues\leftmarginwidth \rightmarginwidth + \enforced\global\swapcsvalues\leftedgewidth \rightedgewidth + \enforced\global\swapcsvalues\backspace \cutspace + \expandafter\setsystemmode + \else + \expandafter\resetsystemmode + \fi{reverselayout}} + +\def\page_layouts_check_pseudo_columns + {\global\layoutcolumns\layoutparameter\c!columns + \global\layoutcolumndistance\layoutparameter\c!columndistance + \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax + \ifnum\layoutcolumns>\plusone + \global\divide\layoutcolumnwidth\layoutcolumns + \dorecurse\layoutcolumns\page_layouts_check_pseudo_column + \fi} + +\def\page_layouts_check_pseudo_column + {\setxvalue{\??layoutcolumn\recurselevel}% + {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}} + +\letvalue{\??layoutcolumn0}\zeropoint + +\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs + {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname} + +\def\page_layouts_synchronize_at_start + {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check + \page_layouts_synchronize + \fi} + +\appendtoks + \page_layouts_synchronize_at_start % still needed? +\to \everystarttext + +% document: +% +% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page] +% +% \startstandardmakeup[page=blank] ... \stopstandardmakeup + +\ifdefined\lastpage \else \let\lastpage\!!plusone \fi + +\permanent\protected\def\page_layouts_change#1% + {%\writestatus\m!layouts{changing to layout #1}% + \xdef\currentlayout{#1}% + \page_layouts_synchronize} + +\aliased\let\changetolayout\page_layouts_change % also public + +\def\v_real_page_normal {\the\realpageno} +\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax} + +\def\v_real_page_odd_or_even + {\ifodd\pagenoshift + \ifodd\realpageno\v!even\else\v!odd \fi + \else + \ifodd\realpageno\v!odd \else\v!even\fi + \fi} + +\let\v_real_page_current\v!current + +\def\v_real_page_named + {\ifnum\lastpage=\realpageno + \v!last + \orelse\ifnum\plusone=\realpageno + \v!first + \else + \__unknown__ + \fi} + +\let\v_page_layouts_pre_check\relax + +\def\page_layouts_check_default_indeed#1% + {\edef\m_page_check{#1} + \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}% + \ifx\m_page_state\v!start + \glet\v_page_layouts_pre_check\currentlayout + \glet\currentlayout\m_page_check + \page_layouts_synchronize + \orelse\ifx\m_page_state\v!repeat + \glet\v_page_layouts_pre_check\relax + \glet\currentlayout\m_page_check + \page_layouts_synchronize + \fi} + +\def\page_layouts_check_revert + {\glet\currentlayout\v_page_layouts_pre_check + \glet\v_page_layouts_pre_check\relax + \page_layouts_synchronize} + +\def\page_layouts_check_default + {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_normal + \orelse\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_reverse + \orelse\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_named + \orelse\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_current + \orelse\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_odd_or_even + \orelse\ifx\v_page_layouts_pre_check\relax + % okay + \else + \page_layouts_check_revert + \fi} + +\permanent\protected\def\installlayoutmethod#1#2% + {\setgvalue{\??layoutmethod#1}{#2}} + +\installlayoutmethod\v!default{\page_layouts_check_default} +\installlayoutmethod\v!normal {\page_layouts_check_default} + +% \def\page_layouts_check_next +% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname +% \layoutparameter\c!method +% \else +% \v!normal +% \fi\endcsname} + +\permanent\protected\def\page_layouts_check_next + {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname + \lastnamedcs + \else + \page_layouts_check_default + \fi} + +\aliased\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay + +% inheritance +% +% \definelayout +% [test] +% [width=12cm, +% height=10cm] +% +% \definelayout +% [more] +% [test] +% [height=12cm] +% +% testcase +% +% \setuppagenumbering[alternative=doublesided] +% +% \setuplayout [width=11cm] +% \definelayout [odd] [backspace=1cm] +% \definelayout [even] [backspace=4cm] +% \definelayout [5] [backspace=5cm] +% \definelayout [6] [backspace=5cm] +% \definelayout [-2] [backspace=0cm,cutspace=0cm] +% \definelayout [last] [backspace=0cm,cutspace=0cm] +% +% \checkcurrentlayout \showframe +% +% \starttext +% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf} +% \stoptext + +% Because we want to keep the set parameters as they are we use some +% helpers to communicate between the several page building related +% mechanism. + +\appendtoks \page_layouts_check_next \to \everystarttext +\appendtoks \page_layouts_check_next \to \everyaftershipout + +\newconditional\c_page_layouts_location_is_set +\newconditional\c_page_layouts_location_is_middle + +\def\page_layouts_location_reset % we start in the left top and mirror right pages + {\setfalse\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \relax + \let\v_page_target_right_fill \hss % ? \relax + \let\v_page_target_top_fill \relax + \let\v_page_target_bottom_fill\vss} % \relax} + +\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill \relax} +\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \relax + \let\v_page_target_right_fill \hss} +\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\relax} +\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \relax + \let\v_page_target_bottom_fill\vss} +\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set + \settrue\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill \hss + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\vss} +\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_ + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_right_fill \hss + \let\v_page_target_bottom_fill\hss} +\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided} +\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided} + +\def\page_target_check_centering_indeed#1% + % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi} + {\begincsname\??layoutlocation#1\endcsname} + +\protected\def\page_target_check_centering + {\setfalse\c_page_target_print_doublesided + \page_layouts_location_reset + \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed} + +% installers + +\permanent\protected\def\installlayoutalternative#1#2% + {\setgvalue{\??layoutalternative#1}{#2}} + +\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box + {\setbox#1\vpack % was \vbox + {\offinterlineskip + \begingroup % needed ? + \uselayoutstyleandcolor\c!style\c!color + \offinterlineskip + \page_layouts_insert_elements % zero size + \endgroup + \page_insert_body#2#3}}% including footnotes + +\installlayoutalternative\v!default{\page_boxes_construct_content_default} +\installlayoutalternative\v!normal {\page_boxes_construct_content_default} + +% \def\page_boxes_construct_content % targetbox flusher box +% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname +% \layoutparameter\c!alternative +% \else +% \v!normal +% \fi\endcsname} + +\def\page_boxes_construct_content % targetbox flusher box + {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname + \expandafter\lastnamedcs + \else + \expandafter\page_boxes_construct_content_default + \fi} + +%D \macros +%D {adaptlayout} + +\installcorenamespace{adaptlayout} +\installcorenamespace{pageadaptations} + +\installsetuponlycommandhandler \??adaptlayout {adaptlayout} + +\newdimen\d_page_adepts_pushed_text_height +\newdimen\d_page_adepts_pushed_footer_height +\newdimen\d_page_adepts_height +\newdimen\d_page_adapts_delta + +\permanent\protected\tolerant\def\adaptlayout[#1]#*[#2]% + {\ifparameter#2\or + \processcommalist[#1]{\page_adapts_layout_register{#2}}% + \page_adapts_check + \else + \page_adapts_layout_indeed{#1}% + \fi} + +\def\page_adapts_layout_register#1#2% + {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}} + +\let\p_adapts_height\zeropoint +\let\p_adapts_lines \zerocount + +\def\page_adapts_layout_indeed#1% + {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]% + \page_adepts_push + \edef\p_adapts_height{\adaptlayoutparameter\c!height}% + \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}% + \ifx\p_adapts_height\v!max + \global\d_page_adepts_height\footerheight + \else + \global\d_page_adepts_height\dimexpr + \ifnum\p_adapts_lines=\zerocount + \p_adapts_height + \else + \p_adapts_lines\openlineheight + \fi + \relax + \ifdim\d_page_adepts_height>\footerheight + \global\d_page_adepts_height\footerheight + \fi + \fi + \global\advance\textheight \d_page_adepts_height + \global\advance\footerheight-\d_page_adepts_height + \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}% + % this will become a better one (do we need insert correction?) + \page_otr_command_set_vsize + % + \page_backgrounds_recalculate + \glet\page_adepts_push\relax + \glet\page_adepts_pop\page_adepts_pop_indeed} + +% \def\page_adapts_check +% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname} +% +% \def\page_adapts_reset +% {\ifcsname\??pageadaptations\the\realpageno\endcsname +% \global\undefinevalue{\??pageadaptations\the\realpageno}% +% \fi} + +\def\page_adapts_check + {\begincsname\??pageadaptations\the\realpageno\endcsname} + +\def\page_adapts_reset + {\ifcsname\??pageadaptations\the\realpageno\endcsname + \gletcsname\??pageadaptations\the\realpageno\endcsname\relax + \fi} + +\def\page_adepts_push_indeed + {\global\d_page_adepts_pushed_text_height \textheight + \global\d_page_adepts_pushed_footer_height\footerheight} + +\def\page_adepts_pop_indeed + {\global\textheight \d_page_adepts_pushed_text_height + \global\footerheight\d_page_adepts_pushed_footer_height + \page_layouts_synchronize + \glet\page_adepts_push\page_adepts_push_indeed + \glet\page_adepts_pop\relax} + +\appendtoks \page_adapts_check \to \everystarttext +\appendtoks \page_adapts_reset \to \everyshipout + +\let\page_adepts_pop \relax +\let\page_adepts_push\page_adepts_push_indeed + +\protected\def\page_adapts_synchronize % used elsewhere + {\page_adepts_pop + \page_adapts_check} + +\def\page_adapts_status_info % used elsewhere + {\ifx\page_adepts_pop\relax \else + \space(adept: \the\d_page_adepts_height)\space + \fi + \the\realpageno} + +%D \macros +%D {startlayout,stoplayout} + +\permanent\protected\def\startlayout[#1]% + {\page + \globalpushmacro\currentlayout + \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}} + +\permanent\protected\def\stoplayout + {\page + \globalpopmacro\currentlayout + \setuplayout[\currentlayout]} + +% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET + +\ifx\doifelselayoutsomeline\undefined % eventually defined in page-txt + \let\doifelselayoutsomeline\secondofthreearguments +\fi + +\permanent\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} +\permanent\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} +\permanent\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} +\permanent\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} + +\permanent\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances} +\permanent\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances} + +\def\page_layouts_set_modes + {\ifzeropt\headerheight + \resetsystemmode\v!header + \else + \setsystemmode\v!header + \fi + \ifzeropt\footerheight + \resetsystemmode\v!footer + \else + \setsystemmode\v!footer + \fi} + +\permanent\protected\def\calculatevsizes % name will change + {\textheight\makeupheight + \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing + \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing + \page_layouts_set_modes + \resetglobal + \page_otr_command_set_vsize} + +\permanent\protected\def\calculateglobalvsizes % name will change + {\global\textheight\makeupheight + \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing + \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing + \page_layouts_set_modes + \page_otr_command_set_vsize} + +\permanent\protected\def\calculatereducedvsizes % name will change + {\textheight\makeupheight + \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero + \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero} + +\newdimen\innermakeupwidth % special purpose +\newdimen\innermakeupmargin % special purpose + +\newconditional\innermakeupcompensation \settrue\innermakeupcompensation + +\permanent\def\compensatedinnermakeupmargin + {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax} + +\permanent\protected\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth + {\textwidth\makeupwidth % which is a tricky but valid value + \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }% + \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}% + \ifempty\m_currentlayout_text_width \else + \textwidth\m_currentlayout_text_width % local + \fi + \global\innermakeupwidth\textwidth + \ifempty\m_currentlayout_text_margin + \global\innermakeupmargin\zeropoint + \else + \global\innermakeupmargin\m_currentlayout_text_margin\relax + \fi + \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax + \global\advance\innermakeupwidth-\scratchdimen + \advance\textwidth-\scratchdimen} % local + +\permanent\protected\def\calculatehsizes % name will change + {\freezetextwidth + \page_otr_command_set_hsize} + +%D When we start at an even page, we need to swap the layout differently. We cannot +%D adapt the real page number, since it is used in cross referencing. The next +%D switch is set when we start at an even page. + +% #single #left #right + +\permanent\def\doifelseoddpage + {\ifodd\pagenoshift + \expandafter\page_layouts_if_odd_else_yes + \else + \expandafter\page_layouts_if_odd_else_nop + \fi} + +\aliased\let\doifoddpageelse\doifelseoddpage + +\def\page_layouts_if_odd_else_yes + {\ifodd\realpageno + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\def\page_layouts_if_odd_else_nop + {\ifodd\realpageno + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\def\page_layouts_if_odd_else_again#1{\doifelseoddpage} + +\permanent\def\doifbothsidesoverruled + {\ifdoublesided + \expandafter\page_layouts_if_odd_else_again + \else + \expandafter\firstofthreearguments + \fi} + +\permanent\def\doifbothsides% #1 #2 #3 + {\ifdoublesided + \expandafter\page_layouts_if_both_sides + \else + \expandafter\firstofthreearguments + \fi} + +\def\page_layouts_if_both_sides + {\ifsinglesided + \expandafter\firstofthreearguments + \else + \expandafter\page_layouts_if_odd_else_again + \fi} + +\newdimen\texthoffset + +\permanent\protected\def\settexthoffset % name will change + {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}} + +\permanent\protected\def\goleftonpage % name will change (we could cache) + {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax} + +\permanent\def\doifelsemarginswap#1#2% protected? + {\doifbothsides{#1}{#1}{#2}} + +\aliased\let\doifmarginswapelse\doifelsemarginswap + +\def\swapmargins % name will change, frozen? + {\doifelsemarginswap\relax\doswapmargins} + +\def\doswapmargins % name will change, frozen? + {\let\swapmargins \relax % to prevent local swapping + \let\doswapmargins\relax % to prevent local swapping + \the\everyswapmargins} + +\permanent\def\rightorleftpageaction + {\ifdoublesided + \expandafter\page_layouts_right_or_left_page_action + \else + \expandafter\firstoftwoarguments + \fi} + +\def\page_layouts_right_or_left_page_action + {\ifsinglesided + \expandafter\firstoftwoarguments + \else + \expandafter\doifelseoddpage + \fi} + +% swapping needs frozen + +\permanent\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth } +\permanent\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth} +\permanent\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance } +\permanent\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance} + +\permanent\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth } +\permanent\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth} +\permanent\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance } +\permanent\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance} + +\permanent\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace} +\permanent\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace } + +\permanent\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax} +\permanent\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax} +\permanent\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax} +\permanent\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax} + +\permanent\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax} +\permanent\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax} +\permanent\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax} +\permanent\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax} + +\permanent\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax} +\permanent\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax} +\permanent\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax} +\permanent\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax} + +\permanent\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax} +\permanent\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax} +\permanent\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax} +\permanent\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax} + +%D \macros +%D {startlocallayout} +%D +%D These macros should be used with care. They permit local layouts (as used in +%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we +%D have \type {\definelayout}, so this hack will disappear in future versions. + +\permanent\protected\def\startlocallayout + {\globalpushmacro\page_paper_restore + \globalpushmacro\currentlayout} + +\permanent\protected\def\stoplocallayout + {\globalpopmacro\currentlayout + \globalpopmacro\page_paper_restore + \page_paper_restore + \setuplayout[\currentlayout]\relax} % explicit ! + +%D \macros +%D {showprint, showframe, showlayout, showsetups} +%D +%D We predefine a couple of tracing macros. +%D +%D \showsetup{showprint} +%D \showsetup{showframe} +%D \showsetup{showlayout} +%D \showsetup{showsetups} +%D %showsetup{showmargins} +%D %showsetup{showgrid} +%D %showsetup{showusage} + +\fetchruntimecommand \showprint \f!page_run +\fetchruntimecommand \showframe \f!page_run +\fetchruntimecommand \showlayout \f!page_run +\fetchruntimecommand \showsetups \f!page_run +\fetchruntimecommand \showmargins \f!page_run +\fetchruntimecommand \showgrid \f!page_run + +\glet\page_grids_add_to_box\gobbleoneargument +\glet\page_grids_add_to_one\gobbleoneargument +\glet\page_grids_add_to_mix\gobbleoneargument + +%D The default dimensions are quite old and will not change. The funny fractions +%D were introduced when we went from fixed dimensions to relative ones. Since +%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The +%D asymmetrical layout is kind of handy for short quick||and||dirty stapled +%D documents. +%D +%D Although valid, it is not a real good idea to use dimensions based on the \type +%D {em} unit. First of all, since there are no fonts loaded yet, this dimension +%D makes no sense, and second, you would loose track of values, since they could +%D change while going to a new page, depending on the current font setting. + +\setuplayout + [ \c!topspace=.08417508418\paperheight, % 2.5cm + \c!top=\zeropoint, + \c!topdistance=\zeropoint, + \c!header=.06734006734\paperheight, % 2.0cm + \c!headerdistance=\zeropoint, + \c!height=.84175084175\paperheight, % 25.0cm + \c!footerdistance=\layoutparameter\c!headerdistance, + \c!footer=.06734006734\paperheight, % 2.0cm + \c!bottomdistance=\layoutparameter\c!topdistance, + \c!bottom=\zeropoint, + \c!backspace=.11904761905\paperwidth, % 2.5cm + \c!edge=\zeropoint, + \c!edgedistance=\layoutparameter\c!margindistance, + \c!margin=.12649983170\paperwidth, % snijwit-2*afstand + \c!margindistance=.02008341748\paperwidth, % 12.0pt + \c!leftedge=\layoutparameter\c!edge, + \c!leftedgedistance=\layoutparameter\c!edgedistance, + \c!leftmargin=\layoutparameter\c!margin, + \c!leftmargindistance=\layoutparameter\c!margindistance, + \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\ + \c!rightmargindistance=\layoutparameter\c!margindistance, + \c!rightmargin=\layoutparameter\c!margin, + \c!rightedgedistance=\layoutparameter\c!edgedistance, + \c!rightedge=\layoutparameter\c!edge, + \c!veroffset=\zeropoint, + \c!bottomspace=\zeropoint, + \c!horoffset=\zeropoint, + \c!cutspace=\zeropoint, + \c!textwidth=, % dangerous option -> centered / local + \c!textmargin=, % dangerous option -> both sides + \c!textdistance=\zeropoint, % shift down on grid + \c!style=, + \c!color=, + \c!marking=\v!off, + \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange) + \c!state=\v!start, + \c!scale=1, + \c!sx=1, + \c!sy=1, + \c!nx=1, + \c!ny=1, + \c!dx=\zeropoint, + \c!dy=\zeropoint, + \c!grid=\v!no, + \c!direction=\v!normal, + \c!preset=, + \c!setups=\systemsetupsprefix\s!default, + \c!clipoffset=\zeropoint, + \c!lines=0, + \c!paper=, % for foxet + \c!page=, % for foxet + \c!columns=\plusone, + \c!columndistance=\zeropoint] + +%D First we define a whole range of (DIN) papersizes, of which the A-series makes +%D most sense. We enable checking. + +\definepapersize [A0] [\c!width=841mm,\c!height=1189mm] +\definepapersize [A1] [\c!width=594mm,\c!height=841mm] +\definepapersize [A2] [\c!width=420mm,\c!height=594mm] +\definepapersize [A3] [\c!width=297mm,\c!height=420mm] +\definepapersize [A4] [\c!width=210mm,\c!height=297mm] +\definepapersize [A5] [\c!width=148mm,\c!height=210mm] +\definepapersize [A6] [\c!width=105mm,\c!height=148mm] +\definepapersize [A7] [\c!width=74mm,\c!height=105mm] +\definepapersize [A8] [\c!width=52mm,\c!height=74mm] +\definepapersize [A9] [\c!width=37mm,\c!height=52mm] +\definepapersize [A10] [\c!width=26mm,\c!height=37mm] + +\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm +%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide + +\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm] +\definepapersize [B1] [\c!width=707mm,\c!height=1000mm] +\definepapersize [B2] [\c!width=500mm,\c!height=707mm] +\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm] +\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm] +\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm] +\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm] +\definepapersize [B7] [\c!width=88mm,\c!height=125mm] +\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm] +\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm] +\definepapersize [B10] [\c!width=31mm,\c!height=44mm] + +\definepapersize [C0] [\c!width=917mm,\c!height=1297mm] +\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm] +\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm] +\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm] +\definepapersize [C4] [\c!width=229mm,\c!height=324mm] +\definepapersize [C5] [\c!width=162mm,\c!height=229mm] +\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm] +\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm] +\definepapersize [C8] [\c!width=57mm,\c!height=81mm] +\definepapersize [C9] [\c!width=40mm,\c!height=57mm] +\definepapersize [C10] [\c!width=28mm,\c!height=40mm] + +%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the +%D latest DIN specifications. Peter Rolf came up with these and a few more missing +%D sizes. Watch out: spaces and slashes! + +\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm] +\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm] +\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm] + +%D Because there are no standardized screen sizes, we define a bunch of sizes with +%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4} +%D paper. + +\definepapersize [S3] [\c!width=300pt,\c!height=225pt] +\definepapersize [S4] [\c!width=400pt,\c!height=300pt] +\definepapersize [S5] [\c!width=500pt,\c!height=375pt] +\definepapersize [S6] [\c!width=600pt,\c!height=450pt] +\definepapersize [S8] [\c!width=800pt,\c!height=600pt] +\definepapersize [SL] [\c!width=640pt,\c!height=400pt] % low +\definepapersize [SM] [\c!width=720pt,\c!height=450pt] % medium +\definepapersize [SW] [\c!width=800pt,\c!height=450pt] % wide +\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt] +\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt] +\definepapersize [HD-] [\c!width=960pt,\c!height=540pt] + +%D These are handy too: + +\definepapersize [S33] [\c!width=300pt,\c!height=300pt] +\definepapersize [S44] [\c!width=400pt,\c!height=400pt] +\definepapersize [S55] [\c!width=500pt,\c!height=500pt] +\definepapersize [S66] [\c!width=600pt,\c!height=600pt] + +%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it +%D does not hurt to have the paper size ready. + +\definepapersize [CD] [\c!width=120mm,\c!height=120mm] + +%D The next series is for our English speaking friends who decided to stick to non +%D metric values. Thanks to Nelson Beebe for completing the inch based list. + +\definepapersize [letter] [\c!width=8.5in,\c!height=11in] +\definepapersize [ledger] [\c!width=11in,\c!height=17in] +\definepapersize [tabloid] [\c!width=17in,\c!height=11in] + +\definepapersize [legal] [\c!width=8.5in,\c!height=14in] +\definepapersize [folio] [\c!width=8.5in,\c!height=13in] +\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in] + +\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet +\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets +\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets + +%D The next set is for Tobias Burnus, who gave me the sizes. + +\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in] +\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in] +\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in] +\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in] +\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in] +\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in] +\definepapersize [check] [\c!width=8.58in,\c!height=3.88in] +\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm] +\definepapersize [E4] [\c!width=280mm,\c!height=400mm] + +%D The next three sets are supplied by Taco: + +\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm] +\definepapersize [RA1] [\c!width=610mm,\c!height=860mm] +\definepapersize [RA2] [\c!width=430mm,\c!height=610mm] +\definepapersize [RA3] [\c!width=305mm,\c!height=430mm] +\definepapersize [RA4] [\c!width=215mm,\c!height=305mm] + +%D ISO SRA (supplementary raw A) sizes: + +\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm] +\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm] +\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm] +\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm] +\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm] + +%D Swedish thesis formats: + +\definepapersize [G5] [\c!width=169mm,\c!height=239mm] +\definepapersize [E5] [\c!width=155mm,\c!height=220mm] + +%D Industry invention: + +\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm] + +%D For Alan: + +\definepapersize [business] [\c!width=85mm,\c!height=55mm] +\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in] + +%D We can now default to a reasonable size. We match the print paper size with the +%D typeset paper size. This setting should come after the first layout specification +%D (already done). + +% \definepapersize +% [\v!default] +% [ \c!width=\paperwidth, +% \c!height=\paperheight] + +% \definepapersize +% [samesized] +% [ \c!width=\paperwidth, +% \c!height=\paperheight] + +\setuppapersize + [\c!distance=1.5cm] % offset is already taken + +\definepapersize + [oversized] + [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax] + +\definepapersize + [undersized] + [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax] + +\definepapersize + [doublesized] + [ \c!width=\dimexpr \paperwidth \relax, + \c!height=\dimexpr2\paperheight\relax] + +\definepapersize + [doubleoversized] + [ \c!width=\dimexpr \paperwidth +\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr2\paperheight+\layouttargetparameter\c!distance\relax] + +\definepapersize + [doublewide] + [ \c!width=\dimexpr2\paperwidth \relax, + \c!height=\dimexpr \paperheight\relax] + +% \setuppapersize +% [A4][A4] + +\setuppapersize + [A4] % [samesized] + +%D A few goodies, first a full page layout: + +\definelayout + [\v!page] + +\setuplayout + [\v!page] + [\c!backspace=\zeropoint, + \c!cutspace=\zeropoint, + \c!topspace=\zeropoint, + \c!bottomspace=\zeropoint, + \c!margin=\zeropoint, + \c!edge=\zeropoint, + \c!header=\zeropoint, + \c!footer=\zeropoint, + \c!top=\zeropoint, + \c!bottom=\zeropoint, + \c!leftmargin=\zeropoint, + \c!rightmargin=\zeropoint, + \c!leftedge=\zeropoint, + \c!rightedge=\zeropoint, + \c!textdistance=\zeropoint, + \c!width=\v!middle, + \c!height=\v!middle, + \c!lines=0, + \c!grid=\v!no] + +%D A quick and dirty one: + +\definelayout + [\v!middle] + [\c!width=\v!middle, + \c!height=\v!middle] + +%D One for testing examples (5mm is often the non printable area): + +\definelayout + [\v!tight] + +\definelayout + [\v!tight] + [\v!page] + [\c!backspace=5mm, + \c!cutspace=5mm, + \c!topspace=5mm, + \c!bottomspace=5mm] + +\protect \endinput diff --git a/tex/context/base/mkxl/page-mak.mklx b/tex/context/base/mkxl/page-mak.mklx new file mode 100644 index 000000000..2a5cd4352 --- /dev/null +++ b/tex/context/base/mkxl/page-mak.mklx @@ -0,0 +1,280 @@ +%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. There is one standard +%D makeup page, but you can define more 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 +%D New is that we have a layout with the same name so one can set up a special +%D layout that then gets used. + +\installcorenamespace{makeup} +\installcorenamespace{makeupdoublesided} + +\installcommandhandler \??makeup {makeup} \??makeup + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentmakeup\e!makeup}{\startmakeup[\currentmakeup]}% + \frozen\instance\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 the direct and +%D indirect way. The parameterless call will build a simple box. + +\permanent\tolerant\protected\def\startmakeup[#1]#*[#2]% + {\ifparameters + \expandafter\page_makeup_start_nop + \else + \expandafter\page_makeup_start_yes + \fi[#1][#2]} + +\aliased\let\stopmakeup\relax + +%D The simple case: just a box with text dimensions. + +\protected\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 + \enforced\let\stopmakeup\page_makeup_stop_nop} + +\permanent\protected\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}% + \ifempty\p_page + \endgroup + \page % new, so best not have dangling mess here like references (we could capture then and flush embedded) + \orelse\ifx\p_page\v!no + % nothing + \endgroup + \else + \normalexpanded{\endgroup\page[\p_page]}% + \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 + \orelse\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 + \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 + \enforced\let\stopmakeup\page_makeup_stop_yes} + +\permanent\protected\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 + \orelse\ifx\m_page_makeup_layout_parent\??layout + \normalexpanded{\setuplayout[\m_page_makeup_name][\s!parent=\??layout]}% is remembered but checked later anyway + \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 Probably obsolete (but used in one manual by Taco): + +\permanent\protected\def\startcolumnmakeup % don't change + {\bgroup + \getrawnoflines\textheight % raw as we can have topskip + \setbox\scratchbox\vbox to \dimexpr\noflines\lineheight-\lineheight+\topskip\relax + \bgroup + \forgetall} + +\permanent\protected\def\stopcolumnmakeup + {\egroup + \dp\scratchbox\zeropoint + \wd\scratchbox\textwidth + \box\scratchbox + \egroup + \page_otr_command_synchronize_hsize} + +%D The text surrounding the main body text can be influenced by setting their +%D associated status variables. The connection between them is made by the following +%D 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/tex/context/base/mkxl/page-mbk.mklx b/tex/context/base/mkxl/page-mbk.mklx new file mode 100644 index 000000000..fcab1abf5 --- /dev/null +++ b/tex/context/base/mkxl/page-mbk.mklx @@ -0,0 +1,243 @@ +%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 floats. There is for +%D instance no save/restore used here. When there is need (and demand) we can use +%D the float cache and then flush them in the text when they are left over. On the +%D other hand, margin float are somewhat manual so it does not make too much sense +%D to complicate the code. As an alternative users can fall back on margin texts: +%D 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 + +\aliased\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] + +\permanent\tolerant\protected\def\startmarginblock[#tag]% + {\begingroup + \edef\currentmarginblock{#tag}% + \doifelse{\marginblockparameter\c!state}\v!start + \page_margin_blocks_start_block_yes + \page_margin_blocks_start_block_nop} + +\permanent\protected\def\stopmarginblock + {\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} + +\permanent\protected\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} + +\protected\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} + +\protected\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} + +\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth} +\protected\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) + +\protected\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 + +\permanent\protected\def\flushmarginblocks + {\page_otr_command_flush_margin_blocks} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-mcl.mkxl b/tex/context/base/mkxl/page-mcl.mkxl new file mode 100644 index 000000000..3cac820c2 --- /dev/null +++ b/tex/context/base/mkxl/page-mcl.mkxl @@ -0,0 +1,545 @@ +%D \module +%D [ file=page-mcl, +%D version=2020.07.26, % stripped down redone page-mul +%D title=\CONTEXT\ Page Macros, +%D subtitle=Multicolumns Limited, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Multicolumns Limited} + +\unprotect + +%D Columns are kind of hairy in \TEX\ and we would be better if no one needed them. +%D Anyway, we do need some support and no mechanism can serve all. The original +%D multicolumn mechanism of \MKII\ was never fully adapted to \MKIV, where mixed +%D columns and page columns showed up instead. However, for some cases a dumb +%D mechanism makes sense, so again we introduce multi columns, but without float +%D hacks. This one will be optimized for mixed usage as for instance itemize needs. +%D Their main advantage is that they can better deal with notes, which are hairy in +%D themselves. This will (for now) only happen in \LMTX. +%D +%D The code is stripped down ancient \MKII\ code and might become cleaner as it +%D evolves. Macros keep similar names but take a different namespace. The code is +%D not yet perfect wrt spacing! + +% \enableexperiments[itemize.columns] +% +% \starttext +% +% \startmulticolumns +% \dorecurse{10}{\samplefile{ward}\footnote{note #1}\par} +% \stopmulticolumns +% +% \dorecurse{4}{\samplefile{ward}\par} +% +% \startitemize[packed,columns,two] +% \dorecurse{100}{\startitem test #1 \footnote{this is a footnote #1}\stopitem} +% \stopitemize +% +% \stoptext + +\ifdefined \startmulticolumns + + % we're testing and don't want to remake the format + +\else + +\installcorenamespace {multicolumns} + +\installframedcommandhandler \??multicolumns {multicolumns} \??multicolumns + +\newdimen \d_page_mcl_available_width +\newdimen \d_page_mcl_distance +\newdimen \d_page_mcl_leftskip +\newdimen \d_page_mcl_rightskip +\newdimen \d_page_mcl_used_width +\newdimen \d_page_mcl_temp +\newdimen \d_page_mcl_saved_pagetotal % brrr, still needed ? + +\newcount \c_page_mcl_balance_minimum +\newcount \c_page_mcl_n_of_lines + +\newbox \b_page_mcl_preceding +\newdimen \d_page_mcl_preceding_height +\newconditional\c_page_mcl_preceding_present + +\newbox \b_page_mcl_rest_of_page +\newbox \b_page_mcl_page + +\newconditional\c_page_mcl_reverse +\newconditional\c_page_mcl_balance + +\newconstant \c_page_mcl_routine + +\setnewconstant\c_page_mcl_routine_regular \zerocount +\setnewconstant\c_page_mcl_routine_intercept \plusone +\setnewconstant\c_page_mcl_routine_continue \plustwo +\setnewconstant\c_page_mcl_routine_balance \plusthree +\setnewconstant\c_page_mcl_routine_error \plusfour + +\newbox \b_page_mcl_balance_content +\newconstant \c_page_mcl_balance_tries_max +\newcount \c_page_mcl_balance_tries +\newdimen \d_page_mcl_balance_target +\newdimen \d_page_mcl_balance_natural_height +\newdimen \d_page_mcl_balance_step +\newconditional\c_page_mcl_balance_possible + +\c_page_mcl_balance_tries_max 250 % 100 is too small when floats are involved + +%def\m_page_mcl_overshoot_ratio{\ifgridsnapping0\else.5\fi} +\def\m_page_mcl_overshoot_ratio{.5} + +\fi + +\protected\def\page_mcl_command_set_hsize + {\d_page_mcl_available_width\dimexpr + \makeupwidth + -\d_page_mcl_leftskip + -\d_page_mcl_rightskip + -\nofcolumns\d_page_mcl_distance + +\d_page_mcl_distance + \relax + \d_page_mcl_used_width\dimexpr + \d_page_mcl_available_width/\nofcolumns + \relax + \textwidth\d_page_mcl_used_width + \hsize\d_page_mcl_used_width} + +\protected\def\page_mcl_set_n_of_lines#1% + {\d_page_mcl_temp\dimexpr + +\textheight + \ifdim\d_page_mcl_preceding_height>\zeropoint -\d_page_mcl_preceding_height \fi +% \ifdim\ht\b_page_mcl_preceding>\zeropoint -\ht\b_page_mcl_preceding \fi + -#1% + \relax + \getnoflines\d_page_mcl_temp + \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines + \noflines\layoutlines + \fi \fi + \c_page_mcl_n_of_lines\noflines} + +% \protected\def\page_mcl_command_set_vsize +% {%%\page_one_command_set_vsize % indeed? +% \page_mcl_set_n_of_lines\zeropoint +% \d_page_mcl_temp\nofcolumns\dimexpr +% \c_page_mcl_n_of_lines\openlineheight +% % +\m_page_mcl_overshoot_ratio\openlineheight % collect enough data +% \relax +% \global\vsize \d_page_mcl_temp +% \global\pagegoal\d_page_mcl_temp} % let's do it only here, reports maxdimen anyway + +\protected\def\page_mcl_command_set_vsize + {\global\vsize\dimexpr\nofcolumns\textheight+\nofcolumns\lineheight\relax + \pagegoal\dimexpr + \vsize +% -\d_page_floats_inserted_top % needs checking +% -\d_page_floats_inserted_bottom % needs checking + -\c_page_mix_n_of_columns\insertheights + \relax} + +\protected\def\page_mcl_command_routine + {\ifcase\c_page_mcl_routine + \page_one_command_routine + \or + \page_mcl_routine_intercept + \or + \page_mcl_routine_continue + \or + \page_mcl_routine_balance + \or + \page_mcl_routine_error + \fi} + +\let\page_mcl_command_package_contents\page_one_command_package_contents + +\def\page_mcl_routine_intercept + {\global\setbox\b_page_mcl_preceding\vbox + {\page_otr_command_flush_top_insertions + \unvbox\normalpagebox}} + +\def\page_mcl_routine_error + {\showmessage\m!columns3\empty + \page_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments + +\protected\def\page_mcl_initialize_variables + {\reseteverypar % maybe still freeze .... + \dontcomplain + \settopskip + \setmaxdepth + \topskip 1\topskip + \splittopskip \topskip + \splitmaxdepth \maxdepth + \boxmaxdepth \maxdepth % dangerous + \emergencystretch\zeropoint + \relax} + +\def\page_mcl_flush_preceding_normal + {\unvbox\b_page_mcl_preceding} + +\def\page_mcl_flush_preceding_ongrid + {\scratchdimen\dimexpr + \d_page_mcl_saved_pagetotal + -\d_page_mcl_preceding_height + -\topskip + \relax + \box\b_page_mcl_preceding + \kern\scratchdimen} + +\def\page_mcl_flush_packaged_columns_continued + {\page_mcl_flush_packaged_columns_indeed + \box\b_page_mcl_page} + +\def\page_mcl_flush_packaged_columns_balanced + {\bgroup + \page_mcl_flush_packaged_columns_indeed + \getnoflines{\htdp\b_page_mcl_page}% + \ht\b_page_mcl_page\dimexpr + \noflines\openlineheight + -\openstrutdepth + \ifgridsnapping + % quick hack (at least it works with itemize) + \else + -\openlineheight + +\topskip + \fi + \relax + \dp\b_page_mcl_page\openstrutdepth + \box\b_page_mcl_page + \egroup} + +\def\page_mcl_synchronize_marks + {\dohandleallcolumns{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}} + +\def\page_mcl_flush_packaged_columns_indeed + {\ifvoid\b_page_mcl_preceding + \setfalse\c_page_mcl_preceding_present % will be set elsewhere + \else + \settrue\c_page_mcl_preceding_present + \page_apply_postprocessors_box\b_page_mcl_preceding + \fi + \forgetall + \page_mcl_initialize_variables + \page_mcl_synchronize_marks + \setbox\b_page_mcl_page\vpack + {\ifconditional\c_page_mcl_reverse\reversehpack\else\naturalhpack\fi to \makeupwidth + {\hskip\ifconditional\c_page_mcl_reverse\d_page_mcl_rightskip\else\d_page_mcl_leftskip\fi\relax + \dohandleallcolumns + {\wd\currentcolumnbox\d_page_mcl_used_width + \setbox\scratchbox\hpack{\strut\box\currentcolumnbox}% hm, why strut + \anch_mark_column_box\scratchbox\currentcolumn + \box\scratchbox + \hfil}% + \unskip + \hskip\ifconditional\c_page_mcl_reverse\d_page_mcl_leftskip\else\d_page_mcl_rightskip\fi}}% + \ifconditional\c_page_mcl_preceding_present + \settrue\c_page_mcl_preceding_present + \ifgridsnapping + \page_mcl_flush_preceding_ongrid % obey grid settings, force on grid + \else + \page_mcl_flush_preceding_normal % ignore grid settings, not on grid + \fi + \fi + \global\d_page_mcl_preceding_height\zeropoint + \page_otr_command_set_vsize + \dosomebreak\nobreak % hm, only needed when topstuff + \ifgridsnapping \else + \ifconditional\c_page_mcl_preceding_present + \nointerlineskip + \vskip\dimexpr\openstrutheight-\topskip\relax + \fi + \fi + \prevdepth\openstrutdepth + \nointerlineskip + \dp\b_page_mcl_page\zeropoint} + +\def\page_mcl_split_column#1#2% copy or box + {\global\setbox\currentcolumnbox\vsplit#1 upto #2} + +\def\page_mcl_routine_continue + {\bgroup + \forgetall + \page_mcl_initialize_variables + \settotalinsertionheight + \page_mcl_set_n_of_lines\totalinsertionheight + \d_page_mcl_balance_target\c_page_mcl_n_of_lines\openlineheight + \dohandleallcolumns{\page_mcl_split_column\normalpagebox\d_page_mcl_balance_target}% + \setbox\b_page_mcl_rest_of_page\vpack{\unvbox\normalpagebox}% + \dohandleallcolumns + {\global\setbox\currentcolumnbox\vpack to \d_page_mcl_balance_target + {\unvbox\currentcolumnbox % wel of niet \unvbox ? + \vfill}}% + \setbox\b_page_mcl_preceding\vpack{\page_mcl_flush_packaged_columns_continued}% + \page_otr_construct_and_shipout\box\b_page_mcl_preceding\zerocount % three arguments + \page_otr_command_set_hsize + \page_otr_command_set_vsize + \unvbox\b_page_mcl_rest_of_page + \egroup} + +\def\page_mcl_routine_balance + {\bgroup + % why no \forgetall here + \page_mcl_initialize_variables + \widowpenalty\zerocount + \setbox\b_page_mcl_balance_content\vpack{\unvbox\normalpagebox}% + \ifdim\ht\b_page_mcl_balance_content>\openlineheight % at least one line + \ifnum\c_page_mcl_balance_minimum<\plustwo % balance anyway + \settrue\c_page_mcl_balance_possible + \else % check criterium to available lines + \getnoflines{\ht\b_page_mcl_balance_content}% + \divide\noflines \nofcolumns \relax + \ifnum\noflines<\c_page_mcl_balance_minimum \relax + \ifdim\dimexpr\ht\b_page_mcl_balance_content+\openlineheight\relax>\makeupheight + \settrue\c_page_mcl_balance_possible % column exceeding text height + \else + \setfalse\c_page_mcl_balance_possible % it seems to fit + \fi + \else + \settrue\c_page_mcl_balance_possible % balance indeed + \fi + \fi + \else + \setfalse\c_page_mcl_balance_possible % balancing does not make sense + \fi + \ifconditional\c_page_mcl_balance_possible % start balancing, was: \ifdim\ht\b_page_mcl_balance_content>\openlineheight + \page_mcl_balance_try_one + \page_mcl_balance_try_two + \else + % a one liner is not properly handled here, so best rewrite the text then + \showmessage\m!columns{10}\empty + \global\setbox\firstcolumnbox\vpack{\unvbox\b_page_mcl_balance_content}% + \fi + \c_page_mcl_routine\c_page_mcl_routine_error + %\baselinebottom % forces depth in separation rule + \page_mcl_flush_packaged_columns_balanced + %\allowbreak + \egroup} + +% \showmakeup + +\def\page_mcl_balance_try_one + {\d_page_mcl_balance_target\dimexpr\ht\b_page_mcl_balance_content+\topskip-\baselineskip\relax + \divide\d_page_mcl_balance_target \nofcolumns + \vbadness\plustenthousand + \c_page_mcl_balance_tries\zerocount + \bgroup + \ifgridsnapping + \d_page_mcl_balance_step\lineheight + \else + \d_page_mcl_balance_step\spacingfactor\onepoint % rubish + \fi + \doloop\page_mcl_balance_try_one_attempt + \global\setbox\b_page_mcl_rest_of_page\box\voidbox + \ifnum\c_page_mcl_balance_tries>\c_page_mcl_balance_tries_max\relax + \showmessage\m!columns7\empty + \else + \showmessage\m!columns8{\the\c_page_mcl_balance_tries}% + \fi + \egroup} + +\def\page_mcl_balance_try_one_attempt + {\advance\c_page_mcl_balance_tries \plusone + \global\setbox\b_page_mcl_rest_of_page\copy\b_page_mcl_balance_content\relax + \dohandleallcolumns{\page_mcl_split_column\b_page_mcl_rest_of_page\d_page_mcl_balance_target}% + \d_page_mcl_balance_natural_height\zeropoint + \dohandleallcolumns\page_mcl_balance_try_one_attempt_step +\advance\d_page_mcl_balance_natural_height-33\scaledpoint % some slack + \ifnum\c_page_mcl_balance_tries>\c_page_mcl_balance_tries_max\relax + \exitloop + \orelse\ifdim\ht\b_page_mcl_rest_of_page>\zeropoint + \advance\d_page_mcl_balance_target\d_page_mcl_balance_step\relax + \orelse\ifdim\d_page_mcl_balance_natural_height>\ht\firstcolumnbox\relax + \advance\d_page_mcl_balance_target\d_page_mcl_balance_step\relax + \else + \exitloop + \fi} + +\def\page_mcl_balance_try_one_attempt_step + {\ifcase\currentcolumn\or\else + \ifdim\ht\currentcolumnbox>\d_page_mcl_balance_natural_height\relax + \d_page_mcl_balance_natural_height\ht\currentcolumnbox + \fi + \fi} + +\def\page_mcl_balance_try_two % hm ... can probably go + {\dohandleallcolumnscs\page_mcl_balance_try_two_step} + +% \def\page_mcl_balance_try_two_step +% {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox +% {\box\currentcolumnbox +% \vfill}} + +\def\page_mcl_balance_try_two_step + {%\global\setbox\currentcolumnbox\box\currentcolumnbox + \ht\currentcolumnbox\ht\firstcolumnbox} + +\permanent\tolerant\protected\def\startmulticolumns[#1]% + {\bgroup + \ifinsidecolumns + \page_mcl_start_nop + \else + \setupmulticolumns[#1]% + \nofcolumns\multicolumnsparameter\c!n\relax + \ifnum\nofcolumns>\plusone + \page_mcl_start_yes + \nofmulticolumns\nofcolumns + \else + \page_mcl_start_nop + \fi + \fi} + +\aliased\let\stopmulticolumns\relax + +\def\page_mcl_start_nop + {\enforced\let\stopmulticolumns\page_mcl_stop_nop} + +\permanent\protected\def\page_mcl_stop_nop + {\egroup} + +\protected\def\page_mcl_start_yes + {\whitespace + \begingroup + \enforced\let\stopmulticolumns\page_mcl_stop_indeed + \global\insidecolumnstrue + \global\insidemulticolumnstrue + % + \d_page_mcl_distance\multicolumnsparameter\c!distance\relax + % + \edef\p_direction{\multicolumnsparameter\c!direction}% + \ifx\p_direction\v!right + \setfalse\c_page_mcl_reverse + \else + \settrue\c_page_mcl_reverse + \fi + % + \edef\p_balance{\multicolumnsparameter\c!balance}% + \ifx\p_balance\v!yes + \settrue\c_page_mcl_balance + \else + \setfalse\c_page_mcl_balance + \fi + % + \usealignparameter\multicolumnsparameter + % + \edef\p_blank{\multicolumnsparameter\c!blank}% + \ifx\p_blank\empty \else + \setupblank[\p_blank]% + \fi + % + \ifdim\s_spac_whitespace_parskip>\zeropoint\relax + \setupwhitespace[\p_blank]% + \fi + \c_page_mcl_balance_minimum\multicolumnsparameter\c!ntop\relax + % + \begingroup + % + \d_page_mcl_leftskip \leftskip + \d_page_mcl_rightskip\rightskip + \leftskip \zeropoint + \rightskip \zeropoint + \hangafter \zerocount + \hangindent \zeropoint + % + \widowpenalty \zerocount % will become option + \clubpenalty \zerocount % will become option + % + \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 + % + \reseteverypar % todo + % + \ifdim\pagetotal=\zeropoint \else + \verticalstrut + \vskip-\struttotal + \fi + \global\d_page_mcl_saved_pagetotal\pagetotal + \setupoutputroutine[\s!multicolumn]% + \c_page_mcl_routine\c_page_mcl_routine_intercept + \page_otr_trigger_output_routine + \global\d_page_mcl_preceding_height\ht\b_page_mcl_preceding + \c_page_mcl_routine\c_page_mcl_routine_continue + \page_otr_command_set_hsize + \page_otr_command_set_vsize} + +\permanent\protected\def\page_mcl_stop_indeed + {\relax + \synchronizeoutput + \par + \ifconditional\c_page_mcl_balance + \c_page_mcl_routine\c_page_mcl_routine_continue + \goodbreak + \c_page_mcl_routine\c_page_mcl_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_mcl_routine\c_page_mcl_routine_regular + % + \ifvoid\b_page_mcl_preceding\else + \unvbox\b_page_mcl_preceding + \fi + \global\d_page_mcl_preceding_height\zeropoint + \endgroup % here + \nofcolumns\plusone + \nofmulticolumns\plusone + \page_otr_command_set_vsize + \dosomebreak\allowbreak + \page_floats_column_pop_saved + % + \global\insidemulticolumnsfalse + \global\insidecolumnsfalse + \endgroup + \egroup}% + +\setupmulticolumns + [\c!n=2, + \c!ntop=1, + \c!direction=\v!right, + \c!distance=1.5\bodyfontsize, % influenced by switching + \c!balance=\v!yes, + \c!align={\v!text,\v!tolerant}, + \c!blank={\v!line,\v!fixed}] + +\defineoutputroutine + [\s!multicolumn] + [\s!page_otr_command_routine =\page_mcl_command_routine, + \s!page_otr_command_package_contents=\page_mcl_command_package_contents, + \s!page_otr_command_set_vsize =\page_mcl_command_set_vsize, + \s!page_otr_command_set_hsize =\page_mcl_command_set_hsize] + +\let\strc_itemgroups_start_columns_old\strc_itemgroups_start_columns +\let\strc_itemgroups_stop_columns_old \strc_itemgroups_stop_columns + +\def\strc_itemgroups_start_columns_new + {\startmulticolumns[\c!n=\itemgroupparameter\c!n]} + +\def\strc_itemgroups_stop_columns_new + {\stopmulticolumns} + +\installtexexperiment + {itemize.columns} + {\let\strc_itemgroups_start_columns\strc_itemgroups_start_columns_new + \let\strc_itemgroups_stop_columns \strc_itemgroups_stop_columns_new} + {\let\strc_itemgroups_start_columns\strc_itemgroups_start_columns_old + \let\strc_itemgroups_stop_columns \strc_itemgroups_stop_columns_old} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-mix.mkxl b/tex/context/base/mkxl/page-mix.mkxl new file mode 100644 index 000000000..c94a1f252 --- /dev/null +++ b/tex/context/base/mkxl/page-mix.mkxl @@ -0,0 +1,1086 @@ +%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}{} + +\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 + +% old multicolumns mechanism +% +% \c!ntop=1, +% \c!rule=\v!off, : now separator=rule +% \c!height=, +% \c!blank={\v!line,\v!fixed}, +% \c!rulethickness=\linewidth, +% \c!offset=.5\bodyfontsize, + +\setupmixedcolumns + [\c!distance=1.5\bodyfontsize, + \c!n=\plustwo, + %\c!align=, % inherit (also replaces tolerance) + %\c!before=, + %\c!after=, + %\c!separator=\v!none, + %\c!setups=, + %\c!balance=\v!no, + %\c!blank={\v!line,\v!fixed}, yes or no + \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!notes=\v!yes, + \c!define=\v!yes, + \c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS + + \let\startmixedcolumns\relax % defined later +\aliased\let\stopmixedcolumns \relax % defined later + +\appendtoks % could become an option + \ifcstok{\mixedcolumnsparameter\c!define}\v!yes + \frozen\instance\setuevalue{\e!start\currentmixedcolumns}{\startmixedcolumns[\currentmixedcolumns]}% + \frozen\instance\setuevalue{\e!stop \currentmixedcolumns}{\stopmixedcolumns}% + \fi +\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 + +\newconditional\c_page_mix_process_notes +\newconditional\c_page_mix_grid_snapping + +%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] +% +% \protected\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, + \c!notes=\v!no] % kind of hidden + +% better + +\setupmixedcolumns + [\s!itemgroupcolumns] + [\c!splitmethod=\v!fixed, + \c!grid=\v!yes, + \c!internalgrid=\v!line] + +% even better: + +\setupitemgroup + [\c!grid=\v!tolerant:10] % 10 pct tolerance in columns snapping + +\setupmixedcolumns + [\s!itemgroupcolumns] + [\c!grid=\itemgroupparameter\c!grid] + +% the fast hooks: + +\protected\def\strc_itemgroups_start_columns + {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one + +\protected\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. + +\protected\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 ? + {\forgetall + \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_construct_and_shipout#1#2#3% + {\ifconditional\c_page_mix_grid_snapping\else\gridsnappingfalse\fi % maybe only for notes (bottom alignment) + \page_otr_construct_and_shipout#1#2#3% + \ifconditional\c_page_mix_grid_snapping \gridsnappingtrue \fi} + + +\def\page_mix_routine_error + {\showmessage\m!columns3\empty + \page_mix_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments + +%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. + +\protected\def\page_mix_command_set_hsize + {\hsize\d_page_mix_column_width + \columnwidth\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. + +\protected\def\page_mix_command_set_vsize + {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax + \pagegoal\dimexpr + \vsize +% -\d_page_floats_inserted_top % needs checking +% -\d_page_floats_inserted_bottom % needs checking + -\c_page_mix_n_of_columns\insertheights + \relax} + +%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}% + \setfalse\c_page_mix_grid_snapping + \ifempty\p_grid + % just follow the default grid settings + \else + \ifgridsnapping\settrue\c_page_mix_grid_snapping\fi + \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} + +\protected\def\installmixedcolumnseparator#1#2% + {\setvalue{\??mixedcolumnsseparator#1}{#2}} + +\installmixedcolumnseparator\v!rule + {\vrule + \s!width \mixedcolumnsparameter\c!rulethickness + \s!height\mixedcolumnseparatorheight + \s!depth \mixedcolumnseparatordepth + \relax} + +\protected\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 + +\installmacrostack\currentmixedcolumns +\installmacrostack\currentmixedcolumnsmethod + +\permanent\tolerant\protected\def\startmixedcolumns[#1]#*[#2]% + {\push_macro_currentmixedcolumns + \push_macro_currentmixedcolumnsmethod + \ifparameters + \expandafter\page_mix_start_columns_c + \or + \expandafter\page_mix_start_columns_b + \or + \expandafter\page_mix_start_columns_a + \fi[#1][#2]} + +\def\page_mix_start_columns_checked#1#2% + {\edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \ifx\currentmixedcolumnsmethod\v!box + \expandafter#1% + \orelse\ifinsidecolumns + \expandafter#2% + \else + \expandafter#1% + \fi} + +\def\page_mix_start_columns_a[#1]% [#2]% + {\edef\currentmixedcolumns{#1}% + \page_mix_start_columns_checked + \page_mix_start_columns_a_yes + \page_mix_start_columns_a_nop} + +\def\page_mix_start_columns_a_yes[#1]% + {\mixedcolumnsparameter\c!before\relax + \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \setupcurrentmixedcolumns[#1]% + \page_mix_initialize_columns + \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname + \enforced\let\stopmixedcolumns\page_mix_columns_stop_yes} + +\def\page_mix_start_columns_a_nop[#1]% + {\begingroup + \enforced\let\stopmixedcolumns\page_mix_columns_stop_nop} + +\def\page_mix_start_columns_b[#1][#2]% + {\ifhastok={#1}% + \let\currentmixedcolumns\empty + \page_mix_error_b + \page_mix_start_columns_checked\page_mix_start_columns_b_yes\page_mix_start_columns_b_nop[#1]% + \else + \edef\currentmixedcolumns{#1}% + \page_mix_start_columns_checked\page_mix_start_columns_b_yes\page_mix_start_columns_b_nop[#2]% + \fi} + +\def\page_mix_start_columns_b_yes[#1]% + {\mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings ! + \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \setupcurrentmixedcolumns[#1]% + \page_mix_initialize_columns + \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname % no \relax + \enforced\let\stopmixedcolumns\page_mix_columns_stop_yes} + +\def\page_mix_start_columns_b_nop[#1]% + {\begingroup + \enforced\let\stopmixedcolumns\page_mix_columns_stop_nop} + +\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 + \page_mix_start_columns_checked + \page_mix_start_columns_c_yes + \page_mix_start_columns_c_nop} + +\def\page_mix_start_columns_c_yes + {\mixedcolumnsparameter\c!before\relax + \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \page_mix_initialize_columns + \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname + \enforced\let\stopmixedcolumns\page_mix_columns_stop_yes} + +\def\page_mix_start_columns_c_nop + {\begingroup + \enforced\let\stopmixedcolumns\page_mix_columns_stop_nop} + +\protected\def\page_mix_fast_columns_start#1% + {\push_macro_currentmixedcolumns + \push_macro_currentmixedcolumnsmethod + \edef\currentmixedcolumns{#1}% + \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings ! + \begincsname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \page_mix_initialize_columns + \begincsname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname % no \relax + \let\page_mix_fast_columns_stop\page_mix_columns_stop_yes} + +%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. + +\let\page_mix_fast_columns_stop\relax + +\newtoks\t_page_mix_at_the_end + +\def\page_mix_finalize_columns + {\ifconditional\c_page_mix_process_notes \else + \global\t_page_mix_at_the_end{\stoppostponingnotes}% + \fi} + +\protected\def\page_mix_columns_stop_yes + {\begincsname\??mixedcolumnsstop\currentmixedcolumnsmethod\endcsname % no \relax + \page_mix_finalize_columns + \endgroup + \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax + \mixedcolumnsparameter\c!after\relax + \pop_macro_currentmixedcolumnsmethod + \pop_macro_currentmixedcolumns + \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} + +\protected\def\page_mix_columns_stop_nop + {\page_mix_finalize_columns + \endgroup + \pop_macro_currentmixedcolumnsmethod + \pop_macro_currentmixedcolumns + \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} + +% \protected\def\page_mix_columns_stop_yes +% {\begincsname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax +% \endgroup +% \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax +% \mixedcolumnsparameter\c!after\relax +% \ifx\currentmixedcolumnsmethod\s!otr +% \pop_macro_currentmixedcolumnsmethod +% \pop_macro_currentmixedcolumns +% \synchronizeoutput % brrr, otherwise sometimes issues in itemize +% \else +% \pop_macro_currentmixedcolumnsmethod +% \pop_macro_currentmixedcolumns +% \fi +% } + +%D This is how the fast one is used: + +\protected\def\strc_itemgroups_start_columns + {\page_mix_fast_columns_start\s!itemgroupcolumns} + +\protected\def\strc_itemgroups_stop_columns + {\page_mix_fast_columns_stop} % set by start + +% not used nor documented so commented: +% +% \setupmixedcolumns +% [\s!itemgroupcolumns] +% [\c!grid=\itemgroupparameter\c!grid] +% +% \setupitemgroup +% [\c!grid=\v!yes] % we need a value + +% 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 + % + \doifelse{\mixedcolumnsparameter\c!notes}\v!yes\settrue\setfalse\c_page_mix_process_notes + \ifconditional\c_page_mix_process_notes \else + \startpostponingnotes + \fi + % + \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 + % + \columnwidth \d_page_mix_column_width + \columndistance\d_page_mix_distance + \nofcolumns \c_page_mix_n_of_columns + \textwidth \d_page_mix_column_width % kind of redundant but we had it so ... + % + \usemixedcolumnscolorparameter\c!color + % + \insidecolumnstrue % new + % + \usealignparameter \mixedcolumnsparameter + \useblankparameter \mixedcolumnsparameter + \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. + +\protected\def\page_mix_routine_construct#1% + {\d_page_mix_max_height\mixedcolumnsparameter\c!maxheight % can have changed due to header=high + \ifconditional\c_page_mix_process_notes + \totalnoteheight\zeropoint + \else + \settotalinsertionheight + \fi + \clf_mixsetsplit + box \b_page_mix_collected + nofcolumns \c_page_mix_n_of_columns + maxheight \d_page_mix_max_height + noteheight \totalnoteheight + 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 tru\else fals\fi e % + notes \ifconditional\c_page_mix_process_notes tru\else fals\fi e % + \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\recurselevel + % 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} + +\protected\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 + \hskip\d_page_mix_rightskip + \egroup + \wd\b_page_mix_collected\dimexpr + \d_page_mix_max_width + +\d_page_mix_rightskip + +\d_page_mix_leftskip + \relax } + +\protected\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 + \vbox \bgroup + \hsize\d_page_mix_column_width + \ifconditional\c_page_mix_process_notes + \placenoteinserts + \fi + \egroup + \hss + \egroup} + +% \protected\def\page_mix_command_package_column +% {\page_mix_hbox to \d_page_mix_column_width \bgroup +% % maybe intercept empty +% \ruledhpack\bgroup +% \clf_mixgetsplit\recurselevel\relax +% \egroup +% \hskip-\d_page_mix_column_width +% \ruledhpack \bgroup +% \hsize\d_page_mix_column_width +% \ifconditional\c_page_mix_process_notes +% \placenoteinserts +% \fi +% \egroup +% \hss +% \egroup} + +\protected\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_mix_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments + \clf_mixflushrest + \clf_mixcleanup + \egroup} + +\protected\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_mix_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments + \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 + \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}% + \ifempty\p_profile \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: + +\protected\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 + +\protected\def\page_mix_command_check_if_float_fits + {\ifpostponecolumnfloats + \global\setfalse\c_page_floats_room + \orelse\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} + +\protected\def\page_mix_command_flush_floats + {\page_one_command_flush_floats} + +\protected\def\page_mix_command_flush_saved_floats + {\page_one_command_flush_saved_floats} + +% \protected\def\page_mix_command_flush_top_insertions +% {\page_one_command_flush_top_insertions} + +\protected\def\page_mix_place_float_top + {\showmessage\m!columns4\empty\page_one_place_float_here} + +\protected\def\page_mix_place_float_bottom + {\showmessage\m!columns5\empty\page_one_place_float_here} + +\protected\def\page_mix_place_float_here + {\page_one_place_float_here} + +\protected\def\page_mix_place_float_force + {\page_one_place_float_force} + +\protected\def\page_mix_command_side_float_output + {\page_mix_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments + +\protected\def\page_mix_command_synchronize_side_floats + {\page_sides_forget_floats} + +\protected\def\page_mix_command_flush_side_floats + {\page_sides_forget_floats} + +\protected\def\page_mix_command_next_page + {\page_otr_eject_page} + +\protected\def\page_mix_command_next_page_and_inserts + {\page_otr_eject_page_and_flush_inserts} + +%D Moved here and dedicated: + +\tolerant\protected\def\page_mix_command_test_column[#1]#*[#2]% works on last column + {\par + \begingroup + \scratchdimen\dimexpr#1\lineheight\ifparameter#2\or+#2\fi\relax + \ifdim\scratchdimen>\zeropoint + \c_attr_checkedbreak\number\scratchdimen % why \number + \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: + +\let\page_mix_command_flush_all_floats\page_one_command_flush_all_floats + +\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_synchronize_hsize =\page_mix_command_synchronize_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_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_check_if_float_fits =\page_mix_command_check_if_float_fits, + % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize, + \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box, + \s!page_otr_command_side_float_output =\page_mix_command_side_float_output, + \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats, + \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_all_floats =\page_mix_command_flush_all_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/tex/context/base/mkxl/page-mrk.mkxl b/tex/context/base/mkxl/page-mrk.mkxl new file mode 100644 index 000000000..697cafdea --- /dev/null +++ b/tex/context/base/mkxl/page-mrk.mkxl @@ -0,0 +1,238 @@ +%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} + +\unprotect + +%D This module implements curmarks and depends on \METAPOST. +%D +%D \starttyping +%D \setuplayout[marking=on,location=middle] +%D \setuplayout[marking=page,location=middle] +%D \setuplayout[marking=empty,location=middle] +%D \setuplayout[marking={color,page},location=middle] +%D \setuplayout[marking={one,page},location=middle] +%D \setuplayout[marking={two,page},location=middle] +%D \setuplayout[marking={four,page},location=middle] +%D \stoptyping + +\mutable\def\pagecutmarklength {5mm} +\mutable\def\pagecutmarkoffset {3mm} % slightly larger than before, and now a fixed size +\mutable\def\pagecutmarkmargin{10cm} + +% maybe all these should be global + +\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_max +\newcount\c_page_marks_nx +\newcount\c_page_marks_ny + +\startuniqueMPgraphic{print:color}{w,h,l,o} + loadmodule "crop" ; + page_marks_add_color(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ; +\stopuniqueMPgraphic + +\startuniqueMPgraphic{print:marking}{w,h,l,o} + loadmodule "crop" ; + page_marks_add_marking(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ; +\stopuniqueMPgraphic + +\startuniqueMPgraphic{print:lines}{w,h,l,o,x,y} + loadmodule "crop" ; + page_marks_add_lines(\MPvar w,\MPvar h,\MPvar l,\MPvar o,\MPvar x,\MPvar y, + \ifconditional\c_page_marks_add_page_lines tru\else fals\fi e) ; +\stopuniqueMPgraphic + +\startuseMPgraphic{print:number}{w,h,l,o,n} + loadmodule "crop" ; + 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 + \page_marks_add_lines + \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 + \global\advance\c_page_marks_max\minusone + \ifnum\c_page_marks_max>\zerocount\else + \glet\page_marks_add_more\gobbleoneargument + \glet\page_marks_add_page\gobbleoneargument + \fi + \egroup} + +\let\page_marks_add_page\gobbleoneargument +\let\page_marks_add_more\gobbleoneargument + +\installcorenamespace{layoutmarking} + +\permanent\protected\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 + {\settrue\c_page_marks_add_page_lines + \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} + +\installpagecutmark\v!one {\global\c_page_marks_max\plusone} % first page +\installpagecutmark\v!two {\global\c_page_marks_max\plustwo} % first two pages +\installpagecutmark\v!four{\global\c_page_marks_max\plusfour} % first four pages + +\permanent\protected\def\page_marks_set#1% + {\begincsname\??layoutmarking#1\endcsname} + +\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 + \global\c_page_marks_max\maxcount + \rawprocesscommacommand[\layoutparameter\c!marking]\page_marks_set + \ifnum\c_page_marks_max<\maxcount + \ifconditional\c_page_marks_add_page_lines \orelse + \ifconditional\c_page_marks_add_more_color \orelse + \ifconditional\c_page_marks_add_more_marking\orelse + \ifconditional\c_page_marks_add_more_lines \orelse + \ifconditional\c_page_marks_add_more_number \else + \settrue\c_page_marks_add_page_lines + \settrue\c_page_marks_add_more_number + \fi + \fi + \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 + \orelse\ifconditional\c_page_marks_add_more_color + \let\page_marks_add_more\page_marks_add_more_indeed + \orelse\ifconditional\c_page_marks_add_more_marking + \let\page_marks_add_more\page_marks_add_more_indeed + \orelse\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 +\to \everysetuplayout + +\setuplayout + [\c!marking=\v!off] + +\protect \endinput diff --git a/tex/context/base/mkxl/page-not.mkxl b/tex/context/base/mkxl/page-not.mkxl new file mode 100644 index 000000000..82523cc66 --- /dev/null +++ b/tex/context/base/mkxl/page-not.mkxl @@ -0,0 +1,32 @@ +%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 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 + +\newdimen\totalinsertionheight + +\permanent\protected\def\settotalinsertionheight + {\calculatetotalnoteheight + \totalinsertionheight\dimexpr + \totalnoteheight + +\page_insert_insertion_height\s!topfloat + +\page_insert_insertion_height\s!bottomfloat + \relax} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-one.mkxl b/tex/context/base/mkxl/page-one.mkxl new file mode 100644 index 000000000..3e7d3e2a8 --- /dev/null +++ b/tex/context/base/mkxl/page-one.mkxl @@ -0,0 +1,709 @@ +%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 + +\protected\def\page_one_command_next_page + {\page_otr_eject_page} + +\protected\def\page_one_command_next_page_and_inserts + {\page_otr_eject_page_and_flush_inserts} + +\protected\def\page_one_command_set_hsize + {\global\hsize\textwidth + \columnwidth\textwidth} % bonus so that it's not zero + +\protected\def\page_one_command_set_float_hsize + {\global\hsize\textwidth} + +\protected\def\page_one_command_set_vsize + {\ifgridsnapping + \ifcase\layoutlines + \getrawnoflines\textheight + \else + \noflines\layoutlines + \fi + \global\vsize\noflines\openlineheight + \else + \global\vsize\textheight + \fi + \global\advance\vsize\d_page_adapts_delta + % alternatively we could set it in builders.buildpage_filter + % \ifdim\pagegoal<\maxdimen .. \fi + \pagegoal\dimexpr + \vsize + -\d_page_floats_inserted_top + -\d_page_floats_inserted_bottom + -\insertheights + \relax} + +% 1 = partial page, 2 = whole page, 3 = partial page + +% We really need a setting! Todo, what key to use? + +\pushoverloadmode + \setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day + \overloaded\let\kindofpagetextareas\kindofpagetextareas +\popoverloadmode + +\def\page_one_registered_text_area_a % two arguments: (un)vbox n + {\ifconditional\c_page_areas_enabled + \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 + +\protected\def\page_one_command_package_contents#1#2% \box \unvbox % 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) +% \parfillskip\zeropoint + \page_one_registered_text_area_a#1#2% \unvbox + % + \ifgridsnapping + \unskip % new per 2019-06-18, otherwise weird bottom floats + \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \prevdepth\openstrutdepth + \page_otr_command_flush_bottom_insertions + \vfil + \orelse\ifcase\bottomraggednessmode + % ragged (default) + \unskip % new per 2019-06-18, otherwise weird bottom floats + \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \prevdepth\openstrutdepth + % these have whitespace before but we can have some more options + % like a \vfill or so + \page_otr_command_flush_bottom_insertions + \vfil + \or + % align (normal) + \page_otr_command_flush_bottom_insertions + \or + % baseline + \unskip % new per 2019-06-18, otherwise weird bottom floats + \vkern\dimexpr\maxdepth-\d_page_one_natural_depth\relax + \page_otr_command_flush_bottom_insertions + \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 + {\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} + +\protected\def\page_one_command_side_float_output + {\page_otr_construct_and_shipout\unvbox\normalpagebox\plusone} % three arguments, we need to be in the output group + +\protected\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 + {\floatingpenalty\zerocount + \insert\namedinsertionnumber\s!topfloat\bgroup + \forgetall + \ifconditional\c_page_one_top_of_insert + \ifconditional\c_page_one_correct_top_insert + \topskipcorrection % [xx] new: see icare topbleed + \kern-\lineskip + \par + \prevdepth\maxdimen + \fi + \fi + \page_otr_command_flush_float_box + \vskip\s_page_one_between_top_insert + \egroup} + +\let\totaltopinserted\!!zeropoint +\let\totalbotinserted\!!zeropoint + +\protected\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} + +\protected\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 + \floatingpenalty\zerocount + \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} + +\protected\def\page_one_command_flush_top_insertions + {\ifvoid\namedinsertionnumber\s!topfloat\else + \page_one_command_flush_top_insertions_indeed % less tracing + \fi + \global\d_page_floats_inserted_top\zeropoint} + +\def\page_one_command_flush_top_insertions_indeed + {\ifgridsnapping + \box\namedinsertionnumber\s!topfloat + \vkern-\topskip + \vkern\strutheight % [xx] new: see icare topbleed + \else + \ifcase\c_page_floats_insertions_topskip_mode + % 0: default, do nothing + \or + % 1: no topskip (crossed fingers) + \vskip-\topskip % skip ! + \vkern\strutheight + \fi + \unvbox\namedinsertionnumber\s!topfloat + \fi} + +\protected\def\page_one_command_flush_bottom_insertions + {\ifvoid\namedinsertionnumber\s!bottomfloat\else + \page_one_command_flush_bottom_insertions_indeed + \fi + \global\d_page_floats_inserted_bottom\zeropoint + \global\setfalse\c_page_floats_not_permitted} + +\def\page_one_command_flush_bottom_insertions_indeed + {\ifgridsnapping + % \floatparameter\c!bottombefore + \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% + % \floatparameter\c!bottomafter + \else + \floatparameter\c!bottombefore + \unvbox\namedinsertionnumber\s!bottomfloat + \floatparameter\c!bottomafter + \fi} + +\protected\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} + +\protected\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_floats_get_compressed + {\setfalse\c_page_floats_center_box % not needed as we do call directly + %% 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 + \hpack to \ifdim\naturalfloatwd>\makeupwidth\makeupwidth\else\naturalfloatwd\fi + {\hss\box\floatbox\hss}% + \ifnum\recurselevel<\nofcollectedfloats + \hfil + \fi}% + \hfil}} + +\def\page_one_command_flush_floats_indeed + {\ifconditional\c_page_floats_some_waiting + \ifconditional\c_page_floats_pack_flushed + \page_floats_collect\s!text\hsize\d_page_floats_compress_distance + \ifcase\nofcollectedfloats + \page_floats_get + \or + \page_floats_get + \else + \page_one_command_floats_get_compressed + \fi + \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} + +\protected\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} + +\protected\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 + \scratchdimenone\dimexpr + \pagetotal + +\floatheight + +\d_strc_floats_top + +\d_strc_floats_overflow + -\pageshrink + \relax + \scratchdimentwo\pagegoal + \relax % needed + \ifcase\c_page_one_float_method + % method 0 : raw + \or + % method 1 : safe + % too fuzzy as it can change and for a high page it's a lot : \scratchdimentwo .99\pagegoal + \advance\scratchdimentwo -\strutdp + \or + % method 2 : tight + \advance\scratchdimenone -\onepoint + \fi + \relax % really needed ! ! ! ! + \ifdim\scratchdimenone>\scratchdimentwo + \global\setfalse\c_page_floats_room + \else + \global\settrue\c_page_floats_room + \fi + \fi} + +\protected\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_ + \orelse\ifconditional\c_page_margin_blocks_present + \page_one_command_flush_floats + \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_here_indeed + {\ifgridsnapping + % otherwise real bad outcome + \else + % this was not really applied (delayed) + % \baselinecorrection % this has to be done better (and definitely not in column mode) + % so we now use this: + \checkprevdepth + \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_margin + {\page_margin_blocks_process_float + \nonoindentation} % new, due to popular request + +\def\page_one_place_float_leftmargin + {\page_one_place_float_side_indeed + \page_sides_process_float_leftmargin + \nonoindentation} % new, due to popular request + +\def\page_one_place_float_rightmargin + {\page_one_place_float_side_indeed + \page_sides_process_float_rightmargin + \nonoindentation} % new, due to popular request + +\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_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 + \nonoindentation} % new, due to popular request + +\def\page_one_place_float_top + {\page_one_place_float_otherwise + \nonoindentation} + +\def\page_one_place_float_bottom + {\page_one_place_float_otherwise + \nonoindentation} % new, due to popular request + +\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 + \orelse\ifx\floatmethod\v!bottom + \page_one_place_float_bottom_indeed + \else + \page_one_place_float_here_indeed + \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 + \floatingpenalty\zerocount + \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} + +\protected\def\page_one_command_flush_side_floats + {\page_sides_flush_floats} + +\protected\def\page_one_command_synchronize_side_floats + {\page_sides_synchronize_floats} + +\protected\def\page_one_command_test_page + {\testpage} + +\protected\def\page_one_command_flush_all_floats + {\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} + +\protected\def\page_one_command_flush_facing_floats + {\strc_floats_facing_flush} + +\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_synchronize_hsize =\page_one_command_synchronize_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_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_check_if_float_fits =\page_one_command_check_if_float_fits, + % \s!page_otr_command_set_float_hsize =\page_one_command_set_float_hsize, + \s!page_otr_command_flush_float_box =\page_one_command_flush_float_box, + \s!page_otr_command_side_float_output =\page_one_command_side_float_output, + \s!page_otr_command_synchronize_side_floats=\page_one_command_synchronize_side_floats, + \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_all_floats =\page_one_command_flush_all_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, + \s!page_otr_command_flush_facing_floats =\page_one_command_flush_facing_floats +] + +% \setupoutputroutine +% [\s!singlecolumn] + +\protect \endinput diff --git a/tex/context/base/mkxl/page-otr.mklx b/tex/context/base/mkxl/page-otr.mklx new file mode 100644 index 000000000..e93590bf6 --- /dev/null +++ b/tex/context/base/mkxl/page-otr.mklx @@ -0,0 +1,335 @@ +%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 same time we +%D 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}{} + +\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 + +\permanent\protected\def\defineoutputroutinecommand[#name]% doing multiple on one go saves syncing + {\processcommalist[#name]\page_otr_commands_define} + +\protected\def\page_otr_commands_define#name% + {\ifcsname#name\endcsname \else + \letcsname#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 + +\protected\def\page_otr_specifics_preset#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \writestatus{\currentoutputroutine}{- \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\endcsname\relax + \else + \writestatus{\currentoutputroutine}{+ \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\protected\def\page_otr_specifics_preset_normal#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \letcsname#name\endcsname\relax + \else + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\protected\def\page_otr_specifics_preset_traced#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \writestatus{\currentoutputroutine}{preset: - \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\endcsname\relax + \else + \writestatus{\currentoutputroutine}{preset: + \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\let\page_otr_specifics_preset\page_otr_specifics_preset_normal + +\permanent\protected\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_otr_trigger_penalty \c_page_otr_trigger_penalty -100010 + +\newcount \c_page_otr_columns % we will share this one + +\newif \ifinotr % we keep this (name) for old times sake + +% \def\page_otr_update_page_goal#1#2% +% {\global\c_page_otr_columns#2\relax +% \pagegoal\dimexpr\vsize-\c_page_otr_columns\insertheights\relax} + +\appendtoks + \insertheights\zeropoint +\to \everyaftershipout + +\protected\def\page_otr_message_b{\page_otr_message_s+} +\protected\def\page_otr_message_e{\page_otr_message_s-} + +\protected\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 + i:\the\insertheights + \ifdim\pagetotal>\pagegoal + ,\space + d:\the\dimexpr\pagetotal-\pagegoal\relax + \fi}} + +\protected\def\page_otr_trigger#penalty% + {\begingroup + \par + \penalty#penalty% + \endgroup} + +\permanent\protected\def\installoutputroutine#invoke#action% \invoke \action + {\global\advance\c_page_otr_trigger_penalty\minusone + \frozen\protected\edef#invoke{\page_otr_trigger{\number\c_page_otr_trigger_penalty}}% + \setvalue{\??otrtriggers\number\c_page_otr_trigger_penalty}{#action}} + +\protected\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} + +\protected\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_otr_set_engine_output_routine#content% + {\global\output + {\inotrtrue + \the\everybeforeoutput + #content\relax + \the\everyafteroutput}} + +% Just as fuzzy (and in 'one' we are okay with \aftergroup anyway): +% +% \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi +% \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi +% +% \def\page_otr_set_engine_output_routine#content% +% {\the\everybeforeoutputgroup +% \global\output +% {\inotrtrue +% \the\everybeforeoutput +% #content\relax +% \the\everyafteroutput +% \aftergroup\the\aftergroup\everyafteroutputgroup}} +% +% \appendtoks +% \ifnum\c_page_postponed_mode=\plusone +% \page_postponed_blocks_flush % and then not in \page_otr_construct_and_shipout +% \fi +% \to \everyafteroutputgroup + +\page_otr_set_engine_output_routine\page_otr_triggered_output_routine + +\installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead + {\ifvoid\normalpagebox\else + \unvbox\normalpagebox + % not \pagediscards as it does more harm than good + \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: + +\permanent\protected\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). Most +%D routines will use ard codes names but sometimes we want to adapt, +%D which is why we have these: + +\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_all_floats} +\definesystemconstant{page_otr_command_flush_margin_blocks} +\definesystemconstant{page_otr_command_test_column} +\definesystemconstant{page_otr_command_flush_facing_floats} + +\definesystemconstant{singlecolumn} +\definesystemconstant{multicolumn} % will move +\definesystemconstant{columnset} % will move +\definesystemconstant{pagecolumn} % 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_all_floats, + \s!page_otr_command_flush_margin_blocks, + \s!page_otr_command_test_column, + \s!page_otr_command_flush_facing_floats] + +\appendtoks + \setupoutputroutine[\s!singlecolumn]% +\to \everydump + +\protect \endinput diff --git a/tex/context/base/mkxl/page-par.mkxl b/tex/context/base/mkxl/page-par.mkxl new file mode 100644 index 000000000..c198784dc --- /dev/null +++ b/tex/context/base/mkxl/page-par.mkxl @@ -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] + +\permanent\let\showparagraphnumber\relax + +\appendtoks + \page_par_check_state +\to \everysetupparagraphnumbering + +\protected\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 + \lastnamedcs + \fi} + +\setvalue{\??paragraphnumberingvariants\v!start}% + {\enforced\let\showparagraphnumber\page_par_show_number_normal} + +\setvalue{\??paragraphnumberingvariants\v!stop}% + {\enforced\let\showparagraphnumber\relax} + +\setvalue{\??paragraphnumberingvariants\v!line}% + {\enforced\let\showparagraphnumber\page_par_show_number_lines} + +\setvalue{\??paragraphnumberingvariants\v!reset}% + {\strc_counters_reset\v!paragraph + \enforced\let\showparagraphnumber\page_par_show_number_normal} + +\permanent\protected\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}} + +\permanent\protected\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/tex/context/base/mkxl/page-pcl.mkxl b/tex/context/base/mkxl/page-pcl.mkxl new file mode 100644 index 000000000..173fad91a --- /dev/null +++ b/tex/context/base/mkxl/page-pcl.mkxl @@ -0,0 +1,857 @@ +%D \module +%D [ file=page-pcl, +%D version=2017.11.08, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Page 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 / Page Columns} + +%D This is very experimental code! We took a bit from the mixed columns and single +%D column page code. This one works acceptable with floats and is for whole double +%D column documents. We don't balance (yet). Footnotes are per column. One can have +%D side floats too. No balancing and other fancy features. +%D +%D Don't use this in production! Although the main approach will stay there might be +%D changes in the way floats are dealt with. Not much testing has been done but as +%D we stay close to the single column mode we expect most to just work. Only floats +%D are the (usual) pain. Backgrounds, line numbering, etc.\ not tested either. + +\unprotect + +\definemeasure[onecolumn] [\columnwidth] +\definemeasure[twocolumns] [\dimexpr\plustwo \columnwidth+ \columndistance\relax] +\definemeasure[threecolumns][\dimexpr\plusthree\columnwidth+\plustwo \columndistance\relax] +\definemeasure[fourcolumns] [\dimexpr\plusfour \columnwidth+\plusthree\columndistance\relax] + +\newcount \c_page_col_n_of_columns \c_page_col_n_of_columns\plusone +\newcount \c_page_col_current \c_page_col_current \plusone +\newdimen \d_page_col_distance +\newdimen \d_page_col_max_height +\newdimen \d_page_col_max_width +%newdimen \d_page_col_balance_step +\newdimen \d_page_col_column_width +\newdimen \d_page_col_top_height +\newdimen \d_page_col_top_width +\newdimen \d_page_col_available +\newdimen \d_page_col_sofar +\newconditional\c_page_col_page + +%D We need to step over empty columns. + +\protected\def\page_col_command_next_page + {\page_col_eject_page} + +\permanent\protected\def\page_col_column + {\page_otr_eject_page} + +\protected\def\page_col_eject_page + {\begingroup + \scratchcountertwo \realpageno + \page_otr_eject_page + \scratchcounterone \c_page_col_current + \scratchcounterthree\zerocount + \doloop{% + \ifnum\scratchcounterthree>\plushundred + % too many attempts + \exitloop + \orelse\ifnum\realpageno>\scratchcountertwo + % we advanced at least one page so we're done + \exitloop + \else + \ifnum\scratchcounterone=\c_page_col_current + \dontleavehmode\null + \fi + \page_otr_eject_page + \scratchcounterone\c_page_col_current + \advance\scratchcounterthree\plusone + \fi + }% + \endgroup} + +%D \unknown + +\protected\def\page_col_command_next_page_and_inserts + {\page_otr_eject_page_and_flush_inserts} + +%D \unknown + +\protected\def\page_col_command_set_hsize + {\global\hsize\d_page_col_column_width\relax + \global\d_page_col_available\dimexpr + \numexpr\c_page_col_n_of_columns-\c_page_col_current+\plusone\relax\d_page_col_column_width + + \numexpr\c_page_col_n_of_columns-\c_page_col_current \relax\d_page_col_distance + \relax + \global\d_page_col_sofar + \ifnum\c_page_col_n_of_columns=\plusone + \zeropoint + \else + \numexpr\c_page_col_n_of_columns-\plusone\relax + \dimexpr\d_page_col_column_width+\d_page_col_distance\relax + \fi + % consistent with mixed: + \textwidth\d_page_col_column_width} + +%D \unknown + +\protected\def\page_col_command_set_vsize % \page_one_command_set_vsize minus the pagegoal setting + {\ifgridsnapping + \ifcase\layoutlines + \getrawnoflines\textheight + \else + \noflines\layoutlines + \fi + \global\vsize\noflines\openlineheight + \else + \global\vsize\textheight + \fi} + +%D \unknown + +\def\page_col_registered_text_area_b#1% + {\begingroup + \makeupwidth\d_page_col_column_width + \page_one_registered_text_area_b{#1}% + \endgroup} + +\protected\def\page_col_command_package_contents#1#2% \box \unvbox % this one will be redone (checked) + {\bgroup + \setbox\b_page_one_contents\vbox to \textheight + {\page_one_registered_text_area_a#1#2}% + \page_one_command_package_show_state + \ht\b_page_one_contents\textheight + \page_col_registered_text_area_b + {\box\b_page_one_contents}% + \egroup} + +\protected\def\page_col_command_package_contents_one#1#2% \box \unvbox % this one will be redone (checked) + {\bgroup + \forgetall + % see one for comments as it is similar + \strc_notes_check_if_bottom_present + \d_page_one_natural_depth\dp#2\relax + \setbox\b_page_one_contents\vbox to \textheight + {\page_col_command_flush_top_insertions + \page_one_registered_text_area_a#1#2% + \hsize\d_page_col_column_width + \ifgridsnapping + \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \prevdepth\openstrutdepth + \page_col_command_flush_bottom_insertions + \vfil + \orelse\ifcase\bottomraggednessmode + % ragged (default) + \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \prevdepth\openstrutdepth + \page_col_command_flush_bottom_insertions + \vfil + \or + % align (normal) + \page_col_command_flush_bottom_insertions + \or + % baseline + \kern\dimexpr\maxdepth-\d_page_one_natural_depth\relax + \page_col_command_flush_bottom_insertions + \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 + {\hsize\d_page_col_column_width + \setupnotes[\c!width=\textwidth]% + \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% + \ht\b_page_one_contents \zeropoint + \wd\b_page_one_contents \zeropoint + \ht\b_page_one_bottom_notes\zeropoint + \wd\b_page_one_bottom_notes\zeropoint + \wd\b_page_one_bottom_notes\d_page_col_column_width + \page_col_registered_text_area_b + {\vpack to \textheight + {\hpack{\box\b_page_one_contents\box\b_page_one_bottom_notes}}}% + \else + \ht\b_page_one_contents\textheight + \wd\b_page_one_contents\d_page_col_column_width + \page_col_registered_text_area_b + {\box\b_page_one_contents}% + \fi + \egroup} + +%D \unknown + +\protected\def\page_col_command_side_float_output + {% % % + \ifvoid\namedinsertionnumber\s!topfloat\else + \scratchwidth\wd\namedinsertionnumber\s!topfloat + \ifdim\scratchwidth>\d_page_col_top_width + \global\d_page_col_top_width \scratchwidth + \fi + \global\d_page_col_top_height\ht\namedinsertionnumber\s!topfloat + \fi + % % % + \setbox\scratchbox\vbox\bgroup + \page_col_command_package_contents_one\unvbox\normalpagebox + \egroup + \putboxincache\s!pagecolumn{\number\c_page_col_current}\scratchbox + \ifnum\c_page_col_current=\c_page_col_n_of_columns + \page_col_routine_package + \page_otr_construct_and_shipout\box\normalpagebox\plusone + \global\c_page_col_current\plusone + \global\d_page_col_top_height\zeropoint + \global\d_page_col_top_width\zeropoint + % \page_col_command_flush_top_insertions + % \page_col_command_flush_floats + \else + \ifdim\d_page_col_top_width>\zeropoint + \ifdim\dimexpr\d_page_col_top_width>\d_page_col_sofar\relax + \begingroup + \floatingpenalty\zerocount + \insert\namedinsertionnumber\s!topfloat\bgroup + \vbox to \d_page_col_top_height{\vss} + % can be an option + \page_col_command_flush_top_insertions + \page_col_command_flush_floats + % so far till option + \egroup + \endgroup + \fi + \fi + \global\advance\c_page_col_current\plusone + \fi + % + \page_col_command_set_vsize + \page_col_command_set_hsize} + +% use \currentmixedcolumns instead of \recurselevel + +\def\page_col_routine_package_step + {% needs packaging anyway + \getboxfromcache{\s!pagecolumn}{\number\recurselevel}\scratchbox + \page_lines_add_numbers_to_box\scratchbox\recurselevel\c_page_col_n_of_columns\plusone % new + \page_marks_synchronize_column\plusone\c_page_col_n_of_columns\recurselevel\scratchbox + % backgrounds + \anch_mark_column_box\scratchbox\recurselevel + \mixedcolumnseparatorheight\ht\scratchbox + \mixedcolumnseparatordepth \dp\scratchbox + \inheritedpagecolumnsframedbox\recurselevel\scratchbox} + +\def\page_col_routine_package + {\global\setbox\normalpagebox\hbox to \makeupwidth\bgroup + \edef\p_separator{\pagecolumnsparameter\c!separator}% + \pagecolumnseparatorwidth\d_page_col_distance + \edef\p_direction{\pagecolumnsparameter\c!direction}% + \ifx\p_direction\v!reverse + \dostepwiserecurse\c_page_col_n_of_columns\plusone\minusone + {\page_col_routine_package_step + \ifnum\recurselevel>\plusone + \page_col_routine_package_separate + \fi}% + \else + \dorecurse\c_page_col_n_of_columns + {\page_col_routine_package_step + \ifnum\recurselevel<\c_page_col_n_of_columns + \page_col_routine_package_separate + \fi}% + \fi + \egroup + \resetboxesincache{\s!pagecolumn}} + +%D \unknown + +% \protected\def\page_col_command_check_if_float_fits +% {\ifconditional\c_page_floats_not_permitted +% \global\setfalse\c_page_floats_room +% %\orelse\ifabsdim\dimexpr\d_page_col_available-\naturalfloatwd\relax<\onepoint +% \orelse\ifdim\dimexpr\d_page_col_available-\naturalfloatwd\relax>-\onepoint +% \global\settrue\c_page_floats_room +% \else +% \global\setfalse\c_page_floats_room +% \fi +% \ifconditional\c_page_floats_room +% \begingroup +% \scratchdimen\dimexpr\pagetotal+\lineheight\relax +% \ifdim\scratchdimen>\pagegoal +% \goodbreak +% \ifdim\dimexpr\d_page_col_available-\naturalfloatwd\relax>\onepoint +% \global\setfalse\c_page_floats_room +% \else +% \global\settrue\c_page_floats_room +% \fi +% \fi +% \endgroup +% \fi +% \ifconditional\c_page_floats_room +% \ifdim\pagetotal>\zeropoint +% \scratchdimenone\dimexpr\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink\relax +% \scratchdimentwo\pagegoal +% \relax % needed +% \ifcase\c_page_one_float_method +% % method 0 : raw +% \or +% % method 1 : safe +% \advance\scratchdimentwo -\strutdp +% \or +% % method 2 : tight +% \advance\scratchdimenone -\onepoint +% \fi +% \relax % really needed ! ! ! ! +% \ifdim\scratchdimenone>\scratchdimentwo +% \global\setfalse\c_page_floats_room +% \fi +% \fi +% \ifconditional\c_page_floats_room +% \global\setbox\floatbox\hpack to \d_page_col_available{\hss\box\floatbox\hss}% +% \fi +% \fi} + +\protected\def\page_col_command_check_if_float_fits + {\ifconditional\c_page_floats_not_permitted + % forget about it anyway + \global\setfalse\c_page_floats_room + \else + % first we check the current column +% \ifdim\dimexpr\d_page_col_width-\naturalfloatwd\relax>-\onepoint + \ifdim\dimexpr\hsize-\naturalfloatwd\relax>-\onepoint + \global\settrue\c_page_floats_room + \else + \global\setfalse\c_page_floats_room + \fi + \ifconditional\c_page_floats_room + % we fit in the column but do we have room + \ifdim\dimexpr\pagetotal+\lineheight\relax>\pagegoal + % try again later + \goodbreak + \fi + \ifdim\pagetotal>\zeropoint + \scratchdimenone\dimexpr\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink\relax + \scratchdimentwo\pagegoal + \relax % needed + \ifcase\c_page_one_float_method + % method 0 : raw + \or + % method 1 : safe + \advance\scratchdimentwo -\strutdp + \or + % method 2 : tight + \advance\scratchdimenone -\onepoint + \fi + \relax % really needed ! ! ! ! + \ifdim\scratchdimenone>\scratchdimentwo + % there is no room, give up + \global\setfalse\c_page_floats_room + % now we can decide on a top float +% \fi + \else +% \ifconditional\c_page_floats_room +% \global\setbox\floatbox\hpack to \d_page_col_float_available{\hss\box\floatbox\hss}% +% \fi + \fi + \fi + \fi + \fi} + +%D \unknown + +\def\page_col_set_float_pack_hsize + {\ifnum\c_page_col_current=\c_page_col_n_of_columns + \c_page_col_current\plusone + \else + \advance\c_page_col_current\plusone + \fi + \page_col_command_set_hsize + \hsize\d_page_col_available} + +\protected\def\page_col_command_flush_floats + {\global\settrue\c_page_floats_flushing + \ifconditional\c_page_floats_some_waiting + \par + \page_col_set_float_pack_hsize + \page_col_command_flush_floats_indeed + \fi + \global\savednoffloats\zerocount + \global\setfalse\c_page_floats_some_waiting + \global\setfalse\c_page_floats_flushing} + +\def\page_floats_show_pack_state_indeed#1% + {\llap{\smash{\backgroundline[black]{\strut\smallinfofont\white#1\space\the\nofcollectedfloats\space of\space\the\savednoffloats:\the\hsize}}\hskip.25\emwidth}} + +\installtextracker + {floats.collecting} + {\let\page_floats_show_pack_state\page_floats_show_pack_state_indeed} + {\let\page_floats_show_pack_state\gobbleoneargument} + +\let\page_floats_show_pack_state\gobbleoneargument + +\def\page_col_command_flush_floats_indeed % much in common with OTRSET + {\ifconditional\c_page_floats_some_waiting + \ifconditional\c_page_floats_compress_flushed + \setfalse\c_page_floats_center_box % not needed as we do call directly + \page_floats_collect\s!text\hsize\d_page_floats_compress_distance + % + \ifnum\nofcollectedfloats=\plusone + \ifdim\naturalfloatwd>\hsize + \nofcollectedfloats\zerocount + \fi + \fi + \ifnum\nofcollectedfloats>\zerocount + \global\setbox\floatbox\hpack to \hsize + {\page_floats_show_pack_state F% + \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 + % this could happen at the lua end instead + \scratchdimen\dimexpr\wd\floatbox-\naturalfloatwd\relax + \ifdim\scratchdimen<\zeropoint + \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}% + \fi + % + \ifdim\wd\floatbox>\textwidth % \hsize + \hpack to \textwidth{\hss\box\floatbox\hss}% \textwidth + \else + \box\floatbox + \fi + \ifnum\recurselevel<\nofcollectedfloats + \hfil + \fi}% + \hfil}% + \doplacefloatbox + % \page_one_insert_top_float + \doubleexpandafter\page_col_command_flush_floats_indeed + \else + % todo + \fi + \else + \page_floats_get + % \page_one_insert_top_float + \doplacefloatbox + \doubleexpandafter\page_col_command_flush_floats_indeed + \fi + \fi} + +\protected\def\page_col_command_flush_saved_floats % like one + {\global\d_page_floats_inserted_top\zeropoint + \global\d_page_floats_inserted_bottom\zeropoint + \ifconditional\c_page_floats_flushing \else + \page_col_command_set_top_insertions + \page_col_command_set_bottom_insertions + \ifconditional\c_page_floats_some_waiting + \doif{\rootfloatparameter\c!cache}\v!no\page_col_command_flush_floats % could be _otr_ + \orelse\ifconditional\c_page_margin_blocks_present + \page_col_command_flush_floats + \fi + \fi} + +\protected\def\page_col_command_set_top_insertions + {\bgroup + \ifconditional\c_page_floats_some_waiting + \noffloatinserts\zerocount + \let\totaltopinserted\!!zeropoint + \page_col_set_float_pack_hsize + \page_col_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\d_page_col_collected_top_float_height % pseudo + {\dimexpr + \d_page_floats_inserted_top + + \maxcollectedfloatstotal + + \ifdim\d_strc_floats_top>\d_strc_floats_bottom + \d_strc_floats_top + \else + \d_strc_floats_bottom + \fi + \relax} + +\def\page_col_command_set_top_insertions_indeed + {\ifnum\noffloatinserts<\c_page_floats_n_of_top + \ifcase\savednoffloats + \let\page_col_command_set_top_insertions_indeed\relax + \else + \page_floats_collect\s!text\hsize\emwidth + \ifdim\d_page_col_collected_top_float_height<\textheight + \global\setbox\floatbox\hpack to \hsize + {\page_floats_show_pack_state T% + \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 + % this could happen at the lua end instead + \scratchdimen\dimexpr\wd\floatbox-\naturalfloatwd\relax + \ifdim\scratchdimen<\zeropoint + \global\setbox\floatbox\hpack spread -\scratchdimen{\hss\box\floatbox\hss}% + \fi + % + \ifdim\wd\floatbox>\makeupwidth % \hsize + \hpack to \makeupwidth{\hss\box\floatbox\hss}% + \else + \box\floatbox + \fi + \ifnum\recurselevel<\nofcollectedfloats + \hfil + \fi}% + \hfil}% + \page_one_prepare_top_float + \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 + \let\page_col_command_set_top_insertions_indeed\relax + \fi + \fi + \else + \ifconditional\c_page_floats_some_waiting + \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}% + \fi + \let\page_col_command_set_top_insertions_indeed\relax + \fi + \page_col_command_set_top_insertions_indeed} + +\let\page_col_command_flush_top_insertions \page_one_command_flush_top_insertions +\let\page_col_command_flush_bottom_insertions\page_one_command_flush_bottom_insertions + +%let\page_col_command_set_top_insertions \page_one_command_set_top_insertions +\let\page_col_command_set_bottom_insertions \page_one_command_set_bottom_insertions + +%let\page_col_command_set_top_insertions_indeed \page_one_command_set_top_insertions +\let\page_col_command_set_bottom_insertions_indeed \page_one_command_set_botttom_insertions + +\let\page_col_command_flush_float_box \page_one_command_flush_float_box +\let\page_col_command_synchronize_side_floats \page_one_command_synchronize_side_floats +\let\page_col_command_flush_side_floats \page_one_command_flush_side_floats +\let\page_col_command_flush_margin_blocks \page_one_command_flush_margin_blocks +\let\page_col_command_test_page \page_one_command_test_page + +%D The separator code is more or less the same as mixed columns but we need +%D to compensate for the top floats so we comment a bit for now. + +\newdimen\pagecolumnseparatorheight +\newdimen\pagecolumnseparatordepth +\newdimen\pagecolumnseparatorwidth + +% \installcorenamespace{pagecolumnsseparator} +% +% \protected\def\installpagecolumnseparator#1#2% +% {\setvalue{\??pagecolumnsseparator#1}{#2}} +% +% \installpagecolumnseparator\v!rule +% {\vrule +% \s!width \pagecolumnsparameter\c!rulethickness +% \s!height\pagecolumnseparatorheight +% \s!depth \pagecolumnseparatordepth +% \relax} +% +% \def\page_col_routine_package_separate +% {\ifcsname\??pagecolumnsseparator\p_separator\endcsname +% \page_col_command_inject_separator +% \else +% \hss +% \fi} +% +% \protected\def\page_col_command_inject_separator +% {\begingroup +% \setbox\scratchbox\hbox to \zeropoint \bgroup +% \hss +% \starttextproperties +% \usepagecolumnscolorparameter\c!rulecolor +% \begincsname\??pagecolumnsseparator\p_separator\endcsname % was \c!rule +% \stoptextproperties +% \hss +% \egroup +% \ht\scratchbox\zeropoint +% \dp\scratchbox\zeropoint +% \hss +% \box\scratchbox +% \hss +% \endgroup} + +\def\page_col_routine_package_separate + {\hss} + +%D \unknown + +\protected\def\page_col_command_routine + {\page_sides_output_routine} + +% % not: +% +% \protected\def\page_col_command_routine +% {\ifconditional\c_page_sides_short +% \page_sides_output_routine_yes_column +% \else +% \page_sides_output_routine_nop_column +% \fi} +% +% \let\page_sides_output_routine_nop_column\page_sides_output_routine +% +% \def\page_sides_output_routine_yes_column % this might become the main one too +% {\unvbox\normalpagebox % bah, and the discards? +% %\page_col_column +% \column % \page +% % why was this \global\holdinginserts\zerocount +% \global\setfalse\c_page_sides_short} + +\let\page_col_command_flush_all_floats\relax + +%D \unknown + +\defineoutputroutine + [\s!pagecolumn] + [\s!page_otr_command_routine =\page_col_command_routine, + \s!page_otr_command_package_contents =\page_col_command_package_contents, + \s!page_otr_command_set_vsize =\page_col_command_set_vsize, + \s!page_otr_command_set_hsize =\page_col_command_set_hsize, + % \s!page_otr_command_synchronize_hsize =\page_col_command_synchronize_hsize, % not done + \s!page_otr_command_next_page =\page_col_command_next_page, + \s!page_otr_command_next_page_and_inserts =\page_col_command_next_page_and_inserts, + \s!page_otr_command_set_top_insertions =\page_col_command_set_top_insertions, + \s!page_otr_command_set_bottom_insertions =\page_col_command_set_bottom_insertions, + \s!page_otr_command_flush_top_insertions =\page_col_command_flush_top_insertions, + \s!page_otr_command_flush_bottom_insertions=\page_col_command_flush_bottom_insertions, + \s!page_otr_command_check_if_float_fits =\page_col_command_check_if_float_fits, + % \s!page_otr_command_set_float_hsize =\page_col_command_set_float_hsize, % not done + \s!page_otr_command_flush_float_box =\page_col_command_flush_float_box, + \s!page_otr_command_side_float_output =\page_col_command_side_float_output, + \s!page_otr_command_synchronize_side_floats=\page_col_command_synchronize_side_floats, + \s!page_otr_command_flush_floats =\page_col_command_flush_floats, + \s!page_otr_command_flush_side_floats =\page_col_command_flush_side_floats, + \s!page_otr_command_flush_saved_floats =\page_col_command_flush_saved_floats, + \s!page_otr_command_flush_all_floats =\page_col_command_flush_all_floats, + \s!page_otr_command_flush_margin_blocks =\page_col_command_flush_margin_blocks, + \s!page_otr_command_test_column =\page_col_command_test_page + ] + +%D \unknown + +\installfloatmethod \s!pagecolumn \v!here \page_one_place_float_here +\installfloatmethod \s!pagecolumn \v!force \page_one_place_float_force +\installfloatmethod \s!pagecolumn \v!left \page_one_place_float_left +\installfloatmethod \s!pagecolumn \v!right \page_one_place_float_right +\installfloatmethod \s!pagecolumn \v!text \page_one_place_float_text +\installfloatmethod \s!pagecolumn \v!top \page_one_place_float_top +\installfloatmethod \s!pagecolumn \v!bottom \page_one_place_float_bottom +\installfloatmethod \s!pagecolumn \v!auto \page_one_place_float_auto +\installfloatmethod \s!pagecolumn \v!margin \page_one_place_float_margin +\installfloatmethod \s!pagecolumn \v!opposite \page_one_place_float_face +\installfloatmethod \s!pagecolumn \v!page \page_one_place_float_page +\installfloatmethod \s!pagecolumn \v!leftpage \page_one_place_float_leftpage +\installfloatmethod \s!pagecolumn \v!rightpage \page_one_place_float_rightpage +\installfloatmethod \s!pagecolumn \v!inmargin \page_one_place_float_inmargin +\installfloatmethod \s!pagecolumn \v!inleft \page_one_place_float_leftmargin +\installfloatmethod \s!pagecolumn \v!inright \page_one_place_float_rightmargin +\installfloatmethod \s!pagecolumn \v!leftmargin \page_one_place_float_leftmargin +\installfloatmethod \s!pagecolumn \v!rightmargin \page_one_place_float_rightmargin +\installfloatmethod \s!pagecolumn \v!leftedge \page_one_place_float_leftedge +\installfloatmethod \s!pagecolumn \v!rightedge \page_one_place_float_rightedge +\installfloatmethod \s!pagecolumn \v!somewhere \page_one_place_float_somewhere +\installfloatmethod \s!pagecolumn \v!backspace \page_one_place_float_backspace +\installfloatmethod \s!pagecolumn \v!cutspace \page_one_place_float_cutspace +%installfloatmethod \s!pagecolumn \s!tblr \page_one_place_float_top +%installfloatmethod \s!pagecolumn \s!lrtb \page_one_place_float_top +%installfloatmethod \s!pagecolumn \s!tbrl \page_one_place_float_top +%installfloatmethod \s!pagecolumn \s!fxtb \page_one_place_float_top +%installfloatmethod \s!pagecolumn \s!rltb \page_one_place_float_top +%installfloatmethod \s!pagecolumn \s!btlr \page_one_place_float_bottom +%installfloatmethod \s!pagecolumn \s!lrbt \page_one_place_float_bottom +%installfloatmethod \s!pagecolumn \s!btrl \page_one_place_float_bottom +%installfloatmethod \s!pagecolumn \s!rlbt \page_one_place_float_bottom +%installfloatmethod \s!pagecolumn \s!fxbt \page_one_place_float_bottom +%installfloatmethod \s!pagecolumn \s!fixd \page_one_place_float_force + +\installfloatmethod \s!pagecolumn \v!local \somelocalfloat + +%D The main interface: + +\installcorenamespace{pagecolumns} + +\installframedcommandhandler \??pagecolumns {pagecolumns} \??pagecolumns + +\setuppagecolumns + [\c!distance=1.5\bodyfontsize, + \c!n=\plustwo, + \c!page=\v!yes, + %\c!align=, % inherit (also replaces tolerance) + %\c!before=, + %\c!after=, + %\c!separator=\v!none, + %\c!setups=, + %\c!balance=\v!no, + %\c!blank={\v!line,\v!fixed}, yes or no + \c!frame=\v!off, + \c!strut=\v!no, + \c!offset=\v!overlay, + %\c!maxheight=\textheight, + \c!maxwidth=\makeupwidth, + %\c!grid=\v!tolerant, + %\c!internalgrid=\v!line, + \c!direction=\v!normal] + +\appendtoks % could become an option + \frozen\instance\setuevalue{\e!start\currentpagecolumns}{\startpagecolumns[\currentpagecolumns]}% + \frozen\instance\setuevalue{\e!stop \currentpagecolumns}{\stoppagecolumns}% +\to \everydefinepagecolumns + +\def\page_col_pickup_preceding + {\begingroup + \setupoutputroutine[\s!mixedcolumn]% + \c_page_mix_routine\c_page_mix_routine_intercept + \page_otr_trigger_output_routine + \ifvoid\b_page_mix_preceding \else + % moved here, before the packaging + \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding + % we need to avoid unvboxing with successive balanced on one page + \global\setbox\b_page_mix_preceding\vbox\bgroup + % yes or no: \forcestrutdepth + \unvbox\b_page_mix_preceding + \forcestrutdepth + \egroup + \wd\b_page_mix_preceding\makeupwidth + \global\d_page_mix_preceding_height\ht\b_page_mix_preceding + \fi + \endgroup} + +\def\page_col_flush_preceding + {\ifvoid\b_page_mix_preceding \else + % this is just one method but ok for now + \begingroup + % we might need more but for now this is ok + \setupfloat[\c!spacebefore=,\c!spaceafter=]% + \startplacefigure[\c!location={\v!top,\v!none}]% + \box\b_page_mix_preceding + \stopplacefigure + \endgroup + \fi} + +\permanent\tolerant\protected\def\startpagecolumns[#1]% + {\begingroup + \begingroup + \doifelseassignment{#1}% + {\let\currentpagecolumns\empty + \setuppagecolumns[#1]}% + {\edef\currentpagecolumns{#1}}% + \edef\p_page{\pagecolumnsparameter\c!page}% + \ifx\p_page\empty + \setfalse\c_page_col_page + \orelse\ifx\p_page\v!no + \setfalse\c_page_col_page + \else + \settrue\c_page_col_page + \page[\p_page]% + \fi + \c_page_col_n_of_columns\pagecolumnsparameter\c!n\relax + \ifnum\c_page_col_n_of_columns>\plusone + \expandafter\page_col_start_yes + \else + \expandafter\page_col_start_nop + \fi} % public + +\aliased\let\stoppagecolumns\relax + +\protected\def\page_col_start_yes + {\d_page_col_distance \pagecolumnsparameter\c!distance\relax + % \d_page_col_max_height \pagecolumnsparameter\c!maxheight + \d_page_col_max_width \pagecolumnsparameter\c!maxwidth + % \d_page_col_balance_step \pagecolumnsparameter\c!step + \c_page_col_current \plusone + % + \d_page_col_column_width\dimexpr(\d_page_col_max_width-\d_page_col_distance*\numexpr(\c_page_col_n_of_columns-\plusone)\relax)/\c_page_col_n_of_columns\relax + % + \columnwidth \d_page_col_column_width + \columndistance \d_page_col_distance + \nofcolumns \c_page_col_n_of_columns + \textwidth \columnwidth % kind of redundant + % + \nopenalties + % + % \insidecolumnstrue % NO! + % + \enforced\let\column\page_col_column + % + \def\page_floats_get_used_hsize{\makeupwidth} % a bit of a hack + % + \usealignparameter \pagecolumnsparameter + \useblankparameter \pagecolumnsparameter + % \useprofileparameter\pagecolumnsparameter + % + \usepagecolumnscolorparameter\c!color + % + \setupnotes[\c!width=\textwidth]% + % + \usesetupsparameter\pagecolumnsparameter + % + % This will become a method but for now it's good enough + % + \ifconditional\c_page_col_page\else + \page_col_pickup_preceding + \fi + \setupoutputroutine[\s!pagecolumn]% + \ifconditional\c_page_col_page\else + \page_col_flush_preceding + \fi + % + \setupfloats[\c!ntop=\plusthousand]% + % \setupfloats[\c!nbottom=\plusthousand]% + % + \page_col_command_set_vsize + \page_col_command_set_hsize + % + \enforced\permanent\protected\def\startpagecolumns[##1]{\page_col_start_nop}% + % + \enforced\let\stoppagecolumns\page_col_stop_yes} + +\protected\def\page_col_start_nop + {\nofcolumns\c_page_mix_n_of_columns + \enforced\let\stoppagecolumns\page_col_stop_nop} + +\protected\def\page_col_stop_yes + {\column % \page_otr_eject_page + \page + \endgroup + % \setupoutputroutine[\s!singlecolumn]% + \page_otr_command_set_vsize + \page_otr_command_set_hsize + \page + \endgroup} + +\protected\def\page_col_stop_nop + {\page + \endgroup + \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-plg.mkxl b/tex/context/base/mkxl/page-plg.mkxl new file mode 100644 index 000000000..10cc1447b --- /dev/null +++ b/tex/context/base/mkxl/page-plg.mkxl @@ -0,0 +1,213 @@ +%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 checked cq.\ +%D optimized. Beware: method has become alternative! + +%D This feature has been present for a while but has never been exploited: pluggable +%D pagebuilders. The next example code demonstrates the application of one such a +%D plug-in. This variant support \type {page}, \type {leftpage} and \type +%D {rightpage} 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 + +\permanent\tolerant\protected\def\pagearea[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreeoptionals + \or + \expandafter\page_area_one + \or + \expandafter\page_area_two + \or + \expandafter\page_area_three + \fi[#1][#2][#3]} + +\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 + \orelse\ifx\m_page_area_three\v!right + \let\m_page_area_three\c!righttext + \else + \let\m_page_area_three\c!middletext + \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 + \orelse\ifcsname\??layoutbackgrounds#1#2\endcsname + \page_area_indeed_yes{#1}{#2}% + \else + \box\b_page_area + \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} + +\permanent\protected\def\startpagelayout + {\bgroup + \catcode\endoflineasciicode\ignorecatcode + \page_layouts_start_layout} + +\aliased\let\stoppagelayout\relax + +\def\page_layouts_start_layout[#1]#2\stoppagelayout + {\egroup + \setvalue{\??layoutmakeupalternative#1}{#2}} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-pst.mkxl b/tex/context/base/mkxl/page-pst.mkxl new file mode 100644 index 000000000..88e962805 --- /dev/null +++ b/tex/context/base/mkxl/page-pst.mkxl @@ -0,0 +1,110 @@ +%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}{} + +\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 is somewhat easier +%D and we also can erase buffers easier when we keep a local cache, especially as we +%D can flush per page. + +\newcount \c_page_postponed_blocks_next_page % set at the lua end +\newconditional\c_page_postponed_busy + +\permanent\protected\setvalue{\e!start\v!postponing}% + {\bgroup + \obeylines + \doifelsenextoptional{\egroup\page_postponed_blocks_start}{\egroup\page_postponed_blocks_start[0]}} + +\permanent\protected\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}} + +%D Officially we should flush again after a flush as there can be new future pages +%D but that will be looked into when we run into it. + +\c_page_postponed_mode\plusone + +\protected\def\page_postponed_blocks_flush_indeed + {\begingroup + \setsystemmode\v!postponing + \settrue\c_page_postponed_busy + \ifnum\c_page_postponed_mode=\plusone + \savepagecontent + \fi + \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 + \ifnum\c_page_postponed_mode=\plusone + \flushpagecontent + \fi + \endgroup} % of blocks: with and without flush + +\protected\def\page_postponed_blocks_flush + {\ifconditional\c_page_postponed_busy + % probably a nested flush + \orelse\ifnum\c_page_postponed_blocks_next_page=\zerocount + % nothing in cache + \orelse\ifnum\c_page_postponed_blocks_next_page<\zerocount + % generic cache + \page_postponed_blocks_flush_indeed + \orelse\ifnum\c_page_postponed_blocks_next_page>\realpageno + % future content + \else + % pending content + \page_postponed_blocks_flush_indeed + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-sel.mklx b/tex/context/base/mkxl/page-sel.mklx new file mode 100644 index 000000000..dfd4c27f3 --- /dev/null +++ b/tex/context/base/mkxl/page-sel.mklx @@ -0,0 +1,417 @@ +%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 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 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. + +%D Beware: width is not the width of the image, but height can be used to control +%D its dimensions. + +\installcorenamespace{withpages} + +\installsetuponlycommandhandler \??withpages {withpages} +% \installdirectcommandhandler \??withpages {withpages} + +\newcount\c_page_selectors_n + +\permanent\tolerant\protected\def\insertpages[#filename]#spacer[#emptylist]#spacer[#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,% + \c!category=,% + #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} + +\permanent\tolerant\protected\def\filterpages[#filename]#spacer[#selection]#spacer[#settings]% % \noffigurepages not yet supported + {\bgroup + \dontcomplain + \getfiguredimensions[#filename]% + \setupcurrentwithpages + [\c!width=\zeropoint,% + \c!n=\noffigurepages,% + \c!category=,% + #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}% + \orelse\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 + \egroup} + +\def\page_selectors_filter_a_page#filename#page% + {\hpack to \textwidth + {\ifdim\scratchwidth>\zeropoint + \rightorleftpageaction{\scratchwidth\zeropoint}{\hfill}% + \fi + \setbox\scratchbox\hpack + {\hskip-\scratchwidth + \edef\p_category{\directwithpagesparameter\c!category}% \useexternalfigure[foo][width=\textwidth] + \ifx\p_category\empty + \externalfigure[#filename][\c!page=#page,\c!height=\textheight]% + \else + \externalfigure[#filename][\p_category][\c!page=#page]% + \fi + \hss}% + \wd\scratchbox\zeropoint + \box\scratchbox} + \page} + +\permanent\tolerant\protected\def\copypages[#filename]#spacer[#settings]#spacer[#figuresettings]% + {\bgroup + \getfiguredimensions[#filename]% + \setupcurrentwithpages + [\c!marking=\v!off,% + \c!offset=\zeropoint,% + \c!n=\noffigurepages,% + \c!category=,% + #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\hpack % 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} + +\permanent\tolerant\protected\def\combinepages[#filename]#spacer[#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}, + \c!category=, + #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}% use hpacks + {\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 + \orelse\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 + \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 + \orunless\ifnum\combinedpagescounter>\c_page_selectors_n + \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}} + \global\advance\combinedpagescounter\plusone + \directwithpagesparameter\c!bottom}}% + \hfil}% + \hfilneg}}% + \page + \ifnum\combinedpagescounter>\c_page_selectors_n + \exitloop + \fi}} + +\letcsname\??combinepagesalternative\v!horizontal\expandafter\endcsname\csname\??combinepagesalternative\v!a\endcsname +\letcsname\??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. + +\permanent\tolerant\protected\def\slicepages[#filename]#spacer[#oddsettings]#spacer[#evensettings]% + {\ifparameter#evensettings\or + \page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]% + \else + \page_selectors_slice_indeed[#filename][#oddsettings][#oddsettings]% + \fi} + +\mutable\let\slicedpagenumber\!!zerocount +\mutable\let\slicedpagestepx \!!zerocount +\mutable\let\slicedpagestepy \!!zerocount + +\def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]% + {\bgroup + \dontcomplain + \glet\slicedpagenumber\!!zerocount + \getfiguredimensions[#filename]% + \setupcurrentwithpages + [\c!offset=\zeropoint,% + \c!hoffset=\zeropoint,% + \c!voffset=\zeropoint, + \c!width=\figurewidth,% + \c!height=\figureheight,% + \c!n=\noffigurepages,% + \c!category=,% + #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 + {\glet\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 + +\permanent\protected\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/tex/context/base/mkxl/page-sid.mkxl b/tex/context/base/mkxl/page-sid.mkxl new file mode 100644 index 000000000..d5032ddd0 --- /dev/null +++ b/tex/context/base/mkxl/page-sid.mkxl @@ -0,0 +1,1019 @@ +%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 + +%D These macro deal with side floats. We started with Daniel Comenetz macros as +%D published in TUGBoat Volume 14 (1993), No.\ 1: Anchored Figures at Either Margin. +%D I extended and patched the macros to suite our needs which results in a messy +%D module. +%D +%D A complication is that we need to deal with spacing differently before and after +%D the float. Also, whitespace can interfere as does the prevdepth. There is no real +%D universal solution. So, by now not much is left of that code, if only because we +%D need to match \CONTEXT\ spacing module, because we have more placement options +%D and control and because the math hackery is not suitable for \CONTEXT\ anyway. +%D +%D This code had been redone many times because we kept running into spacing issues +%D and it's not that much fun (or rewarding). It's probably the module that made +%D me go into distraciton mode most often (like watching amusing Walk of The +%D Earth, sophisticated Massive Attack video clips, impressive Davie504 movies +%D and so on). + +\newdimen \d_page_sides_margin +\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 +\newdimen \d_page_sides_progress +\newdimen \d_page_sides_page_total + +\newdimen \d_page_sides_leftoffset +\newdimen \d_page_sides_rightoffset + +%newbox \b_page_sides_bottom + +\newcount \c_page_sides_lines_done +\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 +\newcount \c_page_sides_hangafter + +\newconditional \c_page_sides_short +\newconditional \c_page_sides_flag + +\newdimen \d_page_sides_shift +\newdimen \d_page_sides_extrashift +\newdimen \d_page_sides_leftshift +\newdimen \d_page_sides_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_midskip +\newdimen \d_page_sides_downshift +\newdimen \d_page_sides_pagetotal +\newdimen \d_page_sides_topoffset +\newdimen \d_page_sides_bottomoffset +\newdimen \d_page_sides_toptotal +\newdimen \d_page_sides_bottomtotal + +\newconstant \c_page_sides_align +\newconstant \c_page_sides_skipmode +\newconstant \c_page_sides_tolerance + +\newconstant \c_page_sides_method % sort of obsolete + +\newdimen \d_page_sides_progression + +\newcount \c_page_sides_m_of_lines +\newconditional \c_page_sides_delayed + +\newconditional \c_page_sides_check_same_page + +\newif \iftracesidefloats % public (might change) + +%D Defaults: + +\d_page_sides_vsize_reset -\onepoint +%d_page_sides_vsize_reset \zeropoint % could be an option, needs testing + +%D We have some basic (and colorful) tracing: + +\def\page_sides_floats_legend + {\showmessage\m!floatblocks{16}\empty + \glet\page_sides_floats_legend\relax} + +\installtextracker{floats.anchoring} + {\page_sides_floats_legend + \tracesidefloatstrue} + {\tracesidefloatsfalse} + +%D The horizontal shifts depend on the location: left or right in the text, margin +%D or edge. These shifts are rather stable and don't interfere with the page flow +%D as much as the vertical ones do. + +\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} + +\def\page_sides_check_horizontal_skips + {\ifcase\c_page_sides_skipmode + \or % high + \or % low + \or % fit + \global\d_page_sides_margin\zeropoint + \fi} + +\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 + \orelse\ifnum\c_page_sides_float_type=\plusfive + \global\advance\d_page_sides_shift\d_page_sides_extrashift + \global\d_page_sides_extrashift\zeropoint + \fi + \else + \ifnum\c_page_sides_float_type<\plusfour + \global\c_page_sides_float_type\plusfour + \orelse\ifnum\c_page_sides_float_type>\plusfive + \global\c_page_sides_float_type\plusfive + \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 + \global\d_page_sides_leftoffset \d_page_sides_rightskip + \global\d_page_sides_rightoffset\d_page_sides_leftskip + \ifdim\d_page_sides_rightskip>\zeropoint + \global\advance\d_page_sides_rightskip\rightskip + \fi + \ifdim\d_page_sides_leftskip >\zeropoint + \global\advance\d_page_sides_leftskip \leftskip + \fi} + +%D Shifts get applied to the float box: + +\def\page_sides_relocate_float#1% + {\global\setbox\floatbox\hpack + {\ifnum\c_page_sides_float_type=\plusfour + \kern\d_page_sides_leftshift + \orelse\ifnum\c_page_sides_float_type=\plusone + \kern\d_page_sides_leftshift + \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_sides_rightshift + \orelse\ifnum\c_page_sides_float_type=\plusfive + \kern\d_page_sides_rightshift + \fi}} + +%D The vertical skips are a nightmare and this mechanism is about as complex +%D as one can get it. + +\def\page_sides_check_vertical_skips + {\ifdim\d_page_sides_topskip <\zeropoint\d_page_sides_topskip \zeropoint\fi + \ifdim\d_page_sides_bottomskip<\zeropoint\d_page_sides_bottomskip\zeropoint\fi + \ifdim\d_page_sides_midskip <\zeropoint\d_page_sides_midskip \zeropoint\fi + % + \global\d_page_sides_toptotal \dimexpr\d_page_sides_topskip +\d_page_sides_topoffset \relax + \global\d_page_sides_bottomtotal\dimexpr\d_page_sides_bottomskip+\d_page_sides_bottomoffset\relax + \ifcase\c_page_sides_skipmode + \or % high + \global\d_page_sides_toptotal \d_page_sides_topoffset + \or % low + \global\d_page_sides_bottomtotal\d_page_sides_bottomoffset + \or % fit + \global\d_page_sides_toptotal \d_page_sides_topoffset + \global\d_page_sides_bottomtotal\d_page_sides_bottomoffset + \fi} + +%D These shifts get (selectively) applied with a bit of optional tracing. + +\def\page_sides_apply_vertical_shift_normal + {\global\setbox\floatbox\hpack % why extra box + {\vpack + {\forgetall + \hsize\wd\floatbox + \vskip\privatescratchdimen + \offinterlineskip + \box\floatbox + % somehow we need this \scratchbox magic, but at least it's the same as the + % tracer now + \setbox\scratchbox\emptybox + \wd\scratchbox\hsize + \ht\scratchbox\d_page_sides_bottomtotal + \box\scratchbox + \vskip-\d_page_sides_bottomtotal + \ifnum\c_page_sides_align=\plusfive + \vskip-\lineheight + \fi}}} + +\def\page_sides_apply_vertical_shift_traced + {\global\setbox\floatbox\hpack % why extra box + {\backgroundline[trace:r]{\ruledhpack{\vpack + {\forgetall + \hsize\wd\floatbox + \vskip\privatescratchdimen + \offinterlineskip + \backgroundline + [trace:g]% + {\ruledhpack{\box\floatbox}}% + \par + \blackrule + [\c!color=trace:s,% + \c!height=\d_page_sides_bottomtotal,% + \c!depth=\zeropoint,% + \c!width=\hsize]% + \vskip-\d_page_sides_bottomtotal + \ifnum\c_page_sides_align=\plusfive + \vskip-\lineheight + \fi}}}}} + +\def\page_sides_apply_vertical_shift + {\ifnum\c_page_sides_align=\plusfour + \getnoflines{\ht\floatbox}% + \privatescratchdimen\dimexpr\noflines\lineheight-\strutdp\relax + \getrawnoflines\d_page_sides_toptotal + \advance\privatescratchdimen\noflines\lineheight + \page_sides_force_depth + \ht\floatbox\privatescratchdimen + \dp\floatbox\zeropoint + \fi + \ifcase\c_page_sides_align \else + \global\d_page_sides_toptotal\zeropoint + \fi + \privatescratchdimen + \ifnum\c_page_sides_float_type<\plusfour + \d_page_sides_toptotal + \orelse\ifnum\c_page_sides_float_type>\plusfive + \d_page_sides_toptotal + \else + \zeropoint + \fi + % the top of the box is at the previous baseline + \ifcase\c_page_sides_align + % 0 normal + \advance\privatescratchdimen\strutdp % or \openstrutdepth + \or % 1 height + \advance\privatescratchdimen\strutdp % or \openstrutdepth + \or % 2 line + \or % 3 depth + \advance\privatescratchdimen\lineheight % or \openlineheight + \advance\privatescratchdimen\strutdp % or \openstrutdepth + \or % 4 grid + \privatescratchdimen\zeropoint + \or + \advance\privatescratchdimen\strutht % or \openstrutheight + \fi + % new + \global\c_page_sides_lines_done\zerocount + \ifnum\c_page_sides_n_of_lines>\zerocount + \advance\privatescratchdimen\c_page_sides_n_of_lines\lineheight + \fi + \iftracesidefloats + \page_sides_apply_vertical_shift_traced % uses \privatescratchdimen + \else + \page_sides_apply_vertical_shift_normal % uses \privatescratchdimen + \fi + \ifnum\c_page_sides_float_type<\plusfour + \global\d_page_sides_toptotal\zeropoint + \orelse\ifnum\c_page_sides_float_type>\plusfive + \global\d_page_sides_toptotal\zeropoint + \fi + \global\d_page_sides_downshift\zeropoint} + +%D We have a few virtual dimensions. I'm not sure what to do with \type +%D {\pagedepth} and \type {\pageshrink} in the next two. If we ever need +%D that it will become options. + +\def\e_page_sides_flush_criterium + {\dimexpr + \d_page_sides_vsize + -\d_page_sides_bottomtotal + -\pagetotal + \relax} + +\def\e_page_sides_room_criterium + {\dimexpr + \d_page_sides_vsize + -\d_page_sides_bottomtotal % added here too + -\pagetotal + \relax} + +%D In order to get a consistent spacing we force a strutdepth unless the +%D preceding material has more depth than that already. This way anchoring +%D becomes predictable. + +\protected\def\page_sides_force_depth + {\iftracesidefloats + \begingroup + \c_page_force_strut_depth_trace_mode\plusone + \ifconditional\c_page_sides_check_same_page + \forcestrutdepthplus + \else + \forcestrutdepth + \fi + \endgroup + \else + \ifconditional\c_page_sides_check_same_page + \forcestrutdepthplus + \else + \forcestrutdepth + \fi + \fi + \page_otr_command_set_vsize} % new + +\def\page_sides_flush_floats + {\par + \ifdim\e_page_sides_flush_criterium>\zeropoint + \page_sides_flush_floats_progress + \page_sides_flush_floats_after_next + \fi + \page_sides_flush_floats_reset} + +\def\page_sides_flush_floats_text + {\par + % what with \c_anch_backgrounds_text_level>\plusone + \ifdim\e_page_sides_flush_criterium>\zeropoint + \page_sides_flush_floats_progress + \page_sides_flush_floats_after_none + \fi + \page_sides_flush_floats_reset} + +\def\page_sides_flush_floats_reset + {\global\d_page_sides_vsize\d_page_sides_vsize_reset + % also here if used at all \global\holdinginserts\zerocount + \global\setfalse\c_page_sides_short + \global\setfalse\c_page_sides_flag + \global\c_page_sides_checks_done\zerocount} + +\def\page_sides_flush_floats_after_none % we force a flush + {\ifdim\d_page_sides_midskip>\zeropoint + \blank[\the\d_page_sides_midskip] + \fi + \ignoreparskip + \blank[\v!disable]} + +\def\page_sides_flush_floats_after_next % we have two successive ones + {\ifdim\d_page_sides_bottomskip>\zeropoint + \blank[\the\d_page_sides_bottomskip] + \fi + \ignoreparskip + \blank[\v!disable]} + +%D A rudimentary checker: + +\permanent\protected\def\doifelsesidefloat + {\par + \ifdim\e_page_sides_room_criterium>\zeropoint % -\pagedepth + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifsidefloatelse\doifelsesidefloat + +%D Sometimes we need to fill up the space alongside a side float and this +%D is where we define the helpers. A user can enforce a smaller step. We use +%D large steps when possible. + +\installcorenamespace{sidefloatsteps} + +\setvalue{\??sidefloatsteps\v!line }{\strut} +\setvalue{\??sidefloatsteps\v!big }{\strut} +\setvalue{\??sidefloatsteps\v!medium}{\halflinestrut} % was \halfstrut +\setvalue{\??sidefloatsteps\v!small }{\noheightstrut} % was \quarterstrut + +\def\page_sides_flush_floats_tracer + {\dontleavehmode + \ruledhpack\bgroup\backgroundline[trace:b]{% + \llap{\smash{\vrule\s!width4\points\s!height.4\points\s!depth.4\points}}% + \ifnum\recurselevel=\plusone + \llap{\smash{\smallinfofont\the\scratchdimen}\hskip.5\leftmargindistance}% + \orelse\ifodd\recurselevel + \llap{\smash{\smallinfofont\recurselevel}\hskip.5\leftmargindistance}% + \fi + \page_sides_flush_floats_normal + \kern\hsize + \egroup}} + +\def\page_sides_flush_floats_normal + {\ifdim\scratchdimen>\htdp\strutbox + \strut + \else + \m_pages_strut + \fi} + +\def\page_sides_flush_floats_progress + {\begingroup + \page_sides_force_depth + \parskip\zeropoint + \let\page_sides_flush_floats\relax + \edef\m_pages_strut + {\ifcsname\??sidefloatsteps\rootfloatparameter\c!step\endcsname + \lastnamedcs + \else + \noheightstrut + \fi}% + \forgetall + \offinterlineskip + \doloop + {\scratchdimen\e_page_sides_flush_criterium + \ifdim\scratchdimen>\onepoint % good enough, can become configurable + \ifnum\recurselevel>\plushundred % safeguard, sort of deadcycles + \exitloop + \orelse\iftracesidefloats + \page_sides_flush_floats_tracer\par + \else + \page_sides_flush_floats_normal\par + \fi + \else + \page_sides_force_depth + \exitloop + \fi}% + \endgroup} + +%D We force a parskip and ignore it afterwards. We can nil it by setting the +%D \type {spacebeforeside} parameter. We can have a leading blank so we need +%D to make sure that we use blank to inject the parskip and then ignore +%D the one injected by the engine. + +\def\page_sides_inject_before + {\page_sides_force_depth + \ifdim\parskip>\zeropoint + \ifdim\parskip>\d_strc_floats_top + \ifdim\d_strc_floats_top>\zeropoint + \ignoreparskip + \blank[\v!white]% + \else + \checkedblank[\rootfloatparameter\c!spacebeforeside]% + \fi + \else + \checkedblank[\rootfloatparameter\c!spacebeforeside]% + \fi + \else + \checkedblank[\rootfloatparameter\c!spacebeforeside]% + \fi} + +%D We are now done with \type {spacebefore} and the parskip is already +%D injected. The dummy line makes sure that we anchor properly and it +%D also can serve as tracer. + +\def\page_sides_inject_dummy_line_normal + {\hpack to \availablehsize{\strut\hss}} + +\def\page_sides_inject_dummy_line_traced + {\ruledhpack to \availablehsize{\backgroundline[trace:c]{\page_sides_inject_dummy_line_normal}}} + +\def\page_sides_inject_dummy_lines + {\par + \nointerlineskip + % \ifnum\lastpenalty>\zerocount + % \penalty\plustenthousand + % \fi + \dontleavehmode + \iftracesidefloats + \page_sides_inject_dummy_line_traced + \else + \page_sides_inject_dummy_line_normal + \fi + \par + % on an empty page we have topskip, say 12pt + \ignoreparskip + % this can be 18.5pt + \kern-\dimexpr\lineheight+\strutdp\relax + % so we can actually have a -2.5pt skip on top + \ignoreparskip + \blank[\v!samepage] + \blank[\v!disable] + % now say we are negative now + \ifdim\pagetotal<\zeropoint + % then we're at the top of the page ... quite messy .. i really need to + % make the page builder a bit more flexible .. should we do something now? + \fi} + +%D Checkers: + +\def\page_sides_check_floats_after_par + {\page_sides_check_floats_indeed + \ifdim\d_page_sides_pagetotal=\pagetotal \else + \glet\page_sides_check_floats\page_sides_check_floats_indeed + \page_sides_flush_floats + \global\c_page_sides_n_of_lines\zerocount % here ! + \fi} + +\protected\def\page_sides_flush_floats_after_par + {\global\d_page_sides_pagetotal\pagetotal + \glet\page_sides_check_floats\page_sides_check_floats_after_par} + +\protected\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} + +%D Here comes the output routine. We either go the fast route or we use the +%D normal one (stored in \type {\page_otr_command_side_float_output}. We no +%D longer have this fuzzy code around with penalties and indentation and +%D such. + +\def\page_sides_output_routine + {\page_otr_command_side_float_output + \ifconditional\c_page_sides_short + \global\setfalse\c_page_sides_short + \else + \global\d_page_sides_vsize\d_page_sides_vsize_reset + \global\c_page_sides_n_of_lines\zerocount + \fi} + +\def\page_sides_place_float + {\ifnum\c_page_sides_float_type=\plusfour \kern\d_page_sides_toptotal \fi + \ifnum\c_page_sides_float_type=\plusfive \kern\d_page_sides_toptotal \fi + \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} + +\def\page_sides_place_float_normal + {\page_sides_push_float_inline\firstofoneargument} + +%D The following needs some more work .. consider this a quick hack. We probably +%D need an mkiv hanging grid option. + +\def\page_sides_place_snap_to_grid#1% + {\edef\p_grid{\floatparameter\c!grid}% + \ifx\p_grid\empty\else + \snaptogrid[\p_grid]% + \fi + \hpack{#1}} + +\def\page_sides_place_float_grid + {\getrawnoflines\d_page_sides_height % raw ? + \d_page_sides_height\noflines\lineheight + \page_sides_push_float_inline\page_sides_place_snap_to_grid} + +\let\strc_floats_mark_par_as_free\relax + +\def\page_sides_push_float_inline#1% + {\begingroup + \reseteverypar % needed ! + \parskip\zeropoint % needed ! + \nointerlineskip + \page_sides_set_skips + \page_floats_report_total + \relax + \lefttoright + \strc_floats_mark_par_as_free + \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} + +% test case +% +% \usemodule[art-01] +% \starttext +% \dorecurse{40}{\line{#1}} +% \placefigure[left]{}{} +% \input ward +% \startitemize +% \item word \item word \item word \item word +% \stopitemize +% \input ward +% \page +% \stoptext + +\def\page_sides_analyse_progress + {%\page_otr_command_set_vsize % this is new, otherwise topfloats are not taken into account + \d_page_sides_progress\d_page_sides_vsize + \ifconditional\c_page_sides_flag + \advance\d_page_sides_progress-\d_page_sides_page_total + \global\setfalse\c_page_sides_flag + \else + \ifdim\dimexpr\d_page_sides_progress+\d_page_sides_bottomtotal\relax>\pagegoal + % we adapt pagegoal because we can already have placed something with + % everypar and we hope that it triggers a flush, see test above + \pagegoal\dimexpr\pagegoal-\d_page_sides_bottomtotal\relax + \fi + \advance\d_page_sides_progress-\pagetotal + \fi} + +\def\page_sides_analyse_space_stage_one + {\global\settrue\c_page_sides_flag +% \ifdim\pagegoal=\maxdimen +% \pagegoal\textheight % maybe +% \fi + \global\d_page_sides_page_total \pagetotal % global + \ifnum\c_page_sides_float_type<\plusfour + \global\d_page_sides_width \zeropoint + \orelse\ifnum\c_page_sides_float_type>\plusfive + \global\d_page_sides_width\zeropoint + \else + \global\d_page_sides_width\dimexpr\wd\floatbox+\d_page_sides_margin\relax + \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_toptotal\relax + \global\d_page_sides_vsize \dimexpr\d_page_sides_height+\d_page_sides_page_total\relax + \scratchdimenone\d_page_sides_vsize + \scratchdimentwo\pagegoal + \ifcase\c_page_sides_tolerance + \ifcase\c_page_sides_method + % method 0 : raw + \or + % method 1 : safe (default) + \advance\scratchdimentwo -\strutdp + \or + % method 2 : tight (grid default) + \advance\scratchdimenone -\onepoint + \fi + \or + % tolerant + \advance\scratchdimentwo -.5\strutdp + \or + % verytolerant + % \advance\scratchdimenone -\onepoint (maybe) + \else + \advance\scratchdimentwo -\strutdp + \fi} + +\def\page_sides_analyse_space_stage_two + {% how about \pagedepth + \ifdim\scratchdimenone>\scratchdimentwo + \global\setfalse\c_page_floats_room + \else + \ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomtotal + % just weird: \global\advance\d_page_sides_vsize \scratchdimenone + \global\settrue\c_page_sides_short + % why was this \global\holdinginserts\plusone + \else + \global\advance\d_page_sides_vsize \d_page_sides_bottomtotal % wins over inbetween + \global\setfalse\c_page_sides_short + \fi + \global\settrue\c_page_floats_room + \fi} + +\def\page_sides_analyse_space + {\page_sides_analyse_space_stage_one + \ifconditional\c_page_sides_check_same_page + \ifdim\d_spac_prevcontent>\zeropoint + \ifdim\dimexpr\scratchdimenone+\d_spac_prevcontent>\scratchdimentwo + \clf_pushatsame + \setbox\scratchbox\vpack{\clf_popatsame}% + \page + \box\scratchbox + \vskip-\lineskip + \page_sides_analyse_space_stage_one + \fi + \fi + \fi + \page_sides_analyse_space_stage_two} + +%D As we have no clear end of one or more paragraphs we only have pre float +%D skips. + +\newconstant\c_page_sides_page_method % will be: \c_page_sides_page_method\plusone + +\def\page_otr_force_new_page_one + {\vskip\d_page_sides_height + \penalty\outputpenalty + \vskip-\dimexpr\d_page_sides_height-\strutdp\relax + \prevdepth\strutdp} + %\ignoreparskip} + +\def\page_sides_handle_float#1% + {\page_sides_initialize_checker + \page_sides_check_horizontal_skips + \page_sides_check_vertical_skips + \page_sides_apply_horizontal_shift + \page_sides_check_previous_float + \page_sides_inject_before + \page_sides_inject_dummy_lines + \page_sides_relocate_float{#1}% + \page_sides_apply_vertical_shift + \page_sides_analyse_space + \ifconditional\c_page_floats_room + \global\setfalse\c_page_sides_delayed + % we're ok + \else + \global\settrue\c_page_sides_delayed + \global\c_page_sides_m_of_lines\c_page_sides_n_of_lines + \ifcase\c_page_sides_page_method + \page_otr_fill_and_eject_page + \or + \page_otr_force_new_page_one + \else + \page_otr_fill_and_eject_page + \fi + \global\c_page_sides_n_of_lines\c_page_sides_m_of_lines + \page_sides_analyse_space + %\page_sides_inject_before + \page_sides_inject_dummy_lines + \fi + \page_sides_place_float + \global\setfalse\c_page_sides_delayed + \page_sides_check_floats_reset + \page_sides_wrapup} + +\def\page_sides_wrapup + {% we need to do this aftergroup + \aftergroup\par + \aftergroup\ignoreparskip + \aftergroup\ignorespaces} + +\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} % not needed + +% \let\page_sides_check_floats\page_sides_check_floats_indeed + +\let\page_sides_check_floats\relax + +\def\page_sides_initialize_checker + {\ifx\page_sides_check_floats\relax + \glet\page_sides_check_floats\page_sides_check_floats_indeed + \clf_enablesidefloatchecker + \glet\page_sides_initialize_checker\relax + \fi} + +\protected\def\page_sides_check_floats_tracer + {\begingroup + \dontleavehmode + \ifnum\c_page_sides_float_type>\plusfour + \rlap + {\hskip\availablehsize % d_page_sides_width % kern + \color[trace:o]% + {\rlap{\kern.25\bodyfontsize\showstruts\strut}% + \vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width}}% + \else + \hskip-\d_page_sides_width % kern + \color[trace:o]% + {\vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width + \llap{\showstruts\strut\kern.25\bodyfontsize}}% + \fi + \endgroup} + +% tricky test: + +% \starttext +% \dorecurse{33}{\line{#1}} +% \placefigure[left]{}{} +% \input ward +% \startitemize +% \item word \item word \item word \item word +% \stopitemize +% \input ward +% \page +% \placefigure[left]{}{} +% \dontleavehmode \begingroup \input ward \par \endgroup +% \dontleavehmode \begingroup \input ward \par \endgroup +% \dontleavehmode \begingroup \input ward \par \endgroup +% \input ward +% \stoptext + +\protected\def\page_sides_check_floats_set + {\edef\p_sidethreshold{\floatparameter\c!sidethreshold}% + \ifconditional\c_page_sides_delayed + % For Alan's hanging right float that moved to the next page. + \d_page_sides_progress\zeropoint + \fi + \ifx\p_sidethreshold\v!old + \d_page_sides_progression\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax + \c_page_sides_n_of_hang\d_page_sides_progression + \divide\c_page_sides_n_of_hang \baselineskip\relax + \else + \d_page_sides_progression + \ifx\p_sidethreshold\empty + \d_page_sides_progress + \else + \dimexpr\d_page_sides_progress-\p_sidethreshold\relax + \fi + \getnoflines\d_page_sides_progression + % this can be an option + \ifdim\dimexpr\noflines\lineheight>\dimexpr\pagegoal-\pagetotal\relax + \getrawnoflines\d_page_sides_progression + \fi + % + \c_page_sides_n_of_hang\noflines + \fi + \global\c_page_sides_hangafter\zerocount + \ifnum\c_page_sides_n_of_hang>\zerocount + \ifcase\c_page_sides_n_of_lines + \else + \ifcase\c_page_sides_lines_done + \global\c_page_sides_lines_done\c_page_sides_n_of_hang + \else + \privatescratchcounter\c_page_sides_lines_done + \advance\privatescratchcounter-\c_page_sides_n_of_hang + \global\advance\c_page_sides_n_of_lines-\privatescratchcounter + \fi + \fi + \ifnum\c_page_sides_n_of_lines>\zerocount + \privatescratchtoks\emptytoks + \privatescratchcounter\c_page_sides_n_of_lines + \privatescratchdimen\dimexpr\hsize-\d_page_sides_width\relax + \dorecurse\c_page_sides_n_of_lines + {\toksapp\privatescratchtoks{\zeropoint\hsize}}% + \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\privatescratchcounter\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 + \toksapp\privatescratchtoks{\zeropoint\privatescratchdimen}% + \else + \toksapp\privatescratchtoks{\d_page_sides_width\privatescratchdimen}% + \fi}% + \fi + \parshape + \numexpr\privatescratchcounter+\plusone\relax + \the\privatescratchtoks + \zeropoint \hsize + \relax + \else + \hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width + \hangafter-\c_page_sides_n_of_hang + \global\c_page_sides_hangafter\hangafter + \fi + \fi + \global\advance\c_page_sides_checks_done \plusone + \iftracesidefloats + \page_sides_check_floats_tracer + \fi} + +\protected\def\page_sides_check_floats_reset + {\ifcase\c_page_sides_checks_done\else + \ifcase\c_page_sides_hangafter\else + % we need to deal with par's ending in a group which would restore + % hang parameters + \global\c_page_sides_hangafter\zerocount + \hangindent\zeropoint + \fi + % \global % no, otherwise a next hangindent won't work + \c_page_sides_checks_done\zerocount + \fi} + +\protected\def\page_sides_synchronize_floats + {\ifinner \else + \page_sides_check_floats + \fi} + +\protected\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\adjustsidefloatdisplaylines % public, will change +% {\aftergroup\page_sides_adjust_display_lines} +% +% \def\page_sides_adjust_display_lines +% {\par +% \noindent +% \ignorespaces} + +%D We need to hook it into the other otr's. This code will be adapted once we rename +%D the callers. We use \type {\def} as they can be redefined! Some will become obsolete + +\permanent\protected\def\checksidefloat {\page_sides_check_floats} +\permanent\protected\def\flushsidefloats {\page_sides_flush_floats_text} +\permanent\protected\def\flushsidefloatsafterpar{\page_sides_flush_floats_after_par} +\permanent\protected\def\forgetsidefloats {\page_sides_forget_floats} +%permanent\protected\def\synchronizesidefloats {\page_sides_synchronize_floats} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-smp.mkxl b/tex/context/base/mkxl/page-smp.mkxl new file mode 100644 index 000000000..ccb0e989e --- /dev/null +++ b/tex/context/base/mkxl/page-smp.mkxl @@ -0,0 +1,56 @@ +%D \module +%D [ file=page-smp, % was: core-mul, page-mul +%D version=1998.03.15, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Simple Multi Column Output, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D The old one: + +\definemixedcolumns + [\v!columns] + % compatible with columns default : + [\c!balance=\v!yes, + \c!blank={\v!line,\v!fixed}] + +\permanent\protected\def\setupcolumns + {\setupmixedcolumns[\v!columns]} + +%D This will be replaced by mixed box. + +\permanent\tolerant\protected\def\startsimplecolumns[#1]% + {\bgroup + \setsimplecolumnshsize[#1]% + \nopenalties + \setbox\scratchbox\vbox\bgroup + \forgetall} % \blank[\v!disable] + +\permanent\protected\def\stopsimplecolumns + {\removebottomthings + \egroup + \rigidcolumnbalance\scratchbox + \egroup} + +\permanent\protected\def\setsimplecolumnshsize[#1]% + {\getdummyparameters + [\c!width=\hsize, + \c!distance=1.5\bodyfontsize, + \c!n=2, + \c!lines=0, + #1]% + \edef\rigidcolumnlines + {\directdummyparameter\c!lines}% + \setrigidcolumnhsize + {\directdummyparameter\c!width}% + {\directdummyparameter\c!distance}% + {\directdummyparameter\c!n}} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-spr.mkxl b/tex/context/base/mkxl/page-spr.mkxl new file mode 100644 index 000000000..49285c96f --- /dev/null +++ b/tex/context/base/mkxl/page-spr.mkxl @@ -0,0 +1,129 @@ +%D \module +%D [ file=page-spr, +%D version=2002.11.11, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Spreading, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Spreading} + +% This module is experimental and not yet official! + +\unprotect + +\newbox \b_page_spread_content +\newconditional\c_page_spread_busy +\newconditional\c_page_spread_once % when true only one flush (writes etc) + +\permanent\overloaded\protected\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear + {\setbox#1\hpack + {\setlayoutcomponentattribute{\v!page:\v!text}% + \vpack \layoutcomponentboxattribute to \textheight + {\offinterlineskip + \freezetextwidth + \hsize\textwidth % local variant of \sethsize + \boxmaxdepth\maxdepth + \noindent % content can be < \hsize + \page_otr_command_package_contents#2#3}}% + \dp#1\zeropoint + \ifconditional\c_page_spread_busy + \normalsettextpagecontent_spread{#1}% + \else + \normalsettextpagecontent_normal{#1}% + \fi} + +\def\normalsettextpagecontent_normal#1% + {\ifdim\wd#1=\makeupwidth\else + \setbox#1\hpack to \makeupwidth + {\hss\box#1\hss}% never change the \hss's + \fi} + +\def\normalsettextpagecontent_spread#1% + {\setbox#1\hpack to \makeupwidth + {\ifvoid\b_page_spread_content + \ifconditional\c_page_spread_once + \box#1% + \else + \global\setbox\b_page_spread_content\box#1% + \copy\b_page_spread_content + \fi + \hss % left page + \else + \hss % right page + \ifarrangingpages + % writes don't matter anyway + \orelse\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 + \box\b_page_spread_content + \fi}} + +\protected\def\page_spread_flush + {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else + % this page will be discarded later + \emptyhbox \page + \fi \fi } + +\permanent\protected\def\startspread + {\unless\ifdoublesided + \expandafter\page_spread_start_nop + \orelse\ifconditional\c_page_spread_busy + \expandafter\page_spread_start_nop + \else + \expandafter\page_spread_start_yes + \fi} + +\aliased\let\stopspread\relax + +\protected\def\page_spread_start_yes + {\bgroup + \page[\v!left]% + %\setsystemmode{spread}% + \settrue\c_page_spread_busy + \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}% + \enforced\let\stopspread\page_spread_stop_yes} + +\permanent\protected\def\page_spread_stop_yes + {\kern\zeropoint + \page + \setuplayout[\c!textwidth=\textwidth]% + \page[\v!left]% + \egroup} + +\protected\def\page_spread_start_nop + {\bgroup + \let\stopspread\page_spread_stop_nop} + +\protected\def\page_spread_stop_nop + {\egroup} + +\protect \endinput + +% texexec --arr --pdf test +% +% \setuplayout[width=middle] +% \setuppapersize[A4][A3,landscape] +% \setuppagenumbering[alternative=doublesided] +% \setuparranging[2UP] +% +% \starttext +% +% \dorecurse{3}{\input tufte } +% +% \startspread +% \dorecurse{10}{\input tufte } +% \stopspread +% +% \dorecurse{3}{\input tufte } +% +% \stoptext diff --git a/tex/context/base/mkxl/page-str.mkxl b/tex/context/base/mkxl/page-str.mkxl new file mode 100644 index 000000000..d6e01ea59 --- /dev/null +++ b/tex/context/base/mkxl/page-str.mkxl @@ -0,0 +1,128 @@ +%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 for Thomas Schmitz +%D who asked for parallel page streams. While playing with the code, I decided to +%D make it into a component that can be used to construct all kind of stream related +%D mechanisms. Because I could apply this feature in a project, there is some +%D additional code here (related to graphics). +%D +%D These macros were written while listening to and watching the DVD \quotation +%D {Rush In Rio}. +%D +%D The reimplementation (or rather experimenting with the complete rewrite) was done +%D while looping over \quotation {Wende Snijders No.9}. +%D +%D Remark: marknotes are gone, at least for a while. + +\registerctxluafile{page-str}{} + +\unprotect + +\mutable\let\currentoutputstream\empty + +\newif \ifinoutputstream % will become a conditional or mode +\newtoks \everyenableoutputstream + +\appendtoks + \page_otr_command_flush_side_floats +\to \everyenableoutputstream + +\permanent\protected\def\initializeoutputstreams + {\clf_initializestream + \enforced\glet\initializeoutputstreams\relax} + +\permanent\protected\def\enableoutputstream[#1]% could be \startoutputsubstream + {\initializeoutputstreams + \the\everyenableoutputstream + \inoutputstreamtrue + \xdef\currentoutputstream{#1}% + \clf_enablestream{#1} + \prevdepth\zeropoint} % maybe more is needed i.e. we need to get rid of leading glue + +\permanent\protected\def\disableoutputstream + {\inoutputstreamfalse + \glet\currentoutputstream\s!default + \clf_disablestream} + +\permanent\protected\def\startoutputstream[#1]% + {\begingroup + \initializeoutputstreams + \the\everyenableoutputstream + \inoutputstreamtrue + \xdef\currentoutputstream{#1}% + \clf_startstream{#1}} + +\permanent\protected\def\stopoutputstream + {\clf_stopstream + \endgroup} + +\permanent\protected\def\startoutputsubstream[#1]% just push/pop instead + {\globalpushmacro\currentoutputstream + \enableoutputstream[#1]} + +\permanent\protected\def\stopoutputsubstream + {\globalpopmacro\currentoutputstream + \enableoutputstream[\currentoutputstream]} + +\permanent \protected\def\flushoutputstream [#1]{\clf_flushstream{#1}} +\permanent \protected\def\outputstreambox [#1]{\vbox{\clf_flushstream{#1}}} +\permanent \protected\def\outputstreamcopy [#1]{\vbox{\clf_flushstreamcopy{#1}}} +\permanent \protected\def\outputstreamunvbox [#1]{\clf_flushstream{#1}} +\permanent \protected\def\outputstreamunvcopy[#1]{\clf_flushstreamcopy{#1}} +\permanent \protected\def\synchronizestreams [#1]{\clf_synchronizestream{#1}} +\permanent\tolerant\protected\def\pushoutputstream [#1]{\clf_pushstream{#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/tex/context/base/mkxl/page-txt.mklx b/tex/context/base/mkxl/page-txt.mklx new file mode 100644 index 000000000..f8c77e572 --- /dev/null +++ b/tex/context/base/mkxl/page-txt.mklx @@ -0,0 +1,950 @@ +% 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,setupfooter, setupbottom} +%D +%D The macros in this module sometimes look a bit more complicated than needed, +%D which is a direct result of the fact that their ancestors are quite old and +%D 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=] + +\permanent\tolerant\protected\def\setuplayouttext[#vertical]#spacer[#horizontal]#spacer[#settings]% + {\ifnum\lastarguments>\plustwo + \setuplayoutelement[#vertical:#horizontal][#settings]% + \else + \setuplayoutelement[#vertical][#horizontal]% + \fi} + +\appendtoks + \ifempty\currentlayoutelement\else + \page_layouts_synchronize_element\currentlayoutelement % brr, can be vertical:horizontal + \fi +\to \everysetuplayoutelement + +\def\page_layouts_reset_element_status#vertical% + {\gdefcsname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}} + +\def\page_layouts_set_element_status_normal#vertical% + {\gletcsname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal + \gletcsname\??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 \orelse + \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \orelse + \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \orelse + \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi + \gletcsname\??layouttextssynchronize#vertical\endcsname\currenttextstate} + +\permanent\protected\def\setuptop {\setuplayouttext[\v!top ]} +\permanent\protected\def\setupheader{\setuplayouttext[\v!header]} +\permanent\protected\def\setuptext {\setuplayouttext[\v!text ]} +\permanent\protected\def\setupfooter{\setuplayouttext[\v!footer]} +\permanent\protected\def\setupbottom{\setuplayouttext[\v!bottom]} + +%D We inherit some settings: + +\setuplayoutelement + [ \c!leftstyle=\layoutelementparameter\c!style, + \c!middlestyle=\layoutelementparameter\c!style, + \c!rightstyle=\layoutelementparameter\c!style, + \c!leftcolor=\layoutelementparameter\c!color, + \c!middlecolor=\layoutelementparameter\c!color, + \c!rightcolor=\layoutelementparameter\c!color, + \c!leftwidth=\layoutelementparameter\c!width, + \c!middlewidth=\layoutelementparameter\c!width, + \c!rightwidth=\layoutelementparameter\c!width] + +%D \macros +%D {noheaderandfooterlines,notopandbottomlines} +%D +%D Although not really needed, the following shortcuts sometimes come in handy. +%D +%D \showsetup{noheaderandfooterlines} +%D \showsetup{notopandbottomlines} + +\permanent\protected\def\noheaderandfooterlines + {\setuplayoutelement[\v!header][\c!state=\v!empty]% + \setuplayoutelement[\v!footer][\c!state=\v!empty]} + +\permanent\protected\def\notopandbottomlines + {\setuplayoutelement[\v!top ][\c!state=\v!empty]% + \setuplayoutelement[\v!bottom][\c!state=\v!empty]} + +%D \macros +%D {setuptoptexts,setupheadertexts,setuptexttexts,setupfootertexts,setupbottomtexts} +%D +%D The next macros take one or more arguments. The exact setup depends on the number +%D of arguments. Although not that intuitive, the current scheme evolved out of the +%D original. When margin and edge texts as well as middle texts showed up, the +%D current odd|/|even scheme surfaced. +%D +%D \showsetup{setuptoptexts} +%D \showsetup{setupheadertexts} +%D \showsetup{setuptexttexts} +%D \showsetup{setupfootertexts} +%D \showsetup{setupbottomtexts} +%D +%D Only the following have checking for pagenumber, date and mark built in, so when +%D someone uses the key|/|value interface these things have to be set explicitly as +%D part of the text. + +\permanent\protected\def\setuptoptexts {\setuptexts[\v!top ]} +\permanent\protected\def\setupheadertexts{\setuptexts[\v!header]} +\permanent\protected\def\setuptexttexts {\setuptexts[\v!text ]} +\permanent\protected\def\setupfootertexts{\setuptexts[\v!footer]} +\permanent\protected\def\setupbottomtexts{\setuptexts[\v!bottom]} + +\permanent\tolerant\protected\def\setuptexts[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% + {\ifarguments + % there is always one + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \edef\currentlayoutelement{#vertical:\v!margin}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \edef\currentlayoutelement{#vertical:\v!edge}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}% + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}% + \or + \edef\currentlayoutelement{#vertical:#horizontal}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}% + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}% + \or + \edef\currentlayoutelement{#vertical:#horizontal}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}% + \fi} + +%D Left and right texts are swapped on odd and even pages, but only when double +%D sided typesetting is enabled. + +\setvalue{\??layouttextstrut\v!yes}{\setstrut\strut} % maybe more variants + +\let\m_page_layouts_element_content\empty + +\protected\def\page_layouts_process_element_single#content% + {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx + \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname + \lastnamedcs + \else + \doifelsemarking\m_page_layouts_element_content + {\getmarking[\m_page_layouts_element_content][\v!first]}% + {#content}% + \fi} + +\protected\def\page_layouts_process_element_double#first#second% + {\doifelseoddpage + {\page_layouts_process_element_single{#first}} + {\page_layouts_process_element_single{#second}}} + +\protected\def\page_layouts_process_element_indeed#style#color#width% + {\begingroup + \uselayoutelementstyleandcolor#style#color% + \begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname + \ignorecrlf + \edef\currentlayoutelementwidth{\layoutelementparameter#width}% + \ifempty\currentlayoutelementwidth\else + \expandafter\page_layouts_process_element_limited + \fi\p_text + \endgroup} + +\def\page_layouts_process_element_limited#content% are the {}{}{} still needed? + {\limitated + left \currentlayoutelementwidth + text {#content} + sentinel {\unknown} + \relax} + +\setvalue{\??layouttextspecial\v!pagenumber}{\page_layouts_place_page_number} +\setvalue{\??layouttextspecial\v!date }{\currentdate} + +%D When specified, the texts are automatically limited in length. + +\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 the \type {status} +%D variable. This is handled by the next 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 + \xdefcsname\namedlayoutelementhash#vertical\c!n\endcsname{\the\numexpr\c_page_layouts_element_state_n+\minusone}% + \let\textlinestatus\v!stop + \fi} + +\appendtoks + \doifinset\v!header\floatspecification{\xdefcsname\namedlayoutelementhash\v!header\c!n\endcsname{1}}% + \doifinset\v!footer\floatspecification{\xdefcsname\namedlayoutelementhash\v!footer\c!n\endcsname{1}}% +\to \everybeforeflushedpagefloat + +\protected\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} + +\permanent\protected\def\doifelselayouttextline#vertical% shown or not + {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% + \ifx\currentlayoutelementstate\v!normal + \expandafter\firstoftwoarguments + \orelse\ifx\currentlayoutelementstate\v!start + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifelselayoutsomeline#vertical% present or not + {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% + \ifx\currentlayoutelementstate\v!none + \expandafter\secondoftwoarguments + \orelse\ifx\currentlayoutelementstate\v!high + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doiflayouttextlineelse\doifelselayouttextline +\aliased\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} + +% \setupheadertexts [11] +% \definetext [title] [header] [aa] +% \setupheadertexts [11] [22] +% \definetext [title] [header] [aa] [bb] +% \setupheadertexts [text] [11] [22] +% \definetext [title] [header] [text] [aa] [bb] +% \setupheadertexts [11] [22] [33] [44] +% \definetext [title] [header] [aa] [bb] [cc] [dd] +% \setupheadertexts [text] [11] [22] [33] [44] +% \definetext [title] [header] [text] [aa] [bb] [cc] [dd] + +\def\page_layouts_place_text_line_unknown#vertical#height% + {\global\settrue\resyncaftertextline + \begingroup % new + \page_layouts_reset_element_status#vertical% + \begincsname\namedlayoutelementhash{#vertical}\textlinestatus\endcsname + \begincsname\namedlayoutelementhash{#vertical:\v!text}\textlinestatus\endcsname + \begincsname\namedlayoutelementhash{#vertical:\v!margin}\textlinestatus\endcsname + \begincsname\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 is flushed. + +\permanent\protected\def\resetlayouttextlines % public + {\begincsname\??layouttextsreset\v!top \endcsname + \begincsname\??layouttextsreset\v!header\endcsname + \begincsname\??layouttextsreset\v!text \endcsname + \begincsname\??layouttextsreset\v!footer\endcsname + \begincsname\??layouttextsreset\v!bottom\endcsname + \ifconditional\resyncaftertextline + \calculateglobalvsizes + \page_backgrounds_recalculate + \global\setfalse\resyncaftertextline + \fi} + +\permanent\def\getspecificlayouttext#vertical#horizontal#what% + {\begincsname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname} + +% \settext[header][text][middle][xxx][yyy] + +\permanent\tolerant\protected\def\settextcontent[#vertical]#spacer[#horizontal]#spacer[#one]#spacer[#two]#spacer[#three]% header text middle text/text + {\ifarguments\or\or\or % 3 + \defcsname\namedlayoutelementhash{#vertical:#horizontal}\c!middletext\endcsname + {\page_layouts_process_element_double{#one}{#one}}% + \or % 4 + \defcsname\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext\endcsname + {\page_layouts_process_element_double{#two}{#two}}% + \or % 5 + \defcsname\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext\endcsname + {\page_layouts_process_element_double{#two}{#three}}% + \fi} + +\let\currentlayoutelement\relax + +%D This will be redefined, so no \type {\frozen} here! + +\permanent\tolerant\protected\def\resettextcontent[#vertical]#spacer[#horizontal]#spacer[#tag]% header text middle + {\ifarguments\or\or % 2 + \edef\currentlayoutelement{#vertical:#horizontal}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!middletext + \resetlayoutelementparameter\c!righttext + \or % 3 + \edef\currentlayoutelement{#vertical:#horizontal}% + \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}% + \fi} + +\letvalue{\??layouttextcontent\v!text:\c!middle}\c!middletext +\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 macros. These are hooked +%D into the general purpose token list registers mentioned before. + +\let\currentlayouttextline\relax + +\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 + \enforced\let\\\ignoredlinebreak + \enforced\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 + \vkern\zeropoint}% keep the \dp, beware of \vtops, never change this! + \dp\b_page_layouts_element\zeropoint + \box\b_page_layouts_element + \vkern-#height\relax} + +\let\page_layouts_place_extra_text_left \empty % historic +\let\page_layouts_place_extra_text_right\empty % historic + +\def\page_layouts_place_text_line_right + {\hpack + {\ifdim\leftedgewidth>\zeropoint + \page_layouts_left_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth + \fi + \ifdim\leftmarginwidth>\zeropoint + \page_layouts_left_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\zerocount + \fi + \ifdim\makeupwidth>\zeropoint + \page_layouts_text_body_element_l_m_r_e + \fi + \ifdim\rightmarginwidth>\zeropoint + \page_layouts_right_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\plusone + \fi + \ifdim\rightedgewidth>\zeropoint + \page_layouts_right_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth + \fi}} + +\def\page_layouts_place_text_line_left + {\hpack + {\ifdim\leftedgewidth>\zeropoint + \page_layouts_left_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth + \fi + \ifdim\leftmarginwidth>\zeropoint + \page_layouts_left_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\zerocount + \fi + \ifdim\makeupwidth>\zeropoint + \page_layouts_text_body_element_e_r_m_l + \fi + \ifdim\rightmarginwidth>\zeropoint + \page_layouts_right_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\plusone + \fi + \ifdim\rightedgewidth>\zeropoint + \page_layouts_right_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth + \fi}} + +\def\page_layouts_left_edge_element_indeed#text#style#color#width% + {\letfromlayoutelementparameter\p_text#text% + \ifempty\p_text + \kern\leftedgewidth + \else + \hbox to \leftedgewidth\bgroup + \hss + \page_layouts_process_element_indeed#style#color#width% + \egroup + \fi} + +\def\page_layouts_left_edge_element#text#style#color#width% + {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}% + \page_layouts_place_element_indeed\leftedgewidth + {\page_layouts_left_edge_element_indeed#text#style#color#width}% + \kern\leftedgedistance} + +\def\page_layouts_right_edge_element_indeed#text#style#color#width% + {\letfromlayoutelementparameter\p_text#text% + \ifempty\p_text + \kern\rightedgewidth + \else + \hbox to \rightedgewidth\bgroup + \page_layouts_process_element_indeed#style#color#width% + \hss + \egroup + \fi} + +\def\page_layouts_right_edge_element#text#style#color#width% + {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}% + \kern\rightedgedistance + \page_layouts_place_element_indeed\rightedgewidth + {\page_layouts_right_edge_element_indeed#text#style#color#width}} + +% margin needs checking! + +\def\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo% + {\letfromlayoutelementparameter\p_text#text% + \ifempty\p_text + \kern\leftmarginwidth + \else + \hbox to \leftmarginwidth\bgroup + \hss + \page_layouts_process_element_indeed#style#color#width% + \egroup + \fi + \ifcase#margintoo\or + \letfromlayoutelementparameter\p_text\c!margintext + \ifempty\p_text\else + \kern-\leftmarginwidth + \hbox to \leftmarginwidth\bgroup + \hss + \p_text % styling ? + \egroup + \fi + \fi} + +\def\page_layouts_left_margin_element#text#style#color#width#margintoo% + {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}% + \page_layouts_place_element_indeed\leftmarginwidth + {\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo}% + \kern\leftmargindistance} + +\def\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo% + {\letfromlayoutelementparameter\p_text#text% + \ifempty\p_text + \kern\rightmarginwidth + \else + \hbox to \rightmarginwidth\bgroup + \page_layouts_process_element_indeed#style#color#width% + \hss + \egroup + \fi + \ifcase#margintoo\or + \letfromlayoutelementparameter\p_text\c!margintext + \ifempty\p_text\else + \kern-\rightmarginwidth + \hbox to \rightmarginwidth\bgroup + \p_text % ? styling + \hss + \egroup + \fi + \fi} + +\def\page_layouts_right_margin_element#text#style#color#width#margintoo% + {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}% + \kern\rightmargindistance + \page_layouts_place_element_indeed\rightmarginwidth + {\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo}} + +\def\page_layouts_text_body_element_indeed_l_m_r_e + {\letfromlayoutelementparameter\p_text\c!lefttext + \ifempty\p_text + \ifempty\page_layouts_place_extra_text_left\else + \hbox to \makeupwidth\bgroup + \page_layouts_place_extra_text_left + \hss + \egroup + \kern-\makeupwidth + \fi + \else + \hbox to \makeupwidth\bgroup + \page_layouts_place_extra_text_left + \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth + \hss + \egroup + \kern-\makeupwidth + \fi + \letfromlayoutelementparameter\p_text\c!middletext + \ifempty\p_text\else + \hbox to \makeupwidth\bgroup + \hss + \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth + \hss + \egroup + \kern-\makeupwidth + \fi + \letfromlayoutelementparameter\p_text\c!righttext + \ifempty\p_text + \kern\makeupwidth + \else + \hbox to \makeupwidth\bgroup + \hss + \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth + \egroup + \fi} + +\def\page_layouts_text_body_element_indeed_e_r_m_l + {\letfromlayoutelementparameter\p_text\c!righttext + \ifempty\p_text\else + \hbox to \makeupwidth\bgroup + \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth + \hss + \egroup + \kern-\makeupwidth + \fi + \letfromlayoutelementparameter\p_text\c!middletext + \ifempty\p_text\else + \hbox to \makeupwidth\bgroup + \hss + \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth + \hss + \egroup + \kern-\makeupwidth + \fi + \letfromlayoutelementparameter\p_text\c!lefttext + \ifempty\p_text + \ifempty\page_layouts_place_extra_text_right + \kern\makeupwidth + \else + \hbox to \makeupwidth\bgroup + \hss + \page_layouts_place_extra_text_right + \egroup + \fi + \else + \hbox to \makeupwidth\bgroup + \hss + \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth + \page_layouts_place_extra_text_right + \egroup + \fi} + +\def\page_layouts_text_body_element_l_m_r_e + {\edef\currentlayoutelement{\currentlayouttextline:\v!text}% + \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_l_m_r_e} + +\def\page_layouts_text_body_element_e_r_m_l + {\edef\currentlayoutelement{\currentlayouttextline:\v!text}% + \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_e_r_m_l} + +\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 purpose, one can add a rule +%D in the following way. This method makes the rules disappear in case of an empty +%D text 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 \type {unknown}. This +%D one is used to take care of symbolic texts handlers. +%D +%D \showsetup{definetext} +%D +%D The next example demonstrates how we can use this mechanism to provide page +%D (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 + +\permanent\tolerant\protected\def\definetext[#tag]#spacer[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% + {\ifnum\lastarguments<\plusfour + \defcsname\namedlayoutelementhash {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal]\relax}% 1, 2, 3 + \orelse\ifarguments\or\or\or\or + \defcsname\namedlayoutelementhash {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a]\relax}% 4 + \or + \defcsname\namedlayoutelementhash{#vertical:#horizontal}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b]\relax}% 5 + \or + \defcsname\namedlayoutelementhash {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b][#c]\relax}% 6 + \or + \defcsname\namedlayoutelementhash{#vertical:#horizontal}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b][#c][#d]\relax}% 7 + \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 main text, the top and +%D 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: +%D +%D We reset a previous location but only when it has a pagenumber associated. This +%D is a rather messy test but better than the MkII way where we use states and keep +%D 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 \protected 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 \empty + \let\page_layouts_place_extra_text_right\empty + \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]} + +\protected\def\strc_pagenumbers_set_location + {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}% + \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location + % unchanged + \else + \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location + \page_layouts_reset_page_number_location + \ifempty\p_strc_pagenumbers_location + % set otherwise + \orelse\ifx\p_strc_pagenumbers_location\v!none + % set otherwise + \else + \page_layouts_identify_page_number_location + \page_layouts_set_page_number_location + \fi + \fi} + +\def\page_layouts_place_page_number_left % historic + {\begingroup + \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}% + \ifzeropt\wd\scratchbox\else + \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}% + \ifempty\p_strc_pagenumbers_width + \box\scratchbox\tfskip + \else + \hpack 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}% + \ifempty\p_strc_pagenumbers_width + \tfskip\box\scratchbox + \else + \hpack to \p_strc_pagenumbers_width{\hss\box\scratchbox}% + \fi + \fi + \endgroup} + +\strc_pagenumbers_set_location % initializes + +\newbox\b_page_layouts_element + +\def\page_layouts_insert_elements + {\ifcase\pageornamentstate + \page_layouts_place_elements_indeed % we could have a special flag for always ignored + \fi} + +\def\page_layouts_place_elements_indeed + {\setbox\b_page_layouts_element\vpack + {\dontcomplain + \calculatereducedvsizes + \swapmargins + \offinterlineskip + \vkern\dimexpr-\topheight-\topdistance\relax + \the\toptextcontent + \vkern\dimexpr\topheight+\topdistance\relax + \the\headertextcontent + \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax + \anch_positions_place_anchors + \vkern\dimexpr-\textdistance-\textheight\relax + \the\texttextcontent + \vkern\textheight + \the\everyendoftextbody + \vkern\footerdistance + \the\footertextcontent + \vkern\dimexpr\footerheight+\bottomdistance\relax + \the\bottomtextcontent + \vkern\bottomheight + \vfilll}% + \smashbox\b_page_layouts_element + \box\b_page_layouts_element} + +% \ifdefined\page_prepare_backgrounds\else +% \let\page_prepare_backgrounds\gobbleoneargument +% \fi + +% only for very special controlled cases or experiments: + +\let\page_scale_text_box\gobbleoneargument + +\def\page_insert_body#1#2% + {\setbox\b_page_layouts_element\vpack + {\offinterlineskip + \calculatereducedvsizes + \calculatehsizes + \swapmargins + \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax + \dontleavehmode + %\page_prepare_backgrounds{#2}% + \hpack 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_apply_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 + \page_scale_text_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 (tracing) information. +%D +%D This will be stored as normal and overloaded in page-lyr and later in page-spr we +%D overload the the stored version .. eventually i will clear up the experimental +%D mess. + +\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded + {\setbox#1\hpack to \makeupwidth + {\hss % so don't change this + \setlayoutcomponentattribute{\v!page:\v!text}% + \vpack \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}% this will vbox + \hss}% + \dp#1\zeropoint} + +\protect \endinput diff --git a/tex/context/base/mkxl/page-var.mkxl b/tex/context/base/mkxl/page-var.mkxl new file mode 100644 index 000000000..1c7fd5b25 --- /dev/null +++ b/tex/context/base/mkxl/page-var.mkxl @@ -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/tex/context/base/mkxl/phys-dim.mkxl b/tex/context/base/mkxl/phys-dim.mkxl new file mode 100644 index 000000000..3102650bf --- /dev/null +++ b/tex/context/base/mkxl/phys-dim.mkxl @@ -0,0 +1,808 @@ +%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, space delimited mode is +%D now resticted! +%D +%D Depending on the digit mode the command \type {\digits} normalizes number +%D 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 purposes. +%D 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 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 well as different +%D formats. We strongly suggest you to use the grouped call. +%D +%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 +%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) + +\permanent\protected\def\setdigitmethod#1{\c_phys_digits_method #1\relax} +\permanent\protected\def\setdigitsign #1{\c_phys_digits_sign #1\relax} +\permanent\protected\def\setdigitorder #1{\c_phys_digits_order #1\relax} + +\aliased\let\setdigitmode\setdigitmethod % compatibility + +\def\phys_digits_normalized % we could calculate once and remember + {\ifcase\c_phys_digits_sign + \expandafter\secondoftwoarguments + \orelse\ifmmode + \expandafter\phys_digits_normalized_math + \else + \expandafter\phys_digits_normalized_text + \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] + +\permanent\protected\def\digitstextbinop#1% assumes preceding + {\ifmmode#1\else\fourperemspace\nobreak#1\fourperemspace\fi} + +%frozen\def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi} +\frozen\def\digitstimessymbol{\digitstextbinop\times} + +\frozen\protected\def\digitszeropadding {\hphantom{0}} +%frozen\protected\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}} +%frozen\protected\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}} +\frozen\protected\def\digitsnegative {\phys_digits_normalized{0}{\mathematics{\negative}}} +\frozen\protected\def\digitspositive {\phys_digits_normalized{0}{\mathematics{\positive}}} +%frozen\protected\def\digitsminus {\phys_digits_normalized{0}{\mathematics{-}}} +%frozen\protected\def\digitsplus {\phys_digits_normalized{0}{\mathematics{+}}} +\frozen\protected\def\digitsminus {\phys_digits_normalized{0}{\mathminus}} +\frozen\protected\def\digitsplus {\phys_digits_normalized{0}{\mathplus}} +\frozen\protected\def\digitsplusminus {\phys_digits_normalized{0}{\mathplusminus}} +\frozen\protected\def\digitsspace {\hphantom{0}} + \protected\def\digitsseparatorspace{\hphantom{.}} +\frozen\protected\def\digitssignspace {\hphantom{\digitsminus}} +\frozen\protected\def\digitshighspace {\hphantom{\digitspositive}} +\frozen\protected\def\digitspower #1{\digitstimessymbol10\phys_digits_raised{#1}} +\frozen\protected\def\digitspowerplus #1{\digitstimessymbol10\phys_digits_raised{\digitsplus#1}} +\frozen\protected\def\digitspowerminus #1{\digitstimessymbol10\phys_digits_raised{\digitsminus#1}} +\frozen\protected\def\digitsdigit #1{#1} + +\frozen\protected\def\normaldigitscommasymbol {,} +\frozen\protected\def\normaldigitsperiodsymbol{.} + +\aliased\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 + +\frozen\protected\def\digitscommasymbol {\csname\??digitscomma \number\c_phys_digits_method\endcsname} +\frozen\protected\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname} +\frozen\protected\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname} + +\frozen\protected\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing +\frozen\protected\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing +\frozen\protected\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing +\frozen\protected\def\digitsintermediateperiod{\digitscommasymbol } % more for tracing + +%D The user macro: + +\protected\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} + +\permanent\protected\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 now +%D but when we moved on to \LUATEX\ a variant was prototyped that permits a less +%D texie coding. I finally picked up that thread and cleaned up the code a bit so +%D users can now play with it. (The main reason was that I wanted to test +%D 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 extent we need +%D 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] + +\aliased\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 + +\frozen\protected\def\unitssmallspace {\thinspace} +\frozen\protected\def\unitsmediumspace{\medspace} +\frozen\protected\def\unitsbigspace {\thickspace} +\frozen\protected\def\unitsbackspace {\negthinspace} + +\permanent\protected\def\installunitsseparator#1#2% + {\setvalue{\??unitseparator#1}{#2}} + +\protected\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 {} + +\permanent\protected\def\installunitsspace#1#2% + {\setvalue{\??unitspace#1}{#2}} + +\protected\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 + \nocharacteralign +\to \everyunits + +\appendtoks + \frozen\instance\setuevalue\currentunit{\phys_units_direct{\currentunit}} +\to \everydefineunit + +\protected\def\phys_units_direct#1% + {\begingroup + \the\everyunits + \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}% + \enforced\edef\unitlanguage{\unitparameter\s!language}% + \enforced\let\prefixlanguage\unitlanguage + \enforced\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} + +\protected\def\phys_units_direct_text_in_math#1% + {\mathtext{% + \c_phys_units_mode\plustwo + \phys_units_indeed{#1}% + \phys_units_finish + }% + \endgroup} + +\protected\def\phys_units_direct_math#1% + {\c_phys_units_mode\plusone + \rm\tf % slow + \mathtf + \phys_units_indeed{#1}% + \phys_units_finish + \endgroup} + +\protected\def\phys_units_direct_text#1% + {\phys_units_indeed{#1}% + \phys_units_finish + \endgroup} + +\protected\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} + +\protected\def\phys_units_direct_nested#1#2% + {\phys_units_indeed{#2}} + +\appendtoks + \let\phys_units_direct\phys_units_direct_nested +\to \everyunits + +\protected\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}}} + +\permanent\protected\def\digitstextbinnop#1% + {\ifmmode#1\else#1\fourperemspace\fi} + +\permanent\protected\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix +\permanent\protected\def\unitsPU #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree} % unit +\permanent\protected\def\unitsPS #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix +\permanent\protected\def\unitsUS #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix +\permanent\protected\def\unitsP #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour} % prefix +\permanent\protected\def\unitsU #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree} % unit +\permanent\protected\def\unitsS #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone} % suffix +\permanent\protected\def\unitsO #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo} % operator +%permanent\protected\def\unitsN #1{\phys_units_start#1\c_phys_units_state\plusfive} % number +\permanent\protected\def\unitsC #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix} % connected +\permanent\protected\def\unitsQ #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount} +\permanent\protected\def\unitsR #1#2{% todo: tagging + \ifmmode + #2% + \orelse\ifnum#1=\plusone + \digitstextbinop{#2}% before and after + \else + \digitstextbinnop{#2}% after + \fi + \c_phys_units_state\zerocount + \setfalse\c_phys_units_dospace + \setfalse\c_phys_units_number + \setfalse\c_phys_units_quantity} +\permanent\protected\def\unitsRPM {\unitsR\plusone {±}} % todo: symbols +\permanent\protected\def\unitsRTO {\unitsR\plusone {–}} % todo: symbols +\permanent\protected\def\unitsRabout {\unitsR\zerocount{±}} % todo: symbols +\permanent\protected\def\unitsPopen {(} +\permanent\protected\def\unitsPclose {)} +\permanent\protected\def\unitrange #1{} + +% 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. + +\permanent\protected\def\phys_units_text_prime {\textacute} +\permanent\protected\def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute} +\permanent\protected\def\phys_units_text_celsius {°C} +\permanent\protected\def\phys_units_text_fahrenheit {°F} + +\permanent\protected\def\checkedtextprime + {\iffontchar\font"2032\relax\iffontchar\font"2033\relax + ′\else\phys_units_text_prime\fi\else\phys_units_text_prime + \fi} + +\permanent\protected\def\checkedtextdoubleprime + {\iffontchar\font"2033\relax\iffontchar\font"2032\relax + ″\else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime + \fi} + +% \permanent\protected\def\checkedtextcelsius +% {\ifmmode +% \phys_units_text_celsius +% \orelse\iffontchar\font"2103\relax +% ℃\else\phys_units_text_celsius +% \fi} +% +% \permanent\protected\def\checkedtextfahrenheit +% {\ifmmode +% \phys_units_text_fahrenheit +% \orelse\iffontchar\font"2109\relax +% ℉\else\phys_units_text_fahrenheit +% \fi} +% +% % but, as users don't like this ... + +\aliased\let\checkedtextcelsius \phys_units_text_celsius +\aliased\let\checkedtextfahrenheit\phys_units_text_fahrenheit + +\setelementnature[unit] [mixed] +\setelementnature[quantity][mixed] + +\let\phys_units_finish\relax + +\permanent\protected\def\unitsNstartindeed + {\ifmmode \else + \settrue\c_phys_units_quantity + \dostarttagged\t!quantity\empty + \settrue\c_phys_units_number + \dostarttagged\t!number\empty + \fi} + +\permanent\protected\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 + +% \aliased\let\unitsNstartindeed\unitsNstart + +\permanent\protected\def\unitsNstart + {\doifelsenextchar\unitsNstop\gobbleoneargument\unitsNstartindeed} + +% End of hack. + +\permanent\protected\def\unitsNspace + {\space} + +\permanent\protected\def\unitsN#1% + {\unitsNstart#1\unitsNstop} + +\def\phys_units_start + {\ifmmode + \dostarttagged\t!maction\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} + +\permanent\def\unitsraise + {\ifcase\c_phys_units_mode + \expandafter\unitshigh + \or + \expandafter\normalsuperscript + \or + \expandafter\unitshigh + \or + \expandafter\normalsuperscript + \fi} + +\permanent\def\unitslower + {\ifcase\c_phys_units_mode + \expandafter\unitslow + \or + \expandafter\normalsubscript + \or + \expandafter\unitslow + \or + \expandafter\normalsubscript + \fi} + +\protected\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} + +\permanent\protected\def\unitsTIMES + {\ifnum\c_phys_units_state=\plusone % suffix + \else + \unitssmallspace + \fi + \cdot} % or \times + +\permanent\protected\def\unitsOUTOF + {\ifnum\c_phys_units_state=\plusone % suffix + \else + \unitssmallspace + \fi + :} + +\permanent\protected\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}, \type +%D {suffix}, \type {symbol},\type {packaged}. You also need to define labels: +%D +%D \starttyping +%D \setupunittext +%D [point=pt, +%D basepoint=bp, +%D scaledpoint=sp, +%D didot=dd, +%D cicero=cc] +%D \stoptyping + +\permanent\tolerant\protected\def\registerunit[#1]#*[#2]% todo: public implementer + {\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/tex/context/base/mkxl/publ-inc.mkxl b/tex/context/base/mkxl/publ-inc.mkxl new file mode 100644 index 000000000..8e6cd2bdf --- /dev/null +++ b/tex/context/base/mkxl/publ-inc.mkxl @@ -0,0 +1,63 @@ +%D \module +%D [ file=publ-inc, +%D version=2018.06.23, +%D title=\CONTEXT\ Publication Macros, +%D subtitle=XML inclusion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Publication Macros / XML inclusion} + +\registerctxluafile{publ-inc}{} + +%D A teaser for Alan. + +\unprotect + +\definesymbol[btxattachment][{\infofont\darkred btx}] +\definesymbol[btxcomment] [{\infofont\darkblue btx}] + +\protected\def\btx_add_blob#1#2% + {\relax + \clf_btxentrytobuffer{\currentbtxdataset}{\currentbtxtag}{temp-btx-export}% + #2% + [\c!symbol=#1,% + \c!space=\v!yes, + \c!buffer=temp-btx-export,% + \c!name={\currentbtxtag.bib}]% + \relax} + +\permanent\protected\def\btxattach + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \btx_add_blob{btxattachment}\attachment + \dostoptagged + \fi \fi \fi} + +\permanent\protected\def\btxcomment + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \btx_add_blob{btxcomment}\comment + \dostoptagged + \fi \fi \fi} + +%D This kind of feature creep is not yet configurable, nor documented. + +\permanent\protected\def\btxaddsource + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \llap{% + \btx_add_blob{btxattachment}\attachment + \quad + \btx_add_blob{btxcomment}\comment + \hskip\leftmargindistance + }% + \dostoptagged + \fi \fi \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/publ-ini.mkxl b/tex/context/base/mkxl/publ-ini.mkxl new file mode 100644 index 000000000..6b520074a --- /dev/null +++ b/tex/context/base/mkxl/publ-ini.mkxl @@ -0,0 +1,2027 @@ +%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: some clf_ can be public implementers instead + +% TODO: s! vs v! for default and neutral key/values +% todo: too many refs in list + +% TODO A.-B. Foo (dash as connector, see JMH) + +% 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}{} +\registerctxluafile{publ-ini}{} +\registerctxluafile{publ-sor}{} +\registerctxluafile{publ-aut}{} +\registerctxluafile{publ-usr}{} +\registerctxluafile{publ-oth}{} % this could become an option +\registerctxluafile{publ-fnd}{} % new method (for the moment only local) +\registerctxluafile{publ-jrn}{} +\registerctxluafile{publ-reg}{} + +\unprotect + +\startcontextdefinitioncode + +%D These are currently not interfaced. + +\definesystemconstant {btx} + +\definesystemconstant {btxset} +\definesystemconstant {btxref} +\definesystemconstant {btxint} +\definesystemconstant {btxltx} +\definesystemconstant {btxrtx} +\definesystemconstant {btxatx} +\definesystemconstant {btxbtx} +\definesystemconstant {btxspc} +\definesystemconstant {btxlst} +\definesystemconstant {btxcom} + +\defineinterfacevariable {btxcite} {btxcite} +\defineinterfacevariable {btxlist} {btxlist} +\defineinterfacevariable {btxrendering} {btxrendering} + +\definelabelclass[btxlabel][2] + +\clf_definelabels{btxlabel}{btx}\s!false\relax + +% 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. + +\mutable\let\currentbtxspecification \empty +\mutable\let\currentbtxspecificationfallback\empty + +\installmacrostack\currentbtxspecification +\installmacrostack\currentbtxspecificationfallback + +\permanent\protected\def\startbtxrenderingdefinitions[#1]% + {\unprotect + \push_macro_currentbtxspecification + \edef\currentbtxspecification{#1}} + +\permanent\protected\def\stopbtxrenderingdefinitions + {\pop_macro_currentbtxspecification + \protect} + +\permanent\protected\def\loadfoundpublicationfile#1#2% name foundname / not a user command + {\input{#2}} + +\permanent\protected\def\loadbtxdefinitionfile [#1]{\clf_btxloaddefinitionfile {#1}} % can be public implementer +\permanent\protected\def\loadbtxreplacementfile[#1]{\clf_btxloadreplacementfile{#1}} % can be public implementer + +\protected\def\publ_specification_push#1% + {\push_macro_currentbtxspecification + \push_macro_currentbtxspecificationfallback + \edef\currentbtxspecification{#1}% + \edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}% + \ifx\currentbtxspecificationfallback\currentbtxspecification + \let\currentbtxspecificationfallback\empty + \fi + \clf_btxsetspecification{\currentbtxspecification}} + +\protected\def\publ_specification_pop + {\pop_macro_currentbtxspecificationfallback + \pop_macro_currentbtxspecification + \clf_btxsetspecification{\currentbtxspecification}} + +\protected\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]% + \ifempty\currentbtxspecification + % 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 + +\protected\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]}} + +% \protected\def\btxcheckdefine#1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain{define}{#1}{#2}}} +% \protected\def\btxchecksetup #1#2{\doifelsecommandhandler\??btx{#1}\donothing{\btx_check_chain {setup}{#1}{#2}}} + +\permanent\protected\def\btxcheckdefine#1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain{define}{#1}}} % {#2} +\permanent\protected\def\btxchecksetup #1{\doifelsecommandhandler\??btx{#1}\gobbleoneargument{\btx_check_chain {setup}{#1}}} % {#2} + +% for the moment experimental: + +\permanent\protected\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}% + \orelse\ifnum\btxsetupmode=\doingrootsetupnamed + \doifelsecommandhandler\??btx\currentbtx + {\publ_specification_set{\btxparameter\c!specification}}% + {}% maybe a warning + \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 + +\permanent\protected\def\startusingbtxspecification[#1]% + {\publ_specification_push{#1}} + +\permanent\protected\def\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 + +\permanent\protected\def\setbtxparameterset#1#2% + {\edef\currentbtx + {\ifcsname\??btx\currentbtxspecification:#1:#2:\s!parent\endcsname + \currentbtxspecification:% + \orelse\ifempty\currentbtxspecificationfallback + \orelse\ifcsname\??btx\currentbtxspecificationfallback:#1:#2:\s!parent\endcsname + \currentbtxspecificationfallback:% + \fi#1:#2}} + +\permanent\protected\def\setbtxparametersetroot#1% + {\edef\currentbtx + {\ifcsname\??btx\currentbtxspecification:#1:\s!parent\endcsname + \currentbtxspecification:#1% + \orelse\ifempty\currentbtxspecificationfallback + \orelse\ifcsname\??btx\currentbtxspecificationfallback:#1:\s!parent\endcsname + \currentbtxspecificationfallback:#1% + \fi}} + +\permanent\protected\def\setbtxrendering + {\edef\currentbtxrendering + {\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname + \currentbtxspecification + \orelse\ifempty\currentbtxspecificationfallback + \orelse\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname + \currentbtxspecificationfallback + \fi}} + +\permanent\protected\def\setbtxlist % maybe simplify this one, always list=rendering? + {\edef\currentbtxlist + {\ifcsname\??btx\currentbtxrendering:\s!parent\endcsname + \currentbtxrendering + \orelse\ifcsname\??btx\currentbtxspecification:\s!parent\endcsname + \currentbtxspecification + \orelse\ifempty\currentbtxspecificationfallback + \orelse\ifcsname\??btx\currentbtxspecificationfallback:\s!parent\endcsname + \currentbtxspecificationfallback + \fi}% + \edef\currentlist{\s!btx:\currentbtxlist}} + +\tolerant\permanent\protected\def\usebtxdataset[#1]#*[#2]#*[#3]% + {\begingroup + \getdummyparameters[\c!specification=\currentbtxspecification,#3]% + \ifparameter#2\or + \clf_btxusedataset + specification {\dummyparameter\c!specification}% + dataset {#1}% + filename {#2}% + \relax + \orelse\ifparameter#1\or + \clf_btxusedataset + specification {\dummyparameter\c!specification}% + dataset {\v!default}% + filename {#1}% + \relax + \fi + \endgroup} + +\definebtxdataset + [\v!default] +% [\c!language=] % nothing set so use current + +% \usebtxdataset +% [default] +% [mybibs.bib] + +%D These can be overloaded in the traditional module so we go \type {\frozen} +%D instead of \type {\permanent}. + +\frozen\let\stoppublication\relax + +\frozen\tolerant\protected\def\startpublication[#1]#*[#2]% + {\begingroup + \catcode\commentasciicode\othercatcode + \ifparameters + \expandafter\publ_set_publication_default + \or + \expandafter\publ_set_publication_checked + \or + \expandafter\publ_set_publication_indeed + \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 + +\permanent\protected\def\btxcommand#1% + {\ifcsname\??btxcommand#1\endcsname + \expandafter\publ_command_yes + \else + \expandafter\publ_command_nop + \fi{#1}} + +\newtoks\t_btx_cmd +\newbox \b_btx_cmd + +\t_btx_cmd{\global\setbox\b_btx_cmd\hpack{\clf_btxcmdstring}} + +\aliased\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}% + \gletcsname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname + \orelse\ifcsname\utfupper{#1}\endcsname + \showmessage\m!publications{10}{#1}{\utfupper{#1}}% + \gletcsname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname + \else + \showmessage\m!publications{11}{#1}% + \setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}% + \fi + \publ_command_yes{#1}} + +\permanent\protected\def\definebtxcommand#1% {body} #1..#n{body} + {\setuvalue{\??btxcommand\csstring#1}}% + +% access + +\let\currentbtxtag \empty +\let\currentbtxdataset\v!default + +\permanent\protected\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 + +% todo we can pick up the current's at the lua end (implementers) + +%permanent\def\btxfield #1{\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}} +%permanent\def\btxdetail #1{\clf_btxdetail {\currentbtxdataset}{\currentbtxtag}{#1}} +%permanent\def\btxflush #1{\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}} +%permanent\def\btxdirect #1{\clf_btxdirect {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxfieldname #1{\clf_btxfieldname {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxfieldtype #1{\clf_btxfieldtype {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxfoundname #1{\clf_btxfoundname {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxfoundtype #1{\clf_btxfoundtype {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxauthorfield#1{\clf_btxauthorfield \currentbtxauthorindex{#1}} +\permanent\def\btxdoifelse #1{\clf_btxdoifelse {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxdoif #1{\clf_btxdoif {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\def\btxdoifnot #1{\clf_btxdoifnot {\currentbtxdataset}{\currentbtxtag}{#1}} + +\aliased\let\btxsetup\fastsetup + +\permanent\def\btxfield #1{\dostarttagged\t!pubfld{#1}\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\permanent\def\btxdetail #1{\dostarttagged\t!pubfld{#1}\clf_btxdetail{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\permanent\def\btxflush #1{\dostarttagged\t!pubfld{#1}\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\permanent\def\btxdirect #1{\dostarttagged\t!pubfld{#1}\clf_btxdirect{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +%permanent\def\btxauthorfield#1{\dostarttagged\t!pubfld{#1}\clf_btxauthorfield \currentbtxauthorindex{#1}\dostoptagged} + +%D How complex will we go? Can we assume that e.g. an apa style will not be mixed +%D with another one? I think this assumption is okay. For manuals we might want to +%D mix but we can work around it. + +%D Rendering. + +\permanent\protected\def\btxspace {\removeunwantedspaces\space} +\permanent\protected\def\btxnobreakspace {\removeunwantedspaces\nobreakspace} % these two are +\permanent\protected\def\btxnbsp {\removeunwantedspaces\nbsp} % the same anyway +\permanent\protected\def\btxperiod {\removeunwantedspaces.\space} +\permanent\protected\def\btxcomma {\removeunwantedspaces,\space} +\permanent\protected\def\btxcommabreak {\removeunwantedspaces,\hskip\zeropoint plus .5\emwidth\relax} +\permanent\protected\def\btxcolon {\removeunwantedspaces:\space} +\permanent\protected\def\btxsemicolon {\removeunwantedspaces;\space} +\permanent\protected\def\btxlparent {\removeunwantedspaces\space(} % obsolete +\permanent\protected\def\btxrparent {\removeunwantedspaces)\space} % obsolete +\permanent\protected\def\btxleftparenthesis {\removeunwantedspaces\space(} +\permanent\protected\def\btxrightparenthesis {\removeunwantedspaces)\space} +\permanent\protected\def\btxrightparenthesisperiod{\removeunwantedspaces).\space} +\permanent\protected\def\btxrightparenthesiscomma {\removeunwantedspaces),\space} +\permanent\protected\def\btxleftbracket {\removeunwantedspaces\space[} +\permanent\protected\def\btxrightbracket {\removeunwantedspaces]\space} +\permanent\protected\def\btxrightbracketperiod {\removeunwantedspaces].\space} +\permanent\protected\def\btxrightbracketcomma {\removeunwantedspaces],\space} + +%D Variables: + +\mutable\let\currentbtxbacklink \empty \permanent\protected\def\btxsetbacklink {\def\currentbtxbacklink} +\mutable\let\currentbtxcategory \empty \permanent\protected\def\btxsetcategory {\def\currentbtxcategory} +\mutable\let\currentbtxcombis \empty \permanent\protected\def\btxsetcombis {\def\currentbtxcombis} +\mutable\let\currentbtxdataset \empty \permanent\protected\def\btxsetdataset {\def\currentbtxdataset} +\mutable\let\currentbtxfirst \empty \permanent\protected\def\btxsetfirst {\def\currentbtxfirst} +\mutable\let\currentbtxsecond \empty \permanent\protected\def\btxsetsecond {\def\currentbtxsecond} +\mutable\let\currentbtxsuffix \empty \permanent\protected\def\btxsetsuffix {\def\currentbtxsuffix} +\mutable\let\currentbtxinternal \empty \permanent\protected\def\btxsetinternal {\def\currentbtxinternal} +\mutable\let\currentbtxlefttext \empty \permanent\protected\def\btxsetlefttext {\def\currentbtxlefttext} +\mutable\let\currentbtxrighttext \empty \permanent\protected\def\btxsetrighttext {\def\currentbtxrighttext} +\mutable\let\currentbtxbefore \empty \permanent\protected\def\btxsetbefore {\def\currentbtxbefore} +\mutable\let\currentbtxafter \empty \permanent\protected\def\btxsetafter {\def\currentbtxafter} +\mutable\let\currentbtxlanguage \empty \permanent\protected\def\btxsetlanguage {\def\currentbtxlanguage} +\mutable\let\currentbtxtag \empty \permanent\protected\def\btxsettag {\def\currentbtxtag} +\mutable\let\currentbtxnumber \empty \permanent\protected\def\btxsetnumber {\def\currentbtxnumber} +\mutable\let\currentbtxfirstinternal\empty \permanent\protected\def\btxsetfirstinternal{\def\currentbtxfirstinternal} +\mutable\let\currentbtxlastinternal \empty \permanent\protected\def\btxsetlastinternal {\def\currentbtxlastinternal} + +\mutable\let\currentbtxauthorvariant\v!normal \permanent\protected\def\btxsetauthorvariant{\def\currentbtxauthorvariant} +\mutable\let\currentbtxfirstnames \empty \permanent\protected\def\btxsetfirstnames {\let\currentbtxfirstnames\currentbtxfirstnames_indeed} +\mutable\let\currentbtxinitials \empty \permanent\protected\def\btxsetinitials {\let\currentbtxinitials \currentbtxinitials_indeed } +\mutable\let\currentbtxjuniors \empty \permanent\protected\def\btxsetjuniors {\let\currentbtxjuniors \currentbtxjuniors_indeed } +\mutable\let\currentbtxsurnames \empty \permanent\protected\def\btxsetsurnames {\let\currentbtxsurnames \currentbtxsurnames_indeed } +\mutable\let\currentbtxvons \empty \permanent\protected\def\btxsetvons {\let\currentbtxvons \currentbtxvons_indeed } + +\newconstant\currentbtxoverflow \permanent\protected\def\btxsetoverflow #1{\currentbtxoverflow #1\relax} +\newconstant\currentbtxconcat \permanent\protected\def\btxsetconcat #1{\currentbtxconcat #1\relax} +\newconstant\currentbtxcount \permanent\protected\def\btxsetcount #1{\currentbtxcount #1\relax} +\newconstant\currentbtxauthorindex %permanent\protected\def\btxsetauthorindex#1{\currentbtxauthorindex#1\relax} % passed directly +\newconstant\currentbtxauthorcount %permanent\protected\def\btxsetauthorcount#1{\currentbtxauthorcount#1\relax} % passed directly +\newconstant\currentbtxauthorstate \permanent\protected\def\btxsetauthorstate#1{\currentbtxauthorstate#1\relax} + +\protected\def\currentbtxfirstnames_indeed{\clf_btxcurrentfirstnames\numexpr\currentbtxauthorindex\relax} +\protected\def\currentbtxinitials_indeed {\clf_btxcurrentinitials \numexpr\currentbtxauthorindex\relax} +\protected\def\currentbtxjuniors_indeed {\clf_btxcurrentjuniors \numexpr\currentbtxauthorindex\relax} +\protected\def\currentbtxsurnames_indeed {\clf_btxcurrentsurnames \numexpr\currentbtxauthorindex\relax} +\protected\def\currentbtxvons_indeed {\clf_btxcurrentvons \numexpr\currentbtxauthorindex\relax} + +\mutable\let\currentbtxfirstpage \empty \permanent\protected\def\btxsetfirstpage#1{\def\currentbtxfirstpage{\btx_page_number{#1}}} +\mutable\let\currentbtxlastpage \empty \permanent\protected\def\btxsetlastpage #1{\def\currentbtxlastpage {\btx_page_number{#1}}} + +\mutable\let\currentbtxfield \empty +\mutable\let\currentbtxfielddoi \empty +\mutable\let\currentbtxfieldmonth \empty +\mutable\let\currentbtxfieldyear \empty +\mutable\let\currentbtxfieldurl \empty +\mutable\let\currentbtxcriterium \empty +\mutable\let\currentbtxlist \empty +\mutable\let\currentbtxlistentry \empty +\mutable\let\currentbtxlistindex \empty +\mutable\let\currentbtxreference \empty +\mutable\let\currentbtxrenderingtitle \empty +\mutable\let\currentbtxcitetag \empty + +\mutable\def\currentbtxauthorvariant{normal} + +\protected\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\currentbtxlanguage \empty + \let\currentbtxsuffix \empty + %\let\currentbtxdataset \empty % will always be set + %\let\currentbtxtag \empty % will always be set + \let\currentbtxnumber \empty} + +\protected\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 \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} + +\protected\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} + +\protected\def\btx_reset_numbering % probably not needed + {\let \currentbtxfirst \empty + \let \currentbtxsecond\empty + \let \currentbtxsuffix\empty + \setconstant\currentbtxconcat\zerocount} + +%D Pages: + +\protected\def\btx_page_number#1% + {\def\currentlistindex{#1}% + \structurelistpagenumber} + +%D Language: + +\mutable\def\mainbtxlanguage{\currentmainlanguage} + +\protected\def\btx_check_language + {\let\mainbtxlanguage\currentlanguage + \ifempty\currentbtxlanguage + \let\currentbtxlanguage\currentlanguage + \else + \btx_check_language_indeed + \fi} + +\protected\def\btx_check_language_indeed + {\edef\currentbtxlanguage{\reallanguagetag\currentbtxlanguage}% + \ifempty\currentbtxlanguage + \let\currentbtxlanguage\currentlanguage + \orelse\ifx\currentbtxlanguage\currentlanguage\else + \setcurrentlanguage\currentmainlanguage\currentbtxlanguage + \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. + +\permanent\protected\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!interaction=\v!none, + %\c!alternative=\v!paragraph, + %\c!width=\v!auto, + %\c!distance=\emwidth, + \c!before=\blank, + \c!after=\blank] + +\permanent\tolerant\protected\def\setupbtxlist[#1]#*[#2]% + {\ifarguments\or + \setuplist[\s!btx][#1]% + \or + \setuplist[\s!btx:#1][#2]% + \fi} + +\appendtoks + \ifempty\currentbtxrenderingparent + \definelist + [\s!btx:\currentbtxrendering]% + [\s!btx]% + \orelse\ifx\currentbtxrenderingparent\s!btx + \definelist + [\s!btx:\currentbtxrendering]% + [\s!btx]% + \else + \definelist + [\s!btx:\currentbtxrendering]% + [\s!btx:\currentbtxrenderingparent]% + \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 + +\protected\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} + +\permanent\protected\def\btxpagesetup#1% there will be no left|right|command|style at this inner level + {\begingroup + \publ_fast_setup\plusfive\s!list\s!page + \endgroup + \btx_reset_page} % probably not needed + +\permanent\protected\def\btxnumberingsetup#1% + {\begingroup + \dostarttagged\t!listtag\empty + \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering % brrrr \setbtxlist + \btxparameter\c!left + \publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}% + \btxparameter\c!right + \dostoptagged + \endgroup + \btx_reset_numbering} % probably not needed + +% end of page stuff + +\permanent\protected\def\btxflushlisttext + {\begingroup + \usebtxstyleandcolor\c!style\c!color + \ignorespaces + \publ_fast_setup\plusfour\s!list\currentbtxcategory + \removeunwantedspaces + \endgroup} + +\permanent\protected\def\btxflushlistcombis + {\begingroup + \processcommacommand[\currentbtxcombis]\btx_entry_inject_combi % maybe in lua + \endgroup} + +\def\btx_entry_inject_list_text + {\publ_fast_setup\plusfour\s!list\s!text} + +\ifdefined\dotagpublication \else \aliased\let\dotagpublication\gobbletwoarguments \fi + +\protected\def\btx_entry_inject + {\begingroup + \dostarttagged\t!publication\empty + \dotagpublication\currentbtxdataset\currentbtxtag + \redoconvertfont % see (**) in strc-lst, this will become an configuration option + \edef\currentbtxcategory{\btxfield{category}}% + \ignorespaces + \ifconditional\c_btx_list_texts + \dostarttagged\t!listtext\s!left + \currentbtxbefore + \dostoptagged + \fi + %\dostarttagged\t!listcontent\empty + \btx_entry_inject_list_text + %\dostoptagged + \ifconditional\c_btx_list_pages + \dostarttagged\t!listpage\empty + \btx_entry_inject_pages + \dostoptagged + \fi + \ifconditional\c_btx_list_texts + \dostarttagged\t!listtext\s!right + \currentbtxafter + \dostoptagged + \fi + \dostoptagged + \endgroup} + +\permanent\protected\def\btxshowentryinline[#1]#*[#2]% + {\ifarguments + \ctxcommand{showbtxentry("\currentbtxdataset","\currentbtxtag")} + \or + \ctxcommand{showbtxentry("\currentbtxdataset","#1")} + \or + \ctxcommand{showbtxentry("#1","#2")} + \fi} + +\permanent\protected\def\btxstartcombientry + {\begingroup} + +\permanent\protected\def\btxstopcombientry + {\endgroup} + +\permanent\protected\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} + +\newtoks\everybtxlistrendering + +\appendtoks + \setbtxlist + % + \edef\currentbtxcriterium{\btxrenderingparameter\c!criterium}% \v!cite will become \s!cite + \ifempty\currentbtxcriterium + \let\currentbtxcriterium\v!previous + \orelse\ifx\currentbtxcriterium\v!cite + \let\currentbtxcriterium\v!here + \fi + % + \iflocation + \letinteractionparameter\c!style\empty +% \letinteractionparameter\c!color\empty +% \letinteractionparameter\c!contrastcolor\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 + +\permanent\protected\def\btxsetnoflistentries #1{\edef\nofbtxlistentries {#1}} +\permanent\protected\def\btxsetcurrentlistentry#1{\edef\currentbtxlistentry{#1}} +\permanent\protected\def\btxsetcurrentlistindex#1{\edef\currentbtxlistindex{#1}} + +\permanent\protected\def\btxdoifelsesameaspreviouschecked#1#2% #1 == always | doublesided + {\clf_btxdoifelsesameasprevious + {\currentbtxdataset}% + \currentbtxlistentry% + {#2}% + \c_btx_list_reference + {#1}} + +\permanent\protected\def\btxdoifelsesameasprevious + {\btxdoifelsesameaspreviouschecked\v!doublesided} + +\permanent\protected\def\btxdoifelsecombiinlist#1#2% + {\clf_btxdoifelsecombiinlist{#1}{#2}} + +\aliased\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked +\aliased\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious +\aliased\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist + +\tolerant\def\publ_place_list_indeed#1#2[#3]#*[#4]% + {\begingroup + \ifparameters + \let\currentbtxrendering\currentbtxspecification + \or + \ifhastok={#3}% + % [settings] + \let\currentbtxrendering\currentbtxspecification + \setupcurrentbtxrendering[#3]% + \edef\p_specification{\btxrenderingparameter\c!specification}% + \ifempty\p_specification\else + \let\currentbtxspecification\p_specification + \let\currentbtxrendering\currentbtxspecification % tricky + \fi + \else + \edef\currentbtxrendering{#3}% + \edef\p_specification{\btxrenderingparameter\c!specification}% + \ifempty\p_specification\else + \let\currentbtxspecification\p_specification + \fi + \fi + \or + % [rendering] [settings] + \edef\currentbtxrendering{#3}% + \setupcurrentbtxrendering[#4]% + \edef\p_specification{\btxrenderingparameter\c!specification}% + \ifempty\p_specification\else + \let\currentbtxspecification\p_specification + \fi + \fi + \setbtxparameterset\currentbtxspecification\s!list + \the\everybtxlistrendering + \ifconditional#1\relax + \edef\currentbtxrenderingtitle{\btxrenderingparameter\c!title}% + \ifempty\currentbtxrenderingtitle + \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\headtext{\currentbtxrendering}}]}% + \else + \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\currentbtxrenderingtitle}]}% + \fi + \fi + \ifempty\currentbtxrendering + \setbtxrendering % hm + \fi + \edef\currentbtxdataset{\btxrenderingparameter\c!dataset}% + \uselanguageparameter\btxdatasetparameter % new + \setbtxlist + \the\everystructurelist + \the\everysetupbtxlistplacement + % 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}% + filter {\btxrenderingparameter\c!filter}% + \relax + \ifnum\nofbtxlistentries>\zerocount + \forgetall + \btxrenderingparameter\c!before + \ifconditional#2\relax + \edef\p_command{\btxrenderingparameter\c!command}% + \ifempty\p_command + \edef\p_setups{\btxrenderingparameter\c!setups}% + \ifempty\p_setups + \else + \directsetup{\p_setups}% + \fi + \else + \expandafter\p_command\expandafter{\number\nofbtxlistentries}\relax + \fi + \else + \dostarttagged\t!publications\currentbtxrendering + \dostarttagged\t!list{btx}% + \startpacked[\v!blank]% + % sorting and so + \clf_btxpreparelistentries{\currentbtxdataset}% could be put in collect + % next we analyze the width + \ifempty\currentbtxnumbering \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 + \dostoptagged + \dostoptagged + \fi + \btxrenderingparameter\c!after + \fi + \ifconditional#1\relax + \stopnamedsection + \fi + \global\advance\btxblock\plusone + \endgroup} + +\permanent\protected\def\placebtxrendering {\publ_place_list_indeed\conditionalfalse\conditionalfalse} +\permanent\protected\def\completebtxrendering{\publ_place_list_indeed\conditionaltrue \conditionalfalse} +\permanent\protected\def\flushbtxrendering {\publ_place_list_indeed\conditionalfalse\conditionaltrue } + +\aliased\let\completelistofpublications\completebtxrendering % for old times sake +\aliased\let\placelistofpublications \placebtxrendering % for old times sake + +%D This is somewhat special (for Alan of course): +%D +%D \starttyping +%D % #1 is number of entries +%D +%D \starttexdefinition unexpanded btx:for:alan:wrapper #1 +%D \bTABLE +%D % we can have a command or setups +%D \flushbtxentries[command=\texdefinition{btx:for:alan:content}] +%D \eTABLE +%D \stoptexdefinition +%D +%D % #1 is tag +%D +%D \starttexdefinition unexpanded btx:for:alan:content #1 +%D \bTR +%D \bTD +%D \btxsettag{#1} +%D \btxfield{name} +%D \eTD +%D \eTR +%D \stoptexdefinition +%D +%D % we can have a command or setups +%D +%D \flushbtxrendering [method=dataset,command=\texdefinition{btx:for:alan:wrapper}] +%D \stoptyping +%D +%D Because we want to be ungrouped we use a special loop construct. + +\permanent\protected\def\btxsetlisttag#1% + {\clf_btxflushlisttag{\currentbtxdataset}#1\relax} + +\newcount\c_btx_list_index + +\let\m_btx_list_action\empty + +\def\publ_flush_list_step_command + {\btxsetlisttag{\c_btx_list_index} + \expandafter\m_btx_list_action\expandafter{\currentbtxtag}% + \ifnum\c_btx_list_index<\nofbtxlistentries + \advance\c_btx_list_index\plusone + \expandafter\publ_flush_list_step_command + \else + \glet\m_btx_list_action\relax + \fi} + +\def\publ_flush_list_step_setup + {\btxsetlisttag{\c_btx_list_index} + \directsetup{\m_btx_list_action}% + \ifnum\c_btx_list_index<\nofbtxlistentries + \advance\c_btx_list_index\plusone + \expandafter\publ_flush_list_step_setup + \else + \glet\m_btx_list_action\relax + \fi} + +\permanent\protected\def\flushbtxentries[#1]% + {\begingroup + \getdummyparameters[\c!command=,\c!setups=,#1]% + \xdef\m_btx_list_action{\dummyparameter\c!command}% + \ifempty\m_btx_list_action + \xdef\m_btx_list_action{\dummyparameter\c!setups}% + \ifempty\m_btx_list_action + \endgroup + \c_btx_list_index\zerocount + \else + \endgroup + \c_btx_list_index\plusone + \doubleexpandafter\publ_flush_list_step_command + \fi + \else + \endgroup + \c_btx_list_index\plusone + \expandafter\publ_flush_list_step_command + \fi} + +%D So far. + +\permanent\def\currentbtxblock{\number\btxblock} + +% called at the lua end, for determining the width + +\permanent\protected\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 + {\dostarttagged\t!listcontent\empty + \btx_list_reference_inject + \btx_entry_inject + \dostoptagged} + +\def\btx_page_indeed + {} + +\permanent\protected\def\btxhandlelistentry + {\strc_lists_entry_process} + +\permanent\protected\def\btxstartlistentry % maybe pass i + {\begingroup + \global\advance\c_btx_list_reference\plusone} + +\permanent\protected\def\btxstoplistentry + {\iftrialtypesetting + \global\advance\c_btx_list_reference\minusone + \fi + \endgroup} + +\newtoks\everybtxlistentry + +\permanent\protected\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 + +\protected\def\btx_reference_indeed + {\begingroup + % redundant will go away: + \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering + % + \ifempty\currentbtxnumbering + % nothing + \orelse\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 + \endgroup} + +\permanent\protected\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} + +\protected\def\btx_reference_checked + {\dontleavehmode\hbox\bgroup % \hpack + \btx_reference_indeed + \egroup} + +\newcount\c_btx_list_reference + +\protected\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 + {\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 + %\ifempty\currentbtxcombis \else\s!btxcom={\currentbtxcombis},\fi% + \ifempty\currentbtxbefore \else\s!btxbtx={\currentbtxbefore},\fi% + \ifempty\currentbtxafter \else\s!btxatx={\currentbtxafter },\fi% + \ifempty\currentbtxbacklink\else\s!btxint=\number\currentbtxbacklink\fi + }% + {\s!btx::\v!list::\number\c_btx_list_reference}% + {\currentbtxnumber}} + +\newconditional\c_btx_cite_reference_injected + +\permanent\protected\def\btx_cite_reference_inject + {\ifconditional\c_btx_cite_reference_injected \else + \dontleavehmode + \iftrialtypesetting \else + \ifempty\currentbtxbacklink + % can be made empty when combining author / year + \orelse\ifnum\currentbtxbacklink>\zerocount + \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 + {\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,% + %\ifempty\currentbtxcombis \else\s!btxcom={\currentbtxcombis},\fi% + \ifempty\currentbtxbefore \else\s!btxbtx={\currentbtxbefore},\fi% + \ifempty\currentbtxafter \else\s!btxatx={\currentbtxafter },\fi% + \ifempty\currentbtxbacklink\else\s!btxint=\number\currentbtxbacklink,\fi + \ifempty\currentbtxciteuservariables\else,\currentbtxciteuservariables\fi]} + +\permanent\def\currentbtxuservariable #1{\clf_btxuservariable {\currentbtxdataset}{#1}} +\permanent\def\btxdoifelseuservariable#1{\clf_btxdoifelseuservariable{\currentbtxdataset}{#1}} + +\aliased\let\btxdoifuservariableelse\btxdoifelseuservariable + +\aliased\let\btxcitereference\btx_cite_reference_inject + +\mutable\let\currentbtxnumbering \empty +\mutable\let\currentbtxcitealternative \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 + \orelse\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 + \let\currentlistmethod\s!btx +\to \everysetupbtxlistplacement + +\permanent\tolerant\protected\def\btxremapauthor[#1]#*[#2]% + {\clf_btxremapauthor{#1}{#2}} + +\permanent\protected\def\btxshowauthorremapping + {\clf_btxshowauthorremapping} + +\permanent\protected\def\btxflushauthor + {\doifelsenextoptionalcs\btx_flush_author_yes\btx_flush_author_nop} + +\permanent\protected\def\btxflushsuffix + {\ifempty\currentbtxsuffix + % 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}} + +\protected\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}}% + connector {\btxparameter{\c!connector:initials}}% + }% + \relax + \endgroup} + +% yes or no: maybe just \flushauthor{...}{...} + +\permanent\protected\def\btxflushauthorname {\btx_flush_author{name}} % #1 +\permanent\protected\def\btxflushauthornormal {\btx_flush_author{normal}} % #1 +\permanent\protected\def\btxflushauthornormalshort {\btx_flush_author{normalshort}} % #1 +\permanent\protected\def\btxflushauthorinverted {\btx_flush_author{inverted}} % #1 +\permanent\protected\def\btxflushauthorinvertedshort{\btx_flush_author{invertedshort}} % #1 + +\mutable\let\currentbtxauthorfield\s!author + +\permanent\protected\def\btxsetauthorfield#1{\edef\currentbtxauthorfield{#1}} + +\permanent\protected\def\currentbtxciteauthorbyfield + {\begingroup + %\setbtxparameterset\s!cite\s!author + % the alternatives inherit from cite:author + % and APA distinguishes authoryears from authoryear ("and" vs. "&") + \setbtxparameterset\s!cite\currentbtxcitealternative + \clf_btxauthor + {\currentbtxdataset}% + {\currentbtxtag}% + {\currentbtxauthorfield}% + {% + 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} + +\permanent\protected\def\currentbtxciteauthor + {\let\currentbtxauthorfield\s!author + \currentbtxciteauthorbyfield} % always author + +\permanent\protected\def\btxstartauthor#1#2#3% a state > 0 signals that some authors can clash + {\begingroup + \currentbtxauthorindex#1\relax + \currentbtxauthorcount#2\relax + \currentbtxauthorstate#3\relax} + +\permanent\protected\def\btxstopauthor + {\endgroup} + +\permanent\protected\def\btxciteauthorsetup#1{\fastsetup{\s!btx:\s!cite:\s!author:#1}} +\permanent\protected\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} + +% Interaction +% +% Because we have more complex entries in lists we don't use the normal list +% interaction features. + +\newconditional\btxinteractive +\newconditional\btxinteractivenumber +\newconditional\btxinteractivetext +\newconditional\btxinteractivepage + +\mutable\let\currentbtxinteraction\empty + +\installcorenamespace{btxinteraction} + +\setvalue{\??btxinteraction\v!number}{\settrue\btxinteractivenumber} +\setvalue{\??btxinteraction\v!text }{\settrue\btxinteractivetext} +\setvalue{\??btxinteraction\v!page }{\settrue\btxinteractivepage} +\setvalue{\??btxinteraction\v!all }{\settrue\btxinteractivenumber + \settrue\btxinteractivetext + \settrue\btxinteractivepage} + +% \setupbtx[interaction=page] % or text or number or all +% \setupbtxrendering[pagestate=start] + +\appendtoks + \iflocation + \edef\currentbtxinteraction{\btxparameter\c!interaction}% + \ifx\currentbtxinteraction\v!stop + \setfalse\btxinteractive + \else + \let\structurelistlocation\empty + \settrue\btxinteractive + \begincsname\??btxinteraction\currentbtxinteraction\endcsname + \fi + \else + \setfalse\btxinteractive + \fi +\to \everysetupbtxlistplacement + +\appendtoks + \iflocation + \edef\currentbtxinteraction{\btxparameter\c!interaction}% + \ifx\currentbtxinteraction\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 + +\mutable\let\currentbtxciteuservariables\empty +\mutable\let\currentbtxcitealternative \empty + +\permanent\protected\def\btxhybridcite % so one can alias the old + {\dontleavehmode + \begingroup + \strictdoifelsenextoptional\publ_cite_tags_options\publ_cite_tags_indeed} + +\protected\def\publ_cite_tags_options[#1]% + {\strictdoifelsenextoptional{\publ_cite_tags_options_indeed{#1}}{\publ_cite_tags_indeed{#1}}} + +\protected\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} + +\protected\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}% + \ifempty\p_reference + \edef\currentbtxcitetag{#2}% + \else + \let\currentbtxcitetag\p_reference + \edef\currentbtxciteuservariables{#2}% + \fi + \edef\p_specification{\dummyparameter\c!specification}% + \ifempty\p_specification + \else + \let\currentbtxspecification\p_specification + \fi + \edef\p_alternative{\dummyparameter\c!alternative}% + \ifempty\p_alternative + \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 + +\mutable\let\currentbtxcitemethod\v!hidden + +\def\publ_cite_variant + {\begingroup + \publ_cite_handle_variant_indeed[\currentbtxcitetag]} + +\protected\def\publ_cite_handle_variant#1% + {\begingroup + \edef\currentbtxcitealternative{#1}% + \setbtxparameterset\s!cite\currentbtxcitealternative + \the\everysetupbtxciteplacement + \publ_cite_handle_variant_indeed} + +\permanent\protected\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} + +\aliased\let\dobtxcitevariantblob\publ_cite_handle_variant_blob % command can use it via lua + +\tolerant\def\publ_cite_handle_variant_indeed[#1]% + {\letbtxparameter\c!alternative\currentbtxcitealternative + \edef\currentbtxreference{#1}% + \saverunningstyleandcolor + \usebtxstyleandcolor\c!style\c!color + \uselanguageparameter\btxdatasetparameter % new + \btxparameter\c!left + \btxparameter\c!command{\dobtxcitevariantblob}% {\publ_cite_handle_variant_blob}% + \btxparameter\c!right + \endgroup} + +\permanent\protected\def\btxlistcitation {\publ_citation\v!list} +\permanent\protected\def\btxtextcitation {\publ_citation\v!text} +\permanent\protected\def\btxalwayscitation{\publ_citation\v!always} + +\tolerant\def\publ_citation#1[#2]#*[#3]% could be made more efficient but not now + {\dontleavehmode + \begingroup + \let\currentbtxcitemethod#1% + \ifparameter#3\or + \publ_cite_tags_options_indeed{#2}[#3]% + \else + \publ_cite_tags_indeed{#2}% + \fi} + +\permanent\tolerant\protected\def\btxhiddencitation[#1]% + {\iftrialtypesetting \else + \begingroup + \let\currentbtxcitemethod\v!hidden + \edef\currentbtxreference{#1}% + \clf_btxhandlenocite + method {\currentbtxcitemethod}% + dataset {\currentbtxdataset}% + reference {\currentbtxreference}% + \relax + %\clf_btxflushmarked + \endgroup + \fi} + +\permanent\protected\def\btxmissing#1% + {\dontleavehmode{\tttf<#1>}} + +%D Compatibility: + +\aliased\let\hiddencitation\btxhiddencitation \aliased\let\hiddencite\hiddencitation +\aliased\let\listcitation \btxlistcitation \aliased\let\listcite \listcitation +\aliased\let\textcitation \btxtextcitation \aliased\let\textcite \textcitation +\aliased\let\alwayscitation\btxalwayscitation \aliased\let\alwayscite\alwayscitation + +\permanent\protected\def\citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite} +\permanent\protected\def\nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite} + +\aliased\let\cite \citation +\aliased\let\nocite \nocitation +\aliased\let\usecitation\nocitation + +\protected\def\publ_entry_citation {\doifelsenextoptionalcs\btxlistcitation \btxdirectlistcite} +\protected\def\publ_entry_nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite} + +\appendtoks + \enforced\let\cite \publ_entry_citation + \enforced\let\nocite\publ_entry_nocitation +\to \everybtxlistrendering + +\permanent\protected\def\btxdirectlistcite #1{\btxlistcitation [#1]\relax} % no optional arguments +\permanent\protected\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% + \orelse\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:#2\endcsname + \currentbtxspecificationfallback:#1:#2% + \orelse\ifcsname\??setup:\s!btx:#1:#2\endcsname + #1:#2% + \orelse\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname + \currentbtxspecification:#1:\s!unknown + \orelse\ifcsname\??setup:\s!btx:\currentbtxspecificationfallback:#1:\s!unknown\endcsname + \currentbtxspecificationfallback:#1:\s!unknown + \else + #1:\s!unknown + \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% + \orelse\ifcsname\??setup:\s!btx:#1:#2\endcsname + #1:#2% + \orelse\ifcsname\??setup:\s!btx:\currentbtxspecification:#1:\s!unknown\endcsname + \currentbtxspecification:#1:\s!unknown + \else + #1:\s!unknown + \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 + +\protected\def\publ_fast_btx_setup_chain_inbetween{\allowbreak->\allowbreak} +\protected\def\publ_fast_btx_setup_colon_inbetween{\allowbreak :\allowbreak} + +\protected\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} + +\protected\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} + +\protected\def\publ_fast_btx_setup_normal#1% + {\btxsetuptype#1\relax + \ifempty\currentbtxspecificationfallback + \expandafter\publ_fast_setup_nop + \else + \expandafter\publ_fast_setup_yes + \fi} + +\protected\def\publ_fast_btx_setup_visual#1#2#3% + {\btxsetuptype#1\relax + \ifempty\currentbtxspecificationfallback + \expandafter\publ_fast_btx_setup_chain_nop + \else + \expandafter\publ_fast_btx_setup_chain_yes + \fi{#2}{#3}% + \ifempty\currentbtxspecificationfallback + \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 + +\permanent\protected\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 + +\permanent\protected\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 + +\permanent\protected\def\btxstartsubcite#1% + {\begingroup + \btx_reset_cite % todo: limited set + % \saverunningstyleandcolor % let's see when Alan needs it + \def\currentbtxcitealternative{#1}% + \setbtxparameterset\s!cite\currentbtxcitealternative + \usebtxstyleandcolor\c!style\c!color + \btxparameter\c!left + \relax} + +\permanent\protected\def\btxstopsubcite + {\relax + \btxparameter\c!right + \endgroup} + +\permanent\protected\def\btxstartciterendering[#1]% + {\begingroup + \edef\currentbtxcitealternative{#1}% + \setbtxparameterset\s!cite\currentbtxcitealternative + \usebtxstyleandcolor\c!style\c!color + \btxparameter\c!left + \relax} + +\permanent\protected\def\btxstopciterendering + {\relax + \btxparameter\c!right + \endgroup} + +\aliased\let\btxstartciteauthor\begingroup +\aliased\let\btxstopciteauthor \endgroup + +\permanent\protected\def\btxstartcite{\begingroup\btx_reset_cite} +\aliased \let\btxstopcite \endgroup + +%D Whatever helpers: + +\permanent\protected\def\btxsingularplural#1{\clf_btxsingularorplural{\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\protected\def\btxoneorrange #1{\clf_btxoneorrange {\currentbtxdataset}{\currentbtxtag}{#1}} +\permanent\protected\def\btxfirstofrange #1{\clf_btxfirstofrange {\currentbtxdataset}{\currentbtxtag}{#1}} + +\aliased\let\btxsingularorplural\btxsingularplural + +\stopcontextdefinitioncode + +%D Journals + +\permanent\protected\def\btxloadjournallist [#1]{\clf_btxloadjournallist{#1}} +\permanent\protected\def\btxsavejournallist [#1]{\clf_btxsavejournallist{#1}} +\permanent\protected\def\btxaddjournal [#1][#2]{\clf_btxaddjournal{#1}{#2}} +\permanent \def\btxexpandedjournal #1{\clf_btxexpandedjournal{#1}} % \protected ? +\permanent \def\btxabbreviatedjournal#1{\clf_btxabbreviatedjournal{#1}} % \protected ? + +% \installcorenamespace{btxjournal} +% +% \letvalue{\s!btxjournal\v!long }\btxexpandedjournal +% \letvalue{\s!btxjournal\v!short }\btxabbreviatedjournal +% \letvalue{\s!btxjournal\v!normal}\firstofoneargument +% +% \protected\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: + +\tolerant\permanent\protected\def\savebtxdataset[#1]#*[#2]#*[#3] + {\ifarguments + % bad news + \or + \ifhastok={#1}% + \publ_save_dataset_indeed[\s!default][\jobname-saved.bib][#1]% + \else + \publ_save_dataset_indeed[\s!default][#1][]% + \fi + \or + \ifhastok={#2}% + \publ_save_dataset_indeed[\s!default][#1][#2]% + \else + \publ_save_dataset_indeed[#1][#2][]% + \fi + \or + \publ_save_dataset_indeed[#1][#2][#3]% + \fi} + +\protected\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: + +\permanent\protected\def\placecitation{\citation[entry]} % [#1] + +\permanent\protected\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] + +\protected\def\publ_registers_set + {\ifempty\currentbtxregister \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 + +\permanent\protected\def\btxindexedauthor#1#2#3#4#5#6% alternative von last initials first junior + {\begingroup + \def\currentbtxcitealternative{#1}% + \ifempty\currentbtxcitealternative + \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} + +\permanent\protected\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 + +\permanent\protected\def\btxstartstyle[#1]% + {\begingroup + \let\savedcurrentbtx\currentbtx + \def\currentbtx{#1}% + \usebtxstyle\c!style + \let\currentbtx\savedcurrentbtx} + +\permanent\protected\def\btxstartcolor[#1]% + {\begingroup + \let\savedcurrentbtx\currentbtx + \def\currentbtx{#1}% + \usebtxcolor\c!color + \let\currentbtx\savedcurrentbtx} + +\permanent\protected\def\btxstartstyleandcolor[#1]% + {\begingroup + \let\savedcurrentbtx\currentbtx + \def\currentbtx{#1}% + \usebtxstyleandcolor\c!style\c!color + \let\currentbtx\savedcurrentbtx} + +\aliased\let\btxstopstyle \endgroup +\aliased\let\btxstopcolor \endgroup +\aliased\let\btxstopstyleandcolor\endgroup + +\permanent\protected\def\btxusecommand[#1]#2% using #2 permits space after [] + {\namedbtxparameter{#1}\c!command{#2}} + +\permanent\protected\def\startbtxrunningstyleandcolor + {\dontleavehmode + \begingroup + \restorerunningstyleandcolor} + +\permanent\protected\def\stopbtxrunningstyleandcolor + {\endgroup} + +%D Maybe handy: + +\permanent\protected\def\btxdoifelsematches#1#2#3% + {\clf_btxdoifelsematches{#1}{#2}{#3}} + +%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={\removepunctuation;\space}, + \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!range=\directdiscretionary\endash, + \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 + +\permanent\protected\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] + +%D Delayed loading: + +\fetchruntimecommand \showbtxdatasetfields \f!publ_tra +\fetchruntimecommand \showbtxdatasetcompleteness \f!publ_tra +\fetchruntimecommand \showbtxdatasetauthors \f!publ_tra +\fetchruntimecommand \showbtxhashedauthors \f!publ_tra +\fetchruntimecommand \showbtxfields \f!publ_tra +\fetchruntimecommand \showbtxtables \f!publ_tra + +%D Some potential crap: +%D +%D Because I consider this bad data management and a weird mix of languages only one +%D accessor is provided. + +\permanent\tolerant\protected\def\btxshortcut[#1]#:#2% + {\clf_btxshortcut{\ifparameter#1\or#1\else\s!default\fi}{#2}} + +\protect diff --git a/tex/context/base/mkxl/publ-old.mkxl b/tex/context/base/mkxl/publ-old.mkxl new file mode 100644 index 000000000..cf7e0c46b --- /dev/null +++ b/tex/context/base/mkxl/publ-old.mkxl @@ -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 + +% No protection because we have a module that overloads them! + +\protected\def\setupbibtex {\usemodule[oldbibtex]\setupbibtex} +\protected\def\setuppublications {\usemodule[oldbibtex]\setuppublications} +\protected\def\setuppublicationlist{\usemodule[oldbibtex]\setuppublicationlist} + +\protect diff --git a/tex/context/base/mkxl/publ-tra.mkxl b/tex/context/base/mkxl/publ-tra.mkxl new file mode 100644 index 000000000..ccad4c22a --- /dev/null +++ b/tex/context/base/mkxl/publ-tra.mkxl @@ -0,0 +1,84 @@ +%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}{} + +\unprotect + +\permanent\protected\gdef\showbtxdatasetfields {\publ_show_dataset_whatever{showbtxdatasetfields}} +\permanent\protected\gdef\showbtxdatasetcompleteness{\publ_show_dataset_whatever{showbtxdatasetcompleteness}} +\permanent\protected\gdef\showbtxdatasetauthors {\publ_show_dataset_whatever{showbtxdatasetauthors}} + +\tolerant\gdef\publ_show_dataset_whatever#1[#2]% + {\begingroup + \letdummyparameter\c!specification\currentbtxspecification + \setdummyparameter\c!dataset {\currentbtxdataset}% + \letdummyparameter\c!field \empty + \ifparameter#2\or + \ifhastok={#2}% + \getdummyparameters[#2]% + \else + \setdummyparameter\c!dataset{#2}% + \fi + \fi + \ctxcommand{#1{ + dataset = "\dummyparameter\c!dataset", + specification = "\dummyparameter\c!specification", + field = "\dummyparameter\c!field", + }}% + \endgroup} + +\permanent\tolerant\protected\gdef\showbtxfields[#1]% + {\begingroup + \setdummyparameter\c!rotation{90}% + \ifparameter#1\or + \ifhastok={#1}% + \letdummyparameter\c!specification\currentbtxspecification + \getdummyparameters[#1]% + \else + \setdummyparameter\c!specification{#1}% + \fi + \else + \letdummyparameter\c!specification\currentbtxspecification + \fi + \ctxcommand{showbtxfields{ + rotation = "\dummyparameter\c!rotation", + specification = "\dummyparameter\c!specification" + }}% + \endgroup} + +\permanent\tolerant\protected\gdef\showbtxtables[#1]% + {\begingroup + \ctxcommand{showbtxtables{}}% + \endgroup} + +\permanent\tolerant\protected\gdef\showbtxhashedauthors[#1]% + {\ctxcommand{showbtxhashedauthors{}}} + +\protect + +\continueifinputfile{publ-tra.mkiv} + +\starttext + + \showbtxfields[rotation=85] \page + \showbtxfields[rotation=90] \page + + \showbtxtables \page + +\stoptext diff --git a/tex/context/base/mkxl/publ-xml.mkxl b/tex/context/base/mkxl/publ-xml.mkxl new file mode 100644 index 000000000..74fb47e08 --- /dev/null +++ b/tex/context/base/mkxl/publ-xml.mkxl @@ -0,0 +1,111 @@ +%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 + +\permanent\tolerant\protected\def\convertbtxdatasettoxml[#1]% + {\clf_convertbtxdatasettoxml{\ifparameter#1\or#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 + + +% \protected\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 + +% \protected\def\btx_xml_doifelse#1{\xmldoifelse\currentbibxmlnode{/field[@name='#1']}} +% \protected\def\btx_xml_doif #1{\xmldoif \currentbibxmlnode{/field[@name='#1']}} +% \protected\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} +% \protected\def\btx_xml_todo #1{[#1]} + +% \xmlfilter{#1}{/field[@name='\currentbtxfield']/btxconcat('\currentbtxfield')} diff --git a/tex/context/base/mkxl/regi-ini.mkxl b/tex/context/base/mkxl/regi-ini.mkxl new file mode 100644 index 000000000..31e8b4717 --- /dev/null +++ b/tex/context/base/mkxl/regi-ini.mkxl @@ -0,0 +1,37 @@ +%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}{} + +\unprotect + +%D \macros +%D {enableregime,disableregime, +%D startregime,stopregime, +%D currentregime} +%D +%D Beware, the enable and disable commands are global switches, so best use the +%D start|/|stop commands. + +\let\currentregime\empty + +\permanent\protected\def\enableregime[#1]{\clf_enableregime{#1}} +\permanent\protected\def\disableregime {\clf_disableregime} +\permanent\protected\def\startregime [#1]{\clf_startregime{#1}} +\permanent\protected\def\stopregime {\clf_stopregime} + +% only for diagnostics: + +% \def\codepagename#1{\cldcontext{os.tocodepage("#1")}} + +\protect \endinput diff --git a/tex/context/base/mkxl/scrn-bar.mklx b/tex/context/base/mkxl/scrn-bar.mklx new file mode 100644 index 000000000..f99f7569f --- /dev/null +++ b/tex/context/base/mkxl/scrn-bar.mklx @@ -0,0 +1,402 @@ +%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 same. In +%D retrospect this should have been a module. We can move some definitions to +%D scrn-run-bar.mkiv if needed. We can also make 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 + +\permanent\tolerant\protected\def\interactionbar[#tag]#spacer[#settings]% somewhat messy + {\iflocation + \begingroup + \ifhastok={#tag}% + \let\currentinteractionbar\empty + \setupcurrentinteractionbar[#tag]% + \edef\currentinteractionbar{\interactionbarparameter\c!alternative}% + \else + \edef\currentinteractionbar{#tag}% + \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 typically only used for +%D navigational purposed. The next macro builds such a row based on a specification +%D 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 \type {subpage} as +%D shortcuts to their four associated buttons. The symbols are derived from the +%D symbols linked to the entries. + +\permanent\tolerant\protected\def\interactionbuttons[#settings]#spacer[#list]% + {\iflocation + \ifcstok{\interactionbarparameter\c!state}\v!start + \ifparameter#list\or + \scrn_bar_buttons_indeed{#settings}{#list}% + \else + \scrn_bar_buttons_indeed{}{#settings}% + \fi + \fi + \fi} + +\def\scrn_bar_buttons_indeed#settings#list% + {\begingroup + %\let\currentinteractionbar\empty + \setupcurrentinteractionbar[#settings]% + \d_scrn_bar_width \interactionbarparameter\c!width\relax + \d_scrn_bar_distance\interactionbarparameter\c!distance\relax + \ifzeropt\d_scrn_bar_width + \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]% + \ifzeropt\d_scrn_bar_width + \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]% + \setupbuttons + [#settings,% + \c!height=\the\scratchheight,% + \c!width=\the\scratchdimenone]% + \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{\symbol[#action]}[#action]\hss} + +% todo: this will be \letblackruleparameter\c!width\scratchdimenone (faster) +% todo: make these setups + +\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\hpack{\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} + +\protected\def\scrn_bar_goto_a#whereto% + {\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!next\fi]} + +\protected\def\scrn_bar_goto_b#whereto% + {\vrule\s!height\d_scrn_bar_height\s!depth\d_scrn_bar_depth\s!width\scratchdimenone\relax} + +\protected\def\scrn_bar_goto_c#whereto% + {\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!somewhere\or\v!somewhere\or\v!next\fi} + +\protected\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 + +\protected\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}}% \hpack ? + }\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}% \hpack ? + \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 + {\donefalse + \advance\scratchcounterfive \plusone + \ifnum\recurselevel=\firstsubpage\relax \donetrue \fi + \ifnum\recurselevel=\lastsubpage \relax \donetrue \fi + \scratchcountersix\therealsubpageno\recurselevel\relax + \c_scrn_bar_mode + \ifdone + \ifnum\scratchcountersix<\realpageno + \zerocount + \orelse\ifnum\scratchcountersix>\realpageno + \plustwo + \else + \plusfour + \fi + \else + \ifnum\scratchcounterfive=\scratchcountertwo + \ifnum\scratchcountersix<\realpageno + \plusone + \orelse\ifnum\scratchcountersix>\realpageno + \plusthree + \else + \plustwo + \fi + \else + \minusone + \fi + \fi + \ifnum\c_scrn_bar_mode<\zerocount\else + \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\c_scrn_bar_mode}[realpage(\the\scratchcountersix)]}% + \hss + \scratchcounterfive\zerocount + \fi}% + \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/tex/context/base/mkxl/scrn-but.mklx b/tex/context/base/mkxl/scrn-but.mklx new file mode 100644 index 000000000..60073a6b7 --- /dev/null +++ b/tex/context/base/mkxl/scrn-but.mklx @@ -0,0 +1,1031 @@ +%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. + +\writestatus{loading}{ConTeXt Screen Macros / Buttons} + +\registerctxluafile{scrn-but}{} + +%D This really needs testing in lmtx ... + +\unprotect + +%D Buttons are just what their names says: things that can be clicked (pushed) on. +%D They are similar to \type{\goto}, except that the text argument is not +%D interpreted. Furthermore one can apply anything to them that can be done with +%D \type {\framed}. +%D +%D \startbuffer +%D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer] +%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 + +\aliased\let\setupbuttons\setupbutton + +\appendtoks + \frozen\instance\setuevalue\currentbutton{\scrn_button_direct{\currentbutton}}% +\to \everydefinebutton + +\protected\def\scrn_button_direct#tag% + {\begingroup + \edef\currentbutton{#tag}% + \iflocation + \expandafter\scrn_button_direct_status + \else + \expandafter\scrn_button_direct_ignore + \fi} + +\def\scrn_button_direct_status + {\ifcstok{\buttonparameter\c!state}\v!start + \expandafter\scrn_button_direct_indeed + \else + \expandafter\scrn_button_direct_ignore + \fi} + +% empty=yes +% +% \button[settings]{}[action] % normally used at the tex end + +\tolerant\def\scrn_button_direct_indeed[#settings]#:#text[#action]% + {\setupcurrentbutton[#settings]% + % no \dontleavehmode as it will force a vbox to \hsize which then + % spoils a tight box + \hpack\bgroup + \scrn_button_make + \buttonparameter + \inheritedbuttonframed + \letbuttonparameter + \setbuttonparameter + {#text}% + {#action}% + \egroup + \endgroup} + +\tolerant\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 used in the whatevertext +%D 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 as well as braces. + +\permanent\tolerant\protected\def\overlaybutton[#1]#;#=% + {\iflocation + \gotobox{\overlayfakebox}[#1]% + \fi} + +%D The renderers: + +\aliased\letcsname\??buttonlocation\v!yes \endcsname\zerocount +\aliased\letcsname\??buttonlocation\v!empty \endcsname\plusone +\aliased\letcsname\??buttonlocation\v!no \endcsname\plustwo +\aliased\letcsname\??buttonlocation\v!none \endcsname\plusthree +\aliased\letcsname\??buttonlocation\v!normal \endcsname\plusone % default +\aliased\letcsname\??buttonlocation\s!default\endcsname\plusone % default +\aliased\letcsname\??buttonlocation \endcsname\plusone % default + +\newconditional\c_scrn_button_skipped + +\def\scrn_button_make#currentparameter#inheritedframed#letparameter#setparameter#text#action% + {\begingroup + \c_attr_reference\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 + \orelse\ifnum\scratchcounter=\realpageno + \expandafter\scrn_button_make_yes_same + \else + \expandafter\scrn_button_make_yes_other + \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 + +\aliased\let\setupinteractionmenus\setupinteractionmenu + +\let\scrn_menu_action\relax + +\let\scrn_menu_define_original\defineinteractionmenu + +\pushoverloadmode + +\permanent\tolerant\protected\def\defineinteractionmenu[#tag]#spacer[#category]#spacer[#settings]% category reflects location, settings can be parent + {\ifarguments\or + \scrn_menu_define_original[#tag]% % root definition + \or + \ifhastok={#category}% + \scrn_menu_define_original[#tag][#category]% % root definition + \else + \scrn_menu_define_original[#tag][#category][\c!category=#category]% % child definition + \scrn_menu_register{#tag}{#category}% + \fi + \or + \ifhastok={#settings}% + \scrn_menu_define_original[#tag][#category][\c!category=#category,#settings]% child definition + \else + \scrn_menu_define_original[#tag][#settings][\c!category=#category]% % child definition + \fi + \scrn_menu_register{#tag}{#category}% + \fi} + +\popoverloadmode + +\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}}}} + \toksapp\csname\??menutoks#category\endcsname{\scrn_menu_action{#tag}}} % needs testing + +\def\scrn_menu_actions#category% + {\the\csname\??menutoks#category\endcsname} + +%D Fill menus: + +\aliased\letcsname\e!stop\v!interactionmenu\endcsname\relax + +%normalexpanded{\permanent\defcsname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}% +% \normalexpanded{\permanent\expandafter\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}% +\normalexpanded{\permanent\expandafter\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\csname\e!stop\v!interactionmenu\endcsname}% + {\def\currentinteractionmenu{#tag}% + \expandafter\settrue\csname\??menustate\interactionmenuparameter\c!category\endcsname + \setinteractionmenuparameter\c!menu{#content}} + +\permanent\protected\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 adapted +%D automatically to offsets in the text backgrounds. Here we have a bit more (but +%D 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 easier. +%D After all, menus need some setup anyway. The offsets are added to the width or +%D height (this is different from \MKII). + +\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 + {\ifzeropt\d_scrn_menu_offset_left \else + \setbox\b_scrn_menu\hbox{\hskip-\d_scrn_menu_offset_left \box\b_scrn_menu}% + \fi + \ifzeropt\d_scrn_menu_offset_bottom \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 \orelse \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 + \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 + +\protected\def\scrn_menu_package_indeed#tag% one menu + {\begingroup + \edef\currentinteractionmenu{#tag}% + \edef\currentinteractionmenustate{\interactionmenuparameter\c!state}% + \ifx\currentinteractionmenustate\v!start + \scrn_menu_packager + \orelse\ifx\currentinteractionmenustate\v!empty + \scrn_menu_packager + \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{\directinteractionmenuparameter\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{\directinteractionmenuparameter\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 {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, while the rest is +%D positional info. The status variable is 0, 1 or~2: not found, found and found but +%D 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}% + );} + +\permanent\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} + +\protected\def\scrn_menu_raw_start[#action]#text\stopraw + {\scrn_menu_action_start + \gotobox{\ignorespaces#text\unskip}[#action]% + \scrn_menu_action_stop} + +\protected\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}% + \xtoksapp\t_scrn_menu_meta_data{\scrn_menu_button_meta_template}% + \hpos + {\askedinteractionmenulocation:\number\c_scrn_menu_position}% + {\scrn_button_make + #currentparameter% + #inheritedframed% + #letparameter% + #setparameter% + {#text}% + {#action}}} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\scrn_menu_rul_start#text\stoprul + {\scrn_menu_action_start + \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}% + \scrn_menu_action_stop} + +\permanent\protected\def\scrn_menu_com_start#text\stopcom + {\ignorespaces#text\removeunwantedspaces + \ignorespaces} + +\permanent\protected\def\scrn_menu_raw#content\\{\scrn_menu_raw_start#content\stopraw} \aliased\let\stopraw\relax +\permanent\protected\def\scrn_menu_but#content\\{\scrn_menu_but_start#content\stopbut} \aliased\let\stopbut\relax +\permanent\protected\def\scrn_menu_got#content\\{\scrn_menu_got_start#content\stopgot} \aliased\let\stopgot\relax +\permanent\protected\def\scrn_menu_nop#content\\{\scrn_menu_nop_start#content\stopnop} \aliased\let\stopnop\relax +\permanent\protected\def\scrn_menu_txt#content\\{\scrn_menu_txt_start#content\stoptxt} \aliased\let\stoptxt\relax +\permanent\protected\def\scrn_menu_rul#content\\{\scrn_menu_rul_start#content\stoprul} \aliased\let\stoprul\relax +\permanent\protected\def\scrn_menu_com#content\\{\scrn_menu_com_start#content\stopcom} \aliased\let\stopcom\relax + +\newtoks\everysetmenucommands % public + +\appendtoks + \enforced\let\raw\scrn_menu_raw \enforced\let\startraw\scrn_menu_raw_start \enforced\let\stopraw\relax + \enforced\let\but\scrn_menu_but \enforced\let\startbut\scrn_menu_but_start \enforced\let\stopbut\relax + \enforced\let\got\scrn_menu_got \enforced\let\startgot\scrn_menu_got_start \enforced\let\stopgot\relax + \enforced\let\nop\scrn_menu_nop \enforced\let\startnop\scrn_menu_nop_start \enforced\let\stopnop\relax + \enforced\let\txt\scrn_menu_txt \enforced\let\starttxt\scrn_menu_txt_start \enforced\let\stoptxt\relax + \enforced\let\rul\scrn_menu_rul \enforced\let\startrul\scrn_menu_rul_start \enforced\let\stoprul\relax + \enforced\let\com\scrn_menu_com \enforced\let\startcom\scrn_menu_com_start \enforced\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 + +\permanent\protected\def\includemenu[#tag]% + {\begingroup + \edef\currentinteractionmenu{#tag}% + \doif{\interactionmenuparameter\c!state}\v!local + {\letinteractionmenuparameter\c!state\v!start + \directinteractionmenuparameter\c!menu}% + \endgroup} + +%D Direct call (todo): + +\permanent\tolerant\protected\def\interactionmenu[#tag]#spacer[#settings]% + {\begingroup + \edef\currentinteractionmenu{#tag}% + \setupcurrentinteractionmenu[#settings]% + \scrn_menu_insert{#tag}% + \endgroup} + +%D Plugin handler: + +\protected\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: + +\protected\def\scrn_menu_leftedge + {\hbox to \leftedgewidth \bgroup + \hsize\leftedgewidth + \settrue\c_scrn_menu_zerodimensions + \scrn_menu_insert\v!left + \egroup + \hskip-\leftedgewidth} + +\protected\def\scrn_menu_rightedge + {\hbox to \rightedgewidth \bgroup + \hsize\rightedgewidth + \settrue\c_scrn_menu_zerodimensions + \scrn_menu_insert\v!right + \egroup + \hskip-\rightedgewidth} + +\protected\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} + +\protected\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: + +\def\scrn_button_direct_status + {\doifelse{\buttonparameter\c!state}\v!start + {\dosingleempty\scrn_button_direct_indeed}% + {\dosingleempty\scrn_button_direct_ignore}} + +\permanent\protected\def\menubutton % tag settings text action + {\iflocation + \expandafter\scrn_menu_menu_button_indeed + \else + \expandafter\scrn_menu_menu_button_ignore + \fi} + +\tolerant\def\scrn_menu_menu_button_indeed[#menutag]#spacer[#settings]#:#text[#action]% + {\ifcstok{\interactionmenuparameter\c!state}\v!start + \ifparameter#settings\or + \expandafter\scrn_menu_menu_button_a + \orelse\ifhastok={#menutag}% + \expandafter\scrn_menu_menu_button_b + \else + \expandafter\scrn_menu_menu_button_c + \fi{#menutag}{#settings}{#text}{#action}% + \fi} + +\tolerant\def\scrn_menu_menu_button_ignore[#menutag]#spacer[#settings]#:#text[#action]% + {} + +\def\scrn_menu_menu_button_a#tag#settings#text#action% + {\dontleavehmode \begingroup + \edef\currentinteractionmenu{#tag}% + \setupcurrentinteractionmenu[#settings]% + \scrn_button_make + \interactionmenuparameter + \inheritedinteractionmenuframed + \letinteractionmenuparameter + \setinteractionmenuparameter + {#text}% + {#action}% + \endgroup} + +\def\scrn_menu_menu_button_b#settings#dummy#text#action% + {\dontleavehmode \begingroup + \let\currentbutton\empty + \setupcurrentbutton[#settings]% + \scrn_button_make + \buttonparameter + \inheritedbuttonframed + \letbuttonparameter + \setbuttonparameter + {#text}% + {#action}% + \endgroup} + +\def\scrn_menu_menu_button_c#tag#dummy#text#action% + {\dontleavehmode \begingroup + \edef\currentinteractionmenu{#tag}% + \scrn_button_make + \interactionmenuparameter + \inheritedinteractionmenuframed + \letinteractionmenuparameter + \setinteractionmenuparameter + {#text}% + {#action}% + \endgroup} + +%D Untested: + +\permanent\tolerant\protected\def\registermenubuttons[#menu]#spacer[#register]% + {\begingroup + \ifparameter#register\or + \clf_registerbuttons{#menu}{#register}{\currentlanguage}% + \else + \clf_registerbuttons{}{#menu}{\currentlanguage}% + \fi + \removeunwantedspaces + \endgroup} + +\def\doregistermenubutton#1#2#3% used at lua end + {\ifcstok{\interactionmenuparameter\c!state}\v!start + \scrn_menu_menu_button_c{#1}{}{#2}{#3}% + \fi + \space} + +\protect \endinput diff --git a/tex/context/base/mkxl/scrn-fld.mklx b/tex/context/base/mkxl/scrn-fld.mklx new file mode 100644 index 000000000..fb249c01f --- /dev/null +++ b/tex/context/base/mkxl/scrn-fld.mklx @@ -0,0 +1,1013 @@ +%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. + +%D There is still some leftover code from mkii, where we need to be sparse with hash +%D entries and so have a somewhat complex setup mechanism. It doesn't pay off to +%D waste time on improving this because one never knows what happens with widgets +%D in \PDF; it has a history of dropping features like this. Also, the implementation +%D of fields fluctuates with versions. + +% interaction checking + +\writestatus{loading}{ConTeXt Screen Macros / Fields} + +\unprotect + +\registerctxluafile{scrn-fld}{} + +%D In \MKII\ we had to cheat a bit with setups in order not to run out of memory +%D with thousands of fields, which we happen to need at that time. In \MKIV\ we can +%D store some data at the \LUA\ end and use a somewhat slower but quite okay +%D inheritance mechanism. For this reason we now have split definitions, although +%D the old method is still somewhat supported. The clone and copy commands are +%D somewhat obsolete for several reasons: we can now use inheritance and autocloning +%D has been supported for a while. In most cases cloning (especially with check +%D boxes) the acrobat browser is not stable enough with respect to appearance +%D 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@xs4all.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 can be set. +%D +%D Because there are persistent problems with acrobat rendering associated +%D appearance streams (some messy /MK interferende) we also support native (built-in +%D dingbat) symbols: check, circle, 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 that we want \FDF\ or +%D \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 can be used as +%D rendering for a widget. + +\permanent\protected\def\presetfieldsymbols[#list]% slow + {\processcommacommand[#list]\scrn_symbols_preset} + +\def\scrn_symbols_preset#set% + {\processcommalist[#set]\scrn_symbols_preset_indeed}% + +\permanent\protected\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 + +\aliased\let\dosetfieldsymbol\scrn_symbols_preset_indeed + +\permanent\def\dogetfieldsymbol#tag% + {\getobject{SYM}{#tag}} + +\permanent\protected\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}% + \ifempty\currentfieldbodycategory + \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 + \ifempty\currentfieldbodyparent + \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 + +\permanent\tolerant\protected\def\fieldbody[#tag]#spacer[#settings]% + {\iflocation + \hbox\bgroup + \edef\currentfieldbody{#tag}% + \setupcurrentfieldbody[#settings]% + \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}% + \ifempty\currentfieldframecolor\else + \getcolorattributevalue\currentfieldframecolor\currentfieldframecolorvalue + % == \edef\currentfieldframecolorvalue{\thecolorattribute\currentfieldframecolor}% + \fi + \edef\currentfieldbackgroundcolor{\fieldbodyparameter\c!fieldbackgroundcolor}% + \ifempty\currentfieldbackgroundcolor\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 \c_attr_color + \ifempty\currentfieldbackgroundcolor \else + backgroundcolor {\currentfieldbackgroundcolor}% + backgroundcolorvalue \numexpr\currentfieldbackgroundcolorvalue\relax + \fi + \ifempty\currentfieldframecolor \else + framecolor {\currentfieldframecolor}% + framecolorvalue \numexpr\currentfieldframecolorvalue\relax + \fi + layer {\fieldbodyparameter\c!fieldlayer}% + option {\fieldbodyparameter\c!option}% + 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] + +\permanent\tolerant\protected\def\definefieldbodyset[#tag]#spacer[#list]% + {\clf_definefieldset{#tag}{#list}} + +\aliased\let\dodefinefieldset\definefieldbodyset % compatibility + +%D A few testing macros (expandable for historic reasons): + +\permanent\def\doifelsefieldbody #tag{\clf_doifelsefield{#tag}} +\permanent\def\doifelsefieldcategory#tag{\clf_doifelsefieldcategory{#tag}} + +\aliased\let\doiffieldbodyelse \doifelsefieldbody +\aliased\let\doiffieldcategoryelse\doifelsefieldcategory + +\aliased\let\doiffieldelse \doifelsefieldbody % compatibility / will be dropped +\aliased\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 achieve the same. + +\permanent\tolerant\protected\def\definefield[#tag]#spacer[#type]#spacer[#category]#spacer[#values]#spacer[#default]% + {\definefieldbody[#tag][\c!type=#type,\c!category=#category,\c!values={#values},\c!default={#default}]} + +\permanent\tolerant\protected\def\definesubfield[#tag]#spacer[#category]#spacer[#values]% + {\definefieldbody[#tag][\c!type=sub,\c!category=#category,\c!values={#values}]} + +\permanent\tolerant\protected\def\clonefield[#parent]#spacer[#tag]#spacer[#category]#spacer[#values]% + {\definefieldbody[#tag][#parent][\c!category=#category,\c!values={#values}]} + +\permanent\tolerant\protected\def\copyfield[#parent]#spacer[#tag]% + {\definefieldbody[#tag][#parent]} + +\aliased\let\definemainfield\definefield % obsolete ! + +%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 \type +%D {\fitfield}, in fact it (now) uses a dedicated instance of framed: \type +%D {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=] + +\permanent\tolerant\protected\def\fitfield[#tag]#spacer[#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 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} + +\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 + +\permanent\tolerant\protected\def\setupfield[#tag]#spacer[#variant]#spacer[#totalsettings]#spacer[#labelsettings]#spacer[#fieldsettings]% + {\ifarguments\or\or + \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#variant]% + \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal]% + \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]% + \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#variant]% + \or + \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]% + \or + \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]% + \or + \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]% + \fi} + +\permanent\tolerant\protected\def\setupfields[#variant]#spacer[#totalsettings]#spacer[#labelsettings]#spacer[#fieldsettings]% + {\ifarguments\or + \setupfieldtotalframed [#variant]% + \or + \setupfieldtotalframed [#variant]% + \setupfieldcontentframed[#totalsettings]% + \or + \setupfieldtotalframed [#variant]% + \setupfieldlabelframed [#totalsettings]% + \setupfieldcontentframed[#labelsettings]% + \or + \setupfieldtotalframed [\c!alternative={#variant},#totalsettings]% + \setupfieldlabelframed [#labelsettings]% + \setupfieldcontentframed[#fieldsettings]% + \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]\glet\scrn_field_load_scripts\relax} + +\newconditional\fieldlabelshown +\newconditional\fieldframeshown +\newconditional\fieldisvertical +\newconditional\fieldishorizontal + +\permanent\tolerant\protected\def\field[#tag]#spacer[#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}}% + \ifempty\currentfieldlabel + \let\currentfieldlabel\currentfieldbody + \fi + \ifempty\currentfieldcategory + \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}% + \orelse\ifconditional\fieldishorizontal + \setfieldcontentframedparameter\c!height{\vsize}% + \else + \setfieldcontentframedparameter\c!height{2cm}% + \fi}% + \doifnothing{\fieldcontentframedparameter\c!width} + {\ifconditional\fieldisvertical + \setfieldcontentframedparameter\c!width{\hsize}% + \orelse\ifconditional\fieldishorizontal + \setfieldcontentframedparameter\c!width{20em}% + \else + \setfieldcontentframedparameter\c!width{2cm}% + \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]% + \orelse\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 + \setupfieldtotalframed[\c!n=,\c!before=,\c!after=\vss,\c!style=,\c!color=]} + +%D Common stuff (obsolete) + +\newcount\c_scrn_field_system_n + +\permanent\def\currentsystemfield{sys::\number\c_scrn_field_system_n} + +\permanent\protected\def\nextsystemfield + {\global\advance\c_scrn_field_system_n\plusone} + +%D \CONTEXT\ had tooltips right from the moment that it supported fields. Due to the +%D at that moment somewhat limited \PDF\ specification, they were implemented using +%D \JAVASCRIPT, but nowadays more kind of actions are supported, so we can do +%D without. The \MKIV\ version also supports definition of tooltips and +%D 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 + \frozen\instance\setuevalue\currenttooltip{\scrn_tooltip_direct{\currenttooltip}}% +\to \everydefinetooltip + +\protected\def\scrn_tooltip_direct#tag% + {\def\currenttooltip{#tag}% + \iflocation + \expandafter\scrn_tooltip_indeed + \else + \expandafter\scrn_tooltip_ignore + \fi} + +\tolerant\def\scrn_tooltip_ignore[#settings]#:#anchortext#tiptext% + {#anchortext} + +\tolerant\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}}% + \orelse\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 + \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 fieldstacks are used so we +%D 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} + +\permanent\tolerant\protected\def\definefieldstack[#tag]#spacer[#symbols]#spacer[#settings]% + {\ifcsname\??fieldstack#tag\endcsname + % already done + \else + %setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}% + \setxvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][\normalunexpanded{#settings}]}% + \fi} + +\permanent\tolerant\protected\def\fieldstack[#tag]#spacer[#symbols]#spacer[#settings]% + {\ifparameter#symbols\or + \scrn_fieldstack_define[#tag][#symbols][#settings]% + \fi + \csname\??fieldstack#tag\endcsname} + +\newbox\b_scrn_fieldstack_box + +\definesymbol[\s!empty][] + +\def\scrn_fieldstack_add#tag#settings#symbol% + {\advance\scratchcounter\plusone + \edef\currentfieldstackname{#tag:\number\scratchcounter}% + \ifnum\scratchcounter=\fieldcategoryparameter\c!start\relax + \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default={#symbol}]% + \else + \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default=\s!empty]% + \fi + \setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}% + \setcollector + [fieldstack] + {\fieldbody + [\currentfieldstackname] + [\c!option={\v!readonly}, + \c!width=\wd\b_scrn_fieldstack_box, + \c!height=\ht\b_scrn_fieldstack_box, + \c!depth=\dp\b_scrn_fieldstack_box, + #settings]}} + +\protected\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 + +\permanent\tolerant\protected\def\overlayrollbutton[#1]#*[#2]#;#=#=% + {\iflocation + \bgroup + \global\advance\c_scrn_rollbutton_n_button\plusone + \global\advance\c_scrn_rollbutton_n_symbol\plusone + \definesymbol + [rollsymbol:\number\c_scrn_rollbutton_n_symbol] + [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]% + % \definefieldbody + % [rollbutton:\number\c_scrn_rollbutton_n_button] + % [\c!type=push, + % \c!values=rollsymbol:\number\c_scrn_rollbutton_n_symbol, + % \c!default=rollsymbol:\number\c_scrn_rollbutton_n_symbol]% + % \fitfield + % [rollbutton:\number\c_scrn_rollbutton_n_button]% + % [\c!regionin={#regionin}, + % \c!regionout={#regionout}]% + % + \definefield + [rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton] + [rollsymbol:\number\c_scrn_rollbutton_n_symbol]% + \fitfield + [rollbutton:\number\c_scrn_rollbutton_n_button]% + [\c!regionin={#1#3},\c!regionout={#2#4}]% + % + \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 + +\permanent\tolerant\protected\def\definepushbutton[#tag]#spacer[#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} + +\permanent\tolerant\protected\def\definepushsymbol[#tag]#spacer[#variant]% [#reference] + {\definesymbol[pushsymbol:#tag:#variant]} + +\permanent\tolerant\def\pushbutton[#tag]#spacer[#variant]% + {\executeifdefined{pushbutton:#tag}\gobbleoneargument{#variant}} + +%D We plug into the menu system + +\permanent\permanent\protected\def\scrn_menu_psh_start[#reference]#text\stoppsh + {\starttxt\pushbutton[\currentinteractionmenu][#reference]\stoptxt} + +\permanent\permanent\protected\def\scrn_menu_psh_direct[#reference]#text\\ + {\scrn_menu_psh_start[#reference]\stoprob} + +\aliased\let\stoppsh\relax + +\appendtoks + \enforced\let\startpsh\scrn_menu_psh_start + \enforced\let\stoppsh \relax + \enforced\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 + +\permanent\def\lastrollbuttonindex{\the\c_scrn_rollbutton_n_button} + +\setupfield + [rollbutton] + [\c!frame=\v!off, + \c!offset=\v!overlay] + +\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} + +\permanent\tolerant\protected\def\rollbutton[#tag]#spacer[#settings]#:#text[#reference]% + {\dontleavehmode + \bgroup + \global\advance\c_scrn_rollbutton_n_button\plusone + \global\advance\c_scrn_rollbutton_n_symbol\plusone + \ifparameter#tag\or + \ifparameter#settings\or + \edef\currentinteractionmenu{#tag}% + \setupcurrentinteractionmenu[#settings]% + \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m + \orelse\ifhastok={#tag}% + \let\currentbutton\empty + \setupcurrentbutton[#tag]% + \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b + \else + \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 (maybe \unique...) + \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}{#text}]% + \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}{#text}]% + \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}{#text}]% + \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]% + [\c!clickout={#reference}]% + \egroup} + +\protected\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 + +\permanent\protected\def\scrn_menu_rob_start[#reference]#text\stoprob + {\starttxt\rollbutton[\currentinteractionmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt} + +\permanent\protected\def\scrn_menu_rob_direct[#reference]#text\\ + {\scrn_menu_rob_start[#reference]#text\stoprob} + +\aliased\let\stoprob\relax + +\appendtoks + \enforced\let\startrob\scrn_menu_rob_start + \enforced\let\stoprob \relax + \enforced\let\rob \scrn_menu_rob_direct +\to \everysetmenucommands + +\protect \endinput diff --git a/tex/context/base/mkxl/scrn-hlp.mklx b/tex/context/base/mkxl/scrn-hlp.mklx new file mode 100644 index 000000000..ad50486a3 --- /dev/null +++ b/tex/context/base/mkxl/scrn-hlp.mklx @@ -0,0 +1,162 @@ +%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 how often it is used, +%D we'll keep it around. However, it is upgraded and usage has changed a bit. We +%D also use some \LUA\ magic in order to avoid multiple passes. + +\registerctxluafile{scrn-hlp}{} + +%D Using help boils down to plugging the placement macro 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 that might change at +%D 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 + \frozen\instance\setuevalue \currenthelp {\scrn_help_argument{\currenthelp}}% + \frozen\instance\setuevalue{\e!start\currenthelp}{\scrn_help_start {\currenthelp}}% + \frozen\instance\setuevalue{\e!stop \currenthelp}{\scrn_help_stop }% +\to \everydefinehelp + +\protected\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} + +\protected\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}} + +\protected\def\scrn_help_stop + {\iflocation + \scrn_help_register{\getbuffer[\currenthelp]}% + \fi} + +\def\scrn_help_register#text% + {\setbox\b_scrn_help_box\hbox{\inheritedhelpframed{#text}}% \hpack ? + \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} + +\permanent\protected\def\doifelsehelp + {\ifcase\c_scrn_help_n + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifhelpelse\doifelsehelp + +\permanent\protected\def\placehelp % was \helpdata + {\ifinpagebody\ifcase\c_scrn_help_n\else + \clf_collecthelp\normalpagebox + \fi\fi} + +\permanent\def\helpreference#category{\clf_helpreference{#category}} % could be public implementors +\permanent\def\helpaction #category{\clf_helpaction {#category}} % could be public implementors + +\permanent\protected\def\helpsignal#category% + {\hbox attr \helpattribute \helpreference{#category}{}} + +\permanent\protected\def\showhelp#target[#category]% + {\goto{\helpsignal{#category}#target}[#category]} + +\definehelp[\v!helptext] + +\protect \endinput diff --git a/tex/context/base/mkxl/scrn-ini.mklx b/tex/context/base/mkxl/scrn-ini.mklx new file mode 100644 index 000000000..aef9bb33e --- /dev/null +++ b/tex/context/base/mkxl/scrn-ini.mklx @@ -0,0 +1,254 @@ +%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}{} + +%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 + \orelse\ifx\currentinteraction\previousinteraction + \checkinteractionstate + \fi +\to \everysetupinteraction + +\permanent\protected\def\checkinteractionstate + {\doifelse{\interactionparameter\c!state}\v!start + {\locationtrue \setsystemmode \v!interaction}% + {\locationfalse \resetsystemmode\v!interaction}} + +\permanent\def\doifelselocation % expandable + {\iflocation + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\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 +% interactions so 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 +% +% \protected\def\scrn_interaction_direct#1% +% {\edef\currentinteraction{#1}} +% +% \protected\def\scrn_interaction_start#1% +% {\pushmacro\currentinteraction +% \edef\currentinteraction{#1}} +% +% \protected\def\scrn_interaction_stop +% {\popmacro\currentinteraction} +% +% \protected\def\setinteraction[#1]% +% {\def\currentinteraction{#1}} +% +% \defineinteraction[\v!interaction] + +\permanent\protected\def\startinteraction[#1]% + {\pushmacro\currentinteraction + \edef\currentinteraction{#1}} + +\permanent\protected\def\stopinteraction + {\popmacro\currentinteraction} + +\permanent\protected\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. + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\setlocationcolor {\setlocationcolorspecified \referencepagestate} +\permanent\protected\def\setlocationattributes{\setlocationattributesspecified\referencepagestate} +\permanent\protected\def\setlocationcolorspec {\setlocationcolorspecspecified \referencepagestate} + +\permanent\protected\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} + +\newconditional\c_scrn_identity_preroll + +\installtexdirective + {interaction.identity.preroll} + {\settrue \c_scrn_identity_preroll} + {\setfalse\c_scrn_identity_preroll} + +\def\scrn_identity_prerolled#1% + {\begingroup + \edef\tempstring{\interactionparameter#1}% + \ifx\tempstring\empty + \endgroup + \else + \the\everypreroll + \nodestostring\tempstring{\tempstring}% + \normalexpanded{\endgroup\setexpandedinteractionparameter{#1}{\tempstring}}% + \fi} + +\def\scrn_identity_synchronize + {\begingroup + \ifconditional\c_scrn_identity_preroll + \scrn_identity_prerolled\c!title + \scrn_identity_prerolled\c!subtitle + \scrn_identity_prerolled\c!author + \scrn_identity_prerolled\c!date + \scrn_identity_prerolled\c!keyword + \fi + \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 + \endgroup} + +\appendtoks + \scrn_identity_synchronize +\to \everysetupinteraction + +% this comes before starttext + +\def\scrn_identity_document#1#2% + {\doifdocumentvariable{metadata:#1}{\setupinteraction[#2=\documentvariable{metadata:#1}]}} + +\appendtoks % not interfaced i.e. english + \scrn_identity_document {title}\c!title + \scrn_identity_document {subject}\c!subtitle + \scrn_identity_document{subtitle}\c!subtitle + \scrn_identity_document {author}\c!author + \scrn_identity_document {authors}\c!author + \scrn_identity_document {keyword}\c!keyword + \scrn_identity_document{keywords}\c!keyword + \scrn_identity_document {date}\c!date +\to \everystartdocument % or stop + +\setupinteraction + [\c!title=, + \c!subtitle=, + \c!author=, + \c!keyword=, + \c!date=] + +\protect \endinput diff --git a/tex/context/base/mkxl/scrn-pag.mklx b/tex/context/base/mkxl/scrn-pag.mklx new file mode 100644 index 000000000..ef3923f56 --- /dev/null +++ b/tex/context/base/mkxl/scrn-pag.mklx @@ -0,0 +1,310 @@ +%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}{} + +\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 + \orelse\ifx\currentinteractionscreenwidth\v!fit + \donefalse + \global\canvaswidth\dimexpr + \leftcombitotal + + \makeupwidth + + \rightcombitotal + + 2\dimexpr + \interactionscreenparameter\c!backspace + + \interactionscreenparameter\c!horoffset + \relax + \relax + \orelse\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 + \ifx\currentinteractionscreenheight\v!max + \global\canvasheight\printpaperheight + \orelse\ifx\currentinteractionscreenheight\v!fit + \donefalse + \global\canvasheight\dimexpr + \topheight + + \topdistance + + \makeupheight + + \bottomdistance + + \bottomheight + + 2\dimexpr + \interactionscreenparameter\c!topspace + + \interactionscreenparameter\c!veroffset + \relax + \relax + \orelse\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 + \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 + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed +\to \everysetuplayout + +\appendtoks + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed +\to \everysetuplayouttarget + +\def\scrn_canvas_synchronize_only + {\clf_setupcanvas + paperwidth \printpaperwidth + paperheight \printpaperheight + \relax} + +\def\scrn_canvas_synchronize_set#width#height% + {\clf_setupcanvas + paperwidth \dimexpr#width\relax + paperheight \dimexpr#height\relax + \relax} + +\let\scrn_canvas_synchronize_reset\scrn_canvas_synchronize_only + +\def\scrn_canvas_synchronize_simple_indeed + {\scrn_canvas_synchronize_only + %\glet\scrn_canvas_synchronize_simple \relax + \glet\scrn_canvas_synchronize_complex\relax} + +\def\scrn_canvas_synchronize_complex_indeed + {\scrn_canvas_calculate % otherwise we need to hook it into setuppage etc + \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 + copies \numexpr\interactionscreenparameter\c!copies\relax + print {\interactionscreenparameter\c!print}% + \relax + %\glet\scrn_canvas_synchronize_simple \relax + \glet\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 + \orelse\ifx\p_option\v!fit + \global\settrue \c_scrn_canvas_tight_page + \else + \global\setfalse\c_scrn_canvas_tight_page + \fi + \endgroup +\to \everysetupinteractionscreen + +\setupinteractionscreen + [\c!width=\printpaperwidth, + \c!height=\printpaperheight, + \c!horoffset=\zeropoint, + \c!veroffset=\zeropoint, + \c!backspace=\backspace, + \c!topspace=\topspace, + \c!copies=\plusone, % not the best place but backend anyway + \c!option=\v!auto] + +\appendtoks + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed +\to \everysetupinteractionscreen + +%D Conditional page breaks: + +\permanent\tolerant\protected\def\screen[#list]% + {\iflocation + \page[#list]% + \fi} + +%D Page transitions: + +\let\scrn_transitions_list\empty + +\permanent\tolerant\protected\def\setuppagetransitions[#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/tex/context/base/mkxl/scrn-ref.mklx b/tex/context/base/mkxl/scrn-ref.mklx new file mode 100644 index 000000000..df395e550 --- /dev/null +++ b/tex/context/base/mkxl/scrn-ref.mklx @@ -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}{} + +\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_setreferencelinkmethod{\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/tex/context/base/mkxl/scrn-wid.mklx b/tex/context/base/mkxl/scrn-wid.mklx new file mode 100644 index 000000000..40bf95cf5 --- /dev/null +++ b/tex/context/base/mkxl/scrn-wid.mklx @@ -0,0 +1,744 @@ +%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}{} + +% 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). + +% hack: x\footnote{x\inleftmargin[scope=local]{\attachment[location=high,file=i-context.pdf]}}x + +% 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 + +\aliased\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=\emwidth, + \c!width=\v!fit, + \c!height=\v!fit, + \c!depth=\v!fit, + \c!location=\v!high] + +\permanent\tolerant\protected\def\registerattachment[#tag]#spacer[#settings]% we save (globally) at the lua end + {\ifarguments\else + \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}% + mimetype {\attachmentparameter\c!type}% + \relax + \endgroup + \fi} + +\appendtoks + \frozen\instance\setuevalue \currentattachment {\scrn_attachment_direct[\currentattachment]}% + \frozen\instance\setuevalue{\e!start\currentattachment}{\scrn_attachment_start [\currentattachment]}% + \frozen\instance\setuevalue{\e!stop \currentattachment}{\scrn_attachment_stop }% +\to \everydefineattachment + +\permanent\tolerant\protected\def\scrn_attachment_direct[#tag]#spacer[#registered]#spacer[#settings]% + {\iflocation + \bgroup + \edef\currentattachment{#tag}% + \ifcstok{\attachmentparameter\c!state}\v!start + \iftok{#registered}\emptytoks + \scrn_attachment_inject[\v!auto][]% + \orelse\ifhastok={#registered}% + \scrn_attachment_inject[\v!auto][#registered]% + \else + \scrn_attachment_inject[#registered][#settings]% + \fi + \fi + \egroup + \fi} + +\tolerant\protected\def\scrn_attachment_start[#tag]#spacer[#registered]#spacer[#settings]% + {\edef\currentattachment{#tag}% + \unless\iflocation + \expandafter\scrn_attachment_start_ignore + \orelse\ifcstok{\attachmentparameter\c!state}\v!start + \expandafter\scrn_attachment_start_indeed + \else + \expandafter\scrn_attachment_start_ignore + \fi[#registered][#settings]} + +\protected\def\scrn_attachment_stop + {} + +\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 \c_attr_colormodel + 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}% + mimetype {\attachmentparameter\c!type}% + \relax + \wd\b_scrn_attachment_link\currentattachmentwidth + \ht\b_scrn_attachment_link\currentattachmentheight + \dp\b_scrn_attachment_link\currentattachmentdepth + \expandnamespaceparameter\??attachmentlocation\attachmentparameter\c!location\s!unknown} + +\setvalue{\??attachmentmethod\v!hidden}% + {\clf_insertattachment + tag {\currentattachment}% + registered {\currentattachmentregistered}% + method {\v!hidden}% + title {\attachmentparameter\c!title}% + subtitle {\attachmentparameter\c!subtitle}% + author {\attachmentparameter\c!author}% + file {\attachmentparameter\c!file}% + name {\attachmentparameter\c!name}% + buffer {\attachmentparameter\c!buffer}% + mimetype {\attachmentparameter\c!type}% + \relax} + +\protected\def\scrn_attachment_flush_traced + {\hpack\bgroup + \blackrule % can be a fast one + [ \c!color=trace:r, + \c!width=\wd\b_scrn_attachment_link, + \c!height=\ht\b_scrn_attachment_link, + \c!depth=\dp\b_scrn_attachment_link]% + \kern-\wd\b_scrn_attachment_link + \box\b_scrn_attachment_link + \egroup} + +\protected\def\scrn_attachment_flush_normal + {\box\b_scrn_attachment_link} + +\installtextracker + {attachments.anchors} + {\let\scrn_attachment_flush\scrn_attachment_flush_traced} + {\let\scrn_attachment_flush\scrn_attachment_flush_normal} + +\let\scrn_attachment_flush\scrn_attachment_flush_normal + +\setvalue{\??attachmentlocation\v!inmargin }{\inmargin {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin{\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!high }{\high {\scrn_attachment_flush}} + +\setvalue{\??attachmentlocation\v!none}% + {\global\setbox\b_scrn_attachment_collect\hbox\bgroup + \ifvoid\b_scrn_attachment_collect\else + \box\b_scrn_attachment_collect + \hskip\attachmentparameter\c!distance\relax + \fi + \scrn_attachment_flush + \egroup} + +\setvalue{\??attachmentlocation\s!unknown}% + {\ifvoid\b_scrn_attachment_collect\else + \box\b_scrn_attachment_collect + \fi} + +\permanent\protected\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: + +\permanent\tolerant\protected\def\useattachment[#tag]#spacer[#title]#spacer[#name]#spacer[#file]% + {\ifarguments\or + \registerattachment[#tag][title=#tag,name=#tag,file=#tag]% + \or + \registerattachment[#tag][title=#title,name=#title,file=#title]% + \or + \registerattachment[#tag][title=#title,name=#title,file=#name]% + \or + \registerattachment[#tag][title=#title,name=#name,file=#file]% + \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=Help] +% 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 + +%D The implementation is mostly the same as for attachments but sharing code +%D will not make it cleaner. + +\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=\emwidth, + \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!buffer=\v!comment, + \c!location=\v!high] + +\appendtoks + \frozen\instance\setuevalue \currentcomment {\scrn_comment_argument[\currentcomment]}% + \frozen\instance\setuevalue{\e!start\currentcomment}{\scrn_comment_start [\currentcomment]}% + \frozen\instance\setuevalue{\e!stop \currentcomment}{\scrn_comment_stop }% +\to \everydefinecomment + +\tolerant\protected\def\scrn_comment_argument[#category]#spacer[#title]#spacer[#settings]#:#text%% + {\iflocation + \def\currentcomment{#category}% + \ifcstok{\commentparameter\c!state}\v!start + \ifhastok={#title} + \setupcurrentcomment[#title]% + \else + \setupcurrentcomment[\c!title=#title,#settings]% + \fi + \clf_assignbuffer{\v!comment}{#text}\catcodetable\relax% todo: expansion control, but expanded by default (xml) + \scrn_comment_inject + \fi + \fi + \ignorespaces} + +\tolerant\protected\def\scrn_comment_start[#category]#spacer[#title]#spacer[#settings]% + {\def\currentcomment{#category}% + \unless\iflocation + \expandafter\scrn_comment_start_ignore + \orelse\ifcstok{\commentparameter\c!state}\v!start + \expandafter\scrn_comment_start_indeed + \else + \expandafter\scrn_comment_start_ignore + \fi[#title][#settings]} + +\def\scrn_comment_start_indeed[#title][#settings]% + {\bgroup + \doifelseassignment{#title} + {\setupcurrentcomment[#title]} + {\setupcurrentcomment[\c!title=#title,#settings]}% + \protected\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} + +\protected\def\scrn_comment_stop + {} + +\installcorenamespace{commentmethods} + +\protected\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 }% + \ifempty\currentcommentsymbol + \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 \c_attr_colormodel + colorvalue \numexpr\thecolorattribute{\commentparameter\c!color}\relax + transparencyvalue \numexpr\thetransparencyattribute{\commentparameter\c!color}\relax + option {\commentparameter\c!option}% % todo + symbol {\commentparameter\c!symbol}% + buffer {\commentparameter\c!buffer}% {\v!comment}% + layer {\commentparameter\c!textlayer}% + space {\commentparameter\c!space}% + \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} + +\letvalue{\??commentmethods\v!hidden}\donothing + +\protected\def\scrn_comment_flush_traced + {\hpack\bgroup + \blackrule % can be a fast one + [ \c!color=trace:y, + \c!width=\wd\b_scrn_comment_link, + \c!height=\ht\b_scrn_comment_link, + \c!depth=\dp\b_scrn_comment_link]% + \kern-\wd\b_scrn_comment_link + \box\b_scrn_comment_link + \egroup} + +\protected\def\scrn_comment_flush_normal + {\box\b_scrn_comment_link} + +\installtextracker + {comments.anchors} + {\let\scrn_comment_flush\scrn_comment_flush_traced} + {\let\scrn_comment_flush\scrn_comment_flush_normal} + +\let\scrn_comment_flush\scrn_comment_flush_normal + +% todo: dedicated margin classes + +\setvalue{\??commentlocation\v!inmargin }{\inmargin {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\scrn_comment_flush}} +\setvalue{\??commentlocation\v!high }{\high {\scrn_comment_flush}} + +\setvalue{\??commentlocation\v!none}% + {\global\setbox\b_scrn_comment_collect\hbox\bgroup + \ifvoid\b_scrn_comment_collect\else + \box\b_scrn_comment_collect + \hskip\commentparameter\c!distance\relax + \fi + \scrn_comment_flush + \egroup} + +\setvalue{\??commentlocation\s!unknown}% + {\ifvoid\b_scrn_comment_collect\else + \box\b_scrn_comment_collect + \fi} + +\permanent\protected\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=] + +\permanent\tolerant\protected\def\useexternalsoundtrack[#tag]#spacer[#filename]% + {\clf_registersoundclip + tag {#tag}% + file {#filename}% + \relax} + +\permanent\def\checksoundtrack#tag% yet untested in mkiv (also move management to lua) + {\iflocation + \clf_insertsoundclip + tag {#tag}% + repeat {\directexternalsoundtracksparameter\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. Probaly by that time this feature is dropped (as are other media +% rel;ated ones). + +\let\currentrendering\empty + +\definereference[StartCurrentRendering] [\v!StartRendering {\currentrendering}] +\definereference[StopCurrentRendering] [\v!StopRendering {\currentrendering}] +\definereference[PauseCurrentRendering] [\v!PauseRendering {\currentrendering}] +\definereference[ResumeCurrentRendering][\v!ResumeRendering{\currentrendering}] + +\permanent\tolerant\protected\def\useexternalrendering[#tag]#spacer[#mime]#spacer[#file]#spacer[#option]% + {\clf_registerrendering + type {external}% + label {#tag}% + mime {#mime}% + filename {#file}% + option {#option}% + \relax} + +\permanent\tolerant\protected\def\setinternalrendering[#tag]#spacer[#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}\hpack{\box\nextbox}% + \egroup}% + \hbox} + +\permanent\def\renderingtype #tag{\clf_renderingvar{#tag}{type}} +\permanent\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 + +\permanent\tolerant\protected\def\placerenderingwindow[#window]#spacer[#rendering]% do all in lua + {\bgroup + \edef\currentrendering{\ifparameter#rendering\or#rendering\else#window\fi}% + % create fall back if needed + \edef\currentrenderingwindow{\namedrenderingwindowparameter{#window}\c!width}% stupid test, we need a proper one here + \ifempty\currentrenderingwindow + \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 + \getobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page + \orelse\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 + % todo: + % \handlereferenceactions{\renderingwindowparameter\c!openpageaction }\dosetuprenderingopenpageaction + % \handlereferenceactions{\renderingwindowparameter\c!closepageaction}\dosetuprenderingclosepageaction + \letrenderingwindowparameter\c!offset\v!overlay + \inheritedrenderingwindowframed + {\vfilll + \dontleavehmode + \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\relax +% \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/tex/context/base/mkxl/scrp-ini.mkxl b/tex/context/base/mkxl/scrp-ini.mkxl new file mode 100644 index 000000000..2c3ae2bb6 --- /dev/null +++ b/tex/context/base/mkxl/scrp-ini.mkxl @@ -0,0 +1,109 @@ +%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. + +%D The script handler has been upgraded mid June 2020 so there might be issues as I +%D didn't test everything (yet). It should all be a bit more efficient now in +%D \LUAMETATEX, although not spectacular. We use no attributes in \LUAMETATEX\ and +%D only one in \LUATEX\ now. +%D +%D A glyph can have (an dget) all kind of properties. Except from the state, these +%D are assigned within \TEX's grouping model! +%D +%D \startitemize +%D \startitem font \stopitem +%D \startitem character \stopitem +%D \startitem language (4 properties packed in an unsigned integer) \stopitem +%D \startitem data (used for dynamics) \stopitem +%D \startitem script (used for special script processing) \stopitem +%D \startitem state (used for analyzing, related to font features) \stopitem +%D \stopitemize +%D +%D Additional properties are set via node list handlers. The state is stored in the +%D glyph, but additional properties are stored in a node's property table. In the +%D future the state might get used for something else, in which case we will stire +%D the state in the property table too. On the other hand, we can now (if we want) +%D influence the state at the\TEX\ end (not that we do that yet). + +%D Todo: as in bidi mode we need a way to globally keep the setting. + +\registerctxluafile{scrp-ini}{} +\registerctxluafile{scrp-cjk}{} +\registerctxluafile{scrp-eth}{} +\registerctxluafile{scrp-tha}{} +\registerctxluafile{scrp-tib}{} + +%D Since scripts need specific \LUA\ code we use hard coded attribute values, but we +%D might have more tricks at some time, so we use a proper define macro too. + +\unprotect + +\installcorenamespace{script} + +\installcommandhandler \??script {script} \??script + +\aliased\let\setupscripts\setupscript % be nice + +% presets are global and are currently defined in lua + +% \appendtoks +% \setuevalue\currentscript{\setscript[\currentscript]}% +% \to \everydefinescript + +\permanent\protected\def\setlocalscript[#1]% + {\edef\currentscript{#1}% + \clf_setscript{\currentscript}{\scriptparameter\c!method}{\scriptparameter\c!preset}} + +\permanent\protected\def\setglobalscript[#1]% + {\setlocalscript[#1]% + \pickupscriptattribute} + +\aliased\let\setscript\setlocalscript + +\permanent\protected\def\resetscript + {\clf_resetscript} + +\permanent\protected\def\startscript[#1]% + {\begingroup + \setlocalscript[#1]} + +\permanent\protected\def\stopscript + {\endgroup} + +% \setscript[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 [tibetan] [\c!method=tibetan] + +\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 + \ifempty\currentscript + \doifelse{\scriptparameter\s!features}\v!auto\enableautofontscript\disableautofontscript + \fi +\to \everysetupscript + +\permanent\protected\def\enableautofontscript {\clf_enableautofontscript } % can be public implementor +\permanent\protected\def\disableautofontscript{\clf_disableautofontscript} % can be public implementor + +\definefontfeature[latn][script=latn] +\definefontfeature[grek][script=grek] + +\protect \endinput diff --git a/tex/context/base/mkxl/sort-ini.mkxl b/tex/context/base/mkxl/sort-ini.mkxl new file mode 100644 index 000000000..d9f9628d5 --- /dev/null +++ b/tex/context/base/mkxl/sort-ini.mkxl @@ -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}{} +\registerctxluafile{sort-lan}{} + +\endinput diff --git a/tex/context/base/mkxl/spac-ali.mkxl b/tex/context/base/mkxl/spac-ali.mkxl new file mode 100644 index 000000000..88bdd44eb --- /dev/null +++ b/tex/context/base/mkxl/spac-ali.mkxl @@ -0,0 +1,1243 @@ +%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 {flush*} +%D variants. Starting at the last day of 2011 both methods are merged into one and +%D caching has been added, which makes switching twice as fast. + +\registerctxluafile{spac-ali}{optimize} + +\definesystemattribute[realign] [public] % might be combined with the next one +\definesystemattribute[alignstate][public] % will make a single attributes for several states + +\appendtoks + \c_attr_realign \attributeunsetvalue + \c_attr_alignstate\attributeunsetvalue +\to \everyforgetall + +\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue} +\permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo} +\permanent\protected\def\signalouterrealign{\clf_setrealign\plusone} + +\installcorenamespace{aligncommand} +\installcorenamespace{alignhorizontal} +\installcorenamespace{alignvertical} + +% \installcorenamespace{alignmentnormalcache} +% \installcorenamespace{alignmentraggedcache} + +% nasty hack: + +\installcorenamespace{alignmentnormalcacheodd} +\installcorenamespace{alignmentnormalcacheeven} + +\installcorenamespace{alignmentraggedcacheodd} +\installcorenamespace{alignmentraggedcacheeven} + +\immutable\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi} +\immutable\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi} + +\newtoks\everyresetalign % todo + +% This will become a more advanced layout controller soon: + +\newconditional\layoutlefttoright \settrue\layoutlefttoright +\newconditional\displaylefttoright \settrue\displaylefttoright +\newconditional\inlinelefttoright \settrue\inlinelefttoright + +\permanent\protected\def\lefttoright + {\ifvmode + \spac_directions_lefttoright_vmode + \else + \spac_directions_lefttoright_hmode + \fi} + +\permanent\protected\def\righttoleft + {\ifvmode + \spac_directions_righttoleft_vmode + \else + \spac_directions_righttoleft_hmode + \fi} + +\protected\def\spac_directions_lefttoright_vmode + {\settrue\displaylefttoright + \settrue\inlinelefttoright + \textdirection\directionlefttoright + \pardirection \directionlefttoright} + +\protected\def\spac_directions_righttoleft_vmode + {\setfalse\displaylefttoright + \setfalse\inlinelefttoright + \textdirection\directionrighttoleft + \pardirection \directionrighttoleft} + +\protected\def\spac_directions_lefttoright_hmode + {\linedirection\directionlefttoright % linedir keeps subtype of skip + \settrue\inlinelefttoright} + +\protected\def\spac_directions_righttoleft_hmode + {\linedirection\directionrighttoleft % linedir keeps subtype of skip + \setfalse\inlinelefttoright} + +\permanent\protected\def\synchronizelayoutdirection + {\ifconditional\layoutlefttoright + \spac_directions_synchronize_lr + \else + \spac_directions_synchronize_rl + \fi} + +\permanent\protected\def\synchronizedisplaydirection + {\ifconditional\displaylefttoright + \spac_directions_synchronize_lr + \else + \spac_directions_synchronize_rl + \fi} + +\def\spac_directions_synchronize_lr + {\settrue\inlinelefttoright + \textdirection\directionlefttoright + \pardirection \directionlefttoright} + +\def\spac_directions_synchronize_rl + {\setfalse\inlinelefttoright + \textdirection\directionrighttoleft + \pardirection \directionrighttoleft} + +\permanent\protected\def\synchronizeinlinedirection + {% why not \linedirection here + \textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi} + +\permanent\protected\def\checkedlefttoright + {\ifvmode + \spac_directions_lefttoright_vmode + \else + \spac_directions_lefttoright_hmode_checked + \fi} + +\permanent\protected\def\checkedrighttoleft + {\ifvmode + \spac_directions_righttoleft_vmode + \else + \spac_directions_righttoleft_hmode_checked + \fi} + +\protected\def\spac_directions_lefttoright_hmode_checked + {\ifconditional\inlinelefttoright\else + \lefttoright + \fi} + +\protected\def\spac_directions_righttoleft_hmode_checked + {\ifconditional\inlinelefttoright + \righttoleft + \fi} + +\installcorenamespace{bidi} + +\letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright +\letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft + +\permanent\protected\def\usebidiparameter#1% + {\begincsname\??bidi#1\c!bidi\endcsname} + +\permanent\protected\def\showdirections + {\dontleavehmode + \begingroup\infofont\textdirection\directionlefttoright[\space + layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space + display: \ifconditional\displaylefttoright l2r\else r2l\fi\space + inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space + ]\endgroup} + +\permanent\protected\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \aliased\let\rtlhbox\righttolefthbox +\permanent\protected\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \aliased\let\ltrhbox\lefttorighthbox +\permanent\protected\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \aliased\let\rtlvbox\righttoleftvbox +\permanent\protected\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \aliased\let\ltrvbox\lefttorightvbox +\permanent\protected\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \aliased\let\rtlvtop\righttoleftvtop +\permanent\protected\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \aliased\let\ltrvtop\lefttorightvtop + +\permanent\protected\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next} +\permanent\protected\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox +\permanent\protected\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop + +\permanent\protected\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi} +\permanent\protected\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi} +\permanent\protected\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi} + +% Tolerance and hyphenation + +\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{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi} + +\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered + {\ifnum\tolerance<\c_spac_tolerance_minimum + \tolerance\c_spac_tolerance_minimum % small values have unwanted side effects + \else + % 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 + %\else + % no need to do something as we're in \nohyphens + \fi} + +\protected\def\spac_align_set_tolerant + {\tolerance\c_spac_tolerance_normal} + +\protected\def\spac_align_set_very_tolerant + {\tolerance\c_spac_tolerance_extreme} + +\protected\def\spac_align_set_stretch + {\emergencystretch\bodyfontsize} + +\protected\def\spac_align_set_extreme_stretch + {\emergencystretch10\bodyfontsize} + +% Vertical + +\newconstant\c_spac_align_state_vertical + +\protected\def\spac_align_set_vertical_none + {\enforced\let\raggedtopcommand \relax + \enforced\let\raggedbottomcommand\relax} + +\protected\def\spac_align_set_vertical_lohi + {\enforced\let\raggedtopcommand \vfilll + \enforced\let\raggedbottomcommand\vfilll} + +\protected\def\spac_align_set_vertical_low + {\enforced\let\raggedtopcommand \vfilll + \enforced\let\raggedbottomcommand\relax} + +\protected\def\spac_align_set_vertical_high + {\enforced\let\raggedtopcommand \relax + \enforced\let\raggedbottomcommand\vfilll} + +\def\spac_align_flush_vertical + {\ifcase\c_spac_align_state_vertical + \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_hard {\plusone fill} +\def\v_spac_align_fill_amount_extreme {\plustenthousand filll} +\def\v_spac_align_fill_amount_negative {\minusone fil} +\def\v_spac_align_fill_amount_double {\plustwo fil} +\def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key +\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 + +\permanent\protected\def\spac_align_set_horizontal_none % should also relax \updateraggedskips + {\raggedstatus \zerocount + \c_attr_alignstate\attributeunsetvalue + \leftskip \plusone\leftskip + \rightskip \plusone\rightskip + \spaceskip \zeropoint + \xspaceskip \zeropoint + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_one_fil % new + \setfalse \raggedonelinerstate % now here + \let\updateraggedskips\relax} % no need for adaption + +\permanent\protected\def\spac_align_set_horizontal_left + {\setraggedness \spac_align_set_raggedness_left + \raggedstatus \plusone + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_center + {\setraggedness \spac_align_set_raggedness_middle + \raggedstatus \plustwo + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_right + {\setraggedness \spac_align_set_raggedness_right + \raggedstatus \plusthree + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_one_fil + %\parindent \parindent + \relax} + +\permanent\protected\def\spac_align_set_horizontal_very_left + {\raggedstatus \plusone + \c_attr_alignstate\plusone + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount + \rightskip \plusone\rightskip\s!plus\zeropoint + \spaceskip \v_spac_align_space_amount + \xspaceskip \v_spac_align_space_amount_x + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_very_center + {\raggedstatus \plustwo + \c_attr_alignstate\plustwo + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount + \spaceskip \v_spac_align_space_amount + \xspaceskip \v_spac_align_space_amount_x + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_very_right + {\raggedstatus \plusthree + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + %\parindent \parindent + \relax} + +\permanent\protected\def\spac_align_set_horizontal_wide_center + {\setraggedness \spac_align_set_raggedness_middle + \raggedstatus \plustwo + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_centered_last_line + {\raggedstatus \zerocount + \c_attr_alignstate\attributeunsetvalue + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax + \spaceskip \zeropoint\relax + \xspaceskip \zeropoint\relax + \parfillleftskip \zeropoint + \parfillskip \zeropoint\s!plus\v_spac_align_fill_amount_double\relax + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_flushedright_last_line + {\raggedstatus \zerocount + \c_attr_alignstate\attributeunsetvalue + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax + \spaceskip \zeropoint\relax + \xspaceskip \zeropoint\relax + \parfillskip \zeropoint + \parfillleftskip \zeropoint\s!plus\v_spac_align_fill_amount_extreme\relax + \parindent \zeropoint + \relax} + +\permanent\protected\def\spac_align_set_horizontal_right_tt % a plain command + {\tttf % brrr + \raggedstatus \plusthree + \c_attr_alignstate\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 + \parfillleftskip \zeropoint + \parfillskip \s_zero_plus_zero + %\parindent \parindent + \relax} + +\permanent\protected\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 + % 8 right aligned last line + \spac_align_set_horizontal_flushedright_last_line + \or + % 9 paragraph + \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 + +\permanent\protected\def\raggedbottom + {\bottomraggednessmode\zerocount + \settopskip} + +\permanent\protected\def\alignbottom + {\bottomraggednessmode\plusone + \settopskip} + +\permanent\protected\def\baselinebottom + {\bottomraggednessmode\plustwo + \settopskip} + +\aliased\let\normalbottom\alignbottom % downward compatible + +\permanent\protected\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 + {\enforced\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}% + \gletcsname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand + \gletcsname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips} + +\def\spac_align_collect#1% + {\csname\??aligncommand#1\endcsname} + +% The local (key driven) setter: + +\permanent\protected\def\spac_align_prepare#1% deferred + {\edef\m_spac_align_asked{#1}% + \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname + \ifx\raggedcommand\relax + \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: + +\permanent\tolerant\protected\def\setupalign[#1]% immediate + {\edef\m_spac_align_asked{#1}% + \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname + \ifx\raggedcommand\relax + \spac_align_add_to_cache + \else + \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align_asked\endcsname + \fi + \raggedcommand} + +\permanent\protected\def\usealignparameter#1% faster local variant + {\edef\m_spac_align_asked{#1\c!align}% + \ifx\m_spac_align_asked\empty\else + \spac_align_use_indeed + \fi} + +\permanent\protected\def\dousealignparameter#1% faster local variant + {\edef\m_spac_align_asked{#1}% + \ifx\m_spac_align_asked\empty\else + \spac_align_use_indeed + \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 + +\protected\def\spac_align_use_later#1% + {\begingroup + \edef\m_spac_align_asked{#1}% + \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname + \ifx\raggedcommand\relax + \spac_align_add_to_cache + \fi + \endgroup} + +\protected\def\spac_align_use_now#1% + {\csname\??alignmentnormalcache#1\endcsname} + +% Maybe we need something different in columns. + +\protected\def\installalign#1#2% beware: commands must be unexpandable! + {\ifcsname\??aligncommand#1\endcsname \else + \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}% + \fi} + +% 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 +% +% \protected\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\plusfour } +\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfive } +\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!end }{\c_spac_align_state_horizontal\pluseight} +\setvalue{\??aligncommand\v!paragraph }{\c_spac_align_state_horizontal\plusnine} + +\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!hangingboth }{\toksapp\t_spac_align_collected{\font_protruding_enable_b}} +\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{\??aligncommand1*\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} + +% a one shot (only usefull in e.g. framed, also needs tolerance and stretch) + +\setvalue{\??aligncommand \v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} +\setvalue{\??aligncommand1*\v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} +\setvalue{\??aligncommand2*\v!more}{\toksapp\t_spac_align_collected{\looseness\plustwo}} + +% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\nopenalties}} +% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\setdefaultpenalties}} + +\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} + +\protected\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 + +\permanent\protected\def\enablereversealignment + {\the\t_spac_every_swap_align + \t_spac_every_swap_align\emptytoks} + +% Visible commands: + +\aliased\let\notragged \spac_align_set_horizontal_none +\aliased\let\raggedleft \spac_align_set_horizontal_left +\aliased\let\raggedcenter \spac_align_set_horizontal_center +\aliased\let\raggedright \spac_align_set_horizontal_right +\aliased\let\veryraggedleft \spac_align_set_horizontal_very_left +\aliased\let\veryraggedcenter \spac_align_set_horizontal_very_center +\aliased\let\veryraggedright \spac_align_set_horizontal_very_right +\aliased\let\raggedwidecenter \spac_align_set_horizontal_wide_center +\aliased\let\centeredlastline \spac_align_set_horizontal_centered_last_line +\aliased\let\flushedrightlastline\spac_align_set_horizontal_flushedright_last_line +\aliased\let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command +\aliased\let\forgetragged \spac_align_set_horizontal_none + +\appendtoks + \spac_align_set_horizontal_none +\to \everyforgetall + +% Box commands. + +\permanent\protected\def\ibox + {\vbox\bgroup + \forgetall + \enforced\let\\\endgraf + \ifdoublesided\signalinnerrealign\fi + \doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left + \let\next} + +\permanent\protected\def\obox + {\vbox\bgroup + \forgetall + \enforced\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) + {\enforced\let\raggedbox\vbox + \processcommacommand[#1]\spac_align_set_ragged_vbox} + +\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used) + {\enforced\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} + +\permanent\protected\def\spac_align_vertical_left {\lbox} +\permanent\protected\def\spac_align_vertical_right {\rbox} +\permanent\protected\def\spac_align_vertical_middle {\cbox} +\permanent\protected\def\spac_align_vertical_inner {\ibox} +\permanent\protected\def\spac_align_vertical_outer {\obox} +\permanent\protected\def\spac_align_vertical_flushleft {\rbox} +\permanent\protected\def\spac_align_vertical_flushright{\lbox} +\permanent\protected\def\spac_align_vertical_center {\cbox} +\permanent\protected\def\spac_align_vertical_no {\vbox\bgroup\spac_align_set_horizontal_right\let\next=} + +\permanent\protected\def\spac_align_horizontal_left {\doalignedline\v!left} +\permanent\protected\def\spac_align_horizontal_right {\doalignedline\v!right} +\permanent\protected\def\spac_align_horizontal_middle {\doalignedline\v!middle} +\permanent\protected\def\spac_align_horizontal_inner {\doalignedline\v!inner} +\permanent\protected\def\spac_align_horizontal_outer {\doalignedline\v!outer} +\permanent\protected\def\spac_align_horizontal_flushleft {\doalignedline\v!right} +\permanent\protected\def\spac_align_horizontal_flushright{\doalignedline\v!left} +\permanent\protected\def\spac_align_horizontal_center {\doalignedline\v!middle} + +\setvalue{\??alignvertical \v!left }{\enforced\let\raggedbox\spac_align_vertical_left} +\setvalue{\??alignvertical \v!right }{\enforced\let\raggedbox\spac_align_vertical_right} +\setvalue{\??alignvertical \v!middle }{\enforced\let\raggedbox\spac_align_vertical_middle} +\setvalue{\??alignvertical \v!inner }{\enforced\let\raggedbox\spac_align_vertical_inner} +\setvalue{\??alignvertical \v!outer }{\enforced\let\raggedbox\spac_align_vertical_outer} +\setvalue{\??alignvertical \v!flushleft }{\enforced\let\raggedbox\spac_align_vertical_flushleft } +\setvalue{\??alignvertical \v!flushright}{\enforced\let\raggedbox\spac_align_vertical_flushright} +\setvalue{\??alignvertical \v!center }{\enforced\let\raggedbox\spac_align_vertical_center} +\setvalue{\??alignvertical \v!no }{\enforced\let\raggedbox\spac_align_vertical_no} + +\setvalue{\??alignhorizontal\v!left }{\enforced\let\raggedbox\spac_align_horizontal_left} +\setvalue{\??alignhorizontal\v!right }{\enforced\let\raggedbox\spac_align_horizontal_right} +\setvalue{\??alignhorizontal\v!middle }{\enforced\let\raggedbox\spac_align_horizontal_middle} +\setvalue{\??alignhorizontal\v!inner }{\enforced\let\raggedbox\spac_align_horizontal_inner} +\setvalue{\??alignhorizontal\v!outer }{\enforced\let\raggedbox\spac_align_horizontal_outer} +\setvalue{\??alignhorizontal\v!flushleft }{\enforced\let\raggedbox\spac_align_horizontal_flushleft} +\setvalue{\??alignhorizontal\v!flushright}{\enforced\let\raggedbox\spac_align_horizontal_flushright} +\setvalue{\??alignhorizontal\v!center }{\enforced\let\raggedbox\spac_align_horizontal_center} + +% The next one can be in use so we keep it around but oen should +% be aware of possible interference. + +\permanent\protected\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall) + {\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% + \updateraggedskips} + +\permanent\def\dosetraggedskips#1#2#3#4#5#6#7% + {\raggedstatus #1\relax + \leftskip 1\leftskip \s!plus#2\relax + \rightskip 1\rightskip\s!plus#3\relax + \spaceskip #4\relax + \xspaceskip #5\relax + \parfillskip \zeropoint\s!plus#6\relax + \parindent #7\relax + \c_attr_alignstate\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi} + +% older (context) names: + +\aliased\let\spaceamount \interwordspace +\aliased\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} + +\permanent\protected\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 \automatichyphenpenalty \explicithyphenpenalty + \displaywidowpenalty \widowpenalty \clubpenalty \brokenpenalty + \doublehyphendemerits \finalhyphendemerits \adjdemerits + \relax}% + \dontleavehmode + \begingroup + \inleftmargin{\vsmash{\infofont\framed[\c!align=\v!right]{\thepardata}}}% + \endgroup + \let\showpardata\relax} + +\permanent\protected\def\startshowpardata + {\begingroup + \showstruts + \tracingparagraphs\maxdimen + \appendtoksonce\showpardata\to\everypar} + +\permanent\protected\def\stopshowpardata + {\endgraf + \endgroup} + +% Structure: + +\protected\def\startalignment + {\par + \begingroup + \setupalign} + +\protected\def\stopalignment + {\par + \endgroup} + +\setnewconstant\alignstrutmode\plusone + +% see later for the real definition, which in the simple case is: + +\newtoks \everyleftofalignedline +\newtoks \everyrightofalignedline + +\permanent\protected\def\shiftalignedline#1#2#3#4% left, right, inner, outer + {\rightorleftpageaction + {\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}% + \everyrightofalignedline{\hskip\dimexpr#2+#4\relax}} + {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}% + \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}} + +\permanent\def\doalignline#1#2% \\ == newline + {\noindentation % was \noindent + \dontleavehmode % added in marrakesch at TUG 2006\begingroup + \begingroup + \setlocalhsize % new + \enforced\permanent\protected\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 \permanent\def\line {\hbox to\hsize} \fi +\ifdefined\leftline \else \permanent\def\leftline #1{\line{#1\hss}} \fi +\ifdefined\rightline \else \permanent\def\rightline #1{\line{\hss#1}} \fi +\ifdefined\centerline \else \permanent\def\centerline#1{\line{\hss#1\hss}} \fi + +% direct commands + +\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% + {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi} + +\permanent\tolerant\protected\def\startlinealignment[#1]% + {\spac_align_wrapper_handle{#1}% + \bgroup\ignorespaces} + +\protected\def\spac_align_wrapper_stop + {\removeunwantedspaces\egroup} + +\permanent\let\stoplinealignment\spac_align_wrapper_stop + +\permanent\protected\def\startleftaligned {\startlinealignment[\v!left ]} \permanent\let\stopleftaligned \spac_align_wrapper_stop +\permanent\protected\def\startmiddlealigned{\startlinealignment[\v!middle]} \permanent\let\stopmiddlealigned\spac_align_wrapper_stop +\permanent\protected\def\startrightaligned {\startlinealignment[\v!right ]} \permanent\let\stoprightaligned \spac_align_wrapper_stop +\permanent\protected\def\startmaxaligned {\startlinealignment[\v!max ]} \permanent\let\stopmaxaligned \spac_align_wrapper_stop + +\aliased\let\startmidaligned \startmiddlealigned \aliased\let\stopmidaligned \stopmiddlealigned +\aliased\let\startcenteraligned\startmiddlealigned \aliased\let\stopcenteraligned\stopmiddlealigned + +\permanent\protected\def\leftaligned {\spac_align_wrapper_handle\v!left } +\permanent\protected\def\middlealigned{\spac_align_wrapper_handle\v!middle} +\permanent\protected\def\rightaligned {\spac_align_wrapper_handle\v!right } +\permanent\protected\def\maxaligned {\spac_align_wrapper_handle\v!max } + +\aliased\let\midaligned \middlealigned +\aliased\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 + +% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname} + +%D Experimental (will be redone when floats are redone as it's real messy +%D now). It can also be made faster (if needed). + +\permanent\protected\def\doxalignline#1#2#3#4#5#6% + {\noindentation % was \noindent + \dontleavehmode % added in marrakesch at TUG 2006\begingroup + \begingroup + \setlocalhsize + \enforced\permanent\protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient + \dowithnextbox + {\hbox to \localhsize + {#1\hskip\ifdone#2\else#3\fi#4% + \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} + +\permanent\protected\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 } + +\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ? + +\permanent\protected\def\alignedline#1#2% setting default + {\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 + +%D We need to pick up a box (downward compatible in case \type {\bgroup} +%D is used (test suite index example). + +\permanent\tolerant\protected\def\wordright[#1]% + {\dowithnextbox + {\normalexpanded{\spac_word_right_indeed{#1}{\hpack{\thebox\nextbox}}}} + \hbox} + +\protected\def\spac_word_right_indeed#1#2% + {\registerparwrapper + {\v!word:\v!right} + {\begingroup + \frozen\parfillskip \zeropoint + \frozen\finalhyphendemerits\zerocount + \endgroup} + {\doifelseparwrapper{\v!word:\v!right}% + {\doifelse{#1}\v!right{\kern-\rightskip}{\doifsomething{#1}{\kern-#1}}% + \strut \removeunwantedspaces + \hfill + \allowbreak % changed back from \hskip\zeropoint + \quad}% + {\allowbreak % changed back from \hskip\zeropoint + \break}% + \unregisterparwrapper{\v!word:\v!right}% + \strut + \hfill + \nobreak + #2% + \allowbreak}} + +% \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. + +% v\protected\def\bottomword +% {\par +% \dowithnextbox +% {\leaders\box\nextbox\vfil\page} +% \vbox to \lineheight} +% +% \permanent\protected\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 + +\protected\def\spac_align_simple_left #1{{#1\hss}} +\protected\def\spac_align_simple_right #1{{\hss#1}} +\protected\def\spac_align_simple_middle#1{{\hss#1\hss}} + +\letvalue{\??alignsimple \v!right }\spac_align_simple_left +\letvalue{\??alignsimple \v!outer }\spac_align_simple_left % not managed! see linenumbers +\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 + +\permanent\protected\def\simplealignedbox#1#2% + {\hbox \ifdim#1>\zeropoint to #1 + \ifcsname\??alignsimple#2\endcsname + \doubleexpandafter\lastnamedcs + \else + \doubleexpandafter\spac_align_simple_left + \fi + \fi} + +\permanent\protected\def\simplealignedspreadbox#1#2% + {\hbox \ifdim#1>\zeropoint spread #1 + \ifcsname\??alignsimple#2\endcsname + \doubleexpandafter\lastnamedcs + \else + \doubleexpandafter\spac_align_simple_left + \fi + \fi} + +\permanent\protected\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 + +\permanent\protected\def\simplereversealignedbox#1#2% + {\hbox \ifdim#1>\zeropoint to #1 + \ifcsname\??alignsimplereverse#2\endcsname + \doubleexpandafter\lastnamedcs + \else + \doubleexpandafter\spac_align_simple_left + \fi + \fi} + +\permanent\protected\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} +% +% \protected\def\spac_align_set_ss#1% +% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname} + +% Some obsolete (old) helpers: + +\permanent\tolerant\protected\def\definehbox[#1][#2]% + {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi} + +%D Some direction related helpers: + +\installcorenamespace {reverse} + +\setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi} +\setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi} + +\permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname} + +%D Now official: + +\permanent\protected\def\spaceorpar + {\endgraf\ifhmode\space\fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-chr.mkxl b/tex/context/base/mkxl/spac-chr.mkxl new file mode 100644 index 000000000..57700704f --- /dev/null +++ b/tex/context/base/mkxl/spac-chr.mkxl @@ -0,0 +1,78 @@ +%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}{optimize} + +\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. + +\pushoverloadmode + +%immutable\edef\nobreakspace {\begingroup\setalignstateattribute\normalUchar"00A0\endgroup} % 1 = left +\immutable\edef\nobreakspace {\normalUchar"00A0} % space +\immutable\edef\softhyphen {\normalUchar"00AD} % softhyohen +\immutable\edef\enquad {\normalUchar"2000} % quad/2 +\immutable\edef\emquad {\normalUchar"2001} % quad +\immutable\edef\twoperemspace {\normalUchar"2002} % quad/2 +% % "2003 % quad == \quad == \hskip\emwidth +\immutable\edef\threeperemspace {\normalUchar"2004} % quad/3 +\immutable\edef\fourperemspace {\normalUchar"2005} % quad/4 +%immutable\edef\fiveperemspace {\normalUchar"001E} % quad/5 (bonus) +\immutable\edef\sixperemspace {\normalUchar"2006} % quad/6 +\immutable\edef\figurespace {\normalUchar"2007} % width of zero +\immutable\edef\punctuationspace {\normalUchar"2008} % width of period +\immutable\edef\breakablethinspace {\normalUchar"2009} % quad/8 +\immutable\edef\hairspace {\normalUchar"200A} % quad/8 +\immutable\edef\zerowidthspace {\normalUchar"200B} % 0 +\immutable\edef\zerowidthnonjoiner {\normalUchar"200C} % 0 +\immutable\edef\zerowidthjoiner {\normalUchar"200D} % 0 +\immutable\edef\narrownobreakspace {\normalUchar"202F} % quad/8 +%immutable\edef\mediummathspace {\normalUchar"205F} % space/8 (math) +%immutable\edef\zerowidthnobreakspace{\normalUchar"FEFF} +%immutable\edef\fiveperemspace {\normalUchar"001E} + +\immutable\protected\def\zerowidthnobreakspace{\penalty\plustenthousand\kern\zeropoint} +\immutable\protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} + +\aliased\let\ideographicspace \enquad +\aliased\let\ideographichalffillspace \emquad + +\immutable\let\zwnj \zerowidthnonjoiner +\immutable\let\zwj \zerowidthjoiner +\immutable\let\nbsp \nobreakspace + +\popoverloadmode + +\immutable\chardef\optionalspace"1F % will be space unless before punctuation + +% Shortcuts: + +% unexpanded as otherwise we need to intercept / cleanup a lot + +\protected\def~{\nobreakspace} + +\protect \endinput + diff --git a/tex/context/base/mkxl/spac-def.mkxl b/tex/context/base/mkxl/spac-def.mkxl new file mode 100644 index 000000000..bba0d47f2 --- /dev/null +++ b/tex/context/base/mkxl/spac-def.mkxl @@ -0,0 +1,91 @@ +%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} + +%D Ideally these definitions should be moved to where they first appear and this +%D 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 + \synchronizeskipamounts + \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/tex/context/base/mkxl/spac-flr.mkxl b/tex/context/base/mkxl/spac-flr.mkxl new file mode 100644 index 000000000..3bf1aa800 --- /dev/null +++ b/tex/context/base/mkxl/spac-flr.mkxl @@ -0,0 +1,194 @@ +%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 development +%D list. Instead of dealing with a few leader types it makes sense to support them +%D all as well as simple rule fillers. Eventually we can also use in for the +%D mathfillers. We distinguish between alternatives and with them methods, and a +%D checker is provided for use in applying e.g.\ fillers in lists. + +\installcorenamespace{filler} +\installcorenamespace{filleralternative} +\installcorenamespace{fillerleadermethod} + +\installcommandhandler \??filler {filler} \??filler + +\aliased\let\setupfillers\setupfiller + +\permanent\protected\def\checkedfiller#1% + {\ifcsname\namedfillerhash{#1}\s!parent\endcsname + \filler[#1]% + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi{#1}} + +\permanent\tolerant\protected\def\filler[#1]% + {\removeunwantedspaces + \begingroup + \edef\currentfiller{#1}% + \usefillerstyleandcolor\c!style\c!color + \scratchdimen\fillerparameter\c!leftmargin\relax + \ifzeropt\scratchdimen\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 + \ifzeropt\scratchdimen\else + \hskip\scratchdimen + \fi + \endgroup + \ignorespaces} + +% \definefiller +% [MyFiller] +% [offset=.25\emwidth, +% rightmargindistance=-\rightskip, +% method=middle] +% +% \startitemize[packed,joinedup][rightmargin=5em] +% \startitem +% \input sapolsky \fillupto[MyFiller]{RS} +% \stopitem +% \stopitemize + +\permanent\tolerant\protected\def\fillupto[#1]#:#2% + {\removeunwantedspaces + \begingroup + \edef\currentfiller{#1}% + \scratchdimen\dimexpr\fillerparameter\c!rightmargindistance\relax + \ifzeropt\scratchdimen\else + \parfillskip \scratchdimen\s!plus \plusone\s!fil\relax + \fi + \spac_fillers_indeed[#1]% + \doifsomething{#2}{\hbox{#2}}% + \par + \endgroup + \ignorespaces} + +\setvalue{\??filleralternative\s!unknown}% + {} + +\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 + \s!height\fillerparameter\c!height + \s!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!rightmargindistance=\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] + +% bonus: + +\definefiller + [dotfill] + [\c!symbol=\textperiod, + \c!style=\v!normal, + \c!method=\v!middle, + \c!width=.5\emwidth, + \c!leftmargin=.2\emwidth, + \c!rightmargin=.2\emwidth] + +\aliased\let\mathdotfill\dotfill + +\permanent\protected\def\textdotfill{\filler[dotfill]} + +\permanent\protected\def\dotfill{\mathortext\mathdotfill\textdotfill} + +% 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{}text \par +% \stoptext diff --git a/tex/context/base/mkxl/spac-grd.mkxl b/tex/context/base/mkxl/spac-grd.mkxl new file mode 100644 index 000000000..fbb02f50c --- /dev/null +++ b/tex/context/base/mkxl/spac-grd.mkxl @@ -0,0 +1,375 @@ +%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} + +\permanent\let\poplastnode\relax + +\permanent\protected\def\pushlastnode + {\csname\??lastnodepusher + \ifcsname\??lastnodepusher\the\lastnodetype\endcsname + \the\lastnodetype + \else + \s!unknown + \fi + \endcsname} + +\setvalue{\??lastnodepusher\number\kernnodecode}% + {\enforced\permanent\protected\edef\poplastnode{\kern\the\lastkern\relax}% + \kern-\lastkern} + +\setvalue{\??lastnodepusher\number\gluenodecode}% + {\enforced\permanent\protected\edef\poplastnode{\vskip\the\lastskip\relax}% + \vskip-\lastskip} + +\setvalue{\??lastnodepusher\number\penaltynodecode}% + {\enforced\permanent\protected\edef\poplastnode{\penalty\the\lastpenalty\relax}% + \nobreak} + +\setvalue{\??lastnodepusher\s!unknown}% + {\enforced\permanent\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\hpack{\setstrut\strut}% + \setbox\b_spac_lines_correction_after \hbox {(}% + \d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax + \d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax + \ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi + \ifdim\d_spac_lines_correction_after <\zeropoint\d_spac_lines_correction_after \zeropoint\fi} + +% 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: + +\permanent\protected\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]} +\permanent\protected\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]} + +\permanent\def\showbaselinecorrection + {\enforced\permanent\protected\def\dobaselinecorrection % visualization is not watertight! + {\bgroup + \ifdim\prevdepth>\zeropoint + \kern-\prevdepth + \fi + \setbox\scratchbox\emptyhbox + \wd\scratchbox\hsize + \dp\scratchbox\strutdp + \nointerlineskip + \forgetall + \ruledvpack{\box\scratchbox}% + \egroup + \prevdepth\strutdp}% + \enforced\permanent\protected\def\dotopbaselinecorrection{\hrule\s!height\d_spac_lines_correction_before}% + \enforced\permanent\protected\def\dobotbaselinecorrection{\hrule\s!height\d_spac_lines_correction_after }} + +% \def\dobaselinecorrection % beware, this one is redefined below +% {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi +% \kern\strutdp +% \prevdepth\strutdp} + +\permanent\protected\def\baselinecorrection + {\endgraf + \ifvmode + \ifdim\prevdepth<\maxdimen + \ifdim\prevdepth<\zeropoint \else + \ifdim\prevdepth<\strutdepth \relax + \pushlastnode + \dobaselinecorrection + \poplastnode + \fi + \fi + \fi + \fi} + +\permanent\protected\def\pagebaselinecorrection + {\ifdim\pagegoal<\maxdimen + \ifdim\pagetotal>\lineheight % or \topskip + \scratchdimen\pagetotal + \advance\scratchdimen\lineheight + \ifdim\scratchdimen<\pagegoal + \baselinecorrection + \fi + \fi + \fi} + +\permanent\protected\def\startbaselinecorrection + {\bgroup + \enforced\let\stopbaselinecorrection\egroup + \ifcase\baselinecorrectionmode + \or % normal + \baselinecorrection + \ifvmode + \setbox\scratchbox\vbox\bgroup\ignorespaces + \enforced\let\stopbaselinecorrection\donormalstopbaselinecorrection + \fi + \or % off + \or % force + \baselinecorrection + \ifvmode + \setbox\scratchbox\vbox\bgroup\ignorespaces + \enforced\let\stopbaselinecorrection\doforcedstopbaselinecorrection + \fi + \fi} + +\permanent\let\stopbaselinecorrection\relax + +\permanent\protected\def\donormalstopbaselinecorrection % I have to check columns yet. + {\egroup + \topbaselinecorrection + \box\scratchbox + \botbaselinecorrection + \egroup} + +\permanent\protected\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 + +\permanent\protected\def\onbaselinecorrection {\baselinecorrectionmode\plusone } +\permanent\protected\def\offbaselinecorrection {\baselinecorrectionmode\plustwo } +\permanent\protected\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree} + +%D \macros +%D {topbaselinecorrection,botbaselinecorrection} +%D +%D The actual top and bottom corrections are implemented as: + +\permanent\protected\def\topbaselinecorrection + {\ifvmode \ifdim\pagegoal<\maxdimen + \forcedtopbaselinecorrection + \fi \fi} + +% \permanent\protected\def\forcedtopbaselinecorrection +% {\ifvmode +% \bgroup +% \spac_lines_initialize_corrections +% \whitespace % no longer ok +% \nointerlineskip +% \dotopbaselinecorrection +% \egroup +% \fi} + +\permanent\protected\def\botbaselinecorrection + {\ifvmode + \bgroup + \spac_lines_initialize_corrections + \dobotbaselinecorrection + \allowbreak % new, otherwise problems when many in a row + \prevdepth\strutdp + \egroup + \fi} + +% nointerlineskip +% +% startpacked +% \startlinecorrection \framed{test} \stoplinecorrection +% \startlinecorrection \framed{test} \stoplinecorrection +% \stoppacked + +\permanent\protected\def\forcedtopbaselinecorrection + {\ifvmode + \bgroup + \spac_lines_initialize_corrections + \vspacing[\v!white] + %\nointerlineskip % + \dotopbaselinecorrection + \egroup + \fi} + +\permanent\protected\def\dobaselinecorrection + {\ifdim\prevdepth>\zeropoint + \vspacing[\the\dimexpr-\prevdepth+\strutdp\relax]% + \else + \vspacing[\the\dimexpr\strutdp\relax]% + \fi + \prevdepth\strutdp} + +% \permanent\protected\def\dobaselinecorrection +% {\scratchdimen\dimexpr\ifdim\prevdepth>\zeropoint-\prevdepth+\fi\strutdp\relax +% \vspacing[\the\scratchdimen]% +% \prevdepth\strutdp} +% +% some day: +% +% \permanent\protected\def\dobaselinecorrection +% {\clf_checkstrutdepth\strutdp} +% +% \permanent\protected\def\baselinecorrection +% {\endgraf +% \ifvmode +% \ifdim\prevdepth<\maxdimen +% \ifdim\prevdepth<\zeropoint \else +% \ifdim\prevdepth<\strutdepth \relax +% % works in mvl: +% % \forcestrutdepth +% % doesn't work immediately (unless enforced with penalty): +% % \pushlastnode +% % \dobaselinecorrection +% % \poplastnode +% % works ok: +% \clf_checkstrutdepth\strutdp +% \fi +% \fi +% \fi +% \fi} + +%D For the moment only with placefloats (should work in mvl and boxes): + +\permanent\protected\def\checkprevdepth + {\endgraf + \ifvmode + \ifdim\prevdepth<\maxdimen + \ifdim\prevdepth<\zeropoint \else + \ifdim\prevdepth<\strutdepth \relax + \clf_checkstrutdepth\strutdp + \fi + \fi + \fi + \fi} + +\let\normalstartbaselinecorrection\startbaselinecorrection + +\pushoverloadmode + +\permanent\protected\def\startbaselinecorrection + {\ifgridsnapping + \snaptogrid[\v!normal]\vbox\bgroup + \enforced\let\stopbaselinecorrection\egroup + \else + \normalstartbaselinecorrection + \fi} + +\popoverloadmode + +% This is new (and experimental) and might replace some of the above. beware it doesn't always work +% out well, e.g. when used grouped and such (e.g. before display math doesn't work out well). + +% \permanent\protected\def\fakenextstrutline +% {\par +% \begingroup +% \reseteverypar +% \dontleavehmode\hpack to \zeropoint{\page_sides_anchor\hss\strut}% just a tracer +% \vskip-\parskip +% \vskip-\struttotal +% \endgroup} + +% \permanent\protected\def\fakenextstrutline +% {\par +% \begingroup +% \reseteverypar +% \dontleavehmode\hpack{\strut}\par +% \clf_fakenextstrutline +% \ifdim\pagetotal>\lineheight +% \pagetotal\dimexpr\pagetotal-\lineheight\relax +% \fi +% \endgroup} + +% \permanent\protected\def\fakenextstrutline +% {\par +% \begingroup +% \reseteverypar +% \forgetall +% \dontleavehmode\hpack{\strut}\par +% \clf_removelastline +% \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl new file mode 100644 index 000000000..e7263ae76 --- /dev/null +++ b/tex/context/base/mkxl/spac-hor.mkxl @@ -0,0 +1,1237 @@ +%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}{} + +\let\parfillrightskip\parfillskip + +\bitwiseflip \normalizelinemode \parindentskipcode +\bitwiseflip \normalizelinemode \normalizelinecode + +\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. + +\permanent\protected\def\presetindentation + {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}} + +\permanent\protected\def\setupindenting + {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size} + +\permanent\protected\def\spac_indentation_setup_size + {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}% + \ifzeropt\parindent\else + \parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand + \fi} + +\aliased\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 + \ifempty\m_spac_indentation_options \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 + \spac_indentation_variant_yes % better than: \let\checkindentation\relax + \else + \spac_indentation_variant_no + \fi + \spac_indentation_check_toggle} + +\def\spac_indentation_set_everypar + {\everypar{\checkindentation}} + +\permanent\protected\def\useindentingparameter#1% faster local variant + {\edef\m_spac_indentation_options{#1\c!indenting}% + \ifempty\m_spac_indentation_options \else + \spac_indentation_setup_indeed + \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} + +\permanent\tolerant\protected\def\defineindenting[#1]#*[#2]% todo: mixes + {\ifarguments\else\setevalue{\??indentingpreset#1}{#2}\fi} + +\def\spac_indentation_apply_step_one_nested + {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one} + +\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 + \orelse\ifcsname\??indentingmethod#1\endcsname + % case two + \else + \edef\v_spac_indentation_current{#1}% single entry in list + \let\normalindentation\v_spac_indentation_current + \spac_indentation_setup_size + \fi} + +\def\spac_indentation_apply_step_two#1% + {\ifcsname\??indentingpreset#1\endcsname + \spac_indentation_apply_step_two_nested + \orelse\ifcsname\??indentingmethod#1\endcsname + \lastnamedcs + \else + % case one + \fi} + +\permanent\protected\def\indenting % kind of obsolete + {\doifelsenextoptionalcs\spac_indentation_setup_options\relax} + +% use \noindentation to suppress next indentation + +\installcorenamespace{indentingmethod} + +\permanent\protected\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{\ifempty\normalindentation\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\ifzeropt\parindent + \d_spac_indentation_par + \else + \zeropoint + \fi\relax} + +\permanent\protected\def\noindenting{\indenting[\v!no, \v!next ]} +\permanent\protected\def\doindenting{\indenting[\v!yes,\v!first]} + +%D Here come the handlers (still rather messy ... we need states). + +%newif\ifindentation \indentationtrue % will become a mode + +\aliased\let\checkindentation\relax + +\installmacrostack\checkindentation + +%D Actually we can forget about indent and let everypar insert a kern or so, +%D but on the other hand it's kind of consistent to keep it and make the +%D width zero. We can do it in \LUA\ or do it natively (which actually makes +%D sense. + +% \permanent\protected\def\undent +% {\begingroup +% % todo: check subtype too +% \ifnum\lastnodetype=\gluenodecode +% \unskip % we also need to check for the subtype +% \orelse\ifnum\lastnodetype=\hlistnodecode +% \setbox\scratchbox\lastbox % we also need to check for the subtype +% \else +% % forget about it +% \fi +% \endgroup} + +\def\spac_indentation_remove + {\ifzeropt\parindent \else + \undent + \fi} + +\def\spac_indentation_kill_indeed + {%\global\indentationfalse + \spac_indentation_remove} + +\permanent\protected\def\spac_indentation_do_toggle_indeed + {%\global\indentationfalse + \enforced\glet\checkindentation\spac_indentation_no_toggle_indeed + \spac_indentation_remove} + +\permanent\protected\def\spac_indentation_no_toggle_indeed + {%\global\indentationtrue + \enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} + +\permanent\protected\def\spac_indentation_do_indeed + {}%\global\indentationtrue} + +\permanent\protected\def\spac_indentation_do_toggle + {\enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} + +\permanent\protected\def\spac_indentation_no_toggle + {\enforced\glet\checkindentation\spac_indentation_no_toggle_indeed} + +\permanent\protected\def\spac_indentation_check_toggle + {\ifcase\c_spac_indentation_toggle_state + % nothing + \or + \spac_indentation_no_toggle + \or + \spac_indentation_do_toggle + \fi} + +\permanent\protected\def\spac_indentation_variant_yes + {\enforced\glet\checkindentation\spac_indentation_do_indeed} + +\permanent\protected\def\spac_indentation_no_next_check + {\spac_indentation_remove + \enforced\glet\checkindentation\spac_indentation_do_indeed} + +\permanent\protected\def\spac_indentation_variant_no % made global + {\ifinpagebody \else + %\global\indentationfalse + \enforced\glet\checkindentation\spac_indentation_no_next_check + \fi} + +\permanent\protected\def\nonoindentation % bv bij floats + {\ifinpagebody \else + %\global\indentationtrue + \enforced\glet\checkindentation\spac_indentation_do_indeed + \fi} + +\permanent\protected\def\spac_indentation_variant_force + {\ifvmode \ifzeropt\parindent \else + % was : \hskip\parindent + % can be: \indent + % but we test: + \noindent\hskip\parindent + \fi \fi} + +% public: + +\aliased\let\indentation \spac_indentation_variant_force +\aliased\let\noindentation\spac_indentation_variant_no % public +\aliased\let\doindentation\spac_indentation_variant_yes % public + +\permanent\protected\def\dontrechecknextindentation % public (in macros) + {\global\enforced\let\dorechecknextindentation\relax} + +\aliased\let\dorechecknextindentation\relax % public (in macros) + +\permanent\protected\protected\def\spac_indentation_check_next_indentation + {\global\enforced\let\dorechecknextindentation\relax + \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par + +\def\spac_indentation_variant_auto + {\global\enforced\let\dorechecknextindentation\spac_indentation_check_next_indentation} + +%D This one sets up the local indentation behaviour (i.e. either or not +%D a next paragraph will be indented). + +\installcorenamespace{indentnext} + +\permanent\protected\def\checknextindentation[#1]% + {\begincsname\??indentnext#1\endcsname} + +\permanent\protected\def\useindentnextparameter#1% new, the more efficient variant + {\edef\p_indentnext{#1\c!indentnext}% + \ifempty\p_indentnext\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 + +\permanent\protected\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 + +\permanent\protected\def\forgethorizontalstretch + {\emergencystretch\zeropoint} + +\appendtoks + \forgethorizontalstretch +\to \everyforgetall % needed in pagebody + +%D Helper: + +\permanent\protected\def\softbreak + {\relax\ifhmode\hskip\parfillskip\break\fi} + +%D \macros +%D {frenchspacing,nonfrenchspacing} +%D +%D Somehow \type{\frenchspacing} can lead to hyphenation between dashes so we now +%D have \type {\newfrenchspacing} (moved from \type {syst-chr}). Maybe it's not +%D needed any more. + +%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 } + +\permanent\protected\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand} +\permanent\protected\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}} +\permanent\protected\def\nonfrenchspacing{\spac_spacecodes_set_stretch} + +\permanent\protected\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}} + +\installspacingmethod \empty {} % keep values +\installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere +\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation +\installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation + +%% \permanent\protected\def\setupspacing +%% {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop} +%% +%% \def\spac_spacecodes_setup_yes[#1]% +%% {\begincsname\??spacecodemethod#1\endcsname +%% \updateraggedskips} +%% +%% \def\spac_spacecodes_setup_nop +%% {\updateraggedskips} + +\permanent\tolerant\protected\def\setupspacing[#1]% + {\ifarguments\or + \begincsname\??spacecodemethod#1\endcsname + \fi + \updateraggedskips} + +%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: + +\permanent\protected\def\synchronizespacecodes{\updateraggedskips} + +% \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 \ 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. + +\permanent\protected\def\specialspaceprimitive + {\begingroup + % so, no fancy extra spacing after: foo i.e.\ bar + \nonfrenchspacing\normalspaceprimitive + \endgroup} + +\permanent\protected\def\normalnotobeyedspace + {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing) + +\pushoverloadmode + +\overloaded\let\ =\normalnotobeyedspace % so we redefine the primitive! + +\popoverloadmode + +% Because I strip spaces at the end of lines (in the editor) we need a bit of +% a trick to define slash+newline, so \space and \ 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} + +\permanent\protected\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math + +\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later + +% \def\space { } +\permanent\protected\def\removelastspace{\ifhmode\unskip\fi} +\permanent\protected\def\nospace {\removelastspace\ignorespaces} + +\ifdefined\nospaces + \permanent\protected\def\nospacing{\normalnospaces\plusone} + \permanent\protected\def\dospacing{\normalnospaces\zerocount} +\else + \permanent\protected\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint} + \permanent\protected\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what +\fi + +\ifdefined\softhyphen \else + \let\softhyphen\explicitdiscretionary +\fi + +% todo: + +\cldcontext{"\string\\protected\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: + +\permanent\protected\def\fixedspace + {\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox + \hskip\wd\scratchbox\relax} + +\permanent\protected\def\fixedspaces + {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace + \enforced\let~\fixedspace} % we need to renew it + +\appendtoks + \enforced\let~\space + \enforced\let\ \space +\to \everysimplifycommands + +\newsignal\d_spac_keep_unwanted_space_signal + +% \parindentmode\plusone + +\permanent\protected\def\keepunwantedspaces + {\ifhmode + \ifdim\lastskip=\d_spac_keep_unwanted_space_signal\else + \hskip\d_spac_keep_unwanted_space_signal\relax + \fi + \fi} + +\permanent\protected\def\removeunwantedspaces + {\ifhmode + \expandafter \spac_helpers_remove_unwantedspace + \fi} + +\def\spac_helpers_remove_unwantedspace + {\ifnum\lastnodetype=\gluenodecode\relax + \ifnum\lastnodesubtype=\indentskipsubtypecode\relax + % keep parindent + \orelse\ifdim\lastskip=\d_spac_keep_unwanted_space_signal\relax + \unskip + \else + \unskip + \doubleexpandafter\spac_helpers_remove_unwantedspace + \fi + \fi} + +\permanent\protected\def\onlynonbreakablespace + {\ifdim\lastskip=\interwordspace + \unskip + \nonbreakablespace + \fi + \ignorespaces} + +% \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\enspace \else \permanent\protected\def\enspace{\kern .5\emwidth} \fi +\ifdefined\quad \else \permanent\protected\def\quad {\hskip \emwidth\relax} \fi +\ifdefined\enskip \else \permanent\protected\def\enskip {\hskip.5\emwidth\relax} \fi +\ifdefined\qquad \else \permanent\protected\def\qquad {\hskip 2\emwidth\relax} \fi + +\permanent\protected\def\negenspace{\kern-.5\emwidth} +\permanent\protected\def\negemspace{\kern- \emwidth} + +\aliased\let\emspace\quad + +\permanent\protected\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) + +\permanent\tolerant\protected\def\quads[#1]% we do robust checking + {\dontleavehmode + \begingroup + %\scratchcounter\ifparameter#1\or#1\else\plusthree\fi + \scratchcounter\ifchknum#1\or#1\else\plusthree\fi + \zwj\dorecurse\scratchcounter{\hskip\emwidth\zwj}% + \endgroup} + +% Suggested by GB (not the name -): + +\def\rapfillskip{.5\hsize plus .092\hsize minus .5\hsize} % D.A.'s value + +% Bovendien definieren we enkele extra \fill's: + +\newskip\s_spac_fil \s_spac_fil = \zeropoint \s!plus 1\s!fil \relax +\newskip\s_spac_fill \s_spac_fill = \zeropoint \s!plus 1\s!fill \relax +\newskip\s_spac_filll \s_spac_filll = \zeropoint \s!plus 1\s!filll\relax + +\newskip\s_spac_neg_fil \s_spac_neg_fil = \zeropoint \s!plus-1\s!fil \relax +\newskip\s_spac_neg_fill \s_spac_neg_fill = \zeropoint \s!plus-1\s!fill \relax +\newskip\s_spac_neg_filll \s_spac_neg_filll = \zeropoint \s!plus-1\s!filll\relax + +\permanent\protected\def\hfilll {\hskip\s_spac_filll\relax} +\permanent\protected\def\vfilll {\vskip\s_spac_filll\relax} + +\permanent\protected\def\hfillneg {\hskip\s_spac_neg_fill \relax} +\permanent\protected\def\hfilllneg{\hskip\s_spac_neg_filll\relax} +\permanent\protected\def\vfillneg {\vskip\s_spac_neg_fill \relax} +\permanent\protected\def\vfilllneg{\vskip\s_spac_neg_filll\relax} + +\permanent\protected\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} +\permanent\protected\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere + +% maybe we should hash the analysis + +\installcorenamespace{narrower} +\installcorenamespace{narrowermethod} + +\newskip\s_spac_narrower_left +\newskip\s_spac_narrower_right +\newskip\s_spac_narrower_middle + +\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 + \frozen\instance\setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}% + \frozen\instance\setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}% +\to \everydefinenarrower + +\permanent\protected\def\installnarrowermethod#1#2% + {\setvalue{\??narrowermethod#1}{#2}} + +\protected\def\spac_narrower_method_analyze#1% + {\ifcsname\??narrowermethod#1\endcsname + \lastnamedcs + \else + \global\advance\s_spac_narrower_middle#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_middle \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_middle-\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_middle \zeropoint + \global \s_spac_narrower_right \zeropoint\relax} +\installnarrowermethod \v!none {} +\installnarrowermethod \v!reverse {} % never seen + +\permanent\overloaded\tolerant\protected\def\spac_narrower_start[#1]#*[#2]% + {\begingroup + \edef\currentnarrower{#1}% + \ifparameter#2\or + \spac_narrower_start_apply{#2}% + \else + \spac_narrower_start_apply{\narrowerparameter\v!default}% + \fi} + +\newskip \s_spac_narrower_left_last +\newskip \s_spac_narrower_right_last +\newconditional\s_spac_narrower_last_swap + +\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_middle\zeropoint + \edef\askednarrower{#1}% + \ifx\askednarrower\v!reverse + \ifconditional\s_spac_narrower_last_swap + \permanent\leftskip \s_spac_narrower_right_last + \permanent\rightskip\s_spac_narrower_left_last + \setfalse\s_spac_narrower_last_swap + \else + \permanent\leftskip \s_spac_narrower_left_last + \permanent\rightskip\s_spac_narrower_right_last + \settrue\s_spac_narrower_last_swap + \fi + \else + \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize + \permanent\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax + \permanent\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax + \fi + \seteffectivehsize} + +\permanent\protected\def\spac_narrower_stop + {\narrowerparameter\c!after + \normalexpanded{% + \endgroup + \s_spac_narrower_left_last \the\leftskip \relax + \s_spac_narrower_right_last\the\rightskip\relax + \ifconditional\s_spac_narrower_last_swap + \setfalse\s_spac_narrower_last_swap + \else + \settrue\s_spac_narrower_last_swap + \fi + }} + +\permanent\tolerant\protected\def\startnarrower[#1]% + {\begingroup + \let\currentnarrower\empty + \ifparameter#1\or + \spac_narrower_start_apply{#1}% + \else + \spac_narrower_start_apply{\narrowerparameter\v!default}% + \fi} + +\aliased\let\stopnarrower\spac_narrower_stop + +\permanent\tolerant\protected\def\startnarrow[#1]#*[#2]% current how + {\begingroup + \ifnum\lastarguments=\plustwo + \expandafter\spac_narrower_start_named_two + \else + \expandafter\spac_narrower_start_named_one + \fi[#1][#2]} + +\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}} + +\aliased\let\stopnarrow\spac_narrower_stop + +\newdimen\d_spac_effective_hsize \permanent\protected\def\effectivehsize {\hsize} +\newdimen\d_spac_effective_leftskip \permanent\protected\def\effectiveleftskip {\dimexpr\leftskip \relax} +\newdimen\d_spac_effective_rightskip \permanent\protected\def\effectiverightskip{\dimexpr\rightskip\relax} + +\permanent\protected\def\seteffectivehsize + {\setlocalhsize + \d_spac_effective_hsize \localhsize + \d_spac_effective_leftskip 1\leftskip + \d_spac_effective_rightskip1\rightskip + \enforced\let\effectivehsize \d_spac_effective_hsize + \enforced\let\effectiveleftskip \d_spac_effective_leftskip + \enforced\let\effectiverightskip\d_spac_effective_rightskip} + +\installcorenamespace{skipadaptionleft} +\installcorenamespace{skipadaptionright} + +\newskip\leftskipadaption +\newskip\rightskipadaption + +\setvalue{\??skipadaptionleft \v!yes }{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} +\letvalue{\??skipadaptionleft \v!no }\zeropoint +\letvalue{\??skipadaptionleft \empty }\zeropoint +\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right} +\letvalue{\??skipadaptionright\v!no }\zeropoint +\letvalue{\??skipadaptionright\empty }\zeropoint + +% \setvalue{\??skipadaptionleft \v!standard}{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} +% \setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right} + +\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname +\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname + +% \protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax} +% \protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax} + +\permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} +\permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} + +\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\permanent\advance\leftskip \leftskipadaption } +\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\permanent\advance\rightskip\rightskipadaption} + +\permanent\protected\def\forgetbothskips + {\leftskip\zeropoint + \rightskip\zeropoint + \relax} + +\appendtoks + \forgetbothskips +\to \everyforgetall + +% in spac-ver.mkiv +% +% \protected\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} + +\permanent\protected\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} + +%% \protected\def\setuptolerance +%% {\dosingleargument\spac_tolerances_setup} +%% +%% \def\spac_tolerances_setup[#1]% +%% {\doifelseinset\v!vertical{#1}% +%% {\processcommacommand[#1]\spac_tolerances_step_vertical } +%% {\processcommacommand[#1]\spac_tolerances_step_horizontal}} + +\permanent\tolerant\protected\def\setuptolerance[#1]% + {\ifarguments\or + \doifelseinset\v!vertical{#1}% + {\processcommacommand[#1]\spac_tolerances_step_vertical } + {\processcommacommand[#1]\spac_tolerances_step_horizontal}% + \fi} + +%D \macros +%D {pushindentation,popindentation} +%D +%D The pushing and popping is done by: + +\newbox\b_spac_indentations_a +\newbox\b_spac_indentations_b + +\permanent\protected\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} + +\permanent\protected\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 + +\permanent\protected\def\justonespace{\removeunwantedspaces\space} +%frozen\protected\def\justaperiod {\removeunwantedspaces.} +%frozen\protected\def\justacomma {\removeunwantedspaces,} + +\installcorenamespace{hspace} + +\permanent\protected\def\ignorecrlf + {\enforced\let\crlf\justonespace + \enforced\let\\\crlf} + +\permanent\tolerant\protected\def\definehspace[#1]#*[#2]#*[#3]% #1 = optional namespace + {\ifparameter#3\or + \setvalue{\??hspace#1:#2}{#3}% + \else + \setvalue{\??hspace:#1}{#2}% + \fi} + +\permanent\tolerant\protected\def\hspace[#1]#*[#2]% + {\ifhmode + \removeunwantedspaces + \hskip % always a skip even when 0pt + \ifparameter#2\or + \hspaceamount{#1}{#2}% + \orelse\ifparameter#1\or + \hspaceamount\empty{#1}% + \else + \hspaceamount\empty\s!default + \fi + \relax + \expandafter\ignorespaces + \fi} + +\permanent\overloaded\def\hspaceamount #1#2{\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\overloaded\def\directhspaceamount #1{\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} + +% no installhspace here (this is already an old command) + +\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}: + +\permanent\protected\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax} +\permanent\protected\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax} +\permanent\protected\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax} + +\newmuskip\hairmuskip \hairmuskip=.15mu + +\overloaded\permanent\protected \def\hairspace {\textormathspace+\hairmuskip{.5}} +\overloaded\permanent\protected \def\thinspace {\textormathspace+\thinmuskip 1} +%overloaded\permanent\protected \def\medspace {\textormathspace+\medmuskip 2} % 4/18 em +\overloaded\permanent\protected \def\thickspace {\textormathspace+\thickmuskip3} +\overloaded\permanent\protected \def\neghairspace {\textormathspace-\thinmuskip{.5}} +\overloaded\permanent\protected \def\negthinspace {\textormathspace-\thinmuskip 1} +\overloaded\permanent\protected \def\negmedspace {\textormathspace-\medmuskip 2} +\overloaded\permanent\protected \def\negthickspace{\textormathspace-\thickmuskip3} +\overloaded\permanent\protected\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}} + +% needed for unicode: + +%protected\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1} +%protected\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace +%protected\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax} +%protected\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax} +%protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie +%protected\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax} +%protected\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this +%protected\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup} +%protected\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax} +%protected\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax} +%protected\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace} +%protected\def\narrownobreakspace {\penalty\plustenthousand\thinspace} +%protected\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint} +%protected\def\zerowidthspace {\hskip\zeropoint} + +\definehspace[.5][.1250\emwidth] % hair +\definehspace[1] [.1667\emwidth] % thin +\definehspace[2] [.2222\emwidth] % med +\definehspace[3] [.2777\emwidth] % thick + +\aliased\let \, \thinspace +\aliased\let \: \medspace +\aliased\let \; \thickspace +\aliased\let \! \negthinspace + +% plain ... +% +% \ifdefined\> \else \protected\def\>{\mskip \medmuskip } \fi +% \ifdefined\* \else \protected\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi + +\permanent\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} + +\permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace + {\setvalue{\??spacemethods#1}{#2}} + +\permanent\def\activatespacehandler#1% + {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname} + +\permanent\protected\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}% +\permanent\protected\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% +\permanent\protected\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% + +% hm, order matters when we \let in \obeyspaces + +\installspacemethod \v!on + {\obeyspaces + \enforced\let\obeyedspace\spac_spaces_checked_control + \enforced\let\ =\obeyedspace} + +\installspacemethod \v!yes + {\obeyspaces + \enforced\let\obeyedspace\spac_spaces_checked_normal + \enforced\let\ =\obeyedspace} + +\installspacemethod \v!off % == default + {\normalspaces + \enforced\let\obeyedspace\normalspace + \enforced\let\ =\normalspaceprimitive} % was \normalspace + +\installspacemethod \v!fixed + {\obeyspaces + \enforced\let\obeyedspace\spac_spaces_checked_fixed + \enforced\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 + +\permanent\protected\def\autoinsertnextspace + {\futurelet\nexttoken\spac_spaces_auto_insert_next} + +\permanent\def\spac_spaces_auto_insert_next + {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end + +%D Moved from bib module: + +\permanent\protected\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): + +\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} + +\permanent\protected\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small} +\permanent\protected\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} +\permanent\protected\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} + +%D A rather unknown one: + +\permanent\protected\def\widened % moved from cont-new + {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop} + +\def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}} +\def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}} + +%D For the moment here (used in page-txt): + +\protected\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\d_spac_ignore_spaces_signal +\newcount \c_spac_ignore_spaces + +\protected\def\startignorespaces + {\advance\c_spac_ignore_spaces\plusone + \ifcase\c_spac_ignore_spaces\or \ifhmode + \hskip\d_spac_ignore_spaces_signal + \fi \fi + \ignorespaces} + +\protected\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 + {\ifzeropt\lastskip + \exitloop + \orelse\ifdim\lastskip=\d_spac_ignore_spaces_signal + \unskip + \exitloop + \else + \unskip + \fi} + +%D \macros +%D {obeyfollowingtoken} + +\permanent\def\obeyfollowingtoken{{}} % end \cs scanning + +%D Something new: + +\permanent\protected\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax} +\permanent\protected\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary} + +\permanent\protected\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore} +\permanent\protected\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter} +\permanent\protected\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter} + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-lin.mkxl b/tex/context/base/mkxl/spac-lin.mkxl new file mode 100644 index 000000000..53da64923 --- /dev/null +++ b/tex/context/base/mkxl/spac-lin.mkxl @@ -0,0 +1,211 @@ +%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 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 + \frozen\instance\setuevalue{\e!start\currentlines}{\spac_lines_start[\currentlines]}% + \frozen\instance\letvalue {\e!stop \currentlines }\spac_lines_stop +\to \everydefinelines + +\let\p_lines_option\empty + +\let\spac_lines_break \relax +\let\spac_after_first_obeyed_line\relax +\let\spac_lines_indent \relax + +%D See \type {indentation-005.tex}: +%D +%D \starttyping +%D \setuplines[indentlist={0pt,10pt,15pt,20pt}] +%D +%D \setupindenting[yes,1em] +%D \setuplines[indentlist={0pt,*,*}] +%D +%D \setuplines[indentlist={0pt,1em,*}] +%D \starttyping + +\newcount\c_spac_lines_indent_cnt +\newcount\c_spac_lines_indent_max +\newdimen\d_spac_lines_indent + +\def\spac_lines_indent_indeed + {\ifnum\c_spac_lines_indent_cnt=\c_spac_lines_indent_max + \c_spac_lines_indent_cnt\plusone + \else + \advance\c_spac_lines_indent_cnt\plusone + \fi + \getfromcommacommand[\m_spac_lines_indentlist][\c_spac_lines_indent_cnt]% + \ifx\commalistelement\wildcardsymbol + \hskip\d_spac_lines_indent + \else + \scratchdimen\dimexpr\commalistelement\relax + \hskip + \ifdim\scratchdimen=\zeropoint + \zeropoint + \else + \scratchdimen + \d_spac_lines_indent\scratchdimen + \fi + \fi + \relax} + +\permanent\tolerant\protected\def\spac_lines_start[#1]% + {\bgroup + \edef\currentlines{#1}% + \obeylines + \spac_lines_start_indeed} + +\tolerant\def\spac_lines_start_indeed[#1]% new: optional second argument (WS) + {\ifarguments\or + \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 + \push_macro_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 + % + \edef\m_spac_lines_indentlist{\linesparameter\c!indentlist}% + \getcommacommandsize[\m_spac_lines_indentlist]% + \c_spac_lines_indent_max\commalistsize + \c_spac_lines_indent_cnt\zerocount + \ifnum\c_spac_lines_indent_max>\plusone + \let\spac_lines_indent\spac_lines_indent_indeed + \d_spac_lines_indent\d_spac_indentation_par + \else + \let\spac_lines_indent\relax + \fi + % + \ignorespaces + \glet\spac_after_first_obeyed_line\spac_lines_after_first_obeyed_line_a + \enforced\let\obeyedline\spac_lines_obeyed_line + \activatespacehandler{\linesparameter\c!space}% + \dostarttagged\t!line\empty + \ignorepars} + + +% 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 + \spac_lines_indent + \linesparameter\c!left + \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 + \spac_lines_indent + \linesparameter\c!left} + +\def\spac_lines_obeyed_line + {\ifdone\linesparameter\c!right\fi + \dostoptagged % can be a dummy one as we don't look ahead + \par + \dostarttagged\t!line\empty + \futurelet\nexttoken\spac_lines_between} + +\protected\def\spac_lines_stop + {\dostoptagged + \endgroup + \dostoptagged + \pop_macro_checkindentation + \linesparameter\c!after + \egroup} + +\def\spac_lines_between + {\ifx\nexttoken\spac_lines_stop + \donefalse + \else + \doifelsemeaning\nexttoken\obeyedline % brrr + {\donefalse\linesparameter\c!inbetween} + {\donetrue\spac_after_first_obeyed_line}% + \fi} + +\definelines[\v!lines] + +\permanent\tolerant\protected\def\emptylines[#1]% + {\endgraf + \begingroup + %\forgetall % debatable + \ifhmode + \crlf % finish the current line + \fi + \scratchcounter\ifparameter#1\or#1\else3\fi\relax + \dorecurse\scratchcounter{\strut\crlf}% + \endgroup} + +\ifdefined\startlines \else + \aliased\expandafter\let\expandafter\startlines\csname\e!start\v!lines\endcsname + \aliased\expandafter\let\expandafter\stoplines \csname\e!stop \v!lines\endcsname +\fi + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-pag.mkxl b/tex/context/base/mkxl/spac-pag.mkxl new file mode 100644 index 000000000..dbee431af --- /dev/null +++ b/tex/context/base/mkxl/spac-pag.mkxl @@ -0,0 +1,182 @@ +%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 + +\permanent\protected\def\setalignmentswitch#1% + {\chardef\alignmentswitch\csname\??alignswitch\ifcsname\??alignswitch#1\endcsname#1\else\v!left\fi\endcsname} + +\newif \ifpagestatemismatch +\newcount \realpagestateno +\newconstant\frozenpagestate + +\permanent\protected\def\dotrackpagestate#1#2% + {\ifdoublesided \ifinpagebody \else + \doforcedtrackpagestate{#1}{#2}% + \fi \fi} + +\permanent\protected\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 + +\permanent\protected\def\docheckpagestate#1#2% + {\ifcase\frozenpagestate + \setpagestaterealpageno{#1}{\number#2}% + \fi} + +\permanent\protected\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 + \orelse\ifdoublesided + \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}% + \ifempty\m_spac_pagestates_realpage + \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 + \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} + +\permanent\protected\def\doifelseforcedrightpagestate#1#2% + {\ifcase\frozenpagestate + \pagestatemismatchfalse + \realpagestateno\realfolio + \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}% + \ifempty\m_spac_pagestates_realpage + \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} + +\aliased\let\doifrightpagestateelse \doifelserightpagestate +\aliased\let\doifforcedrightpagestateelse\doifelseforcedrightpagestate + +\permanent\protected\def\freezepagestate {\frozenpagestate\plusone } +\permanent\protected\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] + +\permanent\protected\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs} % use \dontleavehmode if needed +\permanent\protected\def\doifelserightpage{\doifelserightpagestate\s!paragraph\nofraggedparagraphs} +\permanent\protected\def\rightpageorder {\pagestaterealpageorder\s!paragraph\nofraggedparagraphs} + +\aliased\let\doifrightpageelse\doifelserightpage + +\installcorenamespace{pagechanges} + +\newif\ifpagechanged \mutable\let\lastchangedpage\empty + +\def\spac_pagechanges_check#1#2#3% + {\pagechangedfalse + \doforcedtrackpagestate{#2}{#3}% + \edef\m_spac_pagestates_realpage{\pagestaterealpage{#2}{\number#3}}% + \ifempty\m_spac_pagestates_realpage \orelse\ifnum\m_spac_pagestates_realpage>0\csname\??pagechanges#2:#1\endcsname\relax + \pagechangedtrue + \fi + \ifpagechanged + \letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage + \glet\lastchangedpage\m_spac_pagestates_realpage + \else + \glet\lastchangedpage\realfolio + \fi} + +\permanent\protected\def\changedpagestate#1#2% + {\executeifdefined{\??pagechanges#2:#1}0} + +\permanent\protected\def\checkpagechange#1{\spac_pagechanges_check{#1}\s!paragraph\nofraggedparagraphs} +\permanent\protected\def\changedpage #1{\changedpagestate{#1}\s!paragraph} + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-par.lmt b/tex/context/base/mkxl/spac-par.lmt new file mode 100644 index 000000000..3af8ea415 --- /dev/null +++ b/tex/context/base/mkxl/spac-par.lmt @@ -0,0 +1,80 @@ +if not modules then modules = { } end modules ['spac-par'] = { + version = 1.001, + comment = "companion to spac-par.mkxl", + 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 collected = utilities.storage.allocate() +local tobesaved = utilities.storage.allocate() +local wrappers = { } + +local jobparwrappers = { + collected = collected, + tobesaved = tobesaved, +} + +job.parwrappers = jobparwrappers + +local function initializer() + tobesaved = jobparwrappers.tobesaved + collected = jobparwrappers.collected +end + +local function finalizer() + -- nothing yet +end + +job.register('job.parwrappers.collected', tobesaved, initializer, finalizer) + +implement { + name = "newparwrapper", + arguments = "string", + actions = function(id) + local t = tobesaved[id] + local n + if t then + n = #t + 1 + t[n] = 0 + else + n = 1 + tobesaved[id] = { 0 } + end + wrappers[id] = n + end +} + +implement { + name = "setparwrapper", + arguments = "string", + protected = true, + actions = function(id) + local t = tobesaved[id] + local n = #t + t[n] = t[n] + 1 + end +} + +implement { + name = "getparwrapper", + arguments = "string", + public = true, + actions = function(id) + local t = tobesaved[id] + context(t and t[#t] or 0) + end +} + +implement { + name = "lastparwrapper", + arguments = "string", + public = true, + actions = function(id) + local t = collected and collected[id] + context(t and t[wrappers[id]] or 0) + end +} diff --git a/tex/context/base/mkxl/spac-par.mkxl b/tex/context/base/mkxl/spac-par.mkxl new file mode 100644 index 000000000..524e31bc5 --- /dev/null +++ b/tex/context/base/mkxl/spac-par.mkxl @@ -0,0 +1,446 @@ +%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} + +\registerctxluafile{spac-par}{autosuffix} + +\unprotect + +% TODO: \appendtoks \strut \wrapuppar{\strut}\to \everypar + +%D New experimental stuff: + +% this might move to syst-ini.mkxl + +\setnewconstant\paragraphupdatecodes\numexpr + \frozentolerancecode + + \frozenloosenesscode + + \frozenlinepenaltycode + + \frozenwidowpenaltycode + + \frozenclubpenaltycode + + \frozenbrokenpenaltycode + + \frozendemeritscode +\relax + +\setnewconstant\paragraphpenaltycodes\numexpr + \frozenlinepenaltycode + + \frozenwidowpenaltycode + + \frozenclubpenaltycode + + \frozenbrokenpenaltycode +\relax + +\setnewconstant\paragraphdemeritcodes\numexpr + \frozendemeritscode +\relax + +\setnewconstant\paragraphshapecodes\numexpr + \frozenhangcode + + \frozenskipcode + + \frozenparfillcode + + \frozenshapecode +\relax + +\setnewconstant\frozenparagraphdefault\numexpr + \frozenhsizecode % \hsize + + \frozenskipcode % \leftskip \rightskip + + \frozenhangcode % \hangindent \hangafter + + \frozenindentcode % \parindent + + \frozenparfillcode % \parfillskip \parfillleftskip + + \frozenadjustcode % \adjustspacing + + \frozenprotrudecode % \protrudechars + + \frozentolerancecode % \tolerance \pretolerance + + \frozenstretchcode % \emergcystretch + + \frozenloosenesscode % \looseness + + \frozenlastlinecode % \lastlinefit + + \frozenlinepenaltycode % \linepenalty \interlinepenalty \interlinepenalties + + \frozenclubpenaltycode % \clubpenalty \clubpenalties + + \frozenwidowpenaltycode % \widowpenalty \widowpenalties + + \frozendisplaypenaltycode % \displaypenalty \displaypenalties + + \frozenbrokenpenaltycode % \brokenpenalty + + \frozendemeritscode % \doublehyphendemerits \finalhyphendemerits \adjdemerits + + \frozenshapecode % \parshape + % \frozenlinecode % \baselineskip \lineskip \lineskiplimit +\relax + +\setnewconstant\paragraphlinecodes\numexpr + \frozenlinecode +\relax + +\permanent\protected\def\freezeparagraphproperties {\snapshotpar\frozenparagraphdefault} +\permanent\protected\def\defrostparagraphproperties{\snapshotpar\zerocount} + +\permanent\protected\def\updateparagraphproperties{\ifhmode\snapshotpar\paragraphupdatecodes \fi} +\permanent\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi} +\permanent\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi} +\permanent\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi} +\permanent\protected\def\updateparagraphlines {\ifhmode\snapshotpar\paragraphlinecodes \fi} + +% so far + +\let\spac_paragraph_freeze\relax + +\permanent\protected\def\setparagraphfreezing {\enforced\let\spac_paragraph_freeze\freezeparagraphproperties} +\permanent\protected\def\forgetparagraphfreezing{\enforced\let\spac_paragraph_freeze\relax} + +\installcorenamespace {bparwrap} +\installcorenamespace {eparwrap} +\installcorenamespace {parwrapbefore} +\installcorenamespace {parwrapafter} +\installcorenamespace {parwrapcount} + +\let\spac_paragraph_wrap\relax + +\newcount\c_spac_paragraph_group_level + +\protected\def\spac_paragraph_update + {\c_spac_paragraph_group_level\currentgrouplevel\relax + \ifcsname\??bparwrap\the\c_spac_paragraph_group_level\endcsname + \the\lastnamedcs + \relax + \dontleavehmode % just in case + \wrapuppar{\the\csname\??eparwrap\the\c_spac_paragraph_group_level\endcsname\relax}% + \fi} + +\permanent\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre} +\permanent\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp} + +\protected\def\spac_paragraph_install + {\expandafter\newtoks\csname\??bparwrap\the\currentgrouplevel\endcsname + \expandafter\newtoks\csname\??eparwrap\the\currentgrouplevel\endcsname} + +\def\spac_paragraph_install_count#1% + {\expandafter\newcount\csname\??parwrapcount#1\endcsname} + +\def\spac_paragraph_install_pair#1#2#3% + {\expandafter\newtoks\csname\??parwrapbefore#3\endcsname + \expandafter\newtoks\csname\??parwrapafter #3\endcsname + #1\csname\??bparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapbefore#3\endcsname}% + #2\csname\??eparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapafter #3\endcsname}} + +\def\spac_register_par_wrapper_yes#1#2#3#4#5% + {\ifcsname\??bparwrap\the\currentgrouplevel\endcsname \else + \spac_paragraph_install + \fi + \ifcsname\??parwrapcount#3\endcsname \else + \spac_paragraph_install_count{#3}% + \fi + \ifcsname\??parwrapbefore#3\endcsname \else + \spac_paragraph_install_pair#1#2{#3}% + \fi + #1\csname\??parwrapbefore#3\endcsname{\advance\csname\??parwrapcount#3\endcsname\plusone\relax + \clf_setparwrapper{#3}#4}% + #2\csname\??parwrapafter #3\endcsname{#5}% + \clf_newparwrapper{#3}% + \enforced\let\spac_paragraph_wrap\spac_paragraph_update} + +\def\spac_register_par_wrapper_nop#1#2#3#4#5% + {\ifcsname\??parwrapcount#3\endcsname \else + \spac_paragraph_install_count{#3}% + \fi + \csname\??parwrapcount#3\endcsname\plusone + #4\wrapuppar{#5}} + +\protected\def\spac_register_par_wrapper + {\ifhmode + \expandafter\spac_register_par_wrapper_nop + \else + \expandafter\spac_register_par_wrapper_yes + \fi} + +\permanent\protected\def\forgetparwrapper + {\csname\??bparwrap\the\currentgrouplevel\endcsname\emptytoks + \csname\??eparwrap\the\currentgrouplevel\endcsname\emptytoks} + +\permanent\protected\def\unregisterparwrapper#1% + {\csname\??parwrapcount#1\endcsname\zerocount + \ifcsname\??parwrapbefore#1\endcsname + \lastnamedcs\emptytoks + \csname\??parwrapafter#1\endcsname\emptytoks + \fi} + +\permanent\def\directparwrapper#1#2% + {#1\wrapuppar{#2}} + +\permanent\protected\def\doifelseparwrapper#1% + {\unless\ifcsname\??parwrapcount#1\endcsname + \expandafter\secondoftwoarguments + \orelse\ifcase\lastnamedcs + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +% \getparwrapper % defined in lua +% \lastparwrapper % defined in lua + +\permanent\protected\def\showparwrapperstate#1% + {\begingroup + \infofont ¶#1\hilo + {\smallinfofont\getparwrapper {#1}}% + {\smallinfofont\lastparwrapper{#1}}% + \endgroup} + +%appendtoks\updateparwrapperindeed\to\everypar +%appendtoks\spac_paragraph_wrap \to\everypar +%appendtoks\spac_paragraph_freeze \to\everypar + +\setparagraphfreezing + +\appendtoks\enforced\let\spac_paragraph_wrap\relax\to\everyforgetall + +%D In due time, the code below will be upgraded using the above mechanisms. + +%D The dreadful sequence \type {\bgroup} \unknown\ \type {\carryoverpar} \unknown\ +%D \type {\egroup} is needed when for instance sidefloats are used in combination +%D with something that starts with a group. This is because otherwise the +%D indentation as set (by the output routine) inside the group are forgotten +%D afterwards. (I must not forget its existence). + +\permanent\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable ! + {\normalexpanded + {\noexpand#1% + \hangindent\the\hangindent + \hangafter \the\hangafter + \parskip \the\parskip + \leftskip \the\leftskip + \rightskip \the\rightskip + \relax}} + +\permanent\protected\def\pushparagraphproperties + {\edef\currentparagraphproperties{\carryoverpar\relax}% + \pushmacro\currentparagraphproperties} + +\permanent\protected\def\popparagraphproperties + {\popmacro\currentparagraphproperties + \currentparagraphproperties} + +\permanent\protected\def\flushparagraphproperties + {\popmacro\currentparagraphproperties} + +%D Beware, changing this will break some code (like pos/backgrounds) but it has been +%D 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 + +\permanent\protected\tolerant\def\setupparagraphintro[#1]#*[#2]% + {\def\spac_paragraphs_intro_step##1% + {\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}% + \processcommacommand[#1]\spac_paragraphs_intro_step} + +\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 + \gtoksapp\t_spac_paragraphs_intro_first{#1}% + \glet\insertparagraphintro\spac_paragraphs_flush_intro} + +\setvalue{\??paragraphintro\v!next}#1% + {\global\settrue\c_spac_paragraphs_intro_next + \gtoksapp\t_spac_paragraphs_intro_next{#1}% + \glet\insertparagraphintro\spac_paragraphs_flush_intro} + +\setvalue{\??paragraphintro\v!each}#1% + {\global\settrue\c_spac_paragraphs_intro_each + \gtoksapp\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 + +\permanent\protected\def\flushatparagraph#1% + {\global\c_spac_paragraphs_intro_first\plusone + \gtoksapp\t_spac_paragraphs_intro_first{#1}% + \glet\insertparagraphintro\spac_paragraphs_flush_intro} + +%D Here comes the flusher (we misuse the one level expansion of token registers to +%D feed a nice stream into the paragraph.) + +\protected\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly + {\normalexpanded{% % after another so the first code is there twice + \ifconditional\c_spac_paragraphs_intro_each + \ifconditional\c_spac_paragraphs_intro_next + \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}} + +\protected\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}} + +\protected\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. By using +%D 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 +% +% \protected\def\pushpostponednodedata +% {\global\advance\c_spac_postponed_data\plusone +% \savebox\??postponednodesstack{\the\c_spac_postponed_data}{\box\b_spac_postponed_data}} +% +% \protected\def\poppostponednodedata +% {\global\setbox\b_spac_postponed_data\hbox{\foundbox\??postponednodesstack{\the\c_spac_postponed_data}}% +% \global\advance\c_spac_postponed_data\minusone +% \ifvoid\b_spac_postponed_data\else +% \glet\flushpostponednodedata\spac_postponed_data_flush +% \fi} + +\newtoks\everyflushatnextpar + +\permanent\protected\def\pushpostponednodedata + {\globalpushbox\b_spac_postponed_data} + +\permanent\protected\def\poppostponednodedata + {\globalpopbox\b_spac_postponed_data + \ifvoid\b_spac_postponed_data\else + \glet\flushpostponednodedata\spac_postponed_data_flush + \fi} + +\permanent\protected\def\flushatnextpar + {\begingroup + \the\everyflushatnextpar + \glet\flushpostponednodedata\spac_postponed_data_flush + \dowithnextboxcs\spac_postponed_data_finish\hpack} + +% \def\spac_postponed_data_finish +% {\global\setbox\b_spac_postponed_data\hpack % to\zeropoint +% {\box\b_spac_postponed_data\box\nextbox}% +% \endgroup} +% +% This is better when used with protrusion which does not like too deeply nested +% boxes: +% +% \def\spac_postponed_data_finish +% {\dontcomplain +% \global\setbox\b_spac_postponed_data\hpack to \zeropoint +% {\unhbox\b_spac_postponed_data\unhbox\nextbox}% +% \endgroup} +% +% We could do this if there is content with widths ... not that is should be used +% that way, but this way we don't overflow: + +\def\spac_postponed_data_finish + {\dontcomplain + \global\setbox\b_spac_postponed_data\hpack % to \zeropoint + {\unhbox\b_spac_postponed_data + \scratchdimen\wd\nextbox + \unhbox\nextbox + \ifcase\scratchdimen\else\kern-\b_spac_postponed_data\fi}% + \endgroup} + +\def\spac_postponed_data_flush + {%\iftrialtypesetting \else + \ifvoid\b_spac_postponed_data\else + \hpack{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data + \fi + \glet\flushpostponednodedata\relax + }%\fi} + +\permanent\protected\def\doflushatpar % might be renamed + {\ifvmode + \expandafter\flushatnextpar + \else + \expandafter\firstofoneargument + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/spac-prf.mklx b/tex/context/base/mkxl/spac-prf.mklx new file mode 100644 index 000000000..585437ac4 --- /dev/null +++ b/tex/context/base/mkxl/spac-prf.mklx @@ -0,0 +1,113 @@ +%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 details +%D can change. I moved it into the core because that way we can use it on servers. + +% framed: first reflow then profile + +\unprotect + +\registerctxluafile{spac-prf}{} + +\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] + +\permanent\protected\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} + +\permanent\protected\def\resetprofile + {\c_attr_profilemethod\attributeunsetvalue} + +\permanent\protected\def\useprofileparameter#getparameter% + {\edef\m_spac_profile_asked{#getparameter\c!profile}% + \ifempty\m_spac_profile_asked + \resetprofile + \else + \setprofile[\m_spac_profile_asked]% + \fi} + +\permanent\tolerant\protected\def\profiledbox[#profile]#spacer[#settings]% + {\vbox\bgroup + \ifparameter#settings\or + \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} + +\permanent\protected\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/tex/context/base/mkxl/spac-ver.lmt b/tex/context/base/mkxl/spac-ver.lmt new file mode 100644 index 000000000..90eeacf26 --- /dev/null +++ b/tex/context/base/mkxl/spac-ver.lmt @@ -0,0 +1,2527 @@ +if not modules then modules = { } end modules ['spac-ver'] = { + version = 1.001, + optimize = true, + comment = "companion to spac-ver.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- we also need to call the spacer for inserts! + +-- somehow lists still don't always have proper prev nodes so i need to +-- check all of the luatex code some day .. maybe i should replece the +-- whole mvl handler by lua code .. why not + +-- todo: use lua nodes with lua data (>0.79) +-- see ** can go when 0.79 + +-- needs to be redone, too many calls and tests now ... still within some +-- luatex limitations + +-- this code dates from the beginning and is kind of experimental; it +-- will be optimized and improved soon .. it's way too complex now but +-- dates from less possibilities +-- +-- the collapser will be redone with user nodes; also, we might get make +-- parskip into an attribute and appy it explicitly thereby getting rid +-- of automated injections; eventually i want to get rid of the currently +-- still needed tex -> lua -> tex > lua chain (needed because we can have +-- expandable settings at the tex end + +-- todo: strip baselineskip around display math + +local next, type, tonumber = next, type, tonumber +local gmatch, concat = string.gmatch, table.concat +local ceil, floor, abs = math.ceil, math.floor, math.abs +local lpegmatch = lpeg.match +local unpack = unpack or table.unpack +local allocate = utilities.storage.allocate +local todimen = string.todimen +local formatters = string.formatters + +local nodes = nodes +local trackers = trackers +local attributes = attributes +local context = context +local tex = tex + +local texlists = tex.lists +local texget = tex.get +local texgetcount = tex.getcount +local texgetdimen = tex.getdimen +local texgetglue = tex.getglue +local texset = tex.set +local texsetdimen = tex.setdimen +local texsetcount = tex.setcount +local texnest = tex.nest +local texgetbox = tex.getbox + +local buildpage = tex.triggerbuildpage + +local variables = interfaces.variables +local implement = interfaces.implement + +local v_local = variables["local"] +local v_global = variables["global"] +local v_box = variables.box +----- v_page = variables.page -- reserved for future use +local v_split = variables.split +local v_min = variables.min +local v_max = variables.max +local v_none = variables.none +local v_line = variables.line +local v_noheight = variables.noheight +local v_nodepth = variables.nodepth +local v_line = variables.line +local v_halfline = variables.halfline +local v_line_m = "-" .. v_line +local v_halfline_m = "-" .. v_halfline +local v_first = variables.first +local v_last = variables.last +local v_top = variables.top +local v_bottom = variables.bottom +local v_minheight = variables.minheight +local v_maxheight = variables.maxheight +local v_mindepth = variables.mindepth +local v_maxdepth = variables.maxdepth +local v_offset = variables.offset +local v_strut = variables.strut + +local v_hfraction = variables.hfraction +local v_dfraction = variables.dfraction +local v_bfraction = variables.bfraction +local v_tlines = variables.tlines +local v_blines = variables.blines + +-- vertical space handler + +local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end) +local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end) +local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) +local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) +local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) +local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) +local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end) + +local remove_math_skips = true directives.register("vspacing.removemathskips", function(v) remnove_math_skips = v end) + +local report_vspacing = logs.reporter("vspacing","spacing") +local report_collapser = logs.reporter("vspacing","collapsing") +local report_snapper = logs.reporter("vspacing","snapping") +local report_specials = logs.reporter("vspacing","specials") + +local a_skipcategory = attributes.private('skipcategory') +local a_skippenalty = attributes.private('skippenalty') +local a_skiporder = attributes.private('skiporder') +local a_snapmethod = attributes.private('snapmethod') +local a_snapvbox = attributes.private('snapvbox') + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local setlink = nuts.setlink +local getprev = nuts.getprev +local getid = nuts.getid +local getlist = nuts.getlist +local setlist = nuts.setlist +local getattr = nuts.getattr +local getattrs = nuts.getattrs +local setattr = nuts.setattr +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getwhd = nuts.getwhd +local setwhd = nuts.setwhd +local getprop = nuts.getprop +local setprop = nuts.setprop +local getglue = nuts.getglue +local setglue = nuts.setglue +local getkern = nuts.getkern +local getpenalty = nuts.getpenalty +local setshift = nuts.setshift +local setwidth = nuts.setwidth +local getwidth = nuts.getwidth +local setheight = nuts.setheight +local getheight = nuts.getheight +local setdepth = nuts.setdepth +local getdepth = nuts.getdepth +local setnext = nuts.setnext + +local find_node_tail = nuts.tail +local flush_node = nuts.flush_node +local remove_node = nuts.remove +local count_nodes = nuts.countall +local hpack_node = nuts.hpack +local vpack_node = nuts.vpack +local start_of_par = nuts.start_of_par + +local write_node = nuts.write + +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist + +local nodereference = nuts.reference + +local theprop = nuts.theprop + +local listtoutf = nodes.listtoutf +local nodeidstostring = nodes.idstostring + +local nodepool = nuts.pool + +local new_penalty = nodepool.penalty +local new_kern = nodepool.kern +local new_glue = nodepool.glue +local new_rule = nodepool.rule + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +----- penaltycodes = nodes.penaltycodes +----- listcodes = nodes.listcodes + +local penalty_code = nodecodes.penalty +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local rule_code = nodecodes.rule +local par_code = nodecodes.par + +local userskip_code = gluecodes.userskip +local lineskip_code = gluecodes.lineskip +local baselineskip_code = gluecodes.baselineskip +local parskip_code = gluecodes.parskip +local topskip_code = gluecodes.topskip +local splittopskip_code = gluecodes.splittopskip + +local linelist_code = nodes.listcodes.line + +local properties = nodes.properties.data + +local vspacing = builders.vspacing or { } +builders.vspacing = vspacing + +local vspacingdata = vspacing.data or { } +vspacing.data = vspacingdata + +local snapmethods = vspacingdata.snapmethods or { } +vspacingdata.snapmethods = snapmethods + +storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") + +do + + local default = { + [v_maxheight] = true, + [v_maxdepth] = true, + [v_strut] = true, + [v_hfraction] = 1, + [v_dfraction] = 1, + [v_bfraction] = 0.25, + } + + local fractions = { + [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, + [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, + [v_box] = v_bfraction, + [v_top] = v_tlines, [v_bottom] = v_blines, + } + + local values = { + offset = "offset" + } + + local colonsplitter = lpeg.splitat(":") + + local function listtohash(str) + local t = { } + for s in gmatch(str,"[^, ]+") do + local key, detail = lpegmatch(colonsplitter,s) + local v = variables[key] + if v then + t[v] = true + if detail then + local k = fractions[key] + if k then + detail = tonumber("0" .. detail) + if detail then + t[k] = detail + end + else + k = values[key] + if k then + detail = todimen(detail) + if detail then + t[k] = detail + end + end + end + end + else + detail = tonumber("0" .. key) + if detail then + t[v_hfraction] = detail + t[v_dfraction] = detail + end + end + end + if next(t) then + t[v_hfraction] = t[v_hfraction] or 1 + t[v_dfraction] = t[v_dfraction] or 1 + return t + else + return default + end + end + + function vspacing.definesnapmethod(name,method) + local n = #snapmethods + 1 + local t = listtohash(method) + snapmethods[n] = t + t.name = name -- not interfaced + t.specification = method -- not interfaced + context(n) + end + +end + +local function validvbox(parentid,list) + if parentid == hlist_code then + local id = getid(list) + if id == par_code and start_of_par(list) then + list = getnext(list) + if not next then + return nil + end + end + local done = nil + for n, id in nextnode, list do + if id == vlist_code or id == hlist_code then + if done then + return nil + else + done = n + end + elseif id == glue_code or id == penalty_code then + -- go on + else + return nil -- whatever + end + end + if done then + local id = getid(done) + if id == hlist_code then + return validvbox(id,getlist(done)) + end + end + return done -- only one vbox + end +end + +local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped + -- problem: any snapped vbox ends up in a line + if list and parentid == hlist_code then + local id = getid(list) + if id == par_code and start_of_par(list) then + list = getnext(list) + if not list then + return false + end + end + for n, id in nextnode, list do + if id == hlist_code or id == vlist_code then + -- local a = getattr(n,a_snapmethod) + -- if not a then + -- -- return true -- not snapped at all + -- elseif a == 0 then + -- return true -- already snapped + -- end + local p = getprop(n,"snapper") + if p then + return p + end + elseif id == glue_code or id == penalty_code then -- or id == kern_code then + -- go on + else + return false -- whatever + end + end + end + return false +end + +-- quite tricky: ceil(-something) => -0 + +local function ceiled(n) + if n < 0 or n < 0.01 then + return 0 + else + return ceil(n) + end +end + +local function floored(n) + if n < 0 or n < 0.01 then + return 0 + else + return floor(n) + end +end + +-- check variables.none etc + +local function fixedprofile(current) + local profiling = builders.profiling + return profiling and profiling.fixedprofile(current) +end + +local function snap_hlist(where,current,method,height,depth) -- method[v_strut] is default + if fixedprofile(current) then + return + end + local list = getlist(current) + local t = trace_vsnapping and { } + if t then + t[#t+1] = formatters["list content: %s"](listtoutf(list)) + t[#t+1] = formatters["snap method: %s"](method.name) -- not interfaced + t[#t+1] = formatters["specification: %s"](method.specification) -- not interfaced + end + local snapht, snapdp + if method[v_local] then + -- snapping is done immediately here + snapht = texgetdimen("bodyfontstrutheight") + snapdp = texgetdimen("bodyfontstrutdepth") + if t then + t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp) + end + elseif method[v_global] then + snapht = texgetdimen("globalbodyfontstrutheight") + snapdp = texgetdimen("globalbodyfontstrutdepth") + if t then + t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp) + end + else + -- maybe autolocal + -- snapping might happen later in the otr + snapht = texgetdimen("globalbodyfontstrutheight") + snapdp = texgetdimen("globalbodyfontstrutdepth") + local lsnapht = texgetdimen("bodyfontstrutheight") + local lsnapdp = texgetdimen("bodyfontstrutdepth") + if snapht ~= lsnapht and snapdp ~= lsnapdp then + snapht, snapdp = lsnapht, lsnapdp + end + if t then + t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) + end + end + + local wd, ht, dp = getwhd(current) + + local h = (method[v_noheight] and 0) or height or ht + local d = (method[v_nodepth] and 0) or depth or dp + local hr = method[v_hfraction] or 1 + local dr = method[v_dfraction] or 1 + local br = method[v_bfraction] or 0 + local ch = h + local cd = d + local tlines = method[v_tlines] or 1 + local blines = method[v_blines] or 1 + local done = false + local plusht = snapht + local plusdp = snapdp + local snaphtdp = snapht + snapdp + local extra = 0 + + if t then + t[#t+1] = formatters["hlist: wd %p ht %p (used %p) dp %p (used %p)"](wd,ht,h,dp,d) + t[#t+1] = formatters["fractions: hfraction %s dfraction %s bfraction %s tlines %s blines %s"](hr,dr,br,tlines,blines) + end + + if method[v_box] then + local br = 1 - br + if br < 0 then + br = 0 + elseif br > 1 then + br = 1 + end + local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_box,plusht,plusdp) + end + elseif method[v_max] then + local n = ceiled((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_max,plusht,plusdp) + end + elseif method[v_min] then + -- we catch a lone min + if method.specification ~= v_min then + local n = floored((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if plusht < 0 then + plusht = 0 + end + if plusdp < 0 then + plusdp = 0 + end + end + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_min,plusht,plusdp) + end + elseif method[v_none] then + plusht, plusdp = 0, 0 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_none,0,0) + end + end + -- for now, we actually need to tag a box and then check at several points if something ended up + -- at the top of a page + if method[v_halfline] then -- extra halfline + extra = snaphtdp/2 + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline,plusht,plusdp) + end + end + if method[v_line] then -- extra line + extra = snaphtdp + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line,plusht,plusdp) + end + end + if method[v_halfline_m] then -- extra halfline + extra = - snaphtdp/2 + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline_m,plusht,plusdp) + end + end + if method[v_line_m] then -- extra line + extra = - snaphtdp + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line_m,plusht,plusdp) + end + end + if method[v_first] then + local thebox = current + local id = getid(thebox) + if id == hlist_code then + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) + end + if thebox and id == vlist_code then + local list = getlist(thebox) + local lw, lh, ld + for n in nexthlist, list do + lw, lh, ld = getwhd(n) + break + end + if lh then + local wd, ht, dp = getwhd(thebox) + if t then + t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) + end + local delta = h - lh + ch, cd = lh, delta + d + h, d = ch, cd + local shifted = hpack_node(getlist(current)) + setshift(shifted,delta) + setlist(current,shifted) + done = true + if t then + t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) + end + elseif t then + t[#t+1] = "first: not done, no content" + end + elseif t then + t[#t+1] = "first: not done, no vbox" + end + elseif method[v_last] then + local thebox = current + local id = getid(thebox) + if id == hlist_code then + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) + end + if thebox and id == vlist_code then + local list = getlist(thebox) + local lw, lh, ld + for n in nexthlist, list do + lw, lh, ld = getwhd(n) + end + if lh then + local wd, ht, dp = getwhd(thebox) + if t then + t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) + end + local delta = d - ld + cd, ch = ld, delta + h + h, d = ch, cd + local shifted = hpack_node(getlist(current)) + setshift(shifted,delta) + setlist(current,shifted) + done = true + if t then + t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) + end + elseif t then + t[#t+1] = "last: not done, no content" + end + elseif t then + t[#t+1] = "last: not done, no vbox" + end + end + if method[v_minheight] then + ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht + if t then + t[#t+1] = formatters["minheight: %p"](ch) + end + elseif method[v_maxheight] then + ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht + if t then + t[#t+1] = formatters["maxheight: %p"](ch) + end + else + ch = plusht + if t then + t[#t+1] = formatters["set height: %p"](ch) + end + end + if method[v_mindepth] then + cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp + if t then + t[#t+1] = formatters["mindepth: %p"](cd) + end + elseif method[v_maxdepth] then + cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp + if t then + t[#t+1] = formatters["maxdepth: %p"](cd) + end + else + cd = plusdp + if t then + t[#t+1] = formatters["set depth: %p"](cd) + end + end + if method[v_top] then + ch = ch + tlines * snaphtdp + if t then + t[#t+1] = formatters["top height: %p"](ch) + end + end + if method[v_bottom] then + cd = cd + blines * snaphtdp + if t then + t[#t+1] = formatters["bottom depth: %p"](cd) + end + end + local offset = method[v_offset] + if offset then + -- we need to set the attr + if t then + local wd, ht, dp = getwhd(current) + t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) + end + local shifted = hpack_node(getlist(current)) + setshift(shifted,offset) + setlist(current,shifted) + if t then + local wd, ht, dp = getwhd(current) + t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) + end + setattr(shifted,a_snapmethod,0) + setattr(current,a_snapmethod,0) + end + if not height then + setheight(current,ch) + if t then + t[#t+1] = formatters["forced height: %p"](ch) + end + end + if not depth then + setdepth(current,cd) + if t then + t[#t+1] = formatters["forced depth: %p"](cd) + end + end + local lines = (ch+cd)/snaphtdp + if t then + local original = (h+d)/snaphtdp + local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth")) + t[#t+1] = formatters["final lines : %p -> %p (%p)"](original,lines,whatever) + t[#t+1] = formatters["final height: %p -> %p"](h,ch) + t[#t+1] = formatters["final depth : %p -> %p"](d,cd) + end +-- todo: +-- +-- if h < 0 or d < 0 then +-- h = 0 +-- d = 0 +-- end + if t then + report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t) + end + if not method[v_split] then + -- so extra will not be compensated at the top of a page + extra = 0 + end + return h, d, ch, cd, lines, extra +end + +local categories = { + [0] = "discard", + [1] = "largest", + [2] = "force", + [3] = "penalty", + [4] = "add", + [5] = "disable", + [6] = "nowhite", + [7] = "goback", + [8] = "packed", + [9] = "overlay", + [10] = "enable", + [11] = "notopskip", +} + +categories = allocate(table.swapped(categories,categories)) +vspacing.categories = categories + +function vspacing.tocategories(str) + local t = { } + for s in gmatch(str,"[^, ]") do -- use lpeg instead + local n = tonumber(s) + if n then + t[categories[n]] = true + else + t[b] = true + end + end + return t +end + +function vspacing.tocategory(str) -- can be optimized + if type(str) == "string" then + return set.tonumber(vspacing.tocategories(str)) + else + return set.tonumber({ [categories[str]] = true }) + end +end + +vspacingdata.map = vspacingdata.map or { } -- allocate ? +vspacingdata.skip = vspacingdata.skip or { } -- allocate ? + +storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map") +storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip") + +do + + local P, C, R, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs + + vspacing.fixed = false + + local map = vspacingdata.map + local skip = vspacingdata.skip + + local sign = S("+-")^0 + local multiplier = C(sign * R("09")^1) * P("*") + local singlefier = Cs(sign * Cc(1)) + local separator = S(", ") + local category = P(":") * C((1-separator)^1) + local keyword = C((1-category-separator)^1) + local splitter = (multiplier + Cc(1)) * keyword * (category + Cc(false)) + + local k_fixed = variables.fixed + local k_flexible = variables.flexible + local k_category = "category" + local k_penalty = "penalty" + local k_order = "order" + + function vspacing.setmap(from,to) + map[from] = to + end + + function vspacing.setskip(key,value,grid) + if value ~= "" then + if grid == "" then grid = value end + skip[key] = { value, grid } + end + end + + local expandmacro = token.expand_macro + -- local runlocal = tex.runlocal + -- local setmacro = tokens.setters.macro + -- local settoks = tex.settoks + local toscaled = tex.toscaled + + local setattrs = nuts.setattrs + + local b_done = false + local b_packed = false + + local b_amount = 0 + local b_stretch = 0 + local b_shrink = 0 + local b_category = false + local b_penalty = false + local b_order = false + local b_fixed = false + local b_grid = false + + local pattern = nil + + local packed = categories.packed + + local gluefactor = .25 + + local ctx_ignoreparskip = context.core.ignoreparskip + + local function before() + b_amount = 0 + b_stretch = 0 + b_shrink = 0 + b_category = 1 + b_penalty = false + b_order = false + b_fixed = b_grid + end + + local function after() + if fixed then + b_stretch = 0 + b_shrink = 0 + else + b_stretch = gluefactor * b_amount + b_shrink = gluefactor * b_amount + end + end + + -- use a cache for predefined ones + + local function inject() + local n = new_glue(b_amount,b_stretch,b_shrink) + setattrs(n,false,a_skipcategory,b_category,a_skippenalty,b_penalty,a_skiporder,b_order or 1) + write_node(n) + end + + local function flush() + after() + if b_done then + inject() + b_done = false + end + before() + end + + -- local cmd = token.create("vspacingfromtempstring") + -- local cmd = token.create("vspacingpredefinedvalue") -- not yet known + + local function handler(multiplier, keyword, detail) + if not keyword then + report_vspacing("unknown directive %a",s) + else + local mk = map[keyword] + if mk then + lpegmatch(pattern,mk) + elseif keyword == k_fixed then + b_fixed = true + elseif keyword == k_flexible then + b_flexible = false + elseif keyword == k_category then + local category = tonumber(detail) + if category == packed then + b_packed = true + elseif category then + b_category = category + b_done = true + flush() + end + elseif keyword == k_order and detail then + local order = tonumber(detail) + if order then + b_order = order + end + elseif keyword == k_penalty and detail then + local penalty = tonumber(detail) + if penalty then + flush() + b_done = true + b_category = 3 + b_penalty = penalty + flush() + end + else + local amount, stretch, shrink + multiplier = tonumber(multiplier) or 1 + local sk = skip[keyword] + if sk then + -- multiplier, keyword + -- best, for now, todo: runlocal with arguments + expandmacro("vspacingpredefinedvalue",true,keyword) + -- expandmacro(cmd,true,keyword) + -- setmacro("tempstring",keyword) + -- runlocal(cmd) + -- nicest + -- runlocal(cache[keyword]) + -- fast + -- settoks("scratchtoks",keyword) + -- runlocal("vspacingfromscratchtoks") + -- middleground + -- setmacro("tempstring",keyword) + -- runlocal(ctx_vspacingfromtempstring) + -- + amount, stretch, shrink = texgetglue("scratchskip") + if not stretch then + stretch = 0 + end + if not shrink then + shrink = 0 + end + if stretch == 0 and shrink == 0 then + stretch = gluefactor * amount -- always unless grid + shrink = stretch -- always unless grid + end + else -- no check, todo: parse plus and minus + amount = toscaled(keyword) + stretch = gluefactor * amount -- always unless grid + shrink = stretch -- always unless grid + end + -- we look at fixed later + b_amount = b_amount + multiplier * amount + b_stretch = b_stretch + multiplier * stretch + b_shrink = b_shrink + multiplier * shrink + b_done = true + end + end + end + + -- alternatively we can make a table and have a keyword -> split cache but this is probably + -- not really a bottleneck + + local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler + pattern = (splitter + separator^1)^0 + + function vspacing.inject(grid,str) + if trace_vspacing then + -- ctx_pushlogger(report_vspacing) + end + b_done = false + b_packed = false + b_grid = gridsnapping + before() + lpegmatch(pattern,str) + after() + if b_done then + inject() + end + if b_packed then + ctx_ignoreparskip() + end + if trace_vspacing then + -- ctx_poplogger() + end + end + + function vspacing.injectpenalty(penalty) + local n = new_glue() + setattrs(n,false,a_skipcategory,categories.penalty,a_skippenalty,penalty,a_skiporder,1) + write_node(n) + end + + function vspacing.injectskip(amount) + local n = new_glue(amount) + setattrs(n,false,a_skipcategory,categories.largest,a_skippenalty,false,a_skiporder,1) + write_node(n) + end + + function vspacing.injectdisable(amount) + local n = new_glue() + setattrs(n,false,a_skipcategory,categories.disable,a_skippenalty,false,a_skiporder,1) + write_node(n) + end + +end + +-- implementation + +-- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display + +function vspacing.snapbox(n,how) + local sv = snapmethods[how] + if sv then + local box = getbox(n) + local list = getlist(box) + if list then + local s = getattr(list,a_snapmethod) + if s == 0 then + if trace_vsnapping then + -- report_snapper("box list not snapped, already done") + end + else + local wd, ht, dp = getwhd(box) + if false then -- todo: already_done + -- assume that the box is already snapped + if trace_vsnapping then + report_snapper("box list already snapped at (%p,%p): %s", + ht,dp,listtoutf(list)) + end + else + local h, d, ch, cd, lines, extra = snap_hlist("box",box,sv,ht,dp) + setprop(box,"snapper",{ + ht = h, + dp = d, + ch = ch, + cd = cd, + extra = extra, + current = current, + }) + setwhd(box,wd,ch,cd) + if trace_vsnapping then + report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", + h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) + end + setattr(box,a_snapmethod,0) -- + setattr(list,a_snapmethod,0) -- yes or no + end + end + end + end +end + +-- I need to figure out how to deal with the prevdepth that crosses pages. In fact, +-- prevdepth is often quite interfering (even over a next paragraph) so I need to +-- figure out a trick. Maybe use something other than a rule. If we visualize we'll +-- see the baselineskip in action: +-- +-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page +-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page +-- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page + +-- We can register and copy the rule instead. + +do + + local insert_node_after = nuts.insert_after + local insert_node_before = nuts.insert_before + + local abovedisplayskip_code = gluecodes.abovedisplayskip + local belowdisplayskip_code = gluecodes.belowdisplayskip + local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip + local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip + + local w, h, d = 0, 0, 0 + ----- w, h, d = 100*65536, 65536, 65536 + + local trace_list = { } + local tracing_info = { } + local before = "" + local after = "" + + local function nodes_to_string(head) + local current = head + local t = { } + while current do + local id = getid(current) + local ty = nodecodes[id] + if id == penalty_code then + t[#t+1] = formatters["%s:%s"](ty,getpenalty(current)) + elseif id == glue_code then + t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current)) + elseif id == kern_code then + t[#t+1] = formatters["%s:%p"](ty,getkern(current)) + else + t[#t+1] = ty + end + current = getnext(current) + end + return concat(t," + ") + end + + local function reset_tracing(head) + trace_list, tracing_info, before, after = { }, false, nodes_to_string(head), "" + end + + local function trace_skip(str,sc,so,sp,data) + trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getwidth(data), sc or "-", so or "-", sp or "-") } + tracing_info = true + end + + local function trace_natural(str,data) + trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getwidth(data)) } + tracing_info = true + end + + local function trace_info(message, where, what) + trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) } + end + + local function trace_node(what) + local nt = nodecodes[getid(what)] + local tl = trace_list[#trace_list] + if tl and tl[1] == "node" then + trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } + else + trace_list[#trace_list+1] = { "node", nt } + end + end + + local function show_tracing(head) + if tracing_info then + after = nodes_to_string(head) + for i=1,#trace_list do + local tag, text = unpack(trace_list[i]) + if tag == "info" then + report_collapser(text) + else + report_collapser(" %s: %s",tag,text) + end + end + report_collapser("before: %s",before) + report_collapser("after : %s",after) + end + end + + local function trace_done(str,data) + if getid(data) == penalty_code then + trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getpenalty(data)) } + else + trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getwidth(data)) } + end + tracing_info = true + end + + local function forced_skip(head,current,width,where,trace) -- looks old ... we have other tricks now + if head == current then + if getsubtype(head) == baselineskip_code then + width = width - getwidth(head) + end + end + if width == 0 then + -- do nothing + elseif where == "after" then + head, current = insert_node_after(head,current,new_rule(w,h,d)) + head, current = insert_node_after(head,current,new_kern(width)) + head, current = insert_node_after(head,current,new_rule(w,h,d)) + else + local c = current + head, current = insert_node_before(head,current,new_rule(w,h,d)) + head, current = insert_node_before(head,current,new_kern(width)) + head, current = insert_node_before(head,current,new_rule(w,h,d)) + current = c + end + if trace then + report_vspacing("inserting forced skip of %p",width) + end + return head, current + end + + -- penalty only works well when before skip + + local discard = categories.discard + local largest = categories.largest + local force = categories.force + local penalty = categories.penalty + local add = categories.add + local disable = categories.disable + local nowhite = categories.nowhite + local goback = categories.goback + local packed = categories.packed + local overlay = categories.overlay + local enable = categories.enable + local notopskip = categories.notopskip + + -- [whatsits][hlist][glue][glue][penalty] + + local special_penalty_min = 32250 + local special_penalty_max = 35000 + local special_penalty_xxx = 0 + + -- this is rather messy and complex: we want to make sure that successive + -- header don't break but also make sure that we have at least a decent + -- break when we have succesive ones (often when testing) + + -- todo: mark headers as such so that we can recognize them + + local specialmethods = { } + local specialmethod = 1 + + specialmethods[1] = function(pagehead,pagetail,start,penalty) + -- + if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then + return + end + local current = pagetail + -- + -- nodes.showsimplelist(pagehead,0) + -- + if trace_specials then + report_specials("checking penalty %a",penalty) + end + while current do + local id = getid(current) + if id == penalty_code then + local p = properties[current] + if p then + local p = p.special_penalty + if not p then + if trace_specials then + report_specials(" regular penalty, continue") + end + elseif p == penalty then + if trace_specials then + report_specials(" context penalty %a, same level, overloading",p) + end + return special_penalty_xxx + elseif p > special_penalty_min and p < special_penalty_max then + if penalty < p then + if trace_specials then + report_specials(" context penalty %a, lower level, overloading",p) + end + return special_penalty_xxx + else + if trace_specials then + report_specials(" context penalty %a, higher level, quitting",p) + end + return + end + elseif trace_specials then + report_specials(" context penalty %a, higher level, continue",p) + end + else + local p = getpenalty(current) + if p < 10000 then + -- assume some other mechanism kicks in so we seem to have content + if trace_specials then + report_specials(" regular penalty %a, quitting",p) + end + break + else + if trace_specials then + report_specials(" regular penalty %a, continue",p) + end + end + end + end + current = getprev(current) + end + -- none found, so no reson to be special + if trace_specials then + if pagetail then + report_specials(" context penalty, discarding, nothing special") + else + report_specials(" context penalty, discarding, nothing preceding") + end + end + return special_penalty_xxx + end + + -- This will be replaced after 0.80+ when we have a more robust look-back and + -- can look at the bigger picture. + + -- todo: look back and when a special is there before a list is seen penalty keep ut + + -- we now look back a lot, way too often + + -- userskip + -- lineskip + -- baselineskip + -- parskip + -- abovedisplayskip + -- belowdisplayskip + -- abovedisplayshortskip + -- belowdisplayshortskip + -- topskip + -- splittopskip + + -- we could inject a vadjust to force a recalculation .. a mess + -- + -- So, the next is far from robust and okay but for the moment this overlaying + -- has to do. Always test this with the examples in spac-ver.mkvi! + + local function snap_topskip(current,method) + local w = getwidth(current) + setwidth(current,0) + return w, 0 + end + + local function check_experimental_overlay(head,current) + local p = nil + local c = current + local n = nil + local function overlay(p,n,mvl) + local p_wd, p_ht, p_dp = getwhd(p) + local n_wd, n_ht, n_dp = getwhd(n) + local skips = 0 + -- + -- We deal with this at the tex end .. we don't see spacing .. enabling this code + -- is probably harmless but then we need to test it. + -- + -- we could calculate this before we call + -- + -- problem: prev list and next list can be unconnected + -- + local c = getnext(p) + local l = c + while c and c ~= n do + local id = getid(c) + if id == glue_code then + skips = skips + getwidth(c) + elseif id == kern_code then + skips = skips + getkern(c) + end + l = c + c = getnext(c) + end + local c = getprev(n) + while c and c ~= n and c ~= l do + local id = getid(c) + if id == glue_code then + skips = skips + getwidth(c) + elseif id == kern_code then + skips = skips + getkern(c) + end + c = getprev(c) + end + -- + local delta = n_ht + skips + p_dp + texsetdimen("global","d_spac_overlay",-delta) -- for tracing + -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak + local k = new_kern(-delta) + head = insert_node_before(head,n,k) + if n_ht > p_ht then + local k = new_kern(n_ht-p_ht) + head = insert_node_before(head,p,k) + end + if trace_vspacing then + report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta) + end + return remove_node(head,current,true) + end + + -- goto next line + while c do + local id = getid(c) + if id == glue_code or id == penalty_code or id == kern_code then + -- skip (actually, remove) + c = getnext(c) + elseif id == hlist_code then + n = c + break + else + break + end + end + if n then + -- we have a next line, goto prev line + c = current + while c do + local id = getid(c) + if id == glue_code or id == penalty_code then -- kern ? + c = getprev(c) + elseif id == hlist_code then + p = c + break + else + break + end + end + if not p then + if a_snapmethod == a_snapvbox then + -- quit, we're not on the mvl + else + -- inefficient when we're at the end of a page + local c = tonut(texlists.page_head) + while c and c ~= n do + local id = getid(c) + if id == hlist_code then + p = c + end + c = getnext(c) + end + if p and p ~= n then + return overlay(p,n,true) + end + end + elseif p ~= n then + return overlay(p,n,false) + end + end + -- in fact, we could try again later ... so then no remove (a few tries) + return remove_node(head,current,true) + end + + local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail + if trace then + reset_tracing(head) + end + local current = head + local oldhead = head + local glue_order = 0 + local glue_data + local force_glue = false + local penalty_order = 0 + local penalty_data + local natural_penalty + local special_penalty + local parskip + local ignore_parskip = false + local ignore_following = false + local ignore_whitespace = false + local keep_together = false + local lastsnap + local pagehead + local pagetail + -- + -- todo: keep_together: between headers + -- + local function getpagelist() + if not pagehead then + pagehead = texlists.page_head + if pagehead then + pagehead = tonut(pagehead) + pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet + end + end + end + -- + local function compensate(n) + local g = 0 + while n and getid(n) == glue_code do + g = g + getwidth(n) + n = getnext(n) + end + if n then + local p = getprop(n,"snapper") + if p then + local extra = p.extra + if extra and extra < 0 then -- hm, extra can be unset ... needs checking + local h = p.ch -- getheight(n) + -- maybe an extra check + -- if h - extra < g then + setheight(n,h-2*extra) + p.extra = 0 + if trace_vsnapping then + report_snapper("removed extra space at top: %p",extra) + end + -- end + end + end + return n + end + end + -- + local function removetopsnap() + getpagelist() + if pagehead then + local n = pagehead and compensate(pagehead) + if n and n ~= pagetail then + local p = getprop(pagetail,"snapper") + if p then + local e = p.extra + if e and e < 0 then + local t = texget("pagetotal") + if t > 0 then + local g = texget("pagegoal") -- 1073741823 is signal + local d = g - t + if d < -e then + local penalty = new_penalty(1000000) + setlink(penalty,head) + head = penalty + report_snapper("force pagebreak due to extra space at bottom: %p",e) + end + end + end + end + end + elseif head then + compensate(head) + end + end + -- + local function getavailable() + getpagelist() + if pagehead then + local t = texget("pagetotal") + if t > 0 then + local g = texget("pagegoal") + return g - t + end + end + return false + end + -- + local function flush(why) + if penalty_data then + local p = new_penalty(penalty_data) + if trace then + trace_done("flushed due to " .. why,p) + end + if penalty_data >= 10000 then -- or whatever threshold? + local prev = getprev(current) + if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue + -- tricky case: spacing/grid-007.tex: glue penalty glue + head = insert_node_before(head,prev,p) + else + head = insert_node_before(head,current,p) + end + else + head = insert_node_before(head,current,p) + end + -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end + -- end + end + if glue_data then + if force_glue then + if trace then + trace_done("flushed due to forced " .. why,glue_data) + end + head = forced_skip(head,current,getwidth(glue_data,width),"before",trace) + flush_node(glue_data) + else + local width, stretch, shrink = getglue(glue_data) + if width ~= 0 then + if trace then + trace_done("flushed due to non zero " .. why,glue_data) + end + head = insert_node_before(head,current,glue_data) + elseif stretch ~= 0 or shrink ~= 0 then + if trace then + trace_done("flushed due to stretch/shrink in" .. why,glue_data) + end + head = insert_node_before(head,current,glue_data) + else + -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w) + flush_node(glue_data) + end + end + end + + if trace then + trace_node(current) + end + glue_order, glue_data, force_glue = 0, nil, false + penalty_order, penalty_data, natural_penalty = 0, nil, nil + parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false + end + -- + if trace_vsnapping then + report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p", + texgetdimen("globalbodyfontstrutheight"), + texgetdimen("globalbodyfontstrutdepth"), + texgetdimen("bodyfontstrutheight"), + texgetdimen("bodyfontstrutdepth") + ) + end + if trace then + trace_info("start analyzing",where,what) + end + if snap and where == "page" then + removetopsnap() + end + while current do + local id = getid(current) + if id == hlist_code or id == vlist_code then + -- needs checking, why so many calls + if snap then + lastsnap = nil + local list = getlist(current) + local s = getattr(current,a_snapmethod) + if not s then + -- if trace_vsnapping then + -- report_snapper("mvl list not snapped") + -- end + elseif s == 0 then + if trace_vsnapping then + report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list)) + end + else + local sv = snapmethods[s] + if sv then + -- check if already snapped + local done = list and already_done(id,list,a_snapmethod) + if done then + -- assume that the box is already snapped + if trace_vsnapping then + local w, h, d = getwhd(current) + report_snapper("mvl list already snapped at (%p,%p): %s",h,d,listtoutf(list)) + end + else + local h, d, ch, cd, lines, extra = snap_hlist("mvl",current,sv,false,false) + lastsnap = { + ht = h, + dp = d, + ch = ch, + cd = cd, + extra = extra, + current = current, + } + setprop(current,"snapper",lastsnap) + if trace_vsnapping then + report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", + nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list)) + end + end + elseif trace_vsnapping then + report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) + end + setattr(current,a_snapmethod,0) + end + else + -- + end + -- tex.prevdepth = 0 + flush("list") + current = getnext(current) + elseif id == penalty_code then + -- natural_penalty = getpenalty(current) + -- if trace then + -- trace_done("removed penalty",current) + -- end + -- head, current = remove_node(head,current,true) + current = getnext(current) + elseif id == kern_code then + if snap and trace_vsnapping and getkern(current) ~= 0 then + report_snapper("kern of %p kept",getkern(current)) + end + flush("kern") + current = getnext(current) + elseif id == glue_code then + local subtype = getsubtype(current) + if subtype == userskip_code then + local sc, so, sp = getattrs(current,a_skipcategory,a_skiporder,a_skippenalty) + if not so then + so = 1 -- the others have no default value + end + if sp and sc == penalty then + if where == "page" then + getpagelist() + local p = specialmethods[specialmethod](pagehead,pagetail,current,sp) + if p then + -- todo: other tracer + -- + -- if trace then + -- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod) + -- end + special_penalty = sp + sp = p + end + end + if not penalty_data then + penalty_data = sp + elseif penalty_order < so then + penalty_order, penalty_data = so, sp + elseif penalty_order == so and sp > penalty_data then + penalty_data = sp + end + if trace then + trace_skip("penalty in skip",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif not sc then -- if not sc then + if glue_data then + if trace then + trace_done("flush",glue_data) + end + head = insert_node_before(head,current,glue_data) + if trace then + trace_natural("natural",current) + end + current = getnext(current) + glue_data = nil + else + -- not look back across head + -- todo: prev can be whatsit (latelua) + local previous = getprev(current) + if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then + local pwidth, pstretch, pshrink, pstretch_order, pshrink_order = getglue(previous) + local cwidth, cstretch, cshrink, cstretch_order, cshrink_order = getglue(current) + if pstretch_order == 0 and pshrink_order == 0 and cstretch_order == 0 and cshrink_order == 0 then + setglue(previous,pwidth + cwidth, pstretch + cstretch, pshrink + cshrink) + if trace then + trace_natural("removed",current) + end + head, current = remove_node(head,current,true) + if trace then + trace_natural("collapsed",previous) + end + else + if trace then + trace_natural("filler",current) + end + current = getnext(current) + end + else + if trace then + trace_natural("natural (no prev)",current) + end + current = getnext(current) + end + end + glue_order = 0 + elseif sc == disable or sc == enable then + local next = getnext(current) + if next then + ignore_following = sc == disable + if trace then + trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + else + current = next + end + elseif sc == packed then + if trace then + trace_skip("packed",sc,so,sp,current) + end + -- can't happen ! + head, current = remove_node(head,current,true) + elseif sc == nowhite then + local next = getnext(current) + if next then + ignore_whitespace = true + head, current = remove_node(head,current,true) + else + current = next + end + elseif sc == discard then + if trace then + trace_skip("discard",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif sc == overlay then + -- todo (overlay following line over previous + if trace then + trace_skip("overlay",sc,so,sp,current) + end + -- beware: head can actually be after the affected nodes as + -- we look back ... some day head will the real head + head, current = check_experimental_overlay(head,current,a_snapmethod) + elseif ignore_following then + if trace then + trace_skip("disabled",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif not glue_data then + if trace then + trace_skip("assign",sc,so,sp,current) + end + glue_order = so + head, current, glue_data = remove_node(head,current) + elseif glue_order < so then + if trace then + trace_skip("force",sc,so,sp,current) + end + glue_order = so + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif glue_order == so then + -- is now exclusive, maybe support goback as combi, else why a set + if sc == largest then + local cw = getwidth(current) + local gw = getwidth(glue_data) + if cw > gw then + if trace then + trace_skip("largest",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + else + if trace then + trace_skip("remove smallest",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + elseif sc == goback then + if trace then + trace_skip("goback",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif sc == force then + -- last one counts, some day we can provide an accumulator and largest etc + -- but not now + if trace then + trace_skip("force",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif sc == penalty then + if trace then + trace_skip("penalty",sc,so,sp,current) + end + flush_node(glue_data) + glue_data = nil + head, current = remove_node(head,current,true) + elseif sc == add then + if trace then + trace_skip("add",sc,so,sp,current) + end + local cwidth, cstretch, cshrink = getglue(current) + local gwidth, gstretch, gshrink = getglue(glue_data) + setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink) + -- toto: order + head, current = remove_node(head,current,true) + else + if trace then + trace_skip("unknown",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + else + if trace then + trace_skip("unknown",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + if sc == force then + force_glue = true + end + elseif subtype == lineskip_code then + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + setwidth(current,0) + if trace_vsnapping then + report_snapper("lineskip set to zero") + end + else + if trace then + trace_skip("lineskip",sc,so,sp,current) + end + flush("lineskip") + end + else + if trace then + trace_skip("lineskip",sc,so,sp,current) + end + flush("lineskip") + end + current = getnext(current) + elseif subtype == baselineskip_code then + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + setwidth(current,0) + if trace_vsnapping then + report_snapper("baselineskip set to zero") + end + else + if trace then + trace_skip("baselineskip",sc,so,sp,current) + end + flush("baselineskip") + end + else + if trace then + trace_skip("baselineskip",sc,so,sp,current) + end + flush("baselineskip") + end + current = getnext(current) + elseif subtype == parskip_code then + -- parskip always comes later + if ignore_whitespace then + if trace then + trace_natural("ignored parskip",current) + end + head, current = remove_node(head,current,true) + elseif glue_data then + local w = getwidth(current) + if w ~= 0 and w > getwidth(glue_data) then +flush_node(glue_data) + glue_data = current + if trace then + trace_natural("taking parskip",current) + end + head, current = remove_node(head,current) + else + if trace then + trace_natural("removed parskip",current) + end + head, current = remove_node(head,current,true) + end + else + if trace then + trace_natural("honored parskip",current) + end + head, current, glue_data = remove_node(head,current) + end + elseif subtype == topskip_code or subtype == splittopskip_code then + local next = getnext(current) + if next and getattr(next,a_skipcategory) == notopskip then + nuts.setglue(current) -- zero + end + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + local sv = snapmethods[s] + local w, cw = snap_topskip(current,sv) + if trace_vsnapping then + report_snapper("topskip snapped from %p to %p for %a",w,cw,where) + end + else + if trace then + trace_skip("topskip",sc,so,sp,current) + end + flush("topskip") + end + else + if trace then + trace_skip("topskip",sc,so,sp,current) + end + flush("topskip") + end + current = getnext(current) + elseif subtype == abovedisplayskip_code and remove_math_skips then + -- + if trace then + trace_skip("above display skip (normal)",sc,so,sp,current) + end + flush("above display skip (normal)") + current = getnext(current) + -- + elseif subtype == belowdisplayskip_code and remove_math_skips then + -- + if trace then + trace_skip("below display skip (normal)",sc,so,sp,current) + end + flush("below display skip (normal)") + current = getnext(current) + -- + elseif subtype == abovedisplayshortskip_code and remove_math_skips then + -- + if trace then + trace_skip("above display skip (short)",sc,so,sp,current) + end + flush("above display skip (short)") + current = getnext(current) + -- + elseif subtype == belowdisplayshortskip_code and remove_math_skips then + -- + if trace then + trace_skip("below display skip (short)",sc,so,sp,current) + end + flush("below display skip (short)") + current = getnext(current) + -- + else -- other glue + if snap and trace_vsnapping then + local w = getwidth(current) + if w ~= 0 then + report_snapper("glue %p of type %a kept",w,gluecodes[subtype]) + end + end + if trace then + trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) + end + flush("some glue") + current = getnext(current) + end + else + flush(trace and formatters["node with id %a"](id) or "other node") + current = getnext(current) + end + end + if trace then + trace_info("stop analyzing",where,what) + end + -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then + -- penalty_data = natural_penalty + -- end + if trace and (glue_data or penalty_data) then + trace_info("start flushing",where,what) + end + local tail + if penalty_data then + tail = find_node_tail(head) + local p = new_penalty(penalty_data) + if trace then + trace_done("result",p) + end + setlink(tail,p) + -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end + -- end + end + if glue_data then + if not tail then tail = find_node_tail(head) end + if trace then + trace_done("result",glue_data) + end + if force_glue then + head, tail = forced_skip(head,tail,getwidth(glue_data),"after",trace) + flush_node(glue_data) + glue_data = nil + elseif tail then + setlink(tail,glue_data) +setnext(glue_data) + else + head = glue_data + end + texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler + end + if trace then + if glue_data or penalty_data then + trace_info("stop flushing",where,what) + end + show_tracing(head) + if oldhead ~= head then + trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) + end + end + return head + end + + local stackhead, stacktail, stackhack = nil, nil, false + + local function report(message,where,lst) + if lst and where then + report_vspacing(message,where,count_nodes(lst,true),nodeidstostring(lst)) + else + report_vspacing(message,count_nodes(lst,true),nodeidstostring(lst)) + end + end + + -- ugly code: we get partial lists (check if this stack is still okay) ... and we run + -- into temp nodes (sigh) + + local forceflush = false + + function vspacing.pagehandler(newhead,where) + if newhead then + local newtail = find_node_tail(newhead) -- best pass that tail, known anyway + local flush = false + stackhack = true -- todo: only when grid snapping once enabled + -- todo: fast check if head = tail + for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes + if id ~= glue_code then + flush = true + elseif subtype == userskip_code then + if getattr(n,a_skipcategory) then + stackhack = true + else + flush = true + end + elseif subtype == parskip_code then + -- if where == new_graf then ... end + if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then + -- texsetcount("c_spac_vspacing_ignore_parskip",0) + setglue(n) + -- maybe removenode + end + end + end + texsetcount("c_spac_vspacing_ignore_parskip",0) + + if forceflush then + forceflush = false + flush = true + end + + if flush then + if stackhead then + if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end + setlink(stacktail,newhead) + newhead = stackhead + stackhead = nil + stacktail = nil + end + if stackhack then + stackhack = false + if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end + newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + else + if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end + end + return newhead + else + if stackhead then + if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end + setlink(stacktail,newhead) + else + if trace_collect_vspacing then report("%s > storing %s nodes in stack (initial): %s",where,newhead) end + stackhead = newhead + end + stacktail = newtail + end + end + return nil + end + + function vspacing.pageoverflow() + local h = 0 + if stackhead then + for n, id in nextnode, stackhead do + if id == glue_code then + h = h + getwidth(n) + elseif id == kern_code then + h = h + getkern(n) + end + end + end + return h + end + + function vspacing.forcepageflush() + forceflush = true + end + + local ignore = table.tohash { + "split_keep", + "split_off", + -- "vbox", + } + + function vspacing.vboxhandler(head,where) + if head and not ignore[where] and getnext(head) then + if getnext(head) then -- what if a one liner and snapping? + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + return head + end + end + return head + end + + function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod + local box = getbox(n) + if box then + local list = getlist(box) + if list then + list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod) + if aslist then + setlist(box,list) -- beware, dimensions of box are wrong now + else + setlist(box,vpack_node(list)) + end + end + end + end + +end + +-- This one is needed to prevent bleeding of prevdepth to the next page +-- which doesn't work well with forced skips. I'm not that sure if the +-- following is a good way out. + +do + + local outer = texnest[0] + + local enabled = true + local trace = false + local report = logs.reporter("vspacing") + + trackers.register("vspacing.synchronizepage",function(v) + trace = v + end) + + directives.register("vspacing.synchronizepage",function(v) + enabled = v + end) + + local ignoredepth = -65536000 + + -- A previous version analyzed the number of lines moved to the next page in + -- synchronizepage because prevgraf is unreliable in that case. However, we cannot + -- tweak that parameter because it is also used in postlinebreak and hangafter, so + -- there is a danger for interference. Therefore we now do it dynamically. + + -- We can also support other lists but there prevgraf probably is ok. + + function vspacing.getnofpreviouslines(head) + if enabled then + if not thead then + head = texlists.page_head + end + local noflines = 0 + if head then + local tail = find_node_tail(tonut(head)) + while tail do + local id = getid(tail) + if id == hlist_code then + if getsubtype(tail) == linelist_code then + noflines = noflines + 1 + else + break + end + elseif id == vlist_code then + break + elseif id == glue_code then + local subtype = getsubtype(tail) + if subtype == baselineskip_code or subtype == lineskip_code then + -- we're ok + elseif subtype == parskip_code then + if getwidth(tail) > 0 then + break + else + -- we assume we're ok + end + end + elseif id == penalty_code then + -- we're probably ok + elseif id == rule_code or id == kern_code then + break + else + -- ins, mark, boundary, whatsit + end + tail = getprev(tail) + end + end + return noflines + end + end + + interfaces.implement { + name = "getnofpreviouslines", + public = true, + actions = vspacing.getnofpreviouslines, + } + + function vspacing.synchronizepage() + if enabled then + if trace then + local newdepth = outer.prevdepth + local olddepth = newdepth + if not texlists.page_head then + newdepth = ignoredepth + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth) + -- report("list %s",nodes.idsandsubtypes(head)) + else + if not texlists.page_head then + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + end + end + end + + local trace = false + local last = nil + local vmode_code = tex.modelevels.vertical + local temp_code = nodecodes.temp + local getnest = tex.getnest + local getlist = tex.getlist + + trackers.register("vspacing.forcestrutdepth",function(v) trace = v end) + + -- abs : negative is inner + + function vspacing.checkstrutdepth(depth) + local nest = getnest() + if abs(nest.mode) == vmode_code and nest.head then + local tail = nest.tail + local id = tail.id + if id == hlist_code then + if tail.depth < depth then + tail.depth = depth + end + nest.prevdepth = depth + elseif id == temp_code and getnest("ptr") == 0 then + local head = getlist("page_head") + if head then + tail = nodes.tail(head) + if tail and tail.id == hlist_code then + if tail.depth < depth then + tail.depth = depth + end + nest.prevdepth = depth + -- only works in lmtx + texset("pagedepth",depth) + end + end + end + end + end + + interfaces.implement { + name = "checkstrutdepth", + arguments = "dimension", + actions = vspacing.checkstrutdepth, + } + + function vspacing.forcestrutdepth(n,depth,trace_mode,plus) + local box = texgetbox(n) + if box then + box = tonut(box) + local head = getlist(box) + if head then + local tail = find_node_tail(head) + if tail then + if getid(tail) == hlist_code then + local dp = getdepth(tail) + if dp < depth then + setdepth(tail,depth) + outer.prevdepth = depth + if trace or trace_mode > 0 then + nuts.setvisual(tail,"depth") + end + end + end + last = nil + if plus then + -- penalty / skip ... + local height = 0 + local sofar = 0 + local same = false + local seen = false + local list = { } + last = nil + while tail do + local id = getid(tail) + if id == hlist_code or id == vlist_code then + local w, h, d = getwhd(tail) + height = height + h + d + sofar + sofar = 0 + last = tail + elseif id == kern_code then + sofar = sofar + getkern(tail) + elseif id == glue_code then + if seen then + sofar = sofar + getwidth(tail) + seen = false + else + break + end + elseif id == penalty_code then + local p = getpenalty(tail) + if p >= 10000 then + same = true + seen = true + else + break + end + else + break + end + tail = getprev(tail) + end + texsetdimen("global","d_spac_prevcontent",same and height or 0) + end + end + end + end + end + + function vspacing.pushatsame() + -- needs better checking ! + if last then -- setsplit + nuts.setnext(getprev(last)) + nuts.setprev(last) + end + end + + function vspacing.popatsame() + -- needs better checking ! + nuts.write(last) + end + +end + +-- interface + +do + + -- old variant + +-- implement { +-- name = "vspacing", +-- actions = vspacing.analyze, +-- scope = "private", +-- arguments = "string" +-- } + + -- new variant + + interfaces.implement { + name = "injectvspacing", + actions = vspacing.inject, + arguments = { "integer", "string" }, + } + + interfaces.implement { + name = "injectvpenalty", + actions = vspacing.injectpenalty, + arguments = "integer", + } + + interfaces.implement { + name = "injectvskip", + actions = vspacing.injectskip, + arguments = "dimension", + } + + interfaces.implement { + name = "injectdisable", + actions = vspacing.injectdisable, + } + + -- + + implement { + name = "synchronizepage", + actions = vspacing.synchronizepage, + scope = "private" + } + + implement { + name = "forcestrutdepth", + arguments = { "integer", "dimension", "integer" }, + actions = vspacing.forcestrutdepth, + scope = "private" + } + + implement { + name = "forcestrutdepthplus", + arguments = { "integer", "dimension", "integer", true }, + actions = vspacing.forcestrutdepth, + scope = "private" + } + + implement { + name = "pushatsame", + actions = vspacing.pushatsame, + scope = "private" + } + + implement { + name = "popatsame", + actions = vspacing.popatsame, + scope = "private" + } + + implement { + name = "vspacingsetamount", + actions = vspacing.setskip, + scope = "private", + arguments = "string", + } + + implement { + name = "vspacingdefine", + actions = vspacing.setmap, + scope = "private", + arguments = "2 strings", + } + + implement { + name = "vspacingcollapse", + actions = vspacing.collapsevbox, + scope = "private", + arguments = "integer" + } + + implement { + name = "vspacingcollapseonly", + actions = vspacing.collapsevbox, + scope = "private", + arguments = { "integer", true } + } + + implement { + name = "vspacingsnap", + actions = vspacing.snapbox, + scope = "private", + arguments = { "integer", "integer" } + } + + implement { + name = "definesnapmethod", + actions = vspacing.definesnapmethod, + scope = "private", + arguments = "2 strings", + } + + -- local remove_node = nodes.remove + -- local find_node_tail = nodes.tail + -- + -- interfaces.implement { + -- name = "fakenextstrutline", + -- actions = function() + -- local head = texlists.page_head + -- if head then + -- local head = remove_node(head,find_node_tail(head),true) + -- texlists.page_head = head + -- buildpage() + -- end + -- end + -- } + + implement { + name = "removelastline", + actions = function() + local head = texlists.page_head + if head then + local tail = find_node_tail(head) + if tail then + -- maybe check for hlist subtype 1 + local head = remove_node(head,tail,true) + texlists.page_head = head + buildpage() + end + end + end + } + + implement { + name = "showpagelist", -- will improve + actions = function() + local head = texlists.page_head + if head then + print("start") + while head do + print(" " .. tostring(head)) + head = head.next + end + end + end + } + + implement { + name = "pageoverflow", + actions = { vspacing.pageoverflow, context } + } + + implement { + name = "forcepageflush", + actions = vspacing.forcepageflush + } + +end diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl new file mode 100644 index 000000000..3e68016cc --- /dev/null +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -0,0 +1,2452 @@ +%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}{autosuffix,optimize} + +% 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 most general and often +%D 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 instance saying +%D +%D \starttyping +%D \setupinterlinespace[line=12pt] +%D \stoptyping +%D +%D sets things fixed for all sizes, which is definitely not what we want. Therefore +%D one can also say: +%D +%D \starttyping +%D \definebodyfontenvironment[9pt][interlinespace=11pt] +%D \stoptyping +%D +%D One can still use \type {\setupinterlinespace} (without arguments) to set the +%D interline space according to the 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} + +\permanent\def\normalskipamount + {\openlineheight + \ifgridsnapping \orelse \ifconditional\c_spac_whitespace_flexible + \s!plus \skipgluefactor\openlineheight + \s!minus\skipgluefactor\openlineheight + \fi + \relax} + +\ifdefined\bodyfontinterlinespace \else + \let\bodyfontinterlinespace\empty +\fi + +\permanent\protected\def\presetnormallineheight % each bodyfont + {\edef\normallineheight{\interlinespaceparameter\c!line}% + \iflocalinterlinespace \else + \edef\m_spac_normallineheight{\bodyfontinterlinespace}% + \ifempty\m_spac_normallineheight \else + \let\normallineheight\m_spac_normallineheight + \fi + \fi} + +\permanent\protected\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}} + +\permanent\protected\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 + {\ifempty\currentrelativeinterlinespace\else + \spacing\currentrelativeinterlinespace + \fi} + +\protected\def\spac_linespacing_setup_use + {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname + \let\currentinterlinespace\m_spac_interlinespace + \spac_linespacing_setup_specified_interline_space + % \else + % we only support named interlinespaces + \fi} + +\permanent\protected\def\useinterlinespaceparameter#1% see footnotes + {\edef\m_spac_interlinespace{#1\c!interlinespace}% + \ifempty\m_spac_interlinespace \else + \spac_linespacing_setup_use + \fi} + +\newtoks\everysetupglobalinterlinespace +\newtoks\everysetuplocalinterlinespace + +\newconditional\interlinespaceisset + +\installcorenamespace{interlinespace} + +\installcommandhandler \??interlinespace {interlinespace} \??interlinespace + +\installmacrostack\currentinterlinespace + +\permanent\overloaded\tolerant\protected\def\setupinterlinespace[#1]#*[#2]% + {\ifarguments + \settrue\interlinespaceisset + \spac_linespacing_synchronize_local + \or + \settrue\interlinespaceisset + \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname + \edef\currentinterlinespace{#1}% + \spac_linespacing_setup_specified_interline_space + %\dosetupspecifiedinterlinespaceindeed + \else + \spac_linespacing_setup_specified_or_relative[#1]% + \fi + \or + \settrue\interlinespaceisset + \setup_interlinespace[#1][#2]% + \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} + +\permanent\protected\def\dosetupcheckedinterlinespace#1% often a chain + {\edef\p_spac_checked_interlinespace{#1}% + \ifempty\p_spac_checked_interlinespace + \spac_linespacing_synchronize_local + \orelse\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check + \push_macro_currentinterlinespace + \let\currentinterlinespace\p_spac_checked_interlinespace + \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed + \iflocalinterlinespace + \the\everysetuplocalinterlinespace + \else + \localinterlinespacetrue + \the\everysetuplocalinterlinespace + \localinterlinespacefalse + \fi + \pop_macro_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} + +\permanent\protected\def\setuplocalinterlinespace[#1]% + {\localinterlinespacetrue + \push_macro_currentinterlinespace + \setupinterlinespace[#1]% + \pop_macro_currentinterlinespace + \localinterlinespacefalse} + +\aliased\let\switchtointerlinespace\setuplocalinterlinespace + +%D Helpers + +\newskip \s_spac_lastskip +\newdimen\d_spac_prevdepth +\newcount\c_spac_spacefactor +\newdimen\d_spac_prevcontent % set by lua + +% \permanent\overloaded\protected\def\removelastskip +% {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} + +\permanent\def\doifoutervmode + {\unless\ifvmode + \expandafter\gobbleoneargument + \orelse\ifinner + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\protected\def\dosomebreak#1% + {\doifoutervmode + {\s_spac_lastskip\lastskip + \removelastskip + #1\relax + \ifzeropt\s_spac_lastskip + % avoid interference with footnotes + \else + \vskip\s_spac_lastskip + \fi}} + +\permanent\protected\def\packed + {\nointerlineskip} + +\permanent\protected\def\godown[#1]% + {\relax + \ifhmode\endgraf\fi + \ifvmode\nointerlineskip\vskip#1\relax\fi} + +\permanent\protected\def\smallskip{\vskip\smallskipamount} +\permanent\protected\def\medskip {\vskip\medskipamount} +\permanent\protected\def\bigskip {\vskip\bigskipamount} + +\permanent\protected\def\smallbreak + {\par + \ifvmode\ifdim\lastskip<\smallskipamount + \removelastskip + \penalty-\plusfifty + \smallskip + \fi\fi} + +\permanent\protected\def\medbreak + {\par + \ifvmode\ifdim\lastskip<\medskipamount + \removelastskip + \penalty-\plusonehundred + \medskip + \fi\fi} + +\permanent\protected\def\bigbreak + {\par + \ifvmode\ifdim\lastskip<\bigskipamount + \removelastskip + \penalty-\plustwohundred + \bigskip + \fi\fi} + +\permanent\protected\def\break {\penalty-\plustenthousand} % can be hmode or vmode +\permanent\protected\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode +\permanent\protected\def\allowbreak{\penalty \zerocount} % can be hmode or vmode + +\permanent\protected\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode +\permanent\protected\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode + +%D Made slightly more readable: + +\permanent\protected\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=} +\permanent\protected\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=} +\permanent\protected\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi} + +\def\spac_helpers_vglue_indeed + {\par + \ifvmode + \d_spac_prevdepth\prevdepth + \hrule\s!height\zeropoint + \nobreak + \vskip\s_spac_lastskip + \prevdepth\d_spac_prevdepth + \fi} + +\def\spac_helpers_hglue_indeed + {\dontleavehmode + \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: + +\pushoverloadmode + +\permanent\overloaded\protected\def\removelastskip % also in supp-box + {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} + +\popoverloadmode + +% The whitespace handler. We could cache settings but normally there are not +% that many in a set. + +\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 + +\permanent\tolerant\protected\def\setupwhitespace[#1]% + {\ifarguments + \spac_whitespace_setup_nop + \orelse\iftok{#1}\emptytoks + \spac_whitespace_setup_nop + \else + \edef\v_spac_whitespace_current{#1}% + \spac_whitespace_setup + \fi} + +\permanent\protected\def\spac_whitespace_setup_nop + {\ifx\v_spac_whitespace_current\v!none\else + \spac_whitespace_setup + \fi} + +\aliased\let\synchronizewhitespace\spac_whitespace_setup_nop + +\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} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]} +\permanent\protected\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 + +\permanent\tolerant\protected\def\startpacked[#1]% + {\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} + +\permanent\protected\def\stoppacked + {\par + \ifnum\c_spac_packed_level=\plusone \ifvmode + \endgroup + \fi \fi + \global\advance\c_spac_packed_level\minusone} + +\permanent\protected\def\startunpacked + {\directdefaultvspacing % \blank + \begingroup} + +\permanent\protected\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} + {\letfrozen\let\spac_lines_vbox\ruledvbox} + {\letfrozen\let\spac_lines_vbox\vbox} + +\let\v_spac_lines_around_action_set\relax +\let\m_spac_lines_around \empty + +\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} + +\permanent\tolerant\protected\def\startlinecorrection [#1]{\spac_lines_start_correction\plusone{#1}} +\permanent\tolerant\protected\def\startlocallinecorrection[#1]{\spac_lines_start_correction\plustwo{#1}} + +\permanent\protected\def\spac_lines_start_correction#1#2% + {\endgraf + \begingroup + \setconstant\c_spac_lines_correction_mode#1% + \edef\m_spac_lines_around{#2}% + \spac_lines_action_around + \d_spac_prevdepth\prevdepth + \spac_lines_initialize_corrections + \offbaselinecorrection % ??? + \setbox\scratchbox\spac_lines_vbox\bgroup + \ifcase\c_spac_lines_correction_mode + % nothing + \or + % global + \or + % local + \setlocalhsize + \hsize\localhsize + \forgetbothskips + \fi + \ignorespaces} + +\permanent\protected\def\spac_lines_stop_correction + {\removeunwantedspaces + \egroup + \ifgridsnapping + \spac_lines_stop_correction_ongrid + \else + \spac_lines_stop_correction_normal + \fi + \endgroup} + +\protected\def\spac_lines_stop_correction_ongrid + {\directcheckedvspacing\v!white % \blank[\v!white]% + \spac_lines_action_around + \snaptogrid\hpack{\box\scratchbox}% + \directcheckedvspacing\v!white + \spac_lines_action_around} + +\protected\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} + +\aliased\let\stoplinecorrection \spac_lines_stop_correction +\aliased\let\stoplocallinecorrection\spac_lines_stop_correction + +% todo: + +\permanent\protected\def\correctwhitespace + {\dowithnextboxcs\correctwhitespacefinish\vbox} + +\permanent\protected\def\correctwhitespacefinish + {\startbaselinecorrection + \flushnextbox + \stopbaselinecorrection} + +\permanent\protected\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}} +\permanent\protected\def\horizontalstrut{\hpack {\strut}} + +%D Here follow some presets related to interline spacing and therefore also struts. +%D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used +%D a while after we decided that \LATEX\ was not flexible enough. After that +%D \CONTEXT\ evolved, from some wrapper code around (old) \LATEX\ (on a floppy +%D disk), to using modules from \INRSTEX\ (which also fit on a floppy) and finally +%D all written from scratch. I simply didn't understand all that \TEX\ code at that +%D time, and it was easier to figure it out myself. But \unknown\ some settings +%D stayed, as the height|/|depth ratios, and they never proved to be bad ones! The +%D same is true for the font size relations. + +%D \starttabulate +%D \NC \type {\lineheight} \NC the height of a line \NC \NR +%D \NC \type {\spacing{number}} \NC adapting the interline space \NC \NR +%D \NC \type {\normalbaselines} \NC initialize the interline spacing \NC \NR +%D \NC \type {\setstrut} \NC initialize \type {\strut} \NC \NR +%D \NC \type {\setnostrut} \NC disable the \type {\strut}, \type {\endstrut}, \type {\begstrut} \NC \NR +%D \NC \type {\setteststrut} \NC initialize the visual \type {\strut} \NC \NR +%D \NC \type {\resetteststrut} \NC disable the visual \type {\strut} \NC \NR +%D \NC \type {\setfontparameters} \NC synchronize parameters with foints \NC \NR +%D \stoptabulate +%D +%D \unknown\ and many more (this is a decades old list). +%D +%D The lineheight is the sum of the height and depth of \type {strut}, which is +%D an invisible blob that can be used to enforce the proper dimensions. +%D +%D Such a blob, when placed at the beginning of a paragraph can have side effects +%D that can be prevented with \type {\dontleavehmode}. Never use \type +%D {\leavevmode}! + +\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 + +\permanent\protected\def\topskipcorrection + {\simpletopskipcorrection + \vskip-\struttotal + \verticalstrut} + +\permanent\protected\def\simpletopskipcorrection + {\ifdim\topskip>\openstrutheight + % == \vskip\topskipgap + \vskip\topskip + \vskip-\openstrutheight + \fi} + +\permanent\protected\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} + +\protected\def\setmaxdepth + {\maxdepth\systemmaxdepthfactor\globalbodyfontsize} + +\newskip \usedbaselineskip % These used to be \normal... but that isn't pretty +\newskip \usedlineskip % in the token interface, so thes few now have new +\newdimen\usedlineskiplimit % names. They are public but not really user commands. + +\permanent\protected\def\normalbaselines + {\baselineskip \usedbaselineskip + \lineskip \usedlineskip + \lineskiplimit\usedlineskiplimit} + +\permanent\protected\def\flexiblebaselines + {\baselineskip \usedbaselineskip + \lineskip 1\usedlineskip \s!plus 1\s!fill + \lineskiplimit\usedlineskiplimit} + +\permanent\protected\def\setnormalbaselines % used in overload + {\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 + \usedbaselineskip\openlineheight + \ifgridsnapping\else + \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight + \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight + \fi + \usedlineskip\minimumlinedistance\relax % \onepoint\relax + \usedlineskiplimit\zeropoint\relax + \normalbaselines} + +\permanent\protected\def\spacing#1% vertical + {\ifgridsnapping + \let\spacingfactor\plusone + \else + \edef\spacingfactor{#1}% + \fi + \edef\systemtopskipfactor {\thewithoutunit\dimexpr#1\dimexpr\topskipfactor \points}% + \edef\systemmaxdepthfactor{\thewithoutunit\dimexpr#1\dimexpr\maxdepthfactor\points}% + \setnormalbaselines + \setstrut} + +% \protected\def\forgetverticalstretch % \forgetspacing +% {\spacing\plusone} + +\permanent\protected\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 + +\permanent\protected\def\saveinterlinespace + {\protected\edef\restoreinterlinespace + {\lineheight \the\lineheight + \openstrutheight \the\openstrutheight + \openstrutdepth \the\openstrutdepth + \openlineheight \the\openlineheight + \usedbaselineskip \the\usedbaselineskip + \usedlineskip \the\usedlineskip + \usedlineskiplimit \the\usedlineskiplimit + \noexpand\def\noexpand\normallineheight{\the\dimexpr\normallineheight}% + \noexpand\normalbaselines}} + +%D This is the plain definition: +%D +%D \starttyping +%D \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi} +%D \stoptyping +%D +%D which could be: +%D +%D \starttyping +%D \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox} +%D \stoptyping +%D +%D But we do things differently. + +\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} + +% \protected\def\strut +% {\relax +% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} + +\let\normalstrut\strut + +%D The double \type {\hbox} construction enables us to backtrack boxes. + +\overloaded\let\strutht\undefined \newdimen\strutht +\overloaded\let\strutdp\undefined \newdimen\strutdp + +\permanent\protected\def\setstrut + {\ifgridsnapping + \setstrutgridyes + \else + \setstrutgridnop + \fi} + +\permanent\protected\def\setstrutgridyes + {\strutht\spacingfactor\dimexpr + \ifdim\minimumstrutheight>\zeropoint + \minimumstrutheight + \else + \strutheightfactor\dimexpr\normallineheight + \fi + \relax + \strutdp\dimexpr + \ifdim\minimumstrutdepth>\zeropoint + \minimumstrutdepth + \else + \normallineheight-\strutht + \fi + \relax + \dosetstrut} + +\permanent\protected\def\setstrutgridnop + {\strutht\spacingfactor\dimexpr + \ifdim\minimumstrutheight>\zeropoint + \minimumstrutheight + \else + \strutheightfactor\dimexpr\normallineheight + \fi + \relax + \strutdp\spacingfactor\dimexpr + \ifdim\minimumstrutdepth>\zeropoint + \minimumstrutdepth + \else + \strutdepthfactor\dimexpr\normallineheight + \fi + \relax + \dosetstrut} + +\permanent\protected\def\setcharstrut#1% + {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps + \strutht\ht\strutbox + \strutdp\dp\strutbox + \dosetstrut} + +\permanent\protected\def\settightstrut + {\setcharstrut{(}} + +\permanent\protected\def\setfontstrut + {\setcharstrut{(gplQT}} + +\permanent\protected\def\setcapstrut% could be M, but Q has descender + {\setcharstrut{Q}} + +%D Handy for math (used in mathml): + +\permanent\protected\def\charhtstrut + {\begingroup + \setcharstrut{GJY}% + \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht + \endgroup} + +\permanent\protected\def\chardpstrut + {\begingroup + \setcharstrut{gjy}% + \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint + \endgroup} + +%D Because of all the callbacks in mkiv, we avoid unnecessary boxes ... maybe use an +%D attribute so that we can tag boxes that don't need a treatment; tests with using +%D an attribute so far have shown that it's slower because testing the attribute +%D takes time too. + +\permanent\protected\def\dosetstrut + {\enforced\let\strut\normalstrut + \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo + % compensate rounding error /- 1sp to avoid too many + % 1sp baselineskips in for instance verbatim + % \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 strut; occasionally a +%D one scaled point difference can show up with the lineheight. This is more +%D 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} + +\permanent\protected\def\strut % still callbacks for \hbox{\strut} + {\relax + \dontleavehmode + \copy\strutbox} + +% \protected\def\strut % slightly faster +% {\relax +% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} + +\let\normalstrut\strut + +\permanent\protected\def\halfstrut + {\relax + \dontleavehmode + \begingroup + \setbox\scratchbox\copy\strutbox + \ht\scratchbox\dimexpr\strutht/\plustwo\relax + \dp\scratchbox\dimexpr\strutdp/\plustwo\relax + \box\scratchbox + \endgroup} + +\permanent\protected\def\quarterstrut + {\relax + \dontleavehmode + \begingroup + \setbox\scratchbox\copy\strutbox + \ht\scratchbox\dimexpr\strutht/\plusfour\relax + \dp\scratchbox\dimexpr\strutdp/\plusfour\relax + \box\scratchbox + \endgroup} + +\permanent\protected\def\depthstrut + {\relax + \dontleavehmode + \begingroup + \setbox\scratchbox\copy\strutbox + \ht\scratchbox\dimexpr\strutht-\struthtdp/\plustwo\relax % assumes that ht > lineheight/2 + \box\scratchbox + \endgroup} + +\permanent\protected\def\halflinestrut + {\relax + \dontleavehmode + \begingroup + \setbox\scratchbox\copy\strutbox + \ht\scratchbox\dimexpr\strutht-.5\strutht-.5\strutdp\relax + \box\scratchbox + \endgroup} + +\permanent\protected\def\noheightstrut + {\relax + \dontleavehmode + \begingroup + \setbox\scratchbox\copy\strutbox + \ht\scratchbox\zeropoint + \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 +%D Beware: using an unknown value results in char struts. + +\installcorenamespace{struts} + +\permanent\tolerant\protected\def\setupstrut[#1]% + {\edef\m_strut{#1}% + \ifcsname\??struts\m_strut\endcsname + \lastnamedcs + \else + \setcharstrut\m_strut + \fi} + +\permanent\protected\def\synchronizestrut#1% no [] parsing, faster for internal + {\edef\m_strut{#1}% + \ifcsname\??struts\m_strut\endcsname + \lastnamedcs + \else + \setcharstrut\m_strut + \fi} + +\permanent\protected\def\dosynchronizestrut#1% no [] parsing, faster for internal + {\ifcsname\??struts#1\endcsname + \lastnamedcs + \else + \setcharstrut{#1}% + \fi} + +\permanent\protected\def\showstruts % adapts .. is wrong + {\c_strut_visual_mode\zerocount + \setteststrut + \settestcrlf} + +\permanent\protected\def\showcolorstruts % adapts .. is wrong + {\c_strut_visual_mode\plusone + \setteststrut + \settestcrlf} + +\permanent\protected\def\setteststrut + {\def\strutwidth{.8pt}% + \setstrut} + +\permanent\protected\def\dontshowstruts + {\unsetteststrut + \settestcrlf} + +\permanent\protected\def\unsetteststrut + {\let\strutwidth\zeropoint + \setstrut} + +\def\autostrutfactor{1.1} + +\permanent\protected\def\setautostrut + {\begingroup + \setbox\scratchbox\copy\strutbox + \setstrut + \ifdim\strutht>\autostrutfactor\ht\scratchbox + \endgroup \setstrut + \orelse\ifdim\strutdp>\autostrutfactor\dp\scratchbox + \endgroup \setstrut + \else + \endgroup + \fi} + +\newbox\nostrutbox \setbox\nostrutbox\emptyhbox + +\newtoks\everysetnostrut + +\permanent\protected\def\setnostrut + {\the\everysetnostrut} + +\appendtoks + \setbox\strutbox\copy\nostrutbox + \enforced\let\strut \empty + \enforced\let\endstrut\empty + \enforced\let\begstrut\empty +\to \everysetnostrut + +%D When enabled, sigstruts will remove themselves if nothing goes inbetween. For +%D practical reasons we define some boundary characters here. + +\permanent\protected\def\leftboundary {\protrusionboundary\plusone} +\permanent\protected\def\rightboundary {\protrusionboundary\plustwo} +\permanent\protected\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals + +\newsignal\d_spac_struts_signal \setfalse\sigstruts + +\permanent\protected\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-\d_spac_struts_signal + \hskip\d_spac_struts_signal} + +\def\spac_struts_beg_normal + {\boundary\plusone + \strut + %\boundary\plusone + \penalty\plustenthousand + %\boundary\plusone + \hskip\zeropoint} + +\permanent\protected\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=\d_spac_struts_signal + \unskip + \unskip + \unpenalty + \setbox\scratchbox\lastbox + \else + \penalty\plustenthousand + \hskip\zeropoint + \strut + \fi} + +\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: + +\permanent\protected\def\pseudostrut + {\noindent} % better: \dontleavehmode + +\let\pseudobegstrut\pseudostrut +\let\pseudoendstrut\removeunwantedspaces + +\permanent\protected\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 +\letvalue{\??struts\v!auto }\setautostrut +\letvalue{\??struts\v!no }\setnostrut +\letvalue{\??struts\v!cap }\setcapstrut +\letvalue{\??struts\v!fit }\setfontstrut +\letvalue{\??struts\v!line }\setstrut +\letvalue{\??struts\s!default}\setstrut +\letvalue{\??struts\empty }\setstrut + +%D Handy: + +\def\baselinedistance{\the\lineheight} + +%D We need \type {\normaloffinterlineskip} because the new definition contains an +%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for +%D instance the visual debugger. + +\pushoverloadmode + +\overloaded\permanent\protected\def\offinterlineskip + {\baselineskip-\thousandpoint + \lineskip \zeropoint + \lineskiplimit\maxdimen + % We also need this here now; thanks to taco for figuring that out! + \def\minimumlinedistance{\zeropoint}} + +\overloaded\permanent\protected\def\nointerlineskip + {\prevdepth-\thousandpoint} + +\aliased\let\normaloffinterlineskip\offinterlineskip % knuth's original + +\popoverloadmode + +%D This is tricky. The prevdepth value is still set to the last one even if there is +%D nothing on the page. The same is true for prevgraf, which doesn't resemble the +%D value on the current page. +%D +%D So, here we kick in a checker but it has to happen after the output group and it +%D only has to be done once (output can trigger itself!). +%D +%D However, prevgraf is somehow bound to hangindent so we can get very nasty side +%D effects. So, in tne end we use our own variable! + +\ifdefined\getnofpreviouslines + % defined public at the lua end +\else + \let\getnofpreviouslines\!!zerocount +\fi + +\protected\def\page_otr_synchronize_page_yes + {\aftergroup\page_otr_synchronize_page_indeed + \global\enforced\let\page_otr_synchronize_page\relax} + +% \protected\def\page_otr_synchronize_page_indeed +% {\clf_synchronizepage +% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} +% +% This has to become an otr method: \s!page_otr_command_synchonize_page + +\protected\def\page_otr_synchronize_page_indeed + {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi + \global\enforced\let\page_otr_synchronize_page\page_otr_synchronize_page_yes} + +\let\page_otr_synchronize_page\page_otr_synchronize_page_yes + +\appendtoks + \page_otr_synchronize_page +\to \everyaftershipout + +%D My own one: + +\protected\def\spac_helpers_push_interlineskip_yes + {\enforced\edef\oninterlineskip + {\baselineskip \the\baselineskip + \lineskip \the\lineskip + \lineskiplimit\the\lineskiplimit + \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}% + \enforced\let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed + +\protected\def\spac_helpers_push_interlineskip_nop + {\enforced\let\oninterlineskip\setnormalbaselines} + +\pushoverloadmode + +\overloaded\permanent\protected\def\offinterlineskip + {\ifdim\baselineskip>\zeropoint + \spac_helpers_push_interlineskip_yes + \else + \spac_helpers_push_interlineskip_nop + \fi + \normaloffinterlineskip} + +\permanent\let\oninterlineskip\relax + +\popoverloadmode + +\permanent\protected\def\resetpenalties#1% + {\ifdefined#1% + \frozen#1\minusone + \fi} + +\permanent\protected\def\setpenalties#1#2#3% + {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text + \frozen#1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax + \fi} + +%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 + +\protected\def\spac_penalties_restore + {\global\enforced\let\restoreinterlinepenalty\relax + \overloaded\global\resetpenalties\interlinepenalties + \global\c_spac_keep_lines_together\zerocount} + +\permanent\protected\def\keeplinestogether#1% + {\ifnum#1>\c_spac_keep_lines_together + \global\c_spac_keep_lines_together#1% + \overloaded\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand + \global\enforced\let\restoreinterlinepenalty\spac_penalties_restore + \fi} + +\immutable\integerdef\defaultdisplaywidowpenalty 50 +\immutable\integerdef\defaultwidowpenalty 2000 % was: 1000 +\immutable\integerdef\defaultclubpenalty 2000 % was: 800 +\immutable\integerdef\defaultbrokenpenalty 100 +\immutable\integerdef\defaultdoublehyphendemerits 10000 +\immutable\integerdef\defaultfinalhyphendemerits 5000 +\immutable\integerdef\defaultadjdemerits 10000 + +\immutable\integerdef\defaultgriddisplaywidowpenalty 0 +\immutable\integerdef\defaultgridwidowpenalty 0 +\immutable\integerdef\defaultgridclubpenalty 0 +\immutable\integerdef\defaultgridbrokenpenalty 0 +\immutable\integerdef\defaultgriddoublehyphendemerits 10000 % always was so +\immutable\integerdef\defaultgridfinalhyphendemerits 5000 % always was so +\immutable\integerdef\defaultgridadjdemerits 10000 % always was so + +\permanent\protected\def\nopenalties + {\frozen\widowpenalty \zerocount + \frozen\clubpenalty \zerocount + \frozen\brokenpenalty \zerocount + \frozen\doublehyphendemerits\zerocount + \frozen\finalhyphendemerits \zerocount + \frozen\adjdemerits \zerocount} + +\permanent\protected\def\setdefaultpenalties + {\directsetup{\systemsetupsprefix\s!default}} + +\startsetups [\systemsetupsprefix\s!reset] + \resetpenalties\widowpenalties + \resetpenalties\clubpenalties + \resetpenalties\interlinepenalties +\stopsetups + +%D We use \directsetup because it's faster and we know there is no csl: + +\startsetups [\systemsetupsprefix\s!default] + + \directsetup{\systemsetupsprefix\s!reset} + + \frozen\widowpenalty \defaultwidowpenalty + \frozen\clubpenalty \defaultclubpenalty + \frozen\displaywidowpenalty \defaultdisplaywidowpenalty + \frozen\brokenpenalty \defaultbrokenpenalty + \frozen\doublehyphendemerits\defaultdoublehyphendemerits + \frozen\finalhyphendemerits \defaultfinalhyphendemerits + \frozen\adjdemerits \defaultadjdemerits + +\stopsetups + +\startsetups [\v!grid] [\systemsetupsprefix\s!default] + + \directsetup{\systemsetupsprefix\s!reset} + + \frozen\widowpenalty \defaultgridwidowpenalty + \frozen\clubpenalty \defaultgridclubpenalty + \frozen\displaywidowpenalty \defaultgriddisplaywidowpenalty + \frozen\brokenpenalty \defaultgridbrokenpenalty + \frozen\doublehyphendemerits\defaultgriddoublehyphendemerits + \frozen\finalhyphendemerits \defaultgridfinalhyphendemerits + \frozen\adjdemerits \defaultgridadjdemerits + +\stopsetups + +%D As an illustration: + +\startsetups [\systemsetupsprefix\v!strict] + + \directsetup{\systemsetupsprefix\s!reset} + + \setpenalties \widowpenalties \plustwo \maxdimen + \setpenalties \clubpenalties \plustwo \maxdimen + \frozen \brokenpenalty \maxdimen + \frozen \doublehyphendemerits \defaultdoublehyphendemerits + \frozen \finalhyphendemerits \defaultfinalhyphendemerits + \frozen \adjdemerits \defaultadjdemerits + +\stopsetups + +\setdefaultpenalties % will happen later in \setuplayout + +%D To be checked: + +\newbox\b_spac_struts_saved + +\permanent\protected\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox} +\permanent\protected\def\savedstrut{\copy \b_spac_struts_saved} + +%D Good old blank redone: + +%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} +\installcorenamespace{gridsnappersets} + +\newskip \bodyfontlineheight +\newdimen \bodyfontstrutheight +\newdimen \bodyfontstrutdepth + +\newskip \globalbodyfontlineheight % why a skip +\newdimen \globalbodyfontstrutheight +\newdimen \globalbodyfontstrutdepth + +\permanent\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi} +\permanent\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi} + +\def\spac_grids_set_local_snapping#1% + {\ifgridsnapping + \doifsomething{#1}% + {\spac_grids_snap_value_set{#1}% + \c_attr_snapvbox\c_attr_snapmethod}% + \fi} + +\def\spac_grids_expand_snapper#1% + {\edef\m_spac_snapper + {\ifempty\m_spac_snapper\else\m_spac_snapper,\fi + \ifcsname\??gridsnappersets#1\endcsname + \lastnamedcs\else#1% + \fi}} + +\permanent\protected\def\installsnapvalues#1#2% + {\let\m_spac_snapper\empty + \rawprocesscommacommand[#2]\spac_grids_expand_snapper + \edef\currentsnapper{#1:\m_spac_snapper}% + \ifcsname\??gridsnapperattributes\currentsnapper\endcsname + \scratchcounter\lastnamedcs % already defined + \else + \scratchcounter\clf_definesnapmethod{#1}{\m_spac_snapper}% + \setevalue{\??gridsnapperattributes\currentsnapper}{\the\scratchcounter}% + \fi + \setevalue{\??gridsnappers#1}{\c_attr_snapmethod\the\scratchcounter\relax}% + \letvalue{\??gridsnappersets#1}\m_spac_snapper} + +\permanent\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals + +\permanent\protected\def\usegridparameter#1% no checking here + {\edef\m_spac_grid_asked{#1\c!grid}% + \ifempty\m_spac_grid_asked + \c_attr_snapvbox\attributeunsetvalue + \else + \spac_grids_snap_value_set\m_spac_grid_asked + \c_attr_snapvbox\c_attr_snapmethod + \fi} + +\permanent\tolerant\protected\def\definegridsnapping[#1]#*[#2]% + {\installsnapvalues{#1}{#2}} + +\edef\spac_grids_snap_value_reset + {%\gridsnappingfalse + \c_attr_snapmethod\attributeunsetvalue} + +\def\spac_grids_snap_value_set#1% + {%\gridsnappingtrue + \begincsname\??gridsnappers#1\endcsname} + +% maybe: +% +% \def\spac_grids_snap_value_set#1% +% {%\gridsnappingtrue +% \ifcsname\??gridsnappers#1\endcsname +% \lastnamedcs +% \else +% \definegridsnapping[#1][#1]% +% \begincsname\??gridsnappers#1\endcsname +% \fi} + +\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 +% box centers a box rounded upwards (box:.5 -> tolerance) +% min centers a box rounded downwards +% max centers a box rounded upwards + +%D We're not downward compatible with \MKII ! Not yet in interface file: + +\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!verytolerant] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] + +\definegridsnapping[\v!tolerant:10] [\v!maxdepth:1.1,\v!maxheight:1.1,\v!strut] % 10 pct tolerance +\definegridsnapping[\v!tolerant:20] [\v!maxdepth:1.2,\v!maxheight:1.2,\v!strut] % 20 pct tolerance +\definegridsnapping[\v!tolerant:30] [\v!maxdepth:1.3,\v!maxheight:1.3,\v!strut] % 30 pct tolerance +\definegridsnapping[\v!tolerant:40] [\v!maxdepth:1.4,\v!maxheight:1.4,\v!strut] % 40 pct tolerance + +\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] +\definegridsnapping[\v!min] [\v!min] +\definegridsnapping[\v!max] [\v!max] + +\definegridsnapping[\v!middle] [\v!maxheight,\v!maxdepth] % used in placement + +\definegridsnapping[\v!math] [\v!maxdepth:1.05,\v!maxheight:1.05,\v!strut] % experimental, maybe 1.1 +\definegridsnapping[\v!math:\v!line] [\v!math,\v!line,\v!split] +\definegridsnapping[\v!math:\v!halfline] [\v!math,\v!halfline,\v!split] +\definegridsnapping[\v!math:-\v!line] [\v!math,-\v!line,\v!split] +\definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split] + +\permanent\protected\def\synchronizelocallinespecs + {\bodyfontlineheight \normallineheight + \bodyfontstrutheight\strutht + \bodyfontstrutdepth \strutdp} + +\permanent\protected\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: + +\permanent\protected\def\synchronizeskipamounts + {\bigskipamount + \skipfactor\baselineskip + \s!plus\skipgluefactor\baselineskip + \s!minus\skipgluefactor\baselineskip + \relax + \medskipamount \bigskipamount \divide\medskipamount \plustwo + \smallskipamount\bigskipamount \divide\smallskipamount\plusfour} + +%D Snapping. + +% \newif\ifgridsnapping % already defined + +\permanent\tolerant\protected\def\startgridsnapping[#1]% + {\snaptogrid[#1]\vbox\bgroup} + +\permanent\protected\def\stopgridsnapping + {\egroup} + +\permanent\tolerant\protected\def\placeongrid[#1]% + {\snaptogrid[#1]\vbox} % mark as done + +\permanent\tolerant\protected\def\snaptogrid[#1]% list or predefined + {\ifgridsnapping + \expandafter\spac_grids_snap_to_indeed % todo: move inline + \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\c_attr_snapmethod\relax + \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap + \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} + +\protected\def\synchronizegridsnapping + {\edef\askedgridmode{\layoutparameter\c!grid}% + \ifx\askedgridmode\v!no % official + \spac_grids_check_nop + \orelse\ifx\askedgridmode\v!off % for taco and luigi + \spac_grids_check_nop + \orelse\ifempty\askedgridmode % to be sure + \spac_grids_check_nop + \else + \spac_grids_check_yes + \fi} + +\permanent\protected\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing) + {\setlayoutparameter\c!grid{#1}\synchronizegridsnapping} + +\permanent\protected\def\checkgridmethod#1% + {\edef\p_grid{#1}% + \ifempty\p_grid + \let\checkedgridmethod\empty + \let\checkedgridscope \v!local + \else + \splitatcolon\p_grid\checkedgridscope\checkedgridmethod + \ifempty\checkedgridmethod + \ifx\checkedgridscope\v!local\orelse\ifx\checkedgridscope\v!global\else + \let\checkedgridmethod\checkedgridscope + \let\checkedgridscope \v!local + \fi + \fi + \fi} + +\permanent\protected\def\applygridmethod#1#2#3% content localsettings (used in head rendering) + {\checkgridmethod{#1}% + \ifx\checkedgridscope\v!global + \ifempty\checkedgridmethod \else + % we assume that the call is grouped because grouping here has the side + % effect that the eventually constructed line will get the value outside + % the group + % + % overkill: \setupgridsnapping[\checkedgridmethod]% + % maybe : \spac_grids_snap_value_auto\checkedgridmethod + \spac_grids_snap_value_set\checkedgridmethod + \fi + \hbox{#3}% + \else + % the extra hbox will trigger the global snapper on top of the local and + % we really need that in this case (compatibility etc etc) so here we don't + % het an already done hit (otherwise we would not snap) + \hbox\bgroup + \ifempty\checkedgridmethod\orelse\ifconditional\headisdisplay + #2% + \fi + \snaptogrid[\checkedgridmethod]\hbox{#3}% + \egroup + \fi} + +\protected\gdef\page_layouts_calculate_overshoot + {\ifgridsnapping\ifcase\layoutlines + \getnoflines\textheight + \textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax + \fi\fi} + +\protected\def\page_layouts_report_overshoot + {\page_layouts_calculate_overshoot + \ifdim\textovershoot>\zeropoint + \writestatus\m!layouts{gridmode,\space + noflines: \the\noflines,\space + textheight: \the\textheight,\space + textovershoot: \the\textovershoot\space + (maybe set number of lines instead)% + }% + \fi + \glet\page_layouts_report_overshoot\page_layouts_calculate_overshoot} + +\appendtoks + \page_layouts_report_overshoot +\to \everybeforepagebody + +%D Visualization: + +\definepalet + [grid] + [ one=red, + two=green, + three=blue, + four=gray] + +\permanent\protected\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 + +\permanent\protected\def\gridboxvbox + {\ifcase\gridboxlinemode + \vpack + \or + \ruledvpack + \or + \vpack + \or + \ruledvpack + \else + \ruledvpack + \fi} + +\permanent\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} + +\permanent\protected\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level + {\setbox#1\gridboxvbox to #3 % given size + {\forgetall + \resetvisualizers + \resetteststrut + \offinterlineskip + \hsize#2% + \ifcase\gridboxlinenomode\or\or\or + \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer + \or + \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner + \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\moveboxontogrid#1#2#3% will become obsolete, but it needs checking +% {} + +%D Helper: + +\protected\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} + +\permanent\tolerant\protected\def\definevspacingamount[#1]#*[#2]#*[#3]% can be combined + {\ifarguments + %setvalue{\??vspacingamount#1}{\lineheight}% + \or + \setvalue{\??vspacingamount#1}{\lineheight}% + \or + \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}% + \or + \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}% + \fi + \clf_vspacingsetamount{#1}} + +\def\spac_vspacing_no_topskip % use grouped + {\c_attr_skipcategory\pluseleven} + +%permanent\def\vspacingfromscratchtoks {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax} +\permanent\def\vspacingpredefinedvalue#1{\scratchskip\glueexpr\csname\??vspacingamount#1\endcsname\relax} +%permanent\def\vspacingfromtempstring {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax} + +% \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}} + +\permanent\tolerant\protected\def\definevspacing[#1]#*[#2]% + {\clf_vspacingdefine{#1}{#2}} + +%D The injector code (generated at the \LUA\ end). This will go away! + +\newtoks\everybeforeblankhandling +\newtoks\everyafterblankhandling + +\newconditional\c_space_vspacing_done +\newconditional\c_space_vspacing_fixed +\newconditional\c_space_ignore_parskip + +\appendtoks + \s_spac_vspacing_temp\zeropoint + \c_attr_skipcategory\plusone + \c_attr_skippenalty \attributeunsetvalue + \c_attr_skiporder \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 + +% The main spacer: + +\permanent\tolerant\protected\def\vspacing[#1]% + {\ifarguments + \spac_vspacing_yes[\currentvspacing]% in the new mechanism no [] needed + \else + \spac_vspacing_yes[#1]% in the new mechanism no [] needed + \fi} + +\def\spac_vspacing_yes + {\ifinpagebody % somewhat weird + \expandafter\spac_vspacing_yes_indeed + \orelse\ifconditional\c_spac_packed_blank + \expandafter\spac_vspacing_yes_indeed + \else + \expandafter\spac_vspacing_yes_ignore + \fi} + +\def\spac_vspacing_nop + {\ifinpagebody % somewhat weird + \expandafter\spac_vspacing_nop_indeed + \orelse\ifconditional\c_spac_packed_blank + \expandafter\spac_vspacing_nop_indeed + \else + \expandafter\spac_vspacing_nop_ignore + \fi} + +\def\spac_vspacing_yes_indeed[#1]{\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi} +\def\spac_vspacing_nop_indeed {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\currentvspacing}\fi\fi} + +\def\spac_vspacing_yes_ignore[#1]{\ifmmode\else\par\fi} +\def\spac_vspacing_nop_ignore {\ifmmode\else\par\fi} + +\installcorenamespace{vspacing} + +\permanent\protected\def\directvspacing#1% + {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\iftok{#1}\emptytoks\currentvspacing\else#1\fi}\fi\fi} + +\def\spac_vspacing_dim_preset#1% + {\ifcsname\??vspacing#1\endcsname + \lastnamedcs + \else + \spac_vspacing_yes_preset{#1}% + \fi} + +\def\spac_vspacing_yes_preset#1% + {\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}% + %\writestatus{}{}% + %\writestatus{#1}{\expandafter\meaning\csname\??vspacing#1\endcsname}% + %\writestatus{}{}% + \csname\??vspacing#1\endcsname} + +\permanent\protected\def\directdefaultvspacing + {\ifinpagebody % somewhat weird + \directvspacing\currentvspacing + \orelse\ifconditional\c_spac_packed_blank + \directvspacing\currentvspacing + \fi} + +\permanent\protected\def\directcheckedvspacing + {\ifinpagebody % somewhat weird + \expandafter\directvspacing + \orelse\ifconditional\c_spac_packed_blank + \expandafter\directvspacing + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\useblankparameter#1% faster local variant + {\edef\m_spac_blank_asked{#1\c!blank}% + \ifempty\m_spac_blank_asked\else + \directvspacing\m_spac_blank_asked + \fi} + +%D Handy (and faster): + +\permanent\protected\def\directvpenalty#1{\ifmmode\else\par\ifvmode\clf_injectvpenalty#1\relax\fi\fi} +\permanent\protected\def\directvskip #1{\ifmmode\else\par\ifvmode\clf_injectvskip #1\relax\fi\fi} + +%D These depend on bigskipamount cum suis so we'd better sync them: + +\mutable\let\currentvspacing\s!default % hm, default, standard ... + +\permanent\tolerant\protected\def\setupvspacing[#1]% + {\ifarguments\else + \edef\currentvspacing{#1}% + \fi + \synchronizevspacing} + +\permanent\protected\def\synchronizevspacing + {\ifempty\currentvspacing % mistakenly had an \else + \let\currentvspacing\s!default + \fi + \spac_whitespace_setup_nop} + +\permanent\protected\def\restorestandardblank % or default ? + {\let\currentvspacing\v!standard} + +%D The \type {category:4} is default. + +\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!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible + +\permanent\def\bodyfontwhitespace + {\dimexpr + \ifzeropt\parskip + \zeropoint + \orelse\ifgridsnapping + \bodyfontlineheight + \else + \parskip + \fi + \relax} + +%D used in itemize \unknown\ 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!always] [category:0] % hm, internally it's discard +\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] +\definevspacing[\v!packed] [category:8] % noparskip (kind of special) +\definevspacing[\v!overlay] [category:9] +\definevspacing[\v!enable] [category:10] + +%definevspacing[\v!noparskip] [category:8] +%definevspacing[\v!notopskip] [category:11] + +\definevspacing[\v!weak] [order:0] +\definevspacing[\v!strong] [order:100] + +\definevspacing[\s!default] [\v!white] % was big for a while + +\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 +\newcount\c_spac_vspacing_special_done + +% 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names + +\protected\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m + {\begingroup + \scratchcounterone\numexpr\plusthree*#1+#2\relax + \scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax + %\writestatus{defined}{\v!samepage-\number#1-\number#2\space=>\space penalty:\the\scratchcountertwo}% + \normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}% + \endgroup} + +\protected\def\spac_vspacing_define_same_page#1% + {\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone + {\spac_vspacing_define_same_step\recurselevel\zerocount % before + \spac_vspacing_define_same_step\recurselevel\plusone % after + \spac_vspacing_define_same_step\recurselevel\plustwo}% % whatever + \global\c_spac_vspacing_special_done#1\relax} + +\spac_vspacing_define_same_page{12} % 12 levels should be more than enough as a start + +\def\spac_vspacing_same_page#1#2% level offset (starts at 0) + {\ifnum#1>\c_spac_vspacing_special_done + \spac_vspacing_define_same_page{#1}% + \fi + %\writestatus{used}{\v!samepage-\number#1-\number#2}% + \vspacing[\v!samepage-\number#1-\number#2]} + +\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 \type {\blank} +%D (we needed the first one while playing with the new code). + +% We keep this one as reference +% +% \protected\def\inhibitblank +% {\vspacing[\v!disable]} +% +% but use the following more efficient variant instead: + +\permanent\protected\def\inhibitblank{\ifmmode\else\par\ifvmode\clf_injectdisable\fi\fi} + +\aliased\let\doinhibitblank\inhibitblank % keep this command for a while, used in styles + +%D We use \type {vspacing} because at some point we had the blank mechanism alongside +%D a new experimental variant and I aliased it locally till it all worked out well. So, +%D we're kind of stuck with synonyms now. Some day we will drop the vspacing and use the +%D old aliases instead. + +\aliased\let\defineblank \definevspacing +\aliased\let\setupblank \setupvspacing +\aliased\let\blank \vspacing +\aliased\let\synchronizeblank \synchronizevspacing +\aliased\let\defineblankmethod\definevspacingamount + +%D The following command is for Wolfgang. It has to be used with care as it does +%D {\em not} work in tandem with the other spacing commands. + +\installcorenamespace{vspace} + +\permanent\tolerant\protected\def\definevspace[#1]#*[#2]#*[#3]% + {\ifarguments + \or + \letvalue{\??vspace:#1}\empty % or undefined? + \or + \setvalue{\??vspace:#1}{#2}% + \or + \setvalue{\??vspace#1:#2}{#3}% + \fi} + +\letvalue{\??vspace:\s!unknown}\zeropoint + +\def\spac_vspace_unknown + {\csname\??vspace:\s!unknown\endcsname} + +\permanent\tolerant\protected\def\vspace[#1]#*[#2]% + {\par + \ifvmode + \removelastskip + \vskip + \ifparameter#2\or + \ifcsname\??vspace#1:#2\endcsname + \lastnamedcs + \orelse\ifcsname\??vspace:#2\endcsname + \lastnamedcs + \else + \spac_vspace_unknown + \fi + \orelse\ifparameter#1\or + \ifcsname\??vspace:#1\endcsname + \lastnamedcs + \else + \spac_vspace_unknown + \fi + \else + \ifcsname\??vspace:\s!default\endcsname + \lastnamedcs + \else + \spac_vspace_unknown + \fi + \fi + \relax + \fi} + +%D Some preliminary code: a simple and fast hanger, for usage in macros. + +\installcorenamespace {hanging} + +\installdirectcommandhandler \??hanging {hanging} + +\setuphanging + [\c!distance=.5\emwidth, + \c!location=\v!left, + \c!n=\zerocount] + +\let\m_spac_hanging_location\empty + +\permanent\tolerant\protected\def\starthanging[#1]% + {\dontleavehmode\bgroup + \ifhastok={#1}% + \let\m_spac_hanging_location\empty + \setupcurrenthanging[#1]% + \else + \edef\m_spac_hanging_location{#1}% + \fi + \ifempty\m_spac_hanging_location + \edef\m_spac_hanging_location{\directhangingparameter\c!location}% + \fi + \dowithnextboxcs\spac_hanging_finish\hbox} + +\permanent\protected\def\stophanging + {\endgraf + \egroup} + +\def\spac_hanging_finish + {\scratchdistance\directhangingparameter\c!distance\relax + \ifdim\ht\nextbox>\strutht + \setbox\nextbox\tbox{\box\nextbox}% + \fi + \scratchcounter\directhangingparameter\c!n\relax + \ifnum\scratchcounter>\zerocount + \frozen\hangafter-\scratchcounter + \else + \getboxheight\scratchdimen\of\box\nextbox + \getnoflines\scratchdimen + \frozen\hangafter-\noflines + \fi + \ht\nextbox\strutht + \dp\nextbox\strutdp + \scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax + \ifx\m_spac_hanging_location\v!right + \frozen\hangindent\ifconditional\displaylefttoright-\fi\scratchwidth + \rlap{\hskip\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new + \else + \frozen\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} + +\aliased\let\stopfixed\relax + +\permanent\protected\def\startfixed + {\bgroup + \ifhmode + \expandafter\typo_fixed_start_h + \else + \expandafter\typo_fixed_start_v + \fi} + +\tolerant\def\typo_fixed_start_h[#1]% + {\enforced\let\stopfixed\typo_fixed_stop_h + \dowithnextbox{\typo_fixed_finish{#1}}% + \vbox\bgroup + %ignorespaces + \setlocalhsize} + +\protected\def\typo_fixed_stop_h + {%removeunwantedspaces + \egroup + \egroup} + +\tolerant\def\typo_fixed_start_v[#1]% + {\enforced\let\stopfixed\typo_fixed_stop_v + \startbaselinecorrection} + +\protected\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 + +\protected\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 + +%D Helper: + +\permanent\protected\def\checkedblank[#1]% + {\edef\p_blank{#1}% + \ifempty\p_blank + % ignore + \orelse\ifx\p_blank\v!none + % ignore + \else + \blank[\p_blank]% + \fi} + +% \setupwhitespace[line] +% \prerollblank[2*line] \the\prerolledblank +% \prerollblank[-2*line] \the\prerolledblank + +\newskip\prerolledblank + +\permanent\protected\def\prerollblank[#1]% + {\begingroup + \edef\p_blank{#1}% + \ifempty\p_blank + \global\prerolledblank\zeropoint + \orelse\ifx\p_blank\v!none + \global\prerolledblank\zeropoint + \else + % don't mess with \arskip here! + \scratchskip\plusten\lineheight + \setbox\scratchbox\vbox + {\vskip\scratchskip + \kern\zeropoint + \blank[\p_blank]}% + % \dimexpr doesn't work well with skips + \advance\scratchskip-\ht\scratchbox + \global\prerolledblank-\scratchskip + \fi + \endgroup} + +\newcount\c_spac_vspacing_ignore_parskip + +% \setupwhitespace[line] +% \setuphead[subject][after={\blank[packed]},style=\bfb] +% \subject{foo} +% test \par +% test \par +% \blank[packed] % \ignoreparskip +% test \par +% test \par +% \ignoreparskip +% test \par +% test \par +% \setuphead[subject][after={\blank[nowhite]},style=\bfb] +% \subject{foo} +% test \par +% test \par + +\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-bkm.mkxl b/tex/context/base/mkxl/strc-bkm.mkxl new file mode 100644 index 000000000..c5bd87324 --- /dev/null +++ b/tex/context/base/mkxl/strc-bkm.mkxl @@ -0,0 +1,182 @@ +%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}{} + +% \enabledirectives[references.bookmarks.preroll] + +\unprotect + +%D Bookmarks are a very viewer dependent feature. They are mostly used as additional +%D table of contents and therefore relate directly to lists. +%D +%D A bookmark list is added to the document only when interaction is enabled. The +%D given lists are bookmarked and a second argument specifies the opened bookmark +%D 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 \type +%D {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 one does +%D not want \quotation {Contents} in a table of contents but it has to be in the +%D 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 + +\aliased\let\setupbookmarks\setupbookmark + +\permanent\protected\def\bookmark + {\iflocation + \expandafter\strc_bookmarks_bookmark_yes + \else + \expandafter\strc_bookmarks_bookmark_nop + \fi} + +\tolerant\def\strc_bookmarks_bookmark_yes[#1]#:#2% + {\begingroup + \simplifycommands + \ifnum\thenamedheadlevel{#1}>\zerocount + \clf_overloadbookmark{#1}{\detokenize\expandafter{\normalexpanded{#2}}}% + \else + \writetolist[#1]{#2}{}% todo: a dedicated bookmark writer + \fi + \endgroup} + +\tolerant\def\strc_bookmarks_bookmark_nop[#1]#:#2% + {} + +\permanent\protected\def\placebookmarks + {\iflocation + \expandafter\strc_bookmarks_place_yes + \else + \expandafter\gobblethreeoptionals + \fi} + +\let\m_bookmarks_names \empty +\let\m_bookmarks_opened\empty + +\tolerant\def\strc_bookmarks_place_yes[#1]#*[#2]#*[#3]% + {\begingroup + \edef\m_bookmarks_names{#1}% + \edef\m_bookmarks_opened{#2}% + \ifempty\m_bookmarks_names + \edef\m_bookmarks_names{\namedlistparameter\v!content\c!list}% + \fi + \ifempty\m_bookmarks_names + \let\m_bookmarks_names\v!all + \fi + \ifparameters\or\or + \doifelseassignment{#2}{\let\m_bookmarks_opened\empty\setupcurrentbookmark[#2]}\donothing + \or + \setupcurrentbookmark[#3]% no every so not all possible + \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/tex/context/base/mkxl/strc-blk.mkxl b/tex/context/base/mkxl/strc-blk.mkxl new file mode 100644 index 000000000..4cfbd51eb --- /dev/null +++ b/tex/context/base/mkxl/strc-blk.mkxl @@ -0,0 +1,171 @@ +%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}{} + +\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}% + \frozen\setuevalue{\e!begin\currentblock}{\strc_blocks_begin{\currentblock}}% + \frozen\letvalue {\e!end \currentblock}\donothing +\to \everydefineblock + +% We need to prevent too much lookahead which will gobble newlines that are needed +% for buffers. See blocks-002.tex as example. + +% maybe: systemmode "block:" + +\let\m_block \empty +\let\m_subblock\empty + +\protected\def\strc_blocks_begin#1% + {\edef\m_block {#1}% + \let \m_subblock\empty + \doifelsenextoptionalcs\strc_blocks_begin_yes\strc_blocks_begin_nop} + +\protected\def\strc_blocks_begin_yes[#1]% + {\doifelseassignmentcs{#1}% + \strc_blocks_begin_indeed + \strc_blocks_begin_tagged + {#1}} + +\protected\def\strc_blocks_begin_tagged#1% + {\edef\m_subblock{#1}% + \doifelsenextoptionalcs\strc_blocks_begin_yes_yes\strc_blocks_begin_nop} + +\protected\def\strc_blocks_begin_yes_yes[#1]% + {\strc_blocks_begin_indeed{#1}} + +\protected\def\strc_blocks_begin_nop + {\strc_blocks_begin_indeed{}} + +\protected\def\strc_blocks_begin_indeed#1% + {\normalexpanded{\buff_pickup{\??block}{\e!begin\m_block}{\e!end\m_block}}% + {}% + {\clf_savestructureblock{\m_block}{\m_subblock}{#1}{\??block}}% + \plusone} + +\let\strc_blocks_setup\relax + +\newconstant \c_strc_blocks_index +\newconditional\c_strc_blocks_display + +\permanent\protected\def\dostarthiddenblock % called at lua end + {\begingroup + \visiblefalse % blocks float + \startnointerference + \strc_start_block} + +\permanent\protected\def\dostophiddenblock % called at lua end + {\strc_stop_block + \stopnointerference + \endgroup} + +\permanent\protected\def\dostartnormalblock % called at lua end + {\begingroup + \visibletrue + \strc_start_block} + +\permanent\protected\def\dostopnormalblock % called at lua end + {\strc_stop_block + \endgroup} + +\def\strc_start_block#1#2% + {\edef\currentblock{#2}% + \c_strc_blocks_index#1\relax + \strc_blocks_setup + \let\strc_blocks_setup\relax + \edef\p_alternative{\blockparameter\c!alternative}% + \ifx\p_alternative\v!text + \setfalse\c_strc_blocks_display + \else + \settrue\c_strc_blocks_display + \fi + \ifconditional\c_strc_blocks_display + \blockparameter\c!before + \fi + \begingroup + \usesetupsparameter\blockparameter\relax + \dostarttagged\t!block\currentblock + \useblockstyleandcolor\c!style\c!color + \blockparameter\c!inner % old + \ifconditional\c_strc_blocks_display + \usealignparameter\blockparameter + \else + \blockparameter\c!left + \fi + \ignorespaces} + +\def\strc_stop_block + {\removeunwantedspaces + \ifconditional\c_strc_blocks_display + \par + \else + \blockparameter\c!right + \fi + \dostoptagged + \endgroup + \ifconditional\c_strc_blocks_display + \blockparameter\c!after + \fi} + +\tolerant\def\strc_blocks_set_state[#1]#*[#2]#*[#3]% state name tag % todo: we could use the lua one directly + {\clf_setstructureblockstate{#1}{#2}{#3}} + +\tolerant\def\strc_blocks_select[#1]#*[#2]#*[#3]#*[#4]% state name tag setups + {\begingroup + \ifhastok={#3}% + \getparameters[\??blocktemp][\c!criterium=\v!text,#3]% + \def\strc_blocks_setup{\setupcurrentblock[#3]}% + \clf_selectstructureblock{#1}{#2}{}{\csname\??blocktemp\c!criterium\endcsname}% + \else + \getparameters[\??blocktemp][\c!criterium=\v!text,#4]% + \def\strc_blocks_setup{\setupcurrentblock[#4]}% + \clf_selectstructureblock{#1}{#2}{#3}{\csname\??blocktemp\c!criterium\endcsname}% + \fi + \endgroup} + +\permanent\def\blockuservariable#1% + {\clf_structureblockuservariable\c_strc_blocks_index{#1}} + +% hide : save, if [+] also hidden execute +% keep : save and normal execute +% use : normal execute unless [-] +% process: hidden execute unless [-] +% select : idem use + +\permanent\protected\def\hideblocks {\strc_blocks_set_state[hide]} +\permanent\protected\def\keepblocks {\strc_blocks_set_state[keep]} +\permanent\protected\def\useblocks {\strc_blocks_select [use]} +\permanent\protected\def\processblocks{\strc_blocks_select [process]} +\permanent\protected\def\selectblocks {\strc_blocks_select [use]} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-con.mklx b/tex/context/base/mkxl/strc-con.mklx new file mode 100644 index 000000000..54397ce3a --- /dev/null +++ b/tex/context/base/mkxl/strc-con.mklx @@ -0,0 +1,1158 @@ +%D \module +%D [ file=strc-con, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Constructions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Constructions} + +\registerctxluafile{strc-con}{} + +% todo: check why \copy .. probably mkii leftover +% +% todo: check if commands similar to lists +% todo: \strc_constructions_setup_counter\strc_constructions_setup_counter{#1} in setup ... synchronization +% +% ? : \def\showdnlisttext{\constructionparameter\c!listtext} % space in default +% +% maybe: pickup text and store in buffer ... +% +% \@@notemakeconstruction[##1]{}{##2}% +% \expandafter\endgroup\noteparameter\c!next}} +% +% todo: \currentconstructionattribute : can be a counter instead + +%D Constructions are just descriptions but a bit more abstract so that we can +%D conveniently build upon them. They are not really meant for users but module +%D writers might find them useful. We mention a couple of parameters but these are +%D only mentioned because in the shared code we map all resolvers to constructions. +%D +%D On top of constructions we build descriptions, enumerations, notes, labels and +%D maybe some day more. + +\unprotect + +%D Todo: + +\installcorenamespace{construction} + +\installcommandhandler \??construction {construction} \??construction + +\aliased\let\setupconstructions\setupconstruction + +\setupconstructions[% + %c!title=, + %c!text=, + % + %c!style=, + %c!color=, + %c!command=, + %c!align=, + % + %c!headstyle=, + %c!headcolor=, + %c!headalign=, + % + %c!titlestyle=, + %c!titlecolor=, + %c!titlecommand=, + %c!titleleft=, + %c!titleright=, + % + %c!closesymbol=, + %c!closecommand=, + % + \c!alternative=\v!left, + \c!display=\v!yes, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!stretch=.50, + \c!shrink=.25, + \c!titledistance=.5\emwidth, + %c!hang=, + %c!sample=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + %c!indentnext=, + %c!indenting=, + % + \c!expansion=\v!no, + %c!xmlsetup=, + %s!catcodes=, +] + +%D Constructions and alike uses similar structures. In order to prevent issues +%D we freeze some states. There is some overhead in the intermediate define +%D step (as we could set them directly) but this is more flexible (and looks +%D nicer). Keep in mind that descriptions, enumeration and notations are all +%D independent and that we just remap the resolvers. + +% \defineconstruction[test][handler=description,level=1] +% \defineconstruction[test][parent][handler=description,level=3] + +\installcorenamespace{constructionmain} % frozen after definition +\installcorenamespace{constructionlevel} % frozen after definition +\installcorenamespace{constructionclass} % frozen after definition + +\let\currentconstructionmain \empty +\let\currentconstructionlevel \empty +\let\currentconstructionhandler\empty + +\settrue\c_strc_constructions_define_commands % use with care, might become a proper key + +\appendtoks + \ifempty\currentconstructionparent + \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 + +% todo: inhibit this when we have a different handle .. current we cannot do \frozen + +\appendtoks + \ifconditional\c_strc_constructions_define_commands + %% \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}% + \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start[\currentconstruction]}% + \instance\setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}% + \fi +\to \everydefineconstruction + +%D Just a basic environment (mostly for testing). We will provide a 'setup' based +%D plugin once the rest is sorted out. + +\tolerant\protected\def\strc_constructions_start[#1]#*[#2]#*[#3]% + {\begingroup + \strc_constructions_initialize{#1}% + \strc_constructions_register[#3][\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#2]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname + \endgroup} + +%D As we will build on top of the generic construction mechanism we have handlers +%D as a sort of plug in mechanism. In order to have some consistency we share +%D some namespaces. + +\installcorenamespace{constructioninitializer} +\installcorenamespace{constructionfinalizer} + +\installcorenamespace{constructionmainhandler} +\installcorenamespace{constructioncommandhandler} +\installcorenamespace{constructionstarthandler} +\installcorenamespace{constructionstophandler} + +\installcorenamespace{constructiontexthandler} +\installcorenamespace{constructionnotehandler} + +\protected\def\strc_constructions_initialize#1% class instance + {\edef\currentconstruction{#1}% + \enforced\let\currentconstructionhash\??construction + \let\currentconstructionlistentry\!!zerocount + \enforced\expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname + \enforced\expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname + \enforced\expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname + \csname\??constructioninitializer\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_finalize + {\csname\??constructionfinalizer\currentconstructionhandler\endcsname + \strc_constructions_discard} + +\newconditional\c_strc_constructions_number_state +\newconditional\c_strc_constructions_title_state + +\protected\setvalue{\??constructioninitializer\v!construction}% + {\setfalse\c_strc_constructions_number_state + \setfalse\c_strc_constructions_title_state} + +\protected\setvalue{\??constructionfinalizer\v!construction}% + {} + +%D We keep the command variant around but rather would move to the start-stop one. +%D Also, passing the title as argument has some history so we need to keep that as +%D well. + +% \ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi + +% \startuseMPgraphic{MyFrame} +% picture p ; numeric o ; path a, b ; pair c ; +% p := textext.rt("\FunnyFramed{\currentconstructiontext}") ; +% % p := textext.rt("\wrappedconstruction{\FunnyFramed{\currentconstructiontext}}") ; +% % p := textext.rt("\FunnyFramed{\wrappedconstruction{\currentconstructiontext}}") ; +% % p := textext.rt("\FunnyFramed{\wrappedcurrentconstruction}") ; +% ... +% \stopuseMPgraphic +% +% \defineoverlay[MyFrame][\useMPgraphic{MyFrame}] +% +% \defineframedtext +% [MyText] +% [frame=off, +% background=MyFrame] +% +% \defineenumeration[Theorem] +% [alternative=empty, +% before=\startMyText, +% after=\stopMyText] + +\newtoks\everyconstruction + +\permanent\protected\def\currentconstructiontext + {\begstrut + \csname\??constructiontexthandler\currentconstructionhandler\endcsname + \endstrut} + +\permanent\protected\def\currentconstructionsample + {\begstrut + \constructionparameter\c!text + \p_strc_constructions_sample + \endstrut} + +\permanent\protected\def\wrappedconstruction#1% + {\begingroup + \iftrialtypesetting \else + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax + \fi + #1% + \endgroup} + +\permanent\protected\def\wrappedcurrentconstruction + {\begingroup + \iftrialtypesetting \else + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax + \fi + \currentconstructiontext + \endgroup} + +\protected\setvalue{\??constructionmainhandler\v!construction}#1% + {\iftrialtypesetting \else + \begingroup + \currentconstructionsynchronize % reinstated + \c_attr_destination\currentconstructionattribute\relax % todo, whole text + \signalcharacter + \endgroup + \fi#1} + +\protected\setvalue{\??constructiontexthandler\v!construction}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext + \the\everyconstruction + \constructionparameter\c!headcommand + {\strut + \constructionparameter\c!text + \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}% + \endgroup} + +\protected\def\strc_constructions_stored_start + {\begingroup % brrr \endgroup elsewhere ... will be sorted out + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_stored_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname} + +\newconstant\c_strc_constructions_nested_state % to be redone + +\def\resetconstructions % to be used in e.g. footnotes + {\c_strc_constructions_nested_state\zerocount} + +\protected\setvalue{\??constructioncommandhandler\v!construction}% + {\endgroup} + +\let\p_strc_constructions_sample \empty +\let\p_strc_constructions_align \empty +\let\p_strc_constructions_indenting \empty +\let\p_strc_constructions_width \empty +\let\p_strc_constructions_aligntitle \empty +\let\p_strc_constructions_renderingsetup\empty +\let\p_strc_constructions_headalign \empty +\let\p_strc_constructions_hang \empty +\let\p_strc_constructions_inbetween \empty +\let\p_strc_constructions_closesymbol \empty +\let\p_strc_constructions_distance \empty + +\newconditional\c_strc_constructions_distance_none + +\def\strc_constructions_set_width_and_distance + {\assignwidth + \p_strc_constructions_width + \constructionsheadwidth + {\unhcopy\constructionheadbox} + \constructionsheaddistance} + +\def\strc_constructions_preroll_head#content% + {\setbox\constructionheadbox\hbox + {\forgetall + \dontcomplain + \settrialtypesetting + \csname\??constructionmainhandler\currentconstructionhandler\endcsname#content}} + +\def\strc_constructions_ignore_head + {\constructionsheaddistance\zeropoint + \constructionsheadwidth \zeropoint + % we also need to make sure that no stretch creeps in (new per 2015-02-02, for Alan) + \settrue\c_strc_constructions_distance_none} + +\overloaded\let\currentconstructionhash\??construction + +\protected\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing + {\dostarttaggedchained\t!construction\currentconstruction\currentconstructionhash +% \dotagsetconstruction + \constructionparameter\c!before + \begingroup + \edef\currentconstructionalternative{\constructionparameter\c!alternative}% + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% + % catch fuzzyness + \ifempty\p_strc_constructions_renderingsetup + \letconstructionparameter\c!alternative\v!left + \let\currentconstructionalternative\v!left + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% + \else + \doifnotsetups\p_strc_constructions_renderingsetup + {\letconstructionparameter\c!alternative\v!left + \let\currentconstructionalternative\v!left + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}}% + \fi + % + \doadaptleftskip{\constructionparameter\c!margin}% + \setlocalhsize % so we can use \localhsize in width assignments + \edef\p_strc_constructions_distance{\constructionalternativeparameter\c!distance}% + \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}% + \ifx\p_strc_constructions_distance\v!none + \settrue\c_strc_constructions_distance_none + \constructionsheaddistance\zeropoint + \else + \setfalse\c_strc_constructions_distance_none + \constructionsheaddistance\p_strc_constructions_distance\relax + \ifdim\constructionsheaddistance=\zeropoint + \ifx\p_strc_constructions_width\v!broad + \constructionsheaddistance\emwidth + \orelse\ifx\p_strc_constructions_width\v!line + \constructionsheaddistance\emwidth + \fi + \fi + \fi + % inefficient and not always needed, for instance not with margins so we will make checkers + % per alternative some day (especially in labels this is unwanted overhead) + % + % maybe we should have an option as i cannot oversee the consequences now + % + % \edef\p_strc_constructions_sample{\constructionparameter\c!sample}% + % \ifempty\p_strc_constructions_sample + % \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}% + \ifempty\p_strc_constructions_sample + \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}% + \ifempty\p_strc_constructions_align \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}% + \ifempty\p_strc_constructions_indenting \else + \indenting[\p_strc_constructions_indenting]% \use... + \fi + % + \dostoptagged % tag + \dostarttagged\t!constructioncontent\empty + %\freezeparagraphproperties + \updateparagraphshapes + \ignorespaces} % args not needed + +\protected\setvalue{\??constructionstophandler\v!construction}% + {\strc_constructions_close_symbol_place + \doifnot{\constructionparameter\c!display}\v!no\par + \dostoptagged % content + \dostoptagged % construction + \endgroup + \constructionparameter\c!after + \useindentnextparameter\constructionparameter + \strc_constructions_finalize +% \endgroup + \dorechecknextindentation} + +\permanent\protected\def\boxedconstructionhead#1% + {\doifelse{\constructionalternativeparameter\c!alignbottom}{\v!yes}\vbox\vtop + {\hsize\constructionsheadwidth + \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}% + \ifempty\p_strc_constructions_headalign \else + \setupalign[\p_strc_constructions_headalign]% \use... + \fi + #1}} + +\installcorenamespace{constructionalternative} +\installcorenamespace{constructionrenderings} + +% see lists: alternativemethods ... todo +% +% there will be a proper interface to variables + +\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative + +\setupconstructionalternative + [%c!left=, % no inheritance + %c!right=,% no inheritance + \c!width=\constructionparameter\c!width, + \c!distance=\constructionparameter\c!distance, + \c!stretch=\constructionparameter\c!stretch, + \c!shrink=\constructionparameter\c!shrink] + +\defineconstructionalternative + [\v!left] + [%\c!width=7em, + %\c!distance=1em, + \c!renderingsetup=\??constructionrenderings:\v!left] + +\defineconstructionalternative + [\v!right] + [%\c!width=7em, + %\c!distance=1em, + \c!renderingsetup=\??constructionrenderings:\v!right] + +\defineconstructionalternative + [\v!inmargin] + [\c!renderingsetup=\??constructionrenderings:\v!inmargin] + +\defineconstructionalternative + [\v!inleft] + [\c!renderingsetup=\??constructionrenderings:\v!inleft] + +\defineconstructionalternative + [\v!inright] + [\c!renderingsetup=\??constructionrenderings:\v!inright] + +\defineconstructionalternative + [\v!margin] + [\c!renderingsetup=\??constructionrenderings:\v!margin] + +\defineconstructionalternative + [\v!leftmargin] + [\c!renderingsetup=\??constructionrenderings:\v!leftmargin] + +\defineconstructionalternative + [\v!rightmargin] + [\c!renderingsetup=\??constructionrenderings:\v!rightmargin] + +\defineconstructionalternative + [\v!innermargin] + [\c!renderingsetup=\??constructionrenderings:\v!innermargin] + +\defineconstructionalternative + [\v!outermargin] + [\c!renderingsetup=\??constructionrenderings:\v!outermargin] + +\defineconstructionalternative + [\v!serried] + [\c!renderingsetup=\??constructionrenderings:\v!serried] + +\defineconstructionalternative + [\v!hanging] + [%\c!width=.75\emwidth + \c!renderingsetup=\??constructionrenderings:\v!hanging] + +\defineconstructionalternative + [\v!top] + [\c!renderingsetup=\??constructionrenderings:\v!top, + \c!width=\localhsize] + +\defineconstructionalternative + [\v!command] + [\c!renderingsetup=\??constructionrenderings:\v!command] + +\defineconstructionalternative + [\v!empty] + [\c!renderingsetup=\??constructionrenderings:\v!empty] + +\defineconstructionalternative + [\v!label] + [\c!renderingsetup=\??constructionrenderings:\v!label, + \c!width=] + +\newbox \constructionheadbox +\newskip \leftconstructionskip +\newskip \rightconstructionskip +\newdimen \constructionsheadwidth +\newdimen \constructionsheaddistance + +\def\strc_constructions_set_hang_box#1% messy left/rightskip + {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang + {\forgetall + \dontcomplain + \hsize\constructionsheadwidth\relax + \ifempty\p_strc_constructions_headalign + \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 + \ifempty\p_strc_constructions_headalign + \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% + {\ifempty\p_strc_constructions_hang + % nothing + \orelse\ifx\p_strc_constructions_hang\v!fit + \scratchdimen\htdp\constructionheadbox + \getnoflines\scratchdimen + \hangafter-\noflines + \orelse\ifx\p_strc_constructions_hang\v!broad + \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax + \getnoflines\scratchdimen + \hangafter-\noflines + \else + \hangafter-\p_strc_constructions_hang + \fi + \relax + \hangindent\ifx#1\v!right-\fi\constructionsheadwidth} + +\protected\def\flushconstructionheadbox + {\ifhbox\constructionheadbox\unhbox\else\box\fi\constructionheadbox} + +% The setups. These only deal with placement of the descriptor and initializing the +% environment. The wrapping happens elsewhere. + +% todo: optimize the setups with +% +% \ifconditional\c_strc_constructions_distance_none : no need for skip +% \ifzeropt\wd\constructionheadbox : no need for box and skips + +\startsetups[\??constructionrenderings:\v!left] + \edef\p_strc_constructions_hang{\constructionparameter\c!hang}% + \doifelsesetups{\??constructionrenderings:\v!left:\p_strc_constructions_hang} { + \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang} + } { + \directsetup{\??constructionrenderings:\v!left:\v!hanging} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!right] + \edef\p_strc_constructions_hang{\constructionparameter\c!hang} + \doifelsesetups{\??constructionrenderings:\v!right:\p_strc_constructions_hang} { + \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang} + } { + \directsetup{\??constructionrenderings:\v!right:\v!hanging} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!none] + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushleft + \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax + \rightskip\rightconstructionskip\relax + \llap { + \hpack to \leftskip { + \hskip\leftconstructionskip + \box\constructionheadbox % was copy + \hss + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:0] + \directsetup{\??constructionrenderings:\v!left:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:] + \directsetup{\??constructionrenderings:\v!left:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!none] + \enforced\let\\\crlf + \noindent + \leftskip\leftconstructionskip + \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax + %\strc_constructions_pure_hang_box\raggedleft + \strc_constructions_set_pure_box\v!flushright + \rlap { + \hskip\dimexpr\hsize-\leftskip-\rightskip\relax + \copy\constructionheadbox + \hskip\rightconstructionskip + } + \nobreak + \advance\rightskip \constructionsheaddistance + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:0] + \directsetup{\??constructionrenderings:\v!right:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:] + \directsetup{\??constructionrenderings:\v!right:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!margin]% + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushleft + \llap { + \hpack to \constructionsheadwidth { + \box\constructionheadbox % was copy + \hss + } + \hskip\constructionsheaddistance + } + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!margin]% + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushright + \rlap { + \hskip\constructionsheaddistance + \hpack to \constructionsheadwidth { + \box\constructionheadbox % was copy + \hss + } + } + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!hanging]% + \enforced\let\\\crlf + \dontcomplain + \advance\constructionsheadwidth \constructionsheaddistance + \strc_constructions_set_hang_box\v!flushleft + \strc_constructions_set_hang\v!left + \noindent + \llap { + \tpack to \zeropoint { + \box\constructionheadbox + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!hanging]% + \enforced\let\\\crlf + \dontcomplain + \advance\constructionsheadwidth \constructionsheaddistance + \strc_constructions_set_hang_box\v!flushright + \strc_constructions_set_hang\v!right + \noindent + \rlap { + \hpack to \dimexpr\hsize-\leftskip-\rightskip\relax { + \hss + \tpack to \zeropoint { + \box\constructionheadbox + } + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!top] + % \strc_sectioning_prevent_page_break % commented per 31/5/2019 + \enforced\let\\\space + \noindent + \copy\constructionheadbox % why copy ? + \par + \nobreak + \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}% + \ifempty\p_strc_constructions_inbetween \else + \p_strc_constructions_inbetween + % shouldn't this move to after the fi? + \directcheckedvspacing\v!samepage + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +% why copy? historic reason? + +\startsetups[\??constructionrenderings:\v!margin] + \enforced\let\\\crlf + \noindent + \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!leftmargin] + \enforced\let\\\crlf + \noindent + \inleft[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!rightmargin] + \enforced\let\\\crlf + \noindent + \inright[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!innermargin] + \enforced\let\\\crlf + \noindent + \ininner[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!outermargin] + \enforced\let\\\crlf + \noindent + \inouter[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!inmargin] + \directsetup{\??constructionrenderings:\v!margin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!inleft] + \directsetup{\??constructionrenderings:\v!leftmargin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!inright] + \directsetup{\??constructionrenderings:\v!rightmargin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried] + % already set? + \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace + \doifelsesetups{\??constructionrenderings:\v!serried:\p_strc_constructions_width} { + \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width} + } { + \directsetup{\??constructionrenderings:\v!serried:\v!wide} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!fit] + \enforced\let\\\crlf + \noindent + \flushconstructionheadbox + \nobreak + \hskip\constructionsheaddistance\relax + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!broad] + \enforced\let\\\crlf + \noindent + \flushconstructionheadbox + \ifconditional\c_strc_constructions_distance_none \else + \nobreak + \hskip\constructionsheaddistance + \s!plus \constructionalternativeparameter\c!stretch\constructionsheaddistance + \s!minus\constructionalternativeparameter\c!shrink \constructionsheaddistance + \relax + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:] + \directsetup{\??constructionrenderings:\v!serried:\v!broad} +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!wide] + \enforced\let\\\crlf + \noindent + \hbox to \constructionsheadwidth { + \flushconstructionheadbox + \hss + } + \nobreak + \hskip\constructionsheaddistance\relax + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!hanging] + % tricky: leftskipadaption is somewhat unpredictable + \enforced\let\\\crlf + \noindent + \advance\leftskip-\leftskipadaption\relax + \ifdim\leftskipadaption=\zeropoint + \leftskipadaption1.5\emwidth\relax % just some default + \ifnum\c_strc_constructions_nested_state=\plusone + \ifdim\leftskip>\zeropoint \relax + \leftskipadaption\leftskip + \fi + \fi + \fi + \ifnum\c_strc_constructions_nested_state>\zerocount % was \ifnum\c_strc_constructions_nested_state=\plusone + \advance\leftskip\leftskipadaption % but we're already further on + \fi + \hskip-\leftskipadaption\relax + \ifhbox\constructionheadbox \unhbox\else\box\fi\constructionheadbox + \ifconditional\c_strc_constructions_distance_none \else + % we used to have just a kern, but long lines look bad then + \scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi + \hskip \scratchdistance + \s!plus \constructionalternativeparameter\c!stretch\scratchdistance + \s!minus\constructionalternativeparameter\c!shrink \scratchdistance + \fi + \ifhmode + \ifx\p_strc_constructions_width\v!line + \hfill\break + \else + \allowbreak + \fi + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D \starttyping +%D \setupfootnotation[location=command,headcommand=\llap] +%D \stoptyping + +\startsetups[\??constructionrenderings:\v!command] + \noindent + \constructionparameter\c!headcommand{\flushconstructionheadbox} + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!empty] + \noindent + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!label] + \dontleavehmode + \begingroup + \constructionparameter\c!headcommand{\flushconstructionheadbox} + \endgroup +\stopsetups + +\ifcase\contextlmtxmode \else + % just an empty check so that we can grep for contextlmtxmode in mkiv files +\fi + +% \definedescription[whatever][alternative=right:bottom] +% +% \startwhatever{just a small\\example} +% \input ward +% \stopwhatever + +\defineconstructionalternative + [\v!right:\v!bottom] + [%\c!width=7em, + %\c!distance=1em, + \c!alignbottom=\v!yes, + \c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom] + +\startsetups[\??constructionrenderings:\v!right:\v!bottom] + \enforced\let\\\crlf + \noindent + \leftskip\leftconstructionskip + \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax + \parfillskip\zeropoint + \strc_constructions_set_pure_box\v!flushright + \directparwrapper \relax {% + \hfilll + \rlap + {\kern\constructionsheaddistance + \copy\constructionheadbox}% + }% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D This next feature will get an lmtx implementation (probably by using a new generic +%D close mechanism). + +% you can use \placeclosesymbol or \qed to place a symbol at the end of a +% construction + +\installcorenamespace{constructionclosesymbol} + +\let\placeclosesymbol\donothing +\let\qed \donothing + +\def\strc_constructions_close_symbol_reset % no need for global + {\global\expandafter\settrue\csname\??constructionclosesymbol\currentconstruction\endcsname + \let\placeclosesymbol\strc_constructions_close_symbol_place + \let\qed \strc_constructions_close_symbol_place} + +\protected\def\strc_constructions_close_symbol_place + {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname + \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname + \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}% + \ifempty\p_strc_constructions_closesymbol \else + \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected + \fi + \fi} + +\newif\ifnoconstructioncaption + +%D The storage macros: + +\let\currentconstructionlistentry\!!zerocount + +\protected\def\strc_constructions_register + {\clf_doifelselisthasentry\numexpr\currentconstructionlistentry\relax + \strc_constructions_register_nop + \strc_constructions_register_yes} + +% \def\strc_constructions_register{\strc_constructions_register_yes} + +\def\strc_constructions_register_nop[#1][#2]% #1=optional user data #2=interfaced-settings + %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}} + {} + +\def\strc_constructions_discard + {\iftrialtypesetting + % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}% + \clf_discardfromlist\currentconstructionlistentry\relax + \fi} + +\let\currentconstructionlistnumber \!!zerocount +\let\currentconstructionsynchronize\relax +\let\currentconstructionattribute \attributeunsetvalue + +\def\strc_constructions_register_yes[#1][#2]% #1=optional user data #2=interfaced-settings + {\begingroup % similar to structure so we might generalize this + \setupcurrentconstruction[#2]% % xdef's will become edef's + \xdef\currentconstructionexpansion {\constructionparameter\c!expansion}% + \xdef\currentconstructionxmlsetup {\constructionparameter\c!xmlsetup}% + \xdef\currentconstructioncatcodes {\constructionparameter\s!catcodes}% + \xdef\currentconstructionlabel {\constructionparameter\c!label}% + \xdef\currentconstructionreference {\constructionparameter\c!reference}% + \xdef\currentconstructionreferenceprefix{\constructionparameter\c!referenceprefix}% + %xdef\currentconstructionshownumber {\constructionparameter\c!number}% + \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}% + % + \ifempty\currentconstructionexpansion + \glet\currentconstructionexpansion\v!no + \fi + % + \ifempty\currentconstructionreferenceprefix + \glet\currentconstructionreferenceprefix\referenceprefix + \fi + \ifx\currentconstructionexpansion\s!xml + \xmlstartraw + \xdef\currentconstructiontitle {\constructionparameter\c!title}% + \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\constructionparameter\c!marking}% + \xdef\currentconstructionlist {\constructionparameter\c!list}% + \xmlstopraw + \ifempty\currentconstructionlist + \glet\currentconstructionlist\currentconstructiontitle + \fi + \glet\currentconstructioncoding\s!xml + \else + \ifx\currentconstructionexpansion\v!yes + \xdef\currentconstructiontitle {\constructionparameter\c!title}% + \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\constructionparameter\c!marking}% + \xdef\currentconstructionlist {\constructionparameter\c!list}% + \else + \xdef\currentconstructiontitle {\detokenizedconstructionparameter\c!title}% + \xdef\currentconstructionbookmark{\detokenizedconstructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\detokenizedconstructionparameter\c!marking}% + \xdef\currentconstructionlist {\detokenizedconstructionparameter\c!list}% + \iflocation \ifempty\currentconstructionbookmark + \begingroup + \simplifycommands + \xdef\currentconstructionbookmark{\detokenize\expandafter{\normalexpanded{\constructionparameter\c!title}}}% + \endgroup + \fi \fi + \fi + \ifempty\currentconstructionlist + \glet\currentconstructionlist\currentconstructiontitle + \fi + \glet\currentconstructioncoding\s!tex + \fi + % + \ifx\currentconstructiontitle\v!none % will become obsolete + \global\noconstructioncaptiontrue\global\noconstructionnumbertrue + \fi + % + \ifnoconstructioncaption % then why analyze anyway? + \endgroup + \let\currentconstructionlistnumber \relax + \let\currentconstructionsynchronize\relax + \let\currentconstructionattribute \relax + \else + \setnextinternalreferences{construction}\currentconstructionmain % plural + \relax + \scratchcounter\clf_addtolist + metadata { + kind {construction} + name {\currentconstructionmain} + % level structures.sections.currentlevel() + catcodes \catcodetable + } + references { + internal \locationcount + order \locationorder + reference {\currentconstructionreference} + prefix {\currentconstructionreferenceprefix} + % block {\currentsectionblock} + % section structures.sections.currentid(), + } + titledata { + label {\detokenize\expandafter{\currentconstructionlabel}} + title {\detokenize\expandafter{\currentconstructiontitle}} + \ifx\currentconstructionbookmark\currentconstructiontitle \else + bookmark {\detokenize\expandafter{\currentconstructionbookmark}} + \fi + \ifx\currentconstructionlist\currentconstructiontitle \else + list {\detokenize\expandafter{\currentconstructionlist}} + \fi + } + \ifconditional\c_strc_constructions_number_state + prefixdata { + prefix {\constructionparameter\c!prefix} + separatorset {\constructionparameter\c!prefixseparatorset} + conversion {\constructionparameter\c!prefixconversion} + conversionset {\constructionparameter\c!prefixconversionset} + set {\constructionparameter\c!prefixset} + segments {\constructionparameter\c!prefixsegments} + connector {\constructionparameter\c!prefixconnector} + } + numberdata { + numbers {\currentconstructionnumber} + separatorset {\constructionparameter\c!numberseparatorset} + conversion {\constructionparameter\c!numberconversion} + conversionset {\constructionparameter\c!numberconversionset} + starter {\constructionparameter\c!numberstarter} + stopper {\constructionparameter\c!numberstopper} + segments {\constructionparameter\c!numbersegments} + } + \or + % symbol + \fi + userdata {\detokenize{#1}} + \relax + % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}% + \clf_setinternalreference + prefix {\currentconstructionreferenceprefix}% + reference {\currentconstructionreference}% + internal \locationcount + view {\interactionparameter\c!focus}% + \relax + \normalexpanded {% + \endgroup + \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}% + \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}% + \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}% + }% + \fi} + +% This is not so nice, some day I'll just store the number with the entry +% and deal with all at the Lua end, but first we need to be able to set +% macros. + +\permanent\protected\def\reinstateconstructionnumberentry#1% was xdef + {\edef\currentconstructionattribute {\clf_getinternallistreference#1}% + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} + +\permanent\protected\def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real + {\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} + +\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}} + +% Helpers: + +\def\currentconstructionnumber{\constructionparameter\s!counter} + +\protected\def\strc_constructions_next_indeed #get#tag#level{\strc_counters_increment_sub{#get{#tag}\s!counter}{#level}} +\protected\def\strc_constructions_reset_indeed#get#tag#level{\strc_counters_reset_sub {#get{#tag}\s!counter}{#level}} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-def.mkxl b/tex/context/base/mkxl/strc-def.mkxl new file mode 100644 index 000000000..52b3b3ad9 --- /dev/null +++ b/tex/context/base/mkxl/strc-def.mkxl @@ -0,0 +1,338 @@ +%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}{} + +\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 + +% \setuphead[sectionsegments=\currentheadlevel] +% \setuphead[sectionsegments=current] +% +% \startchapter[title=One,ownnumber={A}] +% \startsection[title=OneOne,ownnumber={A.B}] +% \startsubsection[title=OneOneOne,ownnumber={A.B.C}] +% test +% \stopsubsection +% \stopsection +% \stopchapter + +% \appendtoks +% \setsectionblock[\v!bodypart]% default +% \to \everyjob +% +% \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 +\definesection[\s!section-8] % subsubsubsubsubsection +\definesection[\s!section-9] % subsubsubsubsubsubsection +\definesection[\s!section-10] % subsubsubsubsubsubsubsection +\definesection[\s!section-11] % subsubsubsubsubsubsubsubsection +\definesection[\s!section-12] % subsubsubsubsubsubsubsubsubsection + +% \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!subsubsubsubsubsection] + [\c!section=\s!section-8, + \c!default=\v!subsubsubsubsection] + +\definehead + [\v!subsubsubsubsubsubsection] + [\c!section=\s!section-9, + \c!default=\v!subsubsubsubsubsection] + +\definehead + [\v!subsubsubsubsubsubsubsection] + [\c!section=\s!section-10, + \c!default=\v!subsubsubsubsubsubsection] + +\definehead + [\v!subsubsubsubsubsubsubsubsection] + [\c!section=\s!section-11, + \c!default=\v!subsubsubsubsubsubsubsection] + +\definehead + [\v!subsubsubsubsubsubsubsubsubsection] + [\c!section=\s!section-12, + \c!default=\v!subsubsubsubsubsubsubsubsection] + +\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] + +\definehead + [\v!subsubsubsubsubsubject] + [\c!coupling=\v!subsubsubsubsubsection, + \c!default=\v!subsubsubsubsubsection, + \c!incrementnumber=\v!no] + +\definehead + [\v!subsubsubsubsubsubsubject] + [\c!coupling=\v!subsubsubsubsubsubsection, + \c!default=\v!subsubsubsubsubsubsection, + \c!incrementnumber=\v!no] + +\definehead + [\v!subsubsubsubsubsubsubsubject] + [\c!coupling=\v!subsubsubsubsubsubsubsection, + \c!default=\v!subsubsubsubsubsubsubsection, + \c!incrementnumber=\v!no] + +\definehead + [\v!subsubsubsubsubsubsubsubsubject] + [\c!coupling=\v!subsubsubsubsubsubsubsubsection, + \c!default=\v!subsubsubsubsubsubsubsubsection, + \c!incrementnumber=\v!no] + +\definehead + [\v!subsubsubsubsubsubsubsubsubsubject] + [\c!coupling=\v!subsubsubsubsubsubsubsubsubsection, + \c!default=\v!subsubsubsubsubsubsubsubsubsection, + \c!incrementnumber=\v!no] + +% setups + +\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 + +% prefixes + +\defineprefixset + [\v!all] + [section-1,section-2,section-3,section-4,section-5,section-6,section-7,% + section-8,section-9,section-10,section-11,section-12] + [] + +% \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!textdistance=\emwidth plus \emwidth minus .25\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!textdistance=\emwidth plus \emwidth minus .25\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] +\setuplist [\v!subsubsubsubsubsection] [\c!width=8\emwidth] +\setuplist [\v!subsubsubsubsubsubsection] [\c!width=9\emwidth] +\setuplist [\v!subsubsubsubsubsubsubsection] [\c!width=10\emwidth] +\setuplist [\v!subsubsubsubsubsubsubsubsection] [\c!width=11\emwidth] +\setuplist [\v!subsubsubsubsubsubsubsubsubsection] [\c!width=12\emwidth] + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-des.mklx b/tex/context/base/mkxl/strc-des.mklx new file mode 100644 index 000000000..e63512c7f --- /dev/null +++ b/tex/context/base/mkxl/strc-des.mklx @@ -0,0 +1,194 @@ +%D \module +%D [ file=strc-des, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Descriptions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Descriptions} + +\unprotect + +\installcorenamespace{description} + +\installcommandhandler \??description {description} \??description + +\aliased\let\setupdescriptions\setupdescription + +% \setupdescription % check with old +% [\c!alternative=\descriptionparameter\c!location, +% \c!location=\v!left] + +\setupdescription % check with old + [\c!alternative=\v!left, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!title=\v!yes, + %\c!text=, + ] + +\appendtoks + \ifempty\currentdescriptionparent + \defineconstruction[\currentdescription][\currentdescriptionparent][\s!handler=\v!description,\c!level=1]% + \else + \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]% + \fi + % We can combine these but in tracing (or errors) using a different caller is nicer. + \frozen\instance\setuevalue {\currentdescription}{\strc_descriptions_command[\currentdescription]}% + \frozen\instance\setuevalue{\e!start\currentdescription}{\strc_descriptions_start [\currentdescription]}% + \frozen\instance\setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}% +\to \everydefinedescription + +\let\p_strc_constructions_title \empty + +\protected\setvalue{\??constructioninitializer\v!description}% + {\let \currentdescription \currentconstruction + \enforced\let\constructionparameter \descriptionparameter + \enforced\let\constructionnamespace \??description + \enforced\let\detokenizedconstructionparameter\detokenizeddescriptionparameter + \enforced\let\letconstructionparameter \letdescriptionparameter + \enforced\let\useconstructionstyleandcolor \usedescriptionstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentdescription + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +% We keep the command variant around but rather would move to the +% start-stop one. Also, passing the title as argument has some +% history so we need to keep that as well. + +% \startdescription [reference] text \stopdescription +% \startdescription [reference]{title} text \stopdescription +% \startdescription [title=,title=,reference=] text \stopdescription + +% A bit over the top, the optional title but mkii has it too. + +\tolerant\protected\def\strc_descriptions_start[#1]#*[#2]% + {\begingroup + \strc_constructions_initialize{#1}% + \ifhastok={#2}% + \expandafter\strc_descriptions_start_setups + \orelse\ifconditional\c_strc_constructions_title_state + \expandafter\strc_descriptions_start_title + \else + \expandafter\strc_descriptions_start_reference + \fi[#2]} + +\protected\def\strc_descriptions_start_setups[#1]% + {\setfalse\c_strc_constructions_title_state + \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\tolerant\def\strc_descriptions_start_title[#1]#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_start_reference[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname} + +% \description [reference] text \par +% \description [reference] {title} text \par + +\tolerant\protected\def\strc_descriptions_command[#1]#*[#2]#:#*#=% + {\begingroup + \strc_constructions_initialize{#1}% + \ifhastok={#2}% + \expandafter\strc_descriptions_command_setups + \orelse\ifconditional\c_strc_constructions_title_state + \expandafter\strc_descriptions_command_title + \else + \expandafter\strc_descriptions_command_reference + \fi[#2]} + +\protected\def\strc_descriptions_command_setups[#1]% + {\setfalse\c_strc_constructions_title_state + \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +\protected\tolerant\def\strc_descriptions_command_title[#1]#:#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_command_reference[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +%D Handlers: + +\letcsname\??constructionmainhandler \v!description\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname +\letcsname\??constructioncommandhandler\v!description\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname +\letcsname\??constructiontexthandler \v!description\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname + +\protected\setvalue{\??constructioncommandhandler\v!description}% + {\dowithpar + {\csname\??constructionstarthandler\v!construction\endcsname}% + {\csname\??constructionstophandler \v!construction\endcsname\endgroup}} + +\protected\setvalue{\??constructionstarthandler\v!description}% + {\dogotopar + {\csname\??constructionstarthandler\v!construction\endcsname}} + +\protected\setvalue{\??constructionstophandler\v!description}% + {\csname\??constructionstophandler\v!construction\endcsname + \endgroup} + +%D For historic reasons we have (from now on undocumented): + +\definedescription + [tab] + [\c!alternative=\v!left, + \c!headstyle=\v!normal, + \c!headcolor=, + \c!style=\v!normal, + \c!color=, + \c!width=\v!broad, + \c!sample=\kern4\emwidth, % was \hskip but that no longer is okay + \c!before=, + \c!after=] + +\protected\def\setuptab + {\setupdescription[tab]} + +%D Maybe we should remove this definition. + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-doc.mkxl b/tex/context/base/mkxl/strc-doc.mkxl new file mode 100644 index 000000000..046f0b086 --- /dev/null +++ b/tex/context/base/mkxl/strc-doc.mkxl @@ -0,0 +1,45 @@ +%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}{} + +\unprotect + +%D This will move: + +\permanent\protected\def\setstructuresynchronization#1% todo: use ctxcontext + {\clf_setinternalreference + prefix {\currentstructurereferenceprefix}% + reference {\currentstructurereference} + internal \locationcount + view {\interactionparameter\c!focus}% + \relax + \enforced\xdef\currentstructureattribute + {\the\lastdestinationattribute}% + \enforced\xdef\currentstructuresynchronize + {\currentstructuresynchronize + \strc_lists_inject_enhance{#1}}} + +\permanent\protected\def\setstructurecomponentsynchronization#1% todo: use ctxcontext + {\clf_setinternalreference + prefix {\currentstructurecomponentreferenceprefix}% + reference {\currentstructurecomponentreference} + internal \locationcount + view {\interactionparameter\c!focus}% + \relax + \enforced\xdef\currentstructurecomponentattribute {\the\lastdestinationattribute}% + \enforced\xdef\currentstructurecomponentsynchronize{\strc_lists_inject_enhance{#1}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-enu.mklx b/tex/context/base/mkxl/strc-enu.mklx new file mode 100644 index 000000000..d568247eb --- /dev/null +++ b/tex/context/base/mkxl/strc-enu.mklx @@ -0,0 +1,371 @@ +%D \module +%D [ file=strc-enu, % moved from strc-des +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Enumerations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Enumerations} + +\unprotect + +% command -> headcommand + +%D Enumerations are just super descriptions. Therefore we implement +%D them as an extension. After all, the keys don't clash. In order +%D to be able to differentiate between specific settings we use +%D some flags. Unfortunately we have some historic differences +%D in default values. Therefore we push an extra step in the +%D parent chain (we might do the same for regular descriptions). + +%D In order to be more flexible with theorems Aditya Mahajan added +%D support for titles and endsymbols. At the same time we added more +%D flexible support for inheriting numbers. +%D +%D \startbuffer +%D \defineenumeration[one] +%D \defineenumeration[two] [one] % clone one +%D \defineenumeration[three] [counter=one,style=slanted] % only use counter of one +%D \defineenumeration[four] [three] % clone three +%D \defineenumeration[five] [three] [counter=five] % clone three and use own counter +%D \defineenumeration[six] [three] [counter=four] % clone tree and use counter four (undefined) +%D +%D \startone test test 6 \stopone +%D \starttwo test test 7 \stoptwo +%D \startthree test test 8 \stopthree +%D \startfour test test 9 \stopfour +%D \startfive test test 2 \stopfive +%D \startsix test test 10 \stopsix +%D \stopbuffer +%D +%D \typebuffer \start \getbuffer \stop +%D +%D \starttyping +%D \setupenumerations[one] [prefix=yes,prefixsegments=section] +%D \setupenumerations[two] [prefix=yes,prefixsegments=section] +%D \setupenumerations[three][prefix=yes,prefixsegments=section] +%D \setupenumerations[four] [prefix=yes,prefixsegments=chapter:section] +%D \setupenumerations[five] [prefix=yes,prefixsegments=chapter:section] +%D \setupenumerations[six] [prefix=yes,prefixsegments=chapter:section] +%D \stoptyping + +% list and titles are experimental +% +% \definedescription[test] [location=left,hang=4,headalign={right},distance=1em,list=test] +% \defineenumeration[lemma][title=yes,right=:,textdistance=1em, location=top, titlestyle=\bs,list=lemma] +% \defineenumeration[ammel][title=yes,right=:,textdistance=.5em,location=left,titlestyle=\it,width=9em] +% +% \placelist[enumeration:lemma] +% \placelist[description:test][width=0pt] +% +% \starttest {something something something} \input zapf \stoptest +% \startlemma {with a title of a certain length} \input tufte \stoplemma +% \startammel {with a title} \input zapf \stopammel +% +% \defineenumeration[lemma][...] +% \defineenumeration[titledlemma][lemma][title=yes,right=:,text=lemma,list=lemma] + +\installcorenamespace{enumeration} + +\installcommandhandler \??enumeration {enumeration} \??enumeration + +\installcounterassociation{enumeration} + +\let\setupenumerations\setupenumeration + +\setupenumeration % check with old + [\c!alternative=\v!top, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!width=8\emwidth, + %\c!distance=\zeropoint, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + %\c!starter=, + %\c!stopper=, + \c!text=\currentenumeration, + \c!number=\v!yes, % else description + \c!start=0, + \c!state=\v!start, + \c!levels=4] + +% to be considered: +% +% \let\??construction\??enumeration +% +% with push/pop (also at definition time) + +\protected\def\strc_define_commands_enumeration#tag#level#parent% + {\doifelsenothing{#parent} + {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}% + \setevalue{\??enumeration#tag:\s!parent}{\??enumeration}}% + {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}% + \setevalue{\??enumeration#tag:\s!parent}{\??enumeration#parent}}% + \frozen\instance\setuevalue{\e!next #tag}{\strc_enumerations_next {#tag}{\number#level}}% obsolete + \frozen\instance\setuevalue{\c!reset#tag}{\strc_enumerations_reset {#tag}{\number#level}}% obsolete + %frozen\instance\setuevalue{\c!set #tag}{\strc_enumerations_set {#tag}{\number#level}}% obsolete + \frozen\instance\setuevalue {#tag}{\strc_enumerations_command[#tag]}% we could pass level here as well (faster) + \frozen\instance\setuevalue{\e!start#tag}{\strc_enumerations_start [#tag]}% we could pass level here as well (faster) + \frozen\instance\setuevalue{\e!stop #tag}{\strc_enumerations_stop }} + +\appendtoks + \ifempty\currentenumerationparent + % 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 + \ifempty\p_counter % + \let\p_counter\currentenumeration + \fi + \doifelsecounter\p_counter\donothing{\strc_enumerations_define_counter\p_counter}% + \letenumerationparameter\s!counter\p_counter + %\strc_enumerations_setup_counter\currentenumeration +\to \everydefineenumeration + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\protected\setvalue{\??constructioninitializer\v!enumeration}% + {\let \currentenumeration \currentconstruction + \enforced\let\constructionparameter \enumerationparameter + \enforced\let\constructionnamespace \??enumeration + \enforced\let\detokenizedconstructionparameter\detokenizedenumerationparameter + \enforced\let\letconstructionparameter \letenumerationparameter + \enforced\let\useconstructionstyleandcolor \useenumerationstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentenumeration + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\protected\setvalue{\??constructionfinalizer\v!enumeration}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Interfaces: + +\let\strc_enumerations_command\strc_descriptions_command +\let\strc_enumerations_start \strc_descriptions_start +\let\strc_enumerations_stop \strc_descriptions_stop + +\protected\def\strc_enumerations_next {\strc_constructions_next_indeed \namedenumerationparameter} % #1#2 +\protected\def\strc_enumerations_reset{\strc_constructions_reset_indeed\namedenumerationparameter} % #1#2 +%protected\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 + +\letcsname\??constructionmainhandler \v!enumeration\expandafter\endcsname\csname\??constructionmainhandler \v!description\endcsname +\letcsname\??constructioncommandhandler\v!enumeration\expandafter\endcsname\csname\??constructioncommandhandler\v!description\endcsname +\letcsname\??constructionstarthandler \v!enumeration\expandafter\endcsname\csname\??constructionstarthandler \v!description\endcsname +\letcsname\??constructionstophandler \v!enumeration\expandafter\endcsname\csname\??constructionstophandler \v!description\endcsname + +\protected\setvalue{\??constructiontexthandler\v!enumeration}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \strc_enumerations_text + \endgroup} + +\protected\def\strc_enumerations_text + {\the\everyenumeration % will become obsolete + \ifconditional\c_strc_constructions_number_state + \ifx\currentconstructionreference\!!plustoken + \strc_enumerations_full_number_symbol + \orelse\ifx\currentconstructionreference\!!minustoken + \strc_enumerations_full_number_nop + \else + \strc_enumerations_full_number_coupling + \fi + \else + \strc_enumerations_full_number_nop + \fi} + +\protected\def\strc_enumerations_inject_text_with_space + {\edef\p_text{\constructionparameter\c!text}% + \ifempty\p_text \else + \p_text + \removeunwantedspaces + \nobreakspace + \fi} + +\protected\def\strc_enumerations_inject_extra_text + {\ifconditional\c_strc_constructions_title_state + \clf_doifelselisthastitle{\currentconstructionmain}\numexpr\currentconstructionlistentry\relax + \strc_enumerations_inject_extra_text_indeed + \donothing + \fi} + +\protected\def\strc_enumerations_inject_text + {\constructionparameter\c!numbercommand + {\constructionparameter\c!text}} + +% head ( number title ) + +\protected\def\strc_enumerations_inject_extra_text_indeed + {\begingroup + \hskip\constructionparameter\c!titledistance % we listen to the headstyle + \useconstructionstyleandcolor\c!titlestyle\c!titlecolor + \constructionparameter\c!titlecommand + {\constructionparameter\c!titleleft + \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax + \constructionparameter\c!titleright}% + \endgroup} + +\protected\def\strc_enumerations_inject_symbol % todo check + {\constructionparameter\c!left + \constructionparameter\c!symbol + \constructionparameter\c!right} + +\protected\def\strc_enumerations_inject_number + {\constructionparameter\c!left + \constructionparameter\c!starter + \clf_savedlistprefixednumber{\currentconstructionmain}\currentconstructionlistentry\relax + \constructionparameter\c!stopper + \constructionparameter\c!right} + +\protected\def\strc_enumerations_inject_text_and_number + {\constructionparameter\c!numbercommand + {\strc_enumerations_inject_text_with_space + \strc_enumerations_inject_number}} + +\protected\def\strc_enumerations_inject_text_and_symbol + {\constructionparameter\c!numbercommand + {\strc_enumerations_inject_text_with_space + \strc_enumerations_inject_symbol}} + +\protected\def\strc_enumerations_full_number_yes + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text_and_number + \strc_enumerations_inject_extra_text + \endstrut}} + +\protected\def\strc_enumerations_full_number_nop + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text + \strc_enumerations_inject_extra_text + \endstrut}} + +\protected\def\strc_enumerations_full_number_symbol + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text_and_symbol + \strc_enumerations_inject_extra_text + \endstrut}} + +% to be used in for instance: +% +% coupling=questions .... coupling=answers +% +% we will provide some more control, like skipping etc or reference relates + +% to do / to be checked + +\protected\def\strc_enumerations_full_number_coupling + {\iflocation + \strc_enumerations_full_number_yes + \else + \iftrialtypesetting \else + % \doenumerationregistercoupling + \fi + \strc_enumerations_full_number_yes + \edef\p_coupling{\constructionparameter\c!coupling}% + \ifempty\p_coupling \else + \symbolreference[order(construction:\p_coupling:\the\locationorder)]% + \fi + \fi} + +\protected\def\strc_enumerations_skip_number_coupling[#tag]% e.g. for questions with no answer + {\clf_setnextreferenceorder{construction}{#tag}} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx new file mode 100644 index 000000000..33794d137 --- /dev/null +++ b/tex/context/base/mkxl/strc-flt.mklx @@ -0,0 +1,2580 @@ +%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}{} + +\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} +\installcorenamespace{floatframed} + +\installframedcommandhandler \??float {float} \??float +\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption +\installframedcommandhandler \??floatframed {floatframed} \??floatframed + +\aliased\let\setupfloats \setupfloat +\aliased\let\setupcaption \setupfloatcaption +\aliased\let\setupcaptions\setupfloatcaption + +\permanent\protected\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!offset=\v!overlay, + \c!frame=\v!off, + % \c!expansion=, + % \c!prefix=, + % \c!prefixconnector=, + % \c!way=, + % \c!prefixsegments=, + % \c!way=, + % \c!blockway=, + % \c!sectionnumber=, + % \c!separator=, + % \c!starter=, + % \c!stopper=, + \c!suffixseparator=, % currently rather hard coded + \c!suffix=\floatcaptionsuffix, + \c!distance=\emwidth, % plus .5\emwidth minus .25\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!grid=, + %\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!sidespaceinbetween=\rootfloatparameter\c!spacebefore, + \c!spacebeforeside=, % extra, not part of, can be used to add whitespace before text + \c!spaceafterside=, % idem + \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=\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!small, % the flush side float step (big, medium, small : always depth) + \c!ntop=2, + \c!nbottom=0, + \c!nlines=4, % used? + \c!topoffset=\zeropoint, + \c!bottomoffset=\zeropoint, + \c!freeregion=\v!yes, + %\c!local=, + %\c!bottombefore=, % e.g. \vfill + %\c!bottomafter=, + %\c!default=, % default location + \c!sidethreshold=.5\strutdp, % set to "old" to check with old method + \c!numbering=\v!yes, + \c!compress=\v!yes, % when possible pack floats when flushing + \c!compressdistance=\emwidth] + +\setupfloatframed + [\c!frame=\v!off, + \c!offset=\v!overlay, + \c!strut=\v!no] + +\appendtoks + \doifelse{\floatparameter\c!compress}\v!yes\settrue\setfalse\c_page_floats_pack_flushed + \d_page_floats_compress_distance\floatparameter\c!compressdistance\relax +\to \everysetupfloat + +%D We need to do it again here: + +\setupfloat + [\c!compress=\v!yes, % when possible pack floats when flushing + \c!compressdistance=\emwidth] + +%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 + +\permanent\tolerant\protected\overloaded\def\definefloat[#1]#*[#2]#*[#3]% name+plural+parent | name+parent+settings + {\ifarguments\or + \strc_floats_define_c[#1][#1]% + \or + \doifelsecommandhandler\??float{#2}% + {\strc_floats_define_a[#1][#1][#2]}% + {\strc_floats_define_c[#1][#2]}% + \orelse\ifhastok={#3}% + \strc_floats_define_b[#1][#2][#3]% + \else + \strc_floats_define_a[#1][#2][#3]% + \fi} + +\def\strc_floats_define_a[#1][#2][#3]% name names parent + {\definefloatcaption[#1][#3]% + \definefloatframed[#1][#3]% + \definecounter[#1][#3]% + \definelist[#1][#3]% + \copylabeltext[#1=#3]% + \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]% + \definefloatframed[#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]% + \definefloatframed[#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% + {\frozen\instance\setuevalue{\e!place\e!listof#2}{\strc_lists_place[#1]}% call will change + \frozen\instance\setuevalue{\e!complete\e!listof#2}{\strc_lists_complete[#1][#2]}% call will change + \frozen\instance\setuevalue{\e!place#1}{\placefloat[#1]}% + \frozen\instance\setuevalue{\e!start\e!place#1}{\startplacefloat[#1]}% + \frozen\instance\setuevalue{\e!stop\e!place#1}{\stopplacefloat}% + \frozen\instance\setuevalue{\e!start#1\e!text}{\strc_floats_start_text[#1]}% + \frozen\instance\setuevalue{\e!stop#1\e!text}{\strc_floats_stop_text}% + % these will become obsolete: + \frozen\instance\setuevalue{\e!reserve#1}{\strc_floats_reserve[#1]}% + \frozen\instance\setuevalue{\e!start\e!reserve#1\e!text}{\strc_floats_start_reserve_text[#1]}% + \frozen\instance\setuevalue{\e!stop\e!reserve#1\e!text}{\strc_floats_stop_reserve_text}} + +%D Fallback float body: + +\protected\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}} + +\permanent\protected\def\thecurrentfloatnumbersuffix + {\doifsomething{\floatcaptionparameter\c!suffix} + {\floatcaptionparameter\c!suffixseparator + \floatcaptionparameter\c!suffix + \floatcaptionparameter\c!suffixstopper}} + +\permanent\protected\def\thecurrentfloatnumber + {\ifnofloatcaption \orelse \ifnofloatnumber \orelse \ifx\currentfloatnumber\relax \else + \namedtaggedlabeltexts + \t!floatlabel \currentfloat + \t!floatnumber\currentfloat + {\begstrut + \floatcaptionparameter\c!numbercommand + {\clf_savedlistprefixednumber{\currentfloat}\currentfloatnumber\relax + \thecurrentfloatnumbersuffix}% + \endstrut}% + \fi} + +\permanent\protected\def\thecurrentfloatcaption + {\ifnofloatcaption \orelse \ifemptyfloatcaption \orelse \ifx\currentfloatnumber\relax \else + \dostarttagged\t!floattext\empty + \begstrut + \floatcaptionparameter\c!textcommand + {\clf_savedlisttitle{\currentfloat}\numexpr\currentfloatnumber\relax}% + \endstrut + \dostoptagged + \fi} + +%D Captions. + +\let\floatcaptionsuffix\empty % an optional suffix +\let\floatcaptionnumber\empty % a logical counter + +% For a while these were placeholders: +% +%D \starttyping +%D \protected\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption} +%D \protected\def\setfloatcaption {\dodoubleempty\strc_floats_set_caption} +%D +%D \def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]} +%D \def\strc_floats_set_caption [#tag][#reference]#caption{[not supported]} +%D +%D \protected\def\placefloatcaptiontext [#tag]{[not suported yet]} +%D \protected\def\placefloatcaptionnumber [#tag]{[not suported yet]} +%D \protected\def\placefloatcaptionreference[#tag]{[not suported yet]} +%D \stoptyping +%D +%D because in \MKII\ we had: +%D +%D \starttyping +%D \let\placefloatlabel \placefloatcaption +%D \let\placefloatlabeltext \placefloatcaptiontext +%D \let\placefloatlabelreference\placefloatcaptionreference +%D \stoptyping +%D +%D But as it was never advertised we don't provide it in \MKIV. However, at some +%D point HvdM wanted this: +%D +%D \starttyping +%D \placefigure {labeltext-1} {\externalfigure[figure-1]} +%D \placefloatcaption[figure][title={labeltext-2}] \externalfigure[figure-2] +%D \placefigure {labeltext-3} {\externalfigure[figure-3]} +%D \stoptyping +%D +%D So there you have it: + +\permanent\tolerant\protected\def\placefloatcaption[#category]#spacer[#settings]#spacer[#userdata]% + {\ifarguments\or\else % >= 2 + % we need at least a category and title + \dontleavehmode + \bgroup + \edef\currentfloat{#category}% + \let\currentfloatcaption\currentfloat + \resetfloatcaptionparameter\c!reference + \resetfloatcaptionparameter\c!title + \resetfloatcaptionparameter\c!marking + \resetfloatcaptionparameter\c!list + \resetfloatcaptionparameter\c!bookmark + \setupcurrentfloatcaption[#settings]% + \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% + \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi + \strc_counters_increment\currentfloatcounter + \strc_counters_register_component + \s!float + \setupcurrentfloatcaption + \floatcaptionparameter + \detokenizedfloatcaptionparameter + \relax + \relax + \relax + [\s!name=\currentfloat, + \s!counter=\currentfloatcounter,% + \s!hascaption=\v!yes,% + \s!hasnumber=\v!yes,% + \s!hastitle=\v!yes]% + [#userdata]% + \glet\previousfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatattribute \m_strc_counters_last_registered_attribute + \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize + % + % \iflocation + % \c_attr_destination\currentfloatattribute\relax + % \fi + \currentfloatsynchronize + \strc_floats_make_complete_caption + % + \iftrialtypesetting\strc_counters_restore\currentfloatcounter\fi + \egroup + \fi} + +\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]}% + \strc_floats_make_complete_caption_before + \synchronizedisplaydirection % temp hack, till we have a proper model + \noindent + \gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking + \begingroup + \ifnofloatcaption + \global\d_strc_floats_caption_height\zeropoint + \global\d_strc_floats_caption_depth \zeropoint + \else + \usefloatcaptionstyleandcolor\c!style\c!color + \clf_doifelselisthastitle{\currentfloat}\numexpr\currentfloatnumber\relax + \donothing + \emptyfloatcaptiontrue + \ifnofloatnumber \orelse \ifnofloatcaption \else + \ifemptyfloatcaption + \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}% + \else + \doifelsenothing{\floatcaptionparameter\c!spaceinbetween} + {\scratchskip\floatcaptionparameter\c!distance\relax + \setbox\scratchbox\hbox + {\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor + \thecurrentfloatnumber + \floatcaptionparameter\c!headseparator + \dotfskip\scratchskip}% + \doifelse{\floatcaptionparameter\c!hang}\v!yes + {\leftskip\wd\scratchbox + \llap{\box\scratchbox}} + {\unhbox\scratchbox}% + \emergencystretch.5\scratchskip} + {\hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}% + \blank[\floatcaptionparameter\c!spaceinbetween]}% + \fi + \fi + \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor + \global\d_strc_floats_caption_height\strutheight + \global\d_strc_floats_caption_depth \strutdepth + \thecurrentfloatcaption\endgraf + \fi + \endgroup + \strc_floats_make_complete_caption_after + \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}} + +%let\strc_floats_make_complete_caption_before\relax +\let\strc_floats_make_complete_caption_after \relax + +\def\strc_floats_make_complete_caption_before + {\doifelseframed\floatcaptionparameter\strc_floats_make_complete_caption_before_indeed\relax} + +\def\strc_floats_make_complete_caption_before_indeed + {\edef\m_strc_align{\floatcaptionparameter\c!align}% + \edef\m_strc_strut{\floatcaptionparameter\c!strut}% + \letfloatcaptionparameter\c!align\v!normal + \letfloatcaptionparameter\c!strut\v!no + \inheritedfloatcaptionframed + \bgroup + \letfloatcaptionparameter\c!align\m_strc_align + \letfloatcaptionparameter\c!strut\m_strc_strut + \let\strc_floats_make_complete_caption_after\egroup} + +% \definefloat [figure-1] [figure] +% \definefloat [figure-2] [figure] +% \setupfloat [figure-1] [location=left,leftmargin=10mm] +% \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 +% +% \protected\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) + \ifzeropt\wd\b_strc_floats_caption + \global\emptyfloatcaptiontrue + \ifnofloatnumber + \global\nofloatcaptiontrue + \fi + \else + \global\emptyfloatcaptionfalse + \setbox\b_strc_floats_caption\hpack{\hskip\leftskip\box\b_strc_floats_caption}% + \fi + \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 \glet\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}}% + \ifempty\strc_float_realpage + \glet\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 + \glet\lastplacedfloat\currentfloat + \let\m_strc_floats_saved_userdata\empty + \let\currentfloatcaption\currentfloat} + +\let\askedfloatmethod \empty +\let\askedfloatoptions\empty + +\def\strc_floats_reset_variables + {\global\emptyfloatcaptionfalse + \global\nofloatcaptionfalse + \global\nofloatnumberfalse + \glet\askedfloatmethod \empty + \glet\askedfloatoptions\empty} + +% place + +\let\floatlabel \empty +\let\floatcolumn \empty +\let\floatrow \empty +\let\floatlocation \empty +\let\floatlocationmethod\empty + +\def\strc_floats_analyze_location + {% more will be moved here + \let\floatlabel \empty + \let\floatcolumn\empty + \let\floatrow \empty + % + \edef\floatcaptionlocation{\floatcaptionparameter\c!location}% + % + \setfloatmethodvariables\floatlocation} + +\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 + +\ifdefined\dotagregisterfloat \else \let\dotagregisterfloat\gobbletwoarguments \fi + +\tolerant\def\strc_floats_place[#tag]#spacer[#location]#spacer[#reference]#:#caption% + {\strc_floats_set_current_tag{#tag}% + \strc_floats_reset_variables + \xdef\askedfloatoptions{#location}% + \edef\floatlocation{#location}% + \ifempty\floatlocation + \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} + +\permanent\protected\def\placefloat + {\flushnotes + \page_otr_command_flush_side_floats % here ! + \strc_floats_begin_group + \strc_floats_place} + +% 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 + +%D We abuse the settings to pick up some float parameters too which makes it +%D messy. + +\permanent\tolerant\protected\def\startplacefloat[#tag]#spacer[#settings]#spacer[#userdata]% + {\flushnotes + \page_otr_command_flush_side_floats % here ! + \strc_floats_begin_group + \strc_floats_set_current_tag{#tag}% + \strc_floats_reset_variables + % save + \edef\m_location {\floatcaptionparameter\c!location}% + \edef\m_topoffset {\floatcaptionparameter\c!topoffset}% + \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}% + \edef\m_freeregion {\floatcaptionparameter\c!freeregion}% + % preset + \letfloatcaptionparameter \c!location \empty + \setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}% + \setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}% + \setexpandedfloatcaptionparameter\c!freeregion {\floatparameter\c!freeregion}% + \letfloatcaptionparameter \c!reference \empty + \letfloatcaptionparameter \c!title \empty + \letfloatcaptionparameter \c!marking \empty + \letfloatcaptionparameter \c!list \empty + \letfloatcaptionparameter \c!bookmark \empty + % pickup + \ifparameter#settings\or + \setupcurrentfloatcaption[#settings]% + \fi + \ifparameter#userdata\or + \setupcurrentfloatuserdata[#userdata]% + \def\m_strc_floats_saved_userdata{#userdata}% + \else + \let\m_strc_floats_saved_userdata\empty + \fi + % check + \edef\floatlocation{\floatcaptionparameter\c!location}% + \ifx\floatlocation\empty + \edef\floatlocation{\floatparameter\c!default}% + \fi + % inherit + \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}% + \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}% + \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}% + % restore + \letfloatcaptionparameter\c!location \m_location + \letfloatcaptionparameter\c!topoffset \m_topoffset + \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset + \letfloatcaptionparameter\c!freeregion \m_freeregion + % + \strc_floats_analyze_location + \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal + \bgroup + \ignorespaces} + +\permanent\protected\def\stopplacefloat + {\removeunwantedspaces + \egroup} + +% reserve + +\protected\def\strc_floats_reserve + {\flushnotes + \page_otr_command_flush_side_floats % here ! + \strc_floats_begin_group + \strc_floats_place} + +\def\strc_floats_reserve_box#settings% + {\begingroup + \setupcurrentfloat[\c!frame=\v!on,#settings]% + \inheritedfloatframed{}% + \endgroup} + +% text + +\protected\def\strc_floats_start_text + {\flushnotes % Here indeed? + \page_otr_command_flush_side_floats % Here indeed? + \strc_floats_begin_text_group + \strc_floats_start_text_indeed} + +\tolerant\protected\def\strc_floats_start_text_indeed[#tag]#spacer[#location]#spacer[#reference]% + {\strc_floats_place[#tag][\v!text,#location,\v!left][#reference]} + +\protected\def\strc_floats_stop_text + {\strc_floats_stop_text_indeed} + +% reserved text + +\tolerant\protected\def\strc_floats_start_reserve_text[#tag]#spacer[#settings]#spacer[#location]#spacer[#reference]#:#caption%% + {\flushnotes + \page_otr_command_flush_side_floats + \strc_floats_begin_text_group + \strc_floats_place[#tag][\v!text,#location,\v!left][#reference]{#caption}{\strc_floats_reserve_box{#settings}}} + +\protected\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} % hm +\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 + +\protected\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}} + +\protected\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 + {\page_postprocessors_linenumbers_box\nextbox % for aditya + \dostoptagged + \strc_floats_finish_placement} + \vbox} + +%D \starttyping +%D \definefloat +%D [one] [figure] +%D [default=right, +%D rightmargindistance=-20cm, +%D criterium=129pt, +%D fallback=rightmargin] +%D +%D \definefloat +%D [two] [figure] +%D [default=right, +%D rightmargindistance=-20cm, +%D criterium=129pt, +%D fallback=three] +%D +%D \definefloat +%D [three] [figure] +%D [default=rightmargin, +%D rightmargindistance=0cm] +%D +%D \placefloat[one]{}{\blackrule[width=30pt]} \samplefile{tufte} +%D \placefloat[one]{}{\blackrule[width=60pt]} \samplefile{tufte} +%D \placefloat[one]{}{\blackrule[width=90pt]} \samplefile{tufte} +%D \placefloat[one]{}{\blackrule[width=130pt]} \samplefile{tufte} +%D \placefloat[two]{}{\blackrule[width=130pt]} \samplefile{tufte} +%D \stoptyping + +\def\strc_floats_finish_placement + {\doifsomething{\floatparameter\c!criterium} + {\ifdim\wd\nextbox>\floatparameter\c!criterium\relax + \edef\forcedfloatmethod{\floatparameter\c!fallback}% + \ifempty\forcedfloatmethod \else + \doifelsecommandhandler\??float\forcedfloatmethod + {\let\currentfloat\forcedfloatmethod + \edef\floatlocation{\floatparameter\c!default}% + \let\forcedfloatmethod\floatlocation} + \donothing + \fi + \ifempty\forcedfloatmethod + \let\forcedfloatmethod\v!here + \fi + \fi}% + \strc_floats_check_extra_actions + \strc_floats_analyze_variables_two + \strc_floats_place_packaged_boxes + \dotagregisterfloat\askedfloatoptions\askedfloatmethod + \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 + +\newdimen\d_strc_floats_top +\newdimen\d_strc_floats_bottom +\newdimen\d_strc_floats_overflow + +% \def\strc_floats_calculate_skip#target#skip% +% {\begingroup +% \edef\askedfloatskip{\rootfloatparameter#skip}% +% \ifempty\askedfloatskip +% \global#target\zeropoint +% \orelse\ifx\askedfloatskip\v!none +% \global#target\zeropoint +% \else +% \setbox\scratchbox\vbox{\whitespace\blank[\askedfloatskip]}% todo: move whitespace inside blank +% \global#target\ht\scratchbox +% \fi +% \endgroup} + +\def\strc_floats_calculate_skip#target#skip% + {\begingroup + \edef\p_blank{\rootfloatparameter#skip}% + \ifx\p_blank\v!nowhite + \edef\p_blank{-\v!white}% + \fi + \prerollblank[\p_blank]% + \global#target\prerolledblank + \endgroup} + +\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 + % variable initializations + \global\d_page_sides_shift \zeropoint + \global\d_page_sides_maximum \zeropoint + \global\c_page_sides_align \zerocount + \global\c_page_sides_tolerance \zerocount + \global\c_page_sides_skipmode \zerocount + \global\c_strc_floats_rotation \zerocount + \global\d_page_sides_margin \floatparameter\c!margin + \global\d_page_sides_leftshift \floatparameter\c!leftmargindistance + \global\d_page_sides_rightshift \floatparameter\c!rightmargindistance + \global\d_page_sides_topoffset \floatparameter\c!topoffset + \global\d_page_sides_bottomoffset\floatparameter\c!bottomoffset + \global\c_page_sides_method \floatparameter\c!sidemethod + \global\c_page_one_float_method \floatparameter\c!textmethod + \global\c_page_floats_n_of_top \rootfloatparameter\c!ntop + \global\c_page_floats_n_of_bottom\rootfloatparameter\c!nbottom + \global\d_strc_floats_overflow \zeropoint + \ifconditional\c_strc_floats_par_float + \global\d_strc_floats_top \zeropoint + \global\d_strc_floats_bottom \zeropoint + \strc_floats_calculate_skip\d_page_sides_topskip \c!sidespacebefore + \strc_floats_calculate_skip\d_page_sides_bottomskip\c!sidespaceafter + \strc_floats_calculate_skip\d_page_sides_midskip \c!sidespaceinbetween + \strc_floats_calculate_skip\d_strc_floats_top \c!spacebeforeside + \strc_floats_calculate_skip\d_strc_floats_bottom \c!spaceafterside + \else + \global\d_page_sides_topskip \zeropoint + \global\d_page_sides_bottomskip \zeropoint + \strc_floats_calculate_skip\d_strc_floats_top \c!spacebefore + \strc_floats_calculate_skip\d_strc_floats_bottom\c!spaceafter + \fi + % keyword handling + \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\c_page_sides_skipmode \plusone }% + \doifinset\v!low \floatlocation{\global\c_page_sides_skipmode \plustwo }% + \doifinset\v!fit \floatlocation{\global\c_page_sides_skipmode \plusthree}% + \doifinset\v!tolerant \floatlocation{\global\c_page_sides_tolerance\plusone }% + \doifinset\v!verytolerant\floatlocation{\global\c_page_sides_tolerance\plustwo }% + \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}% + \doifinset\v!effective\floatlocation + {\letfloatparameter \c!leftmargin \effectiveleftskip + \letfloatparameter \c!rightmargin\effectiverightskip + \letfloatcaptionparameter\c!leftmargin \effectiveleftskip + \letfloatcaptionparameter\c!rightmargin\effectiverightskip}% + \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 + \doifelse{\floatparameter\c!freeregion}\v!yes + \settrue\setfalse\c_strc_floats_mark_as_free + \doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! ! + {\setfalse\c_page_floats_center_box_global + \setfalse\c_page_floats_center_box_local}} + +\permanent\def\naturalfloatheight{\the\naturalfloatwd} +\permanent\def\naturalfloatwidth {\the\naturalfloatht} +\permanent\def\naturalfloatdepth {\the\naturalfloatdp} + +\permanent\def\floatcaptionheight{\the\floatcaptionwd} +\permanent\def\floatcaptionwidth {\the\floatcaptionht} +\permanent\def\floatcaptiondepth {\the\floatcaptiondp} + +\newdimen\naturalfloatwd +\newdimen\naturalfloatht +\newdimen\naturalfloatdp + +\newdimen\floatcaptionwd +\newdimen\floatcaptionht +\newdimen\floatcaptiondp + +\def\strc_floats_set_natural_dimensions#box% + {\global\naturalfloatwd\wd#box\relax + \global\naturalfloatht\ht#box\relax + \global\naturalfloatdp\dp#box\relax} + +\def\strc_floats_set_caption_dimensions#box% + {\global\floatcaptionwd\wd#box\relax + \global\floatcaptionht\ht#box\relax + \global\floatcaptiondp\dp#box\relax} + +\permanent\def\doifelsemainfloatbody + {\unless\ifinsidesplitfloat + \expandafter\firstoftwoarguments + \orelse\ifconditional\splitfloatfirstdone + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doifmainfloatbodyelse\doifelsemainfloatbody + +% todo: optional user pars + +\let\currentfloatattribute\empty % to be checked + +\def\floatcaptionattribute + {\iflocation + \ifempty\currentfloatattribute + % safeguard, can be samepage too + \orelse\ifnofloatcaption + \orelse\ifinsidesplitfloat + \ifconditional\splitfloatfirstdone + \else + attr \destinationattribute \currentfloatattribute + \fi + \else + attr \destinationattribute \currentfloatattribute + \fi + \fi} + +% \def\floatcaptionattribute +% {\iflocation +% \ifempty\currentfloatattribute +% % safeguard, can be samepage too +% \orelse\ifnofloatcaption +% % nothing +% \orunless\ifinsidesplitfloat +% attr \destinationattribute \currentfloatattribute +% \orunless\ifconditional\splitfloatfirstdone +% attr \destinationattribute \currentfloatattribute +% \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 + \glet\currentfloatnumber \previousfloatnumber + \glet\currentfloatattribute \empty + \glet\currentfloatsynchronize\relax + \else + \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% + \edef\currentfloatgroup {\floatcaptionparameter\c!group}% + \ifnofloatnumber + \orelse\ifnofloatcaption + \orelse\ifempty\currentfloatgroup + % independent + \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi + \strc_counters_increment\currentfloatcounter + \orelse\ifcase\strc_floats_group_index + % first in group + \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi + \strc_counters_increment\currentfloatcounter + \else + % next in group + \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]% + \glet\previousfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatattribute \m_strc_counters_last_registered_attribute + \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize + \fi + % + \iftrialtypesetting\else\global\setfalse\usesamefloatnumber\fi % 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 + \ifzeropt\htdp\floatbox + \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 \ifempty\p_availablewidth \hsize\else\p_availablewidth \relax\fi + \availablefloatheight\ifempty\p_availableheight\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 + +\permanent\def\doifelserightpagefloat + {\unless\ifdoublesided + \expandafter\firstoftwoarguments + \orelse\ifsinglesided + \expandafter\firstoftwoarguments + \orelse\ifodd\purenumber\strc_float_realpage\space + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\def\doifelseoddpagefloat + {\ifodd\purenumber\strc_float_realpage\space + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifrightpagefloatelse\doifelserightpagefloat +\aliased\let\doifoddpagefloatelse \doifelseoddpagefloat + +\appendtoks + \enforced\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 ! ! ! + +\permanent\protected\def\movesidefloat[#settings]% (-)n*line|x=,y= + {\global\d_page_sides_downshift \zeropoint + \global\d_page_sides_extrashift\zeropoint + \ifhastok={#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 + \else + \movedownsidefloat[#settings]% + \fi} + +\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}} + +\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}} + +\def\strc_floats_move_down#setting% + {\begincsname\??floatmovement#setting\endcsname} + +\def\strc_floats_move_down_line#sign% + {\ifscratchconditionone \else + \global\d_page_sides_downshift\zeropoint + \scratchconditiononetrue + \fi + \global\advance\d_page_sides_downshift#sign\lineheight} + +\def\strc_floats_move_down_hang#lines% + {\ifscratchconditiontwo \else + \global\c_page_sides_n_of_lines\zerocount + \scratchconditiontwotrue + \fi + \global\advance\c_page_sides_n_of_lines#lines\relax} + +\permanent\protected\def\movedownsidefloat[#settings]% already in core + {\unless\ifhastok:{#settings}% + \begingroup + \scratchconditiononefalse + \scratchconditiontwofalse + \normalexpanded{\dorepeatwithcommand[#settings]}\strc_floats_move_down + \endgroup + \fi} + +\permanent\protected\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 + \ifempty\extrafloatlocation \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 + \ifzeropt\d_page_sides_downshift\else + \global\setbox\floatbox\vpack + {\vskip\d_page_sides_downshift + \nointerlineskip + \box\floatbox}% + \fi + \edef\p_minwidth{\floatparameter\c!minwidth}% + \ifempty\p_minwidth + % 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}}% + \ifempty\p_maxwidth + % 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 % why is this + {\global\setbox\floatbox\hpack to \scratchwidth + {\doifnot{\floatparameter\c!location}\v!left\hss + \box\floatbox + \doifnot{\floatparameter\c!location}\v!right\hss}} + +\permanent\protected\def\placefloats + {\page_otr_command_flush_floats} + +\permanent\protected\def\betweenfloatblanko % assumes that spaceafter is present + {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,.... + +% keep as old 1 +% +% \protected\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 +% +% \protected\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}% + \ifempty\m_space\orelse\ifx\m_space\v!none\else + \directvspacing\m_space + \fi} + +\permanent\protected\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 % todo + {\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} + +\permanent\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 + +% keep these as reference: +% +% \def\strc_floats_align_content_indeed +% {\alignstrutmode\zerocount +% \doifnotcommon\floatcaptionlocation{\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} +% +% Test case: +% +% \setupfloats[location=left] +% \setupfloatcaption[width=max] +% +% \startfloatcombination +% \placefigure{}{} +% \placefigure{}{} +% \stopfloatcombination + +%D In a floatcombination we ignore the margins .. if that is ever needed we need another +%D state (instead of local). + +\def\strc_floats_align_indeed + {\alignedline{\floatparameter\c!location}\v!middle} + +\def\strc_floats_shift_indeed#1% + {\shiftalignedline{#1\c!leftmargin}{#1\c!rightmargin}{#1\c!innermargin}{#1\c!outermargin}} + +\def\strc_floats_align_content_indeed + {\alignstrutmode\zerocount + \ifx\forcedfloatmethod\v!local \else + \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} + {\strc_floats_shift_indeed\floatparameter}% + \expandafter\strc_floats_align_indeed + \fi} + +\def\strc_floats_align_caption_indeed + {\alignstrutmode\zerocount + \ifx\forcedfloatmethod\v!local + \expandafter\strc_floats_align_indeed_local + \else + \strc_floats_shift_indeed\floatcaptionparameter + \expandafter\strc_floats_align_indeed + \fi} + +% \def\strc_floats_align_indeed_local#1% +% {\begingroup +% \hsize\wd\floatbox +% \strc_floats_align_indeed{#1}% +% \endgroup} + +\let\strc_floats_align_indeed_local\firstofoneargument + +\newdimen\d_strc_floats_content +\newdimen\d_strc_float_temp_height +\newdimen\d_strc_float_temp_width + +\newconditional\c_floats_adapt_to_caption_width +\newconditional\c_floats_store_minimal_package + +\def\captionminwidth {15\bodyfontsize} % can become parameter (but what name) +\def\captionovershoot{2\emwidth} % can become parameter (but what name) + +\let\strc_floats_mark_pag_as_free\relax + +\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 + \strc_floats_set_caption_dimensions\voidbox + %\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}}% + \strc_floats_set_caption_dimensions\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 + \ifconditional\c_floats_store_minimal_package + % nothing + \orelse\ifcase\c_strc_floats_rotation + \doifnotinset\v!margin\floatlocation % brr, really needed! see wm + {\postcenterfloatbox\d_strc_floats_content + \strc_floats_mark_pag_as_free}% + % mark as free not done here + \else + \global\setbox\floatbox\vpack + {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\box\floatbox}}% + \strc_floats_mark_pag_as_free + \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_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 + \doifcommonelse\floatcaptionlocation{\v!top,\v!bottom} + {\strc_floats_prepare_page_caption_top_bottom} + {\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_side_auto_caption + \orelse\ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_side_auto_caption + \else + \strc_floats_prepare_side_width_caption + \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 + \orelse\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} + +\def\strc_floats_prepare_page_caption_top_bottom_fit_max + {\unless\ifx\p_strc_floats_caption_minwidth\v!fit + \strc_floats_prepare_stack_caption_fixed + \orelse\ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_stack_caption_max + \orelse\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} + +\def\strc_floats_caption_set_align + {\edef\m_align{\v!reset\ifempty\p_strc_floats_caption_align\else,\fi\p_strc_floats_caption_align}% + \doifinset\v!tolerant \floatcaptionlocation{\edef\m_align{\m_align,\v!tolerant}}% + \doifinset\v!verytolerant\floatcaptionlocation{\edef\m_align{\m_align,\v!verytolerant}}% + \doifinset\v!stretch \floatcaptionlocation{\edef\m_align{\m_align,\v!stretch}}% + \setupalign[\m_align]} + +\def\strc_floats_prepare_side_auto_caption + {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax + \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 + \ifempty\p_strc_floats_caption_align + \raggedcenter % on purpose overloads align ! + \fi + \strc_floats_make_complete_caption}} + +\def\strc_floats_prepare_stack_caption_auto + {\ifempty\p_strc_floats_caption_align \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 + \ifconditional\c_floats_adapt_to_caption_width + \let\captionminwidth \!!zeropoint + \let\captionovershoot\!!zeropoint + \fi + \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}% +% \ifconditional\c_floats_adapt_to_caption_width +% \setbox\b_strc_floats_content\hpack to \captionhsize{\hss\box\b_strc_floats_content\hss}% +% \fi + \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}% + \orelse\if\empty\p_strc_floats_caption_align + \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} + +\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 \hpack \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\floatcaptionlocation + {\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 \hpack \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\floatcaptionlocation + {\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 + \setbox\scratchboxone\vbox{#2}% + \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content + \global\d_strc_floats_overflow\dimexpr\htdp\scratchboxone-\htdp\b_strc_floats_content\relax + \fi + \ht\scratchboxone\d_strc_float_temp_height + \everyrightofalignedline{\hsmash{\hskip#1\box\scratchboxone}}% + \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 + \setbox\scratchboxone\vbox{#2}% + \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content + \global\d_strc_floats_overflow\dimexpr\htdp\scratchboxone-\htdp\b_strc_floats_content\relax + \fi + \ht\scratchboxone\d_strc_float_temp_height + \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\scratchboxone\relax\box\scratchboxone}}% + \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[\floatcaptionlocation] + [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin, + \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin, + \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin, + \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[\floatcaptionlocation] + [ \v!low=>\let\next\strc_floats_build_box_low, + \v!middle=>\let\next\strc_floats_build_box_middle, + \v!high=>\let\next\strc_floats_build_box_high]% + \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 + {\doifelseinset\v!righthanging\floatcaptionlocation + {\strc_floats_flush_right_caption_hang} + {\doifelseinset\v!lefthanging\floatcaptionlocation + {\strc_floats_flush_left_caption_hang} + {\doifelseinset\v!hang\floatcaptionlocation + {\doifelseinset\v!outer\floatcaptionlocation + {\doifelserightpagefloat{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}} + {\doifelseinset\v!right\floatcaptiondirectives + {\strc_floats_flush_right_caption_hang} + {\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 + \hsize\d_strc_float_temp_width + \ifconditional\c_strc_floats_par_float + \strc_floats_locate_side_float{\box\b_strc_floats_caption}% + \vss\strc_floats_between_stack + \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 + \vpack to \noflines\lineheight{\unvbox\scratchbox}} + +\def\strc_floats_build_box_bottom_stack_grid + {\dp\b_strc_floats_caption\strutdepth + \setbox\scratchbox\vbox + {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width + \ifconditional\c_strc_floats_par_float + \hpack{\box\b_strc_floats_content}% + \vss\strc_floats_between_stack + \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 + \vpack 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 + \hsize\d_strc_float_temp_width + \ifconditional\c_strc_floats_par_float + \strc_floats_locate_side_float{\box\b_strc_floats_caption}% + \vss\strc_floats_between_stack\vss + \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\vpack + {\strc_floats_align_content{\copy\b_strc_floats_content}% + \strc_floats_align_caption{\copy\b_strc_floats_caption}}% + \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy + \vbox to \noflines\lineheight + {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width + \ifconditional\c_strc_floats_par_float + \hpack{\box\b_strc_floats_content}% + \vss\strc_floats_between_stack\vss + \strc_floats_locate_side_float{\box\b_strc_floats_caption}% + \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!lines=>\let\next\strc_floats_build_box_top_stack_stretch]% was \v!grid but interfered + \next} + +\def\strc_floats_build_box_bottom + {\let\next\strc_floats_build_box_bottom_stack_normal + \processfirstactioninset[\floatcaptionparameter\c!location] + [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid, + \v!lines=>\let\next\strc_floats_build_box_bottom_stack_stretch]% was \v!grid but interfered + \next} + +\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}} +\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}} + +\permanent\protected\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}} + +\def\strc_floats_build_box + {\strc_floats_build_box_before + \global\setbox\floatbox\vbox % pack ? probably not + {\strc_floats_set_local_hsize + \forgetall + \ifconditional\c_floats_store_minimal_package + \strc_floats_build_box_separate_make + \else + % \let\floatcaptionarrangement\s!default + \let\floatcaptionarrangement\v!bottom % for Alan + \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step + \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname + \lastnamedcs + \else + \strc_floats_build_box_default + \fi + \fi}% + \strc_floats_build_box_after} + +% \let\strc_floats_build_box_before\relax +% \let\strc_floats_build_box_after \relax + +\def\strc_floats_build_box_before + {\let\currentfloatframed\currentfloat + \floatwidth\wd + \ifdim\wd\b_strc_floats_content>\wd\b_strc_floats_caption + \b_strc_floats_content\else\b_strc_floats_caption + \fi} + +\def\strc_floats_build_box_after + {\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax} + +\def\strc_floats_build_box_after_indeed + {\global\setbox\floatbox\hpack + {\edef\m_width{\floatframedparameter\c!width}% + \ifx\m_width\v!fit + \let\m_width\floatwidth + \orelse\ifx\m_width\v!broad + \let\m_width\v!fit + \fi + \letfloatframedparameter\c!strut\v!no + \letfloatframedparameter\c!width\m_width + \inheritedfloatframedframed + {\box\floatbox}}} + +% special purpose: used in floatcombinations +% +% todo : keep float content and caption separated in local + +\newbox\b_strc_floats_separate_content +\newbox\b_strc_floats_separate_caption + +\def\strc_floats_build_box_separate_set + {\settrue\c_floats_adapt_to_caption_width + \settrue\c_floats_store_minimal_package} + +% \def\strc_floats_build_box_separate_make +% {\offinterlineskip +% \vpack to \onepoint{\box\b_strc_floats_content}\break +% \vpack to \onepoint{\box\b_strc_floats_caption}} + +%D Remark for \LMTX: we don't want to migrate inserts here so we unpack +%D (could be a flag). When migrated, the inserts end up in the vertical +%D list and we no longer have just a box (but inserts and lines again). + +\def\strc_floats_build_box_separate_make + {\savebox\??localfloatstack{\number\numexpr\c_strc_localfloats_n+1\relax:a}{\box\b_strc_floats_content}% + \savebox\??localfloatstack{\number\numexpr\c_strc_localfloats_n+1\relax:b}{\box\b_strc_floats_caption}} + +\protected\def\strc_floats_build_box_separate_split#1% + {\global\setbox\b_strc_floats_separate_content\vpack{\foundbox\??localfloatstack{\number#1:a}}% + \global\setbox\b_strc_floats_separate_caption\tpack{\foundbox\??localfloatstack{\number#1:b}}} + +% \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!rightmargin \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!leftmargin \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!innermargin \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!outermargin \strc_floats_build_box_side % added 2016-08-23 + +\installfloatboxbuilder \v!left \strc_floats_build_box_side +\installfloatboxbuilder \v!right \strc_floats_build_box_side +\installfloatboxbuilder \v!inner \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!outer \strc_floats_build_box_side % added 2016-08-23 + +\installfloatboxbuilder \v!lefthanging \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!righthanging \strc_floats_build_box_side % added 2016-08-23 +\installfloatboxbuilder \v!hang \strc_floats_build_box_side % added 2016-08-23 + +\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 + +\permanent\def\postcenterfloatbox#1% + {\scratchdimen + \ifcase\postcenterfloatmethod + #1% \wd\floatbox + \orelse\ifinsidecolumns + \ifpostponecolumnfloats\makeupwidth\else#1\fi + \orelse\ifdim#1>\hsize + \hsize + \else + \wd\floatbox + \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 + \orelse\ifconditional\c_page_floats_center_box_local + \donetrue + \else + \donefalse + \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}% \vpack >? + %\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}}% \hpack ? + %\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 + \orelse\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_side_caption_fit + \else + \strc_floats_prepare_side_caption_width + \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? + \strc_floats_caption_set_align + \hsize\wd\b_strc_floats_content + \strc_floats_make_complete_caption}% + \else + % maybe we should listen to the align option here (now side floats need the max option + \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 + \ifconditional\c_floats_store_minimal_package \else + \setbox\floatbox\hpack{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently + \fi + \global\floatheight\htdp\floatbox + \global\floatwidth\wd\floatbox + \ifconditional\c_floats_store_minimal_package \else + \doifnotinset\v!margin\floatlocation % gaat namelijk nog fout + {\setbox\floatbox\vpack + {\parindent\zeropoint + \box\floatbox}}% + \fi + \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 and floatcombinations + +\permanent\protected\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn + {\clf_analysefloatmethod{#1}} % move definition to lua end + +\permanent\protected\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 + \ifempty\forcedfloatmethod \else + \let\floatmethod\forcedfloatmethod + \fi + \let\askedfloatmethod\floatmethod + \ifexporting \ifx\askedfloatmethod\v!here \else + \showmessage\m!floatblocks{15}{\askedfloatmethod,\v!here}% + \let\floatlocation\v!here + \fi \fi + % [] will go + \edef\floatlocationmethod{\floatmethod,\floatlocation}% + \csname\??floatmethods\currentoutputroutine:\floatmethod\endcsname + \fi} + +\installcorenamespace{floatsettings} + +\permanent\protected\def\installfloatmethod#1#2#3% routine keyword handler + {\setvalue{\??floatmethods#1:#2}{#3}} + +\permanent\protected\def\handlefloatmethod#1% + {\csname\??floatmethods\currentoutputroutine:#1\endcsname} + +% \protected\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}} +% +% \protected\def\startfloatmethodsettings#1#2 #3\stopfloatmethodsettings +% {\csname\??floatsettings#1:#2\endcsname\expandafter{\the\csname\??floatsettings#1:#2\endcsname#3}} +% +% \let\stopfloatmethodsettings\relax +% +% \protected\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} + +% can move to page-one: + +\installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here +\installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force +\installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left +\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 + +%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 + +\permanent\protected\def\resetlocalfloats + {\global\c_strc_localfloats_n\zerocount + \initializeboxstack\??localfloatstack} + +\permanent\protected\def\somelocalfloat + {\global\advance\c_strc_localfloats_n\plusone + \savebox\??localfloatstack{\number\c_strc_localfloats_n}{\box\floatbox}} + +\permanent\protected\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}} + +\permanent\protected\def\flushlocalfloats + {\getlocalfloats + \resetlocalfloats} + +% \protected\def\getlocalfloat#1% +% {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}}% \vbox{\restorebox...} + +\permanent\protected\def\getlocalfloat#1% + {\foundbox\??localfloatstack{\number#1}} % \vbox{\restorebox...} + +\permanent\protected\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/tex/context/base/mkxl/strc-ind.mkxl b/tex/context/base/mkxl/strc-ind.mkxl new file mode 100644 index 000000000..31d7eb575 --- /dev/null +++ b/tex/context/base/mkxl/strc-ind.mkxl @@ -0,0 +1,128 @@ +%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 + \frozen\instance\setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}% + \frozen\instance\setuevalue {\e!stop \currentindentedtext}{\strc_indentedtexts_stop}% + % to be avoided ... might go away + \frozen\instance\setuevalue {\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{0}}% + \frozen\instance\setuevalue {\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{1}}% + \frozen\instance\setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}% +\to \everydefineindentedtext + +\protected\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} + +\protected\def\strc_indentedtexts_stop + {\indentedtextparameter\c!after + \par + \endgroup} + +\permanent\tolerant\protected\def\startindentedtext[#1]% + {\strc_indentedtexts_start{#1}\c_strc_indentedtexts_nesting} + +\permanent\let\stopindentedtext\strc_indentedtexts_stop + +\protected\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/tex/context/base/mkxl/strc-ini.mklx b/tex/context/base/mkxl/strc-ini.mklx new file mode 100644 index 000000000..3897c1d2a --- /dev/null +++ b/tex/context/base/mkxl/strc-ini.mklx @@ -0,0 +1,81 @@ +%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}{} + +\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. + +\permanent\tolerant\protected\def\defineresetset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:resets} {#name}{\detokenize{#set}}{\detokenize{#default}}true\relax} +\permanent\tolerant\protected\def\defineseparatorset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:separators} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} +\permanent\tolerant\protected\def\defineconversionset[#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:conversions}{#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} +\permanent\tolerant\protected\def\defineprefixset [#name]#spacer[#set]#spacer[#default]{\clf_definestructureset{structure:prefixes} {#name}{\detokenize{#set}}{\detokenize{#default}}false\relax} + +\aliased\let\definestructureresetset \defineresetset +\aliased\let\definestructureseparatorset \defineseparatorset +\aliased\let\definestructureconversionset\defineconversionset +\aliased\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/tex/context/base/mkxl/strc-itm.mklx b/tex/context/base/mkxl/strc-itm.mklx new file mode 100644 index 000000000..a1de95195 --- /dev/null +++ b/tex/context/base/mkxl/strc-itm.mklx @@ -0,0 +1,1907 @@ +%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}{} + +%D As we analyze/register widths and such we could as well push and pop the numbers +%D at the \LUA\ end (which saves a few calls). +%D +%D Cleaning up this module happened around the time when Kate Bush came up with the +%D nicest numbered list of words: 50 Words For Snow. It's therefore no surprise that +%D I had that cd running several times when updating this code. One of the +%D highlights of 2011. +%D +%D This module needs to be rewritten but that is tricky with respect to +%D compatibilitity. Basically each major variant (regular, text, columns, +%D horizontal, etc) needs to be on its own. + +% 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 +% +% \startitemize[n,repeat][width=0pt] +% \noitem \startitemize[a][width=2em] \item Item 1.a. \item Item 1.b. \stopitemize +% \noitem \startitemize[a][width=2em] \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 +\newconditional\c_strc_itemgroups_inline_head + +% 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 \orelse \ifempty\currentitemreference \else + \strc_itemgroups_insert_reference_indeed + \fi} + +\def\strc_itemgroups_insert_extra_reference + {\iftrialtypesetting \orelse \ifempty\currentitemreference \else + \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}% + \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 \locationcount % 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 + +\aliased\let\setupitemgroups\setupitemgroup + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}% + \frozen\instance\setuevalue{\e!stop \currentitemgroup}{\stopitemgroup}% + \frozen\instance\setuevalue{\e!setup\currentitemgroup\e!endsetup}{\setupitemgroup[\currentitemgroup]}% obsolete + \let\currentparentitemgroup\currentitemgroup + \definecounter[\v_strc_itemgroups_counter]% +\to \everydefineitemgroup + +%D Global states + +\def\strc_itemgroups_store_continue_state#options#settings% + {\xdefcsname\??itemgroupoption \currentitemgroup\endcsname{\strc_itemgroups_process_options{#options}}% + \gdefcsname\??itemgroupsetting\currentitemgroup\endcsname{\setupcurrentitemgroup[#settings]}} + +\def\strc_itemgroups_fetch_continue_state + {\csname\??itemgroupoption \currentitemgroup\endcsname + \csname\??itemgroupsetting\currentitemgroup\endcsname} + +\def\strc_itemgroups_reset_continue_state + {\gletcsname\??itemgroupoption \currentitemgroup\endcsname\relax + \gletcsname\??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} + +\protected\def\strc_itemgroups_process_options#options% + {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml + +% \installcommalistprocessorcommand \strc_itemgroups_process_option_list \strc_itemgroups_process_option +% +% \protected\def\strc_itemgroups_process_options#options% +% {\normalexpanded{\strc_itemgroups_process_option_list[#options]}} % expansion of options is handy for xml + +\def\strc_itemgroups_process_option#option% + {\edef\itemgroupconstantvalue{#option}% + \ifempty\itemgroupconstantvalue\else + \splitatasterisk\itemgroupconstantvalue\itemgroupfirst\itemgroupsecond + \ifempty\itemgroupsecond + \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} + +\def\strc_itemgroups_process_set_option_unpack + {\ifcase\c_strc_itemgroups_nesting\else + \setfalse\c_strc_itemgroups_pack + \fi} + +\setvalue{\??itemgroupkeyword\!!zerocount }{} % ignore 0 +\setvalue{\??itemgroupkeyword\v!packed }{\strc_itemgroups_process_set_option_pack} +\setvalue{\??itemgroupkeyword\v!unpacked }{\strc_itemgroups_process_set_option_unpack} +\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 }{\ifempty\itemgroupfirst + \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!headintext }{\settrue\c_strc_itemgroups_inline_head} +\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!notjoinedup}{\setfalse\c_strc_itemgroups_joined} +\setvalue{\??itemgroupkeyword\v!serried }{\edef\itemgroupfirst{-\ifempty\itemgroupfirst1\else\itemgroupfirst\fi}% + \letitemgroupparameter\c!factor\itemgroupfirst} +\setvalue{\??itemgroupkeyword\v!stopper }{\letitemgroupparameter\c!placestopper\v!yes} % keep {} +\setvalue{\??itemgroupkeyword\v!nostopper }{\letitemgroupparameter\c!placestopper\v!no} % keep {} +\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 }{\setitemgroupparameter\c!width {1.5\emwidth}% + \setitemgroupparameter\c!distance {.5\emwidth}% + %\letitemgroupparameter\c!factor \!!zerocount + \letitemgroupparameter\c!factor {\zerocount}% + \setitemgroupparameter\c!packcriterium{\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} + +% \installcommalistprocessorcommand \strc_itemgroups_preset_stage_one_list \strc_itemgroups_preset_stage_one_indeed +% +% \def\strc_itemgroups_preset_stage_one#options% +% {\normalexpanded{\strc_itemgroups_preset_stage_one_list[#options]}} + +\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 + \orelse\ifconditional\c_strc_itemgroups_joined + % \empty + \else + \itemgroupparameter\c!before + \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 + \orelse\ifconditional\c_strc_itemgroups_joined + % \empty + \else + \itemgroupparameter\c!after + \fi} + +\def\strc_itemgroups_between_command + {\ifconditional\c_strc_itemgroups_nowhite + \nowhitespace + \orelse\ifconditional\c_strc_itemgroups_joined + % \empty + \else + \itemgroupparameter\c!inbetween + \fi} + +\def\strc_itemgroups_before_head_command + {\ifconditional\c_strc_itemgroups_nowhite + \nowhitespace + \orelse\ifconditional\c_strc_itemgroups_joined + % \empty + \else + \itemgroupparameter\c!beforehead + \fi} + +\def\strc_itemgroups_after_head_command + {\ifconditional\c_strc_itemgroups_nowhite + \nowhitespace + \orelse\ifconditional\c_strc_itemgroups_joined + % \empty + \else + \itemgroupparameter\c!afterhead + \fi} + +% compatible setup command: + +\let\strc_itemgroups_normal_setup\setupitemgroup + +\permanent\overloaded\tolerant\protected\def\setupitemgroup[#category]#spacer[#levels]#spacer[#options]#spacer[#settings]% category level|each options|settings settings|options + {\ifarguments + % nothing to set up + \or + \edef\strc_itemgroups_setup_what{#levels}% + \strc_itemgroups_normal_setup[#category]% == settings + \or + \edef\strc_itemgroups_setup_what{#levels}% + \strc_itemgroups_setup_each{#category}{#levels}% + \or + \edef\strc_itemgroups_setup_what{#levels}% + \ifx\strc_itemgroups_setup_what\v!each + \strc_itemgroups_setup_each{#category}{#options}% + \else + \strc_itemgroups_setup_list{#levels}{#category}{#options}% + \fi + \or + \edef\strc_itemgroups_setup_what{#levels}% + \ifx\strc_itemgroups_setup_what\v!each + \strc_itemgroups_setup_each{#category}{#options}% + \strc_itemgroups_setup_each{#category}{#settings}% + \else + \strc_itemgroups_setup_list{#levels}{#category}{#options}% + \strc_itemgroups_setup_list{#levels}{#category}{#settings}% + \fi + \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_each#category#whatever% + {\ifcondition\validassignment{#whatever}% + \strc_itemgroups_normal_setup[#category][#whatever]% + \else + \strc_itemgroups_normal_setup[#category][\c!option={#whatever}]% + \fi} + +\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_setup_list#subcategories#category#whatever% + {\ifcondition\validassignment{#whatever}% + \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}% + \else + \processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}% + \fi} + +\def\strc_itemgroups_increment_item_counter + {\ifconditional\c_strc_itemgroups_sub \else + \ifconditional\c_strc_itemgroups_symbol \else % \ifempty\strc_itemgroups_extra_symbol + \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel + \fi + \fi} + +\protected\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} + +\installcorenamespace{itemstopper} + +\setvalue{\??itemstopper\v!yes }{\itemgroupparameter\c!stopper} +\setvalue{\??itemstopper\v!display}{\ifconditional\c_strc_itemgroups_inline\else\itemgroupparameter\c!stopper\fi} +\setvalue{\??itemstopper\v!inline }{\ifconditional\c_strc_itemgroups_inline\itemgroupparameter\c!stopper\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=\begincsname\??itemstopper\itemgroupparameter\c!placestopper\endcsname, + \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}% + \ifempty\strc_itemgroups_tmp_symbol \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 + \orelse\ifnum\itemgroupparameter\c!factor>\zerocount + \d_strc_itemgroups_list_width\itemgroupparameter\c!step\relax + \ifzeropt\d_strc_itemgroups_list_width \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 + \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax + \let\currentitemgroup\savedcurrentitemgroup} + +\permanent\tolerant\protected\def\startitemgroup[#category]#spacer[#options]#spacer[#settings]% + {\begingroup % (1) + \nofarguments\lastarguments + \def\currentitemgroup{#category}% no nested mixing of itemgroups + \let\currentparentitemgroup\currentitemgroup + \global\advance\c_strc_itemgroups_nesting\plusone + \def\currentitemlevel{\number\c_strc_itemgroups_nesting}% + \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}% + \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}% + % + \edef\itemgroupoptions{\itemgroupparameter\c!option}% + \let\itemgroupextraoptions\empty + \ifcase\nofarguments + \strc_itemgroups_start_indeed{}% + \or + \strc_itemgroups_start_indeed{}% + \or + \ifhastok={#options}% + \strc_itemgroups_start_indeed{#options}% + \else + \edef\itemgroupextraoptions{#options}% + \strc_itemgroups_start_indeed{}% + \fi + \or + \edef\itemgroupextraoptions{#options}% + \strc_itemgroups_start_indeed{#settings}% + \fi} + +\def\strc_itemgroups_start_indeed#settings% + {\ifempty\itemgroupoptions + \let\itemgroupoptions\itemgroupextraoptions + \orelse\ifempty\itemgroupextraoptions + % ok + \else + \edef\itemgroupoptions{\itemgroupoptions,\itemgroupextraoptions}% + \fi + \begingroup % (2) + \the\itemgroupcommands + \setconditional\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 + \ifempty\itemgroupoptions + \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 + % + \ifconditional\c_strc_itemgroups_pack + \ifnum\currentnofitems>\itemgroupparameter\c!packcriterium\relax\else + \setfalse\c_strc_itemgroups_pack + \fi + \fi + % + \ifnum\c_strc_itemgroups_nesting=\plusone % NIEUW + \doadaptleftskip {\itemgroupparameter\c!margin}% + \doadaptleftskip {\itemgroupparameter\c!leftmargin}% + \doadaptrightskip{\itemgroupparameter\c!rightmargin}% + \fi + % + \doadaptleftskip {\itemgroupparameter\c!leftmargindistance}% + \doadaptrightskip{\itemgroupparameter\c!rightmargindistance}% + % + \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 + \ifempty\strc_itemgroups_used_symbol + \strc_itemgroups_set_symbol\strc_itemgroups_asked_symbol % ** default value + \ifempty\strc_itemgroups_used_symbol + \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\orelse\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 + \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 + \frozen\advance\leftskip\d_strc_itemgroups_list_width\relax + \fi + \fi + \ifempty\m_strc_itemgroups_repeat_start + \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\currentitemgroup:\currentitemlevel}#symbol} + +\def\strc_itemgroups_store_local_symbol#symbol% + {\letgvalue{\??itemgrouplocal\currentitemgroup:\currentitemlevel}#symbol} + +\def\strc_itemgroups_fetch_global_symbol + {\csname\??itemgroupglobal\currentitemgroup:\currentitemlevel\endcsname} + +\def\strc_itemgroups_fetch_local_symbol + {\csname\??itemgrouplocal\currentitemgroup:\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\currentitemgroup:\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 + \protected\def\startcolumns[#settings]{} + \protected\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 + +\permanent\protected\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 + \orelse\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 + % 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. + +\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 + +\tolerant\protected\def\startitemgroupitem[#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 + \begstrut % \strut + \nobreak % else problems with intext items + \seteffectivehsize % NEW ! + \hskip\d_strc_itemgroups_signal % concat + \itemgroupparameter\c!command} + +\protected\def\stopitemgroupitem + {\ifhmode + \endstrut % new per 2017-12-15 + \fi + \ifconditional\c_strc_itemgroups_text + % nothing + \else + \endgraf + \fi} + +\tolerant\protected\def\startitemgrouphead[#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]% + \startitemgroupitem[#reference]% + \pickupgroupedcommand + \strc_itemgroups_start_head_indeed + \strc_itemgroups_stop_head_indeed + \strc_itemgroups_head_body_indeed} + +\protected\def\stopitemgrouphead + {\dostoptagged + \stopitemgroupitem} + +\protected\def\strc_itemgroups_start_head_indeed + {\settrue\c_strc_itemgroups_head + \dotagsetitem\s!head% % weird place + \dostarttagged\t!itemhead\empty + \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces} + +\protected\def\strc_itemgroups_stop_head_indeed + {\removeunwantedspaces + \dostoptagged + \ifconditional\c_strc_itemgroups_inline_head + \space + \ignorespaces + \else + \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 + \fi} + +\protected\def\strc_itemgroups_head_body_indeed + {\dostarttagged\t!itembody\empty + \noindentation + \ignorespaces} + +% Simple commands. + +\protected\def\strc_itemgroups_start_do_item + {\startitemgroupitem} + +\protected\def\strc_itemgroups_start_no_item + {\let\currentitemreference\empty + \strc_itemgroups_increment_item_counter + %\advance\c_strc_itemgroups_n_of_items\plusone + \setbox\b_strc_itemgroups\emptyhbox + \strc_itemgroups_check_for_repeated + \ignorespaces} + +\protected\def\strc_itemgroups_start_button[#destination]% + {\edef\m_strc_itemgroups_destination{#destination}% + \startitemgroupitem} + +\protected\def\strc_itemgroups_start_symbol#text% + {\def\strc_itemgroups_extra_symbol{#text}% + \settrue\c_strc_itemgroups_symbol + \startitemgroupitem + \dotagsetitem\s!symbol} + +\protected\def\strc_itemgroups_start_dummy + {\strc_itemgroups_start_symbol + %\strut\strut} % two ? + \begstrut} + +\protected\def\strc_itemgroups_start_subitem + {\settrue\c_strc_itemgroups_sub + \startitemgroupitem + \dotagsetitem\s!sub} + +\protected\def\strc_itemgroups_start_edge#text% + {\strc_itemgroups_start_symbol + {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting + \dostarttagged\t!ignore\empty % for the moment, maybe an attribute + \hbox to \d_strc_itemgroups_list_width + {#text\hskip\itemgroupparameter\c!distance}% + \dostoptagged}} + +\protected\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} + +\protected\def\strc_itemgroups_start_text#text% + {\def\strc_itemgroups_extra_symbol{#text}% + \settrue\c_strc_itemgroups_symbol + \settrue\c_strc_itemgroups_txt + \startitemgroupitem} + +% \protected\def\strc_itemgroups_start_head +% {\settrue\c_strc_itemgroups_head +% \startitemgrouphead} + +\protected\def\strc_itemgroups_start_items + {\dosingleempty\strc_itemgroups_start_items_indeed} + +\protected\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost + {\strc_itemgroups_start_edge + {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}% + \unskip}} + +\protected\def\startspecialitemgroupitem[#name]% todo: frozen + {\ifcsname\??itemgroupstart#name\endcsname + \expandafter\lastnamedcs + \else + \expandafter\strc_itemgroups_start_do_item + \fi} + +\protected\def\stopspecialitemgroupitem % todo: frozen + {\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 +\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text + +\def\strc_itemgroups_optimize_breaks + {\ifcase\c_strc_itemgroups_column_depth + \ifconditional\c_strc_itemgroups_optimize + \ifcase\c_strc_itemgroups_max_items + \orelse\ifnum\c_strc_itemgroups_max_items=\plusthree + \ifnum\c_strc_itemgroups_n_of_items>\plusone + \strc_itemgroups_insert_nobreak + \fi + \orelse\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 + \orelse\ifnum\c_strc_itemgroups_max_items=\c_strc_itemgroups_n_of_items\relax + \strc_itemgroups_insert_nobreak + \orelse\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} + +\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 + +\protected\def\strc_itemgroups_start_head_sym#text% + {\def\strc_itemgroups_extra_symbol{#text}% + \settrue\c_strc_itemgroups_symbol + \settrue\c_strc_itemgroups_head + %\strc_itemgroups_start_head} + \startitemgrouphead} + +\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 \orelse \ifempty\m_strc_itemgroups_destination \else + \setbox\b_strc_itemgroups\hbox{\directgotobox{\box\b_strc_itemgroups}[\m_strc_itemgroups_destination]}% + \fi} + +\def\strc_itemgroups_check_indenting + {\setfalse\c_strc_itemgroups_indented_first + \ifempty\m_strc_itemgroups_indenting \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 + \ifempty\m_strc_itemgroups_repeat_start + \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 + \strc_itemgroups_optimize_breaks + \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 + \orelse\ifdim\d_strc_itemgroups_asked_width>\zeropoint + \strc_itemgroups_make_aligned_box + \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 + \ifzeropt\d_strc_itemgroups_asked_width + \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 + \orelse\ifconditional\c_strc_itemgroups_inline + \strc_itemgroups_handle_groups_inline_item + \orelse\ifconditional\c_strc_itemgroups_txt + \strc_itemgroups_handle_text_item + \else + \strc_itemgroups_handle_lapped_item_positive + \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\s!plus\interwordstretch\s!minus\interwordshrink}} + +\setvalue\??itemgroupdistance % catches empty value + {\let\m_strc_itemgroups_text_distance\zeropoint} + +\protected\def\strc_itemgroups_set_text_item_distance + {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}% + \ifempty\m_strc_itemgroups_text_distance + % + \orelse\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname + \lastnamedcs + \else + \strc_itemgroups_set_text_item_distance_indeed + \fi} + +\def\strc_itemgroups_set_text_item_distance_indeed + {\assignvalue + \m_strc_itemgroups_text_distance + \m_strc_itemgroups_text_distance + {.5\interwordspace\s!plus.5\emwidth}% + {\interwordspace \s!plus \emwidth}% + {\emwidth \s!plus \interwordstretch\s!minus\interwordshrink}} + +% \protected\def\strc_itemgroups_default_command +% {\EveryPar{\ignorespaces}% needed ? +% \ignorespaces} + +\protected\def\strc_itemgroups_default_command + {\ignorespaces} + +%D Special case: + +\protected\def\strc_itemgroups_head#text\par + {\startitemgrouphead{#text}} + +%D The local commands: + +\ifdefined\item \else \let\item \relax \fi +\ifdefined\sub \else \let\sub \relax \fi +\ifdefined\sym \else \let\sym \relax \fi +\ifdefined\ran \else \let\ran \relax \fi +\ifdefined\its \else \let\its \relax \fi +\ifdefined\mar \else \let\mar \relax \fi +\ifdefined\noitem \else \let\noitem \relax \fi +\ifdefined\itm \else \let\itm \relax \fi +\ifdefined\but \else \let\but \relax \fi +\ifdefined\nop \else \let\nop \relax \fi +\ifdefined\txt \else \let\txt \relax \fi +\ifdefined\head \else \let\head \relax \fi +\ifdefined\headsym \else \let\headsym \relax \fi +\ifdefined\startitem \else \let\startitem \relax \fi +\ifdefined\stopitem \else \let\stopitem \relax \fi +\ifdefined\starthead \else \let\starthead \relax \fi +\ifdefined\stophead \else \let\stophead \relax \fi +\ifdefined\startspecialitem \else \let\startspecialitem\relax \fi +\ifdefined\stopspecialitem \else \let\stopspecialitem \relax \fi + + +\appendtoks + \enforced\let\item \strc_itemgroups_start_do_item + \enforced\let\sub \strc_itemgroups_start_subitem + \enforced\let\sym \strc_itemgroups_start_symbol + \enforced\let\ran \strc_itemgroups_start_edge + \enforced\let\its \strc_itemgroups_start_items + \enforced\let\mar \strc_itemgroups_start_margin + \enforced\let\noitem \strc_itemgroups_start_no_item + \enforced\let\itm \strc_itemgroups_start_do_item + \enforced\let\but \strc_itemgroups_start_button + \enforced\let\nop \strc_itemgroups_start_dummy + \enforced\let\txt \strc_itemgroups_start_text + \enforced\let\head \strc_itemgroups_head + \enforced\let\headsym \strc_itemgroups_start_head_sym + \enforced\let\startitem \startitemgroupitem + \enforced\let\stopitem \stopitemgroupitem + \enforced\let\starthead \startitemgrouphead + \enforced\let\stophead \stopitemgrouphead + \enforced\let\startspecialitem\startspecialitemgroupitem + \enforced\let\stopspecialitem \stopspecialitemgroupitem +\to \itemgroupcommands + +\ifx\currentinterface \s!english \else + + \def\next#1#2{\ifcsname#1\endcsname\else\enforced\letcsname#1\endcsname#2\fi} + + \etoksapp\itemgroupcommands{% + \next{\v!item }\strc_itemgroups_start_do_item + \next{\v!sub }\strc_itemgroups_start_subitem + \next{\v!sym }\strc_itemgroups_start_symbol + \next{\v!ran }\strc_itemgroups_start_edge + \next{\v!head }\strc_itemgroups_head + \next{\v!its }\strc_itemgroups_start_items + \next{\v!mar }\strc_itemgroups_start_margin + \next{\v!txt }\strc_itemgroups_start_text + \next{\e!start\v!item}\startitemgroupitem + \next{\e!stop \v!item}\stopitemgroupitem + \next{\e!start\v!head}\startitemgrouphead + \next{\e!stop \v!head}\stopitemgrouphead + } + +\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 + +\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} + +\protected\def\stopcollectitems % todo: frozen + {\ifconditional\c_strc_itemgroups_collecting + \c_strc_itemgroups_collected_done \zerocount + \c_strc_itemgroups_collected_current\zerocount + \ifnum\c_strc_itemgroups_collected_stored>\zerocount + \ifconditional\c_strc_itemgroups_horizontal + \strc_itemgroups_before_command + \setfalse\c_strc_itemgroups_first + \strc_itemgroups_collected_flush + %\strc_itemgroups_after_command % triggered elsewhere + \else + \strc_itemgroups_collected_flush + \fi + \fi + \fi} + +\protected\def\startcollectitems % todo: frozen + {\ifconditional\c_strc_itemgroups_collecting + \c_strc_itemgroups_collected_stored\zerocount + \letvalue{\e!start\v!item}\strc_itemgroups_collected_store + \fi} + +%D Left-overs: + +\protected\def\item % todo: frozen + {\strc_itemgroups_item_alone} + +\def\strc_itemgroups_item_alone[#category]#text\par + {\doifelsesomething{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}% + \startitem#text\stopitem + \stopitemgroup} + +\protected\def\head % todo: frozen + {\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}% todo: frozen + {\startitemgroup[\v!itemize]% + \startitemgroupitem + \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}} % todo: frozen + +% \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: + +\permanent\tolerant\protected\def\itemtag[#reference]% we can reuse more + {% what if empty + \def\currentitemreference{#reference}% + \iftrialtypesetting + \strc_counters_save\v_strc_itemgroups_counter + \strc_itemgroups_increment_item_counter + \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!leftmargindistance=\zeropoint, + \c!rightmargindistance=\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!packcriterium=\zerocount, + \c!criterium=\v!all, % permits 0 and negative numbers + %\c!option=, + \c!textdistance=\v!space, % none big medium small + \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] + +%D This is really ugly I should get rid of the global mess, whuch is a side +%D effect of the simple \type {\item} interface that we're stuck with for +%D compatibility reasons. See footnotes for usage. It's probablynot robust +%D for mixed itemgroups so in the end I need to get rid of the globals. One +%D problem is that counters are set. + +\defineitemgroup + [\v!itemize:\v!note] + +\def\strc_itemgroups_push + {\edef\strc_itemgroups_pop + {\xdef\noexpand\currentitemlevel{\currentitemlevel}% + \global\c_strc_itemgroups_nesting \the\c_strc_itemgroups_nesting \relax + \global\c_strc_itemgroups_column_depth\the\c_strc_itemgroups_column_depth\relax}% + \global\c_strc_itemgroups_column_depth\zerocount + \global\c_strc_itemgroups_nesting \zerocount + \glet\currentitemlevel\!!zerocount + \enforced\permanent\protected\def\startitemize{\startitemgroup[\v!itemize:\v!note]}% + \enforced\permanent\protected\def\stopitemize {\stopitemgroup}} + +\let\strc_itemgroups_pop\relax + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-lab.mkxl b/tex/context/base/mkxl/strc-lab.mkxl new file mode 100644 index 000000000..389f868a8 --- /dev/null +++ b/tex/context/base/mkxl/strc-lab.mkxl @@ -0,0 +1,198 @@ +%D \module +%D [ file=strc-lab, % was part of strc-des, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Labels, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Labels} + +\unprotect + +% todo: reset and increment will go + +%D Labels are implemented somewhat inefficient but have the advantage that they +%D can be controlled like other constructions. Who knows when that comes in +%D handy? + +\installcorenamespace{labels} + +\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one) + +\installcounterassociation{label} + +\let\setuplabels\setuplabel + +\setuplabel + [\c!alternative=\v!intext, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + \c!distance=\zeropoint, + \c!width=\v!fit, + \c!titledistance=.5\emwidth, + \c!margin=\v!no, + \c!titleleft=(, + \c!titleright=), + \c!display=\v!no, + \c!titlecommand=, + \c!expansion=\v!no, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + \c!text=\currentlabel, + \c!number=\v!yes, % else description + \c!start=0, + \c!state=\v!start, + \c!levels=3] + +\protected\def\strc_define_commands_label#1#2#3% current level parent + {\doifelsenothing{#3} + {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}% + \edefcsname\??label#1:\s!parent\endcsname{\??label}}% + {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}% + \edefcsname\??label#1:\s!parent\endcsname{\??label#3}}% + \ifconditional\c_strc_constructions_define_commands + \frozen\instance\protected\edefcsname\e!next #1\endcsname{\strc_labels_next {#1}{\number#2}}% obsolete + \frozen\instance\protected\edefcsname\v!reset#1\endcsname{\strc_labels_reset{#1}{\number#2}}% obsolete % should be \e!reset anyway + %frozen\instance\setuevalue{\c!set #1}{\strc_labels_set {#1}{\number#2}}% obsolete + \ifcsname\v!current#1\endcsname + % we play safe + \else + \protected\edefcsname\v!current#1\endcsname{\strc_labels_current{#1}}% % obsolete % should be \e!current anyway + \fi + \frozen\instance\protected\edefcsname#1\endcsname{\strc_labels_command[#1]}% + \fi} + +% todo: \strc_labels_command for user + +\appendtoks + \ifempty\currentlabelparent + % 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 + \ifempty\p_counter % + \let\p_counter\currentlabel + \fi + \doifelsecounter\p_counter\donothing{\strc_labels_define_counter\p_counter}% + \letlabelparameter\s!counter\p_counter +\to \everydefinelabel + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\newconditional\c_strc_constructions_number_keep + +\setvalue{\??constructioninitializer\v!label}% + {\let \currentlabel \currentconstruction + \enforced\let\constructionparameter \labelparameter + \enforced\let\constructionnamespace \??label + \enforced\let\detokenizedconstructionparameter\detokenizedlabelparameter + \enforced\let\letconstructionparameter \letlabelparameter + \enforced\let\useconstructionstyleandcolor \uselabelstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentlabel + % shared with enumerations + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + \ifconditional\c_strc_constructions_number_keep \else + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\setvalue{\??constructionfinalizer\v!label}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Interfaces: + +\protected\def\strc_labels_command{\setfalse\c_strc_constructions_number_keep\strc_descriptions_command} +\protected\def\strc_labels_current{\settrue \c_strc_constructions_number_keep\strc_descriptions_command} + +\protected\def\strc_labels_next {\strc_constructions_next_indeed \namedlabelparameter} % #1#2 +\protected\def\strc_labels_reset {\strc_constructions_reset_indeed\namedlabelparameter} % #1#2 +%protected\def\strc_labels_set {\strc_constructions_set_indeed \namedlabelparameter} % #1#2 + +% similar to enumerations + +\def\strc_labels_define_counter#1% + {\definecounter[#1]% + \registerlabelcounter{#1}} + +\appendtoks + \synchronizelabelcounters +\to \everysetuplabel + +\appendtoks + \synchronizelabelcounters +\to \everydefinelabel + +% no start stop here + +\letcsname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname + +\protected\setevalue{\??constructioncommandhandler\v!label}% + {\csname\??constructionstarthandler\v!construction\endcsname + \csname\??constructionstophandler \v!construction\endcsname + \endgroup} + +\protected\setvalue{\??constructiontexthandler\v!label}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \strc_labels_text + \endgroup} + +\let\strc_labels_text\strc_enumerations_text + +% inline variant + +\defineconstructionalternative + [\v!intext] + [\c!renderingsetup=\??constructionrenderings:\v!intext] + +\startsetups[\??constructionrenderings:\v!intext] + \dontleavehmode\box\constructionheadbox +\stopsetups + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-lev.mklx b/tex/context/base/mkxl/strc-lev.mklx new file mode 100644 index 000000000..08688ee04 --- /dev/null +++ b/tex/context/base/mkxl/strc-lev.mklx @@ -0,0 +1,98 @@ +%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}{} + +\unprotect + +\permanent\tolerant\protected\def\definesectionlevels[#category]#spacer[#list]% + {\clf_definesectionlevels{#category}{#list}} % we could scan/use public at the lua end + +\permanent\tolerant\protected\def\startsectionlevel[#category]% + {\doifelseassignment{#category}% + {\clf_startsectionlevel\plusone{\v!default}{\currentnamedsection}[#category]}% + {\clf_startsectionlevel\plusone {#category}{\currentnamedsection}}} + +\permanent\protected\def\stopsectionlevel + {\clf_stopsectionlevel} % we could use public at the lua end + +\permanent\tolerant\protected\def\startsubjectlevel[#category]% + {\doifelseassignment{#category}% + {\clf_startsectionlevel\plustwo{\v!default}{\currentnamedsection}[#category]}% + {\clf_startsectionlevel\plustwo {#category}{\currentnamedsection}}} + +\permanent\protected\def\stopsubjectlevel + {\clf_stopsectionlevel} % we could use public at the lua end + +\permanent\tolerant\protected\def\nostarthead[#category]#spacer[#settings]#spacer[#userdata]% + {\blank + \noindentation{\tttf[start missing section level #category]} + \blank} + +\permanent\tolerant\protected\def\nostophead[#category]% + {\blank + \noindentation{\tttf[stop missing section level #category]} + \blank} + +\definesectionlevels + [\v!default] + [{\v!chapter,\v!title}, + {\v!section,\v!subject}, + {\v!subsection,\v!subsubject}, + {\v!subsubsection,\v!subsubsubject}, + {\v!subsubsubsection,\v!subsubsubject}, + {\v!subsubsubsubsection,\v!subsubsubject}] + +\aliased\let\definestructurelevels\definesectionlevels +\aliased\let\startstructurelevel \startsectionlevel +\aliased\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/tex/context/base/mkxl/strc-lnt.mklx b/tex/context/base/mkxl/strc-lnt.mklx new file mode 100644 index 000000000..2a06d3c79 --- /dev/null +++ b/tex/context/base/mkxl/strc-lnt.mklx @@ -0,0 +1,359 @@ +%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} + +\aliased\let\setuplinenote\setupnote + +\newcount\c_strc_linenotes +\newtoks\everydefinelinenote + +\permanent\tolerant\protected\def\definelinenote[#1]#*[#2]#*[#3]% + {\ifarguments + % error + \orelse\ifcsname\??linenote#1\endcsname + % there might be files that define the default 'linenote' + \ifparameters\or\or + \setupnote[#1][#2]% + \or + \setupnote[#1][#3]% + \fi + \else + \ifparameters\or + \definenote[#1]% + \or + \definenote[#1][#2]% + \or + \definenote[#1][#2][#3]% + \fi + \pushmacro\currentnote + \edef\currentnote{#1} + \letcsname\??linenote\currentnote\expandafter\endcsname\csname\currentnote\endcsname % use copy command + \frozen\instance\setuevalue {\currentnote}{\strc_linenotes_direct{\currentnote}}% + \frozen\instance\setuevalue{\e!start\currentnote}{\strc_linenotes_start {\currentnote}}% + \frozen\instance\setuevalue{\e!stop \currentnote}{\strc_linenotes_stop }% + \the\everydefinelinenote + \popmacro\currentnote + \fi} + +\protected\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]}} + +\protected\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]} + +\protected\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]} + +\protected\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} + +\protected\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 + +\protected\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}% + \gletcsname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from + \gletcsname\??linenotespreviousto \currentnotation\endcsname\m_page_lines_current_to + \endgroup} + +% compression + +\installcorenamespace{linenotescompressmethod} + +% compress=yes|no +% compressmethod=separator|stopper + +\setvalue{\??linenotescompressmethod\v!separator}% + {\edef\p_compressseparator{\noteparameter\c!compressseparator}% + \scratchskip\noteparameter\c!compressdistance\relax + \ifempty\p_compressseparator + \hskip\scratchskip + \else + \hskip.5\scratchskip + \begingroup\p_compressseparator\endgroup + \hskip.5\scratchskip + \fi} + +\setvalue{\??linenotescompressmethod\v!stopper}% + {\edef\p_compressstopper{\noteparameter\c!compressstopper}% + \scratchskip\noteparameter\c!compressdistance\relax + \ifempty\p_compressstopper + \hskip\scratchskip + \else + \begingroup\p_compressstopper\endgroup + \hskip.5\scratchskip + \fi} + +\setvalue{\??linenotescompressmethod\v!space}% + {\hskip\noteparameter\c!compressdistance\relax} + +\def\strc_linenotes_check_compression + {\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 + {\begincsname\??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: + +\permanent\protected\def\doresetlinenotecompression#1% \strc_linenotes_reset_previous + {\gletcsname\??linenotespreviousfrom#1\endcsname\empty + \gletcsname\??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 + \hpack to \zeropoint + {\forgetall + \hsize\zeropoint + \hss + \vpack to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}% + {\color[blue]{\vl}}% + \vpack to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}% + \hss}% + \prewordbreak + \fi} + +\permanent\protected\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: + +\aliased\let\fromlinenote\startlinenote +\aliased\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/tex/context/base/mkxl/strc-lst.mklx b/tex/context/base/mkxl/strc-lst.mklx new file mode 100644 index 000000000..df2eb6e0f --- /dev/null +++ b/tex/context/base/mkxl/strc-lst.mklx @@ -0,0 +1,1571 @@ +%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}{} + +% 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 + +\aliased\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: + +\permanent\protected\def\usenestedliststyleandcolor#style#color% will change + {\useliststyleandcolor#style#color% + % how about style + \ifempty\currentcolorparameter \else + \resetinteractionparameter\c!color + \resetinteractionparameter\c!contrastcolor + \fi} + +\permanent\protected\def\doifelselist#tag% can also move to \installcommandhandler + {\ifcsname\namedlisthash{#tag}\s!parent\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflistelse\doifelselist + +%D Regular list entries are bound to a specific location in order to get the right +%D pagenumber etc.\ associated. When pushing something inbetween (in mkiv) it ends +%D up directtly in the list. This is the default because otherwise users will wonder +%D why spacing might get messed up (due to an unseen but present node). It is +%D possible to 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} variable when +%D placing a list. The \type {command} option only pushes commands into the right +%D order, and \type {all} orders all entries (which might be too much). In this case +%D no specific location is needed with the inbetween method. Maybe additional +%D mechanisms show up some day. See \type {inbetween-001.tex} for an example. + +% command : location=none +% userdata : location=none +% simple : location=here + +\installcorenamespace {listlocations} + +% \permanent\protected\def\doifelseinlistentry#1% +% {\ifcsname\??listlocations#1\endcsname +% \ifnum\lastnamedcs=\structurelistlocation\relax +% \doubleexpandafter\firstoftwoarguments +% \else +% \doubleexpandafter\secondoftwoarguments +% \fi +% \else +% \expandafter\secondoftwoarguments +% \fi} + +\permanent\protected\def\doifelseinlistentry#1% + {\unless\ifcsname\??listlocations#1\endcsname + \expandafter\secondoftwoarguments + \orelse\ifnum\lastnamedcs=\structurelistlocation\relax + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifelseincurrentlistentry + {\doifelseinlistentry\currentlist} + +\permanent\protected\def\structurelistinject[#tag]% + {\begingroup + \edef\currentlist{#tag}% + \doifelse{\listparameter\c!state}\v!start\strc_lists_inject_yes\strc_lists_inject_nop} + +\tolerant\protected\def\strc_lists_inject_nop[#settings]#spacer[#userdata]% + {\endgroup} + +\def\strc_lists_inject_enhance#listindex% + {\expandafter\clf_deferredenhancelist\number#listindex\relax} + +\tolerant\protected\def\strc_lists_inject_yes[#settings]#spacer[#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 \locationcount + % 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}{\the\locationcount}% + \ifx\p_location\v!here + % this branch injects nodes ! + \strc_lists_inject_enhance{\currentlistnumber}% + \clf_setinternalreference + internal \locationcount + view {\interactionparameter\c!focus}% + \relax % this will change + \xdef\currentstructurelistattribute{\the\lastdestinationattribute}% + \dontleavehmode\hpack 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 {}{}{} + +\protected\def\strc_lists_inject_direct[#tag]% [#settings][#userdata] + {\begingroup + \edef\currentlist{#tag}% + \strc_lists_inject_yes} % [#settings][#userdata] + +\permanent\protected\def\writebetweenlist[#tag]% + {\begingroup + \edef\currentlist{#tag}% + \doifelse{\namedlistparameter{#tag}\c!state}\v!start + \strc_lists_write_between_yes + \strc_lists_write_between_nop} + +\tolerant\def\strc_lists_write_between_yes[#settings]#:#command% + {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]} + +\tolerant\def\strc_lists_write_between_nop[#settings]#:#command% + {\endgroup} + +\permanent\protected\def\writedatatolist[#tag]% + {\begingroup + \edef\currentlist{#tag}% + \doifelse{\namedlistparameter{#tag}\c!state}\v!start + \strc_lists_write_data_to_yes + \strc_lists_write_data_to_nop} + +\tolerant\def\strc_lists_write_data_to_yes[#settings]#spacer[#userdata]% + {\ifparameter#userdata\or % 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} + +\tolerant\def\strc_lists_write_data_to_nop[#settings]#spacer[#userdata]% + {\endgroup} + +\permanent\protected\def\writetolist[#tag]% + {\begingroup + \edef\currentlist{#tag}% + \doifelse{\namedlistparameter{#tag}\c!state}\v!start + \strc_lists_write_to_yes + \strc_lists_write_to_nop} + +\tolerant\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}]} + +\tolerant\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 it possible to +%D flush for instance an nested (or merged) table of contents. Keep in mind that +%D placing a list is what we do most (think of tables of contents, figures, etc.\ +%D but other usage is also possible in which case low level commands have to be +%D used. + +\newtoks\everystructurelist + +\permanent\tolerant\protected\def\placelist[#taglist]#spacer[#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} + +\permanent\tolerant\protected\def\placerawlist[#tag]#spacer[#settings]% just one list + {\strc_lists_place_indeed\empty{#tag}{#settings}} + +\aliased\let\strc_lists_place\placelist % used in strc-flt + +\def\strc_lists_place_indeed#tag#list#settings% + {\begingroup + \the\t_lists_every_renderingcleanup % \let\currentlistentrylocation\empty + \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 originally introduced +%D to minimize the number for commands in a document source but nowadays that is +%D less an issue in the sense that the extra few lines are neglectable to the rest. + +\ifdefined\startnamedsection \else \let\startnamedsection\relax \fi +\ifdefined\stopnamedsection \else \let\stopnamedsection \relax \fi +\ifdefined\headtext \else \let\headtext \relax \fi + +\permanent\tolerant\protected\def\completelist[#tag]#spacer[#settings]% + {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#tag},\c!reference=#tag]}% {} around ref ? + \strc_lists_place[#tag][#settings]% + \stopnamedsection} + +\permanent\tolerant\protected\def\strc_lists_complete[#singular]#spacer[#plural]#spacer[#settings]% used in strc-flt + {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}% {} around ref ? + \strc_lists_place[#singular][#settings]% + \stopnamedsection} + +\permanent\tolerant\def\strc_lists_combined_complete[#tag]#spacer[#settings]% + {\normalexpanded{\startnamedsection[\v!title][\c!title={\headtext{#tag}},\c!reference=#tag]}% + \placecombinedlist[#tag][#settings]% + \stopnamedsection} + +%D Combined list provide a nice level of abstraction. +%D +%D \starttyping +%D \definecombinedlist[whatever][a,b,c][settings] +%D \stoptyping + +\permanent\tolerant\protected\def\definecombinedlist[#tag]#spacer[#list]#spacer[#settings]% + {\definelist[#tag][\c!criterium=\v!local,\c!reference=,\c!alternative=,\c!list={#list},#settings]% inherits from root + \frozen\instance\setvalue{\e!setup#tag\e!endsetup}{\setupcombinedlist[#tag]}% + \frozen\instance\setvalue{\e!place#tag}{\placecombinedlist[#tag]}% + \frozen\instance\setvalue{\e!complete#tag}{\strc_lists_combined_complete[#tag]}} + +\permanent\tolerant\protected\def\setupcombinedlist[#tag]#spacer[#settings]% + {\ifarguments\or\or + \setuplist[#tag][#settings]% we don't want to mess up the parent + \fi} + +\permanent\tolerant\protected\def\placecombinedlist[#tag]#spacer[#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} + +%D Given that some variables are set, we can ask for some properties of +%D an entry. + +\mutable\def\currentstructurelistnumber{0} % injection +\mutable\def\currentlistmethod {entry} % typesetting +\mutable\def\currentlistindex {0} % typesetting (maybe also a real counter) + +\permanent\protected\def\savedlistnumber #1#2{\clf_savedlistnumber {#1}\numexpr#2\relax} +\permanent\protected\def\savedlisttitle #1#2{\clf_savedlisttitle {#1}\numexpr#2\relax} +\permanent\protected\def\savedlistprefixednumber#1#2{\clf_savedlistprefixednumber{#1}\numexpr#2\relax} + +\newconditional\c_lists_show_realpage + +\installcorenamespace {listpagenumber} + +\setvalue{\??listpagenumber\v!always }{\settrue\c_lists_show_page\settrue\c_lists_has_page} +\setvalue{\??listpagenumber\v!yes }{\settrue\c_lists_show_page} +\setvalue{\??listpagenumber\s!realpage}{\settrue\c_lists_show_page\settrue\c_lists_show_realpage} + +\def\strc_lists_process_pagenumber#1% + {\begincsname\??listpagenumber#1\endcsname} + +\def\structurelistlocation + {\clf_listlocation\numexpr\currentlistindex\relax} + +\def\structurelistrealpagenumber + {\clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax} + +\protected\def\structurelistpagenumber + {\dostarttagged\t!listpage\empty + \ifconditional\c_lists_show_realpage + \clf_listrealpage{\currentlist}\numexpr\currentlistindex\relax + \else + \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 + \fi + \dostoptagged} + +\permanent\protected\def\structurelistuservariable#name% + {\dostarttagged\t!listdata{#name}% + \clf_listuserdata{\currentlist}\currentlistindex{#name}% + \dostoptagged} + +\permanent\def\rawstructurelistuservariable#name% + {\clf_listuserdata{\currentlist}\currentlistindex{#name}} + +\permanent\protected\def\structurelistfirst {\structurelistuservariable\s!first } % s! +\permanent\protected\def\structurelistsecond{\structurelistuservariable\s!second} % s! + +\permanent\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! % was \protected +\permanent\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! % was \protected + +\permanent\protected\def\doifelsestructurelisthaspage + {\clf_doifelselisthaspage{\currentlist}\numexpr\currentlistindex\relax} + +\permanent\protected\def\doifelsestructurelisthasnumber + {\clf_doifelselisthasnumber{\currentlist}\numexpr\currentlistindex\relax} + +\aliased\let\doifstructurelisthaspageelse \doifelsestructurelisthaspage +\aliased\let\doifstructurelisthasnumberelse\doifelsestructurelisthasnumber + +\permanent\protected\def\structurelistgenerictitle + {\dostarttagged\t!listcontent\empty + \clf_listtitle{\currentlist}\currentlistindex\relax + \dostoptagged} + +\permanent\protected\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 ...) + +\protected\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} + +\protected\def\strc_lists_analyze#list#criterium#reference% + {\clf_analyzelist + names {#list} + criterium {#criterium} + reference {#reference} + \relax} + +\permanent\def\firststructureelementinlist#list% expandable + {\firstinset{#list}} + +\permanent\def\structurelistsize + {\clf_listsize} + +%D Depending on what kind of list we have (e.g.\ a section related one) processors +%D 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}] + +\permanent\protected\def\installstructurelistprocessor#tag#meaning% + {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}} + +\permanent\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 + \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\orelse + \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\lastnamedcs\orelse + \ifcsname\??structurelistprocessor\currentlist \endcsname\lastnamedcs\else + \strc_lists_entry_process_default\fi + \dostoptagged + \listextraparameter\c!after} + +\protected\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end! + {\clf_pushlist#index\relax + %\let\currentlistentrylocation\empty + \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 are used but +%D nevertheless structure is present. Beware, the list symbol macro gets an argument +%D passed, i.e. when this argument is not picked up, the symbol becomes a kind of +%D prefix. It's not really a user command (and might even get protected). + +\permanent\protected\def\listsymbol[#tag]#number% + {\begingroup + \edef\currentlist{#tag}% + \def\currentlistentrynumber{#number}% no edef else tag problems + \currentlistsymbol + \endgroup} + +%D For historical reasons we're stuck to symbols, so in order to generalize, we have +%D to hook it into the symbol handle. One way to deal with this is to use a +%D different key and as it makes sense to use setups instead of def's we use a new +%D key \quote {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] + +\permanent\protected\def\currentlistsymbol + {\edef\p_symbol{\listparameter\c!symbol}% + \doifelseinsymbolset\v!list\p_symbol + {\directsymbol\v!list\p_symbol} + {\directsymbol\v!list\s!default}} + +\protected\def\strc_lists_symbol_none + {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}% + \hpack to \scratchwidth{}} + +\protected\def\strc_lists_symbol_one + {\strut\symbol[bullet]} + +\protected\def\strc_lists_symbol_two + {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} + +\protected\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\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchdepth + \endgroup} + +\protected\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} + +\protected\def\strc_lists_symbol_default + {\dontleavehmode + \strut + \begingroup + \edef\currentlistlabel{\listparameter\c!label}% can be used in label + \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} +% +% \protected\def\installlistfiller#1#2% +% {\setuvalue{\??listfiller#1}{#2}} +% +% \protected\def\listfiller#1% +% {\begincsname\??listfiller#1\endcsname} +% +% \protected\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=\directlistparameter\c!command, + \c!symbol=.] + +\permanent\protected\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 .5\emwidth{\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 + +\permanent\tolerant\protected\def\definelistplacement[#tag]#spacer[#method]% + {\edef\p_method{#method}% + \ifempty\p_method + \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: : {\bla} + +\def\strc_lists_define_placement_yes#tag% + {\protected\defcsname\??listelementcommand#tag\endcsname##1##2##3} + +% direct definition: {\bla} + +\def\strc_lists_define_placement_nop#tag% + {\protected\defcsname\??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 + +\mutable\let\currentlistentrylocation \empty % watch the 'entry' in the name +\mutable\let\currentlistentrynumber \empty % watch the 'entry' in the name +\mutable\let\currentlistentrytitle \empty % watch the 'entry' in the name +\mutable\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 + \enforced\let\\\space + % so expanding this token register has to come *after* the font switch + \dontconvertfont % (**) this has to become an option (see publ) +\to \t_lists_every_renderingtext + +\appendtoks + % because we want to avoid redundant lua calls we expand the + % location beforehand + \ifempty\currentlistentrylocation + \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 + \setfalse\c_lists_show_page % necessary? + \processcommacommand[\listparameter\c!pagenumber]\strc_lists_process_pagenumber + \ifconditional\c_lists_has_page \else + \doifelsestructurelisthaspage\settrue\setfalse\c_lists_has_page + \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_realpage + \setfalse\c_lists_show_number +\to \t_lists_every_renderingcleanup + +\let\m_strc_list_alternative\empty % combined + +\protected\def\strc_lists_apply_renderingsetup + {\the\t_lists_every_renderingsetup + % now we group + \begingroup + \ifempty\m_strc_list_alternative + \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 + +\permanent\protected\def\currentlistentrytitlesynchronize + {\the\t_lists_every_renderingsynchronize} + +\permanent\protected\def\currentlistentrytitlerendered + {\currentlistentrytitlesynchronize\currentlistentrytitle} + +\startsetups[\??listrenderings:command] + \edef\p_command{\listalternativeparameter\c!command}% + \ifempty\p_command + [\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} + \ifempty\p_command + \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 + \orelse\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 + \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\hpack { + \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 + \ifzeropt\wd\b_strc_lists_page \else \ifdim\scratchdimen>\zeropoint\relax + \rightskip\scratchdimen\s!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 + \ifzeropt\wd\b_strc_lists_page\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} + \ifempty\p_symbol + \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\s!plus\emwidth\s!minus.25\emwidth\relax + \else + \hskip\scratchdistance\s!plus.5\scratchdistance\s!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 { + \ifempty\p_command + [ + \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 such +%D (for now). No interaction either as that is dealt with elsewhere. +%D +%D \currentlistsymbol +%D \currentlistentrynumber +%D \currentlistentrytitle +%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 + \ifzeropt\scratchoffset + \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 in an +%D 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 + +\permanent\def\listboxproperties {\strc_lists_get_reference_attribute} +\permanent\def\listrenderingsetup {\the\t_lists_every_renderingtext} +\permanent\def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize} + +\protected\def\strc_lists_interaction_check + {\iflocation + \strc_lists_interaction_check_yes + \else + \strc_lists_interaction_check_nop + \fi} + +\def\strc_lists_interaction_check_yes_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_yes_nop + {\a_strc_lists_reference \attributeunsetvalue + \a_strc_lists_destination\attributeunsetvalue + \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} + +\def\strc_lists_interaction_check_yes + {\ifempty\currentlistentrylocation + \strc_lists_interaction_check_yes_nop + \orelse\ifnum\currentlistentrylocation=\zerocount + \strc_lists_interaction_check_yes_nop + \else + \strc_lists_interaction_check_yes_yes + \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 + \c_attr_reference\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 + {\c_attr_destination\a_strc_lists_destination} + +\protected\def\strc_lists_set_style_color_normal#style#color#element% + {\useliststyleandcolor#style#color} + +\protected\def\strc_lists_set_style_color_special#style#color#element% + {\useliststyleandcolor#style#color% + \ifempty\currentcolorparameter + \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}% + \ifempty\p_maxwidth + \listparameter\c!textcommand{#text}% + \else + \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}% + \fi} + +% public helpers + +\permanent\protected\def\startcurrentlistentrywrapper + {\hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute\bgroup} + +\aliased\let\stopcurrentlistentrywrapper\egroup + +\aliased\let\currentlistentryreferenceattribute \strc_lists_get_reference_attribute +\aliased\let\currentlistentrydestinationattribute\strc_lists_get_destination_attribute +\aliased\let\currentlistentrylimitedtext \strc_lists_limitated_text + +% todo: + +\def\utilitylistlength{\listlength} % old name ... uses in styles + +\mutable\let\listlength\!!zerocount % better use listmode + +\permanent\tolerant\protected\def\determinelistcharacteristics[#list]#spacer[#settings]% + {\begingroup + \edef\currentlist{\firststructureelementinlist{#list}}% + \ifempty\currentlist + \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/tex/context/base/mkxl/strc-mar.mkxl b/tex/context/base/mkxl/strc-mar.mkxl new file mode 100644 index 000000000..eb095a2a5 --- /dev/null +++ b/tex/context/base/mkxl/strc-mar.mkxl @@ -0,0 +1,136 @@ +%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}{} + +\unprotect + +%D Synchronizing marks is a rather tricky and messy business. When setting a mark, a +%D node is added to the list in order for to \TEX\ be able to figure out the 3 +%D current marks when a page is made (last mark on previous page, first on current +%D page, last on 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 one on the +%D previous page for instance. In \LUATEX\ we can clear a marks state register with +%D \type {\clearmarks} but since this is an immediate operation it might have +%D unwanted side effects when \TEX\ has collected several pages of text and +%D finishing off these pages uses marks. +%D +%D In \MKIV\ we provide an alternative model that permits some more control over the +%D way marks are used. It is not entirely compatible with \MKII\ or previous \MKIV\ +%D implementations but in practice this is not a real problem. It's also easier now +%D to extend this mechanism. + +\definesystemattribute [marks] [global] + +\installcorenamespace{marking} + +\installcommandhandler \??marking {marking} \??marking + +\newconditional\inhibitgetmarking % will become private +\newconditional\inhibitsetmarking % will become private + +\newtoks \everymarking + +\appendtoks + \clf_definemarking{\currentmarking}{\currentmarkingparent}% +\to \everydefinemarking + +\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}} +\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}} +\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} +\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded + +\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini + +\permanent\protected\tolerant\def\setmarking[#1]#:#2% + {\ifconditional\inhibitsetmarking\else + \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes + {\clf_setmarking{#1}{#2}}% + {\clf_setmarking{#1}{\detokenize{#2}}}% + \fi} + +\aliased\let\marking \setmarking +\aliased\let\doifmarkingelse\doifelsemarking + +% defaults + +\setupmarking + [\c!expansion=\v!no, + \c!separator=\space\emdash\space, + \c!filtercommand=\firstofoneargument, + \c!state=\v!start] + +% fetching, regular interface + +\permanent\protected\def\getmarking + {\ifconditional\inhibitgetmarking + \expandafter\strc_markings_get_nop + \else + \expandafter\strc_markings_get_yes + \fi} + +\tolerant\def\strc_markings_get_nop[#-]#*[#-]#*[#-]% + {} + +\tolerant\def\strc_markings_get_yes[#1]#*[#2]#*[#3]% + {\ifcstok{\namedmarkingparameter{#1}\c!state}\v!start + \begingroup + \setsystemmode\v!marking + \the\everymarking + \ifparameter#3\or + \clf_getmarking{#1}{#2}{#3}% + \else + \clf_getmarking{#1}{\v!page}{#2}% + \fi + \endgroup + \fi} + +% the fetchers are fully expandable: [name][method] + +\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi} +\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi} +\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi} + +\aliased\let\fetchmark\fetchonemark + +% also fully expandable but here we have: [name][range][method] + +\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi} +\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi} +\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi} + +\aliased\let\fetchmarking\fetchonemarking + +\permanent\def\markingseparator#1{\namedmarkingparameter{#1}\c!separator} +\permanent\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/tex/context/base/mkxl/strc-mat.mkxl b/tex/context/base/mkxl/strc-mat.mkxl new file mode 100644 index 000000000..a9efa8d25 --- /dev/null +++ b/tex/context/base/mkxl/strc-mat.mkxl @@ -0,0 +1,1311 @@ +%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}{} + +% -- 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=\v!math, + \c!location=\v!right, + \c!left=(, + \c!right=), + \c!expansion=\v!yes, % maybe automatically + \c!spacebefore=\v!big, + \c!spaceafter=\formulaparameter\c!spacebefore, + \c!width=\hsize, + \c!leftmargin=\zeropoint, + \c!rightmargin=\zeropoint, + \c!indentnext=\v!no, + \c!alternative=\s!default, + \c!strut=\v!no, + \c!numberstrut=\v!yes, % \v!no \v!yes \v!always + \c!distance=2\emwidth] + +\setupformulaframed + [%c!location=, + %c!width=, + %c!align=, + \c!offset=.5\exheight] + +\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? + \frozen\instance\setuevalue{\e!start\currentformula\v!formula}{\strc_formulas_start_formula{\currentformula}}% + \frozen\instance\setuevalue{\e!stop \currentformula\v!formula}{\strc_formulas_stop_formula}% +\to \everydefineformula + +\definelist[\v!formula] + +\permanent\setuvalue{\e!start\v!formula}{\strc_formulas_start_formula{}} +\permanent\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 + +\permanent\tolerant\protected\def\defineformulaalternative[#1]#*[#2]#*[#3]% + {\frozen\instance\setvalue{\e!start#1\v!formula}{#2}% + \frozen\instance\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 + +\protected\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 + \glet#3\m_strc_counters_last_registered_index + \glet#4\m_strc_counters_last_registered_synchronize + \glet#5\m_strc_counters_last_registered_attribute} + +% modes: 0=unset, 1=forced, 2=none, 3=reference + +\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_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_number_noneed + {\doif{\formulaparameter\c!numberstrut}\v!always\strut} + +\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\strc_formulas_place_number_noneed + \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 + +\permanent\protected\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 + {\edef\p_strut{\formulaparameter\c!numberstrut}% + \ifx\p_strut\v!always + \strut + \orelse\ifx\p_strut\v!yes + \strut + \fi + \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} + +\protected\def\strc_formulas_place_current_number + {\ifempty\namedformulaentry + \strc_formulas_handle_current_references + \labeltexts\currentformula{\convertedcounter[\v!formula][]}% + \else + \expandafter % hm, the next one reset \namedformulaentry + \strc_formulas_handle_current_references + \namedformulaentry + \fi} + +\permanent\def\theformuladestinationattribute#1% + {\iflocation\ifx#1\relax\orelse\ifempty#1\else + \c_attr_destination#1% + \glet#1\relax + \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 + +\mutable\let\currentformulasreference \empty +\mutable\let\currentformulareference \empty +\mutable\let\currentsubformulareference \empty +\mutable\let\currentnestedformulareference\empty + +\appendtoks + \glet\currentformulasreference \empty + \glet\currentformulareference \empty + \glet\currentsubformulareference \empty + \glet\currentnestedformulareference\empty +\to \everyresetformulas + +\mutable\let\currentformulassuffix \empty +\mutable\let\currentformulasuffix \empty +\mutable\let\currentsubformulasuffix \empty +\mutable\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 + {\ifempty\namedformulaentry + \strc_counters_increment\v!formula + \doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}% + \fi + \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. + +\pushoverloadmode + +\let\reqno\eqno % no longer valid as we just nil it + +\let\math_native_leqno\leqno +\let\math_native_reqno\reqno + +\protected\def\normaleqno#1{\writestatus\m!system{no native (l)eqno equation number support}} + +\let\normalleqno\normaleqno +\let\normalreqno\normaleqno + +\let\leqno\normaleqno +\let\reqno\normaleqno +\let\eqno \normaleqno + +\popoverloadmode + +%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: + +\abovedisplayskip \zeropoint +\abovedisplayshortskip \zeropoint % evt. 0pt minus 3pt +\belowdisplayskip \zeropoint +\belowdisplayshortskip \zeropoint % evt. 0pt minus 3pt + +\predisplaypenalty \zerocount +\postdisplaypenalty \zerocount % -5000 goes wrong, see penalty at \section +\mathdisplayskipmode \plusthree % because align also adds + +% \predisplaygapfactor \zerocount % default is 2000 + +\protected\def\strc_formulas_forget_display_skips + {\mathdisplayskipmode \plusthree + \abovedisplayskip \zeropoint + \belowdisplayskip \zeropoint + \abovedisplayshortskip\zeropoint + \belowdisplayshortskip\zeropoint} + +\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 +\newdimen\d_strc_formulas_display_width + +\newconstant\c_strc_formulas_mode % this will go away +\newconstant\c_strc_formulas_space_model + +\newconstant\c_strc_math_vertical % experiment + +\c_strc_formulas_mode \plustwo % 0=native 1=simple (old) 2=align (new) +\c_strc_formulas_space_model\plusthree % replaces \plusone, we might use \plusfour in the future + +\newconditional\c_strc_formulas_tight + +\newbox\b_strc_formulas_number +\newbox\b_strc_formulas_content + +\def\strc_formulas_flush_content_and_number + {\noindentation + % \dontleavehmode + \kern\d_strc_formulas_display_margin_left + \ifcase\wd\b_strc_formulas_number + \hbox to \displaywidth \bgroup + \hfill + \box\b_strc_formulas_content + \hfill + \egroup + \orelse\ifdim\dimexpr\wd\b_strc_formulas_content+\wd\b_strc_formulas_number\relax>\displaywidth + \vbox \bgroup + \hsize\displaywidth + \box\b_strc_formulas_content + \par + \ifx\p_location\v!left + \box\b_strc_formulas_number\hfill + \else + \hfill\box\b_strc_formulas_number + \fi + \egroup + \else + \hbox to \displaywidth \bgroup + \ifx\p_location\v!left + \rlap{\box\b_strc_formulas_number}% + \hfill\box\b_strc_formulas_content\hfill + \else + \hfill\box\b_strc_formulas_content\hfill + \llap{\box\b_strc_formulas_number}% + \fi + \egroup + \fi} + +\installcorenamespace{mathdisplayspacemodel} + +\setvalue{\??mathdisplayspacemodel\v!before:1}% old + {\ifx\p_spacebefore\v!none + % nothing + \else + \directvspacing\p_spacebefore + \fi} + +\setvalue{\??mathdisplayspacemodel\v!after:1}% old + {\prevdepth .5\strutdp + \edef\p_spaceafter{\formulaparameter\c!spaceafter}% + \ifx\p_spaceafter\v!none + % nothing + \else + \directvspacing\p_spaceafter + \fi} + +\setvalue{\??mathdisplayspacemodel\v!before:2}% old + {\ifx\p_spacebefore\v!none + % nothing + \else + \directvspacing\p_spacebefore + \fi + \prevdepth-\maxdimen} % texbook pagina 79-80 + +\setvalue{\??mathdisplayspacemodel\v!after:2}% old + {\prevdepth\lineheight + \edef\p_spaceafter{\formulaparameter\c!spaceafter}% + \ifx\p_spaceafter\v!none + % nothing + \else + \directvspacing\p_spaceafter + \fi} + +\setvalue{\??mathdisplayspacemodel\v!before:3}% + {% not ok, try \stopformula\par\startformula vs \stopformula\startformula + \let\m_spacebefore\empty + \ifvmode + \ifdim\lastskip>\zeropoint\else + \ifdim\prevdepth<\zeropoint\else + \ifdim\prevdepth<\strutdp + % maybe add a tracing option here + \ifgridsnapping + \let\m_spacebefore\v!depth + \else + \edef\m_spacebefore{\the\dimexpr\strutdp-\prevdepth\relax}% + \fi + \fi + \fi + \fi + \nointerlineskip + \fi + \ifempty\m_spacebefore + \ifx\p_spacebefore\v!none + % nothing + \orelse\ifempty\p_spacebefore + \directvspacing\currentvspacing + \else + \directvspacing{\p_spacebefore,\the\scratchdimen}% + \fi + \else + \ifx\p_spacebefore\v!none + \directvspacing{\m_spacebefore}% + \orelse\ifempty\p_spacebefore + \directvspacing{\m_spacebefore,\currentvspacing}% + \else + \directvspacing{\m_spacebefore,\p_spacebefore}% + \fi + \fi} + +\setvalue{\??mathdisplayspacemodel\v!after:3}% + {\prevdepth\strutdp % \directvspacing\v!depth + \ifx\p_spaceafter\v!none + % nothing + \orelse\ifempty\p_spaceafter + \directvspacing\currentvspacing + \else + \directvspacing\p_spaceafter + \fi} + +\newconditional\c_math_model_four_indeed + +\setvalue{\??mathdisplayspacemodel\v!before:4}% + {% not ok, try \stopformula\par\startformula vs \stopformula\startformula + \ifvmode + \ifinner + \csname\??mathdisplayspacemodel\v!before:3\endcsname + \else + \settrue\c_math_model_four_indeed + \forcestrutdepth + \nointerlineskip + \ifx\p_spacebefore\v!none + % nothing + \orelse\ifempty\p_spacebefore + \directvspacing\currentvspacing + \else + \directvspacing{\p_spacebefore,\the\scratchdimen}% + \fi + \fi + \else + \csname\??mathdisplayspacemodel\v!before:3\endcsname + \fi} + +\setvalue{\??mathdisplayspacemodel\v!after:4}% + {\ifconditional\c_math_model_four_indeed + \setfalse\c_math_model_four_indeed + \forcestrutdepth + \else + \prevdepth\strutdp % \directvspacing\v!depth + \fi + \ifx\p_spaceafter\v!none + % nothing + \orelse\ifempty\p_spaceafter + \directvspacing\currentvspacing + \else + \directvspacing\p_spaceafter + \fi} + +\permanent\protected\def\setdisplaymathspacemodel[#1]% + {\ifcsname\??mathdisplayspacemodel\v!before:\number#1\endcsname + \c_strc_formulas_space_model#1\relax + \fi} + +% \newtoks\everybeforedisplay +% \appendtoks\page_sides_check_floats_indeed\to\everybeforedisplay + +\permanent\protected\def\beforedisplayspace + {\ifhmode + \par + \fi + \ifvmode + \edef\p_spacebefore{\formulaparameter\c!spacebefore}% + \begincsname\??mathdisplayspacemodel\v!before:\number\c_strc_formulas_space_model\endcsname + \fi + \ifhmode + \par + \fi + \page_sides_check_floats_indeed} % probably needs more + +\permanent\protected\def\afterdisplayspace + {\ifhmode + \par + \fi + \ifvmode + \edef\p_spaceafter{\formulaparameter\c!spaceafter}% + \begincsname\??mathdisplayspacemodel\v!after:\number\c_strc_formulas_space_model\endcsname + \fi + \ifhmode + \par + \fi} + +\permanent\protected\def\setdisplaydimensions + {\displayindent\dimexpr + \d_strc_formulas_display_skip_left + +\d_strc_formulas_display_margin_left + \relax + \displaywidth\d_strc_formulas_display_width + %\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 + +\protected\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 + +\setvalue{\??formulaoption\v!packed}% + {\c_strc_formulas_space_model\zerocount} + +\setvalue{\??formulaoption\v!tight}% + {\settrue\c_strc_formulas_tight} + +\setvalue{\??formulaoption\v!middle}% + {\d_strc_formulas_display_skip_left \zeropoint + \d_strc_formulas_display_skip_right\zeropoint} + +\setvalue{\??formulaoption\v!depth}% + {\c_strc_formulas_space_model\plusfour} + +\setvalue{\??formulaoption\v!line}% + {\ifgridsnapping + \setformulaparameter\c!grid{\v!math:\v!line}% + \fi} + +\setvalue{\??formulaoption\v!halfline}% + {\ifgridsnapping + \setformulaparameter\c!grid{\v!math:\v!halfline}% + \fi} + +\setvalue{\??formulaoption-\v!line}% + {\ifgridsnapping + \setformulaparameter\c!grid{\v!math:-\v!line}% + \fi} + +\setvalue{\??formulaoption-\v!halfline}% + {\ifgridsnapping + \setformulaparameter\c!grid{\v!math:-\v!halfline}% + \fi} + +% when we have 1.0.6 we wil use \mathpenaltiesmode +% +% \prebinoppenalty -100 +% \prerelpenalty -100 + +\def\strc_math_set_split + {\edef\p_split{\formulaparameter\c!split}% + \ifx\p_split\v!yes + \global\c_strc_math_vertical\plusone + \orelse\ifx\p_split\v!page + \global\c_strc_math_vertical\plustwo + \else + \global\c_strc_math_vertical\zerocount + \fi + \ifcase\c_strc_math_vertical + % \mathpenaltiesmode \zerocount + \clf_setmathpenalties\zerocount + \clf_resetmathhang + \else + % \mathpenaltiesmode \plusone + \clf_setmathpenalties\plusone + \edef\p_hang{\formulaparameter\c!hang}% + \ifx\p_hang\v!none + \global\setfalse\c_strc_math_indent + \clf_resetmathhang + \else + \global\settrue\c_strc_math_indent + \clf_setmathhang {% + method {\p_hang}% + distance \formulaparameter\c!distance + }% + \fi + \fi} + +\setupformula + [\c!split=\v!no, + \c!distance=\zeropoint, + %\c!interlinespace=1.5\lineheight, + \c!interlinespace=, + \c!hang=\v!none] + +% for the moment (when testing) we use a penalty 1 + +\protected\def\strc_math_align_here{\ifmmode\penalty\plusone\fi}% +\protected\def\strc_math_break_here{\ifmmode\hfill\break \fi}% + +\ifdefined\alignhere \else \aliased\let\alignhere\relax \fi +\ifdefined\breakhere \else \aliased\let\breakhere\relax \fi + +\appendtoks + \enforced\let\alignhere\strc_math_align_here + \enforced\let\breakhere\strc_math_break_here +\to \everymathematics + +\protected\def\strc_formulas_start_formula_indeed[#1][#2]% setting leftskip adaption is slow ! + {\ifhmode + \par + \fi + \bgroup % HERE + \iftrialtypesetting\else + \global\advance\c_strc_formulas_n\plusone + \fi + \def\currentformula{#1}% + \strc_math_set_split + \dostarttaggedchained\t!formula\currentformula\??formula + \setfalse\c_strc_formulas_tight + \d_strc_formulas_display_skip_left \leftskip + \d_strc_formulas_display_skip_right \rightskip + \d_strc_formulas_display_width \formulaparameter\c!width\relax + \d_strc_formulas_display_margin_left \formulaparameter\c!leftmargin\relax + \d_strc_formulas_display_margin_right\formulaparameter\c!rightmargin\relax + \iftok{#2}\emptytoks + \edef\p_option{\formulaparameter\c!option}% + \orelse\ifhastok={#2}% this is new, so that we can also set the grid + \setupcurrentformula[#2]% + \edef\p_option{\formulaparameter\c!option}% + \else + \edef\p_option{\formulaparameter\c!option}% + \edef\p_option{\ifempty\p_option\else\p_option,\fi#2}% + \fi + \ifempty\p_option \else + \rawprocesscommacommand[\p_option]\strc_formulas_option + \fi + \edef\p_margin{\formulaparameter\c!margin}% + \ifempty\p_margin \else + \dosetleftskipadaption\p_margin + \d_strc_formulas_display_margin_left\leftskipadaption + \fi + \let\strc_formulas_start_formula\strc_formulas_start_formula_nested + \strc_formulas_forget_display_skips + \the\everybeforedisplayformula + \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname} + +\protected\def\strc_formulas_start_formula_nested#1% + {\bgroup + \let\strc_formulas_stop_formula\strc_formulas_stop_formula_nested + \dostarttagged\t!subformula\empty} + +\protected\def\strc_formulas_stop_formula_nested + {\dostoptagged + \egroup} + +% tagging of formulanumbers is not ok (we get two display maths blobs) + +\newcount\c_strc_formulas_n + +\ifdefined\dotagregisterformula \else \let\dotagregisterformula\gobbleoneargument \fi + +\protected\def\strc_formulas_stop_formula + {\strc_formulas_place_number % in case it hasn't happened yet + \strc_formulas_flush_number % in case we are in native mode + \dostarttagged\t!formulacontent\empty + \dotagregisterformula\c_strc_formulas_n + \csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname + \dostoptagged + \dostoptagged + \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: + +\def\strc_formulas_set_grid_snapping + {\edef\p_grid{\formulaparameter\c!grid}% + \ifempty\p_grid \else + \spac_grids_snap_value_auto\p_grid + \fi} + +\appendtoks + \ifgridsnapping + \strc_formulas_set_grid_snapping + \fi +\to \everybeforedisplayformula + +% \protected\def\switchtoformulabodyfont +% {\switchtobodyfont} + +\setuvalue{\v!formula}{\dosingleempty\strc_formulas_formula} + +\def\strc_formulas_formula[#1]#2% todo: tagged + {\begingroup + \edef\p_direct{#1}% + \ifempty\p_direct \else + \rawprocesscommalist[\p_direct]\strc_formulas_option + \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 + +\permanent\protected\def\startdisplaymath + {\ifhmode + \par + \fi + \bgroup + \informulatrue + \beforedisplayspace + \setdisplaydimensions + \ifcase\c_strc_formulas_mode + \noindent % prevents that tex injects empty line (when using native display mechanism) + \Ucheckedstartdisplaymath + \the\everydisplay % new (probably too much) + \or + \setbox\b_strc_formulas_content\hbox\bgroup + \normalUstartmath + \displaystyle + \the\everydisplay % new (probably too much) + \else + \expandafter\startinnermath + \fi + \begingroup} % less interference with upcoming a \over b + +\permanent\protected\def\stopdisplaymath + {\endgroup % less interference with upcoming a \over b + \ifcase\c_strc_formulas_mode + \Ucheckedstopdisplaymath + \or + \normalUstopmath + \egroup + \strc_formulas_flush_content_and_number + \else + \expandafter\stopinnermath + \fi + \afterdisplayspace + \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} + +\permanent\protected\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} + +\permanent\protected\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) + +\permanent\protected\def\startnamedsubformulas + {\dosingleempty\strc_formulas_start_named_sub_formulas} + +\def\strc_formulas_start_named_sub_formulas[#1]#2% + {\setformulalistentry{#2}% + \startsubformulas[#1]} + +\permanent\protected\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 + +\permanent\protected\def\startformulas{\strc_formulas_start_formulas} + +\permanent\letcsname\e!stop\v!formulas\endcsname\relax + +\protected\def\strc_formulas_nested_formula_start + {\hbox to \displaywidth \bgroup + \hsize\displaywidth + \hss + %\Ustartmath + \dostarttagged\t!formulacontent\empty + \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname} + +\protected\def\strc_formulas_nested_formula_stop + {\csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname + \dostoptagged + %\Ustopmath + \hss + \egroup + \hss} + +\normalexpanded{\tolerant\def\noexpand\strc_formulas_start_formulas[#1]#:#2\csname\e!stop\v!formulas\endcsname}% + {\startformula + \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 + \enforced\protected\def\startformula + {\advance\scratchcounter\plusone + \expandafter\gobbleuntil\csname\e!stop\v!formula\endcsname}% + \scratchcounter\zerocount + #2% preroll + \hbox to \displaywidth \bgroup + \divide\displaywidth\scratchcounter + \hss + \enforced\let\startformula\strc_formulas_nested_formula_start + \enforced\let\stopformula \strc_formulas_nested_formula_stop + #2% + \egroup + \global\setfalse\c_strc_formulas_inside_formulas + \dostoptagged + \stopformula + \the\everyresetformulas + \hangafter\minusone % added for side floats + \hangindent\zeropoint} % added for side floats + +% place + +\def\m_strc_formulas_flag_inhibit{-} +\def\m_strc_formulas_flag_force {+} + +\def\strc_formulas_check_reference#1#2% + {#1\unless\ifempty\namedformulaentry % \relax % new 29/8/2010 + \plusthree + \orelse\ifempty#2% + \zerocount + \orelse\ifx#2\m_strc_formulas_flag_force + \plusone + \orelse\ifx#2\m_strc_formulas_flag_inhibit + \plustwo + \else + \plusthree + \fi} + +\permanent\protected\def\formulanumber + {\strc_formulas_number} % for the moment + +\tolerant\protected\def\strc_formulas_number[#1]% + {\def\currentformulareference{#1}% + \strc_formulas_place_number_in_box} + +\permanent\protected\def\placeformula {\global\settrue\c_strc_formulas_inside_place} +\permanent\protected\def\placesubformula{\global\settrue\c_strc_formulas_inside_place_sub} + +\tolerant\protected\def\strc_formulas_place[#1]% + {\def\currentplaceformulareference{#1}% + \let\currentplaceformulasuffix\empty + \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{} + +\protected\def\strc_formulas_place_yes#1% + {\def\currentplaceformulasuffix{#1}% + \strc_formulas_place_nop} + +\protected\def\strc_formulas_place_nop + {\doifelsenextchar$\strc_formulas_place_pickup\strc_formulas_place_indeed} % [ref]$$ [ref]\start + +\protected\def\strc_formulas_place_indeed + {\strc_formulas_place_numbering} + +\protected\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 + +\let\currentplaceformulareference\empty +\let\currentplaceformulasuffix \empty + +\permanent\tolerant\protected\def\startplaceformula[#1]% + {\begingroup + \global\settrue\c_strc_formulas_inside_place + \ifparameter#1\or + \expandafter\strc_formulas_start_place_yes + \else + \expandafter\strc_formulas_start_place_nop + \fi[#1]} + +\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}% + \ifempty\currentplaceformulatitle\else + \normalexpanded{\setformulalistentry{\currentplaceformulatitle}}% + \fi + \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{} + +\permanent\protected\def\stopplaceformula + {\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}% + \strc_formulas_check_reference\c_strc_formulas_nested_number_mode\currentnestedformulareference + \ifcase\c_strc_formulas_nested_number_mode + % nothing + \or + \glet\strc_formulas_place_number\relax + \expandafter\strc_formulas_number % hm, looks ahead for [] + \or + % nothing + \or + \glet\strc_formulas_place_number\relax + \expandafter\strc_formulas_number % hm, looks ahead for [] + \fi} + +\def\strc_formulas_place_number_indeed + {\strc_formulas_place_number_in_box} + +\def\strc_formulas_place_number_in_box + {\dostarttagged\t!formulacaption\empty + \global\setbox\b_strc_formulas_number\naturalhbox{\strc_formulas_number_indeed}% + \dostoptagged} + +\def\strc_formulas_flush_number + {\ifcase\c_strc_formulas_mode + \ifzeropt\wd\b_strc_formulas_number + % nothing to be done + \orelse\ifx\p_location\v!left + \math_native_leqno{\box\b_strc_formulas_number}% + \else + \math_native_reqno{\box\b_strc_formulas_number}% + \fi + \fi} + +% todo + +\permanent\tolerant\protected\def\placenamedformula[#1]% + {\ifarguments + \expandafter\strc_formulase_place_named_nop + \else + \expandafter\strc_formulase_place_named_yes + \fi[#1]} + +\def\strc_formulase_place_named_yes[#1]#2% + {\setformulalistentry{#2}% + \placeformula[#1]} + +\def\strc_formulase_place_named_nop[#1]#2% + {\setformulalistentry{#2}% + \placeformula} + +\mutable\let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks + +\permanent\protected\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/tex/context/base/mkxl/strc-not.mklx b/tex/context/base/mkxl/strc-not.mklx new file mode 100644 index 000000000..ec8cf849f --- /dev/null +++ b/tex/context/base/mkxl/strc-not.mklx @@ -0,0 +1,1972 @@ +%D \module +%D [ file=strc-not, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Note Handling, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Note Handling} + +\registerctxluafile{strc-not}{} + +\unprotect + +% todo: finish local rendering +% todo: more p_strc_notations_* (outside trial loop) +% todo: see if we can now use \insertpenalties (>0 == some left) + +\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi +\ifdefined\dotagsetnotation \else \let\dotagsetnotation \relax \fi + +\permanent\protected\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often +\permanent\protected\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often + +%D \LMTX\ testcase: +%D +%D \starttyping +%D \hbox {\hbox{\footnote{HH1}\footnote{HH2}}} \par +%D \hbox {\hbox{x\footnote{XHH1}x\footnote{XHH2}}} \par +%D \vbox {\setbox0\hbox{\footnote{VH1}\footnote{VH2}}\box0} \par +%D \vbox {\hbox{\footnote{VH1}xxx\footnote{VH2}}} \par +%D \vbox {\hbox{\footnote{VH1}\footnote{VH2}} +%D \hbox{\footnote{VH1}\footnote{VH2}}} \par +%D \vbox {\hbox{x\footnote{XVH1}x\footnote{XVH2}}} \par +%D \vbox {\vbox{\footnote{VV1}\footnote{VV2}}} \par % two lines +%D \vbox {\vbox{x\footnote{XVV1}x\footnote{XVV2}}} \par +%D \stoptyping + +%D Notes have two handlers: notations and notes. Although notations can be defined +%D independently it makes not much sense. In principle we can treat notes as lists +%D but they are currently done as a variant on enumerations. I will provide a list +%D variant as well. One complication is that for page related notes inserts are used +%D and therefore notes are typeset immediately and descriptions are better suited +%D for that. For instance endnotes can as well be typeset using lists. + +% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number + +%D \macros +%D {setupnote,setupnotation} +%D +%D We can influence footnote typesetting with the setup command: +%D +%D \showsetup{setupnotation} +%D \showsetup{setupnote} +%D +%D The definition command indicate that we can frame the footnote area. The +%D footnotes themselves are treated as descriptions. +%D +%D \showsetup{definenote} +%D +%D It's sort of a custom to precede footnotes by a horizontal rule and although +%D fancy rules like +%D +%D \starttyping +%D \hbox to 10em{\hskip-3em\dotfill} +%D \stoptyping +%D +%D Are quite ligitimate, we default to a simple one 20\% of the text width. + +% \c!headstyle=\noteparameter\c!style, +% \c!headcolor=\noteparameter\c!color, + +\installcorenamespace{notation} + +\installcommandhandler \??notation {notation} \??notation + +\installcounterassociation{notation} + +\aliased\let\setupnotations\setupnotation + +\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}] +\definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}] + +\setupnotations % check with old + [\c!alternative=\v!note, + %\c!headstyle=, + %\c!titlestyle=, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!numbercommand=\high, + %\c!symbolcommand=\lowllap, % experiment + %\c!indicator=\v!no, % was \v!yes in mkii for page notes + \c!width=\v!fit, + \c!titledistance=.5em, + \c!distance=.5em, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=, + \c!inbetween=, + \c!after=, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + %\c!starter=, + %\c!stopper=, + \c!number=\v!yes, + \c!text=, + \c!start=0, + \c!state=\v!start, + \c!levels=3] + +%D The code here is mostly the same as enumerations but we want to keep them +%D isolated and at some point we might differentiate. + +% \installcorenamespace{noteclass} + +\protected\def\strc_define_commands_notation#tag#level#parent% + {\doifelsenothing{#parent} + {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}% + \setevalue{\??notation#tag:\s!parent}{\??notation}}% + {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}% + \setevalue{\??note #tag:\s!parent}{\??note#parent}% see later for \s!note + \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}% + \instance\setuevalue{\e!next #tag}{\strc_notations_next {#tag}{\number#level}}% obsolete + \instance\setuevalue{\c!reset#tag}{\strc_notations_reset {#tag}{\number#level}}% obsolete + \instance\setuevalue {#tag}{\strc_notations_command[#tag]}% + \instance\setuevalue{\e!start#tag}{\strc_notations_start [#tag]}% + \instance\setuevalue{\e!stop #tag}{\strc_notations_stop }} + +\appendtoks + \ifempty\currentnotationparent + % 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 + \ifempty\p_counter + \let\p_counter\currentnotation + \fi + \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}% + \letnotationparameter\s!counter\p_counter + %\strc_notes_setup_counter\currentnotation +\to \everydefinenotation + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\protected\setvalue{\??constructioninitializer\v!notation}% + {\let \currentnotation \currentconstruction + \enforced\let\constructionparameter \notationparameter + \enforced\let\constructionnamespace \??notation + \enforced\let\detokenizedconstructionparameter\detokenizednotationparameter + \enforced\let\letconstructionparameter \letnotationparameter + \enforced\let\useconstructionstyleandcolor \usenotationstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentnotation + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + %\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\protected\setvalue{\??constructionfinalizer\v!notation}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Notations (we simply needed a word that relates to notes and is and sounds like +%D description and enumeration) are a special case in the sense that they are +%D stored, rendered elsewhere and referered to from where they are specified. For +%D that reason they have a different set op main commands. + +% \notation[ref]{title} +% \notation[reference=,title=] +% \startnotation[ref] title \stopnotation + +\protected\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2 +\protected\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2 +%protected\def\strc_notations_set {\strc_constructions_set_indeed \namednotationparameter} % #1#2 + +\newconditional\c_strc_notations_anchored_next + +\def\strc_notations_finalize + {\ifconditional\c_strc_notations_anchored_next + \expandafter\strc_notations_finalize_next + \else + \expandafter\strc_notations_finalize_previous + \fi} + +\def\strc_notations_finalize_previous + {\normalexpanded{\endgroup\noteparameter\c!next}} + +\def\strc_notations_finalize_next + {\endgroup\ignorespaces} + +\tolerant\protected\def\strc_notations_command[#1]#*[#2]% + {\begingroup + \edef\currentnote{#1}% + \strc_constructions_initialize{#1}% + \strc_notes_synchronize + \edef\p_next{\noteparameter\c!anchor}% + \ifx\p_next\v!next % for now only two states + \settrue \c_strc_notations_anchored_next + \else + \setfalse\c_strc_notations_anchored_next + \fi + \ifnotesenabled + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \ifhastok={#2}% + \expandafter\strc_notations_command_setups + \else + \expandafter\strc_notations_command_reference + \fi[#2]} + +\def\strc_notations_command_setups[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \strc_notations_wrapup} + +\tolerant\def\strc_notations_command_reference[#1]#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \strc_notations_wrapup} + +\def\strc_notations_wrapup + {\csname\??constructionnotehandler\currentconstructionhandler\endcsname + \strc_constructions_finalize + \strc_notations_finalize} + +\tolerant\protected\def\strc_notations_start[#1]#*[#2]% + {\begingroup + \edef\currentnote{#1}% + \strc_constructions_initialize{#1}% + \strc_notes_synchronize + \ifnotesenabled + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \ifhastok={#2}% + \expandafter\strc_notations_start_setups + \else + \expandafter\strc_notations_start_reference + \fi[#2]} + +\protected\def\strc_notations_start_setups[#1]% + {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_setups_indeed[#1]{##1}}}% + \strc_pickup_yes} + +\protected\def\strc_notations_start_setups_indeed[#1]#*#2% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#2},\c!bookmark=,\c!list=,#1]% + \strc_notations_wrapup} + +\protected\def\strc_notations_start_reference[#1]% + {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_reference_indeed[#1]{##1}}}% + \strc_pickup_yes} + +\protected\def\strc_notations_start_reference_indeed[#1]#*#2% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \strc_notations_wrapup} + +\protected\def\strc_notations_stop + {} + +%D A complication is that we need to set up rather specific properties of e.g. +%D footnotes. It is for this reason that we introduce an extra level of +%D indirectness. This way notations don't bark on undefined macros when used in +%D combination. + +\protected\setvalue{\??constructionnotehandler\v!notation}% + {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname} + +\protected\setvalue{\??constructionnotehandler\v!notation:}% empty case + {[\currentconstructionhandler:\currentconstruction]} + +%D Here is a simple renderer for notes + +\defineconstructionalternative + [\v!note] + [\c!renderingsetup=\??constructionrenderings:\v!note] + +\startsetups[\??constructionrenderings:\v!note] + \noindent + \leftboundary % experiment, to be done in more places + \llap{\box\constructionheadbox\hskip\constructionparameter\c!distance}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D We now implement the note definer. + +\installcorenamespace{note} + +\installframedcommandhandler \??note {note} \??note + +\let\setupnotes\setupnote + +% These only concern the inline symbol/number and wrapping of the whole list. + +\setupnotes % not all make sense here + [\c!location=\v!page, + %\c!conversion=, + \c!rule=\v!on, + \c!before=\blank, + \c!bodyfont=\v!small, + \c!anchor=, % can also be v!next + %\c!style=, + %\c!color=, + %\c!after=, + %\c!rulecolor=, + %\c!rulecommand=, + \c!rulethickness=\linewidth, + \c!frame=\v!off, + \c!distance=.125em, % in the text between symbols + % \c!textseparator={,}, % optional separator + \c!columndistance=1em, + % \c!margindistance=.5em, + \c!align=, % also use instead of \c!tolerance + \c!split=\v!tolerant, + \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi + \c!height=\textheight, + \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice + \c!separator=,% + \c!textcommand=\high, + \c!textstyle=\tx, + %\c!textcolor=, + \c!interaction=\v!yes, + %\c!factor=, + %\c!scope=, % \v!text \v!page + \c!prefixconnector=., + %\c!next=\autoinsertnextspace, + \c!prefix=\v!no, + %\c!continue=\v!no, + \c!paragraph=\v!no, + \c!inbetween=\hskip\emwidth, + \c!symbol=\mathematics{*}, + \c!n=1] + +\setupnotes + [\c!expansion=\v!no, + \c!xmlsetup=, + \s!catcodes=] + +%D Insertions are part of notes. + +% \installcorenamespace{noteinsertion} + +\permanent\def\currentnoteinsertion {\noteparameter\s!insert} +\permanent\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}} + +\appendtoks + \ifempty\currentnoteparent + \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 + +%letcsname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname +\letcsname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess +\letcsname\??constructionstophandler \v!notation\expandafter\endcsname\csname\??constructionstophandler \v!enumeration \endcsname +\letcsname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname +\letcsname\??constructiontexthandler \v!notation\expandafter\endcsname\csname\??constructiontexthandler \v!enumeration \endcsname + +\protected\setvalue{\??constructionmainhandler\v!notation}#following% + {\iftrialtypesetting \else + \begingroup + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax % todo, whole text + \signalcharacter + \endgroup + \fi#following} + +\protected\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text + {\ifnotesenabled + % do be done elsewhere + % + %let\currentnote\currentconstructionmain + \let\currentnote\currentconstruction % else wrong inheritance + % + \iftrialtypesetting + \strc_notes_inject_dummy + \else + \begingroup + \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}% + \settrue\processingnote + \ifconditional\c_strc_notes_skip + \glet\lastnotesymbol\strc_notes_inject_symbol_nop + \else + \iftypesettinglines % otherwise problems with \type {xxx} + \ignorelines % makes footnotes work in \startlines ... \stoplines + \fi + \ifconditional\c_strc_notes_symbol + \strc_notes_inject_symbol_yes + \else + \unskip\unskip + \glet\lastnotesymbol\strc_notes_inject_symbol_yes + \fi + \fi + \ifconditional\postponingnotes % todo: per note class + \global\settrue\postponednote + \orelse\ifconditional\inlocalnotes % todo: per note class + \global\settrue\postponednote + \orelse\ifconditional\c_strc_notes_delayed + % probably end notes + \else + \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed + \fi + \endgroup + \fi + \fi + \ifconditional\c_strc_notes_skip + \global\setfalse\c_strc_notes_skip + \else + \kern\d_strc_notes_signal\relax % \relax is needed to honor spaces + \fi} + +%D Interaction in notes is somewhat complex due to the way notes get flushed. In +%D principle it is more or less the same as lists but where in lists we pack whole +%D entries, in notes this doesn't happen. Okay, in retrospect we could have made +%D descriptions lists but that will be a backward compatibility mess. At some point +%D a completely new mechanism might show up, but not now. Also, as notes are inserts +%D there is some extra mess to be kept in mind and it's easier to maintain two +%D mechanisms than to combine too much. +%D +%D Interaction is also complicated because we want to provide several variants. For +%D simple reference there is no need for anything special, as page references will +%D do and we store them in the list anyway. But if we want a destination with +%D dimensions we will use an additional destination because we can have only one +%D with the same name and we always have the number as one. + +% interaction: +% +% all : text and number +% number|yes: only number +% text : only text +% +% \dogetsimple : injects + +\installcorenamespace{noteinteractioninline} +\installcorenamespace{noteinteractiondisplay} + +\newconstant\a_strc_notes_symbol_reference +\newconstant\a_strc_notes_number_reference +\newconstant\a_strc_notes_text_reference +\newconstant\a_strc_notes_text_destination + +\let\strc_notes_get_reference_attribute_symbol \empty +\let\strc_notes_get_destination_attribute_symbol\empty + +\def\strc_notes_interaction_check_inline + {\edef\p_interaction{\noteparameter\c!interaction}% + \csname\??noteinteractioninline + \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi + \endcsname} + +\def\strc_notes_interaction_check_display + {\edef\p_interaction{\noteparameter\c!interaction}% + \csname\??noteinteractiondisplay + \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi + \endcsname} + +\def\currentnotenumber{0} + +\let\strc_notes_get_reference_attribute_symbol \empty +\let\strc_notes_get_destination_attribute_symbol\empty + +\let\strc_notes_set_reference_attribute_number\donothing +\let\strc_notes_set_reference_attribute_text \donothing +\let\strc_notes_set_destination_attribute_text\donothing + +% inline + +\def\strc_references_prepare_inline_references_nop + {\let\strc_notes_get_reference_attribute_symbol\empty + \let\strc_notes_get_destination_attribute_symbol\empty + \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop} + +% \def\strc_references_prepare_inline_references_yes +% {\strc_references_set_simple_reference{symb:\currentnote:\currentnotenumber}% destination +% \strc_references_get_simple_reference{internal(\clf_noteinternal{\currentnote}\currentnotenumber)}% reference +% \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% +% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% +% \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} + +\def\strc_references_prepare_inline_references_yes + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \strc_references_set_simple_reference{*\currentnoteinternal}% destination + \strc_references_get_simple_reference{internal(\currentnoteinternal)}% reference + \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% + \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% + \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} + +\letvalue{\??noteinteractioninline\v!no }\strc_references_prepare_inline_references_nop +\letvalue{\??noteinteractioninline\v!all }\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!number}\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!text }\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!yes }\strc_references_prepare_inline_references_yes + +% display (for 'all' we need unique text and number attributes so we resolve twice +% as we otherwise don't get the number one which is lapped in the margin so we need +% to explicitly visit it) + +\def\strc_references_prepare_display_references_nop + {\let\strc_notes_set_reference_attribute_number\donothing + \let\strc_notes_set_reference_attribute_text\donothing + \let\strc_notes_set_destination_attribute_text\donothing + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop} + +\def\strc_references_prepare_display_references_yes_number + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \let\strc_notes_set_reference_attribute_text\donothing + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\def\strc_references_prepare_display_references_yes_text + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_reference_attribute_number\donothing + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\def\strc_references_prepare_display_references_yes_all + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\letvalue{\??noteinteractiondisplay\v!no }\strc_references_prepare_display_references_nop +\letvalue{\??noteinteractiondisplay\v!all }\strc_references_prepare_display_references_yes_all +\letvalue{\??noteinteractiondisplay\v!number}\strc_references_prepare_display_references_yes_number +\letvalue{\??noteinteractiondisplay\v!text }\strc_references_prepare_display_references_yes_text +\letvalue{\??noteinteractiondisplay\v!yes }\strc_references_prepare_display_references_yes_number + +\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor +\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor + +\protected\def\strc_notes_set_style_color_inline_yes#style#color% + {\usenotestyleandcolor#style#color% + \iflocation\strc_notes_set_style_color_special\fi} + +\protected\def\strc_notes_set_style_color_display_yes#style#color% + {\usenotationstyleandcolor#style#color% + \iflocation\strc_notes_set_style_color_special\fi} + +\def\strc_notes_set_style_color_special + {\iftrialtypesetting + % keep + \orelse\ifempty\currentcolorparameter + \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once + \setlocationcolorspecified\scratchcounter + \fi} + +\setvalue{\??constructiontexthandler\v!notation}% + {\begingroup + % we need to retrigger the reference as otherwise it gets lost because we don't do nested + % references with the same id ... maybe some day if we can figure out a nice heuristic ... + % the problem is that normally it's no issue but here we lap into the margin, so maybe that's + % a criterium + % \strc_notes_interaction_check_display + \strc_notes_set_reference_attribute_number + \dotagsetnotation + \strc_notes_set_style_color_display\c!headstyle\c!headcolor + \strc_enumerations_text + \endgroup} + +% in mkii the pointer only showed up in pagewise notes + +\protected\def\strc_notes_inject_pointer % todo calculate once + {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax + % unknown + \or + % same page + \or + \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}% + \or + \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}% + \fi} + +\protected\def\strc_notes_inject_symbol_yes + {\strc_notes_inject_symbol_indeed\conditionaltrue} + +\protected\def\strc_notes_inject_symbol_nop + {\strc_notes_inject_symbol_indeed\conditionalfalse} + +\definemargindata + [strc_notes_destination_margin] + [\v!left] + [\c!margin=\zeropoint, + \c!width=\zeropoint, + \c!style=, + \c!color=] + +\protected\def\strc_notes_inject_symbol_indeed#synchronize% + {\ifconditional\c_strc_notations_anchored_next\else + \removeunwantedspaces + \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} + \fi + \ifdim\lastkern=\d_strc_notes_signal + % \kern\noteparameter\c!distance % yes or no note font? or main text + \strc_notes_inject_separator + \fi + \nobreak + \begingroup + \strc_notes_interaction_check_inline + \strc_notes_set_style_color_inline\c!textstyle\c!textcolor + \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup + % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack + \strc_references_flush_destination_nodes % a bit late but ok + \dostarttagged\t!descriptionsymbol\currentnote + \dotagsetnotesymbol + \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}% + % the next one can cycle so we need to make sure it has no advance width + \doif{\noteparameter\c!indicator}\v!yes\strc_notes_inject_pointer + \dostoptagged + \egroup + \endgroup + \glet\lastnotesymbol\relax} + +\protected\def\strc_notes_inject_dummy % temp hack + {\removeunwantedspaces + \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} + \ifdim\lastkern=\d_strc_notes_signal + % \kern\noteparameter\c!distance % yes or no note font? or main text + \strc_notes_inject_separator + \fi + \nobreak + \hpack to .5\emwidth{}% + \glet\lastnotesymbol\relax} + +\protected\def\strc_notes_inject_separator % patch by WS due to request on list + {\edef\p_textseparator{\noteparameter\c!textseparator}% + \ifempty\p_textseparator + \kern\noteparameter\c!distance + \else + % skip or kern + \nobreak + \hbox\bgroup + \strc_notes_interaction_check_inline + \strc_notes_set_style_color_inline\c!textstyle\c!textcolor + \noteparameter\c!textcommand{\p_textseparator}% + \kern\noteparameter\c!distance + \egroup + \nobreak + \fi} + +% this needs a further cleanup ... soon as it's a slow mechanism +% +% -- set breakpoint in descriptions +% -- reset after trialtypesetting +% -- that way we can trick the symbol space + +% removed: +% +% \pushsomestates +% +% core-ins -> obsolete +% +% saveinsertiondata +% restoreinsertiondata +% saveinsertionbox +% eraseinsertionbackup +% restoreinsertionbackup + +\def\savenotedata {} % \writestatus{todo}{save note data}} +\def\restorenotedata {} % \writestatus{todo}{restore note data}} +\def\savenotecontent {} % \writestatus{todo}{save note content}} +\def\restorenotecontent{} % \writestatus{todo}{restore note content}} +\def\erasenotebackup {} % \writestatus{todo}{erase note backup}} + +% page-set: + +\def\enablenotes {\writestatus{todo}{enable notes}} +\def\disablenotes {\writestatus{todo}{disable notes}} +\def\savenotes {\writestatus{todo}{save notes}} +\def\flushsavednotes{\writestatus{todo}{flush notes}} + +% experiment: (compare scope=text and scope=page) +% +% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] + +%D Footnotes are can be characterized by three components: +%D +%D \startitemize[packed] +%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes +%D [conversion=set 2]\footnote {a footnote}} +%D \item and a similar mark at the bottom of the page +%D \item followed by some additional text +%D \stopitemize +%D +%D Because footnotes are declared at the location of their reference they can be +%D seen as a special kind of floating bodies. Their placement is postponed but has +%D to be taken into account in the pagebreak calculations. This kind of calculations +%D are forced by using \type{\insert}s and dealing with all cases is not trivial. + +%D \macros +%D {notesenabled} +%D +%D We need a couple of states because at some moments we don't want to mess around +%D with inserts at all. Take for instance a table of contents. And so we can +%D temporary disable footnotes by saying +%D +%D \starttyping +%D \notesenabledfalse +%D \stoptyping + +\newif\ifnotesenabled \notesenabledtrue + +% better mark a note .. once flushed no more flushing + +%appendtoks \notesenabledfalse \to \everymarking +\appendtoks \notesenabledfalse \to \everybeforepagebody +\appendtoks \notesenabledfalse \to \everystructurelist % quick hack +\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack +\appendtoks \notesenabledfalse \to \everypreroll % quick hack + +%D Often we need to process the whole set of notes and to make that fast, we use a +%D token register: + +% we have several synchronizers: +% +% - after a definition +% - after a specific setup +% - after a general setup (inheritance of dimensions) +% - just before a note is typeset + +\newtoks\t_strc_notes + +\let\strc_notes_process_list\gobbleoneargument + +\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote + {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}% + \the\t_strc_notes} + +\newtoks\everychecknote % just before a note is typeset +\newtoks\everysynchronizenote % after a general setup has happened + +\appendtoks + \ifempty\currentnote \else + \setupnotations[\currentnote][]% also a synchronize + \fi +\to \everysynchronizenote + +\def\strc_notes_synchronize + {\the\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist + +\appendtoks + \strc_notes_process\strc_notes_synchronize +\to \everysetupnoteroot + +\appendtoks + \the\everysynchronizenote +\to \everydefinenote + +% \starttext +% text \startfootnote Test.\stopfootnote +% test \footnote{xxxx} \subfootnote{xxxx} +% test \footnote{xxxx} \subfootnote{xxxx} +% \stoptext + +\installcorenamespace{notecommand} +\installcorenamespace{notealign} +\installcorenamespace{notepenalty} +\installcorenamespace{noterule} + +\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname} +\permanent\protected\def\currentnoterulealign {\begincsname\??notealign \currentnote\endcsname} + +\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand} +\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards + +\permanent\protected\def\letcurrentnoterulecommand{\enforced\letcsname\??notecommand\currentnote\endcsname} +\permanent\protected\def\letcurrentnoterulealign {\enforced\letcsname\??notealign \currentnote\endcsname} + +\appendtoks + \enforced\letcsname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal + \enforced\letcsname\??notealign \currentnote\endcsname\lefttoright +\to \everysynchronizenote + +\def\strc_notes_set_rule + {\letcurrentnoterulecommand\relax % so we default to nothing + \letcurrentnoterulealign \relax + \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step} + +\def\strc_notes_set_rule_step#alternative% + {\begincsname\??noterule#alternative\endcsname} + +\def\strc_notes_set_rule_autodir + {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright} + +\setvalue{\??noterule \v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand} +\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal} +\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal} +\setvalue{\??noterule \v!left}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \lefttoright} +\setvalue{\??noterule \v!right}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \righttoleft} +\setvalue{\??noterule\v!paragraph}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \strc_notes_set_rule_autodir} +\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax} + +\appendtoks + \strc_notes_set_rule +\to \everysynchronizenote + +\permanent\def\currentnotepenalty + {\ifcsname\??notepenalty\noteparameter\c!split\endcsname + \lastnamedcs + \else + \numexpr\noteparameter\c!split\relax + \fi} + +\setnewconstant\notepenaltytolerant \zerocount +\setnewconstant\notepenaltystrict 9999 +\setnewconstant\notepenaltyverystrict\maxdimen + +\letvalue{\??notepenalty\v!tolerant }\notepenaltytolerant +\letvalue{\??notepenalty\v!strict }\notepenaltystrict +\letvalue{\??notepenalty\v!verystrict}\notepenaltyverystrict +\letvalue{\??notepenalty }\notepenaltytolerant + +%D The following switch can be used to disable limiting the height of the footnote +%D area, something that is needed in multi column balancing. Use this switch with +%D care. + +\newif\ifnotelimit \notelimittrue % shared + +\def\strc_notes_set_factor + {\edef\p_factor{\noteparameter\c!factor}% + \ifempty\p_factor \else + \ifnum\p_factor<\zerocount \else +% \global + \count\currentnoteinsertionnumber\p_factor % new: global + \fi + \fi} + +\appendtoks + \strc_notes_set_factor +\to \everysynchronizenote + +% locations: + +\installcorenamespace{notelocationvariant} +\installcorenamespace{notepositionvariant} +\installcorenamespace{notedelayedvariant} +\installcorenamespace{notelocation} + +\newconditional\c_strc_notes_delayed + +\protected\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed} +\protected\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed} + +\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page} +\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns} +\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn} +\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn} +\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none} +\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text} +\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high} +\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom} + +\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let +\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let +\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let + +\protected\def\strc_notes_set_delayed + {\csname\??notedelayedvariant + \ifcsname\??notedelayedvariant\currentnote\endcsname + \currentnote + \else + \??notedelayedvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_position + {\csname\??notepositionvariant + \ifcsname\??notepositionvariant\currentnote\endcsname + \currentnote + \else + \??notepositionvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_location + {\csname\??notelocationvariant + \ifcsname\??notelocationvariant\currentnote\endcsname + \currentnote + \else + \??notelocationvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_variants + {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}} + +\protected\def\strc_notes_set_location_step#alternative% the insert related one + {\begincsname\??notelocation#alternative\endcsname} + +\appendtoks + \strc_notes_set_variants + \strc_notes_set_delayed +\to \everysynchronizenote + +\newskip \s_strc_notes_distance % we need to implement stretch +\newcount\c_strc_notes_columns + +\newskip \s_strc_notes_before +\newskip \s_strc_notes_inbetween +\newconditional\c_strc_notes_first_flushed + +\appendtoks + \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}% + \ifempty\p_spacebefore + \global\s_strc_notes_before\zeropoint + \else + \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}% + \fi + \edef\p_spaceinbetween{\rootnoteparameter\c!spaceinbetween}% + \ifempty\p_spaceinbetween + \global\s_strc_notes_inbetween\zeropoint + \else + \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}% + \fi +\to \everysynchronizenote + +\def\strc_notes_set_distance + {\begingroup + \restoreglobalbodyfont + \setbox\scratchbox\vbox % no reuse as it can mirror + {\forgetall + \dontcomplain + \noteparameter\c!before + \placenoterule + \strut + \noteparameter\c!after}% + % also dp now + \scratchdimen\dimexpr\htdp\scratchbox-\lineheight\relax + \ifgridsnapping + \getnoflines\scratchdimen + \scratchdimen\noflines\lineheight + \fi + \expandafter\endgroup\expandafter + \s_strc_notes_distance\the\scratchdimen\relax} + +\def\strc_notes_set_columns + {\c_strc_notes_columns\noteparameter\c!n\relax + \ifcase\c_strc_notes_columns + \c_strc_notes_columns\plusone + \fi} + +\def\strc_notes_set_location_page + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]% + \global\count\currentnoteinsertionnumber\numexpr(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns\relax + \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_columns + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \ifnum\currentnofcolumns=\zerocount + \c_strc_notes_columns\plusone + \fi + \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]% + \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax + \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_somecolumn#whatcolumn% + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]% + \global\count\currentnoteinsertionnumber\plusthousand + \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn} +\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn } + +\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes) + {\settrue\c_strc_notes_delayed + \clf_setnotestate{\currentnote}{store}% + \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]% + \global\count\currentnoteinsertionnumber\zerocount + \global\dimen\currentnoteinsertionnumber\maxdimen + \global\skip \currentnoteinsertionnumber\zeropoint} + +\let\strc_notes_set_location_none\strc_notes_set_location_text + +\def\strc_notes_set_properties + {\strc_notes_set_columns + \strc_notes_set_distance + \strc_notes_set_location + \strc_notes_set_delayed} + +\let\strc_notes_set_position_high\relax + +\def\strc_notes_set_position_bottom + {\settrue\c_notes_bottom_present} + +\appendtoks + \strc_notes_set_properties +\to \everysynchronizenote + +%D A fast checker for bottom notes being used: + +\newconditional\c_notes_bottom_present + +\def\strc_notes_check_if_bottom_present_indeed % in otr ! + {\ifvoid\currentnoteinsertionnumber\else + \strc_notes_set_position + \fi} + +\def\strc_notes_check_if_bottom_present_step + {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi} + +\def\strc_notes_check_if_bottom_present + {\setfalse\c_notes_bottom_present + \strc_notes_process\strc_notes_check_if_bottom_present_step} + +% Example of using factor: +% +% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0] +% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] +% \starttext +% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} } +% \stoptext + +%D The noterule can be a graphic and therefore calling this setup macro at every +%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that +%D probably match those of the stretch component. A bit messy: + +\permanent\protected\def\placenoterule + {\begingroup + \currentnoterulealign + \currentnoterulecommand + \par + \endgroup} + +\permanent\protected\def\normalnoterule + {\ifvmode + \dontleavehmode \blackrule + [\c!color=\noteparameter\c!rulecolor, + \c!width=.2\hsize, + \c!height=\noteparameter\c!rulethickness, + \c!depth=\zeropoint]% + \endgraf + \kern\strutdepth + \fi} + +%D The formatting depends on the width of the table, so we have to set \type {n} to +%D zero. +%D +%D \starttyping +%D \startbuffer +%D \bTABLE +%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR +%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \startlocalfootnotes[n=0,location={text,none}] +%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes} +%D \stoplocalfootnotes +%D \stoptyping + +%D \macros +%D {footnote} +%D +%D A footnote can have a reference as optional argument and therefore its formal +%D specification looks like: +%D +%D \showsetup{footnote} +%D +%D This command has one optional command: the reference. By saying \type{[-]} the +%D number is omitted. The footnote command is not that sensitive to spacing, so it's +%D quite legal to say: +%D +%D \startbuffer +%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the +%D ground and not get confused \footnote {Or even crazy.} by all those obscure +%D \footnote {But fortunately readable.} parameters. +%D \stopbuffer +%D +%D \typebuffer +%D +%D When setting the \type{conversion} to \type{set 2} we get +%D something like: +%D +%D \bgroup +%D \startnarrower +%D \setupfootnotes[conversion=set 1] +%D \getbuffer +%D \stopnarrower +%D \egroup +%D +%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes. +%D The additional macro \type {\footnotetext} and the associated \type {\note} macro +%D were implemented at request of users on the mailing list and a suggestion by taco +%D to split of the symbol placement. I decided to merge this functionality with the +%D existing \type {\note} functionality. + +\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used +\newconditional\c_strc_notes_skip + +\permanent\protected\def\setnote [#tag]{\csname#tag\endcsname} +\permanent\protected\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname} + +\permanent\protected\def\handlenoteinsert#tag#id% + {\begingroup + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% + \strc_notes_synchronize + \the\everybeforenoteinsert + \insert\currentnoteinsertionnumber\bgroup + \the\everyinsidenoteinsert\relax + \usesetupsparameter\noteparameter % experimental + \useinterlinespaceparameter\noteparameter + \doifelse{\noteparameter\c!paragraph}\v!yes + {\nointerlineskip + \startvboxtohboxseparator + \noteparameter\c!inbetween + \stopvboxtohboxseparator + \startvboxtohbox + \handlenoteitself{#tag}{#id}% + \stopvboxtohbox} + {\handlenoteitself{#tag}{#id}}% + \egroup + \the\everyafternoteinsert + \endgroup} + +\permanent\protected\def\betweennoteitself#tag% used ? + {\edef\currentnote{#tag}% + \doif{\noteparameter\c!paragraph}\v!yes{\noteparameter\c!inbetween}} + +\permanent\protected\def\handlenoteitself#tag#id% + {\edef\currentnotenumber{#id}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% + \strc_notes_synchronize + \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache + % as we can have collected notes (e.g. in tables) we need to recover + % \currentdescriptionattribute and \currentdescriptionsynchronize + % + \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table) + % + \dontcomplain + %begingroup + \strc_notes_interaction_check_display + \strc_notes_set_reference_attribute_text + \strc_constructions_stored_start + \begstrut + \strc_references_flush_destination_nodes + \strc_notes_set_destination_attribute_text + \strc_notes_inject_text\relax + \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10 + \strc_constructions_stored_stop + %endgroup + } + +\protected\def\strc_notes_inject_text % hm main? + {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax} + +\let\startpushnote\relax +\let\stoppushnote \relax + +\newsignal\d_strc_notes_signal + +\newconditional\processingnote +\newconditional\postponednote + +\newtoks\everybeforenoteinsert +\newtoks\everyinsidenoteinsert +\newtoks\everyafternoteinsert + +\permanent\protected\def\doifelseinnote + {\ifconditional\processingnote + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\appendtoks + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax + \forgetall + \resetallattributes % new, we don't want color bleed into notes + \inheritmaintextcolor % but we do want to obey the textcolor +\to \everybeforenoteinsert + +\def\strc_notes_set_penalties + {% stored in insert node + \floatingpenalty \currentnotepenalty + % used when typesetting + \interlinepenalty\plushundred % plain value + % used when we need to split in columns + \ifnum\noteparameter\c!n>\plusone + \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated) + \fi} + +\appendtoks + \strc_notes_set_penalties + \forgetall % again + \strc_notes_set_bodyfont + \redoconvertfont % to undo \undo calls in in headings etc + \splittopskip\strutht % not actually needed here + \splitmaxdepth\strutdp % not actually needed here + % + % not: + % + % \leftmargindistance \noteparameter\c!margindistance + % \rightmargindistance\leftmargindistance + % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? + % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? + % \fi + % + \pickupattributes +\to \everyinsidenoteinsert + +%D Nasty, the might be more: + +\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert +\appendtoks \strc_itemgroups_pop \to \everyafternoteinsert + +% maybe but better use [scope=local] here +% +% \appendtoks +% \setfalse\inhibitmargindata +% \to \everyinsidenoteinsert + +\setupnotes + [\c!width=\v!auto] + +\permanent\protected\def\setnotehsize + {\ifinsidemulticolumns + \setnoteparameter\c!width{\makeupwidth}% + \else + \edef\p_width{\noteparameter\c!width}% + \ifx\p_width\v!auto + % \ifinsidecolumns + \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}% + % \else + % \setnoteparameter\c!width{\makeupwidth}% + % \fi + \orelse\ifempty\p_width + \setnoteparameter\c!width{\hsize}% + \fi + \fi + \hsize\noteparameter\c!width\relax} + +\appendtoks + % only needed when columns (could be three \set...) + \setnotehsize + \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% +\to \everyinsidenoteinsert + +%D Normally footnotes are saved as inserts that are called upon as soon as the +%D pagebody is constructed. The footnote insertion routine looks just like the +%D \PLAIN\ \TEX\ one, except that we check for the end note state. + +% testcase for split bottom alignment see (a) below +% +% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}} + +\newconditional\c_strc_notes_first_placed + +\permanent\protected\def\placenoteinserts + {\setfalse\c_strc_notes_first_placed + \strc_notes_process\strc_notes_place_inserts} + +\def\strc_notes_place_inserts + {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed + \ifconditional\c_strc_notes_delayed \else + \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test + \strc_notes_place_inserts_indeed + \settrue\c_strc_notes_first_placed + \fi + \fi} + +\def\strc_notes_place_inserts_indeed + {\relax + \ifdim\ht\currentnoteinsertionnumber>\zeropoint + \endgraf + \ifvmode + \whitespace + \ifconditional\c_strc_notes_first_placed + \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}% + \ifempty\p_spaceinbetween\else + \blank[\p_spaceinbetween]% + \fi + \else + \edef\p_spacebefore{\noteparameter\c!spacebefore}% + \ifempty\p_spacebefore\else + \blank[\p_spacebefore]% + \fi + \fi + \noteparameter\c!before + \fi + \placenoterule + \bgroup + \strc_notes_set_bodyfont + \setbox\scratchbox\hbox + {\strc_notes_flush_inserts}% + \page_postprocessors_linenumbers_deepbox\scratchbox + \setbox\scratchbox\hbox + {\setupcurrentnote + [\c!location=, + \c!width=\v!fit, + \c!height=\v!fit, + \c!strut=\v!no, + \c!offset=\v!overlay]% + \inheritednoteframed + {\ifzeropt\dp\scratchbox % this hack is needed because \vadjust + \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement + \else % hides the (always) present depth + \box\scratchbox + \fi}}% + \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}% + \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth + \ifvmode + \nointerlineskip % else sometimes empty line + \fi + \box\scratchbox + \egroup + \endgraf + \ifvmode + \noteparameter\c!after + \fi + \fi} + +\def\strc_notes_flush_inserts + {\ifcase\noteparameter\c!n\relax + % should not happen + \or + \strc_notes_flush_inserts_normal + \else + \strc_notes_flush_inserts_columns + \fi} + +\def\strc_notes_flush_inserts_normal + {\strc_notes_flush_global + \obeydepth} % (a) added , since split footnotes will not align properly + +\def\strc_notes_flush_inserts_columns + {\begingroup + \setnotehsize % probably still not ok for columns + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% + \strc_notes_flush_global + \stopsimplecolumns + \endgroup} + +% idea: tag with attr and then just flush them again + +\def\strc_notes_flush_global + {\begingroup + \useinterlinespaceparameter\noteparameter + \doifelse{\noteparameter\c!paragraph}\v!yes + {\leftorrightvbox % cf mail from ws to list + {\starthboxestohbox + \iftrialtypesetting\unvcopy\else\unvbox\fi\currentnoteinsertionnumber + \stophboxestohbox}} + {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}% + \endgroup} + +%D Supporting end notes is surprisingly easy. Even better, we can combine this +%D feature with solving the common \TEX\ problem of disappearing inserts when +%D they're called for in deeply nested boxes. The general case looks like: +%D +%D \starttyping +%D \postponenotes +%D \.box{whatever we want with footnotes} +%D \flushnotes +%D \stoptyping +%D +%D This alternative can be used in headings, captions, tables etc. The latter one +%D sometimes calls for notes local to the table, which can be realized by saying +%D +%D \starttyping +%D \setlocalfootnotes +%D some kind of table with local footnotes +%D \placelocalfootnotes +%D \stoptyping +%D +%D Postponing is accomplished by simply redefining the (local) insert operation. A +%D not too robust method uses the \type{\insert} primitive when possible. This +%D method fails in situations where it's not entirely clear in what mode \TEX\ is. +%D Therefore the auto method can is to be overruled when needed. + +\newconditional\postponingnotes + +% we need a proper state: normal, postponing, flushing + +\permanent\protected\def\postponenotes % will be locally overloaded + {\ifcase\insertionmigrationmode + \ifconditional\postponingnotes\else + \global\settrue\postponingnotes + \enforced\glet\flushnotes\doflushnotes + \clf_postponenotes + \fi + \fi} + +\aliased\let\flushnotes\relax + +% also \ifcase\insertionmigrationmode here, needs testing: + +\permanent\protected\def\startpostponingnotes % experimental, page-mix + {\ifconditional\postponingnotes\else + \global\settrue\postponingnotes + %\glet\flushnotes\doflushnotes + \clf_postponenotes + \fi} + +\permanent\protected\def\stoppostponingnotes % experimental, page-mix + {\doflushnotes} + +\permanent\protected\def\doflushnotes + {\ifconditional\postponingnotes + \begingroup + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax + \ifconditional\postponednote + \ifhmode + % needed for tagging ... otherwise we get some weird node free error + \signalcharacter + \fi + \fi + \clf_flushpostponednotes% this also resets the states ! + \global\setfalse\postponednote + \global\setfalse\postponingnotes + \enforced\glet\flushnotes\relax + \endgroup + \fi} + +%D \macros +%D {startlocalfootnotes,placelocalfootnotes} +%D +%D The next two macros can be used in for instance tables, as we'll demonstrate +%D later on. +%D +%D \showsetup{startlocalfootnotes} +%D \showsetup{placelocalfootnotes} + +% todo: compatibility mode: when first arg is assignment or missing, then all + +\newtoks\everyplacelocalnotes + +\appendtoks + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax +\to \everyplacelocalnotes + +\newconditional\inlocalnotes + +\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings) + {\def\localnoteslist{#list}% + \settrue\inlocalnotes + \processcommacommand[\localnoteslist]\strc_notes_local_start_step} + +\permanent\protected\def\stoplocalnotes + {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step + \setfalse\inlocalnotes} + +\let\p_strc_notes_continue\empty + +\def\strc_notes_local_start_step#tag% + {\p_strc_notes_continue{\noteparameter\c!continue}% + \ifx\p_strc_notes_continue\v!yes \else + \strc_counters_save{#tag}% + \strc_counters_reset{#tag}% + \fi + \clf_savenote{#tag}{store}} + +\def\strc_notes_local_stop_step#tag% + {\p_strc_notes_continue{\noteparameter\c!continue}% + \ifx\p_strc_notes_continue\v!yes \else + \strc_counters_restore{#tag}% + \fi + \clf_restorenote{#tag}} + +\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#settings]% + {\doif{\clf_getnotestate{#tag}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}} + +\def\strc_notes_local_place_indeed#settings#tag% + {\begingroup + \edef\currentnote{#tag}% is already set? + \the\everyplacelocalnotes + % beware, we cannot trust setting \currentnote here + \setupcurrentnote[#settings]% later we set height etc for framed + \strc_notes_place_local_alternative + \strc_notes_set_properties % restore globals (if needed) + \endgroup + }% TODO: just restore properties \the\everychecknote} % we need to restore the old state + +%D These commands can be used like: +%D +%D \startbuffer +%D \startlocalnotes[footnote] +%D \placetable +%D {Some Table} +%D \placeontopofeachother +%D {\starttable[|l|r|] +%D \HL +%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR +%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR +%D \HL +%D \stoptable} +%D {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]% +%D \placelocalnotes[footnote]} +%D \stoplocalnotes +%D \stopbuffer +%D +%D \typebuffer +%D +%D Because this table placement macro expect box content, and thanks to the grouping +%D of the local footnotes, we don't need additional braces. +%D +%D \getbuffer + +%D \macros +%D {placefootnotes} +%D +%D We still have no decent command for placing footnotes somewhere else than at the +%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can +%D be placed by using +%D +%D \showsetup{placefootnotes} + +\permanent\protected\def\placebottomnotes + {\strc_notes_process\strc_notes_place_inserts} + +\permanent\tolerant\protected\def\placenotes[#list]#spacer[#settings]% + {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}} + +\def\strc_notes_place_indeed#settings#tag% settings note + {\edef\currentnote{#tag}% grouping ? + \doifelse{\clf_getnotestate{#tag}}{store} + \strc_notes_local_place_indeed + \strc_notes_global_place_indeed + {#settings}{#tag}} + +\def\strc_notes_global_place_indeed#settings#tag% + {\begingroup + \setupnote[#tag][#settings]% + \strc_notes_place_inserts + \endgroup + \the\everysetupnote} % to be checked .. synchronize + +%D Placement + +\installcorenamespace{notealternative} + +\permanent\protected\def\installnotealternative#alternative#command% + {\setvalue{\??notealternative#alternative}{#command}} + +\permanent\protected\def\doifnotescollected#tag% + {\clf_doifnotecontent{#tag}} + +\def\strc_notes_place_local_alternative % will be a setup (wrapper) + {\doifnotescollected\currentnote + {\endgraf + \ifvmode + \whitespace + \noteparameter\c!before + \fi + \begingroup + \strc_notes_set_bodyfont + \csname\??notealternative\noteparameter\c!alternative\endcsname + \endgroup + \ifvmode + \noteparameter\c!after + \fi}} + +%D A stupid alternative is also provided: +%D +%D \starttyping +%D \setupfootnotes[location=text,alternative=none] +%D \stoptyping + +% setups ? + +\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}} + +\installnotealternative \v!none + {\flushlocalnotes\currentnote} + +\installnotealternative \empty + {\flushlocalnotes\currentnote} + +\installnotealternative \v!grid % test if n > 0 + {\begingroup + \setupcurrentnote[\c!location=]% + \snaptogrid\hbox + {\inheritednoteframed + {\flushlocalnotes\currentnote}}% + \endgroup} + +\installnotealternative \v!fixed % test if n > 0 + {\begingroup + \setupcurrentnote[\c!location=]% + \inheritednoteframed + {\flushlocalnotes\currentnote}% + \endgroup} + +\installnotealternative \v!columns % redundant + {\begingroup + \setupcurrentnote[\c!location=]% + \inheritednoteframed + {\edef\currentnotewidth{\noteparameter\c!width}% + \doifelsedimension\currentnotewidth\donothing + {\edef\currentnotewidth{\the\hsize}}% + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]% + \flushlocalnotes\currentnote + \stopsimplecolumns}% + \endgroup} + +% 0:page 1:firstcolumn 2:lastcolumn + +\newconstant\c_strc_notes_page_location + +\protected\def\strc_notes_check_locations + {\edef\p_strc_notes_location{\rootnoteparameter\c!location}% + \c_strc_notes_page_location + \ifx\p_strc_notes_location\v!firstcolumn\plusone \else + \ifx\p_strc_notes_location\v!lastcolumn \plustwo \else + \zerocount\fi\fi} + +\appendtoks + \strc_notes_check_locations +\to \everysynchronizenote + +% still semi public (but will change) + +\newif\ifnotespresent + +\permanent\protected\def\checknotepresence + {\notespresentfalse + \strc_notes_process\strc_notes_check_presence} + +\def\strc_notes_check_presence + {\ifdim\ht\currentnoteinsertionnumber>\zeropoint + \notespresenttrue + \fi} + +%D \macros +%D {fakenotes} + + % used in page-mul + + \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi + + \permanent\protected\def\fakenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalclevernoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + \permanent\protected\def\fakepagenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalpagenoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + % used in page-not but not yet ok + + \newdimen\totalnoteheight + + \permanent\protected\def\additionaltotalnoteheight#insert% temp hacks anyway + {\dimexpr + \ifdim\ht#insert>\zeropoint + \ifcase\count#insert % + \zeropoint + \else % todo: divide by count + \ht#insert+\skip#insert% hm, no stretch but a dimen anyway + \fi + \else + \zeropoint + \fi + \relax} + + \permanent\def\docalculatetotalnoteheight + {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! ! + \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% + \fi} + + \permanent\def\docalculatetotalclevernoteheight + {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! ! + \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% + \fi} + + \permanent\def\docalculatetotalpagenoteheight + {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}} + + \permanent\def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight} + \permanent\def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight} + \permanent\def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight} + +%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing +%D footnotes? The solution turned out to be rather simple: +%D +%D \starttyping +%D \everypar {...\flushnotes...} +%D \neverypar {...\postponenotes} +%D \stoptyping +%D +%D We can use \type {\neverypar} because in most commands sensitive to footnote +%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact, +%D this footnote implementation is the first to use this scheme. + +%D This is a nasty and new secondary footnote flusher. It can be hooked into \type +%D {\everypar} like: +%D +%D \starttyping +%D \appendtoks \synchronizenotes \to \everypar +%D \stoptyping + +\let\synchronizenotes\relax + +%D When typesetting footnotes, we have to return to the footnote specific bodyfont +%D size, which is in most cases derived from the global document bodyfont size. In +%D the previous macros we already used a footnote specific font setting macro. + +\def\strc_notes_set_bodyfont + {\let\strc_notes_set_bodyfont\relax + \restoreglobalbodyfont + \usebodyfontparameter\noteparameter + \usealignparameter\noteparameter} + +%D The footnote mechanism defaults to a traditional one column way of showing them. +%D By default we precede them by a small line. + +% end notes in the margin: +% +% \setuptexttexts +% [margin] +% [] [{\directsetup{notabene}}] +% +% \startsetups notabene +% \vbox to \textheight \bgroup +% \setupalign[tolerant] +% \topskipcorrection +% \placenotes[endnote][before=,after=] +% \vfilll +% \egroup +% \stopsetups + +\definenote [\v!footnote] +\definenote [\v!endnote ] [\c!location=\v!none] % else no break + +%D Compatibility macros: + +\permanent\protected\def\setupfootnotedefinition{\setupnotation [\v!footnote]} +\permanent\protected\def\setupfootnotes {\setupnote [\v!footnote]} +\permanent \def\footnotetext {\setnotetext [\v!footnote]} +\permanent\protected\def\placefootnotes {\strc_notes_place_footnotes [\v!footnote]} +\permanent\protected\def\placelocalfootnotes {\strc_notes_place_local_footnotes[\v!footnote]} +\permanent\protected\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote +\permanent\protected\def\stoplocalfootnotes {\stoplocalnotes } + +\tolerant\def\strc_notes_place_footnotes[#list]#spacer[#settings]% + {\ifarguments\or + \placenotes[#list][\c!height=\textheight]% + \or + \placenotes[#list][#settings,\c!height=\textheight]% + \fi} + +\tolerant\def\strc_notes_place_local_footnotes[#list]#spacer[#settings]% + {\ifarguments\or + \placelocalnotes[#list][\c!height=\textheight]% + \or + \placelocalnotes[#list][#settings,\c!height=\textheight]% + \fi} + +%D Goodies: +%D +%D \starttyping +%D \dorecurse {100} { +%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}} +%D } +%D \stoptyping + +\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}} + +\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage + +%D New trickery: + +%D \macros +%D {note} +%D +%D Refering to a note is accomplished by the rather short command: +%D +%D \showsetup{note} +%D +%D This command is implemented rather straightforward as: + +\installcorenamespace{notesymbol} + +\let\lastnotesymbol\relax % todo: per class + +\permanent\tolerant\protected\def\notesymbol[#tag]#spacer[#reference]% + {\ifnotesenabled + \dontleavehmode + \begingroup + \edef\currentnote{#tag}% + \usenotestyleandcolor\c!textstyle\c!textcolor + \iftok{#reference}\emptytoks + \noteparameter\c!textcommand\lastnotesymbol % check if command double + \else + \unskip + \noteparameter\c!textcommand{\in[#reference]}% command here? + \fi + \endgroup + \fi} + +\permanent\tolerant\protected\def\note[#tag]#spacer[#reference]% + {\iftok{#reference}\emptytoks + \notesymbol[\v!footnote][#tag]% + \else + \notesymbol[#tag][#reference]% + \fi} + +% will be redone if needed +% +% \def\ownnotesymbol#1% #1 gets number passed +% {\executeifdefined{\??notesymbol\currentnote}\empty} +% +% \protected\def\setnotesymbol[#1]#2#3% +% {\prewordbreak % prevent lookback +% \setgvalue{\??notesymbol#1}{#3} +% \strc_notes_inject_symbol} +% +% \protected\def\ownnote[#1]#2#3#4% +% {\setnotesymbol[#1]{#2}{#3}% +% \setnotetext [#1]{#4}} +% +% \defineconversion +% [ownnote] +% [\ownnotesymbol] + +% tricky: +% +% \enabletrackers[nodes.areas] +% \enabletrackers[nodes.references] +% \enabletrackers[nodes.destinations] +% +% \setupnotes[interaction=all,rule=no] +% \setupinteraction[state=start,focus=standard] +% +% \starttext +% \goto{\input tufte\relax}[page(2)] \par +% \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par +% \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par +% % \completecontent +% % \chapter{Chapter} +% % \dorecurse{5}{\input knuth} +% a\footnote{\input tufte\par\input ward\relax} +% \stoptext + +%D Bonus: + +\appendtoks + \setsystemmode\currentnote +\to \everysynchronizenote + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-num.mkxl b/tex/context/base/mkxl/strc-num.mkxl new file mode 100644 index 000000000..041e2c138 --- /dev/null +++ b/tex/context/base/mkxl/strc-num.mkxl @@ -0,0 +1,687 @@ +%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}{} + +\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 + +\aliased\let\setupcounters \setupcounter +\aliased\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] + +\permanent\def\autostructureprefixsegments#1% todo: \c!prefixsegments=\v!auto + {2:\thenamedheadlevel{\clf_way{#1\c!way}}} + +\appendtoks + \resetcounterparameter\s!counter +\to \everypresetcounter + +\appendtoks + \ifempty\currentcounterparent + \edef\p_start{\counterparameter\c!start}% + \clf_definecounter + name {\currentcounter}% + start \ifempty\p_start\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 + \ifempty\currentcounter \else + \edef\p_number{\counterparameter\c!number}% + \ifempty\p_number \else + \clf_setcounter{\counterparameter\s!name}\numexpr\p_number\relax + \letcounterparameter\c!number\empty + \fi + \edef\p_start{\counterparameter\c!start}% + \setexpandedcounterparameter\c!start{\ifempty\p_start0\else\number\p_start\fi}% + \strc_counters_check_setup + \fi +\to \everysetupcounter + +% % % % + +\permanent\def\strc_counters_way #1{\clf_way{\namedcounterparameter{#1}\c!way}} +\permanent\def\thenamedcounterlevel#1{\xthenamedheadlevel{\clf_way{\namedcounterparameter{#1}\c!way}}} + +\protected\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\ifempty\p_start\zerocount\else\p_start\fi\relax % bug in scanner + {\counterparameter\c!state}% + \fi} + +\permanent\protected\def\doifelsecounter #1{\clf_doifelsecounter{\namedcounterparameter{#1}\s!name}} +\permanent\protected\def\doifcounter #1{\clf_doifcounter {\namedcounterparameter{#1}\s!name}} +\permanent\protected\def\doifnotcounter #1{\clf_doifnotcounter {\namedcounterparameter{#1}\s!name}} + +\aliased\let\doifcounterelse\doifelsecounter + +\permanent\tolerant\protected\def\setcounter[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \else + \clf_setsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax + \fi} + +\permanent\tolerant\protected\def\setcounterown[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}\or + \else + \clf_setownsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}% + \fi} + +\permanent\tolerant\protected\def\restartcounter[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \else + \clf_restartsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax + \fi} + +\permanent\tolerant\protected\def\resetcounter[#1]#*[#2]% + {\ifarguments\or + \clf_resetcounter {\namedcounterparameter{#1}\s!name}\or + \else + \clf_resetsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax + \fi} + +\permanent\tolerant\protected\def\incrementcounter[#1]#*[#2]% + {\ifarguments\or + \strc_counters_increment_sub{#1}\plusone\or + \else + \strc_counters_increment_sub{#1}{#2}% + \fi} + +\permanent\tolerant\protected\def\decrementcounter[#1]#*[#2]% + {\ifarguments\or + \clf_decrementcounter {\namedcounterparameter{#1}\s!name}\or + \else + \clf_decrementsubcounter{\namedcounterparameter{#1}\s!name}\numexpr#2\relax + \fi} + +\permanent\tolerant\protected\def\rawcounter[#1]#*[#2]% + {\ifarguments\or\or + \clf_countervalue {\namedcounterparameter{#1}\s!name}% + \else + \clf_subcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\lastcounter[#1]#*[#2]% + {\ifarguments\or\or + \clf_lastcountervalue {\namedcounterparameter{#1}\s!name}% + \else + \clf_lastsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\firstcounter[#1]#*[#2]% + {\ifarguments\or\or + \clf_firstcountervalue {\namedcounterparameter{#1}\s!name}% + \else + \clf_firstsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\prevcounter[#1]#*[#2]% + {\ifarguments\or\or + \clf_previouscountervalue {\namedcounterparameter{#1}\s!name}%} + \else + \clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\nextcounter[#1]#*[#2]% + {\ifarguments\or\or + \clf_nextcountervalue {\namedcounterparameter{#1}\s!name}% + \else + \clf_nextsubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\countersubs[#1]#*[#2]% + {\ifarguments\or\or + \clf_subcountervalues {\namedcounterparameter{#1}\s!name}% + \else + \clf_subsubcountervalues{\namedcounterparameter{#1}\s!name}\numexpr#2\relax\or + \fi} + +\permanent\tolerant\protected\def\savecounter[#1]% + {\ifarguments\or + \clf_savecounter{\namedcounterparameter{#1}\s!name}% + \fi} + +\permanent\tolerant\protected\def\restorecounter[#1]% + {\ifarguments\or + \clf_restorecounter{\namedcounterparameter{#1}\s!name}% + \fi} + +\protected\def\strc_counters_set #1#2{\clf_setcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\protected\def\strc_counters_setown #1#2{\clf_setowncounter {\namedcounterparameter{#1}\s!name}{#2}} +\protected\def\strc_counters_restart #1#2{\clf_restartcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\protected\def\strc_counters_reset #1{\clf_resetcounter {\namedcounterparameter{#1}\s!name}} +\protected\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}} + +\protected\def\strc_counters_set_sub #1#2#3{\clf_setsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax} +\protected\def\strc_counters_setown_sub #1#2#3{\clf_setownsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax{#3}} +\protected\def\strc_counters_restart_sub #1#2#3{\clf_restartsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax\numexpr#3\relax} +\protected\def\strc_counters_reset_sub #1#2{\clf_resetsubcounter {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\protected\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} + +\protected\def\strc_counters_save #1{\clf_savecounter {\namedcounterparameter{#1}\s!name}} +\protected\def\strc_counters_restore #1{\clf_restorecounter {\namedcounterparameter{#1}\s!name}} + +\protected\def\strc_counters_incremented #1{\clf_incrementedcounter {\namedcounterparameter{#1}\s!name}} +\protected\def\strc_counters_decremented #1{\clf_decrementedcounter {\namedcounterparameter{#1}\s!name}} + +\permanent\protected\def\showcounter [#1]{\clf_showcounter {\namedcounterparameter{#1}\s!name}} +\permanent\protected\def\incrementedcounter[#1]{\clf_incrementedcounter{\namedcounterparameter{#1}\s!name}} % no \dosingleargument +\permanent\protected\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 + +\permanent\def\rawcountervalue [#1]{\clf_countervalue {\namedcounterparameter{#1}\s!name}} +\permanent\def\lastcountervalue [#1]{\clf_lastcountervalue {\namedcounterparameter{#1}\s!name}} +\permanent\def\firstcountervalue[#1]{\clf_firstcountervalue {\namedcounterparameter{#1}\s!name}} +\permanent\def\nextcountervalue [#1]{\clf_nextcountervalue {\namedcounterparameter{#1}\s!name}} +\permanent\def\prevcountervalue [#1]{\clf_previouscountervalue{\namedcounterparameter{#1}\s!name}} + +\permanent\def\rawsubcountervalue [#1]#*[#2]{\clf_subcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\permanent\def\lastsubcountervalue [#1]#*[#2]{\clf_lastsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\permanent\def\firstsubcountervalue[#1]#*[#2]{\clf_firstsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\permanent\def\nextsubcountervalue [#1]#*[#2]{\clf_nextsubcountervalue {\namedcounterparameter{#1}\s!name}\numexpr#2\relax} +\permanent\def\prevsubcountervalue [#1]#*[#2]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#2\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. + +\protected\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} + +\protected\def\strc_counters_increment#1% + {\strc_counters_increment_sub{#1}\plusone} + +% so far for the hack + +\permanent\tolerant\protected\def\convertedcounter[#1]#*[#2]% + {\begingroup + \edef\currentcounter{#1}% + \ifparameter#2\or\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} + +\permanent\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} + +\permanent\tolerant\protected\def\convertedsubcounter[#1]#*[#2]#*[#3]% #2 can be n or n:m + {\ifarguments\or + \convertedcounter[#1][]% + \else + \convertedcounter[#1][\c!numbersegments=#2,#3]% + \fi} + +\permanent\protected\def\doifdefinedcounter {\doifcommandhandler \??counter} +\permanent\protected\def\doifundefinedcounter {\doifnotcommandhandler \??counter} +\permanent\protected\def\doifelsedefinedcounter{\doifelsecommandhandler\??counter} + +\aliased\let\doifdefinedcounterelse\doifelsedefinedcounter + +%D What follows is a compatibility layer. Do we need this? + +\aliased\let \numberparameter \namedcounterparameter % {name}\c!key + +\aliased\let \definenumber \definecounter % [name] +\aliased\let \setupnumber \setupcounter % [name][setups] + +\aliased\let \setnumber \setcounter % [name]{value} +\aliased\let \resetnumber \resetcounter % [name] +\aliased\let \savenumber \savecounter % [name] +\aliased\let \restorenumber \restorecounter % [name] +\aliased\let \incrementnumber \incrementcounter % [name] +\aliased\let \decrementnumber \decrementcounter % [name] +\aliased\let \rawnumber \rawcounter % [name] +\aliased\let \getnumber \convertedcounter % [name] +\aliased\let \convertednumber \convertedcounter % [name] + +\aliased\let \doifdefinednumber \doifdefinedcounter % {number}{true} +\aliased\let \doifundefinednumber \doifnotdefinedcounter % {number}{true} +\aliased\let \doifelsedefinednumber \doifelsedefinedcounter % {number}{true}{false} +\aliased\let \doifdefinednumberelse \doifelsedefinedcounter % {number}{true}{false} + +\aliased\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_ + +\protected\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}% + \ifempty\currentname + \edef\currentname{#1}% + \fi + \edef\currentcounter{#3\s!counter}% + \ifempty\currentcounter + \let\currentcounter\currentname + \fi + % + \ifx\p_hascaption\v!yes + \strc_counters_register_component_list{#1}{#3}{#4}{#9}% + \orelse\ifempty\currentstructurecomponentreference + \strc_counters_register_component_none + \else + \strc_counters_register_component_page{#3}% + \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 + {\ifempty\currentstructurecomponentreferenceprefix + \let\currentstructurecomponentreferenceprefix\currentstructurereferenceprefix + \fi + \ifempty\currentstructurecomponentreferenceprefix + \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 \locationcount + % 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 + \ifempty\currentstructurecomponentlist + \glet\currentstructurecomponentlist\currentstructurecomponenttitle + \fi + \glet\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 \ifempty\currentstructurecomponentbookmark + \begingroup + \simplifycommands + \xdef\currentstructurecomponentbookmark{\detokenize\expandafter{\normalexpanded{#2\c!title}}}% + \endgroup + \fi \fi + \fi + \ifempty\currentstructurecomponentlist + \glet\currentstructurecomponentlist\currentstructurecomponenttitle + \fi + \glet\currentstructurecomponentcoding\s!tex + \fi + % + \setnextinternalreference + \scratchcounter\clf_addtolist %{ + metadata { + kind {#1} + name {\currentname} + % level structures.sections.currentlevel() + catcodes \ifempty\currentstructurecomponentcatcodes\catcodetable\else\csname\currentstructurecomponentcatcodes\endcsname\fi + coding {\currentstructurecomponentcoding} + \ifx\currentstructurecomponentcoding\s!xml + xmlroot {\xmldocument} + \fi + \ifempty\currentstructurecomponentxmlsetup \else + xmlsetup {\currentstructurexmlsetup} + \fi + } + references { + internal \locationcount + % 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}% + \setstructurecomponentsynchronization\m_strc_counters_last_registered_index + \glet\m_strc_counters_last_registered_attribute \currentstructurecomponentattribute + \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize} + +\let\m_strc_counters_last_registered_index \relax +\let\m_strc_counters_last_registered_attribute \relax +\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). + +\protected\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]} + +\protected\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} + +\protected\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% + \permanent\protected\def #6{\ifx#2\empty\the#5\else\strc_counter_setup_using_parameter#2#4\fi}% sync + \permanent\protected\def#7##1{\normalexpanded{#5{\the#5\strc_counter_setup_using_parameter{##1}\noexpand#4}}}} % register + +\permanent\protected\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: +% +% \protected\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} +% +% \protected\def\strc_counter_setup_pop +% {\let\counterparameter \savedcounterparameter +% \let\directcounterparameter \saveddirectcounterparameter +% \let\setexpandedcounterparameter \savedsetexpandedcounterparameter} +% +% \protected\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% +% \protected\def#6% sync +% {\strc_counter_setup_push +% \ifx#2\empty +% \the#5% +% \else +% \let\currentcounter\empty +% \the\everysetupcounter +% \fi +% \strc_counter_setup_pop}% +% \protected\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 +% \ifempty\currentcounter \else +% \edef\p_number{\counterparameter\c!number}% +% \ifempty\p_number \else +% \strc_counters_set\currentcounter\p_number +% \letcounterparameter\c!number\empty +% \fi +% \fi +% \to \everysetupcounter + +\stopcontextdefinitioncode + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-pag.mkxl b/tex/context/base/mkxl/strc-pag.mkxl new file mode 100644 index 000000000..07ac30d26 --- /dev/null +++ b/tex/context/base/mkxl/strc-pag.mkxl @@ -0,0 +1,497 @@ +%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}{} + +\unprotect + +\startcontextdefinitioncode + +% Allocation: + +\ifdefined\realpageno \else \permanent\countdef\realpageno \zerocount \fi \realpageno \plusone +\ifdefined\userpageno \else \permanent\countdef\userpageno \plusone \fi \userpageno \plusone +\ifdefined\subpageno \else \permanent\countdef\subpageno \plustwo \fi \subpageno \plusone % was \zerocount but that doesn't work well with bytext +\ifdefined\arrangeno \else \permanent\countdef\arrangeno \plusthree \fi \arrangeno \zerocount % ! +\ifdefined\pagenoshift \else \permanent\countdef\pagenoshift\plusfour \fi \pagenoshift\zerocount % ! +\ifdefined\lastpageno \else \permanent\countdef\lastpageno \plusfive \fi \lastpageno \zerocount % ! + +\ifdefined\pageno \else \aliased\let\pageno\userpageno \fi + +\def\realfolio{\the\realpageno} +\def\userfolio{\the\userpageno} +\def\subfolio {\the\subpageno } +\def\lastfolio{\the\lastpageno} + +\newtoks\everyinitializepagecounters + +\protected\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 + +\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}} + +\permanent\tolerant\protected\def\setuprealpagenumber[#1]{\strc_pagenumbers_save_state\s!realpage\setupcounter[\s!realpage][#1]\the\everysetuprealpagenumber} +\permanent\tolerant\protected\def\setupuserpagenumber[#1]{\strc_pagenumbers_save_state\s!userpage\setupcounter[\s!userpage][#1]\the\everysetupuserpagenumber} +\permanent\tolerant\protected\def\setupsubpagenumber [#1]{\strc_pagenumbers_save_state\s!subpage \setupcounter[\s!subpage ][#1]\the\everysetupsubpagenumber } + +\permanent\protected\def\resetrealpagenumber {} % not permitted +\permanent\protected\def\resetuserpagenumber {\strc_counters_reset\s!userpage} +\permanent\protected\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 + +\aliased\let\setuppagenumber\setupuserpagenumber +\aliased\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 + +\protected\def\strc_pagenumbers_page_state_push{\setxvalue{\??pagestatestack\c!state}{\namedcounterparameter\s!userpage\c!state}} +\protected\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!start] % was stop but start looks better in logging + +% Counters + +%permanent\def\firstrealpagenumber{\convertedcounter[\s!realpage][\c!type=\v!first]} +%permanent\def\firstuserpagenumber{\convertedcounter[\s!userpage][\c!type=\v!first]} +%permanent\def\firstsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!first]} + +%permanent\def\lastrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!last]} +%permanent\def\lastuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!last]} +%permanent\def\lastsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!last]} + +%permanent\def\prevrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!previous]} +%permanent\def\prevuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!previous]} +%permanent\def\prevsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!previous]} + +%permanent\def\nextrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!next]} +%permanent\def\nextuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!next]} +%permanent\def\nextsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!next]} + +\permanent\def\firstrealpage{\strc_counters_first\s!realpage} +\permanent\def\firstuserpage{\strc_counters_first\s!userpage} +\permanent\def\firstsubpage {\strc_counters_first\s!subpage } + +\permanent\def\prevrealpage {\strc_counters_prev \s!realpage} +\permanent\def\prevuserpage {\strc_counters_prev \s!userpage} +\permanent\def\prevsubpage {\strc_counters_prev \s!subpage } + +\permanent\def\nextrealpage {\strc_counters_next \s!realpage} +\permanent\def\nextuserpage {\strc_counters_next \s!userpage} +\permanent\def\nextsubpage {\strc_counters_next \s!subpage } + +\permanent\def\lastrealpage {\strc_counters_last \s!realpage} +\permanent\def\lastuserpage {\strc_counters_last \s!userpage} +\permanent\def\lastsubpage {\strc_counters_last \s!subpage } + +\aliased\let\firstpage\firstrealpage +\aliased\let\prevpage \prevrealpage +\aliased\let\nextpage \nextrealpage +\aliased\let\lastpage \lastrealpage + +% Compatibility counters: + +\permanent\def\nofrealpages {\lastrealpage} \permanent\def\totalnumberofpages{\lastrealpage} +\permanent\def\nofuserpages {\lastuserpage} \permanent\def\lastpagenumber {\lastuserpage} +\permanent\def\nofsubpages {\lastsubpage } + +% Renderers: + +\permanent\def\pagenumber {\strc_counters_raw\s!userpage} +\permanent\def\prefixedpagenumber {\directconvertedcounter\s!userpage\empty} % \userpagenumber + +\permanent\def\realpagenumber {\directconvertedcounter\s!realpage\empty} +\permanent\def\userpagenumber {\directconvertedcounter\s!userpage\empty} +\permanent\def\subpagenumber {\directconvertedcounter\s!subpage \empty} + +\permanent\def\firstrealpagenumber{\directconvertedcounter\s!realpage\v!first} +\permanent\def\firstuserpagenumber{\directconvertedcounter\s!userpage\v!first} +\permanent\def\firstsubpagenumber {\directconvertedcounter\s!subpage \v!first} + +\permanent\def\lastrealpagenumber {\directconvertedcounter\s!realpage\v!last} +\permanent\def\lastuserpagenumber {\directconvertedcounter\s!userpage\v!last} +\permanent\def\lastsubpagenumber {\directconvertedcounter\s!subpage \v!last} + +\permanent\def\prevrealpagenumber {\directconvertedcounter\s!realpage\v!previous} +\permanent\def\prevuserpagenumber {\directconvertedcounter\s!userpage\v!previous} +\permanent\def\prevsubpagenumber {\directconvertedcounter\s!subpage \v!previous} + +\permanent\def\nextrealpagenumber {\directconvertedcounter\s!realpage\v!next} +\permanent\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next} +\permanent\def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next} + +\protected\def\strc_pagenumbers_decrement_counters % only at the end + {\strc_counters_decrement\s!realpage + \strc_counters_decrement\s!userpage + \strc_counters_decrement\s!subpage} + +\protected\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 + +\permanent\def\realpage{\the\realpageno} +\permanent\def\userpage{\the\userpageno} +\permanent\def\subpage {\the\subpageno} + +% Hooks: + +\permanent\def\currentpage{\the\realpageno}% rather useless + +\appendtoks + \ifnum\realpageno>\lastpage \enforced\glet\lastpage\lastrealpage \fi +\to \everyinitializepagecounters + +% States: + +\newconditional\layoutisdoublesided % already defined: \newif\ifdoublesided +\newconditional\layoutissinglesided % already defined: \newif\ifsinglesided + +% Realpage and subpage numbers: + +\permanent\protected\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax} +\permanent\protected\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax} + +% Page numbers: (can move to lua) ... inconsistent names + +\installcorenamespace{pagenumberinc} +\installcorenamespace{pagenumberdec} + +\protected\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax} +\protected\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax} + +\permanent\protected\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax} +\permanent\protected\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax} + +\protected\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible + +\permanent\protected\def\decrementpagenumber{\csname\??pagenumberdec\namedcounterparameter\s!userpage\c!state\endcsname} +\permanent\protected\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} + +% some day ifsinglesided and ifdoublesided will become obsolete + +\newtoks\everysidedswitch + +\appendtoks + \singlesidedfalse \setfalse\layoutisdoublesided + \doublesidedfalse \setfalse\layoutissinglesided + \resetsystemmode\v!singlesided + \resetsystemmode\v!doublesided + \processallactionsinset + [\directpagenumberingparameter\c!alternative]% + [ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided, + \v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]% + \the\everysidedswitch + \pageduplexmode + \ifsinglesided + \ifdoublesided\plustwo\else\zerocount\fi + \else + \ifdoublesided\plusone\else\zerocount\fi + \fi + \page_backgrounds_recalculate + \strc_pagenumbers_set_location +\to \everysetuppagenumbering + +\appendtoks + \ifdefined\trackingmarginnotestrue + \ifdoublesided + \trackingmarginnotestrue + \else + \trackingmarginnotesfalse + \fi + \fi +\to \everysidedswitch + +\ifdefined \page_backgrounds_recalculate \else + \let\page_backgrounds_recalculate\relax +\fi + +\ifdefined \strc_pagenumbers_set_location \else + \let\strc_pagenumbers_set_location\relax +\fi + +\protected\def\strc_pagenumbers_flush_final_page + {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}% + \ifempty\p_strc_pagenumbers_page \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: + +\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\placepagenumber + {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo + \ifnum\c_strc_pagenumbers_state=\plusone + \labeltexts\v!pagenumber\pagenumber + \fi + \fi} + +\permanent\protected\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 + +\protected\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 + #2\ifx\m_strc_pagenumbers_state_new\v!start\plustwo\else\zerocount\fi + \fi} + +\appendtoks % todo: set state: none, start, stop, reset + \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage +\to \everysetuprealpagenumber + +\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}% + \ifempty\askeduserpagenumber \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}% + \ifempty\askedsubpagenumber \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 + +\protected\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/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx new file mode 100644 index 000000000..e25cb49f1 --- /dev/null +++ b/tex/context/base/mkxl/strc-ref.mklx @@ -0,0 +1,2193 @@ +%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}{} +\registerctxluafile{strc-ref}{} +\registerctxluafile{node-ref}{optimize} + +\unprotect + +% 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 the core +%D features, although at a first glance probably nobody will notice. This is good, +%D because referencing should be as hidden as possible. +%D +%D Before we start implementing functionality we provide a way to set up this +%D mechanism. +%D +%D \showsetup{setupreferencing} +%D +%D In interactive documents verbose references don't always make sense (what is a +%D page number in an unnumbered document). By setting the \type{interaction} +%D variable, one can influences the way interactive references are set. + +\let\referenceprefix\empty + +\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 + +\permanent\protected\def\showreferences{\enabletrackers[nodes.references.show,nodes.destinations.show]} + +%D These are implemented in a low level form as: + +\permanent\tolerant\protected\def\textreference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}} +\permanent\tolerant\protected\def\pagereference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}} +\permanent\tolerant\protected\def\reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}} +\permanent\tolerant\protected\def\setreference [#labels]#spacer[#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}} + +\permanent\protected\def\dosetdirectpagereference#1{\strc_references_set_named_reference\s!page{#1}{}{}} % low level, maybe use _ + +\permanent\protected\def\usereferenceparameter#1% faster local variant + {\edef\m_strc_references_asked{#1\c!reference}% + \ifempty\m_strc_references_asked\else + \dosetdirectpagereference\m_strc_references_asked + \fi} + +%D Actually there is not much difference between a text and a full reference, but +%D it's the concept that counts. The low level implementation is: + +\newcount\lastreferenceattribute +\newcount\lastdestinationattribute + +\def\strc_references_finish#prefix#reference#internal% gets expanded anyway + {\normalexpanded{\clf_deferredenhancereference{#prefix}{#reference}}} + +\permanent\let\dofinishreference\strc_references_finish % used at lua end + +%D This is somewhat tricky: we want to keep the reference with the following word but +%D that word should also hyphenate. We need to find a better way. + +% 0 = nothing +% 1 = bind to following word + +\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} + + +\protected\def\strc_references_set_named_reference + {\ifreferencing + \expandafter\strc_references_set_named_reference_indeed + \else + \expandafter\gobblefourarguments + \fi} + +\newbox\b_strc_destination_nodes + +\protected\def\strc_references_flush_destination_nodes + {\ifvoid\b_strc_destination_nodes \else + \unhbox\b_strc_destination_nodes + \fi} + +\def\strc_references_placeholder + {\ifempty\dotaggedplaceholder\else + \c_attr_destination\lastdestinationattribute + \dotaggedplaceholder + \fi} + +\protected\def\strc_references_destination_point_yes + {\strc_references_inject_before % new + \dostarttagged\t!reference\empty + \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup + \strc_references_flush_destination_nodes + \strc_references_placeholder + \egroup + \dostoptagged + \strc_references_inject_after} + +\protected\def\strc_references_destination_point_nop + {\strc_references_inject_before % new + \dostarttagged\t!reference\empty + \dontleavehmode\hbox \bgroup + \strc_references_flush_destination_nodes + \strc_references_placeholder + \egroup + \dostoptagged + \strc_references_inject_after} + +\protected\def\strc_references_start_destination_nodes % messy but we need the delay + {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute + +\protected\def\strc_references_stop_destination_nodes + {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}} + +\protected\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} + \ifempty\currentreferencelabels + \lastdestinationattribute\attributeunsetvalue + \else + \ifx\currentreferenceexpansion\s!xml + \xmlstartraw + \xdef\currentreferencedata{#text}% data, no text else conflict + \xmlstopraw + \glet\currentreferencecoding\s!xml + \else + \ifx\currentreferenceexpansion\v!yes + \xdef\currentreferencedata{#text}% + \else + \xdef\currentreferencedata{\detokenize{#text}}% + \fi + \glet\currentreferencecoding\s!tex + \fi + % beware, the structures.references.set writes a + \setnextinternalreference + \strc_references_start_destination_nodes + \clf_setdestinationattribute + {% + references {% + internal \locationcount + % block {\currentsectionblock}% + view {\interactionparameter\c!focus}% + \ifempty\referenceprefix\else + prefix {\referenceprefix}% + \fi + reference {\currentreferencelabels}% + }% + metadata {% + kind {\currentreferencekind}% + \ifx\currentreferencekind\s!page\else + \ifx\currentreferencecoding\s!xml + xmlroot {\xmldocument}% + \fi + catcodes \catcodetable + \fi + }% + \ifempty\currentreferencedata\else + entries {% + text {\currentreferencedata}% + }% + \fi + \ifempty\currentreferenceuserdata\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_destination_point_yes + \orelse\ifvoid\b_strc_destination_nodes\else + \strc_references_destination_point_nop + \fi} + +\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable + {\ifreferencing + \edef\currentreferencelabels{#labels}% + \ifempty\currentreferencelabels + \setbox\b_strc_destination_nodes\emptyhbox + \lastdestinationattribute\attributeunsetvalue + \else + \strc_references_start_destination_nodes + \setnextinternalreference + \clf_setdestinationattribute + {% + references {% + internal \locationcount + % block {\currentsectionblock}% + view {\interactionparameter\c!focus}% + \ifempty\referenceprefix\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} + +\protected\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 \locationcount + % block {\currentsectionblock}% + view {\interactionparameter\c!focus}% + \ifempty\referenceprefix\else + prefix {\referenceprefix}% + \fi + reference {#labels}% + }% + metadata {% + kind {\s!full}% + }% + \ifempty\m_strc_references_text \else + entries {% + text {\m_strc_references_text}% + }% + \fi + \ifempty\m_strc_references_user \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_destination_point_yes + \orelse\ifvoid\b_strc_destination_nodes\else + \strc_references_destination_point_nop + \fi} + +\protected\def\strc_references_direct_full + {\strc_references_direct_full_user\empty} + +\permanent\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. + +\permanent\protected\def\boxreference[#1]% + {\begingroup + \dowithnextbox + {\strc_references_set_page_only_destination_attribute{#1}% + \hpack % \hbox + \ifnum\lastdestinationattribute=\attributeunsetvalue\else attr \destinationattribute \lastdestinationattribute \fi + {\box\b_strc_destination_nodes\box\nextbox}% + \endgroup}} + +\permanent\protected\def\hboxreference[#1]{\boxreference[#1]\hbox} +\permanent\protected\def\vboxreference[#1]{\boxreference[#1]\vbox} + +% \ifx\currentdestinationattribute\empty +% \begingroup\c_attr_destination\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}% + \ifempty\referenceprefix\else + prefix {\referenceprefix}% + \fi + reference {#label}% + internal \locationcount + }% + 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 \locationcount + }% + 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 + +\permanent\tolerant\protected\def\contentreference[#1]#*[#2]% + {\ifarguments + \expandafter\gobbletwoarguments + \or + \expandafter\strc_references_content_pickup_nop + \else + \expandafter\strc_references_content_pickup_yes + \fi{#1}{#2}} + +\def\strc_references_content_pickup_yes#1#2% + {\hbox\bgroup\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox} + +\def\strc_references_content_pickup_nop#1#2% + {\hbox\bgroup\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\hpack + {\framed[\c!frame=\v!off,#2]{\box\nextbox}}% + \strc_references_set_simple_reference{#1}% + \setbox\nextbox\hpack attr \destinationattribute \currentdestinationattribute % \hpack ? + {\strc_references_flush_destination_nodes + \box\nextbox}% + \setbox\nextbox\hpack{\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}% + \hpack attr \destinationattribute \currentdestinationattribute % \hpack ? + {\strc_references_flush_destination_nodes + \box\nextbox}% + \egroup} + +%D \macros +%D {everyreference} +%D +%D For rather tricky purposes, one can assign sanitizing macros to \type +%D {\everyreference} (no longer that relevant). + +\newevery \everyreference \relax + +%D This is really needed, since for instance Polish has a different alphabet and +%D needs accented entries in registers. + +\appendtoks + \cleanupfeatures +\to \everyreference + +%D We did not yet discuss prefixing. Especially in interactive documents, it's not +%D always easy to keep track of duplicate references. The prefix mechanism, which we +%D will describe later on, solves this problem. By (automatically) adding a prefix +%D one keeps references local, but the global ones in view. To enable this feature, +%D we explictly split the prefix from the reference. + +\let\referenceprefix\empty + +%D For a long time the only way to access an external file was to use the file +%D prefix (\type {somefile::}. However, when you split up a document, redefining the +%D references may be such a pain, that another approach is feasible. By setting the +%D \type {autofile} variable to \type {yes} or \type {page}, you can access the +%D reference directly. +%D +%D \starttabulate[||||] +%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR +%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 + +\permanent\protected\def\usereferences[#filename]{} % obsolete + +%D As mentioned we will also use the cross reference mechanism for navigational +%D purposes. The main reason for this is that we want to treat both categories +%D alike: +%D +%D \starttyping +%D \goto{go back}[PreviousJump] +%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 from a file. The pure +%D navigational ones don't need to be written to file, but both for fast processing +%D and transparant integration, they are saved internally as a sort of reference. We +%D can easily distinguish such system references from real cross reference ones by +%D their tag. +%D +%D We also use the odd/even characteristic to determine the 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) or pagenumbers +%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In +%D interactive documents we also have \type {\goto}, \type {\button} and alike. +%D These are more versatile and look like: +%D +%D \starttyping +%D \goto[reference] +%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 are references to a +%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT. +%D The last example shows that we can pass arguments to the actions. +%D +%D Now we've come to the testing step. As we can see below, this macro does bit more +%D than testing: it also resolves the reference. This means that whenever we test +%D for the existance of a reference at an outer level, we have all the relevant +%D properties of that reference avaliable inside the true branche~(\type {#2}). +%D +%D The prefix has to do with localizing references. When a prefix is set, looking +%D for a reference comes to looking for the prefixed one, and when not found, +%D looking for the non prefixed one. Consider for instance the prefix set to \type +%D {sidetrack}. +%D +%D \starttyping +%D \pagereference[important] +%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 the pagenumber +%D associated to this reference. But when we call for \type{important}, while the +%D prefix is still set, we will get the pagenumber bound to the prefixed one. +%D +%D {\em Some day, when processing time and memory are no longer +%D performance factors, we will introduce multi||level +%D prefixes.} +%D +%D Before we start analyzing, I introduce a general 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 true. + +\permanent\tolerant\protected\def\definereference[#name]#spacer[#specification]% + {\clf_definereference{\referenceprefix}{#name}{\detokenize{#specification}}} + +\permanent\protected\def\resetreference[#name]% + {\clf_resetreference{\referenceprefix}{#name}} + +\permanent\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 we only provide the +%D hooks. + +%D \macros +%D {highlighthyperlinks} +%D +%D The next switch can be used to make user hyperlinks are not highlighted when +%D clicked on. + +\newconditional\highlighthyperlinks \settrue\highlighthyperlinks + +%D \macros +%D {gotonewwindow} +%D +%D To make the {\em goto previous jump} feature more convenient when using more than +%D one file, it makes sense to force the viewer to open a new window for each file +%D opened. + +\newconditional\gotonewwindow \setfalse\gotonewwindow + +\permanent\def\expandtexincurrentreference % will happen in lua some time + {\ifcase\referencehastexstate\else\clf_expandcurrentreference\fi} + +\permanent\def\expandreferenceoperation#tag#content{\clf_setreferenceoperation#tag{#content}} +\permanent\def\expandreferencearguments#tag#content{\clf_setreferencearguments#tag{#content}} + +\permanent\def\doifelsereferencefound#label#yes#nop% + {\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% + {\expandtexincurrentreference + #yes}% + {#nop}} + +\aliased\let\doifreferencefoundelse\doifelsereferencefound + +%D The tester only splits the reference in components but does not look into them. +%D The following macro does a preroll and determines for instance the current real +%D reference pagenumber. The \type {\currentrealreference} macro does the same so +%D unless one wants to use the pagestate the next macro seldom needs to be called. +%D +%D The inner case is simple. Only two cases have to be taken +%D care of: +%D +%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 tolerant, depending on +%D 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 file and, when +%D enabled, in the left margin of the text. + +\let\unknownreference\gobbleoneargument + +%D When a reference is not found, we typeset a placeholder (two glyphs are often +%D enough to represent the reference text). + +\def\dummyreference{{\tttf ??}} +\def\emptyreference{{\tttf !!}} + +\installtextracker + {structures.referencing.show} + {\let\strc_references_dummy\strc_references_dummy_yes} + {\let\strc_references_dummy\strc_references_dummy_nop} + +\def\strc_references_dummy_nop + {\dummyreference} + +\def\strc_references_dummy_yes + {\dummyreference + \margindata + [\referencingparameter\c!labelalternative]% alternative? + [\c!style=\referencingparameter\c!labelstyle, + \c!color=\referencingparameter\c!labelcolor] + {\askedreference}} + +\let\strc_references_dummy\strc_references_dummy_nop + +\setupreferencing + [\c!labelalternative=\v!inleft, + \c!labelcolor=darkred, + \c!labelstyle=\smallinfofont] + +%D To prevent repetitive messages concerning a reference being defined, we set such +%D an unknown reference to an empty one after the first encounter. +%D +%D Apart from cross references supplied by the user, \CONTEXT\ generates cross +%D references itself. Most of them are not saved as a reference, but stored with +%D their source, for instance a list or an index entry. Such automatically +%D generated, for the user invisible, references are called {\em internal +%D references}. The user supplied ones are labeled as {\em external references}. +%D +%D A second important characteristic is that when we want to support different +%D backends (viewers), we need to support named destinations as well as page +%D numbers. I invite readers to take a glance at the special driver modules to +%D understand the fine points of this. As a result we will deal with {\em locations} +%D as well as {\em real page numbers}. We explictly call this pagenumber a real one, +%D because it is independant of the page numbering scheme used in the document. +%D +%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to +%D support sophisticated interactive \PDF\ files, lays in the mere fact that real +%D page numbers are available in most two pass data, like references, list data and +%D index entries. +%D +%D We will speak of \type {thisis...} when we are marking a location, and +%D \type {goto...} when we point to such a location. The latter one can be seen as a +%D hyperlink to the former one. In the next macros one we use constructs like: +%D +%D \starttyping +%D \dostart... +%D \dostop... +%D \stoptyping +%D +%D The flag \type {\iflocation} signals if we're in interactive mode. + +\ifdefined\buttonheight \else \newdimen\buttonheight \fi +\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi + +%D Internal references can best be set using the next few macros. Setting such +%D references to unique values is completely up to the macros that call them. +%D +%D \starttyping +%D \thisissomeinternal{tag}{identifier} +%D \gotosomeinternal {tag}{identifier}{pagenumber}{text} +%D \stoptyping +%D +%D We could do this in \LUA\ \unknown + +\newif \iflocation +\newcount\locationcount +\newcount\locationorder +\newbox \locationbox + +\permanent\def\nextinternalreference {\the\locationcount} +\permanent\def\nextinternalorderreference{\the\locationorder} + +\permanent\def\setnextinternalreference + {\global\advance\locationcount\plusone} + +\permanent\def\setnextinternalreferences#kind#name% plural + {\clf_setnextinternalreference{#kind}{#name}} + +\permanent\def\getinternalorderreference#kind#name% + {\clf_currentreferenceorder{#kind}{#name}} + +\permanent\def\thisissomeinternal#kind#name% only for old time sake, will go away + {\begingroup + \clf_setinternalreference + reference {#kind:#name}% no view + \relax + \hpack attr \destinationattribute\lastdestinationattribute{}% + \endgroup} + +\installcorenamespace{savedinternalreference} + +\letvalue{\??savedinternalreference\s!default}\!!zerocount + +\permanent\protected\def\storeinternalreference#1#2% + {\xdefcsname\??savedinternalreference\currentstructurename\endcsname{\number#2}} + +\newconditional\preferpagereferences + +\permanent\def\gotosomeinternal#kind#name#target#text% + {\ifconditional\preferpagereferences + \directgoto{#text}[page(#target)]% + \else + \directgoto{#text}[#kind:#name]% + \fi} + +\permanent\def\gotonextinternal#text#target% + {\directgoto{#text}[internal(#target)]} + +%D In this module we define three system references: one for handling navigational, +%D viewer specific, commands, another for jumping to special pages, like the first +%D or last one, and a third reference for linking tree like lists, like tables of +%D contents. The latter two adapt themselves to the current state. +%D +%D An example of an action is: +%D +%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 +%D One can also activate an automatic prefix mechanism. By setting the +%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to +%D \type {-} or empty, the prefix is reset. Other values become the prefix. + +\newcount\prefixcounter + +\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 + +\permanent\protected\def\setupglobalreferenceprefix[#prefix]% + {\xdef\referenceprefix{#prefix}} + +\permanent\protected\def\globalpushreferenceprefix#prefix% + {\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}} + +\permanent\protected\def\globalpopreferenceprefix + {\xdef\referenceprefix{\clf_popreferenceprefix}} + +\permanent\protected\def\pushreferenceprefix#prefix% + {\edef\referenceprefix{\clf_pushreferenceprefix{#prefix}}} + +\permanent\protected\def\popreferenceprefix + {\edef\referenceprefix{\clf_popreferenceprefix}} + +\def\m_strc_references_prefix_yes{+} +\def\m_strc_references_prefix_nop{-} + +\permanent\protected\def\setupreferenceprefix[#prefix]% + {\edef\p_prefix{#prefix}% + \ifempty\p_prefix + \let\referenceprefix\empty + \orelse\ifx\p_prefix\m_strc_references_prefix_yes + \letreferencingparameter\c!prefix\s!unknown + \global\advance\prefixcounter\plusone + \edef\referenceprefix{\the\prefixcounter}% + \orelse\ifx\p_prefix\m_strc_references_prefix_nop + \letreferencingparameter\c!prefix\s!unknown + \let\referenceprefix\empty + \orelse\ifx\p_prefix\s!unknown + % forget about it + \else + \let\referenceprefix\p_prefix + \fi} + +\appendtoks + \setupreferenceprefix[\referencingparameter\c!prefix] +\to \everysetupreferencing + +%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and +%D goto specific locations using \type {\goto}. The last one does not make that much +%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an +%D \type {\in} but fortunately that one only makes sense in math mode. +%D +%D Typesetting the reference is a bit more complicated than one would at first sight +%D expect. This is due to the fact that we distinguish three (five) alternative +%D calls: +%D +%D \placefigure +%D [here][three calls] +%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 document meant for paper, +%D one is tempted to use the last (most straightforward) alternative. When a +%D document is also meant voor electronic distribution, the former alternatives have +%D preference, because everything between the \type {\in} and~\type {[} becomes +%D active (and when asked for, typeset in a different color and typeface). + +\appendtoks + \ifdefined\in \let\normalmathin \in \protected\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi + \ifdefined\at \let\normalmathat \at \protected\def\at {\mathortext\normalmathat \strc_references_at } \else \let\at \strc_references_at \fi + \ifdefined\about \let\normalmathabout\about \protected\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi + \ifdefined\from \let\normalmathfrom \from \protected\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from \fi + \ifdefined\over \let\normalmathover \over \protected\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi +\to \everydump + +\permanent \def\filterreference #key{\clf_filterreference{#key}} % no checking, expandable +\permanent\protected\def\getreferenceentry#key{\clf_filterreference{#key}} % no checking, not expandable + +\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 using \type {\ref}. + +\permanent\tolerant\protected\def\getreference[#key]#spacer[#label]% #key = number page title text default realpage ... + {\ifarguments\or + \strc_references_dummy + \else + \doifelsereferencefound{#label}{\clf_filterreference{#key}}\strc_references_dummy + \fi} + +\aliased\let\ref\getreference + +%D Special cases: + +\protected\def\strc_references_about[#label]% + {\dontleavehmode + \begingroup + \enforced\let\crlf\space + \enforced\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 representation of +%D references. A symbol reference does not show the specific data, like the number +%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$ +%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to +%D go. +%D +%D \starttyping +%D ... \somewhere{backward text}{forward text}[someref] ... +%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] + +\permanent\def\referencepagestate + {\numexpr\clf_referencepagestate + {rst::\number\nofreferencestates}% + \relax} + +\permanent\def\referencepagedetail + {\numexpr\clf_referencepagedetail + {rst::\number\nofreferencestates}% + true % + \ifconditional\pagestatespread false\ifdoublesided true\else false\fi\fi + \relax} + +\permanent\def\referencerealpage {\clf_referencerealpage} % todo: no need for wrapping +\permanent\def\referencecolumnnumber{\clf_referencecolumn} % todo: no need for wrapping + +% So we need : instead of \ but that's only lmtx: +% +% \def\referencecolumnnumber +% {\numexpr\dimexpr\clf_referenceposx-\cutspace\relax:\dimexpr\makeupwidth/\nofcolumns\relax+\plusone\relax} +% +% Tacos patch of the older one, kept here as illustration +% +% \def\referencecolumnnumber +% {\numexpr +% \dimexpr\clf_referenceposx-\cutspace-\makeupwidth/(2*\nofcolumns)\relax +% /\dimexpr \makeupwidth/ \nofcolumns \relax +% +\plusone +% \relax} + + +\permanent\protected\def\tracedpagestate + {{\blue\tttf(\ifcase\referencepagedetail unknown\or same\or previous\or next\or above\or below\else unknown\fi)}} + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\referencesymbol + {\hpack\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. + +\permanent\protected\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}}% + +\permanent\protected\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}} + +\permanent\protected\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\strc_references_dummy}[#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! +% +% \protected\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}} +% +% \protected\def\conditionalat {\strc_references_conditional\at} +% \protected\def\conditionalin {\strc_references_conditional\in} +% \protected\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 + +\permanent\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 + +\permanent\let\rightofreferencecontent\empty +\permanent\let\leftofreference \empty +\permanent\let\rightofreference \empty + +\permanent\protected\def\leftofreferencecontent + {\removeunwantedspaces + \nonbreakablespace + \ignorespaces} + +\installcorenamespace{referencinginteraction} + +\def\strc_references_interaction_all + {\the\leftreferencetoks + \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing + \leftofreference + \doifelsesometoks\leftreferencetoks\onlynonbreakablespace\relax % new, replace space by nonbreakable if present + \currentreferencecontent + \rightofreference + \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing + \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 + {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname + \expandafter\lastnamedcs + \else + \expandafter\strc_references_interaction_all + \fi} + +\newtoks\everyresetinatreference + +\appendtoks + \enforced\glet\leftofreference \relax + \enforced\glet\rightofreference\relax +\to \everyresetinatreference + +\def\strc_references_start_goto + {\dontleavehmode + \begingroup} + +\def\strc_references_stop_goto + {\the\everyresetinatreference + \endgroup} + +% NEEDS TESTING: + +\tolerant\def\strc_references_pickup_goto#=#=#:#*[#3]% + {\leftreferencetoks + \ifparameter#1\or + {#1}% + \else + \defaultleftreferencetoks + \enforced\let\leftofreferencecontent\empty + \fi + \rightreferencetoks + \ifparameter#2\or + {#2}% + \else + \defaultrightreferencetoks + \enforced\let\rightofreferencecontent\empty + \fi + % inefficient: double resolve + \doifelsereferencefound{#3} % we need to resolve the text + {\goto{\referencesequence}[#3]} + {\let\currentreferencecontent\strc_references_dummy + \goto{\referencesequence}[#3]}% + \strc_references_stop_goto} + +\protected\def\strc_references_in + {\strc_references_start_goto + \let\currentreferencecontent\currentreferencedefault + \strc_references_pickup_goto} + +\protected\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 Hoekwater. They can +%D be used for predefining reference 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 be defined with \type +%D {\setuplabeltext}. +%D +%D Watch out: the second argument is somewhat special and mostly meant for a suffix +%D to a number: +%D +%D \startbuffer +%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] +%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=] + +\protected\def\strc_references_apply_format#name% + {\strc_references_start_goto + \edef\currentreferenceformat{#name}% + \enforced\gdef\leftofreference {\referenceformatparameter\c!left }% + \enforced\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 + \ifempty\currentstyleparameter \else + \resetinteractionparameter\c!style + \fi + \ifempty\currentcolorparameter \else + \resetinteractionparameter\c!contrastcolor + \resetinteractionparameter\c!color + \fi + \ifx\currentreferenceformatlabel\autoreferencelabeltextflag + \edef\currentreferenceformatlabel{\autoreferencelabeltext}% + \fi + \ifx\currentreferenceformatautocase\v!yes + \setcharactercleaning[1]% + \fi + \ifempty\currentreferenceformatlabel + \defaultleftreferencetoks {\referenceformatparameter\c!text}% + \defaultrightreferencetoks\emptytoks + \else + \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}% + \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}% + \fi + \ifempty\currentreferenceformattype + \def\currentreferenceformattype{default}% + \fi + % + \ifempty\currentreferenceformatsetups + \def\currentreferencecontent{\filterreference\currentreferenceformattype}% + \else + \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}% + \fi + % + \enforced\let\leftofreferencecontent \empty + \enforced\let\rightofreferencecontent\empty + \strc_references_pickup_goto} + +\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key + +\permanent\protected\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 bound to cross +%D references. The \type {\goto} commands can be used to let users access another +%D part of the document. In this respect, interactive tables of contents and +%D registers can be considered goto's. Because in fact a \type {\goto} is just a +%D reference without reference specific data, the previous macros are implemented +%D using the goto functionality. +%D +%D \showsetup{goto} +%D +%D One important characteristic is that the first argument of \type {\goto} (and +%D therefore \type {\at} and \type {\in} is split at spaces. This means that, +%D although hyphenation is prevented, long references can cross line endings. + +% \starttext +% \setupinteraction[state=start] +% [\goto{state}[file(mk-last-state)]] +% [\goto{state} [file(mk-last-state)]] +% \stoptext + +\newconditional\uselocationstrut \settrue\uselocationstrut + +\permanent\def\extrareferencearguments + {highlight \luaconditional\highlighthyperlinks\space + newwindow \luaconditional\gotonewwindow\space + layer {\currentviewerlayer}} + +\permanent\protected\def\directgoto + {\ifconditional\uselocationstrut + \expandafter\strc_references_direct_goto + \else + \expandafter\strc_references_direct_goto_htdp + \fi} + +\permanent\protected\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 + +\permanent\def\revivesavedreferenceattribute % sometimes handy as no test etc needed + {\c_attr_reference\lastsavedreferenceattribute} + +\def\strc_references_direct_goto#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \c_attr_reference\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 + \c_attr_reference\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 + \c_attr_reference\attributeunsetvalue + \iflocation + \clf_injectreference + {\referenceprefix}% + {#label}% + {% + height \dimexpr\interactionparameter\c!height\relax + depth \dimexpr\interactionparameter\c!depth \relax + \extrareferencearguments + }% + \relax + \setlocationattributes + \c_attr_reference\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 + \c_attr_reference\attributeunsetvalue + \iflocation + \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% + {\expandtexincurrentreference + \clf_injectcurrentreferencehtdp + \ht\strutbox + \dp\strutbox + \relax + \setlocationattributes + \setstrut % can be option + \global\lastsavedreferenceattribute\lastreferenceattribute + \c_attr_reference\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 + \c_attr_reference\attributeunsetvalue + \iflocation + \setstrut % can be option + \strc_references_get_simple_reference{#internal}% + \global\lastsavedreferenceattribute\currentreferenceattribute + \c_attr_reference\currentreferenceattribute + \setlocationattributes + \dostarttagged\t!link\empty + #content% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\permanent\protected\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} + +\permanent\protected\def\strc_references_start_goto_nop + {\let\stopgoto\strc_references_stop_goto_nop} + +\permanent\protected\def\strc_references_stop_goto_nop + {\endgroup} + +\protected\def\strc_references_start_goto_yes + {\expandtexincurrentreference + \clf_injectcurrentreferencehtdp + \ht\strutbox + \dp\strutbox + \relax + \setlocationattributes + \setstrut % can be option + \global\lastsavedreferenceattribute\lastreferenceattribute + \c_attr_reference\lastreferenceattribute + \dostarttagged\t!link\empty + \let\stopgoto\strc_references_stop_goto_yes} + +\protected\def\strc_references_stop_goto_yes + {\dostoptagged + \endgroup} + +\def\strc_references_goto_htdp#content#dummy[#label]% dummy gobbles spaces + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\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 + \c_attr_reference\lastreferenceattribute + \dostarttagged\t!link\empty + #content% + \dostoptagged}% + {#content}% + \else + #content% + \fi + \endgroup} + +\permanent\protected\def\directgotobox#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\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} + +\permanent\protected\def\directgotospecbox#resolver#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\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} + +\permanent\protected\def\directgotodumbbox#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\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} + +\permanent\protected\def\gotobox#content[#label]% + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\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} + +\permanent\protected\def\gotowdhtbox#width#height[#label]% fast variant for overlays + {\dontleavehmode + \begingroup + \setbox\scratchbox\emptyhbox + \wd\scratchbox#width% + \ht\scratchbox#height% + \global\lastsavedreferenceattribute\attributeunsetvalue + \c_attr_reference\attributeunsetvalue + \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% + {\clf_injectcurrentreference + \global\lastsavedreferenceattribute\lastreferenceattribute + \hpack attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} + {\box\scratchbox}% + \endgroup} + +%D An reference to another document can be specified as a file or as an \URL. Both +%D are handled by the same mechanism and can be issued by saying something like: +%D +%D \starttyping +%D \goto[dictionary::the letter a] +%D \stoptyping +%D +%D One can imagine that many references to such a dictionary are made, so in most +%D cases such a document reference in an 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 care of loading the +%D 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 specified. This is logical +%D when one keeps in mind that a valid \URL\ can also be a mail address. + +\permanent\tolerant\protected\def\useurl[#label]#spacer[#url]#spacer[#file]#spacer[#description]% + {\clf_useurl{#label}{\detokenize{#url}}{\detokenize{#file}}{\detokenize{#description}}} + +\permanent\tolerant\protected\def\usefile[#label]#spacer[#file]#spacer[#description]% + {\clf_usefile{#label}{\detokenize{#file}}{\detokenize{#description}}} + +\aliased\let\useURL \useurl +\aliased\let\useexternaldocument\usefile + +\permanent\def\doifelseurldefined #label{\clf_doifelseurldefined {#label}} % todo: no wrap +\permanent\def\doifelsefiledefined#label{\clf_doifelsefiledefined{#label}} % todo: no wrap + +\aliased\let\doifurldefinedelse \doifelseurldefined +\aliased\let\doiffiledefinedelse\doifelsefiledefined + +%D \macros +%D {url,setupurl} +%D +%D We also have: \type {\url} for directly calling the description. So we can say: +%D +%D \starttyping +%D \useURL [one] [http://www.test.nl] +%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=] + +\permanent\protected\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 \URL's break ok, according +%D 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 also specify a suitable +%D name (the last argument). This name can be called upon with: +%D +%D \showsetup{from} +%D +%D We keep this for compatibility reasons, hence the hackery. + +\permanent\tolerant\protected\def\strc_references_from[#label]% + {\dontleavehmode + \goto{\clf_from{#label}}[fileorurl(#label)]} + +\permanent\def\dofromurldescription#content% called at the lua end + {#content} + +\permanent\def\dofromurlliteral#content% called at the lua end + {\useurlstyleandcolor\c!style\c!color + \hyphenatedurl{#content}} + +\aliased\let\dofromfiledescription\dofromurldescription +\aliased\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, very system dependant +%D references are implemented by abusing 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} + +\permanent\tolerant\protected\def\defineprogram[#name]#spacer[#program]#spacer[#description]% + {\clf_defineprogram{#name}{#program}{#description}} + +\permanent\protected\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 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. When documenting and +%D sanitizing the original reference macros, I decided to keep the present meaning +%D as well as to make this meaning available as a special reference method. So now +%D one can use: +%D +%D \starttyping +%D \gotopage{some text}[location] +%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} + +\permanent\tolerant\protected\def\definepage[#name]#spacer[#target]% + {\definereference[#name][page(#target)]} + +\permanent\protected\def\gotopage#text[#target]% + {\goto{#text}[\v!page(#target)]} + +%D The previous definitions are somewhat obsolete so we don't 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 references: +%D +%D \starttyping +%D \goto{print version}[print::chapter] +%D \stoptyping +%D +%D and alike. The title placement definition macros have a key \type {file}, which +%D is interpreted as the file to jump to, that is, when one clicks on the title. + +\permanent\tolerant\protected\def\coupledocument[#name]#spacer[#file]#spacer[#sections]#spacer[#description]% + {} % this will be done differently (when it's needed) + +%D \macros +%D {dotextprefix} +%D +%D In previous macros we used \type {\dotextprefix} to generate a space between +%D a label and a number. +%D +%D \starttyping +%D \dotextprefix{text} +%D \stoptyping +%D +%D Only when \type {text} is not empty, a space is inserted. + +\permanent\protected\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}% + \ifempty\p_separator \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 used here and that +%D concern the way the pagenumbers refered 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} + +\permanent\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}% + }} + +\permanent\tolerant\protected\def\setupreferencestructureprefix[#kind]#spacer[#category]#spacer[#settings]% + {\ifarguments\or\or + \getparameters[\??referencingprefix:#kind][#category]% + \else + \getparameters[\??referencingprefix#kind:#category][#settings]% + \fi} + +\def\referencestructureprefixparameter#kind#name#category#parameter% + {\ifcsname\??referencingprefix#name:#category#parameter\endcsname + \lastnamedcs + \orelse\ifcsname\??referencingprefix#kind:#category#parameter\endcsname + \lastnamedcs + \orelse\ifcsname\??referencingprefix:#category#parameter\endcsname + \lastnamedcs + \fi} + +\permanent\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 + +\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/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl new file mode 100644 index 000000000..f44819bc1 --- /dev/null +++ b/tex/context/base/mkxl/strc-reg.mkxl @@ -0,0 +1,1211 @@ +%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}{} + +\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 + +\aliased\let\strc_registers_setup_saved\setupregister + +% maybe we should drop the plural form + +\permanent\tolerant\protected\overloaded\def\setupregister[#1]#*[#2]#*[#3]% + {\ifarguments\or + \strc_registers_setup_saved[#1]% + \or + \strc_registers_setup_saved[#1][#2]% + \or + \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}% + \processcommalist[#2]\strc_registers_setup_step + \fi} + +\permanent\tolerant\protected\def\setupregisters[#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!check=\v!yes, % check for weird see usage + %\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!define=\v!no, + \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 \protected\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}]}% + \frozen\instance\setuevalue{\currentregister}{\strc_registers_insert_entry[\currentregister]}% + \frozen\instance\setuevalue{\e!see\currentregister}{\strc_registers_insert_see[\currentregister]}% + %frozen\instance\setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}% + % historic ballast + \frozen\instance\setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}% + \frozen\instance\setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}% + \frozen\instance\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: + +\glet\currentregistername \empty +\glet\currentregisternumber\!!zerocount + +\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 + \glet\currentregistercoding\s!xml} + +\def\strc_registers_register_page_expand_yes_entries + {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% + \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% + \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% + \glet\currentregistercoding\s!tex} + +\def\strc_registers_register_page_expand_nop_entries + {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}% + \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}% + \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}% + \glet\currentregistercoding\s!tex} + +\def\strc_registers_register_page_expand_xml + {\xmlstartraw + \xdef\currentregisterentries{\registerparameter\c!entries}% + \xmlstopraw + \glet\currentregistercoding\s!xml} + +\def\strc_registers_register_page_expand_yes + {\xdef\currentregisterentries{\registerparameter\c!entries}% + \glet\currentregistercoding\s!tex} + +\def\strc_registers_register_page_expand_nop + {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% + \glet\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}% + \ifempty\currentregisterentries + \ifx\currentregisterexpansion\s!xml + \strc_registers_register_page_expand_xml_entries + \orelse\ifx\currentregisterexpansion\v!yes + \strc_registers_register_page_expand_yes_entries + \else + \strc_registers_register_page_expand_nop_entries + \fi + \else + \ifx\currentregisterexpansion\s!xml + \strc_registers_register_page_expand_xml + \orelse\ifx\currentregisterexpansion\v!yes + \strc_registers_register_page_expand_yes + \else + \strc_registers_register_page_expand_nop + \fi + \fi + \ifempty\currentregisterkeys + \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 + \glet\currentregistername\currentregister + \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 + \ifempty\currentregisterxmlsetup \else + xmlsetup {\currentregisterxmlsetup}% + \fi + }% + references {% + \ifempty\currentregisterlabel \else + label {\currentregisterlabel}% + \fi +% view {\interactionparameter\c!focus}% + }% + entries {% + % we need a special one for xml, this is just a single one + \ifempty\currentregisterentries + entries { + {\currentregisterentriesa}% + {\currentregisterentriesb}% + {\currentregisterentriesc}% + } + \else + entry {\currentregisterentries}% + \fi + \ifempty\currentregisterkeys + keys { + {\currentregisterkeysa}% + {\currentregisterkeysb}% + {\currentregisterkeysc}% + } + \else + key {\currentregisterkeys}% + \fi + }% + userdata {\detokenize\expandafter{\normalexpanded{#3}}} + }% + \clf_setinternalreference + internal \locationcount + view {\interactionparameter\c!focus}% + \relax % this will change + \ifx\currentregisterownnumber\v!yes + \glet\currentregistersynchronize\relax + \else + \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\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 + \c_attr_destination\lastdestinationattribute + \signalcharacter % no \strut as it will be removed during cleanup + \dotagregisterlocation + \dostoptagged + \endgroup} + +\permanent\protected\def\dosetfastregisterentry#1#2#3#4#5% register entry key processor processor + {\begingroup + \edef\currentregister{#1}% + \setnextinternalreference + \glet\currentregistername\currentregister + \xdef\currentregisternumber{\clf_storeregister + {% + metadata {% + name {\currentregister}% + } + entries {% + entry {#2}% + key {#3}% + }% + processors {% + entry {#4}% + page {#5}% + }% + }% + }% + % overlap with the above + % \clf_setinternalreference + % internal \locationcount + % view {\interactionparameter\c!focus}% + \relax % this will change + \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% + \currentregistersynchronize % here? + \dostarttagged\t!registerlocation\currentregister + \c_attr_destination\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup + \dotagregisterlocation + \dostoptagged + \endgroup} + +\let\dotagregisterlocation\relax % experiment + +\tolerant\protected\def\strc_registers_insert_entry[#1]#*[#2]% + {\def\currentregister{#1}% + \edef\p_ownnumber{\registerparameter\c!ownnumber}% + \ifx\p_ownnumber\v!yes + \expandafter\strc_registers_insert_entry_yes + \else + \expandafter\strc_registers_insert_entry_nop + \fi{#2}} + +% \def\strc_registers_insert_entry_nop#1#2% +% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} +% +% \def\strc_registers_insert_entry_yes#1#2#3% +% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} +% +% less tokens passed (nicer for tracing) .. could become installable + +\def\strc_registers_insert_entry_nop + {\ifvmode + \expandafter\strc_registers_insert_entry_nop_par + \else + \expandafter\strc_registers_insert_entry_nop_txt + \fi} + +\def\strc_registers_insert_entry_yes + {\ifvmode + \expandafter\strc_registers_insert_entry_yes_par + \else + \expandafter\strc_registers_insert_entry_yes_txt + \fi} + +\def\strc_registers_insert_entry_nop_par#1#2% + {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} + +\def\strc_registers_insert_entry_yes_par#1#2#3% + {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} + +\def\strc_registers_insert_entry_nop_txt#1#2% + {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}} + +\def\strc_registers_insert_entry_yes_txt#1#2#3% + {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}} + +%D This is one of the few commands where a stop has arguments. + +\permanent\tolerant\protected\def\startregister[#1]#*[#2]#*[#3]#*[#4]#*#:#5% + {\ifparameter#4\or + % #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} + +\permanent\tolerant\protected\def\stopregister[#1]#*[#2]% + {\normalexpanded{\ctxlatecommand{extendregister("#1","#2")}}} + +% a synonym, so that we can nest with overlap without syntax check problems + +\aliased\let\openregisterrange \startregister +\aliased\let\closeregisterrange\stopregister + +% not yet document, not sure if this will stay: + +\permanent\tolerant\protected\def\setregisterentry[#1]#*[#2]#*[#3]% + {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} + +\permanent\tolerant\protected\def\finishregisterentry[#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 + \resetregisterparameter\c!entries + \resetregisterparameter\c!label + \resetregisterparameter\c!keys + \resetregisterparameter\c!alternative + \setupcurrentregister[#2]% + \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 + \glet\currentregistercoding\s!xml + \else + \ifx\currentregisterexpansion\v!yes + \xdef\currentregisterentries{\registerparameter\c!entries}% + \else + \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% + \fi + \glet\currentregistercoding\s!tex + \fi + % I hate this kind of mess ... but it's a user request. + \ifempty\currentregisterentries + \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 + +\permanent\tolerant\protected\def\setstructurepageregister[#1]#*[#2]#*[#3]% [register][settings][userdata] + {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} + +\permanent\tolerant\protected\def\startstructurepageregister[#1]#*[#2]#*[#3]#*[#4]% [register][tag][settings][userdata] + {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}} + +\permanent\tolerant\protected\def\stopstructurepageregister[#1]#*[#2]% + {\normalexpanded{\ctxlatecommand{structures.registers.extend("#1","#2")}}} + +\aliased\let\openstructurepageregisterrange \startstructurepageregister +\aliased\let\closestructurepageregisterrange\stopstructurepageregister + +% So far. + +\tolerant\protected\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 + \glet\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 + \glet\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 \locationcount + view {\interactionparameter\c!focus}% + \relax % this will change + \dostarttagged\t!registerlocation\currentregister + \c_attr_destination\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 + +\permanent\tolerant\protected\def\determineregistercharacteristics[#1]#*[#2]% + {\begingroup + \setupregister[#1][#2]% + \edef\currentregister{\firstinset{#1}}% + \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 \ifempty\registerpageseparatorsymbol false\else true\fi + }% + }}% + \ifcase\utilityregisterlength\relax + \resetsystemmode\v!register + \else + \setsystemmode \v!register + \fi} + +\newtoks\everyplaceregister + +\appendtoks + \dontcomplain +\to \everyplaceregister + +\newconditional\c_strc_registers_text_interaction + +\permanent\tolerant\protected\def\placeregister[#1]#*[#2]% + {\ifarguments\else + \begingroup + %\forgetall + \setupregister[#1][#2]% can be a list + \edef\currentregister{\firstinset{#1}}% + \the\everyplaceregister + \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone + \startmixedcolumns[\currentregister]% + \strc_registers_place_indeed{#1}% + \stopmixedcolumns + \else + \strc_registers_place_indeed{#1}% + \fi + \endgroup + \fi} + +\def\strc_registers_place_indeed#1% + {\doifelse{\registerparameter\c!interaction}\v!text + \settrue\setfalse\c_strc_registers_text_interaction + \clf_processregister + {#1}% + {% + language {\registerparameter\s!language}% + method {\registerparameter\c!method}% + numberorder {\registerparameter\c!numberorder}% + check {\registerparameter\c!check}% + compress {\registerparameter\c!compress}% + criterium {\registerparameter\c!criterium}% + pagemethod {\registerparameter\c!pagemethod}% + pagenumber \ifempty\registerpageseparatorsymbol 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}% + +\def\strc_registers_limited_entry#1% + {\limitated left \currentregistermaxwidth sentinel {\unknown} text {#1} freeze true\relax} + +\aliased\let\limitedregisterentry\firstofoneargument + +\appendtoks + \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}% + \ifempty\currentregistermaxwidth + \enforced\let\limitedregisterentry\firstofoneargument + \else + \enforced\let\limitedregisterentry\strc_registers_limited_entry + \fi +\to \everyplaceregister + +\permanent\tolerant\protected\def\completeregister[#1]#*[#2]% + {\ifarguments\or + \begingroup + \edef\currentregister{\firstinset{#1}}% + \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}% + \placeregister[#1][#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} + +\permanent\def\defaultregistercharacter#1% + {\edef\currentregistercharacter{#1}% + \ifempty\currentregistercharacter + % skip + \orelse\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} + +\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 = + +\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 = + +\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 + +\permanent\protected\def\startregisteroutput + {\endgraf + \begingroup + \d_strc_registers_distance\registerparameter\c!distance\relax + \dostarttaggedchained\t!register\currentregister\??register + \forgeteverypar + \forgetparindent + \forgetparskip} + +\permanent\protected\def\stopregisteroutput + {\endgraf + \dostoptagged + \endgroup} + +\newdimen\d_strc_registers_hangindent +\newcount\c_strc_registers_hangafter + +\permanent\protected\def\usenestedregisterstyleandcolor#1#2% will change + {\useregisterstyleandcolor#1#2% + % how about style + \ifconditional\c_strc_registers_text_interaction + \ifempty\currentcolorparameter \else + \resetinteractionparameter\c!color + \resetinteractionparameter\c!contrastcolor + \fi + \fi} + +\permanent\protected\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}% + \usenestedregisterstyleandcolor\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} + +\permanent\protected\def\stopregisterentries + {\endgraf + \dostoptagged + \endgroup} + +\permanent\protected\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} + +\permanent\protected\def\stopregisterentry + {\endgraf + \global\setconstant\c_strc_registers_page_state\zerocount + \dostoptagged + \endgroup} + +\permanent\protected\def\startregistersection#1% title + {\dostarttagged\t!registersection\empty + \dostarttagged\t!registertag\empty + \registercharacter{#1}\endgraf + \dostoptagged} + +\permanent\protected\def\stopregistersection + {\dostoptagged + \endgraf} + +\permanent\protected\def\startregisterpages + {\begingroup + \dostarttagged\t!registerpages\empty + \useregisterstyleandcolor\c!pagestyle\c!pagecolor + \registerparameter\c!pageleft} + +\permanent\protected\def\stopregisterpages + {\registerparameter\c!pageright + \dostoptagged + \endgroup} + +\permanent\protected\def\startregisterseewords + {\begingroup + \dostarttagged\t!registerpage\empty + \useregisterstyleandcolor\c!pagestyle\c!pagecolor} + +\permanent\protected\def\stopregisterseewords + {\dostoptagged + \endgroup} + +\permanent\protected\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} + +\permanent\protected\def\registeronepagerangeseparator + {|\endash|} % todo use \prewordbreak + +% \protected\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} + +\permanent\protected\def\withregisterpagecommand#1#2#3#4% + {\ifcase#3\relax + {\tt [entry\space not\space flushed]}% + \else + \def\currentregisterpageindex{#2}% + \iflocation + \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% + \else + \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% + \fi + \fi} + +\permanent\protected\def\pushcurrentregister#1% + {\let\m_current_register\currentregister + \edef\currentregister{#1}} + +\permanent\protected\def\popcurrentregister + {\let\currentregister\m_current_register} + +\permanent\protected\def\registeronepage#1#2#3#4#5% #1:class #2:processor content + {\pushcurrentregister{#1}% + \edef\p_pagenumber{\registerparameter\c!pagenumber}% + \ifx\p_pagenumber\v!no\else + \registerpageseparator + \global\setconstant\c_strc_registers_page_state\plusone + \dostarttagged\t!registerpage\empty + \withregisterpagecommand{#2}{#3}{#4}{#5}% + \dostoptagged + \fi + \popcurrentregister} + +\newconditional\c_strc_registers_following + +\appendtoks + \edef\p_compress{\registerparameter\c!compress}% + \ifx\p_compress\v!text + \settrue\c_strc_registers_following + \letregisterparameter\c!compress\v!yes + \else + \setfalse\c_strc_registers_following + \fi +\to \everyplaceregister + +\permanent\protected\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable + {\pushcurrentregister{#1}% + \edef\p_pagenumber{\registerparameter\c!pagenumber}% + \ifx\p_pagenumber\v!no\else + \registerpageseparator + \global\setconstant\c_strc_registers_page_state\plusone + \dostarttagged\t!registerpagerange\empty + \dostarttagged\t!registerfrompage\empty + \withregisterpagecommand{#2}{#3}{#4}{#5}% + \dostoptagged + \ifconditional\c_strc_registers_following + \ifnum#3=\numexpr#6-1\relax + \labeltext{following:\s!singular}% + \else + \labeltext{following:\s!plural}% + \fi + \else + \registeronepagerangeseparator + \dostarttagged\t!registertopage\empty + \withregisterpagecommand{#2}{#6}{#7}{#8}% + \fi + \dostoptagged + \dostoptagged + \fi + \popcurrentregister} + +\permanent\protected\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word + {\pushcurrentregister{#1}% + \def\currentregisterpageindex{#3}% + \iflocation + \def\currentregisterseeindex{#4}% + \ifconditional\c_strc_registers_text_interaction + \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% + \else + \doapplyregisterentrycommand{#2}{#5}% + \fi + \else + \let\currentregisterseeindex\empty + \doapplyregisterentrycommand{#2}{#5}% + \fi + \popcurrentregister} + +\permanent\protected\def\doapplyregisterentrycommand#1#2% processor text + {\dostarttagged\t!registercontent\empty + \ifempty\currentregisterseeindex \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} + +\permanent\protected\def\doapplyregisterseecommand#1#2% + {\ifempty\currentregisterseeindex + \applyprocessor{#1}{#2}% + \orelse\iflocation + \strc_references_goto_internal{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]% + \else + \applyprocessor{#1}{#2}% + \fi} + +\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word + {\pushcurrentregister{#1}% + \ifnum#2=\plusone + \registerpageseparator + \fi + \global\setconstant\c_strc_registers_page_state\plustwo + \def\currentregisterpageindex{#5}% + \dostarttagged\t!registersee\empty + \settrue\c_strc_registers_page_done + \iflocation + \def\currentregisterseeindex{#6}% + \else + \let\currentregisterseeindex\empty + \fi + \ifnum#2=\plusone + \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% + \orelse\ifnum#2=#3\relax + \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% + \else + ,\space\doapplyregisterseecommand{#4}{#7}% + \fi + \dostoptagged + \popcurrentregister} + +\permanent\protected\def\doapplyregistersectioncommand#1#2% + {\ifempty\currentregistersectionindex + \applyprocessor{#1}{#2}% + \orelse\iflocation + \strc_references_goto_internal{\applyprocessor{#1}{#2}}[sectionindex:\currentregistersectionindex]% + \else + \applyprocessor{#1}{#2}% + \fi} + +\permanent\protected\def\defaultregistersection#1#2#3#4#5#6#7% class i n #4:processor #5:internal #6:sectionindex #7:word + {\pushcurrentregister{#1}% + \ifnum#2=\plusone + \registerpageseparator + \fi + \global\setconstant\c_strc_registers_page_state\plustwo + \def\currentregisterpageindex{#5}% + \dostarttagged\t!registersection\empty + \settrue\c_strc_registers_page_done + \iflocation + \def\currentregistersectionindex{#6}% + \else + \let\currentregistersectionindex\empty + \fi + \ifnum#2=\plusone\else + ,\space + \fi + \doapplyregistersectioncommand{#4}{#7}% + \dostoptagged + \popcurrentregister} + +\aliased\let\registersection \defaultregistersection +\aliased\let\registerseeword \defaultregisterseeword +\aliased\let\registerentry \defaultregisterentry +\aliased\let\registercharacter\defaultregistercharacter + +%D Experimental: +%D +%D \starttyping +%D \setupregister +%D [index] +%D [pagesegments=1:4, +%D pagemethod=section] +%D +%D \starttext +%D +%D \chapter {one} \section {alpha} +%D +%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page +%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page +%D +%D \chapter {one} \section {alpha} +%D +%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page +%D x\index {whatever 1}x\index {whatever 2}x\index {whatever 2}x \page +%D +%D \placeindex[n=1] +%D +%D \stoptext +%D \stoptyping + +%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 + +\permanent\def\registerpageuserdata #1#2{\clf_registeruserdata#1{#2}} +\permanent\def\currentregisterpageuserdata {\registerpageuserdata\currentregisterpageindex} % {#1} + +% not yet ok : new internal handler names + +\aliased\let\registerpageseparatorsymbol\empty + +\permanent\protected\def\registerpagebuttonsymbol + {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} + +\installcorenamespace{registersymbol} + +\setvalue{\??registersymbol n}% + {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} + +\setvalue{\??registersymbol a}% + {\enforced\frozen\def\registerpageseparatorsymbol{,\space}} % now done via conversion + +\setvalue{\??registersymbol\v!none}% + {\enforced\frozen\let\registerpageseparatorsymbol\empty + \enforced\frozen\let\registeronepage\gobblefivearguments + \enforced\frozen\let\registerpagerange\gobbleeightarguments} + +\setvalue{\??registersymbol 1}% + {\enforced\frozen\let\registerpageseparatorsymbol\space + \enforced\frozen\def\registeronepage{\symbol[1]\gobblefivearguments}% + \enforced\frozen\def\registerpagerange{\symbol[1]\gobbleeightarguments}} + +\setvalue{\??registersymbol 2}% + {\enforced\frozen\let\registerpageseparatorsymbol\space + \enforced\frozen\def\registeronepage{\registerpagebuttonsymbol\gobblefivearguments}% + \enforced\frozen\def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}} + +\protected\def\setregisterpagerendering + {\doifelse{\registerparameter\c!pagenumber}\v!no + {\enforced\frozen\let \currentregisterpagesymbol\v!none} + {\enforced\frozen\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}% + \ifempty\currentregisterpagesymbol + \csname\??registersymbol n\endcsname + \orelse\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname + \csname\??registersymbol\currentregisterpagesymbol\endcsname + \else + \enforced\frozen\let\registerpageseparatorsymbol\space + \enforced\frozen\def\registeronepage{\registerparameter\c!symbol\gobblefivearguments}% + \enforced\frozen\def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}% + \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. + +\permanent \def\findregisterinternal#1#2#3{\clf_findregisterinternal{#1}{#2}#3\relax} +\permanent\protected\def\pageofinternal #1{\clf_pageofinternal#1\relax} + +\permanent\protected\def\linkedregisterentrylink#1#2#3#4% tag where before after + {\iflocation + \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax + \ifcase\scratchcounter\else + #3\relax + \goto{\symbol[#2]}[internal(\the\scratchcounter)]% + #4\relax + \fi + \else + % \scratchcounter\findregisterinternal{#1}{#2}\currentregisternumber\relax\relax + % \ifcase\scratchcounter\else + % #3\relax + % \pageofinternal\scratchcounter + % #4\relax + % \fi + \fi} + +\permanent\protected\def\linkedregisterentry#1% + {\dontleavehmode + \begingroup + \setbox\scratchbox\hbox{#1}% + \linkedregisterentrylink\currentregistername\v!previous\relax\nobreakspace + \unhbox\scratchbox + \linkedregisterentrylink\currentregistername\v!next\nobreakspace\relax + \endgroup} + +\permanent\protected\def\registerpacked#1#2% + {\iflocation + \hskip\d_strc_registers_distance\relax + \nobreak + \ifnum#1=#2\relax + \goto{\symbol[\v!somewhere]}[internal(#1)]% + \else + \goto{\symbol[\v!first]}[internal(#1)]% + \nobreakspace + \goto{\symbol[\v!last]}[internal(#2)]% + \fi + \fi} + +%D Default index: + +\defineregister + [\v!index] +% [\v!indices] + +\stopcontextdefinitioncode + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-ren.mkxl b/tex/context/base/mkxl/strc-ren.mkxl new file mode 100644 index 000000000..2d553964b --- /dev/null +++ b/tex/context/base/mkxl/strc-ren.mkxl @@ -0,0 +1,817 @@ +%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 + +\protected\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} + +\protected\def\strc_rendering_initialize_style_and_color_display#1#2% + {\dontconvertfont + \edef\p_strc_rendering_interlinespace{\headparameter\c!interlinespace}% + \ifempty\p_strc_rendering_interlinespace + % 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} + +\protected\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 + +\permanent\def\headreferenceattributes + {\iflocation + % \ctxlua{structures.lists.taglocation(\the\locationcount)}% maybe ... tags entry as used + attr \destinationattribute \currentstructureattribute + attr \referenceattribute \currentstructurereferenceattribute + % attr \internalattribute \locationcount + \fi} + +\permanent\def\setinlineheadreferenceattributes + {\ifconditional\headisdisplay \else \iflocation + \c_attr_destination\currentstructureattribute + \c_attr_reference \currentstructurereferenceattribute + % \c_attr_internal \locationcount + \fi \fi} + +\permanent\protected\def\docheckheadreference + {\edef\currentheadinteraction{\headparameter\c!interaction}% + \ifx\currentheadinteraction\v!list + % setuphead[
][interaction=list,...] + \strc_references_get_simple_reference{*\the\locationcount}% + \let\currentstructurereferenceattribute\currentreferenceattribute + \orelse\ifx\currentheadinteraction\v!reference + % setuphead[
][interaction=reference,...] start
[backreference=abc,...] + \edef\currentheadbackreference{\structurevariable\c!backreference}% weird, was references.backreference + \ifempty\currentheadbackreference \else + \strc_references_get_simple_reference\currentheadbackreference + \let\currentstructurereferenceattribute\currentreferenceattribute + \fi + \else + % maybe auto: backreference when given, else list + \fi} + +% a bit messy ... empty in place instead of self .. might change (or use special +% whatsig (invisible user one) + +\protected\def\strc_rendering_place_head_text + {\strc_rendering_start_placement + \setheadmarking + \doresetstructureheadnumbercontent + \ifconditional\c_strc_sectioning_empty + \setbox\b_strc_rendering_head\hpack \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} + +\protected\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\hpack \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} + +\protected\def\strc_rendering_place_head_empty + {\hpack\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 + +\permanent\protected\def\headhbox{\hbox\headreferenceattributes} +\permanent\protected\def\headvbox{\vbox\headreferenceattributes} + +\permanent\protected\def\startlocalheadsetup{\bgroup\strc_rendering_initialize_spacing} +\permanent\protected\def\stoplocalheadsetup {\egroup} + +\protected\def\strc_rendering_initialize_spacing + {\forgetall % local ! + \edef\p_align{\headparameter\c!align}% + \ifempty\p_align \else + \setupalign[\p_align]% + \fi + \edef\p_tolerance{\headparameter\c!tolerance}% + \ifempty\p_tolerance \else + \setuptolerance[\p_tolerance]% + \fi + \edef\p_strut{\headparameter\c!strut}% + \ifx\p_strut\v!no + \setnostrut + \fi + \enforced\let\\\strc_rendering_shortcut_backslash} + +\protected\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 + \synctexpushline + \edef\p_aligntitle{\headparameter\c!aligntitle}% + \ifx\p_aligntitle\v!yes + \strc_rendering_initialize_hsize_local + \orelse\ifx\p_aligntitle\v!float + \strc_rendering_initialize_hsize_local + \else + \strc_rendering_initialize_hsize_global + \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_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\hpack{\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_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_sectioning_stay_on_this_line +% {\directcheckedvspacing{-\v!line,\v!samepage,\v!nowhite}% +% \directcheckedvspacing\v!disable} +% +% we now use \ignoreparskip, so: + +\def\strc_sectioning_stay_on_this_line + {\directcheckedvspacing{-\v!line,\v!samepage}% + \directcheckedvspacing\v!disable} + +\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 + \setbox\b_strc_rendering_head\hbox + {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax + \box\b_strc_rendering_head + \getheadsyncs % a latelua why not in the box + }% + \ifgridsnapping + \applygridmethod + {\headparameter\c!grid}% + {\ifconditional\headisdisplay + \strc_rendering_initialize_style_and_color_display\c!textstyle\c!textcolor + \fi}% + {\box\b_strc_rendering_head} + \else + \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 % a latelua why not in the box + \else + % somehow this goes ok even when we push in the margin probably because we gobble pars + % in the process of collecting index entries etc + \strut + \flushnotes % new, here since we're in par mode + \unhbox\b_strc_rendering_head + \getheadsyncs % a latelua + \ifconditional\headissomewhere + \strc_sectioning_stay_on_this_line % test case: alternative=margintext and \startparagraph .. + \else + %\hskip\headnumberdistance\s!plus\headnumberdistance\s!minus.25\dimexpr\headnumberdistance\relax + \hskip\headtextdistance\relax + \strc_sectioning_inject_continuous_signal + \fi + \fi + \ifconditional\headisdisplay + \ifvmode + \ifgridsnapping % important, font related depth, see comment + \prevdepth\strutdp + \else + \prevdepth\d_strc_rendering_local_depth + \fi + \fi + \fi + \synctexpopline + \egroup + \egroup + \ifconditional\headisdisplay + \useindentnextparameter\headparameter + \orelse\ifconditional\headissomewhere + \ignoreparskip + \noindentation + \else + \ignoreparskip + \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 + +\permanent\tolerant\protected\def\defineheadplacement[#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 +\newskip \headtextdistance +\newdimen\headnumberdistance +\newdimen\headnumberwidth + +% \newconditional\headshownumber % defined already +% \newconditional\headisdisplay % defined already + +\protected\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}% + \ifempty\currentheadrenderingalternative + \let\currentheadrenderingalternative\v!vertical + \fi + \ifx\currentheadrenderingalternative\v!horizontal + \global\setfalse\headisdisplay % global + \global\setfalse\headissomewhere % global + \orelse\ifx\currentheadrenderingalternative\v!somewhere + \global\setfalse\headisdisplay % global + \global\settrue \headissomewhere % global + \else + \global\settrue \headisdisplay % global + \global\setfalse\headissomewhere % global + \fi} + +\protected\def\strc_rendering_initialize_dimensions + {\headwidth \headparameter\c!width \relax % \zeropoint == unset + \headnumberwidth \headparameter\c!numberwidth \relax % \zeropoint == unset + \headnumberdistance\headparameter\c!distance \relax + \headtextdistance \headparameter\c!textdistance\relax + \headtextwidth \headparameter\c!textwidth \relax} % \zeropoint == unset + +\permanent\protected\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} + +\permanent\protected\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} + +\permanent\protected\def\fakedheadnumber{\vphantom{0}} % needed for mathplus + +% \permanent\protected\def\fakeheadnumbercontent +% {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}} + +\permanent\protected\def\fakeheadnumbercontent + {\edef\p_hidenumber{\headparameter\c!hidenumber}% + \ifx\p_hidenumber\v!yes\else + \hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}% + \fi} + +\permanent\protected\def\strc_rendering_inject_number_and_text + {\edef\p_command{\headparameter\c!command}% assumes \protected definition + \ifempty\p_command + \directsetup\currentheadrenderingsetup + \else + \p_command\headnumbercontent\headtextcontent + \fi} + +\protected\def\strc_rendering_inject_text + {\edef\p_command{\headparameter\c!command}% assumes \protected definition + \ifempty\p_command + \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 + \ifzeropt\headwidth \else + \ifzeropt\headnumberwidth + \ifzeropt\headtextwidth \else + \headnumberwidth\dimexpr\headwidth-\headtextwidth\relax + \fi + \else + \ifzeropt\headtextwidth + \headtextwidth\dimexpr\headwidth-\headnumberwidth\relax + \fi + \fi + \hsize\headwidth + \fi + \ifzeropt\headnumberwidth \else + \headnumberdistance\zeropoint + \fi + \setbox\scratchbox\hbox \ifzeropt\headnumberwidth\else to \headnumberwidth\fi{\headnumbercontent} + \scratchdimen\dimexpr\wd\scratchbox+\headnumberdistance\relax + \ifzeropt\headtextwidth \else + \hsize\dimexpr\scratchdimen+\headtextwidth\relax + \fi + \hangindent\scratchdimen + \hangafter \plusone + \noindent + \box\scratchbox + \hskip\headnumberdistance + \else + \ifzeropt\headtextwidth + \ifzeropt\headwidth \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 + \dontleavehmode % in case there is no strut, else side effects with llap + \begstrut % use one \strut here! + \ifconditional\headshownumber + \doifelsesomething {\headparameter\c!location} { + % kind of new + \margindata [\headparameter\c!location] { + \headnumbercontent + } + } { + % normal backward compatible variant + \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 + \enforced\let\\\endgraf + \enforced\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 + \setbox\scratchboxone\hbox { + \headnumbercontent + } + \setbox\scratchboxtwo\vbox { + \headsetupspacing + \advance\hsize-\wd\scratchboxone\relax + \headtextcontent + } + \hpack { + \box\scratchboxone + \hskip\headnumberdistance + \box\scratchboxtwo + } + \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 + \setbox\scratchboxone\hbox { + \headnumbercontent + } + \setbox\scratchboxtwo\vtop { + \headsetupspacing + \advance\hsize-\wd\scratchboxone\relax + \headtextcontent + } + \hpack { + \box\scratchboxone + \hskip\headnumberdistance + \box\scratchboxtwo + } + \else + \vtop{ + \headsetupspacing + \noindent + \headtextcontent + } + \fi +\stopsetups + +% see typo-mar.mkiv: +% +% \defineheadalternative +% [\v!margintext] + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-sbe.mkxl b/tex/context/base/mkxl/strc-sbe.mkxl new file mode 100644 index 000000000..4ff1263bf --- /dev/null +++ b/tex/context/base/mkxl/strc-sbe.mkxl @@ -0,0 +1,137 @@ +%D \module +%D [ file=strc-sbe, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Section Block Environments, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Section Block Environments} + +\unprotect + +% \def\ChapterEntry#1#2#3% +% {chapter : \hbox to \hsize{\strut\bf#2\hss#3}\endgraf\placelist[section]} +% +% \startfrontmatter % optional +% \placelist[chapter][alternative=command,command=\ChapterEntry,criterium=text] \page +% \stopfrontmatter % optional +% +% \startbodymatter % optional +% \chapter{first} \section{one} test \section{two} test \page +% \chapter{second} \section{alpha} test \section{beta} test \page +% \stopbodymatter % optional + +\installcorenamespace{sectionblock} + +\installcommandhandler \??sectionblock {sectionblock} \??sectionblock + +\setupsectionblock + [\c!number=\v!yes, + \c!page=\v!right] % otherwise marks are reset too soon + +\newtoks\everybeforesectionblock +\newtoks\everyaftersectionblock + +\let\strc_sectionblock_define_normal\definesectionblock + +\permanent\overloaded\tolerant\protected\def\definesectionblock[#1]#*[#2]#*[#3]% singular plural settings + {\strc_sectionblock_define_normal[#1][#3]% + %\expandafter\newif\csname if#2\endcsname % obsolete + \strc_sectionblock_set_environment{#1}\empty + \frozen\setuvalue{\e!start#2}{\startsectionblock[#1]}% + \frozen\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}% + \ifempty\p_strc_sectionblock_page \else + \page[\p_strc_sectionblock_page]% + \fi} + +\appendtoks + \strc_sectionblock_handle_page + \resetallstructuremarks + \strc_sectionblock_get_environment\currentsectionblock + \sectionblockparameter\c!before % don't move + \dostarttagged\t!division\currentsectionblock % no parents +\to \everybeforesectionblock + +\appendtoks + \sectionblockparameter\c!after % don't move + \strc_sectionblock_handle_page + \dostoptagged + \resetallstructuremarks +\to \everyaftersectionblock + +\permanent\tolerant\protected\def\setsectionblock[#1]#*[#2]% used to set the default + {\edef\currentsectionblock{#1}% from now on we assume a value + \setupcurrentsectionblock[#2]% + \clf_setsectionblock{#1} + bookmark {\sectionblockparameter\c!bookmark}% + \relax} + +\let\currentsectionblock\empty % was \s!unknown + +\permanent\tolerant\protected\def\startsectionblock[#1]#*[#2]% + {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push) + \begingroup + \edef\currentsectionblock{#1}% from now on we assume a value + \setupcurrentsectionblock[#2]% + \clf_pushsectionblock{#1} + bookmark {\sectionblockparameter\c!bookmark}% + \relax + %\csname #1true\endcsname % obsolete + \setsystemmode\currentsectionblock + \the\everybeforesectionblock\relax + \showmessage\m!structures1\currentsectionblock} + +\permanent\protected\def\stopsectionblock + {\showmessage\m!structures2\currentsectionblock + \the\everyaftersectionblock\relax + \clf_popsectionblock + \endgroup} + +%D \starttyping +%D \startsectionblockenvironment[frontpart] +%D \setupnumber[userpage][numberconversion=romannumerals,start=1] +%D \stopsectionblockenvironment +%D +%D \startsectionblockenvironment[bodypart] +%D \setupnumber[userpage][numberconversion=numbers,start=1] +%D \stopsectionblockenvironment +%D +%D \startsectionblockenvironment[backpart] +%D \setupnumber[userpage][numberconversion=numbers,start=1] +%D \stopsectionblockenvironment +%D +%D \starttext +%D \startfrontmatter \chapter{test} \stopfrontmatter +%D \startbodymatter \chapter{test} \stopbodymatter +%D \startappendices \chapter{test} \stopappendices +%D \stoptext +%D \stoptyping + +\installcorenamespace{sectionblockenvironment} + +\protected\def\strc_sectionblock_set_environment#1#2% + {\setvalue{\??sectionblockenvironment#1}{#2}} + +\protected\def\strc_sectionblock_get_environment#1% + {\csname\??sectionblockenvironment#1\endcsname} + +\permanent\tolerant\protected\setvalue{\e!start\v!sectionblockenvironment}[#1]% evt \pushendofline \popendofline + {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}} + +\aliased\letvalue{\e!stop\v!sectionblockenvironment}\relax + + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-sec.mkxl b/tex/context/base/mkxl/strc-sec.mkxl new file mode 100644 index 000000000..e5371d1e9 --- /dev/null +++ b/tex/context/base/mkxl/strc-sec.mkxl @@ -0,0 +1,1321 @@ +%D \module +%D [ file=strc-sec, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Sectioning, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In retrospect I should have gone futher and move more to the +%D \LUA\ end but here we are now. Maybe some day. + +\writestatus{loading}{ConTeXt Structure Macros / Sectioning} + +\unprotect + +\startcontextdefinitioncode + +\installcorenamespace{structure} + +\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters + +\setupstructure % not a user command so we might need to change the name + [\c!number=, + \c!level=, + \c!name=, + \c!title=, + \c!bookmark=, + \c!marking=, + \c!list=, + \c!label=, + \c!coupling=, + \c!ownnumber=, + % \c!interaction=\v!list, + \c!sectionseparatorset=\s!default, + \c!sectionconversionset=\s!default, + \c!sectionstopper=, + \c!sectionstarter=, + \c!sectionsegments=, + \c!sectionresetset=, + \c!reference=, + \c!backreference=, + \c!expansion=\v!no, + \c!xmlsetup=, + \s!catcodes=, + \c!saveinlist=\v!yes] + +% maybe flags for list, bm, mark + +\def\m_strc_references_prefix_yes{+} +\def\m_strc_references_prefix_nop{-} + +\let\currentstructurereferenceprefix\empty + +\installglobalmacrostack\currentstructurereferenceprefix + +\def\strc_sectioning_set_reference_prefix + {\ifempty\currentstructurereferenceprefix + % nothing + \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes + \global\advance\prefixcounter \plusone % temp here + \setupglobalreferenceprefix[\the\prefixcounter]% + \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop + \setupglobalreferenceprefix[]% + \else + \setupglobalreferenceprefix[\currentstructurereferenceprefix]% + \fi + \glet\currentstructurereferenceprefix\referenceprefix} + +% why xdef ? + +\setupstructure + [\c!label={\headparameter{\currentsectionblock\c!label}}, + \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed + \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi, + \c!level=\currentheadlevel, + \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi, + \c!expansion=\headparameter\c!expansion, + \c!xmlsetup=\headparameter\c!xmlsetup, + \s!catcodes=\headparameter\s!catcodes, + \c!sectionresetset=\headparameter\c!sectionresetset, + \c!sectionseparatorset=\headparameter\c!sectionseparatorset, + \c!sectionconversionset=\headparameter\c!sectionconversionset, + \c!sectionconversion=\headparameter\c!conversion, % just for compatibility + \c!sectionstarter=\headparameter\c!sectionstarter, + \c!sectionstopper=\headparameter\c!sectionstopper, + \c!sectionset=\headparameter\c!sectionset, + \c!sectionsegments=\headparameter\c!sectionsegments, + \c!reference=\headparameter\c!reference, + \c!referenceprefix=\headparameter\c!referenceprefix, + \c!criterium=\headparameter\c!criterium] + +% see lists/neat-001.tex for usage of: + +\permanent\def\namedstructureheadlocation#1% expandable, maybe [#1] + {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname} + +% The next directive only makes sense when we have sort of garanteed outcome (math is not so +% nice for instance). +% +% \enabledirectives[references.bookmarks.preroll] + +\newconditional\c_strc_bookmarks_preroll + +\installtexdirective + {references.bookmarks.preroll} + {\settrue \c_strc_bookmarks_preroll} + {\setfalse\c_strc_bookmarks_preroll} + +\def\strc_sectioning_autobookmark#1% + {\begingroup + % \settrialtypesetting + \the\everypreroll + \nodestostring\tempstring{#1}% + \glet\currentstructurebookmark\tempstring + \endgroup} + +% zeros: +% +% \setuphead[subsection][criterium=all] +% +% \dorecurse{3} { +% \chapter{Blabla} \subsection{bla 1 1} \subsection{bla 1 2} +% \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2} +% } + +\protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported) + {\begingroup + \setupstructure[\c!name={#1},#2]% + \xdef\currentstructurename {\structureparameter\c!name}% + \xdef\currentstructurecoupling {\structureparameter\c!coupling}% + \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number + \xdef\currentstructurelevel {\structureparameter\c!level}% + \edef\currentstructureexpansion {\structureparameter\c!expansion}% + \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}% + \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}% + \xdef\currentstructurelabel {\structureparameter\c!label}% + \xdef\currentstructurereference {\structureparameter\c!reference}% + \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}% + \xdef\currentstructurebackreference {\structureparameter\c!backreference}% + \xdef\currentstructureshownumber {\structureparameter\c!number}% + \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}% + \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}% + \xdef\currentstructureplaceholder {\structureparameter\c!placeholder}% + \ifx\currentstructureexpansion\s!xml + \xmlstartraw + \xdef\currentstructuretitle {\structureparameter\c!title}% + \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% + \xdef\currentstructuremarking {\structureparameter\c!marking}% + \xdef\currentstructurelist {\structureparameter\c!list}% + \xmlstopraw + \iflocation \ifempty\currentstructurebookmark \ifconditional\c_strc_bookmarks_preroll + \strc_sectioning_autobookmark\currentstructuretitle + \fi \fi \fi + \ifempty\currentstructurelist + \glet\currentstructurelist\currentstructuretitle + \fi + \glet\currentstructurecoding\s!xml + \else + \ifx\currentstructureexpansion\v!yes + \xdef\currentstructuretitle {\structureparameter\c!title}% + \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% + \xdef\currentstructuremarking {\structureparameter\c!marking}% + \xdef\currentstructurelist {\structureparameter\c!list}% + \iflocation \ifempty\currentstructurebookmark \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 \ifempty\currentstructurebookmark + \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 + \ifempty\currentstructurelist + \glet\currentstructurelist\currentstructuretitle + \fi + \glet\currentstructurecoding\s!tex + \fi + \setnextinternalreference + \storeinternalreference\currentstructurename{\the\locationcount}% + \strc_sectioning_set_reference_prefix + \clf_setsectionentry + references { + internal \locationcount + % block {\currentsectionblock} + prefix {\currentstructurereferenceprefix} + reference {\currentstructurereference} + backreference {\currentstructurebackreference} + } + directives { + resetset {\structureparameter\c!sectionresetset} + } + metadata { + kind {section} + name {\currentstructurename} + catcodes \ifempty\currentstructurecatcodes\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space + coding {\currentstructurecoding} + \ifx\currentstructurecoding\s!xml + xmlroot {\xmldocument} + \fi + \ifempty\currentstructurexmlsetup \else + xmlsetup {\currentstructurexmlsetup} + \fi + \ifx\currentstructuresaveinlist\v!no + nolist \space true\space + \fi + \ifx\currentstructureincrementnumber\v!yes + increment {\currentstructureincrementnumber} + \fi + } + titledata { + label {\detokenize\expandafter{\currentstructurelabel}} + title {\detokenize\expandafter{\currentstructuretitle}} + \ifx\currentstructurebookmark\currentstructuretitle \else + bookmark {\detokenize\expandafter{\currentstructurebookmark}} + \fi + \ifx\currentstructuremarking\currentstructuretitle \else + marking {\detokenize\expandafter{\currentstructuremarking}} + \fi + \ifx\currentstructuresaveinlist\v!no \else + \ifx\currentstructurelist\currentstructuretitle \else + list {\detokenize\expandafter{\currentstructurelist}} + \fi + \fi + } + numberdata { + % block {\currentsectionblock} + \ifx\currentstructureshownumber\v!no + hidenumber \space true\space % space needed for parser + \fi + separatorset {\structureparameter\c!sectionseparatorset} + conversionset {\structureparameter\c!sectionconversionset} + conversion {\structureparameter\c!sectionconversion} + starter {\structureparameter\c!sectionstarter} + stopper {\structureparameter\c!sectionstopper} + set {\structureparameter\c!sectionset} + segments {\structureparameter\c!sectionsegments} + ownnumber {\currentstructureownnumber} + language {\currentlanguage}% for the moment, needed for bookmarks conversion + criterium {\structureparameter\c!criterium} + } + userdata {\detokenize{#3}}% will be converted to table at the lua end + \relax + \xdef\currentstructurelistnumber{\clf_currentsectiontolist}% + % \currentstructuresynchronize has to be called someplace, since it introduces a node + \setstructuresynchronization\currentstructurelistnumber + \endgroup} + +\let\currentsectioncountervalue \!!zerocount % redefined later +\let\previoussectioncountervalue\!!zerocount % redefined later + +% We can access the (stored) data with the following macros. +% +% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}} +% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2} +% +% \setuphead[chapter][command=\MyHeadCommand] +% \setuplist[chapter][alternative=command,command=\MyListCommand] +% +% \starttext +% \setupheadertexts[chapter] +% \setupinteraction[state=start] +% \placebookmarks[chapter] +% \placelist[chapter] +% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps] +% \stopchapter +% \stoptext + +% todo: #1 => "#1" ... adapt lua code for name and number + +\permanent\def\structurenumber {\clf_structurenumber} +\permanent\def\structuretitle {\clf_structuretitle} +\permanent\def\structurevariable #1{\clf_structurevariable {#1}} +\permanent\def\structureuservariable #1{\clf_structureuservariable {#1}} +\permanent\def\structurecatcodedget #1{\clf_structurecatcodedget {#1}} % bad name +\permanent\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name +\permanent\def\structureautocatcodedget #1#2{\clf_structureautocatcodedget {#1}{#2}} +\permanent\def\namedstructurevariable #1#2{\clf_namedstructurevariable {#1}{#2}} +\permanent\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}} + +% compatibility issue: +% +% \def\setfullsectionnumber #1{} +% \def\preparefullnumber #1{} +% \def\fullsectionnumber {1--1--1} +% \def\makesectionnumber [#1]{} +% \def\makesectionformat {} +% \def\sectionformat {1--1-1-1-1-1-1} +% \def\composedsectionnumber{} +% \def\@@kolist{} + +% \setuphead[section] [separator=\separatorlist{?,!,*}] +% \setuphead[subsection][separator=\separatorlist{??,!!,**}] +% +% \let\spr\separatorlist % this will enable this feature +% +% \setuphead[section] [separator={?,!,*}] +% \setuphead[subsection][separator={??,!!,**}] +% +% \setupheads[separator={A,B,C,D,E,F}] +% \chapter{test} +% \section{test} \subsection{test} \subsection{test} +% \section{test} \subsection{test} \subsection{test} + +% lua interface / names and interface might change + +% \newconditional\c_strc_rendering_continuous % not used (mkii ?) + +\permanent\def\setstructurelevel #1#2{\clf_setstructurelevel {#1}{#2}} % name, level|parent +\permanent\def\getstructurelevel #1{\clf_getstructurelevel {#1}} % name +\permanent\def\setstructurenumber #1#2{\clf_setstructurenumber #1{#2}} % level, number (+/-) +\permanent\def\getstructurenumber #1{\clf_getstructurenumber \numexpr#1\relax} % level +\permanent\def\getsomestructurenumber #1#2{\clf_getsomestructurenumber #1{#2}} % level, what +\permanent\def\getfullstructurenumber #1{\clf_getfullstructurenumber \numexpr#1\relax} % level +\permanent\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}} % level, what +\permanent\def\getspecificstructuretitle #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}} + +% structure heads (like \startchapter) + +% \c!deeptextcommand, \c!deepnumbercommand: undefined ! +% \c!before \c!after \c!distance +% \c!page \c!header \c!text \c!footer=, +% \c!numbercommand \c!textcommand \c!ownnumber \c!number +% \c!file \c!grid \c!margintext +% \c!expansion \c!xmlsetup \s!catcode + +\installcorenamespace{head} +\installcorenamespace{headlevel} +\installcorenamespace{headincrement} +\installcorenamespace{headplace} +\installcorenamespace{headmarkyes} +\installcorenamespace{headmarknop} + +\installcommandhandler \??head {head} \??head + +\installmacrostack\currenthead +\installmacrostack\currentheadparent + +\setuphead [% + %\c!after=, + %\c!align=, + %\c!aligntitle=, + \c!alternative=\v!normal, + %\c!before=, + %\c!color=, + %\c!command=, + \c!continue=\v!yes, + %\c!coupling=, + %\c!deepnumbercommand=, + %\c!deeptextcommand=, + %\c!default=, + \c!distance=\zeropoint, + \c!textdistance=\zeropoint, + \c!textwidth=\zeropoint, % signal too + \c!numberwidth=\zeropoint, % signal too + \c!width=\zeropoint, % signal too + \c!expansion=\v!no, + %\c!file=, + %\c!footer=, + %\c!grid=, + \c!hang=\v!none, + %\c!header=, + \c!incrementnumber=\v!yes, + \c!indentnext=\v!no, + %\c!label=, + %\c!limittext=\languageparameter\c!limittext, + \c!margin=\zeropoint, + %\c!margintext=, + \c!number=\v!yes, + \c!numbercolor=\headparameter\c!color, + \c!textcolor=\headparameter\c!color, + \c!numberstyle=\headparameter\c!style, + \c!textstyle=\headparameter\c!style, + %\c!numbercommand=, + %\c!textcommand=, + \c!ownnumber=\v!no, + %\c!page=, + \c!placehead=\v!yes, + \c!sectionconversionset=\s!default, + \c!sectionnumber=\v!yes, + %\c!sectionsegments=, + \c!sectionseparatorset=\s!default, + \c!sectionset=\v!all, + \c!interlinespace=, + %\c!sectionstopper=, + %\c!sectionstarter=, + %\c!strut=, + %\c!style=, + %\c!text=, + %\c!tolerance=, + %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace + %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace + %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace + ] + +\aliased\let\setupheads\setuphead % will go + +\appendtoks + \ifempty\currentheadparent + \edef\currentheaddefault{\headparameter\c!default}% + \edef\currentheadsection{\headparameter\c!section}% + \ifx\currenthead\currentheaddefault + \let\currentheadparent\currentheadsection + \orelse\ifempty\currentheaddefault + \let\currentheadparent\currentheadsection + \else + \let\currentheadparent\currentheaddefault + \fi + \normalexpanded {% + \setheadparameter{\c!label}{\currenthead}% + \setheadparameter{\c!coupling}{\currenthead}% + \setheadparameter{\s!parent}{\??head\currentheadparent}% + \definemarking[\currenthead] [\currentheadsection]% + \definemarking[\currenthead\v!number][\currentheadsection]% + \setupmarking [\currenthead] [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]% + \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]% + }% + \doifelselist\currenthead\donothing + {\definelist[\currenthead][\c!prefix=\v!no]}% + % we can't do this now for backward compatibility reasons + % \doifelselist\currenthead\donothing + % {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% + \else + \normalexpanded {% + \setheadparameter{\c!label}{\currenthead}% + \setheadparameter{\c!coupling}{\currentheadparent}% + \definemarking[\currenthead] [\currentheadparent]% + \definemarking[\currenthead\v!number][\currentheadparent\c!number]% + }% + \doifelselist\currenthead\donothing + {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% + \fi + \presetlabeltext[\currenthead=]% + \the\everysetuphead +\to \everydefinehead + +\newtoks\everyredefinehead + +\appendtoks + \the\everyredefinehead +\to \everydefinehead + +\appendtoks + \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}% +\to \everyredefinehead + +\appendtoks + % beware, this is a global register + \begingroup + \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}% + \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}% + \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}% + \clf_registersection {\currenthead} { + coupling {\currentsectionheadcoupling} + section {\currentsectionheadsection} + level \space \currentsectionlevel \space % space needed for parser + parent {\currentheadparent} + }% + \endgroup +\to \everyredefinehead + +\appendtoks + \frozen\instance\setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}% + \frozen\instance\setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}% +\to \everydefinehead + +% so \subject as well as \section will need two commands when ownnumber +% is used (one can disable it anyway for subject) .. this is not downward +% compatible but better + +\appendtoks + \ifempty\currenthead \else + \doifelse{\headparameter\c!ownnumber}\v!yes + {\instance\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}} + {\instance\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}% + \fi +\to \everysetuphead + +\permanent\protected\def\doredefinehead#1#2% called at lua end + {\push_macro_currenthead + \push_macro_currentheadparent + \edef\currenthead{#1}% + \edef\currentheadparent{#2}% + \the\everyredefinehead\relax + \pop_macro_currentheadparent + \pop_macro_currenthead} + +\let\currentnamedsection\empty + +\installmacrostack\currentnamedsection + +% structure sections (the parents of chapter etc) + +\let\firstsectionname\empty +\let\lastsectionname \empty + +\let\resetallstructuremarks \relax +\let\resetcurrentstructuremarks \relax +\let\resetcurrentstructuremarkswithpage\relax + +\def\resetallstructuremarks {\resetmarking[\firstsectionname]} % will become option (was \v!section-1) +\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option +%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option + +% We could use a commandhandler here but sections are somewhat special in the +% sense that we have two ways of chaining: the main section (levels) as well +% as rendering (head). + +% -2 = text +% -1 = manual +% 0 = block +% +1 = structurelevel 1 .. n + +\newcount\maxstructuredepth + +\permanent\def\sectionlevel#1% + {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname} + +\permanent\def\namedsectionlevel#1#2% direct indirect + {\csname\??headlevel + \ifcsname\??headlevel#1\endcsname + #1% + \orelse\ifcsname\??headlevel#2\endcsname + #2% + \else + \v!none + \fi + \endcsname} + +\permanent\def\xthenamedheadlevel#1% + {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}} + +\setvalue{\??headlevel\v!block}{0} +\setvalue{\??headlevel\v!none }{-1} +\setvalue{\??headlevel\v!text }{-2} +\setvalue{\??headlevel\v!head }{-3} + +\newtoks\everydefinesection + +\permanent\protected\def\definesection[#1]% + {\ifcsname\??headlevel#1\endcsname \else + \edef\currentsection{#1}% not used, will go + \edef\currenthead{#1}% + \global\advance\maxstructuredepth\plusone + \setevalue{\??headlevel#1}{\the\maxstructuredepth}% + \setstructurelevel{#1}{\sectionlevel{#1}}% + \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER + \the\everydefinesection + % so far for these default inheritances + \definemarking[#1]% + \ifnum\maxstructuredepth>\plusone + \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child + \fi + \xdef\lastsectionname{#1}% + \ifempty\firstsectionname + \glet\firstsectionname\lastsectionname + \fi + \fi} + +\permanent\tolerant\protected\def\setupsection[#1]#*[#2]#*[#3]% + {\ifparameter#1\else + \push_macro_currenthead + \edef\currenthead{\ifcsname\??headlevel#1\endcsname#1\else\sectionheadsection{#1}\fi}% + \ifparameter#3\or + \edef\currenthead{\currenthead#2}% not used at any more in mkiv (sets now) + \setupcurrenthead[#3]% + \else + \setupcurrenthead[#2]% + \fi + \pop_macro_currenthead + \fi} + +% we share the parameters as sections are roots of heads so eventually we can +% consider \definesection -> \definehead with one argument + +\appendtoks + % This is a rather practical default that we don't want to + % be part of the parent chain lookup mechanism; it's also + % mkii compatible. Somewhat weird that it's part of the + % top level structure but it will be flattened anyway. + \let\currenthead\currentsection % + \setheadparameter\c!textstyle {\directheadparameter\c!style}% + \setheadparameter\c!textcolor {\directheadparameter\c!color}% + \setheadparameter\c!numberstyle{\directheadparameter\c!style}% + \setheadparameter\c!numbercolor{\directheadparameter\c!color}% +\to \everydefinesection + +% head -> head + +\permanent\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}} % can be done at lua end +\permanent\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}} % can be done at lua end + +\permanent\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling} +\permanent\def\sectionheadsection #1{\namedheadparameter{#1}\c!section} + +% head construction + +\newconditional\currentstructureown + +\newtoks\everybeforehead % hook, todo: before/after keys +\newtoks\everyafterhead % hook, todo: before/after keys + +\permanent\tolerant\protected\def\strc_sectioning_handle_own[#1]#*[#2]#:#*#=#*#=% [ref] {nr} {title} + {\settrue\currentstructureown + \triggerautostructurelevel + \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title -- + +\permanent\tolerant\protected\def\strc_sectioning_handle_nop[#1]#*[#2]% [ref] {title} / for taco: [key=value] variant + {\setfalse\currentstructureown + \triggerautostructurelevel + \ifhastok={#2}% + \expandafter\strc_sectioning_handle_nop_indeed_yes + \else + \expandafter\strc_sectioning_handle_nop_indeed_nop + \fi + {#1}{#2}} + +\def\strc_sectioning_handle_nop_indeed_yes#1#2% + {\strc_sectioning_handle{#1}{#2}{}} + +\def\strc_sectioning_handle_nop_indeed_nop#1#2#3% + {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- + +\permanent\tolerant\protected\def\strc_sectioning_start[#1]#*[#2]#*[#3]% for the moment no grouping, too annoying with page breaks + {\push_macro_currentnamedsection + \push_macro_currentstructurereferenceprefix + \edef\currentnamedsection{#1}% + \setfalse\currentstructureown + %\globalpushmacro\currenthead % this does not work out well + \xdef\currenthead{#1}% + \setsystemmode\currenthead % new, also here now + \headparameter\c!beforesection % beware, no users vars set yet + \the\everybeforehead + \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here) + % potential: \bgroup (can be optional: grouped = yes) + \headparameter\c!insidesection} + +\permanent\protected\def\strc_sectioning_stop[#1]% !!! also used at lua end + {\dostoptagged + \dostoptagged + % potential: \egroup + %\globalpopmacro\currenthead % so we do a hard recover + \xdef\currenthead{#1}% recover + \headparameter\c!aftersection + \the\everyafterhead + \resetsystemmode\currenthead + \pop_macro_currentstructurereferenceprefix + \pop_macro_currentnamedsection} % new, also here now + +\aliased\let\dostarthead\strc_sectioning_start % used at lua end +\aliased\let\dostophead \strc_sectioning_stop % used at lua end + +% todo: add grouping but where: before/after trickery .. probably inside because one can always add +% grouping to the before/after settings + +\aliased\let\startnamedsection\strc_sectioning_start + +\permanent\protected\def\stopnamedsection + {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}} + +% \newconditional\structurereversesectionnumbers % todo: key/val + +\newconditional\c_strc_sectioning_to_list +\newconditional\c_strc_sectioning_increment +\newconditional\c_strc_sectioning_place +\newconditional\c_strc_sectioning_empty +\newconditional\c_strc_sectioning_hidden +\newconditional\c_strc_sectioning_section + +\newconditional\headshownumber % public +\newconditional\headisdisplay % public +\newconditional\headissomewhere % public + +\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} +\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list} +\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} +\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} + +\protected\def\strc_sectioning_initialize_increment + {\edef\currentheadincrement{\headparameter\c!incrementnumber}% + \ifcsname\??headincrement\currentheadincrement\endcsname + \lastnamedcs + \else + \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list + % \filterheadnumber + \fi} + +\permanent\protected\def\filterheadnumber + {\settrue\c_strc_sectioning_increment + \settrue\c_strc_sectioning_to_list + \ifempty\currentproduct + % todo : filter from other toc (number, file, title) + % use : \currentheadincrement as spec + \fi} + +\setvalue{\??headplace\v!yes}% + {\setfalse\c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!empty}% + {\settrue \c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!no}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!hidden}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \settrue \c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!section}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \settrue \c_strc_sectioning_hidden + \settrue \c_strc_sectioning_section} + +\protected\def\strc_sectioning_initialize_placement + {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes} + +\newmode\v!sectionnumber + +\def\dosetstructureheadnumbercontent + {\setsystemmode\v!sectionnumber + \settrue\headshownumber} % why ? + +\def\doresetstructureheadnumbercontent + {\resetsystemmode\v!sectionnumber + \setfalse\headshownumber} % why ? + +\protected\def\strc_sectioning_initialize_number + {\edef\p_number{\sectionblockparameter\c!number}% + \ifx\p_number\v!yes + \edef\p_number{\headparameter\c!number}% + \ifx\p_number\v!yes + \settrue\headshownumber + \else + \setfalse\headshownumber + \fi + \else + \setfalse\headshownumber + \fi} + +% Beware, we do need some node for anchoring marks and normally a zwnj will +% do but it interferes so we deal with it at the \LUA\ end. + +\newtoks\everyheadsynchronization + +% \appendtoks +% \currentstructuresynchronize +% \to \everyheadsynchronization + +\aliased\let\currentstructuresynchronize\donothing + +\appendtoks + \currentstructuresynchronize + \enforced\glet\currentstructuresynchronize\donothing +\to \everyheadsynchronization + +\protected\def\theheadsynchonization + {% no, interferes: \signalcharacter + \the\everyheadsynchronization} + +% BEWARE: \marking[section]{my text} does not work as we use list indices instead +% so we need a 'keep track of raw set option' (or maybe a funny internal prefix) + +\permanent\protected\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this} + {\strc_sectioning_delayed_flush + \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}} + +\let\deepstructurenumbercommand\relax +\let\deepstructuretitlecommand \relax + +\permanent\protected\def\fullheadnumber + {\edef\currentheadlabeltag{\currentsectionblock\c!label}% + \dostarttagged\t!sectionnumber\empty + \labeltexts + {\headparameter\currentheadlabeltag} + {\ifx\deepstructurenumbercommand\relax + \structurenumber + \else + \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}% + \fi}% + \dostoptagged} + +\permanent\protected\def\fullheadtitle + {\dostarttagged\t!sectiontitle\empty + \ifx\deepstructuretitlecommand\relax + \structuretitle + \else + \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}% + \fi + \dostoptagged} + +\let\currenthead \empty +\let\currentheadcoupling\empty +\let\currentheadsection \empty +\let\currentheadlevel \!!zerocount +\let\currentheadcounter \!!zerocount + +\let\strc_show_used\relax + +\installtextracker + {structures.showused} + {\let\strc_show_used\clf_showstructure} + {\let\strc_show_used\relax} + +\appendtoks + \strc_show_used +\to \everystoptext + +\protected\def\strc_sectioning_report{\clf_reportstructure} + +\ifdefined\strc_rendering_initialize_style_and_color \else + + \protected\def\strc_rendering_initialize_style_and_color#1#2% + {\dontconvertfont + \useheadstyleandcolor\c!style\c!color + \useheadstyleandcolor#1#2% + \setupinterlinespace} + +\fi + +\permanent\tolerant\protected\def\placeheadtext[#1]% + {\dontleavehmode + \begingroup + \protected\def\\{\space}% messy here, but the default (and needs to be grouped) + \global\settrue\headisdisplay % triggers interlinespace checking + \edef\currenthead{#1}% maybe only when #1 is given + \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor + \relax + \getspecificstructuretitle{\thenamedheadlevel{#1}}% + \endgraf + \endgroup} + +\permanent\tolerant\protected\def\placeheadnumber[#1]% + {\dontleavehmode + \begingroup + \global\settrue\headisdisplay % triggers interlinespace checking + \edef\currenthead{#1}% maybe only when #1 is given + \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor + \relax + \getfullstructurenumber{\thenamedheadlevel{#1}}% + \endgraf + \endgroup} + +\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi + +\newtoks\everybeforesectionheadhandle +\newtoks\everyaftersectionheadhandle + +\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller) + {\xdef\currenthead {#1}% + \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}% + \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}% + \xdef\currentheadlevel {\sectionlevel \currentheadsection}% + % + %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}% + % + \strc_sectioning_initialize_autolevel + \strc_sectioning_initialize_increment + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + % + \the\everybeforesectionheadhandle + % + % todo: also mark (for header) + % + % we might remove the lower level + % + % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}% + % +% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call + % + % \currentstructuresynchronize % will move + % + \let\getheadnumber\empty + \let\getheadtitle \empty + \let\getheadsyncs \empty + \ifconditional\c_strc_sectioning_increment + \ifconditional\c_strc_sectioning_place + \strc_sectioning_before_yes + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \let\getheadtitle\fullheadtitle + \ifconditional\headshownumber + \let\getheadnumber\fullheadnumber + \strc_rendering_place_head_number_and_text + \else + \strc_rendering_place_head_text + \fi + \dostoptagged + \strc_sectioning_after_yes + \orelse\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \ifconditional\c_strc_sectioning_section + \strc_rendering_place_head_section + \else + \strc_rendering_place_head_hidden % only something when tracing + \fi + \dostoptagged + \else + \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \strc_rendering_place_head_empty % just flush 'm + \dostoptagged + \strc_sectioning_after_nop + \fi + \else + \ifconditional\c_strc_sectioning_place + \strc_sectioning_before_yes + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \let\getheadtitle\fullheadtitle + \strc_rendering_place_head_text + \dostoptagged + \strc_sectioning_after_yes + \orelse\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \let\getheadsyncs\theheadsynchonization + \dostarttagged\t!sectioncaption\empty + \ifconditional\c_strc_sectioning_section + \strc_rendering_place_head_section + \else + \strc_rendering_place_head_hidden % only something when tracing + \fi + \dostoptagged + \else + % do nothing / should be vbox to 0pt + \strc_sectioning_before_nop + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \strc_rendering_place_head_empty % just flush 'm + \dostoptagged + \strc_sectioning_after_nop + \fi + \fi + % + \the\everyaftersectionheadhandle + % + \setfalse\c_strc_sectioning_ignore_page + % ignorespaces prevents spaces creeping in when after=\dontleavehmode + \dostarttagged\t!sectioncontent\empty + \ifempty\currentstructureplaceholder + \ifconditional\headisdisplay + \doubleexpandafter\ignorespaces + \else + \doubleexpandafter\ignorepars + \fi + \else + \expandafter\strc_sectioning_placeholder + \fi} + +%D \starttyping +%D \startsubject[placeholder=todo,title=one] +%D whatever one +%D \stopsubject +%D \stoptyping + +\def\strc_sectioning_placeholder + {\placeholder[\currentstructureplaceholder]% + \gobblenested{\e!start\currenthead}{\e!stop\currenthead}{\e!stop\currenthead}} + +% typesetting (the getters are public) + +\protected\def\strc_rendering_place_head_number_and_text + {\setheadmarking + \getheadnumber/\getheadtitle + \getheadsyncs} + +\protected\def\strc_rendering_place_head_text + {\setheadmarking + \getheadtitle + \getheadsyncs} + +\protected\def\strc_rendering_place_head_empty + {\setheadmarking + \getheadsyncs} + +\installcorenamespace{hiddenheadattr} +\installcorenamespace{hiddenheadsync} + +% todo: when in the page builder we need to resolve the marking immediately +% because otherwise we have an async + +\newbox\b_sectioning_delayed + +\def\strc_sectioning_delayed_flush + {\ifvoid\b_sectioning_delayed\else + \smashedbox\b_sectioning_delayed + \fi} + +\protected\def\strc_rendering_place_head_section % see hidden below + {\global\setbox\b_sectioning_delayed\hpack\bgroup + \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% + \hpack\headreferenceattributes{}% also does the mark + \theheadsynchonization + \egroup} + +\protected\def\strc_rendering_place_head_hidden % maybe trialtypesetting check + {\xdefcsname\??hiddenheadattr\currenthead\endcsname + {\headreferenceattributes}% can be used when making a box + \xdefcsname\??hiddenheadsync\currenthead\endcsname + {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax + \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% + \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference + \theheadsynchonization}} % and it's a node anyway + +\permanent\def\synchronizehead #1{\begincsname\??hiddenheadsync#1\endcsname} +\permanent\def\theheadreferenceattributes#1{\begincsname\??hiddenheadattr#1\endcsname} + +\permanent\protected\def\placerawheaddata [#1]{\synchronizehead{#1}} +\permanent\protected\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}} +\permanent\protected\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}} + +\permanent\protected\def\repeathead[#1]% + {\begingroup + \setupinteraction[\c!state=\v!stop]% + \def\currenthead{#1} + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs \relax + \def\getheadtitle {\getmarking[#1]} + \def\getheadnumber{\getmarking[#1\v!number]} + \strc_sectioning_before_yes + \ifconditional\headshownumber + \strc_rendering_place_head_number_and_text + \else + \strc_rendering_place_head_text + \fi + \dostoptagged + \strc_sectioning_after_yes + \endgroup} + +% \setuphead[chapter][placehead=hidden] +% \chapter {test} +% +% %(\synchronizehead{chapter}) % \getheadsyncs +% %(\getfullstructurenumber{\thenamedheadlevel{chapter}}) +% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}}) +% +% (\placerawheaddata [chapter]) +% (\placerawheadnumber[chapter]) +% (\placerawheadtext [chapter]) + +% pagebreaks + +\letvalue{\??headmarknop\v!page }\donothing +\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks} +\letvalue{\??headmarknop\s!unknown}\donothing + +\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks} +\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks} +\letvalue{\??headmarkyes\s!unknown}\donothing + +\def\strc_sectioning_check_layout + {\edef\p_page{\headparameter\c!page}% + \ifempty\p_page + \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}% + \ifempty\p_header \else + \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing + \fi + \edef\p_text{\headparameter\c!text}% + \ifempty\p_text \else + \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing + \fi + \edef\p_footer{\headparameter\c!footer}% + \ifempty\p_footer \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 \d_strc_sectioning_continuous_signal + +\protected\def\strc_sectioning_inject_continuous_signal + {\ifhmode + \hskip\d_strc_sectioning_continuous_signal\relax + \fi} + +% \let\dotagsectionlevel\relax + +\def\strc_sectioning_before_yes + {\strc_sectioning_check_before\strc_sectioning_handle_page_yes + \headparameter\c!inbetween + \dostarttaggedchained\t!section\currenthead\??head +% \dotagsectionlevel + } + +\def\strc_sectioning_before_nop + {\strc_sectioning_check_before\strc_sectioning_handle_page_nop + \headparameter\c!inbetween + \dostarttagged\currenthead\empty} % this is a weird one .. needs checking + +\def\strc_sectioning_empty_correction + {\ifconditional\c_strc_sectioning_empty + % this needs checking + \penalty\plustenthousand + \vskip-\lineheight + \kern\zeropoint + \prevdepth\strutdepth + \fi} + +\def\strc_sectioning_after_nop + {} + +\def\strc_sectioning_check_before#1% + {\ifhmode + \scratchcounter\lastpenalty + \unpenalty % no beauty in this + \ifdim\lastskip=\d_strc_sectioning_continuous_signal + % no page break + \ifconditional\c_strc_sectioning_ignore_page + \setfalse\c_strc_sectioning_ignore_page + \else + \global\c_strc_sectioning_preceding_level\currentheadlevel + \nobreak + \fi + % \global\settrue\c_strc_rendering_continuous + \else + \penalty\scratchcounter + % \global\setfalse\c_strc_rendering_continuous + #1% + \fi + \else + % \global\setfalse\c_strc_rendering_continuous + #1% + \fi} + +%permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} +%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} + +\permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} +%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} +\permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax} + +\let\previoushead\empty + +\def\strc_sectioning_handle_page_nop + {\edef\p_continue{\headparameter\c!continue}% + \ifx\p_continue\v!yes + \ifx\currenthead\previoushead % not really needed + \strc_sectioning_check_layout + \orelse\ifnum\previoussectioncountervalue=\zerocount + \strc_sectioning_check_layout + \orelse\ifnum\currentsectioncountervalue>\zerocount + \strc_sectioning_check_layout + \fi + \else + \strc_sectioning_check_layout + \fi + \glet\previoushead\currenthead} + + +\def\strc_sectioning_handle_page_yes + {\ifconditional\c_strc_sectioning_ignore_page + \setfalse\c_strc_sectioning_ignore_page + \else + % beware, these numbers are not yet know here + \strc_sectioning_handle_page_nop + \edef\p_aligntitle{\headparameter\c!aligntitle}% + \ifx\p_aligntitle\v!float + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\zerocount + \fi + \headparameter\c!before\relax + \indent + \else + \page_otr_command_flush_side_floats + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\zerocount + \fi + \headparameter\c!before\relax + \fi + \global\c_strc_sectioning_preceding_level\currentheadlevel + \fi + \glet\previoushead\currenthead} + +\def\strc_sectioning_depth_correction + {\ifvmode + \edef\p_depthcorrection{\headparameter\c!depthcorrection}% + \ifx\p_depthcorrection\v!strut + \prevdepth\strutdepth + \fi + \fi} + +\def\strc_sectioning_after_yes + {\ifconditional\headisdisplay + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\plusone + \fi + \strc_sectioning_empty_correction + \headparameter\c!after + \strc_sectioning_depth_correction + \fi} + +\protected\def\strc_sectioning_prevent_page_break % see strc-con + {\ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\plustwo + \fi} + + +% We do support negative numbers but it can have side effects that we won't catch: +% +% \chapter{some} \setupheadnumber[chapter][3] \chapter{more} +% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d} + +\permanent\def\thenamedheadlevel#1% + {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}} + +\permanent\tolerant\protected\def\setupheadnumber[#1]#*[#2]% todo: reset if at other level + {\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}} + +\def\currentheadnumber{0} % ==> \currentheadnumber + +\permanent\protected\def\determineheadnumber[#1]% + {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}} + +% The previous macro is been replaced by the expandable: + +\permanent\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}} +\permanent\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}} + +\permanent\tolerant\protected\def\headnumber[#1]#*[#2]% simple case is just a number + {\getsomefullstructurenumber{\ifparameter#1\or\thenamedheadlevel{#1}\fi}{#2}} + +\permanent\tolerant\protected\def\someheadnumber[#1]#*[#2]% + {\dontleavehmode + \begingroup + \edef\currenthead{#1}% + \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}% + \endgroup} + +\aliased\let\sectioncountervalue\structurevalue + +\def\currentheadtext{obsolete,\space use marks} + +% list references, will be redone in lua when we need it + +\let\startlistreferences\relax +\let\stoplistreferences \relax + +% experimental + +\newconditional\c_strc_sectioning_auto_levels + +\appendtoks + \settrue\c_strc_sectioning_auto_levels +\to \everyenableelements + +\protected\def\strc_sectioning_initialize_autolevel + {\ifconditional\c_strc_sectioning_auto_levels + \clf_autonextstructurelevel\currentheadlevel\relax + \global\setfalse\c_strc_sectioning_auto_levels + \fi} + +\permanent\protected\def\triggerautostructurelevel + {\global\settrue\c_strc_sectioning_auto_levels} + +\permanent\protected\def\finalizeautostructurelevels + {\clf_autofinishstructurelevels} + +\permanent\protected\def\finalizeautostructurelevel + {\dostoptagged + \dostoptagged} + +\appendtoks + \finalizeautostructurelevels +\to \everystoptext + +\stopcontextdefinitioncode + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-syn.mkxl b/tex/context/base/mkxl/strc-syn.mkxl new file mode 100644 index 000000000..6f2f255d5 --- /dev/null +++ b/tex/context/base/mkxl/strc-syn.mkxl @@ -0,0 +1,658 @@ +%D \module +%D [ file=strc-syn, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Synonyms and Sorting, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting} + +\registerctxluafile{strc-syn}{} + +%D Although we could nowadays build this on top of regular lists we keep this +%D more efficient variant around. Eventually we can add some options to lists +%D that also provide such functionality but at the cost of much more overhead. +%D +%D We show a usage of both synonyms and sorts, which are deep down variants of +%D so called simple lists. A definition looks like this: +%D +%D \startbuffer +%D \definesynonyms +%D [myabbreviation] +%D +%D \setupsynonyms +%D [myabbreviation] +%D [headstyle=bold, +%D headcolor=darkred, +%D synonymstyle=boldslanted, +%D synonymcolor=darkblue, +%D textstyle=slanted, +%D textcolor=darkgreen, +%D style=normal, +%D color=darkyellow] +%D +%D \definesorting +%D [mylogo] +%D +%D \setupsorting +%D [mylogo] +%D [style=bold, +%D color=darkmagenta] +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D More complex definitions involves commands to call up meanings and such. The +%D use of the defined commands is as follows: \ +%D +%D \startbuffer +%D \myabbreviation [FIRST] {TheFirst} {The First Words} +%D \myabbreviation [SECOND] {TheSecond} {The Second Words} +%D \myabbreviation [THIRD] {TheThird} {The Third Words} +%D +%D \mylogo [FOURTH] {TheFourth} +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D By default a synonym is just typeset and flagges as being used, so that in +%D a list it wil be shows with its meaning. You can however also expand the +%D meaning automatically at first use: +%D +%D \startbuffer +%D \setupsynonyms[myabbreviation][alternative=first] +%D +%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. +%D +%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D We can change the order, as demonstrated in: +%D +%D \startbuffer +%D \resetshownsynonyms[myabbreviation] +%D +%D \setupsynonyms[myabbreviation][alternative=last] +%D +%D We have \FIRST\ and \THIRD\ or \FOURTH. +%D +%D We have \FIRST\ and \THIRD\ or \FOURTH. +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D A list is called up with: +%D +%D \startbuffer +%D \placelistofsynonyms[myabbreviation] +%D +%D \placelistofsorts[mylogo] +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D The lists are constructions (like descriptions are) and can be set up +%D likewise. + +% todo: add 'define only' option to descriptions, then add sorting (also based on key) +% and call to definition -> replaces this module + +\unprotect + +% split but common in lua + +\permanent\protected\def\preprocessexpansion#1#2#3#4% do this at the lua end if still needed + {\ifx#1\s!xml + \xmlstartraw + \xdef#2{#4}% + \xmlstopraw + \glet#3\s!xml + \else + \ifx#1\v!yes + \xdef#2{#4}% + \else + \xdef#2{\detokenize{#4}}% + \fi + \glet#3\s!tex + \fi} + +%D We now use a simple list variant: + +\installcorenamespace {simplelist} + +\installcommandhandler \??simplelist {simplelist} \??simplelist + +\let\setupsimplelists\setupsimplelist + +\setupsimplelists[% + %c!title=, + %c!text=, + % + %c!style=, + %c!color=, + %c!command=, + %c!align=, + % + %c!headstyle=, + %c!headcolor=, + %c!headalign=, + % + %c!titlestyle=, + %c!titlecolor=, + %c!titlecommand=, + %c!titleleft=, + %c!titleright=, + % + %c!closesymbol=, + %c!closecommand=, + % + \c!alternative=\v!left, + \c!display=\v!yes, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %c!hang=, + %c!sample=, + \c!margin=\v!no, + \c!before=\startpacked, + \c!inbetween=\blank, + \c!after=\stoppacked, + %c!indentnext=, + %c!indenting=, + % + \c!expansion=\v!no, + %c!xmlsetup=, + %s!catcodes=, + \s!language=\currentmainlanguage, +] + +\appendtoks + \setfalse\c_strc_constructions_define_commands + \ifempty\currentsimplelistparent + \defineconstruction[\currentsimplelist][\s!handler=\v!simplelist,\c!level=1]% + \else + \defineconstruction[\currentsimplelist][\currentsimplelistparent][\s!handler=\v!simplelist,\c!level=1]% + \fi + \settrue\c_strc_constructions_define_commands +\to \everydefinesimplelist + +\setuvalue{\??constructioninitializer\v!simplelist}% + {\let \currentsimplelist \currentconstruction + \enforced\let\constructionparameter \simplelistparameter + \enforced\let\constructionnamespace \??simplelist + \enforced\let\detokenizedconstructionparameter\detokenizedsimplelistparameter + \enforced\let\letconstructionparameter \letsimplelistparameter + \enforced\let\useconstructionstyleandcolor \usesimpleliststyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentsimplelist} + +\setuvalue{\??constructionfinalizer\v!simplelist}% + {} + +\setuvalue{\??constructiontexthandler\v!simplelist}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \the\everyconstruction + \constructionparameter\c!headcommand + {\strut + \currentsimplelistentry}% + \endgroup} + +% And we build on top of this. + +\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi +\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi + +\definesimplelist + [\v!synonym] + [\c!state=\v!start, + %\c!synonymstyle=, + %\c!textstyle=, + %\c!headstyle=, + %\c!headcolor=, + %\c!criterium=, + \c!location=\v!left, + \c!width=5\emwidth, + \c!distance=\zeropoint, + %\c!sample=, + %\c!hang=, + %\c!align=, + %\c!before=, + %\c!inbetween=, + %\c!after=, + \c!indentnext=\v!no, + %\c!expansion=, + \c!method=] + +\aliased\let\setupsynonyms\setupsimplelist + +\permanent\tolerant\protected\def\definesynonyms[#1]#*[#2]#*[#3]#*[#4]% name plural \meaning \use + {\ifnum\lastarguments=\plusfour + \protected\instance\def#4##1{\strc_synonyms_insert{#1}{##1}}% name tag + \frozen\instance\setuvalue{#1}{\definesynonym[\v!no][#1]}% \name + \else + \frozen\instance\setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name + \fi + \ifparameter#3\or + \frozen\instance\protected\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning + \fi + \edef\currentsynonym{#1}% + % + %\checksynonymparent + %\setupcurrentsynonym[\s!single={#1},\s!multi={#2}]% + \setfalse\c_strc_constructions_define_commands + \definesimplelist + [\currentsynonym]% + [\v!sorting] + [\s!single={#1},% + \s!multi={#2}]% + \settrue\c_strc_constructions_define_commands + \ifparameter#2\or + % + \presetheadtext[#2=\Word{#2}]% changes the \if...argument + % + % These will go away. Actually the overloads catched this empty case! + % + \frozen\instance\setuvalue{\e!setup #2\e!endsetup}{\setupsynonyms[#1]}% obsolete definition + \frozen\instance\setuvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument + \frozen\instance\setuvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}% + \fi} + +\permanent\tolerant\protected\def\definesynonym[#1]#*[#2]#*[#3]% + {\begingroup + \edef\currentsynonymoption{#1}% + \edef\currentsynonym{#2}% + \edef\currentsynonymtag{#3}% + \strc_synonyms_define_entry} + +\def\strc_synonyms_define_entry#1#2% + {\let\currentsimplelist\currentsynonym + \ifempty\currentsynonymtag + \edef\currentsynonymtag{#1}% + \fi + \ifempty\currentsynonymtag \else + % this is not that efficient, esp when we load a big list + \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}% + \preprocessexpansion\currentsynonymexpansion\m_synonyms_text \currentsynonymcoding{#1}% + \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#2}% + % + \clf_registersynonym + {\currentsynonym}% + {synonym}% + {% + metadata {% + catcodes \catcodetable + coding {\currentsynonymcoding}% + \ifx\currentsynonymcoding\s!xml + xmlroot {\xmldocument}% + \fi + }% + definition {% + tag {\currentsynonymtag}% + synonym {\m_synonyms_text}% + meaning {\m_synonyms_meaning}% + % used false + }% + }% + \relax + \ifx\currentsynonymoption\v!yes + \instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}% + \fi + \fi + \endgroup} + +\permanent\tolerant\protected\def\registersynonym [#1]#*[#2]{\clf_registerusedsynonym{#1}{#2}} +\permanent \protected\def\currentsynonymname {\clf_synonymname{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\resetusedsynonyms [#1]{\clf_resetusedsynonyms{#1}} +\permanent \protected\def\resetshownsynonyms [#1]{\clf_resetshownsynonyms{#1}} + +\aliased\let\rawsynonymname \clf_synonymname +\aliased\let\rawsynonymmeaning\clf_synonymmeaning + +\installcorenamespace{simplelistalternative} % specific ways of rendering a list +\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local) + +\installcommandhandler \??simplelistalternative {simplelistalternative} \??simplelistalternative + +\setupsimplelist + [\v!synonym] + [\c!alternative=\v!normal] + +\protected\def\strc_synonyms_insert_meaning#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + \def\currentsimplelist{#1}% + \def\currentsynonymtag{#2}% + \fastsetup{\??simplelistrenderings::\v!text}% + \endgroup} + +\protected\def\strc_synonyms_insert#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + \edef\currentsimplelist{#1}% + \let\currentsynonym\currentsimplelist % for a while + \def\currentsynonymtag{#2}% + \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% + \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative + {\let\currentsimplelistalternative\v!normal}% + \fastsetup{\??simplelistrenderings:\v!synonym:\currentsimplelistalternative}% + \normalexpanded{\endgroup\simplelistparameter\c!next}} + +% \setupsimplelistalternative +% [\c!command=\directsimplelistparameter\c!command] + +\definesimplelistalternative + [\v!normal] + [\c!inbetween=\space, + \c!left=(, + \c!right=)] + +\definesimplelistalternative + [\v!first] + [\v!normal] + +\definesimplelistalternative + [\v!last] + [\v!normal] + +\startsetups[\??simplelistrenderings::\v!synonym] + \begingroup + \dostarttaggedchained\t!synonym\currentsynonym\??simplelist + \dotagsynonym + \usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor + \simplelistparameter\c!synonymcommand{\currentsynonymname}% + \dostoptagged + \endgroup +\stopsetups + +\startsetups[\??simplelistrenderings::\v!text] + \begingroup + \usehyphensparameter\simplelistparameter + \usesimpleliststyleandcolor\c!textstyle\c!textcolor + \simplelistparameter\c!textcommand{\currentsynonymmeaning}% + \endgroup +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!normal] + \fastsetup{\??simplelistrenderings::\v!synonym} +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!first] + \fastsetup{\??simplelistrenderings::\v!synonym} + \doifelsecurrentsynonymshown \donothing { + \simplelistalternativeparameter\c!inbetween + \simplelistalternativeparameter\c!left + \fastsetup{\??simplelistrenderings::\v!text} + \simplelistalternativeparameter\c!right + } +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!last] + \doifelsecurrentsynonymshown { + \fastsetup{\??simplelistrenderings::\v!synonym} + } { + \fastsetup{\??simplelistrenderings::\v!text} + \simplelistalternativeparameter\c!inbetween + \simplelistalternativeparameter\c!left + \fastsetup{\??simplelistrenderings::\v!synonym} + \simplelistalternativeparameter\c!right + } +\stopsetups + +\permanent\tolerant\protected\def\placelistofsynonyms[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \doifelsecommandhandler\??simplelist\currentsimplelist + {\strc_constructions_initialize{#1}% + \setupcurrentsimplelist[#2]% + \let\synonymentry\strc_synonym_normal + % so we can hook tabulate into before and after + \normalexpanded{\simplelistparameter\c!before + \noexpand\clf_processsynonyms + {#1}% + {% + criterium {\simplelistparameter\c!criterium}% + language {\simplelistparameter\s!language}% + method {\simplelistparameter\c!method}% + }% + \relax + \simplelistparameter\c!after}% + \relax}% + {}% todo: message that invalid + \endgroup} + +\permanent\tolerant\protected\def\completelistofsynonyms[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \doifelsecommandhandler\??simplelist\currentsimplelist + {\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% + \strc_synonyms_place_list[#1][#2]% + \page + \stopnamedsection}% + {}% todo: message that invalid + \endgroup} + +\protected\def\strc_synonym_normal#1#2#3#4% + {\begingroup + \def\currentsimplelistentry{#3}% + \csname\??constructionstarthandler\v!construction\endcsname + #4% + \csname\??constructionstophandler\v!construction\endcsname + \endgroup} + +%D Sorting (a simplified version of synonym). + +\definesimplelist + [\v!sorting] + [\c!state=\v!start, + %\c!command=, % we test for defined ! + %\c!criterium=, + %\c!style=, + \c!before=\startpacked, + \c!after=\stoppacked, + %\c!expansion=, + \c!method=] + +\aliased\let\setupsorting\setupsimplelist + +% if #3=\relax or \v!none, then no command but still protected + +\permanent\tolerant\protected\def\definesorting[#1]#*[#2]#*[#3]% + {\ifnum\lastarguments=\plusthree + \doifnot{#3}\v!none + {\ifx#3\relax \else + \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}% + \fi}% + \frozen\instance\setuvalue{#1}{\definesort[\v!no][#1]}% + \else + \frozen\instance\setuvalue{#1}{\definesort[\v!yes][#1]}% + \fi + \edef\currentsorting{#1}% + \setfalse\c_strc_constructions_define_commands + \definesimplelist + [\currentsorting]% + [\v!sorting] + [\s!single={#1},% + \s!multi={#2}]% + \settrue\c_strc_constructions_define_commands + \ifparameter#2\or + % + \presetheadtext[#2=\Word{#2}]% changes the \if...argument + % + % These will go away. Actually the overloads catched this empty case! + % + % + \presetheadtext[#2=\Word{#2}]% + % + \frozen\instance\setuvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition + \frozen\instance\setuvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}% + \frozen\instance\setuvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}% + \fi} + +\permanent\tolerant\protected\def\definesort[#1]#*[#2]#*[#3]% + {\begingroup + \edef\currentsortingoption{#1}% + \edef\currentsorting{#2}% + \edef\currentsortingtag{#3}% + \strc_sorting_define_entry} + +\def\strc_sorting_define_entry#1% + {\let\currentsimplelist\currentsimplelist + \ifempty\currentsortingtag + \edef\currentsortingtag{#1}% + \fi + \ifempty\currentsortingtag \else + \edef\currentsortingexpansion{\simplelistparameter\c!expansion}% + \preprocessexpansion\currentsortingexpansion\currentsortingtext\currentsortingcoding{#1}% + \clf_registersynonym + {\currentsorting}% + {sorting}% + {% + metadata {% + catcodes \catcodetable + coding {\currentsortingcoding}% + \ifx\currentsortingcoding\s!xml + xmlroot {\xmldocument}% + \fi + }% + definition {% + tag {\currentsortingtag}% + synonym {\currentsortingtext}% + % used false + }% + }% + \relax + \ifx\currentsortingoption\v!yes + \instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}% + \fi + \fi + \endgroup} + +\permanent\protected\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}} +\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}} +\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}} + +\setupsimplelist + [\v!sorting] + [\c!alternative=\v!normal] + +\protected\def\strc_sorting_insert#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + % no kap currently, of .. we need to map cap onto WORD + \edef\currentsorting{#1}% + \edef\currentsortingtag{#2}% + \let\currentsimplelist\currentsorting + \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% + \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative + {\let\currentsimplelistalternative\v!normal}% + \fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}% + \normalexpanded{\endgroup\simplelistparameter\c!next}} + +% or: +% +% \doifelsesetups{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative} +% {\fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}} +% {\fastsetup{\??simplelistrenderings:\v!sorting:\v!normal}} + +\startsetups [\??simplelistrenderings:\v!sorting:\v!normal] + \fastsetup{\??simplelistrenderings::\v!sorting}% +\stopsetups + +\startsetups [\??simplelistrenderings::\v!sorting] + \begingroup + \dostarttaggedchained\t!sorting\currentsorting\??simplelist + \dotagsorting + \usesimpleliststyleandcolor\c!style\c!color + \currentsortingname + \dostoptagged + \endgroup +\stopsetups + +\permanent\tolerant\protected\def\registersort[#1]#*[#2]% + {\clf_registerusedsynonym{#1}{#2}} + +% before after +% +% maybe just 'commandset' and then combine + +\permanent\tolerant\protected\def\placelistofsorts[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \strc_constructions_initialize{#1}% + \setupcurrentsimplelist[#2]% + \edef\p_simplelist_command{\simplelistparameter\c!command}% + \ifempty\p_simplelist_command + \let\synonymentry\strc_sorting_normal + \else + \let\synonymentry\strc_sorting_command + \fi + % so we can hook tabulate into before and after + \normalexpanded{\simplelistparameter\c!before + \noexpand\clf_processsynonyms + {#1}% + {% + criterium {\simplelistparameter\c!criterium}% + language {\simplelistparameter\s!language}% + method {\simplelistparameter\c!method}% + }% + \relax + \simplelistparameter\c!after}% + \endgroup} + +\permanent\tolerant\protected\def\completelistofsorts[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% + \strc_sorting_place_list[#1][#2]% + \page + \stopnamedsection + \endgroup} + +\def\strc_sorting_command#1#2#3#4% #4 is meaning but empty here + {\p_simplelist_command{#1}{#2}{#3}} + +\def\strc_sorting_normal#1#2#3#4% #4 is meaning but empty here + {\begingroup + \usesimpleliststyleandcolor\c!style\c!color + #3% + \endgroup + \par} + +%D Presets. + +% To be considered: +% +% \setupsimplelist +% [\v!sorting] +% [\c!headstyle=\simplelistparameter\c!synonymstyle, +% \c!headcolor=\simplelistparameter\c!synonymcolor, +% \c!style=\simplelistparameter\c!textstyle, +% \c!color=\simplelistparameter\c!textcolor] + +\definesynonyms + [\v!abbreviation] + [\v!abbreviations] + [\infull] + +\setupsynonyms + [\v!abbreviation] + [\c!hyphens=\v!no, % new, not yet in setup definitions + \c!textstyle=\v!capital] + +\definesorting + [\v!logo] + [\v!logos] +% [\logogram] % no + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-tag.lmt b/tex/context/base/mkxl/strc-tag.lmt new file mode 100644 index 000000000..11049abe0 --- /dev/null +++ b/tex/context/base/mkxl/strc-tag.lmt @@ -0,0 +1,615 @@ +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 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 texgetattribute = tex.getattribute +local texsetattribute = tex.setattribute + +local taglist = allocate() -- access by attribute +local specifications = allocate() -- access by fulltag +local labels = allocate() +local stack = { } +local chain = { } +local ids = { } +local enabled = false +local tagcontext = { } +local tagpatterns = { } +local lasttags = { } +local stacksize = 0 +local metadata = nil -- applied to the next element +local documentdata = { } +local extradata = false + +local tags = structures.tags +tags.taglist = taglist -- can best be hidden +tags.labels = labels +tags.patterns = tagpatterns +tags.specifications = specifications + +function tags.current() + if stacksize > 0 then + return stack[stacksize] -- maybe copy or proxy + end +end + +-- Tags are internally stored as: +-- +-- 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 { -- todo: more "record = true" to improve formatting + + 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" }, + sectioncaption = { pdf = "Div", nature = "display", record = true }, + 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" }, + linenumber = { pdf = "Span", nature = "inline" }, + + 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" }, + tableheadcell = { pdf = "TH", nature = "mixed" }, + tablehead = { pdf = "THEAD", nature = "display" }, + tablebody = { pdf = "TBODY", nature = "display" }, + tablefoot = { pdf = "TFOOT", nature = "display" }, + + tabulate = { pdf = "Table", nature = "display" }, + tabulaterow = { pdf = "TR", nature = "display" }, + tabulatecell = { pdf = "TD", nature = "mixed" }, + tabulateheadcell = { pdf = "TH", nature = "mixed" }, + tabulatehead = { pdf = "THEAD", nature = "display" }, + tabulatebody = { pdf = "TBODY", nature = "display" }, + tabulatefoot = { pdf = "TFOOT", nature = "display" }, + + 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" }, + listtext = { pdf = "Span", nature = "inline" }, + + 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" }, + reference = { pdf = "Span", nature = "inline" }, + + margintextblock = { pdf = "Span", nature = "inline" }, + margintext = { pdf = "Span", nature = "inline" }, + marginanchor = { pdf = "Span", nature = "inline" }, + + math = { pdf = "Div", nature = "inline" }, -- no display + mn = { pdf = "Span", nature = "mixed" }, + 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" }, + + publications = { pdf = "Div", nature = "display" }, + publication = { pdf = "Div", nature = "mixed" }, + pubfld = { pdf = "Span", nature = "inline" }, + + block = { pdf = "Div", nature = "display" }, + userdata = { pdf = "Div", nature = "display" }, + +} + +tags.properties = properties + +local patterns = setmetatableindex(function(t,tag) + local v = topattern("^" .. tag .. ">") + t[tag] = v + return v +end) + +function tags.locatedtag(tag) + local attribute = texgetattribute(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[texgetattribute(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.getmetadata() + return documentdata or { } +end + +function tags.registerextradata(name,serializer) + if type(serializer) == "function" then + if extradata then + extradata[name] = serializer + else + extradata = { [name] = serializer } + end + end +end + +function tags.getextradata() + return extradata +end + +function tags.start(tag,specification) + if not enabled then + codeinjections.enabletags() + 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 userdata == "" then + specification.userdata = nil + elseif 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 + -- + texsetattribute(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 + texsetattribute(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 + texsetattribute(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 = "strc_tags_start", + public = true, + protected = true, + actions = starttag, + arguments = "argument", +} + +implement { + name = "strc_tags_stop", + public = true, + protected = true, + actions = tags.stop, +} + +implement { + name = "strc_tags_start_userdata", + public = true, + protected = true, + actions = function(tag,userdata) starttag(tag,{ userdata = userdata }) end, + arguments = { "optional", "optional" }, +} + +implement { + name = "strc_tags_start_detail", + public = true, + protected = true, + actions = function(tag,detail) starttag(tag,{ detail = detail }) end, + arguments = "2 arguments", +} + +implement { + name = "strc_tags_start_ignore", + public = true, + protected = true, + actions = function(detail) starttag("ignore",{ detail = detail }) end, + arguments = { "argument" }, +} + +implement { + name = "strc_tags_start_chained", + public = true, + protected = true, + actions = function(tag,detail,parents) starttag(tag,{ detail = detail, parents = parents }) end, + arguments = "3 arguments", +} + +implement { + name = "strc_tags_set_aspect", + public = true, + protected = true, + actions = tags.setaspect, + arguments = "2 arguments" +} + +implement { + name = "settagproperty", + actions = tags.setproperty, + arguments = "3 arguments" +} + +implement { + name = "setelementbackendtag", + public = true, + protected = true, + actions = tags.setproperty, + arguments = { "optional", "'backend'", "optional" }, +} + +implement { + name = "setelementnature", + public = true, + protected = true, + actions = tags.setproperty, + arguments = { "optional", "'nature'", "optional" }, +} + +implement { + name = "strc_tags_get_element_tag", + public = true, + protected = true, + actions = { tags.elementtag, context } +} + +implement { + name = "strc_tags_set_element_user_properties", + public = true, + protected = true, + actions = tags.setuserproperties, + arguments = { "optional", "optional" }, +} + +implement { + name = "doifelseinelement", + public = true, + protected = true, + actions = { structures.atlocation, commands.testcase }, + arguments = "argument", +} + +implement { + name = "settaggedmetadata", + public = true, + protected = true, + actions = tags.registermetadata, + arguments = "optional", +} diff --git a/tex/context/base/mkxl/strc-tag.mkxl b/tex/context/base/mkxl/strc-tag.mkxl new file mode 100644 index 000000000..08d8fef6c --- /dev/null +++ b/tex/context/base/mkxl/strc-tag.mkxl @@ -0,0 +1,531 @@ +%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}{autosuffix} + +\unprotect + +%D Eventually these labels will either move to the modules where they're used, or +%D they will en dup in mult-tag. + +\definetagconstant{document} % Div + +\definetagconstant{division} % Div +\definetagconstant{paragraph} % P +\definetagconstant{p} % P +\definetagconstant{construct} % Span +\definetagconstant{highlight} % Span + +\definetagconstant{section} % Sect +\definetagconstant{sectioncaption} % Div +\definetagconstant{sectiontitle} % H +\definetagconstant{sectionnumber} % H +\definetagconstant{sectioncontent} % Div + +\definetagconstant{itemgroup} % L +\definetagconstant{item} % Li +\definetagconstant{itemtag} % Lbl +\definetagconstant{itemcontent} % LBody +\definetagconstant{itemhead} % Div +\definetagconstant{itembody} % Div + +\definetagconstant{description} % Li +\definetagconstant{descriptiontag} % Lbl +\definetagconstant{descriptioncontent} % LBody +\definetagconstant{descriptionsymbol} % Span + +\aliastagconstant{construction} {description} +\aliastagconstant{constructiontag} {descriptiontag} +\aliastagconstant{constructioncontent}{descriptioncontent} +\aliastagconstant{constructionsymbol} {descriptionsymbol} + +\definetagconstant{verbatimblock} % Code +\definetagconstant{verbatimlines} % Code +\definetagconstant{verbatimline} % Code +\definetagconstant{verbatim} % Code + +\definetagconstant{lines} % Code +\definetagconstant{line} % Code +\definetagconstant{linenumber} % Span + +\definetagconstant{sorting} % Span +\definetagconstant{synonym} % Span + +\definetagconstant{register} % Div +\definetagconstant{registerlocation} % Span +\definetagconstant{registersection} % Div +\definetagconstant{registertag} % Span +\definetagconstant{registerentries} % Div +\definetagconstant{registerentry} % Span +\definetagconstant{registercontent} % Span +\definetagconstant{registersee} % Span +\definetagconstant{registerpages} % Span +\definetagconstant{registerpage} % Span +\definetagconstant{registerpagerange} % Span +\definetagconstant{registerfrompage} % Span +\definetagconstant{registertopage} % Span +\definetagconstant{registerseparator} % Span + +\definetagconstant{table} % Table +\definetagconstant{tablerow} % TR +\definetagconstant{tablecell} % TD +\definetagconstant{tableheadcell} % TH +\definetagconstant{tablehead} % THEAD +\definetagconstant{tablebody} % TBODY +\definetagconstant{tablefoot} % TFOOT + +\definetagconstant{tabulate} % Table +\definetagconstant{tabulaterow} % TR +\definetagconstant{tabulatecell} % TD +\definetagconstant{tabulateheadcell} % TH +\definetagconstant{tabulatehead} % THEAD +\definetagconstant{tabulatebody} % TBODY +\definetagconstant{tabulatefoot} % TFOOT + +\definetagconstant{math} % math +\definetagconstant{mtable} % Table +\definetagconstant{mtr} % TR +\definetagconstant{mtd} % TD +\definetagconstant{maction} % +\definetagconstant{mstacker} +\definetagconstant{mstackertop} +\definetagconstant{mstackermid} +\definetagconstant{mstackerbot} + +\aliastagconstant{mtablerow} {mtr} +\aliastagconstant{mtablecell}{mtd} + +\definetagconstant{munderover} % special cases +\definetagconstant{munder} % special cases +\definetagconstant{mover} % special cases + +\definetagconstant{list} % TOC +\definetagconstant{listitem} % TOCI +\definetagconstant{listtag} % Lbl +\definetagconstant{listcontent} % P +\definetagconstant{listdata} % P +\definetagconstant{listpage} % Reference +\definetagconstant{listtext} % Span + +\definetagconstant{delimited} % BlockQuote +%definetagconstant{delimited} % Quote +\definetagconstant{delimitedsymbol} % Span +\definetagconstant{delimitedcontent} % Span + +\aliastagconstant{delimitedblock}{delimited} + +\definetagconstant{subsentence} % Span +\definetagconstant{subsentencecontent} % Span +\definetagconstant{subsentencesymbol} % Span + +\definetagconstant{float} % Div +\definetagconstant{floatcaption} % Caption +\definetagconstant{floatlabel} % Span +\definetagconstant{floattext} % Span +\definetagconstant{floatnumber} % Span +\definetagconstant{floatcontent} % P + +\definetagconstant{image} % P + +\definetagconstant{mpgraphic} % P + +\definetagconstant{formulaset} % Div +\definetagconstant{formula} % Div +\definetagconstant{formulacaption} % Span +\definetagconstant{formulalabel} % Span +\definetagconstant{formulanumber} % P +\definetagconstant{formulacontent} % P +\definetagconstant{subformula} % Div + +\definetagconstant{link} % Link +\definetagconstant{reference} % Span + +\definetagconstant{margintext} % Span +\definetagconstant{margintextblock} % Div +\definetagconstant{marginanchor} % Span + +% we might opt for verbose variants so this is experimental: + +\definetagconstant{label} % Span +\definetagconstant{number} % Span + +\definetagconstant{ignore} % Span +\definetagconstant{private} % Span + +\definetagconstant{mid} % Span +\definetagconstant{sub} % Span +\definetagconstant{sup} % Span +\definetagconstant{subsup} % Span + +\definetagconstant{unit} % Span +\definetagconstant{quantity} % Span +%definetagconstant{number} % Span + +\definetagconstant{combination} % Span +\definetagconstant{combinationpair} % Span +\definetagconstant{combinationcontent} % Span +\definetagconstant{combinationcaption} % Span + +\definetagconstant{publications} % Span +\definetagconstant{publication} % Span +\definetagconstant{pubfld} % Span + +\definetagconstant{block} % Div +\definetagconstant{userdata} % Div + +% \setuptaglabeltext +% [en] +% [\t!document=document] + +% the real code + +\definesystemattribute[tagged][public] +\definesystemattribute[image] [public] + +% \setelementbackendtag [#1][#2] % define at the lua end +% \setelementnature [#1][#2] % define at the lua end + +\permanent\protected\def\ignoretagsinexport[#1]{\clf_ignoretagsinexport{#1}} % todo: public implementor + +\installcorenamespace{tagging} + +\installsetuponlycommandhandler \??tagging {tagging} + +\def\strc_tags_report_hyphen#1% + {\writestatus\m!languages{setting #1 to U+00AD}} + +\protected\def\strc_tags_patch_hyphen + {% for the moment here + \ifnum\languageparameter\s!lefthyphenchar>\zerocount + \setuplanguage[\s!default][\s!lefthyphenchar="AD]% + \strc_tags_report_hyphen\s!lefthyphenchar + \fi + \ifnum\languageparameter\s!righthyphenchar>\zerocount + \setuplanguage[\s!default][\s!righthyphenchar="AD]% + \strc_tags_report_hyphen\s!righthyphenchar + \fi + \let\strc_tags_report_hyphen\gobbleoneargument} + +% 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. + +% \strc_tags_start_userdata % defined at the lua end +% \strc_tags_stop % defined at the lua end +% \strc_tags_set_aspect % defined at the lua end +% \strc_tags_get_element_tag % defined at the lua end +% \strc_tags_set_element_user_properties % defined at the lua end + +\permanent\protected\def\strc_tags_element_start_yes + {\iftrialtypesetting + \expandafter\gobbletwooptionals + \else + \expandafter\strc_tags_start_userdata + \fi} + +\permanent\protected\def\strc_tags_element_stop_yes + {\iftrialtypesetting + % nothing + \else + \expandafter\strc_tags_stop + \fi} + +\protected\def\strc_tags_enable_elements + {\strc_tags_patch_hyphen + \enforced\let\startelement \strc_tags_element_start_yes + \enforced\let\stopelement \strc_tags_element_stop_yes + \enforced\let\dosettagproperty\strc_tags_set_aspect} + +\protected\def\strc_tags_disable_elements + {\enforced\let\startelement \gobbletwooptionals + \enforced\let\stopelement \relax + \enforced\let\dosettagproperty\gobbletwoarguments} + +% beware: making these unexpanded spoils tables (noalign problem) + +\def\strc_tags_enabled_start_no_detail + {\iftrialtypesetting + \expandafter\gobbleoneargument + \else + \expandafter\strc_tags_start + \fi} + +\def\strc_tags_enabled_start_detail + {\iftrialtypesetting + \expandafter\gobbletwoarguments + \else + \expandafter\strc_tags_start_detail + \fi} + +\def\strc_tags_enabled_start_chained + {\iftrialtypesetting + \expandafter\gobblethreearguments + \else + \expandafter\strc_tags_start_chained_indeed + \fi} + +\def\strc_tags_enabled_start_ignore + {\iftrialtypesetting + \expandafter\gobbleoneargument + \else + \expandafter\strc_tags_start_ignore + \fi} + +\def\strc_tags_enabled_stop + {\iftrialtypesetting + % do nothing + \else + \expandafter\strc_tags_stop + \fi} + +\def\strc_tags_start_chained_indeed#1#2#3{\strc_tags_start_chained{#1}{#2}{\getcurrentparentchain#3{#2}}} + +\newconditional\c_strc_tags_enabled + +\permanent\let\dotaggedplaceholder\empty + +\immutable\chardef\strc_tags_placeholder_char\zerocount % "FFFC + +\protected\def\strc_tags_enable_indeed + {\enforced\let\dotaggedplaceholder \strc_tags_placeholder_char + \enforced\let\dostarttagged \strc_tags_enabled_start_detail + \enforced\let\dostarttaggednodetail\strc_tags_enabled_start_no_detail + \enforced\let\dostarttaggedchained \strc_tags_enabled_start_chained + \enforced\let\dostoptagged \strc_tags_enabled_stop + \enforced\let\dostartignoretagging \strc_tags_enabled_start_ignore + \enforced\let\dostopignoretagging \strc_tags_stop} + +\protected\def\strc_tags_enable + {% once enable one is toast + \global\settrue\c_strc_tags_enabled + % and gets: + \strc_tags_enable_indeed} + +\protected\def\strc_tags_disable + {\ifconditional\c_strc_tags_enabled + % so now all are artifacts + \enforced\let\dotaggedplaceholder \strc_tags_placeholder_char + \enforced\let\dostarttagged \gobbletwoarguments + \enforced\let\dostarttaggednodetail\gobbleoneargument + \enforced\let\dostarttaggedchained \gobblethreearguments + \enforced\let\dostoptagged \donothing + \else + % initial + \enforced\let\dotaggedplaceholder \empty + \enforced\let\dostarttagged \gobbletwoarguments + \enforced\let\dostarttaggednodetail\gobbleoneargument + \enforced\let\dostarttaggedchained \gobblethreearguments + \enforced\let\dostoptagged \donothing + \enforced\let\dostartignoretagging \donothing + \enforced\let\dostopignoretagging \donothing + \fi} + +% for luigi (beware: fully expandable): + +\protected\def\strc_tags_setup_element_user_properties + {\iftrialtypesetting + \expandafter\gobbletwooptionals + \else + \expandafterstrc_set_element_user_properties + \fi} + +\protected\def\strc_tags_enable_properties + {\enforced\let\getelementtag \strc_tags_get_element_tag + \enforced\let\setupelementuserproperties\strc_tags_set_element_user_properties} + +\protected\def\strc_tags_disable_properties + {\enforced\let\getelementtag \donothing + \enforced\let\setupelementuserproperties\gobbletwooptionals} + +%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 + +\permanent\protected\def\forgettagging + {\c_attr_tagged\attributeunsetvalue} + +\setuptagging + [\c!state=\v!stop, + \c!method=\v!auto] + +% 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=] + +\ifdefined\dotagparagraph \else \let\dotagparagraph\gobbleoneargument \fi + +\permanent\tolerant\protected\def\startparagraph[#1]#*[#2]% + {\endgraf % we end before the group + \begingroup + \ifarguments + \let\currentparagraph\empty + \or + \ifhastok={#1}% + \let\currentparagraph\empty + \setupcurrentparagraph[#1] + \else + \edef\currentparagraph{#1}% + \fi + \or + \edef\currentparagraph{#1}% + \setupcurrentparagraph[#2]% + \fi + \useparagraphstyleandcolor\c!style\c!color + \usealignparameter\paragraphparameter + \usesetupsparameter\paragraphparameter + \dostarttagged\t!paragraph\currentparagraph + \dotagparagraph{\paragraphparameter\c!align}} + +\permanent\protected\def\stopparagraph + {\dostoptagged + \endgraf % we end inside the group + \endgroup} + +\aliased\let\startpar\startparagraph +\aliased\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 + +% This doesn't work well either, so instead we handle the ornaments in the tagging +% in a different way (see attr -> false code). + +% \appendtoks +% \dostartignoretagging +% \to \everybeforepagebody +% +% \appendtoks +% \dostopignoretagging +% \to \everyafterpagebody + +% \doifelseinelement{structure:section} {yes} {no} +% \doifelseinelement{structure:chapter} {yes} {no} +% \doifelseinelement{division:*-structure:chapter} {yes} {no} + +\aliased\let\doifinelementelse\doifelseinelement % define at the lua end + +\permanent\protected\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} + +\permanent\protected\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 here we get some as +%D child of the document root and some as child 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 + +% \settaggedmetadata[#1] % define at the lua end + +%D An overload: + +\pushoverloadmode + +\aliased\let\strc_tagged_saved_bpar\bpar +\aliased\let\strc_tagged_saved_epar\epar + +\enforced\permanent\protected\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar} +\enforced\permanent\protected\def\epar{\strc_tagged_saved_epar\dostoptagged} + +\popoverloadmode + +% \permanent\def\untagged{attr \taggedattribute\attributeunsetvalue} + +\protect diff --git a/tex/context/base/mkxl/strc-tnt.mkxl b/tex/context/base/mkxl/strc-tnt.mkxl new file mode 100644 index 000000000..4129117f0 --- /dev/null +++ b/tex/context/base/mkxl/strc-tnt.mkxl @@ -0,0 +1,117 @@ +%D \module +%D [ file=strc-tnt, +%D version=2019.05.30, % based on older code +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Text 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. + +\unprotect + +%D \macros +%D {definetextnote,setuptextnote} +%D +%D \startbuffer +%D \definetextnote +%D [textnote] +%D +%D \startbuffer +%D Test test test \textnote [n=5] {alpha}. test test test test tets test test +%D \textnote [n=10] {beta}. Test test test test tets test test \textnote [n=12] +%D {gamma}. Test test test test tets test test \textnote [n=24] {delta}. Test test +%D test test test test \textnote {epsilon} test test \textnote [n=*] {zeta}. +%D \stopbuffer +%D +%D \blank {\setuptextnote[empty=yes] \getbuffer\par} \blank +%D \blank {\setuptextnote[empty=number] \getbuffer\par} \blank +%D \blank {\setuptextnote[empty=none] \getbuffer\par} \blank +%D \blank { \getbuffer\par} \blank +%D +%D \blank[2*big] +%D +%D \placenotes[textnote:note][criterium=text] +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace{textnote} + +\installcommandhandler \??textnote {textnote} \??textnote + +\definebar + [\v!textnote:\v!underbar] + [\v!underbar] + +\definenote + [\v!textnote:\v!note] + +\setuptextnote + [\c!rule=\v!textnote:\v!underbar, + \c!note=\v!textnote:\v!note, + \c!n=10] % * will use the real space + +\appendtoks + \frozen\instance\setuevalue{\currenttextnote}{\educ_textnote[\currenttextnote]}% +\to \everydefinetextnote + +\tolerant\protected\def\educ_textnote[#1]#*[#2]#:#3% + {\dontleavehmode + \begingroup + \def\currenttextnote{#1}% + \ifparameter#2\or\setupcurrenttextnote[#2]\fi + \edef\p_n{\textnoteparameter\c!n}% + \edef\p_empty{\textnoteparameter\c!empty}% + \edef\currentbar{\textnoteparameter\c!rule}% + \edef\currentnote{\textnoteparameter\c!note}% + \ifx\p_n\wildcardsymbol + \donefalse + \ifx\p_empty\v!yes + \donetrue + \orelse\ifx\p_empty\v!number + \donetrue + \orelse\ifx\p_empty\v!none + \donetrue + \fi + \ifdone + \setupbar[\currentbar][\c!empty=\v!yes]% + \fi + \inlinebar[\currentbar]\bgroup + \wordboundary#3% + \ifx\p_empty\v!yes + \setnotetext[\currentnote]{#3}% + \orelse\ifx\p_empty\v!number + \runninghbox{\resetbar\setnote[\currentnote]{#3}}% + \orelse\ifx\p_empty\v!none + \setupnote[\currentnote][\c!location=\v!none]% + \runninghbox{\resetbar\setnote[\currentnote]{#3}}% + \fi + \egroup + \else + \inlinebar[\currentbar]\bgroup + \scratchcounter\numexpr\p_n/\plustwo\relax + \ifx\p_empty\v!yes + \interwordspacesbefore\scratchcounter + \setnotetext[\currentnote]{#3}% + \interwordspacesafter\scratchcounter + \orelse\ifx\p_empty\v!number + \interwordspacesbefore\scratchcounter + \zwnj\runninghbox{\resetbar\setnote[\currentnote]{#3}}\zwnj + \interwordspacesafter\scratchcounter + \orelse\ifx\p_empty\v!none + \setupnote[\currentnote][\c!location=\v!none]% + \interwordspacesbefore\scratchcounter + \zwnj\runninghbox{\resetbar\setnote[\currentnote]{#3}}\zwnj + \interwordspacesafter\scratchcounter + \else + #3% + \fi + \egroup + \fi + \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-usr.mkxl b/tex/context/base/mkxl/strc-usr.mkxl new file mode 100644 index 000000000..28d398194 --- /dev/null +++ b/tex/context/base/mkxl/strc-usr.mkxl @@ -0,0 +1,169 @@ +%D \module +%D [ file=strc-bkm, +%D version=2009.04.01, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Bookmarks, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Userdata} + +\registerctxluafile{strc-usr}{} + +%D It's a bit like blocks that also use buffers but more lightweight and with +%D inplace settings. +%D +%D \starttyping +%D \defineuserdata [test] [style=italic] +%D +%D \samplefile{klein} +%D +%D \startuserdata [before=\blank,after=\blank,color=red] +%D \samplefile{greenfield} +%D \stopuserdata +%D +%D \samplefile{sapolsky} +%D +%D \startuserdata [test] +%D \samplefile{bryson} +%D \stopuserdata +%D +%D \samplefile{jojomayer} +%D +%D \startuserdata [test] [before=\blank,after=\blank,color=red] +%D \samplefile{linden} +%D \stopuserdata +%D +%D \samplefile{montgomery} +%D \stoptyping +%D +%D Or from \LUA: +%D +%D \starttyping +%D \startluacode +%D context.startuserdata({color="blue"}) +%D context.samplefile("klein") +%D context.stopuserdata() +%D \stopluacode +%D \stoptyping +%D +%D An example of an alternative: +%D +%D \starttyping +%D \defineuserdataalternative [epigraph] [renderingsetup=userdata:epigraph] +%D +%D \startsetups [userdata:epigraph] +%D \startframedtext [location=right,frame=off,align={flushleft,broad},style=\tfx,offset=.25ex,width=.5\textwidth] +%D \begstrut\inlinebuffer[userdata]\endstrut +%D \hairline +%D \wordright{\userdataparameter{author}} +%D \stopframedtext +%D \stopsetups +%D +%D \defineuserdata +%D [epigraph] +%D [alternative=epigraph] +%D +%D \startuserdata [epigraph] [author={Sean B. Carrol}] +%D The fraction of fossil olfactory receptor genes is significantly higher in +%D all species with full color vision. This suggests that the evolution of +%D trichromatic vision --- which allows these primates to detect food, mates, +%D and danger with visual cues --- has reduced their reliance on the sense of +%D smell. +%D \stopuserdata +%D +%D \startuserdata [epigraph] [author={Sean B. Carrol}] +%D \samplefile{carrol} +%D \stopuserdata +%D \stoptyping + +\unprotect + +\installnamespace {userdata} +\installnamespace {userdataalternative} +\installnamespace {userdatarenderings} + +\installcommandhandler \????userdata {userdata} \????userdata +\installcommandhandler \????userdataalternative {userdataalternative} \????userdataalternative + +\permanent\protected\def\startuserdata + {\begingroup + \let\currentuserdata\empty + \doifelsenextoptionalcs\userdata_start_delayed\userdata_start_indeed} + +% This variant works only when the userdata instance exists while the assignment check +% can also be used with undefined instances which falls back to the global settings. +% +% \def\userdata_start_delayed[#1]% +% {\ifcsname\nameduserdatahash{\detokenize\expandafter{\normalexpanded{#1}}}\s!parent\endcsname +% \expandafter\userdata_start_delayed_name +% \else +% \expandafter\userdata_start_delayed_parameters +% \fi[#1]} + +\def\userdata_start_delayed[#1]% + {\doifelseassignmentcs{#1}% + \userdata_start_delayed_parameters + \userdata_start_delayed_name + [#1]} + +\def\userdata_start_delayed_parameters[#1]% + {\setupcurrentuserdata[#1]% + \userdata_start_indeed} + +\def\userdata_start_delayed_name[#1]% + {\edef\currentuserdata{#1}% + \checkuserdataparent + \doifelsenextoptionalcs\userdata_start_delayed_parameters\userdata_start_indeed} + +\def\userdata_start_indeed + {\grabbufferdatadirect\s!userdata{\csstring\startuserdata}{\csstring\stopuserdata}} + +\permanent\protected\def\stopuserdata + {\userdataparameter\c!before % HH: moved, so we obey the outer spacing + \dostarttagged\t!userdata\currentuserdata % HH: added, maybe move up ? + \begingroup + \useuserdatastyleandcolor\c!style\c!color + \usealignparameter\userdataparameter % HH: added + \edef\currentuserdataalternative{\userdataparameter\c!alternative}% + \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else + \let\currentuserdataalternative\s!default + \fi + \usesetupsparameter\userdataparameter + \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}% + \directsetup\p_renderingsetup + \endgroup + \dostoptagged + \userdataparameter\c!after % HH: moved + \endgroup} + +\permanent\protected\def\getuserdata + {\getbufferdata[\s!userdata]} + +\permanent\protected\def\getinlineuserdata + {\inlinebuffer[\s!userdata]} + +\defineuserdataalternative + [\s!default] + [\c!renderingsetup=\????userdatarenderings:\s!default] + +% \startsetups[\????userdatarenderings:\s!default] +% \userdataparameter\c!before +% \usesetupsparameter\userdataparameter +% \getbufferdata[\s!userdata] +% \userdataparameter\c!after +% \stopsetups + +\startsetups[\????userdatarenderings:\s!default] + \getuserdata +\stopsetups + +\setupuserdata + [\c!alternative=\s!default] + +\protect diff --git a/tex/context/base/mkxl/supp-box.lmt b/tex/context/base/mkxl/supp-box.lmt new file mode 100644 index 000000000..41013da9a --- /dev/null +++ b/tex/context/base/mkxl/supp-box.lmt @@ -0,0 +1,1335 @@ +if not modules then modules = { } end modules ['supp-box'] = { + version = 1.001, + optimize = true, + 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 report_hyphenation = logs.reporter("languages","hyphenation") + +local tonumber, next, type = tonumber, next, type + +local lpegmatch = lpeg.match + +local tex = tex +local context = context +local nodes = nodes + +local implement = interfaces.implement + +local nodecodes = nodes.nodecodes + +local disc_code = nodecodes.disc +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local glyph_code = nodecodes.glyph +local par_code = nodecodes.par + +local indent_code = nodes.listcodes.indent + +local hmode_code = tex.modelevels.horizontal + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +----- getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getboth = nuts.getboth +local getdisc = nuts.getdisc +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist +local getattribute = nuts.getattribute +local getbox = nuts.getbox +local getdirection = nuts.getdirection +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth +local getwhd = nuts.getwhd +local takebox = nuts.takebox + +----- setfield = nuts.setfield +local setlink = nuts.setlink +local setboth = nuts.setboth +local setnext = nuts.setnext +local setprev = nuts.setprev +local setbox = nuts.setbox +local setlist = nuts.setlist +local setdisc = nuts.setdisc +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth +local setshift = nuts.setshift +local setsplit = nuts.setsplit +local setattrlist = nuts.setattrlist +local setwhd = nuts.setwhd +local setglue = nuts.setglue + +local flush_node = nuts.flush_node +local flush_list = nuts.flush_list +local copy_node = nuts.copy +local copy_list = nuts.copy_list +local find_tail = nuts.tail +local getdimensions = nuts.dimensions +local hpack = nuts.hpack +local vpack = nuts.vpack +local traverse_id = nuts.traverse_id +local traverse = nuts.traverse +local free = nuts.free +local findtail = nuts.tail +local reverse = nuts.reverse +local effective_glue= nuts.effective_glue + +local nextdisc = nuts.traversers.disc +local nextdir = nuts.traversers.dir +local nexthlist = nuts.traversers.hlist + +local listtoutf = nodes.listtoutf + +local nodepool = nuts.pool +local new_penalty = nodepool.penalty +local new_hlist = nodepool.hlist +local new_glue = nodepool.glue + +local setlistcolor = nodes.tracers.colors.setlist + +local texget = tex.get +local texgetbox = tex.getbox +local texsetdimen = tex.setdimen +local texgetnest = tex.getnest + +local function hyphenatedlist(head,usecolor) + local current = head and tonut(head) + while current do + local id = getid(current) + local prev, next = getboth(current) + if id == disc_code then + local pre, post, replace = getdisc(current) + 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) + end + setdisc(current) + if pre then + setlink(prev,new_penalty(10000),pre) + setlink(find_tail(pre),current) + end + if post then + setlink(current,new_penalty(10000),post) + setlink(find_tail(post),next) + end + 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 nextdisc, 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(n) + -- we just hyphenate (as we pass a hpack) .. a bit too much casting but ... + local l = languages.hyphenators.handler(tonode(checkedlist(n))) + report_hyphenation("show: %s",listtoutf(l,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 command then + command = context[command] + end + if method == "char" or method == "character" then + if spaced then + spaced = context.space + end + local words = lpegmatch(split_char,str) + for i=1,#words do + local word = words[i] + if word == " " then + if spaced then + spaced() + end + elseif command then + command(word) + else + context(word) + end + end + elseif method == "word" then + if spaced then + spaced = context.space + end + local words = lpegmatch(split_word,str) + for i=1,#words do + local word = words[i] + if spaced and i > 1 then + spaced() + end + if command then + command(word) + else + context(word) + end + end + elseif method == "line" then + if spaced then + spaced = context.par + end + local words = lpegmatch(split_line,str) + for i=1,#words do + local word = words[i] + if spaced and i > 1 then + spaced() + end + if command then + 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 + flush_node(temp) + end + -- done + setnext(tail) + setlist(current) + end + current = next + end + local result = new_hlist() + setlist(result,head) + setbox(target,result) + -- setbox(target,new_hlist(head)) + end +} + +implement { + name = "hboxtovbox", + arguments = "integer", + actions = function(n) + local b = getbox(n) + local factor = texget("baselineskip",false) / texget("hsize") + setdepth(b,0) + setheight(b,getwidth(b) * 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 = 0 + local h = 0 + local d = 0 + local l = getlist(getbox(n)) + if l then + w, h, d = getdimensions(l) + end + texsetdimen("lastnaturalboxwd",w) + texsetdimen("lastnaturalboxht",h) + texsetdimen("lastnaturalboxdp",d) + return w, h, d +end + +implement { + name = "getnaturaldimensions", + arguments = "integer", + actions = getnaturaldimensions +} + +implement { + name = "naturalwd", + arguments = "integer", + actions = function(n) + getnaturaldimensions(n) + context.lastnaturalboxwd(false) + end +} + +implement { + name = "getnaturalwd", + arguments = "integer", + actions = function(n) + local w = 0 + local h = 0 + local d = 0 + local l = getlist(getbox(n)) + if l then + w, h, d = getdimensions(l) + end + context("\\dimexpr%i\\scaledpoint\\relax",w) + end +} + +local function setboxtonaturalwd(n) + local old = takebox(n) + local new = hpack(getlist(old)) + setlist(old,nil) + flush_node(old) + setbox(n,new) +end + +implement { + name = "setnaturalwd", + arguments = "integer", + actions = setboxtonaturalwd +} + +nodes.setboxtonaturalwd = setboxtonaturalwd + +local doifelse = commands.doifelse + +do + + local dirvalues = nodes.dirvalues + local lefttoright_code = dirvalues.lefttoright + local righttoleft_code = dirvalues.righttoleft + + local function firstdirinbox(n) + local b = getbox(n) + if b then + local l = getlist(b) + if l then + for d in nextdir, l do + return getdirection(d) + end + for h in nexthlist, l do + return getdirection(h) + end + end + end + return lefttoright_code + end + + nodes.firstdirinbox = firstdirinbox + + implement { + name = "doifelserighttoleftinbox", + arguments = "integer", + actions = function(n) + doifelse(firstdirinbox(n) == righttoleft_code) + end + } + +end + +-- new (handy for mp) .. might move to its own module + +do + + local takebox = nuts.takebox + local flush_list = nuts.flush_list + local copy_list = nuts.copy_list + local getwhd = nuts.getwhd + local setbox = nuts.setbox + local new_hlist = nuts.pool.hlist + + local boxes = { } + nodes.boxes = boxes + local cache = table.setmetatableindex("table") + local report = logs.reporter("boxes","cache") + local trace = false + + trackers.register("nodes.boxes",function(v) trace = v end) + + function boxes.save(category,name,b) + name = tonumber(name) or name + local b = takebox(b) + if trace then + report("category %a, name %a, %s (%s)",category,name,"save",b and "content" or "empty") + end + cache[category][name] = b or false + end + + function boxes.savenode(category,name,n) + name = tonumber(name) or name + if trace then + report("category %a, name %a, %s (%s)",category,name,"save",n and "content" or "empty") + end + cache[category][name] = tonut(n) or false + end + + function boxes.found(category,name) + name = tonumber(name) or name + return cache[category][name] and true or false + end + + function boxes.direct(category,name,copy) + name = tonumber(name) or name + local c = cache[category] + local b = c[name] + if not b then + -- do nothing, maybe trace + elseif copy then + b = copy_list(b) + else + c[name] = false + end + if trace then + report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty") + end + if b then + return tonode(b) + end + end + + function boxes.restore(category,name,box,copy) + name = tonumber(name) or name + local c = cache[category] + local b = takebox(box) + if b then + flush_list(b) + end + local b = c[name] + if not b then + -- do nothing, maybe trace + elseif copy then + b = copy_list(b) + else + c[name] = false + end + if trace then + report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty") + end + setbox(box,b or nil) + end + + function boxes.dimensions(category,name) + name = tonumber(name) or name + local b = cache[category][name] + if b then + return getwhd(b) + else + return 0, 0, 0 + end + end + + function boxes.reset(category,name) + name = tonumber(name) or name + local c = cache[category] + if name and name ~= "" then + local b = c[name] + if b then + flush_list(b) + c[name] = false + end + if trace then + report("category %a, name %a, reset",category,name) + end + else + for k, b in next, c do + if b then + flush_list(b) + end + end + cache[category] = { } + if trace then + report("category %a, reset",category) + end + end + end + + implement { + name = "putboxincache", + arguments = { "string", "string", "integer" }, + actions = boxes.save, + } + + implement { + name = "getboxfromcache", + arguments = { "string", "string", "integer" }, + actions = boxes.restore, + } + + implement { + name = "directboxfromcache", + arguments = "2 strings", + actions = { boxes.direct, context }, + -- actions = function(category,name) local b = boxes.direct(category,name) if b then context(b) end end, + } + + implement { + name = "directcopyboxfromcache", + arguments = { "string", "string", true }, + actions = { boxes.direct, context }, + -- actions = function(category,name) local b = boxes.direct(category,name,true) if b then context(b) end end, + } + + implement { + name = "copyboxfromcache", + arguments = { "string", "string", "integer", true }, + actions = boxes.restore, + } + + implement { + name = "doifelseboxincache", + arguments = "2 strings", + actions = { boxes.found, doifelse }, + } + + implement { + name = "resetboxesincache", + arguments = "string", + actions = boxes.reset, + } + +end + +implement { + name = "lastlinewidth", + actions = function() + local head = tex.lists.page_head + -- list dimensions returns 3 value but we take the first + context(head and getdimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0) + end +} + +implement { + name = "shiftbox", + arguments = { "integer", "dimension" }, + actions = function(n,d) + setshift(getbox(n),d) + end, +} + +implement { name = "vpackbox", arguments = "integer", actions = function(n) setbox(n,(vpack(takebox(n)))) end } +implement { name = "hpackbox", arguments = "integer", actions = function(n) setbox(n,(hpack(takebox(n)))) end } + +implement { name = "vpackedbox", arguments = "integer", actions = function(n) context(vpack(takebox(n))) end } +implement { name = "hpackedbox", arguments = "integer", actions = function(n) context(hpack(takebox(n))) end } + +implement { + name = "scangivendimensions", + public = true, + protected = true, + arguments = { + { + { "width", "dimension" }, + { "height", "dimension" }, + { "depth", "dimension" }, + }, + }, + actions = function(t) + texsetdimen("givenwidth", t.width or 0) + texsetdimen("givenheight",t.height or 0) + texsetdimen("givendepth", t.depth or 0) + end, +} + +local function stripglue(list) + local done = false + local first = list + while first do + local id = getid(first) + if id == glue_code or id == penalty_code then + first = getnext(first) + else + break + end + end + if first and first ~= list then + -- we have discardables + setsplit(getprev(first),first) + flush_list(list) + list = first + done = true + end + if list then + local tail = findtail(list) + local last = tail + while last do + local id = getid(last) + if id == glue_code or id == penalty_code then + last = getprev(last) + else + break + end + end + if last ~= tail then + -- we have discardables + flush_list(getnext(last)) + setnext(last) + done = true + end + end + return list, done +end + +local function limitate(t) -- don't pack the result ! + local text = t.text + if text then + text = tonut(text) + else + return + end + local sentinel = t.sentinel + if sentinel then + sentinel = tonut(sentinel) + local s = getlist(sentinel) + setlist(sentinel) + free(sentinel) + sentinel = s + else + return tonode(text) + end + local width = getwidth(text) + local list = getlist(text) + local done = false + if t.strip then + list, done = stripglue(list) + if not list then + setlist(text) + setwidth(text,0) + return text + elseif done then + width = getdimensions(list) + setlist(text,list) + end + end + local left = t.left or 0 + local right = t.right or 0 + local total = left + right + if total < width then + local last = nil + local first = nil + local maxleft = left + local maxright = right + local swidth = getwidth(sentinel) + if maxright > 0 then + maxleft = maxleft - swidth/2 + maxright = maxright - swidth/2 + else + maxleft = maxleft - swidth + end + for n in traverse_id(glue_code,list) do + local width = getdimensions(list,n) + if width > maxleft then + if not last then + last = n + end + break + else + last = n + end + end + if last and maxright > 0 then + for n in traverse_id(glue_code,last) do + local width = getdimensions(n) + if width < maxright then + first = n + break + else + first = n + end + end + end + if last then + local rest = getnext(last) + if rest then + local tail = findtail(sentinel) + if first and getid(first) == glue_code and getid(tail) == glue_code then + setwidth(first,0) + end + if last and getid(last) == glue_code and getid(sentinel) == glue_code then + setwidth(last,0) + end + if first and first ~= last then + local prev = getprev(first) + if prev then + setnext(prev) + end + setlink(tail,first) + end + setlink(last,sentinel) + setprev(rest) + flush_list(rest) + end + end + end + setlist(text) + free(text) + + if t.freeze then + local l = hpack(list,total,"exactly") + for n in traverse_id(glue_code,list) do + setglue(n,(effective_glue(n,l))) + end + setlist(l) + flush_node(l) + end + + return tonode(list) +end + +implement { + name = "limitated", + public = true, + protected = true, + arguments = { + { + { "left", "dimension" }, + { "right", "dimension" }, + { "text", "hbox" }, + { "sentinel", "hbox" }, + { "strip", "boolean" }, + { "freeze", "boolean" }, + } + }, + actions = function(t) + context.dontleavehmode() + context(limitate(t)) + end, +} + +-- only in lmtx: + +implement { + name = "widthuptohere", + public = true, + usage = "value", + actions = function() + local n = texgetnest() + local w = 0 + if n.mode == hmode_code then + local h = hpack(getnext(tonut(n.head))) + w = getwidth(h) + setlist(h) + free(h) + end + return tokens.values.dimension, w + end, +} + +implement { + name = "doifelseindented", + public = true, + protected = true, + actions = function() + local n = texgetnest() + local b = false + if n.mode == hmode_code then + n = tonut(n.head) + while n do + n = getnext(n) + if n then + local id = getid(n) + if id == hlist_code then + if getsubtype(n) == indent_code then + b = getwidth(n) > 0 + break + end + elseif id ~= par_code then + break + end + end + end + end + commands.doifelse(b) + end, +} + +implement { + name = "noflinesinbox", + public = true, + protected = false, + arguments = "integer", + actions = function(n) + local c = 0 + local b = getbox(n) + if b then + b = getlist(b) + if b then + for n, id in traverse(b) do + if id == hlist_code or id == vlist_code then + c = c + 1 + end + end + end + end + context(c) + end, +} + +do + + local takebox = tex.takebox + + implement { + name = "thebox", + public = true, + arguments = "integer", + actions = function(n) + context(takebox(n)) + end + } + +end + +-- only in lmtx + +implement { + name = "reversevboxcontent", + protected = true, + public = true, + arguments = "integer", + actions = function(n) + local b = getbox(n) + local l = b and getid(b) == vlist_code and getlist(b) + if l and getnext(l) then + setlist(b,reverse(l)) -- no re-vpack here! + end + end +} + +-- only in lmtx + +do + + local scaninteger = tokens.scanners.integer + local scanbox = tokens.scanners.box + local scandimen = tokens.scanners.dimen + + local setsubtype = nuts.setsubtype + local removenode = nuts.remove + local getnormalizedline = nuts.getnormalizedline -- we can optimize this + local getdimensions = nuts.dimensions + local getrangedimensions = nuts.rangedimensions + + local setprop = nuts.setprop + local getprop = nuts.getprop + + local listcodes = nodes.listcodes + local line_code = listcodes.line + local equation_code = listcodes.equation + local unknown_code = listcodes.unknown + + local values = tokens.values + local dimension_value = values.dimension + local cardinal_value = values.cardinal + local direct_value = values.direct + + -- todo: make helper that formats + + local reporterror = logs.texerrormessage + + -- The first variant did a linear lookup but for large boxes and lots of + -- analysis that is not nice. Okay, in practice performance is quite ok + -- (milliseconds for thousands of access) but still ... the next is nicer + -- and it's part of the experimental fun stuff anyway. + + local function countlines(box) + local prop = getprop(box,"boxlines") + if not prop then + local line = 0 + local list = getlist(box) + prop = { } + if list then + for n, subtype in nexthlist, list do + if subtype == line_code then -- or subtype == equation_code then + line = line + 1 + prop[line] = n + end + end + end + setprop(box,"boxlines",prop) + end + return prop + end + + local function boxlinecount(what) + local n = scaninteger() + local box = getbox(n) + if what == "value" then + return cardinal_value, box and #countlines(box) or 0 + end + end + + local function findline() + local n = scaninteger() + local line = scaninteger() + local box = getbox(n) + if box then + local prop = getprop(box,"boxlines") + if not prop then + prop = countlines(box) + end + local found = prop[line] + if found then + local props = getprop(found,"lineproperties") + if not props then + props = getnormalizedline(found) + props.width, props.height, props.depth = getwhd(found) + setprop(found,"lineproperties",props) + end + return props, line, found, box + end + end + reporterror("no line %i in box %i",line,n) + end + + local function findrange() + local n = scaninteger() + local first = scaninteger() + local last = scaninteger() + local box = getbox(n) + if box then + local prop = getprop(box,"boxlines") + if not prop then + prop = countlines(box) + end + if first > 0 and last <= #prop then + for i = first, last do + local found = prop[i] + local props = getprop(found,"lineproperties") + if not props then + props = getnormalizedline(found) + props.width, props.height, props.depth = getwhd(found) + setprop(found,"lineproperties",props) + end + end + return prop, first, last, box + end + end + reporterror("no lines %i - %i in box %i",first,last,n) + end + + local function getline(props,line,found,box,value) + local p, n = getboth(found) + local temp = new_hlist() + setsubtype(temp,getsubtype(found)) + setwhd(temp,getwhd(found)) + if found == getlist(box) then + setlink(temp,n) + setlist(box,temp) + else + setlink(p,temp,n) + end + getprop(box,"boxlines")[line] = temp + setboth(found) + setsubtype(found, unknown_code) + if value then + return direct_value, found + else + context(tonode(found)) + end + end + + local function copyline(props,line,found,box,value) + found = copy_node(found) + setsubtype(found, unknown_code) + if value then + return direct_value, found + else + context(tonode(found)) + end + end + + local function setline(props,line,found,box) + local p, n = getboth(found) + local temp = scanbox() + if temp then + temp = tonut(temp) + if found == getlist(box) then + setlink(temp,n) + setlist(box,temp) + else + setlink(p,temp,n) + end + flush_node(found) + getprop(box,"boxlines")[line] = temp + end + end + + local function naturaldimensions(p,l,found) + if not p.naturalwidth then + p.naturalwidth, p.naturalheight, p.naturaldepth = getdimensions(getlist(found)) + end + return p + end + + local function rangedimensions(p,f,l,box) + local w, h, d = getrangedimensions(box,p[f],getnext(p[l]),true) + return { width = w, height = h, depth = d } + end + + local getters_one = { + + ["wd"] = function(p,l,found) return dimension_value, p.width end, + ["ht"] = function(p,l,found) return dimension_value, p.height end, + ["dp"] = function(p,l,found) return dimension_value, p.depth end, + ["ls"] = function(p,l,found) return dimension_value, p.leftskip end, + ["rs"] = function(p,l,found) return dimension_value, p.rightskip end, + ["lh"] = function(p,l,found) return dimension_value, p.lefthangskip end, + ["rh"] = function(p,l,found) return dimension_value, p.righthangskip end, + ["lp"] = function(p,l,found) return dimension_value, p.parfillleftskip end, + ["rp"] = function(p,l,found) return dimension_value, p.parfillrightskip end, + ["in"] = function(p,l,found) return dimension_value, p.indent end, + + ["nw"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturalwidth end, + ["nh"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturalheigth end, + ["nd"] = function(p,l,found) return dimension_value, naturaldimensions(p,l,found).naturaldepth end, + + ["get"] = function(p,l,found,box) return getline(p,l,found,box,true) end, + } + + local getters_two = { + ["wd"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).width end, + ["ht"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).height end, + ["dp"] = function(p,f,l,box) return dimension_value, rangedimensions(p,f,l,box).depth end, + } + + local setters_one = { + ["wd"] = function(p,l,found) return setwidth (found,scandimen(false,false,true)) end, + ["ht"] = function(p,l,found) return setheight(found,scandimen(false,false,true)) end, + ["dp"] = function(p,l,found) return setdepth (found,scandimen(false,false,true)) end, + ["set"] = setline, + ["get"] = getline, + ["copy"] = copyline, + } + + local function boxline(name,what) + local props, line, found, box = findline() + if not found then + -- + elseif what == "value" then + local getter = getters_one[name] + if getter then + return getter(props,line,found,box) + end + else + local setter = setters_one[name] + if setter then + return setter(props,line,found,box) + end + end + end + + -- + + local function boxrange(name,what) + local prop, first, last, box = findrange() + if not prop then + -- + elseif what == "value" then + local getter = getters_two[name] + if getter then + return getter(prop,first,last,box) + end + else + local setter = setters_two[name] + if setter then + return setter(prop,first,last,box) + end + end + end + + local function define_one(name,action) + implement { + name = name, + public = true, + usage = "value", + actions = function(what) return boxline(action,what) end, + } + end + + local function define_two(name,action) + implement { + name = name, + public = true, + usage = "value", + actions = function(what) return boxrange(action,what) end, + } + end + + implement { + name = "boxlines", + public = true, + usage = "value", + actions = boxlinecount, + } + + define_one("boxline", "get") + define_one("setboxline", "set") + define_one("copyboxline", "copy") + define_one("boxlineht", "ht") + define_one("boxlinedp", "dp") + define_one("boxlinewd", "wd") + define_one("boxlinels", "ls") + define_one("boxliners", "rs") + define_one("boxlinelh", "lh") + define_one("boxlinerh", "rh") + define_one("boxlinelp", "lp") + define_one("boxlinerp", "rp") + define_one("boxlinein", "in") + define_one("boxlinenw", "nw") + define_one("boxlinenh", "nh") + define_one("boxlinend", "nd") + + define_two("boxrangewd", "wd") + define_two("boxrangeht", "ht") + define_two("boxrangedp", "dp") + +end + +do + + local getbox = tex.getbox + local setfield = nodes.setfield + local getfield = nodes.getfield + local flush = nodes.flush + local copynode = nodes.copy + + local function get(n,field,copy) + local b = getbox(n) + if b then + local p = getfield(b,field) + if copy then + p = copynode(p) + else + setfield(b,field) + end + context(p) + end + end + + local function set(n,l,field) + local b = getbox(n) + if b then + setfield(b,field,l) + else + flush(l) + end + end + + implement { + name = "prelistbox", + public = true, + usage = "value", + arguments = { "integer", '"pre"' }, + actions = get, + } + + implement { + name = "postlistbox", + public = true, + usage = "value", + arguments = { "integer", '"post"' }, + actions = get, + } + + implement { + name = "prelistcopy", + public = true, + usage = "value", + arguments = { "integer", '"pre"', true }, + actions = get, + } + + implement { + name = "postlistcopy", + public = true, + usage = "value", + arguments = { "integer", '"post"', true }, + actions = get, + } + + implement { + name = "setprelistbox", + public = true, + usage = "value", + arguments = { "integer", "box", '"pre"' }, + actions = set, + } + + implement { + name = "setpostlistbox", + public = true, + usage = "value", + arguments = { "integer", "box", '"post"' }, + actions = set, + } + +end diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl new file mode 100644 index 000000000..88fd5c9fb --- /dev/null +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -0,0 +1,2872 @@ +%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}{autosuffix,optimize} + +%D And some dimensions: + +\newdimen\givenwidth +\newdimen\givenheight +\newdimen\givendepth + +% \fixupboxesmode\plusone % gone: is now the default + +%D This module implements some box manipulation macros. Some are quite simple, some +%D are more advanced and when understood well, all can be of use. +%D +%D \macros +%D {strutdp,strutht,strutwd} +%D +%D The next shortcuts save memory and keying. The width is normally zero points (if +%D not, you're in trouble). These shortcuts can be used like a dimension, opposite +%D to the core macros \type {\strutdepth} and alike, which are values. + + \def\strutdp {\dp\strutbox} % overloaded in spac-ver + \def\strutht {\ht\strutbox} % overloaded in spac-ver +\permanent\protected\def\strutwd {\wd\strutbox} +\permanent\protected\def\struthtdp{\dimexpr\strutht+\strutdp\relax} +\permanent\protected\def\strutgap {\dimexpr\strutht-\strutdp\relax} + +%D \macros +%D {voidbox,nextbox} +%D +%D Let's start with an easy one. The next macro hides the ugly \type {@} in \type +%D {\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 need to save the \TEX\ +%D \DIMENSION\ \type{\prevdepth} and append it later on. The name \type {\nextdepth} +%D suits this purpose well. + +\newdimen\nextdepth + +%D \macros +%D {smashbox, smashboxed, smashedbox} +%D +%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of +%D a box to zero. The most resolute one is presented first. + +% \permanent\protected\def\smashbox#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint} +% +% \permanent\protected\def\smashboxed#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint +% \box#1\relax} + +%D \macros +%D {hsmashbox,vsmashbox} +%D +%D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or +%D vertical, one can use: + +% \permanent\protected\def\hsmashbox#1% +% {\wd#1\zeropoint} +% +% \permanent\protected\def\vsmashbox#1% +% {\ht#1\zeropoint +% \dp#1\zeropoint} + +%D The next implementation is less sensitive for spurious spaces. + +\newcount\c_boxes_register + +\permanent\protected\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} + +\permanent\protected\def\hsmashbox + {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register} + +\def\syst_boxes_hsmashed_boxes_register + {\wd\c_boxes_register\zeropoint} + +\permanent\protected\def\vsmashbox + {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register} + +\def\syst_boxes_vsmashed_boxes_register + {\ht\c_boxes_register\zeropoint + \dp\c_boxes_register\zeropoint} + +\permanent\protected\def\smashedbox + {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register} + +\protected\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} + +\aliased\let\smashboxed\smashedbox + +%D \macros +%D {hsmash,vsmash, +%D hsmashed,vsmashed} +%D +%D While the previous macros expected a \BOX, the next act on a content. They are +%D some subtle differences betreen the smash and smashed alternatives. The later +%D ones reduce all dimensions to zero. + +\permanent\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox} +\permanent\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox} +\permanent\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox} +\permanent\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox} + +\protected\def\syst_boxes_hsmashed_nextbox + {\wd\nextbox\zeropoint + \box\nextbox + \egroup} + +\protected\def\syst_boxes_vsmashed_nextbox + {\ht\nextbox\zeropoint + \dp\nextbox\zeropoint + \box\nextbox + \egroup} + +\protected\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 + +\permanent\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} +\permanent\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} + +%D First we define a helper. We use a \LUATEX\ feature in order to avoid +%D mathpalettes. + +\newcount\c_boxes_math_style + +\protected\def\syst_boxes_math_set_nextbox#1% + {\c_boxes_math_style\normalmathstyle + \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 well as is potentially +%D catcode safer. It is needed by the math module (although the \type {\leavevmode} +%D is not added here). + +\permanent\protected\def\smash + {\begingroup + \futureexpandis[\syst_boxes_smash_yes\syst_boxes_smash_nop} + +\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 + \orelse\ifx\nexttoken\bgroup + \expandafter\syst_boxes_smash_hbox + \else + \expandafter\syst_boxes_smash_text + \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} + +\def\syst_boxes_lower_nextbox_dp + {\setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}} + +%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 not grab an argument in +%D the non||math case, which is better. +%D +%D Due to a complicated call to \type {\mathpallete} and thereby \type +%D {\mathchoice}, the next macro looks ugly. We also take care of non||braced +%D arguments. + +\permanent\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed } +\permanent\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v} +\permanent\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h} + +\def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make } +\def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v} +\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 + \orelse\ifx\nexttoken\bgroup + \expandafter\syst_boxes_phantom_hbox + \else + \expandafter\syst_boxes_phantom_text + \fi} + +\def\syst_boxes_phantom_indeed_v + {\ifmmode + \expandafter\syst_boxes_phantom_math_v + \orelse\ifx\nexttoken\bgroup + \expandafter\syst_boxes_phantom_hbox_v + \else + \expandafter\syst_boxes_phantom_text_v + \fi} + +\def\syst_boxes_phantom_indeed_h + {\ifmmode + \expandafter\syst_boxes_phantom_math_h + \orelse\ifx\nexttoken\bgroup + \expandafter\syst_boxes_phantom_hbox_h + \else + \expandafter\syst_boxes_phantom_text_h + \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}. + +\permanent\protected\def\mathstrut{\vphantom(} % can be made faster by inlining + +%D \macros +%D {getboxheight} +%D +%D Although often needed, \TEX\ does not support arithmics 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 it accepts \type {{12}} as +%D well as \type {12} as box number. + +\permanent\protected\def\getboxheight#1\of#2\box#3% + {\def\next{#1\htdp\c_boxes_register}% + \afterassignment\next\c_boxes_register=#3} + +%D For a long time the following three macros were part of the grid snapping core +%D module, but it makes more sense to 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 (dimensie) in een aantal +%D regels en kent dit toe aan \type {\noflines}. +%D +%D \starttyping +%D \getnoflines{dimensie} +%D \stoptyping +%D +%D Er wordt gedeeld door \type {\openlineheight} en een hoogte van~0pt komt overeen +%D met 0~regels. The raw alternative does not round. See the \MKII\ and \MKIV\ files +%D for historic variants. + +\ifx\roundingeps\undefined \newdimen\roundingeps \roundingeps=10sp \fi + +\newcount\noflines +\newdimen\noflinesheight + +\permanent\protected\def\getnoflines#1% + {\noflinesheight#1\relax + \ifzeropt\noflinesheight + \noflines\zerocount + \orelse\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} + +\permanent\protected\def\getroundednoflines#1% + {\noflinesheight#1\relax + \ifzeropt\noflinesheight + \noflines\zerocount + \orelse\ifdim\noflinesheight>\zeropoint + \advance\noflinesheight\roundingeps + \divide\noflinesheight\openlineheight + \noflines\noflinesheight + \else + \advance\noflinesheight-\roundingeps + \divide\noflinesheight\openlineheight + \noflines\noflinesheight + \fi} + +\permanent\protected\def\getrawnoflines#1% + {\noflinesheight#1\relax + \ifzeropt\noflinesheight + \noflines\zerocount + \orelse\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} + +%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 returns it it \type +%D {\noflines}. The macro works reasonable well as long as the content can be +%D unboxed. +%D +%D \starttyping +%D \determinenoflines{test\\test} +%D \determinenoflines{\bfd test\\test} +%D \determinenoflines{\definedfont[Sans at 40pt]test\\test} +%D \stoptyping + +% \def\syst_boxes_determine_noflines % can be mkiv'd +% {\beginofshapebox +% \unvbox\nextbox +% \endofshapebox +% \globalscratchcounter\zerocount +% \reshapebox{\global\advance\globalscratchcounter\plusone}% +% \expandafter\egroup\expandafter\noflines\the\globalscratchcounter\relax} + +\def\syst_boxes_determine_noflines + {\expandafter\egroup\expandafter\noflines\noflinesinbox\nextbox\relax} + +\permanent\protected\def\determinenoflines + {\bgroup + \forgetall + \enforced\let\crlf\endgraf + \enforced\let\\\endgraf + \dowithnextboxcs\syst_boxes_determine_noflines\vbox} + +%D \macros +%D {doiftextelse, doiftext} +%D +%D When \type {\doifelse} cum suis hopelessly fail, for instance because we pass +%D data, we can fall back on the next macro: +%D +%D \starttyping +%D \doiftextelse {data} {then branch} {else branch} +%D \doiftext {data} {then branch} +%D \stoptyping + +\permanent\protected\def\doifelsetext#1% + {\begingroup + \setbox\scratchbox\hbox % no \hpack because we can have fallbacks + {\settrialtypesetting + \ignorespaces#1\removeunwantedspaces}% + \ifzeropt\wd\scratchbox + \endgroup\expandafter\secondoftwoarguments + \else + \endgroup\expandafter\firstoftwoarguments + \fi} + +\permanent\protected\def\doiftext#1% + {\begingroup + \setbox\scratchbox\hbox % no \hpack because we can have fallbacks + {\settrialtypesetting + \ignorespaces#1\removeunwantedspaces}% + \ifzeropt\wd\scratchbox + \endgroup\expandafter\gobbleoneargument + \else + \endgroup\expandafter\firstofoneargument + \fi} + +% more efficient but maybe fragile: +% +% \nospacing#1}% + +\aliased\let\doiftextelse\doifelsetext + +%D \macros +%D {dowithnextbox,nextbox} +%D +%D Sometimes we want a macro to grab a box and do something on the content. One +%D could pass an argument to a box, but this can violate the specific \CATCODES\ of +%D its content and leads to unexpected results. The next macro treats the following +%D braced text as the content of a box and manipulates it afterwards in a predefined +%D way. +%D +%D The first argument specifies what to do with the content. This content is +%D available in \type {\nextbox}. The second argument is one of \type {\hbox}, \type +%D {\vbox} or \type {\vtop}. The third argument must be grouped with \type {\bgroup} +%D and \type {\egroup}, \type {{...}} or can be a \type {\box} specification. +%D +%D In \CONTEXT\ this macro is used for picking up a box and treating it according to +%D earlier specifications. We use for 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 is needed because +%D \type {\afterassignment} is executed inside the box. + +\permanent\protected\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} + +\permanent\protected\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 \protected\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 \orelse\ifx#2\vbox +%D \afterassignment\syst_boxes_with_next_box_indeed +%D \orelse\ifx#2\vtop +%D \afterassignment\syst_boxes_with_next_box_indeed +%D \orelse\ifx#2\normalvcenter +%D \afterassignment\syst_boxes_with_next_box_indeed +%D \else +%D \afterassignment\syst_boxes_with_next_box +%D \fi +%D \setbox\nextbox#2} +%D \stoptyping +%D +%D This alternative also accepts \type {\box0} and alike, but we don't really need +%D this functionality now. + +%D \macros +%D {nextboxht,nextboxwd,nextboxdp,flushnextbox} +%D +%D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing +%D parameters. + +\permanent\def\nextboxht {\ht\nextbox} +\permanent\def\nextboxwd {\wd\nextbox} +\permanent\def\nextboxdp {\dp\nextbox} +\permanent\def\nextboxhtdp{\htdp\nextbox} + +\permanent\protected\def\flushnextbox{\box\nextbox} + +%D \macros +%D {dowithnextboxcontent} +%D +%D But, occasionally we do need to pass some local settings without wanting to use +%D additional grouping. Therefore we provide: +%D +%D \starttyping +%D \dowithnextboxcontent{inside}{after}{box content} +%D \stoptyping +%D +%D {\em todo: Search source for potential usage!} + +% \protected\def\dowithnextboxcontent#1#2% inside, after +% {\def\syst_boxes_with_next_box_one{#2}% +% \def\syst_boxes_with_next_box_two{#1}% +% \afterassignment\syst_boxes_with_next_box_content_indeed +% \setbox\nextbox} +% +% \protected\def\dowithnextboxcontentcs#1#2% inside, after +% {\let\syst_boxes_with_next_box_one#2% +% \let\syst_boxes_with_next_box_two#1% +% \afterassignment\syst_boxes_with_next_box_content_indeed +% \setbox\nextbox} + +\permanent\protected\def\dowithnextboxcontent#1#2% inside, after + {\afterassigned{#1\aftergrouped{#2}}% + \setbox\nextbox} + +\permanent\protected\def\dowithnextboxcontentcs#1#2% inside, after + {\afterassigned{#1\aftergroup#2}% + \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 way. We want the macros to +%D work in both math and text mode. + +\def\syst_boxes_do_rlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup} +\def\syst_boxes_do_llap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup} +\def\syst_boxes_do_clap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup} +\def\syst_boxes_do_tlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup} +\def\syst_boxes_do_blap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup} + +\def\syst_boxes_rlap {\begingroup\dowithnextboxcs\syst_boxes_do_rlap\hbox} +\def\syst_boxes_llap {\begingroup\dowithnextboxcs\syst_boxes_do_llap\hbox} +\def\syst_boxes_clap {\begingroup\dowithnextboxcs\syst_boxes_do_clap\hbox} +\def\syst_boxes_math_clap{\mathpalette\syst_boxes_do_math_clap} +\def\syst_boxes_math_llap{\mathpalette\syst_boxes_do_math_llap} +\def\syst_boxes_math_rlap{\mathpalette\syst_boxes_do_math_rlap} + +\def\syst_boxes_do_math_clap#1#2{\syst_boxes_clap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} +\def\syst_boxes_do_math_llap#1#2{\syst_boxes_llap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} +\def\syst_boxes_do_math_rlap#1#2{\syst_boxes_rlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} + +\permanent\protected\def\rlap{\mathortext\syst_boxes_math_rlap\syst_boxes_rlap} +\permanent\protected\def\llap{\mathortext\syst_boxes_math_llap\syst_boxes_llap} +\permanent\protected\def\clap{\mathortext\syst_boxes_math_clap\syst_boxes_clap} +\permanent\protected\def\tlap{\begingroup\dowithnextboxcs\syst_boxes_do_tlap\vbox} +\permanent\protected\def\blap{\begingroup\dowithnextboxcs\syst_boxes_do_blap\vbox} + +%D \macros +%D {beginofshapebox, +%D reshapebox, doreshapebox, +%D flushshapebox, +%D innerflushshapebox, +%D shapebox, +%D ifreshapingbox} +%D +%D The next utility macro originates from some linenumbering mechanism. Due to +%D \TEX's advanced way of typesetting paragraphs, it's not easy to do things on a +%D line||by||line basis. This macro is able to reprocess a given box and can act +%D upon its vertical boxed components, such as lines. The unwinding sequence in this +%D macro is inspired by a \NTG\ workshop of David Salomon in June 1992. +%D +%D First we have to grab the piece of text we want to act upon. This is done by +%D 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} and do something +%D with it's vertical components. We can make as much passes as needed. When we're +%D done, the box can be unloaded with \type {\flushshapebox}. The only condition in +%D this scheme is that \type {\reshapebox} must somehow unload the \BOX\ \type +%D {\shapebox}. +%D +%D An important aspect is that the content is unrolled bottom||up. The next example +%D illustrates this maybe 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 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 available after flushing. +%D Another feature is that only the last reshaping counts. Multiple reshaping can be +%D 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 introduce no new concepts. +%D Nearly all books on \TEX\ show similar solutions for unwinding \BOXES. +%D +%D Some macros, like footnote ones, can be sensitive for reshaping, which can result +%D in an endless loop. We therefore offer: +%D +%D \starttyping +%D \ifreshapingbox +%D \stoptyping +%D +%D Some \CONTEXT\ commands are protected this way. Anyhow, reshaping is aborted +%D after 100 dead cycles. +%D +%D By the way, changing the height and depth of \BOX\ \type {\shapebox} results in +%D bad spacing. This means that for instance linenumbers etc. should be given zero +%D height and depth before being lapped into the margin. The previous examples +%D ignore this side effect, but beware! +%D +%D This is ancient stuff and proably not used any more but we keep it around or +%D maybe turn it into a module some day. It shows the kind of struggling that we +%D needed before \LUATEX\ came around. + +\newif \ifsomeshapeleft +\newif \ifreshapingbox +\newif \ifreshapingfailed % may save redundant runs + +\newbox \shapebox +\newcount \shapepenalty +\newdimen \shapekern +\newskip \shapeskip + +\newbox \newshapebox +\newbox \oldshapebox +\newbox \tmpshapebox + +\newcount \shapecounter + +\newevery \everyshapebox \relax + +\def\shapesignal{.12345678pt} % or 12345sp + +\permanent\protected\def\reshapebox#1% + {\doreshapebox + {#1}% + {\penalty\shapepenalty}% + {\kern \shapekern }% + {\vskip \shapeskip }} + +\def\doreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip + {\global\reshapingfailedfalse + \ifzeropt\ht\oldshapebox + \setbox\newshapebox\emptyvbox + \else + \setbox\newshapebox\vbox % can be \vpack + {\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 (we can use \type {\vpack} too). + +\permanent\protected\def\insertshapesignal + {\hpack to \shapesignal{\strut\hss}% plus \strut + \prevdepth\strutdp} % never \nointerlineskip + +\permanent\protected\def\restoreshapebox % compensates for the signal + {\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}} + +\permanent\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip + {\ifnum\lastnodetype=\gluenodecode + \shapeskip\lastskip + \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}% + \unskip + \orelse\ifnum\lastnodetype=\kernnodecode + \shapekern\lastkern + \global\setbox\tmpshapebox\vbox{#3\unvbox\tmpshapebox}% + \unkern + \orelse\ifnum\lastnodetype=\penaltynodecode + \shapepenalty\lastpenalty + \global\setbox\tmpshapebox\vbox{#2\unvbox\tmpshapebox}% + \unpenalty + \orelse\ifnum\lastnodetype<\zeropoint + \exitloop + \else + \setbox\shapebox\lastbox + \ifvoid\shapebox + \orelse\ifdim\wd\shapebox=\shapesignal\relax + \exitloop + \else + \shapecounter\zerocount + \global\setbox\tmpshapebox\vbox{#1\unvbox\tmpshapebox}% + \fi + \fi + \ifnum\shapecounter>100 % can be less + \global\reshapingfailedtrue + \message{!!forced exit from shapebox \the\lastnodetype !!}% + \restoreshapebox + \exitloop + \else + \advance\shapecounter \plusone + \fi} + +\permanent\protected\def\beginofshapebox + {\setbox\oldshapebox\vbox + \bgroup + \reshapingboxtrue + \the\everyshapebox + \insertshapesignal} + +\permanent\protected\def\endofshapebox + {\endgraf + \egroup} + +\let\beginshapebox\beginofshapebox +\let\endshapebox \endofshapebox + +\permanent\protected\def\flushshapebox + {\bgroup + \ifzeropt\ht\newshapebox + \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 + \orelse\ifinner + % not watertight and not ok + \donefalse + \orelse\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 + \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} + +\permanent\protected\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} directly. This macro +%D takes four arguments, that take care 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 {\shapebox}, one can best +%D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and +%D depth of the line. + +\permanent\protected\def\shapedhbox % lines with non strutted dimensions have + {\expanded{\dowithnextbox % interlineskip so if we want the original + {\ht\nextbox\the\ht\shapebox % spacing, we need to preserve the original + \dp\nextbox\the\dp\shapebox % height and depth which is definitely + \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 report some more +%D advanced statistics. +%D +%D \starttyping +%D \showhyphens{dohyphenatedword} +%D \stoptyping + +\permanent\protected\def\doshowhyphenatednextbox + {\clf_showhyphenatedinlist\nextbox} + +\permanent\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua) + {\dowithnextboxcs\doshowhyphenatednextbox\hpack} + +%D The following macros are seldom used but handy for tracing. +%D +%D \starttyping +%D \hyphenatedword{dohyphenatedword} +%D \hyphenatedpar {\dorecurse{10}{dohyphenatedword }} +%D \hyphenatedfile{tufte} +%D \stoptyping + +\def\syst_boxes_hyphenatednextbox {\clf_hyphenatedlist\nextbox false\relax\unhbox\nextbox} +\def\syst_boxes_hyphenatednextboxcolor{\clf_hyphenatedlist\nextbox true \relax\unhbox\nextbox} + +\permanent\protected\def\hyphenatedword {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} +\permanent\protected\def\hyphenatedpar {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} +\permanent\protected\def\hyphenatedfile #1{\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}} +\permanent\protected\def\hyphenatedcoloredword{\dowithnextboxcs\syst_boxes_hyphenatednextboxcolor\hbox} + +%D \macros +%D {processtokens} +%D +%D We fully agree with (most) typographers that inter||letter spacing is only +%D permitted in fancy titles, we provide a macro that can be used to do so. Because +%D this is (definitely and fortunately) no feature of \TEX, we have to step through +%D 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 {\\}, \type {{}} and \type {\ +%D } are handled as space too. + +%D This can be done in a more modern way but for nostalgic reasons we keep it. + +\permanent\protected\def\processtokens#1#2#3#4#5% + {\begingroup + \def\lastcharacter{\lastcharacter}% hm, recursive ? + \enforced\permanent\def\space{ }% + \enforced\let\\\space + \def\before {#1}% + \def\between{#2}% + \def\after {#3}% + \def\white {#4}% + \let\savedbefore\before + \syst_boxes_processtokens#5\lastcharacter + \endgroup} + +\def\syst_boxes_processtokens% the space after = is essential + {\afterassignment\syst_boxes_do_processtokens\let\nextprocessedtoken= } + +\def\syst_boxes_redo_processedtoken + {\dowithnextbox + {\before{\copy\nextbox}% \before can use nextbox several times + \let\before\between + \syst_boxes_processtokens} + \hbox\bgroup} + +\def\syst_boxes_do_processtokens + {\ifx\nextprocessedtoken\lastcharacter + \after + \orelse\ifx\nextprocessedtoken\bgroup + \expandafter\syst_boxes_redo_processedtoken + \else + \expandafter\if\space\nextprocessedtoken + \after\white + \let\before\savedbefore + \else + \before\nextprocessedtoken + \let\before\between + \fi + \expandafter\syst_boxes_processtokens + \fi} + +%D \macros +%D {doboundtext} +%D +%D Sometimes there is not enough room to show the complete (line of) text. In such a +%D situation we can strip of some characters by using \type {\doboundtext}. When the +%D text is wider than the given width, it's split and the third argument is +%D appended. When the text to be checked is packed in a command, we'll have to use +%D \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 third argument into +%D account, which leads to a bit more complex macro than needed at first sight. +%D +%D Sort of obsolete I guess: + +\def\syst_boxes_boundtext#1% + {\setbox\scratchboxone\hbox{#1}% + \advance\scratchdimen -\wd\scratchboxone + \ifdim\scratchdimen>\zeropoint\relax#1\fi} + +\permanent\protected\def\doboundtext#1#2#3% still used? + {\hbox + {\setbox\scratchbox\hbox{#1}% + \scratchdimen#2\relax + \ifdim\wd\scratchbox>\scratchdimen + \setbox\scratchbox\hbox{#3}% + \advance\scratchdimen -\wd\scratchbox + \handletokens#1\with\syst_boxes_boundtext + \fi + \box\scratchbox}} + +%D \macros +%D {limitatetext} +%D +%D A bit more beautiful alternative for the previous command is the next one. This +%D command is more robust because we let \TEX\ do most of the job. The previous +%D command works better 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 sentinel is optional. +%D This is about the third version. + +\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi +\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi + +%D See \MKIV\ file for the older implementation. + +\permanent\protected\def\limitatetext#1#2#3% + {\splitatcomma{#2}\leftlimit\rightlimit + \limitated + left \leftlimit + \ifempty\rightlimit\else + right \rightlimit + \fi + strip true + sentinel {#3} + text {#1} + \relax} + +%D Undocumented bonus (see wiki): +%D +%D \starttyping +%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown} +%D \stoptyping + +\permanent\protected\def\limitatefirstline#1#2#3% + {\hbox\bgroup\strut % \hpack + \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 % \hpack + {\ifx\clip\undefined + \box\plusone + \orelse\ifdim\wd\plusone>\hsize + \lower\strutdepth\hpack{\clip[\c!width=\hsize,\c!height=\lineheight]{\hpack{\raise\strutdepth\box\plusone}}}% + \else + \box\plusone + \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 + +\permanent\protected\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} + +\permanent\protected\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: + +\permanent\protected\def\applytocharacters#1% + {\dontleavehmode + \dowithnextbox{\clf_applytobox + method {char}% + box \nextbox + command {\csstring#1}% + nested true% + \relax}% + \hbox} + +\permanent\protected\def\applytowords#1% + {\dontleavehmode + \dowithnextbox{\clf_applytobox + method {word}% + box \nextbox + command {\csstring#1}% + nested true% + \relax}% + \hbox} + +%D The old call: + +\permanent\protected\def\processwords#1% + {\processisolatedwords{#1}\processword} + +\let\processword\relax + +\permanent\protected\def\applytosplitstringchar#1#2% + {\dontleavehmode\clf_processsplit + data {#2}% + command {\csstring#1}% + method {char}% + \relax} + +\permanent\protected\def\applytosplitstringword#1#2% + {\dontleavehmode\clf_processsplit + data {#2}% + command {\csstring#1}% + method {word}% + \relax} + +\permanent\protected\def\applytosplitstringline#1#2% + {\dontleavehmode\clf_processsplit + data {#2}% + command {\csstring#1}% + method {line}% + \relax} + +\permanent\protected\def\applytosplitstringcharspaced#1#2% + {\dontleavehmode\clf_processsplit + data {#2}% + command {\csstring#1}% + method {char}% + spaced true% + \relax} + +\permanent\protected\def\applytosplitstringwordspaced#1#2% + {\dontleavehmode\clf_processsplit + data {#2}% + command {\csstring#1}% + method {word}% + spaced true% + \relax} + +\permanent\protected\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 and and limits the +%D size to the height and depth of a \type {\strut}. The resulting bottom||alligned +%D box can be used 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 the first two lines +%D would have ended up in the text. This macro can be useful when building +%D complicated menus, headers and footers and|/|or margin material. + +\permanent\protected\def\sbox + {\vpack\bgroup + \dowithnextboxcs\syst_boxes_sbox_finish\vbox} + +\def\syst_boxes_sbox_finish + {\boxyoffset\nextbox-\strutdp + \dp\nextbox\strutdp + \ht\nextbox\strutht + \box\nextbox + \egroup} + +%D A variant on this: +%D +%D \starttyping +%D xx \ruledhbox{\inlinedbox{\tfd test}} xx +%D \stoptyping + +\permanent\protected\def\inlinedbox + {\bgroup + \dowithnextboxcs\syst_boxes_inlined_finish\hbox} + +\def\syst_boxes_inlined_finish + {\boxyoffset\nextbox-\dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax + \ht\nextbox\strutht + \dp\nextbox\strutdp + \box\nextbox + \egroup} + +%D \macros +%D {struttedbox} +%D +%D This boxing macro limits the height and depth to those of a strut. + +\permanent\protected\def\struttedbox + {\hpack\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 and strutheight. Watch +%D how we preserve the depth when it equals strutdepth. + +\permanent\protected\def\topskippedbox + {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox} + +\def\syst_boxes_topskippedbox_finish + {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}% + \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 with positive or +%D negative offsets. This command can be used in well defined areas where no offset +%D options are available. We first used it when building a button inside the margin +%D footer, where the button should have a horizontal offset and should be centered +%D with respect to the surrounding box. The last of the three examples we show below +%D 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 and \type {\vrule} is +%D 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 \type {height}. +%D Observing readers can see that we use \TEX's own scanner for grabbing these +%D arguments: \type {#1#} reads everyting till the next brace and passes it to both +%D rules. The setting of the box dimensions at the end is needed for special cases. +%D The dimensions of the surrounding box are kept intact. This commands handles +%D positive and negative dimensions (which is why we need two boxes with rules). + +\permanent\protected\def\centeredbox#1#% height +/-dimen width +/-dimen + {\bgroup + \dontcomplain + \forgetall + \scangivendimensions#1\relax + \advance\vsize\givenheight + \advance\hsize\givenwidth + \dowithnextboxcs\syst_boxes_centered_finish + \hbox} + +\def\syst_boxes_centered_finish + {\boxxoffset\nextbox.5\dimexpr + \hsize + -\wd\nextbox + -\givenwidth + \relax + \boxyoffset\nextbox.5\dimexpr + \vsize + -\ht\nextbox + +\dp\nextbox + -\givenheight + \relax + \wd\nextbox\dimexpr\hsize-\givenwidth \relax + \ht\nextbox\dimexpr\vsize-\givenheight\relax + \dp\nextbox\zeropoint + \box\nextbox + \egroup} + +%D For those who don't want to deal with \type {\hsize} and \type {\vsize}, we have: +%D +%D \starttyping +%D \centerednextbox width 2bp height 2bp +%D {\framed[width=100bp,height=100bp]{}} +%D \stoptyping +%D +%D Do you see why we call this one \type {next}? + +\permanent\protected\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 {content} +%D \stoptyping +%D +%D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local +%D dimensions are supported. + +\permanent\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen + {\bgroup + \dowithnextbox + {\setlocalhsize + \setbox\scratchbox\hpack{\vrule\s!width \zeropoint#1}% + \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi + \setbox\scratchbox\vpack{\hrule\s!height\zeropoint#1}% + \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi + \vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}% + \egroup}% + \hbox} + +%D \macros +%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines} +%D +%D These macros are copied from the \TEX book, page~397, and extended by a macro +%D 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 footnotes. The following +%D flags influence the process. + +\newif\ifalignrigidcolumns +\newif\ifstretchrigidcolumns +\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections + +\permanent\protected\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 + +\mutable\let\rigidcolumnlines\!!zerocount + +\permanent\protected\def\rigidcolumnbalance#1% + {\ifnum\rigidcolumns=1 % tzt ook h/d correctie + \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax + \else + \vbox % \vpack + {\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\vtop + \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 pages 398 and 399 of the +%D \TEX book. These macros can be used 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 what they're meant +%D for. + +\newdimen\vboxtohboxslack +\newdimen\hboxestohboxslack + +%D Create line and fake height of paragraph by messign with heights: a nice hack by +%D DEK himself. + +%\protected\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} +% +% \protected\def\startvboxtohbox +% {\bgroup +% \setvboxtohbox +% \setbox\scratchbox\hbox\bgroup} +% +% \protected\def\stopvboxtohbox +% {\ifcase\vboxtohboxslack\else\hskip\zeropoint\s!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 + +\permanent\protected\def\startvboxtohboxseparator + {\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup} + +\permanent\protected\def\stopvboxtohboxseparator + {\egroup} + +\permanent\protected\def\startvboxtohbox + {\begingroup + \setbox\scratchbox\hbox\bgroup} + +\permanent\protected\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: + +\permanent\protected\def\convertvboxtohbox + {\makehboxofhboxes + \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack + \noindent\unhbox\scratchboxone\par} + +\permanent\protected\def\makehboxofhboxes + {\setbox\scratchboxone\emptyhbox + \loop % \doloop { .. \exitloop .. } + \setbox\scratchboxtwo\lastbox + \ifhbox\scratchboxtwo + \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}% + \repeat} + +\permanent\protected\def\removehboxes + {\setbox\scratchboxone\lastbox + \ifhbox\scratchboxone + {\removehboxes}\unhbox\scratchboxone + \fi} + +% And one special for notes: + +\permanent\protected\def\starthboxestohbox + {\bgroup + \setbox\scratchbox\vbox\bgroup} + +\permanent\protected\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. Let's first look at the +%D macro and then show an example. + +\newbox \unhhedbox +\newbox \hhbox +\newdimen \lasthhboxwidth +\newskip \hhboxindent + +\permanent\protected\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}% \hpack + \fi + \ht\hhbox\strutht + \dp\hhbox\strutdp + \ifzeropt\hhboxindent\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\syst_boxes_hboxofvbox + {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}% + \unhbox1 + \egroup} + +\permanent\protected\def\hboxofvbox + {\bgroup + \afterassignment\syst_boxes_hboxofvbox + \scratchcounter=} + +%D This macro can be used to break a paragraph apart and treat each line seperately, +%D for instance, making it clickable. The main complication is that we want to be +%D able to continue the 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 we've build in the +%D line that connects the two paragraphs. + +%D \macros +%D {doifcontent} +%D +%D When processing depends on the availability of content, one can give the next +%D 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 \type {\vbox}. If the +%D dimension of this box suggest some content, the resulting box is unboxed and +%D surrounded by the first two arguments, else the third arguments is executed. + +\permanent\protected\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 document, but definitely +%D generates a confusing message. + +%D \macros +%D {processboxes} +%D +%D The next macro gobble boxes and is for instance used for overlays. First we show +%D the general handler. + +\newbox\processbox % public : this is the one where \nextbox's end up in + +\permanent\protected\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} + +\protected\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 + +\permanent\def\boxisempty#1% + {\ifdim\wd#1=\zeropoint + \ifdim\ht#1=\zeropoint + \ifdim\dp#1=\zeropoint + \zerocount + \else + \plusone + \fi + \else + \plusone + \fi + \else + \plusone + \fi} + +\def\syst_boxes_overlay_process + {\ifcase\boxisempty\nextbox\else + \syst_boxes_overlay_process_indeed + \fi} + +\def\syst_boxes_overlay_process_indeed + {%\removeunwantedspaces % already done + \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi + \ifdim\ht\nextbox>\ht\processbox + \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}}} + +\permanent\protected\def\startoverlay + {\bgroup + \enforced\aliased\let\stopoverlay\egroup + \processboxes\syst_boxes_overlay_process} + +\aliased\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 specified, here being zero. + +\permanent\protected\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 accept something like +%D \type {to 3cm}, but align to the left, middle and right. These box types can be +%D used to typeset paragraphs. + +\def\syst_boxes_lrc_process#1% + {\bgroup + \forgetall + \enforced\let\\\endgraf + #1% + \let\nexttoken} + +\permanent\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft } +\permanent\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter} +\permanent\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright } + +\permanent\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft } +\permanent\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter} +\permanent\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright } + +%D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align +%D boxes, like in: +%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 + +\permanent\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} +\permanent\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} + +\def\syst_boxes_tbox_finish + {\scratchheight\ht\strutbox + \scratchdepth\dimexpr\htdp\nextbox-\scratchheight\relax + \ht\nextbox\scratchheight + \dp\nextbox\scratchdepth + \boxyoffset\nextbox-\scratchdepth + \box\nextbox + \egroup} + +\def\syst_boxes_bbox_finish + {\scratchdepth\dp\strutbox + \scratchheight\dimexpr\htdp\nextbox-\scratchdepth\relax + \dp\nextbox\scratchdepth + \ht\nextbox\scratchheight + \boxyoffset\nextbox-\scratchdepth + \box\nextbox + \egroup} + +%D \macros +%D {lhbox,mhbox,rhbox} +%D +%D A few more boxes. + +\def\syst_boxes_lhbox{\hpack to \hsize{\box\nextbox\hss }} +\def\syst_boxes_mhbox{\hpack to \hsize{\hss\box\nextbox\hss}} +\def\syst_boxes_rhbox{\hpack to \hsize{\hss\box\nextbox }} + +\permanent\protected\def\lhbox{\dowithnextboxcs\syst_boxes_lhbox\hbox} +\permanent\protected\def\mhbox{\dowithnextboxcs\syst_boxes_mhbox\hbox} +\permanent\protected\def\rhbox{\dowithnextboxcs\syst_boxes_rhbox\hbox} + +\aliased\let\lefthbox \lhbox +\aliased\let\midhbox \mhbox +\aliased\let\righthbox\rhbox + +%D \macros +%D {boxofsize} +%D +%D Sometimes we need to construct a box with a height or width made up of several +%D dimensions. Instead of cumbersome 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 negative values. +%D Dimension registers are also accepted. + +\newdimen\sizeofbox + +\permanent\protected\def\boxofsize#1% + {\bgroup + \sizeofbox\zeropoint + \scratchdimen\zeropoint + \def\docommand + {\advance\sizeofbox\scratchdimen + \futurelet\nexttoken\dodocommand}% + \def\dodocommand + {\ifx\nexttoken\bgroup + \expanded{\egroup#1 to \the\sizeofbox}% + \else + \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen + \fi}% + \docommand} + +%D Some new, still undocumented features: + +% limitatetext -> beter {text} als laatste !! +% +% \limitvbox +% \limithbox + +\permanent\protected\def\limitatelines#1#2% size sentinel + {\dowithnextbox + {\scratchdimen#1\hsize + \ifdim\wd\nextbox>\scratchdimen + \setbox\nextbox\hbox + {\advance\scratchdimen -.1\hsize + \limitatetext{\unhbox\nextbox}{\scratchdimen}{\nobreak#2}}% + \fi + \unhbox\nextbox} + \hbox} + +\permanent\protected\def\fittoptobaselinegrid % weg hier + {\dowithnextbox + {\bgroup + \par + \scratchdimen\ht\nextbox + \ht\nextbox\strutht + \dp\nextbox\strutdp + \hpack{\box\nextbox} + \prevdepth\strutdp + \doloop + {\advance\scratchdimen -\lineheight + \ifdim\scratchdimen<\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\hpack + {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} + +\permanent\protected\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} + +\permanent\protected\def\placedbox + {\iftraceboxplacement\ruledhbox\else\hbox\fi} + +\newdimen\boxoffset +\newdimen\boxhdisplacement +\newdimen\boxvdisplacement + +\permanent\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox} +\permanent\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox} +\permanent\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox} +\permanent\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox} +\permanent\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox} +\permanent\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox} +\permanent\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox} +\permanent\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox} + +\aliased\let\topleftbox \lefttopbox +\aliased\let\toprightbox \righttopbox +\aliased\let\bottomleftbox \leftbottombox +\aliased\let\bottomrightbox\rightbottombox + +\def\syst_boxes_rightbox_finish + {\global\boxhdisplacement\boxoffset + \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_leftbox_finish + {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax + \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_topbox_finish + {\global\boxhdisplacement-.5\wd\nextbox + \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_bottombox_finish + {\global\boxhdisplacement-.5\wd\nextbox + \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_lefttopbox_finish + {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax + \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_righttopbox_finish + {\global\boxhdisplacement\boxoffset + \global\boxvdisplacement\dimexpr-\dp\nextbox-\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_leftbottombox_finish + {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax + \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_rightbottombox_finish + {\global\boxhdisplacement\boxoffset + \global\boxvdisplacement\dimexpr\ht\nextbox+\boxoffset\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\permanent\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox} +\permanent\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox} +\permanent\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox} +\permanent\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox} + +\def\syst_boxes_middlebox_finish + {\global\boxhdisplacement-.5\wd\nextbox + \global\boxvdisplacement.5\dimexpr\ht\nextbox-\dp\nextbox\relax + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_baselinemiddlebox_finish + {\global\boxhdisplacement\dimexpr-.5\wd\nextbox-\boxoffset\relax + \global\boxvdisplacement-\boxoffset + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_baselineleftbox_finish + {\global\boxhdisplacement\dimexpr-\wd\nextbox-\boxoffset\relax + \global\boxvdisplacement-\boxoffset + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +\def\syst_boxes_baselinerightbox_finish + {\global\boxhdisplacement\boxoffset + \global\boxvdisplacement-\boxoffset + \boxcursor + \boxxmove\nextbox \boxhdisplacement + \boxymove\nextbox-\boxvdisplacement + \box\nextbox + \egroup} + +%D \macros +%D {obox} +%D +%D Experimental, not yet frozen: + +\permanent\protected\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: + +\permanent\protected\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 have implemented a box +%D 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} + +\permanent\protected\def\setstackbox#1#2% + {\ifcsname\??stackbox#1:#2\endcsname\else + \expandafter\newbox\csname\??stackbox#1:#2\endcsname + \fi + \global\setbox\csname\??stackbox#1:#2\endcsname\vbox} + +\permanent\protected\def\initializeboxstack#1% + {\def\docommand##1{\setstackbox{#1}{##1}{}}% + \ifcsname\??stacklst#1\endcsname + \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand + \fi + \letgvalueempty{\??stacklst#1}} + +\permanent\protected\def\savebox#1#2% stack name + {% beware, \setxvalue defines the cs beforehand so we cannot use the test inside the { } + \ifcsname\??stacklst#1\endcsname + \xdefcsname\??stacklst#1\expandafter\endcsname\expandafter{\lastnamedcs,#2}% + \else + \xdefcsname\??stacklst#1\endcsname{#2}% + \fi + \setstackbox{#1}{#2}} + +\permanent\protected\def\flushbox#1#2% unwrapped + {\ifcsname\??stackbox#1:#2\endcsname + \box\lastnamedcs + \else + \emptybox + \fi} + +\permanent\protected\def\restorebox#1#2% unwrapped + {\ifcsname\??stackbox#1:#2\endcsname + \copy\lastnamedcs + \else + \emptybox + \fi} + +\permanent\protected\def\foundbox#1#2% wrapped + {\vpack + {\ifcsname\??stackbox#1:#2\endcsname + \copy\lastnamedcs + \fi}} + +\permanent\protected\def\doifelsebox#1#2% + {\unless\ifcsname\??stackbox#1:#2\endcsname + \expandafter\secondoftwoarguments + \orelse\ifvoid\lastnamedcs + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doifboxelse\doifelsebox + +%D This one is cheaper (the above is no longer used that much): + +\installcorenamespace {boxstack} + +\newcount\c_syst_boxes_stack + +\mutable\let\b_syst_boxes_stack\relax + +\protected\def\syst_boxes_stack_allocate + {\newbox\b_syst_boxes_stack + \letcsname\??boxstack\number\c_syst_boxes_stack\endcsname\b_syst_boxes_stack} + +\protected\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} + +\protected\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} + +\permanent\protected\def\localpushbox {\syst_boxes_push\relax} +\permanent\protected\def\localpopbox {\syst_boxes_pop \relax} + +\permanent\protected\def\globalpushbox{\syst_boxes_push\global} +\permanent\protected\def\globalpopbox {\syst_boxes_pop \global} + +%D And here is a more modern one (not yet in i-*): +%D +%D \starttyping +%D \dorecurse {100} { +%D \setbox\zerocount\hbox{test \recurselevel} +%D \putboxincache{foo}{\recurselevel}\zerocount +%D \copyboxfromcache{foo}{\recurselevel}\zerocount +%D \iftrue +%D \setbox\zerocount\hbox{\directboxfromcache{foo}{\recurselevel}}% +%D \else +%D \getboxfromcache{foo}{\recurselevel}\zerocount +%D \fi +%D } +%D \resetboxesincache{foo} +%D \stoptyping + +\permanent\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax} +\permanent\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax} +\permanent\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}} +\permanent\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax} +\permanent\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}} +\permanent\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}} +\permanent\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}} + +\permanent\protected\def\putnextboxincache#1#2% + {\dowithnextbox{\putboxincache{#1}{#2}\nextbox}} + +%D \macros +%D {removedepth, obeydepth} +%D +%D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes +%D sure we have depth. Both macros leave the \type {\prevdepth} untouched. + +\permanent\protected\def\removedepth + {\ifvmode + \ifdim\prevdepth>\zeropoint + \kern-\prevdepth + \fi + \fi} + +\permanent\protected\def\obeydepth + {\par % watch out for changes in math formulas + \ifvmode\ifdim\prevdepth<\zeropoint\orelse\ifdim\prevdepth<\strutdp + \kern\dimexpr\strutdp-\prevdepth\relax + \prevdepth\strutdp + \fi\fi} + +\permanent\protected\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. + +\permanent\protected\def\removebottomthings + {\dorecurse\plusfive{\unskip\unkern\unpenalty}} + +\permanent\protected\def\removelastskip % \ifvmode the plain tex one \fi, overloaded to \permanent in spac-ver + {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} + +%D \macros +%D {makestrutofbox} +%D +%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so +%D it will go away. + +\permanent\protected\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 construction). Nice stuff for +%D a tips and tricks maps article. +%D +%D \starttyping +%D \raisebox{100pt}\hbox{test} +%D \hsmash{\raisebox{100pt}\hbox{test}} +%D \stoptyping + +\permanent\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted +\permanent\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted + +\def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish} +\def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish} + +\def\syst_boxes_raise_finish + {\boxyoffset\nextbox\scratchdimen + \ht\nextbox\strutht + \dp\nextbox\strutdp + \box\nextbox + \egroup} + +\def\syst_boxes_lower_finish + {\boxyoffset\nextbox-\scratchdimen + \ht\nextbox\strutht + \dp\nextbox\strutdp + \box\nextbox + \egroup} + +% vcenter in text, we kunnen vcenter overloaden + +\permanent\protected\def\halfwaybox + {\hpack\bgroup + \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox} + +\def\syst_boxes_halfwaybox_finish + {\dp\nextbox\zeropoint + \lower.5\ht\nextbox\box\nextbox + \egroup} + +\permanent\protected\def\depthonlybox + {\tpack\bgroup + \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox} + +\def\syst_boxes_depthonlybox_finish + {\hsize\wd\nextbox + \kern\zeropoint\box\nextbox + \egroup} + +%D New: + +\permanent\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi} +\permanent\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi} + +%D And even rawer: + +\aliased\let\naturalvcenter\normalvtop % will go away + +% \appendtoks \let\vcenter\normalvcenter \to \everymathematics + +%D \macros +%D {frozenhbox} +%D +%D A not so well unhboxable box can be made with: + +\permanent\protected\def\frozenhbox + {\hpack\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} + +\permanent\protected\def\setboxllx #1#2{\edefcsname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\setboxlly #1#2{\edefcsname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} + +\permanent\protected\def\gsetboxllx#1#2{\xdefcsname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\gsetboxlly#1#2{\xdefcsname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} + +\permanent\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi} +\permanent\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi} + +\permanent\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence +\permanent\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence + +%D \macros +%D {shownextbox} +%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 + +\permanent\protected\def\shownextbox % seldom used + {\dowithnextbox + {\bgroup + \showboxbreadth\maxdimen + \showboxdepth \maxdimen + \scratchcounter\interactionmode + \batchmode + \showbox\nextbox + \box\nextbox + \interactionmode\scratchcounter + \egroup}} + +\permanent\protected\def\spreadhbox#1% rebuilds \hbox{} + {\bgroup + \ifhbox#1\relax + \setbox\scratchboxtwo\emptybox + \unhbox#1% + \doloop + {\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip + \setbox\scratchboxone\lastbox + \ifvoid\scratchboxone + \exitloop + \else + \setbox\scratchboxtwo\hbox + {\ifhbox\scratchboxone \spreadhbox\scratchboxone\else\box\scratchboxone\fi + \ifvoid\scratchboxtwo \else\hss\unhbox\scratchboxtwo\fi}% + \fi}% + \ifvoid\scratchboxtwo\else\unhbox\scratchboxtwo\fi + \else + \box#1% + \fi + \egroup} + +% Why not ... + +\showboxbreadth\plusthousand +\showboxdepth \plusthousand + +%D Moved from cont-new: +%D +%D \starttyping +%D \minimalhbox 100pt {test} +%D \stoptyping + +\permanent\protected\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: + +\permanent\protected\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: + +\aliased\let\hyphenatedhbox\hbox % was a macro in mkii + +%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 + +\aliased\let\getnaturaldimensions\clf_getnaturaldimensions % sets three dimensions +\aliased\let\naturalwd \clf_naturalwd % calculates and returns wd + +\aliased\let\getnaturalwd\clf_getnaturalwd % no intermediate +\aliased\let\setnaturalwd\clf_setnaturalwd % no intermediate + +\permanent\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox} + +\aliased\let\doifrighttoleftinboxelse\doifelserighttoleftinbox + +%D New, used in high/low: + +\definesystemattribute [runningtext] [public] + +\permanent\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-* + +%D To complement lua (yet undocumented): + +\permanent\protected\def\beginhbox{\hbox\bgroup} \aliased\let\endhbox\egroup +\permanent\protected\def\beginvbox{\vbox\bgroup} \aliased\let\endvbox\egroup +\permanent\protected\def\beginvtop{\vtop\bgroup} \aliased\let\endvtop\egroup + +\permanent\protected\def\sethboxregister#1{\setbox#1\hbox} +\permanent\protected\def\setvboxregister#1{\setbox#1\vbox} +\permanent\protected\def\setvtopregister#1{\setbox#1\vtop} + +\permanent\protected\def\flushboxregister#1{\box\numexpr#1\relax} + +\permanent\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \aliased\let\stophboxregister\egroup +\permanent\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \aliased\let\stopvboxregister\egroup +\permanent\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \aliased\let\stopvtopregister\egroup + +%D For whatever third party package needs it: +%D +%D \starttyping +%D \newlocalbox\BoxOne +%D \newlocalbox\BoxTwo +%D +%D \setbox\BoxOne\hbox{Box One} +%D \setbox\BoxTwo\hbox{Box Two} +%D +%D [\box\BoxTwo] [\box\BoxOne] +%D \stoptyping + +\installcorenamespace{localbox} + +\permanent\protected\def\newlocalbox#1% + {\expandafter\let\expandafter#1\csname\??localbox\string#1\endcsname + \ifx#1\relax + \syst_aux_new_localbox#1% + \fi} + +\def\syst_aux_new_localbox#1% + {\expandafter\newbox\csname\??localbox\string#1\endcsname + \newlocalbox#1} + +%D Who knows when this comes in handy: + +\permanent\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax} + +%D Keep as reference: + +% \protected\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox} +% \protected\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop} + +%D This one keeps dimensions and sets the shift field (and so it's more for testing +%D than for real usage): + +\permanent\protected\def\shiftbox {\clf_shiftbox} +\permanent\protected\def\vpackbox {\clf_vpackbox} +\permanent\protected\def\hpackbox {\clf_hpackbox} +\permanent\protected\def\vpackedbox{\clf_vpackedbox} +\permanent\protected\def\hpackedbox{\clf_hpackedbox} + +%D This one has been moved from a 2 decade old file. It makes something boxed +%D sit on the baseline. + +\permanent\protected\def\linebox + {\hpack\bgroup\dowithnextbox + {\scratchdimen\dimexpr\dimexpr\htdp\nextbox-\lineheight\relax/2+\dp\strutbox\relax + \setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}% + \ht\nextbox\ht\strutbox + \dp\nextbox\dp\strutbox + \box\nextbox + \egroup} + \hbox} + +%D \macros +%D {widthuptohere} +%D +%D Implemented at the \LUA\ end: +%D +%D \startbuffer +%D widthuptohere:\the\widthuptohere\crlf +%D widthuptohere : \the\widthuptohere (space without stretch or shrink!) +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D +%D Implemented elsewhere: +%D +%D \starttyping +%D \boxlines +%D \boxline +%D \copyboxline +%D \setboxline +%D \boxlineht [] +%D \boxlinedp [] +%D \boxlinewd [] +%D \boxlinels +%D \boxliners +%D \boxlinelh +%D \boxlinerh +%D \boxlinelp +%D \boxlinerp +%D \boxlinein +%D \boxrangeht +%D \boxrangedp +%D \boxrangewd +%D \stoptyping + +% To be discussed with ws. +% +% \installcorenamespace{namedboxes} +% +% \protected\def\newnamedbox#1% +% {\ifcsname\??namedboxes#1\endcsname\else +% \expandafter\newbox\csname\??namedboxes#1\endcsname +% \fi} +% +% \protected\def\namedbox#1{\csname\??namedboxes#1\endcsname} + +%D Implemented elsewhere: +%D +%D \startbuffer +%D \setbox0\hbox{test \footnote{test}} (\prelistbox0) (\postlistbox0) +%D \setprelistbox0\hbox{BEFORE} \setpostlistbox0\hbox{AFTER} +%D \box0 +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D +%D \starttyping +%D \prelistbox +%D \postlistbox +%D \prelistcopy +%D \postlistcopy +%D \setprelistbox +%D \setpostlistbox +%D \stoptyping + +\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 +% +% \protected\def\withwordsinstring#1#2% command str +% {\ctxcommand{withwords(\!!bs#1\!!es,\!!bs#2\!!es)}} +% +% \protected\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/tex/context/base/mkxl/supp-dir.mkxl b/tex/context/base/mkxl/supp-dir.mkxl new file mode 100644 index 000000000..d2500d236 --- /dev/null +++ b/tex/context/base/mkxl/supp-dir.mkxl @@ -0,0 +1,44 @@ +%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. + +\unprotect + +\aliased\let\directionlefttoright\zerocount +\aliased\let\directionrighttoleft\plusone + +\immutable\edef\??bdir{\ifdefined\bodydir bdir\else direction\fi} + +\permanent\protected\edef\naturalhbox {\hbox \??bdir\directionlefttoright} +\permanent\protected\edef\naturalvbox {\vbox \??bdir\directionlefttoright} +\permanent\protected\edef\naturalvtop {\vtop \??bdir\directionlefttoright} +\permanent\protected\edef\naturalhpack {\hpack \??bdir\directionlefttoright} +\permanent\protected\edef\naturalvpack {\vpack \??bdir\directionlefttoright} +\permanent\protected\edef\naturaltpack {\tpack \??bdir\directionlefttoright} + +\permanent\protected\edef\reversehbox {\hbox \??bdir\directionrighttoleft} +\permanent\protected\edef\reversevbox {\vbox \??bdir\directionrighttoleft} +\permanent\protected\edef\reversevtop {\vtop \??bdir\directionrighttoleft} +\permanent\protected\edef\reversehpack {\hpack \??bdir\directionrighttoleft} +\permanent\protected\edef\reversevpack {\vpack \??bdir\directionrighttoleft} +\permanent\protected\edef\reversetpack {\tpack \??bdir\directionrighttoleft} + +% \expanded{\defineactivecharacter \number"2000E} {\textdirection\directionrighttoleft\relax} +% \expanded{\defineactivecharacter \number"2000F} {\textdirection\directionlefttoright\relax} + +\def\syst_direction_string#1{\ifcase#1=\plusone r2l\else l2r\fi} + +\permanent\protected\def\showdirsinmargin + {\normalexpanded{\inleft{\naturalhbox + {\ttxx[\syst_direction_string\pardirection,\syst_direction_string\textdirection]}}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/supp-mat.mkxl b/tex/context/base/mkxl/supp-mat.mkxl new file mode 100644 index 000000000..7e0086fc8 --- /dev/null +++ b/tex/context/base/mkxl/supp-mat.mkxl @@ -0,0 +1,180 @@ +%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 a support module. +%D There is nothing spectacular here. It may move 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. This can lead to +%D confusing and errorprone situations when macros insert \type {$}. When for +%D 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 definitely +%D complain about this. A more save definition would have been: +%D +%D \starttyping +%D \def\MyPlus{\mathematics{\,+\,}} +%D \stoptyping +%D +%D Which is implemented (in \type{syst-ini.mkiv}) as: + +\permanent\protected\def\Ucheckedstartdisplaymath + {\ifinner + \ifhmode + \normalUstartmath + \let\Ucheckedstopdisplaymath\normalUstopmath + \else + \normalUstartdisplaymath + \let\Ucheckedstopdisplaymath\normalUstopdisplaymath + \fi + \else + \normalUstartdisplaymath + \let\Ucheckedstopdisplaymath\normalUstopdisplaymath + \fi} + +\aliased\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 + +\aliased\let\startimath\Ustartmath +\aliased\let\stopimath \Ustopmath +\aliased\let\startdmath\Ustartdisplaymath % \Ucheckedstartdisplaymath +\aliased\let\stopdmath \Ustopdisplaymath % \Ucheckedstopdisplaymath + +\permanent\protected\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi} +\permanent\protected\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi} +\permanent\protected\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi} +\permanent\protected\def\textmath #1{\dontleavehmode\ifmmode#1\else\begingroup\everymath\emptytoks\normalstartimath#1\normalstopimath\endgroup\fi} % \mathsurround\zeropoint + +\aliased\let\stopmathmode\relax + +\permanent\protected\def\startmathmode % nested variant + {\relax\ifmmode + \begingroup + \enforced\let\stopmathmode\endgroup + \else + \normalstartimath + \enforced\let\stopmathmode\normalstopimath + \fi} + +\permanent\protected\def\nomathematics#1% + {\relax\ifmmode\hbox{#1}\else#1\fi} + +\aliased\let\m \mathematics % \mathematics will be overloaded later +\aliased\let\math\mathematics % \mathematics will be overloaded later + +%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 + +\permanent\protected\def\displaymathematics#1{\relax\ifmmode#1\else\strc_formulas_start_formula{}#1\strc_formulas_stop_formula\fi} +\permanent\protected\def\inlinemathematics {\dontleavehmode\mathematics} +%permanent\protected\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi} + +% better, esp when used in bTABLE ... eTABLE + +\permanent\protected\def\automathematics + {\relax + \ifhmode + \expandafter\inlinemathematics + \orelse\ifintable + \doubleexpandafter\inlinemathematics + \else + \doubleexpandafter\displaymathematics + \fi} + +%D \macros +%D {dimension, nodimension} +%D +%D The next few macros are used for typesetting dimensions in such a way that +%D spacing is acceptable. I won't spend much words on these macros, because they +%D will be overloaded in the units module. +%D +%D REPLACED (keep commented): + +\newsignal\dimensionsignal + +\def\dimensiontypeface {\tf} +\def\dimensionhalfspace {\,} + +\protected\def\dimension#1% + {\pushmacro\dodimensionsignal + \gdef\dodimensionsignal{\kern\dimensionsignal}% + \ifzeropt\lastskip + \ifzeropt\lastkern + \ifmmode + \mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% + \else + \mathematics{\dimensiontypeface#1}% + \fi + \orelse\ifdim\lastkern=\dimensionsignal + \mathematics{\dimensionhalfspace\dimensiontypeface#1}% + \else + \unkern\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% + \fi + \else + \unskip\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% + \fi + \dodimensionsignal + \popmacro\dodimensionsignal} + +\protected\def\nodimension#1% + {\unskip#1\glet\dodimensionsignal\relax} + +% experiment, not yet to be used + +% \protected\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} + +\aliased\let\superscript \Usuperscript +\aliased\let\subscript \Usubscript +\aliased\let\nosuperscript \Unosuperscript +\aliased\let\nosubscript \Unosubscript +\aliased\let\superprescript \Usuperprescript +\aliased\let\subprescript \Usubprescript +\aliased\let\nosuperprescript\Unosuperprescript +\aliased\let\nosubsprecript \Unosubprescript + +\protect \endinput diff --git a/tex/context/base/mkxl/supp-ran.mkxl b/tex/context/base/mkxl/supp-ran.mkxl new file mode 100644 index 000000000..e70c3d437 --- /dev/null +++ b/tex/context/base/mkxl/supp-ran.mkxl @@ -0,0 +1,49 @@ +%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 the user +%D interface (which uses intermediate variables). +%D +%D \starttyping +%D \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \pushrandomseed \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \poprandomseed \type{old}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \stoptyping + +\registerctxluafile{supp-ran}{} + +\unprotect + +\permanent\protected\def\getrandomcount #1#2#3{#1=\clf_getrandomnumber\numexpr#2\relax\numexpr#3\relax\relax} +\permanent\protected\def\getrandomdimen #1#2#3{#1=\clf_getrandomdimen\dimexpr#2\relax\dimexpr#3\relax\scaledpoint\relax} +\permanent\protected\def\getrandomnumber#1#2#3{\edef#1{\clf_getrandomnumber\numexpr#2\relax\numexpr#3\relax}} +\permanent\protected\def\getrandomfloat #1#2#3{\edef#1{\clf_getrandomfloat\dimexpr#2\relax\dimexpr#3\relax}} +\permanent\protected\def\setrandomseed #1{\clf_setrandomseed\numexpr#1\relax} +\permanent\protected\def\getrandomseed #1{\edef#1{\clf_getrandomseed}} +%permanent\protected\def\pushrandomseed {\clf_pushrandomseed} +%permanent\protected\def\poprandomseed {\clf_poprandomseed} +%permanent\protected\def\reuserandomseed {\clf_reuserandomseed} % within push/pop + +\aliased\let\freezerandomseed \pushrandomseed +\aliased\let\defrostrandomseed\poprandomseed + +\permanent\def\randomnumber #1#2{\clf_getrandomnumber\numexpr#1\relax\numexpr#2\relax} +\permanent\def\mprandomnumber {\clf_getmprandomnumber} + +\protect \endinput diff --git a/tex/context/base/mkxl/symb-emj.mkxl b/tex/context/base/mkxl/symb-emj.mkxl new file mode 100644 index 000000000..96c4c0859 --- /dev/null +++ b/tex/context/base/mkxl/symb-emj.mkxl @@ -0,0 +1,26 @@ +%D \module +%D [ file=symb-emj, +%D version=2017.04.21, +%D title=\CONTEXT\ Symbol Libraries, +%D subtitle=Emoji, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Symbol Libraries / Emoji} + +\registerctxluafile{symb-emj}{} + +\unprotect + +\permanent \def\expandedemoji#1{\clf_resolvedemoji{#1}} +\permanent\protected\def\resolvedemoji#1{\clf_resolvedemoji{#1}} +\permanent\protected\def\checkedemoji #1{\clf_checkedemoji {#1}} +\permanent\protected\def\emoji #1{\dontleavehmode{\setdirectsymbolicfont{emoji}\clf_resolvedemoji{#1}}} +\permanent\protected\def\robustemoji #1{\dontleavehmode{\setdirectsymbolicfont{emoji}\clf_checkedemoji {#1}}} + +\protect \endinput diff --git a/tex/context/base/mkxl/symb-ini.mkxl b/tex/context/base/mkxl/symb-ini.mkxl new file mode 100644 index 000000000..1d1f66c17 --- /dev/null +++ b/tex/context/base/mkxl/symb-ini.mkxl @@ -0,0 +1,340 @@ +%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 {core-con} module. I +%D decided to move them here when symbolsets saw the light. Let their light shine. + +\writestatus{loading}{ConTeXt Symbol Libraries / Initialization} + +\registerctxluafile{symb-ini}{} + +\unprotect + +%D \macros +%D {definesymbol, symbol} +%D +%D Converting numbers or levels into a character, romannumeral, symbol or something +%D else, is supported by many \CONTEXT\ commands. Therefore we need a mechanism for +%D linking such numbers to their counterparts. +%D +%D First we take care of symbols. These are for instance used in enumerations and +%D itemizations. We have: +%D +%D \showsetup{definesymbol} +%D \showsetup{symbol} +%D +%D Symbols are simply linked to a tag. Such tags can be numbers or strings. +%D +%D \starttyping +%D \definesymbol [1] [$\bullet$] +%D \definesymbol [level 5] [$\star$] +%D \stoptyping + +\installcorenamespace{symbol} +\installcorenamespace{symbols} +\installcorenamespace{symbolset} +\installcorenamespace{symboldefault} + +%D For now we only have one option. + +\installparameterhandler\??symbols {symbols} +\installsetuphandler \??symbols {symbols} + +\appendtoks + \doifelse{\symbolsparameter\c!stylealternative}\v!math + \settrue\setfalse\prefermathovertextchar +\to \everysetupsymbols + +\setupsymbols + [\c!stylealternative=\v!text] + +\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 subsystem for resolving +%D values. + +\permanent\tolerant\protected\def\definesymbol[#1]#*[#2]#*[#3]% + {\ifparameter#3\or + \defcsname\??symbol#1:#2\endcsname{#3}% + \doifsomething{#1}{\addvalue{\??symbolset#1}{#2}}% + \else + \defcsname\??symbol\m_symb_current_set:#1\endcsname{#2}% + \addvalue{\??symbolset\m_symb_current_set}{#1}% + \fi} + +\permanent\protected\def\doifelseinsymbolset#1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} +\permanent\protected\def\doifinsymbolset #1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\permanent\protected\def\doifelsesymbolset #1{\ifcsname\??symbolset#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} + +\aliased\let\doifinsymbolsetelse\doifelseinsymbolset +\aliased\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 + +\permanent\def\symbolset#1{\begincsname\??symbolset#1\endcsname} % no [#1], to be used in commalists etc + +%D Since symbols are used frequently in interactive documents, we speed up this one. +%D Well, that was history, 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}. + +\permanent\tolerant\protected\def\symbol[#1]#*[#2]% + {\ifarguments + \expandafter\symb_place_argument + \or + \symb_place_argument{#1}% + \or + \dontleavehmode + \edef\currentsymbol{#2}% + \ifcsname\??symbol#1:#2\endcsname + \symb_place_indeed{#1:#2}% maybe use \lastnamescs + \orelse\ifcsname\??symboldefault#1\endcsname + \symb_place_named{#1}% maybe use \lastnamescs + \else + \symb_place_normal + \fi + \fi} + +\def\symb_place_argument#1% + {\dontleavehmode + \edef\currentsymbol{#1}% + \ifcsname\??symbol\currentsymbolset:#1\endcsname + \symb_place_indeed{\currentsymbolset:#1}% + \else + \symb_place_normal + \fi} + +\def\symb_place_normal + {\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_indeed#1% \relax's prevent lookahead problems + {\settrue\c_symb_found + \begingroup + \the\everysymbol + \csname\??symbol#1\endcsname\relax + \endgroup} + +\letvalue{\??symbol}\firstofoneargument + +\permanent\def\directsymbol#1#2% no \relax, there can be an argument, see lists + {\begincsname\??symbol#1:#2\endcsname} + +\protected\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}% + \orelse\ifcsname\??symboldefault#1\endcsname + \symb_place_named{#1}% + \fi} + +\def\symb_place_named#1% \relax's prevent lookahead problems + {\begingroup + \setbox\scratchbox\hbox\bgroup + \the\everysymbol + \getglyphstyled + {\csname\??symboldefault#1\endcsname}% + {\tochar{n:\currentsymbol}}% + \relax + \egroup + \ifdim\wd\scratchbox>\zeropoint + \unhbox\scratchbox + \endgroup + \xdefcsname\??symbol#1:\currentsymbol\endcsname{\symb_place_named_indeed{#1}{\currentsymbol}}% + \settrue\c_symb_found + \else + \endgroup + \fi} + +\protected\def\symb_place_named_indeed#1#2% \relax's prevent lookahead problems + {\settrue\c_symb_found + \begingroup + \the\everysymbol + \getglyphstyled + {\csname\??symboldefault#1\endcsname}% + {\tochar{n:#2}}% + \relax + \endgroup} + +\def\symb_place_retry#1% + {\ifcsname\??symbol:#1\endcsname + \symb_place_indeed{:#1}% + \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 size or running font +%D size (which is better). + +\ifdefined\externalfigure \else \def\externalfigure[#1][#2]{#1} \fi + +\def\defaultsymbolfactor{10} +\def\defaultsymbolheight{1.25ex} + +\permanent\tolerant\protected\def\figuresymbol[#1]#*[#2]% + {\externalfigure[#1][\c!reset=\v!yes,\c!symbol=\v!yes,\c!height=\defaultsymbolheight,#2]} + +\permanent\tolerant\protected\def\definefiguresymbol[#1]#*[#2]#*[#3]% + {\ifarguments\or\else + \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}} + +\permanent\protected\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} + +\aliased\let\doifsymboldefinedelse\doifelsesymboldefined + +%D \macros +%D {setupsymbolset,startsymbolset} +%D +%D From these macro definitions one can deduce that symbols can be grouped in +%D 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} + +\permanent\tolerant\protected\def\startsymbolset[#1]#*[#2]% + {\pushmacro\m_symb_current_set + \def\m_symb_current_set{#1}% + \ifarguments\or\or + \getdummyparameters[\s!font=,#2]% + \edef\p_font{\dummyparameter\s!font}% + \ifempty\p_font\else + \letcsname\??symboldefault#1\endcsname\p_font + \fi + \fi} + +\permanent\protected\def\stopsymbolset + {\popmacro\m_symb_current_set} + +\permanent\protected\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}}% + \letcsname\??symbolsets\currentsymbolset\endcsname\empty} % speedup + +\permanent\protected\def\resetsymbolset + {\t_symb_setups\emptytoks} + +\permanent\protected\def\forcesymbolset[#1]% + {\t_symb_setups{\symb_fetch{#1}}} + +%D \macros +%D {showsymbolset} +%D +%D \showsetup{showsymbolset} + +\fetchruntimecommand \showsymbolset \f!symb_run + +%D \macros +%D {usesymbols} +%D +%D \showsetup{usesymbols} + +\permanent\protected\def\usesymbols[#1]{\clf_usesymbols{#1}} + +%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. + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-aux.lmt b/tex/context/base/mkxl/syst-aux.lmt new file mode 100644 index 000000000..c0de8a953 --- /dev/null +++ b/tex/context/base/mkxl/syst-aux.lmt @@ -0,0 +1,747 @@ + if not modules then modules = { } end modules ['syst-aux'] = { + version = 1.001, + comment = "companion to syst-aux.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- slower than lpeg: +-- +-- utfmatch(str,"(.?)(.*)$") +-- utf.sub(str,1,1) + +local tonumber, next, type = tonumber, next, type +local utfsub = utf.sub +local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match +local find, formatters = string.find, string.formatters + +local context = context +local implement = interfaces.implement +local setmacro = interfaces.setmacro +local setcatcode = tex.setcatcode +local texget = tex.get +local utf8character = lpeg.patterns.utf8character +local settings_to_array = utilities.parsers.settings_to_array +local settings_to_set = utilities.parsers.settings_to_set + +local pattern = C(utf8character^-1) * C(P(1)^0) + +implement { + name = "getfirstcharacter", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + setmacro("firstcharacter",first) + setmacro("remainingcharacters",rest) + end +} + +implement { + name = "thefirstcharacter", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + context(first) + end +} + +implement { + name = "theremainingcharacters", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + context(rest) + end +} + +local pattern = C(utf8character^-1) +local ctx_doifelse = commands.doifelse + +implement { + name = "doifelsefirstchar", + arguments = "2 strings", + actions = function(str,chr) + ctx_doifelse(lpegmatch(pattern,str) == chr) + end +} + +implement { + name = "getsubstring", + arguments = "3 strings", + actions = function(str,first,last) + context(utfsub(str,tonumber(first),tonumber(last))) + end +} + +-- function commands.addtocommalist(list,item) +-- if list == "" then +-- context(item) +-- else +-- context("%s,%s",list,item) -- using tex.print is some 10% faster +-- end +-- end +-- +-- function commands.removefromcommalist(list,item) +-- if list == "" then +-- context(item) +-- else +-- -- okay, using a proper lpeg is probably faster +-- -- we could also check for #l = 1 +-- local l = settings_to_array(list) +-- local t, n = { } +-- for i=1,#l do +-- if l[i] ~= item then +-- n = n + 1 +-- t[n] = item +-- end +-- end +-- if n == 0 then +-- context(item) +-- else +-- context(concat(list,",")) +-- end +-- end +-- end + +local pattern = (C((1-P("%"))^1) * Carg(1)) / function(n,d) + return formatters["%.0fsp"](d * tonumber(n)/100) end * P("%") * P(-1) -- .0 ? + +-- percentageof("10%",65536*10) + +implement { + name = "percentageof", + arguments = { "string", "dimen" }, + actions = function(str,dim) + context(lpegmatch(pattern,str,1,dim) or str) + end +} + +-- \gdef\setpercentdimen#1#2% +-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} + +local space = P(" ") / "" +local spaces = P(" ")^0 / "" +local nohash = 1 - P("#") +local digit = R("09") +local double = P("##") / "#" +local single = P("#") +local sentinel = spaces * (nohash^1 / "\\%0") +local whatever = S("+-/*_^=:") + digit +local sargument = (single * digit)^1 +local dargument = (double * digit)^1 +local swhatever = (single * whatever)^1 +local dwhatever = (double * whatever)^1 + +-- different ones: + +local space = P(" ") +local spaces = space^0 + +-- see syst-aux.lua for historic variants + +local global = nil +local protected = nil +local expanded = nil +local optional = nil +local tolerant = nil +local instance = nil +local frozen = nil +local csname = nil +local rest = nil + +local function catcodes_s() + setcatcode(32,10) -- space + setcatcode(13, 5) -- endofline +end + +local function catcodes_n() + setcatcode(32, 9) -- ignore + setcatcode(13, 9) -- ignore +end + +local function oldoption(s) + if optional > 1 then + optional = optional - 1 + return s .. "#*" + else + return s + end +end + +local option = ( + P("single") * Cc(1) + + P("double") * Cc(2) + + P("triple") * Cc(3) + + P("quadruple") * Cc(4) + + P("quintuple") * Cc(5) + + P("sixtuple") + ) * (P("empty") + P("argument")) + +local pattern = ( + ( + spaces * ( + ( P("spaces") * space / catcodes_s ) + + ( P("nospaces") * space / catcodes_n ) + + ( P("global") * space / function() global = true end) + + ( P("protected") * space / function() protected = true end) + + ( P("expanded") * space / function() expanded = true end) + + ( P("tolerant") * space / function() tolerant = true end) + + ( P("instance") * space / function() instance = true end) + + ( P("frozen") * space / function() frozen = true end) + + ( P("unexpanded") * space / function() protected = true end) + + ( option * space / function(s) tolerant = true + optional = s end) + ) + )^0 + * spaces * ( C((1-S(" #["))^1) ) + * spaces * Cs( + (Cs(P("[") * dargument * P("]")) / oldoption + dwhatever)^1 * sentinel^-1 * double^-1 + + (Cs(P("[") * sargument * P("]")) / oldoption + swhatever)^1 * sentinel^-1 * single^-1 + + sentinel^-1 * (double+single)^-1 + ) +) + +local ctx_dostarttexdefinition = context.dostarttexdefinition + +local function texdefinition_one(str) + global = false + protected = false + expanded = false + optional = 0 + tolerant = false + instance = false + frozen = false + csname, rest = lpegmatch(pattern,str) + ctx_dostarttexdefinition() +end + +local function texdefinition_two() + context ( + (tolerant and [[\tolerant]] or "") .. (frozen and [[\frozen]] or "") .. (protected and [[\protected]] or "") .. (instance and [[\instance]] or "") .. + [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) .. + [[\csname ]] .. csname .. [[\endcsname ]] .. + rest + ) +end + +implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" } +implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" } + +do + + -- Quite probably we don't yet have characters loaded so we delay some + -- aliases. + + local _lower_, _upper_, _strip_ + + _lower_ = function(s) + if characters and characters.lower then + _lower_ = characters.lower + return _lower_(s) + end + return string.lower(s) + end + + _upper_ = function(s) + if characters and characters.upper then + _upper_ = characters.upper + return _upper_(s) + end + return string.upper(s) + end + + _strip_ = function(s) + -- or utf.strip + if string.strip then + _strip_ = string.strip + return _strip_(s) + end + return s + end + + local function lower(s) context(_lower_(s)) end + local function upper(s) context(_upper_(s)) end + local function strip(s) context(_strip_(s)) end + + implement { name = "upper", arguments = "string", actions = upper } + implement { name = "lower", arguments = "string", actions = lower } + implement { name = "strip", arguments = "string", actions = strip } + +end + +implement { + name = "converteddimen", + arguments = { "dimen", "string" }, + actions = function(dimen,unit) + context(number.todimen(dimen,unit or "pt","%0.5f")) -- no unit appended (%F) + end +} + +-- where, not really the best spot for this: + +implement { + name = "immediatemessage", + arguments = { "'message'", "string" }, + actions = logs.status +} + +implement { + name = "resettimer", + actions = function() + statistics.resettiming("whatever") + statistics.starttiming("whatever") + end +} + +implement { + name = "benchmarktimer", + actions = function() + statistics.benchmarktimer("whatever") + end +} + +implement { + name = "elapsedtime", + actions = function() + statistics.stoptiming("whatever") + context(statistics.elapsedtime("whatever")) + end +} + +implement { + name = "elapsedsteptime", + arguments = "integer", + actions = function(n) + statistics.stoptiming("whatever") + local t = statistics.elapsed("whatever")/(n > 0 and n or 1) + if t > 0 then + context("%0.9f",t) + else + context(0) + end + end +} + +local accuracy = table.setmetatableindex(function(t,k) + local v = formatters["%0." ..k .. "f"] + t[k] = v + return v +end) + +implement { + name = "rounded", + arguments = "integer", + actions = function(n,m) context(accuracy[n](m)) end +} + +-- not faster but just less tracing: + +local ctx_protected_cs = context.protected.cs -- more efficient + +local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments +local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments +local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument +local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument + +context.firstoftwoarguments = ctx_firstoftwoarguments +context.secondoftwoarguments = ctx_secondoftwoarguments +context.firstofoneargument = ctx_firstofoneargument +context.gobbleoneargument = ctx_gobbleoneargument + +local ctx_iftrue = context.iftrue +local ctx_iffalse = context.iffalse + +local hash = utilities.parsers.hashes.settings_to_set + +local function doifelsecommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_secondoftwoarguments() + else + ctx_firstoftwoarguments() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_firstoftwoarguments() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_firstoftwoarguments() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstoftwoarguments() + return + end + end + setmacro("commalistelement","") + ctx_secondoftwoarguments() +end + +local function doifcommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_firstofoneargument() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_firstofoneargument() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstofoneargument() + return + end + end + setmacro("commalistelement","") + ctx_gobbleoneargument() +end + +local function doifnotcommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_gobbleoneargument() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_gobbleoneargument() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_gobbleoneargument() + return + end + end + setmacro("commalistelement","") + ctx_firstofoneargument() +end + +-- local function hascommonargumentcondition(a,b) +-- if a == b then +-- setmacro("commalistelement",a) +-- if a == "" then +-- ctx_iffalse() +-- else +-- ctx_iftrue() +-- end +-- return +-- end +-- local ba = find(a,",",1,true) +-- local bb = find(b,",",1,true) +-- if ba and bb then +-- local ha = hash[a] +-- local hb = hash[b] +-- for k in next, ha do +-- if hb[k] then +-- setmacro("commalistelement",k) +-- ctx_iftrue() +-- return +-- end +-- end +-- elseif ba then +-- if hash[a][b] then +-- setmacro("commalistelement",b) +-- ctx_iftrue() +-- return +-- end +-- elseif bb then +-- if hash[b][a] then +-- setmacro("commalistelement",a) +-- ctx_iftrue() +-- return +-- end +-- end +-- setmacro("commalistelement","") +-- ctx_iffalse() +-- end + +local function doifelseinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_secondoftwoarguments() + else + ctx_firstoftwoarguments() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstoftwoarguments() + return + end + end + setmacro("commalistelement","") + ctx_secondoftwoarguments() +end + +local function doifinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstofoneargument() + return + end + end + setmacro("commalistelement","") + ctx_gobbleoneargument() +end + +local function doifnotinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_gobbleoneargument() + return + end + end + setmacro("commalistelement","") + ctx_firstofoneargument() +end + +implement { + name = "doifelsecommon", + actions = doifelsecommon, + arguments = "2 strings", +} + +implement { + name = "doifcommon", + actions = doifcommon, + arguments = "2 strings", +} + +implement { + name = "doifnotcommon", + actions = doifnotcommon, + arguments = "2 strings", +} + +-- implement { +-- name = "hascommonargumentcondition", +-- actions = hascommonargumentcondition, +-- arguments = "2 strings", +-- arguments = { "argument", "argument" }, +-- } + +implement { + name = "doifelseinset", + actions = doifelseinset, + arguments = "2 strings", +-- arguments = { "argument", "argument" }, +} + +implement { + name = "doifinset", + actions = doifinset, + arguments = "2 strings", +} + +implement { + name = "doifnotinset", + actions = doifnotinset, + arguments = "2 strings", +} + +-- done elsewhere: +-- +-- local function firstinset(a) +-- local aa = hash[a] +-- context(aa and aa[1] or a) +-- end +-- +-- implement { +-- name = "firstinset", +-- actions = firstinset, +-- arguments = "string", +-- private = false, +-- } + +-- implement { +-- name = "stringcompare", +-- arguments = "2 strings", +-- actions = function(a,b) +-- context((a == b and 0) or (a > b and 1) or -1) +-- end +-- } +-- +-- implement { +-- name = "doifelsestringafter", +-- arguments = "2 strings", +-- actions = function(a,b) +-- ctx_doifelse((a == b and 0) or (a > b and 1) or -1) +-- end +-- } +-- +-- implement { +-- name = "doifelsestringbefore", +-- arguments = "2 strings", +-- actions = function(a,b) +-- ctx_doifelse((a == b and 0) or (a < b and -1) or 1) +-- end +-- } + +-- implement { -- not faster than addtocommalist +-- name = "additemtolist", -- unique +-- arguments = "2 strings", +-- actions = function(l,s) +-- if l == "" or s == l then +-- -- s = s +-- elseif find("," .. l .. ",","," .. s .. ",") then +-- s = l +-- else +-- s = l .. "," .. s +-- end +-- context(s) +-- end +-- } + +local bp = number.dimenfactors.bp + +implement { + name = "tobigpoints", + actions = function(d) context("%.5F",bp * d) end, + arguments = "dimension", +} + +implement { + name = "towholebigpoints", + actions = function(d) context("%r",bp * d) end, + arguments = "dimension", +} + +-- for now here: + +local function getshape(s) + local t = texget(s) + local n = t and #t or 0 + context(n) + if n > 0 then + for i=1,n do + local ti = t[i] + if type(ti) == "table" then + context(" %isp %isp",ti[1],ti[2]) + else + context(" %i",ti) + end + end + end +end + +implement { + name = "getparshape", + public = true, + actions = function() getshape("parshape") end, +} +implement { + name = "getclubpenalties", + public = true, + actions = function() getshape("clubpenalties") end, +} +implement { + name = "getinterlinepenalties", + public = true, + actions = function() getshape("interlinepenalties") end, + } +implement { + name = "getdisplaywidowpenalties", + public = true, + actions = function() getshape("displaywidowpenalties") end, +} +implement { + name = "getwidowpenalties", + public = true, + actions = function() getshape("widowpenalties") end, +} diff --git a/tex/context/base/mkxl/syst-aux.mkxl b/tex/context/base/mkxl/syst-aux.mkxl new file mode 100644 index 000000000..8fc9d6e02 --- /dev/null +++ b/tex/context/base/mkxl/syst-aux.mkxl @@ -0,0 +1,6704 @@ +%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 In the process of being adapted to \LMTX\ flags so a bit of a mess now. Also +%D our playground. + +\registerctxluafile{syst-aux}{autosuffix} +\registerctxluafile{syst-mac}{autosuffix} + +%D This file is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv} where +%D you can find some more pure \TEX\ or \LUATEX\ variants. There are quite some +%D helpers here and many no longer are used but we keep them around because they +%D have always been there. However, the implementation in \LMTX\ can be somewhat +%D different that in \MKIV, because it's also a kind of a playground for new +%D features. Of course nostalgia also plays a role. +%D +%D For the original code we refer to \type {syst-aux.mkii} and its follow up \type +%D {syst-aux.mkiv}. These also have historic versions. As usual, the upgrade went +%D through stages. First I wrote variants usign the new \type {\ignorearguments} +%D feature, then I decided to implement a few more conditionals and new fancy code +%D could be ditched before it was even published. I kept some as examples. +%D +%D Of course I couldn't do this without Wolfgang looking over my shoulder. Changing +%D core code is kind of tricky. + +\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 \protected\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. So, effectively we have two ways to +%D protect a macro. +%D +%D In \LMTX\ we try to avoid this and use \type {\protected} instead, which is +%D possible because over time we got rid of using the \CONTEXT\ macro with that +%D name. + +\pushoverloadmode + +\aliased\let\unexpanded\normalprotected + +\popoverloadmode + +%D We're definitely in \LMTX\ mode here. + +\aliased \let\startlmtxmode\relax +\aliased \let\stoplmtxmode \relax +\permanent\def\startmkivmode#-\stopmkivmode{} +\permanent\let\stopmkivmode \relax + +%D As we don't have namespace definers yet, we use a special one. Later we will +%D do a better job. + +\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 + +\permanent\protected\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 + \edefcsname ??#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 this one: + +\def\normalspace{ } + +\newif\if!!donea \newif\if!!doneb \newif\if!!donec % soon obsolete in lmtx +\newif\if!!doned \newif\if!!donee \newif\if!!donef % soon obsolete in lmtx + +\immutable\def\!!zerocount {0} % alongside \zerocount +\immutable\def\!!minusone {-1} % ... +\immutable\def\!!plusone {1} % ... +\immutable\def\!!plustwo {2} % ... +\immutable\def\!!plusthree {3} % ... +\immutable\def\!!plusfour {4} % ... +\immutable\def\!!plusfive {5} % ... +\immutable\def\!!plussix {6} % ... +\immutable\def\!!plusseven {7} % ... +\immutable\def\!!pluseight {8} % ... +\immutable\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. Of course, expanding them costs time, so +%D that's the price to pay. More are defined elsewhere. Of course we later pay a +%D price when they need to be expanded. + +% \def\v!prefix! {v!} +% \def\c!prefix! {c!} +% \def\s!prefix! {s!} +% +% \def\s!next {next} +% \def\s!default {default} +% \def\s!dummy {dummy} +% \def\s!unknown {unknown} +% +% \def\s!do {do} +% \def\s!dodo {dodo} +% +% \def\s!complex {complex} +% \def\s!simple {simple} +% +% \def\s!start{start} +% \def\s!stop {stop} + +% \immutable\def\s!empty {empty} + +%D Sometimes we pass macros as arguments to commands that don't expand them before +%D interpretation. Such commands can be enclosed with \type {\expanded}, like: +%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 + +\pushoverloadmode + +\permanent\protected\def\expanded#1% + {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded} + +\popoverloadmode + +\permanent\protected\def\startexpanded#1\stopexpanded + {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded} + +\aliased\let\stopexpanded\relax + +%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when +%D possible. After all, we can make not expandable macros now. The name clash is an +%D unfortunate fact and in retrospect I should nto have agreed to a primitive having +%D that same name. + +% 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. These zero references prevent intermediate storage. In principle that +%D is more efficient but it probably won't be noticed. It's anyway cheaper on memory +%D access. We use versions that don't even store the arguments. + +%permanent\def\gobbleoneargument #-{} +\permanent\def\gobbletwoarguments #-#-{} +\permanent\def\gobblethreearguments #-#-#-{} +\permanent\def\gobblefourarguments #-#-#-#-{} +\permanent\def\gobblefivearguments #-#-#-#-{} +\permanent\def\gobblesixarguments #-#-#-#-{} +\permanent\def\gobblesevenarguments #-#-#-#-#-{} +\permanent\def\gobbleeightarguments #-#-#-#-#-#-{} +\permanent\def\gobbleninearguments #-#-#-#-#-#-#-{} + +\permanent\tolerant\def\gobbleoneoptional [#-]{} +\permanent\tolerant\def\gobbletwooptionals [#-]#*[#-]{} +\permanent\tolerant\def\gobblethreeoptionals[#-]#*[#-]#*[#-]{} +\permanent\tolerant\def\gobblefouroptionals [#-]#*[#-]#*[#-]#*[#-]{} +\permanent\tolerant\def\gobblefiveoptionals [#-]#*[#-]#*[#-]#*[#-]#*[#-]{} + +%D Reserved macros for tests: + +\aliased\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 This macro has a long history. Among the things we had to deal with was ignoring +%D blank spaces but in the meantime we can use some \LUATEX\ trickery. Older versions +%D use more code and can be find in the \MKIV\ and \MKII\ files. + +% \mutable\let\next \relax +% \mutable\let\nextnext \relax % kind of obsolete +% \mutable\let\nextnextnext \relax % kind of obsolete +% \mutable\let\nexttoken \relax + +\permanent\protected\def\doifelsenextchar#1#2#3% #1 should not be {} ! + {\def\m_syst_action_yes{#2}% + \def\m_syst_action_nop{#3}% + \futureexpandis#1\m_syst_action_yes\m_syst_action_nop} + +\permanent\protected\def\doifelsenextcharcs % #1#2#3% #1 should not be {} ! + {\futureexpandis} + +\aliased\let\doifnextcharelse \doifelsenextchar +\aliased\let\doifnextcharcselse\doifelsenextcharcs + +%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. Here we use a lookahead primitive that ignores (blank) spaces +%D which makes for less tracing clutter than the original definition. It's also +%D faster bit that will probably go unnoticed. Of course, hard||core \TEX ies whose +%D reputations depends on understanding obscure macro definitions will love the more +%D low level variants. + +\permanent\protected\def\doifelsenextoptional#1#2% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% + \futureexpandis[\m_syst_action_yes\m_syst_action_nop} + +\permanent\protected\def\doifelsenextoptionalcs + {\futureexpandis[} + +\aliased\let\doifnextoptionalelse \doifelsenextoptional +\aliased\let\doifnextoptionalcselse\doifelsenextoptionalcs + +\permanent\protected\def\doifelsenextbgroup#1#2% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% + \futureexpandis\bgroup\m_syst_action_yes\m_syst_action_nop} + +\permanent\protected\def\doifelsenextbgroupcs % #1#2 + {\futureexpandis\bgroup} + +\aliased\let\doifnextbgroupelse \doifelsenextbgroup +\aliased\let\doifnextbgroupcselse\doifelsenextbgroupcs + +\permanent\protected\def\doifelsenextparenthesis#1#2% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% + \futureexpandis(\m_syst_action_yes\m_syst_action_nop} + +\aliased\let\doifnextparenthesiselse\doifelsenextparenthesis + +%D The next one is handy in predictable situations: + +\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} + +\permanent\protected\def\doifelsefastoptionalcheck#1#2% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% + \futureexpandis[\m_syst_action_yes\m_syst_action_nop} + +\permanent\protected\def\doifelsefastoptionalcheckcs + {\futureexpandis[} + +\aliased\let\doiffastoptionalcheckelse \doifelsefastoptionalcheck +\aliased\let\doiffastoptionalcheckcselse\doifelsefastoptionalcheckcs + +%D Here's one for skipping spaces and pars, handy for: +%D +%D \starttyping +%D \hbox +%D +%D {a few lines later} +%D \stoptyping +%D +%D like: +%D +%D \starttyping +%D \def\somecommand{\dowithnextbox{\box\nextbox}\ruledhbox} +%D +%D \assumelongusagecs\somecommand +%D +%D \bgroup +%D oeps +%D \egroup +%D \stoptyping +%D +%D The original kind of clumsy but working version is now replaced by a simple +%D macro. And it can be even less code in \LUAMETATEX: + +\aliased\let\assumelongusagecs\expandafterpars % so we can replace it + +%D It's used to skip over empty lines in some constructs that we like to set up +%D spacy. We already permit par tokens (and equivalents) in math and some other +%D places visa engine features. And, \type {\long} stuff has been dropped for a long +%D time already (it is still optional in \lUATEX). But the \quote {long} in the +%D name kind of stuck. + +%D \macros +%D {blankspace} +%D +%D Here is how this works. The \type {\let} primitive first picks up the to be let +%D name. Then it scans for an optional equal and when that is found it will skip the +%D next space, which is why we need an extra one to achieve our goal. Such a \type +%D {\blankspace} has the meaning \typ {blank space}. A typical \TEX ie definition: + +\normalexpanded{\permanent\let\noexpand\blankspace=\space\space} + +%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}=\... = \glet\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. + +\permanent\def\setvalue #1{\defcsname #1\endcsname} +\permanent\def\setgvalue #1{\gdefcsname#1\endcsname} +\permanent\def\setevalue #1{\edefcsname#1\endcsname} +\permanent\def\setxvalue #1{\xdefcsname#1\endcsname} +\permanent\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname +\permanent\def\letvalue #1{\letcsname #1\endcsname} +\permanent\def\letgvalue #1{\gletcsname#1\endcsname} +\permanent\def\resetvalue #1{\letcsname#1\endcsname\empty} +\permanent\def\undefinevalue#1{\letcsname#1\endcsname\undefined} +\permanent\def\ignorevalue#1#2{\letcsname#1\endcsname\empty} + +\permanent\def\setuvalue #1{\protected\defcsname #1\endcsname} +\permanent\def\setuevalue #1{\protected\edefcsname#1\endcsname} +\permanent\def\setugvalue #1{\protected\gdefcsname#1\endcsname} +\permanent\def\setuxvalue #1{\protected\xdefcsname#1\endcsname} + +\permanent\protected\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 tokens will +%D save us some $300\times4=1200$ bytes of format file on a 32~bit system. Not that +%D it matters much today. But nowadays we can just alias to a primitive: + +\aliased\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 +%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 +%D +%D Suppression of errors while constructing a control sequence is one of the (few) +%D things that I remember being discussed in the perspective of \ETEX\ but it was +%D rejected because it was not considered useful. Well, in \LUATEX\ we can surpress +%D it and that is what we do in \MKIV. We're probably the only macro package that +%D needs it. That kind of configuration happens elsewhere. These macros are (mostly +%D for historic reasons) fully expandable. + +\permanent\def\doifelseundefined#1% + {\ifcsname#1\endcsname + \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments + \fi} + +\permanent\def\doifelsedefined#1% + {\ifcsname#1\endcsname + \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments + \fi} + +\permanent\def\doifundefined#1% + {\ifcsname#1\endcsname + \expandafter\gobbleoneargument\else\expandafter\firstofoneargument + \fi} + +\permanent\def\doifdefined#1% + {\ifcsname#1\endcsname + \expandafter\firstofoneargument\else\expandafter\gobbleoneargument + \fi} + +\aliased\let\doifundefinedelse\doifelseundefined +\aliased\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: + +\permanent\protected\def\letbeundefined#1% + {\letcsname#1\endcsname\undefined} % or use \undefinevalue to match \setvalue + +\permanent\protected\def\localundefine#1% conditional + {\ifcsname#1\endcsname\letcsname#1\endcsname\undefined\fi} + +\permanent\protected\def\globalundefine#1% conditional + {\ifcsname#1\endcsname\gletcsname#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}. + +\permanent\protected\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} + +\aliased\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 +%D +%D Again, we use some of the new primitives in \LUAMETATEX. Using straightforward +%D \type {\edef}'s and \type {\ifx} comparison works as well, but this saves tokens +%D and, more important, tracing clutter. + +\permanent\protected\def\doifelse#1#2% + {\iftok{#1}{#2}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doif#1#2% + {\iftok{#1}{#2}% + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnot#1#2% + {\iftok{#1}{#2}% + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \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, but we use the dedicated empty checker +%D here. + +\permanent\protected\def\doifelseempty#1% + {\def\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifemptyelse\doifelseempty + +\permanent\protected\def\doifempty#1% + {\def\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotempty#1% + {\def\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \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} + +%D These are normally only used for keywords, i.e.\ strings so we can delegate +%D the work to \LUA: + +%protected\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}} +%protected\def\doifinset #1#2{\clf_doifinset {#1}{#2}} +%protected\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}} +% % \let\firstinset \clf_firstinset + +% These don't accept spaces after commas: +% +% \protected\def\doifelseinset#1#2% +% {\ifhasxtoks{,#1,}{,#2,}% +% \expandafter\firstoftwoarguments +% \else +% \expandafter\secondoftwoarguments +% \fi} + +% \protected\def\doifinset#1#2% +% {\ifhasxtoks{,#1,}{,#2,}% +% \expandafter\firstofoneargument +% \else +% \expandafter\gobbleoneargument +% \fi} + +% \protected\def\doifnotinset#1#2% +% {\ifhasxtoks{,#1,}{,#2,}% +% \expandafter\gobbleoneargument +% \else +% \expandafter\firstofoneargument +% \fi} + +% But these do: + +\immutable\edef\a!comma{\expandtoken \ignorecatcode \commaasciicode} +\immutable\edef\a!space{\expandtoken \ignorecatcode \spaceasciicode} + +\normalexpanded { + + \permanent \protected \def \noexpand \doifelseinset#1#2% + {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% + \noexpand\expandafter\noexpand\firstoftwoarguments + \noexpand\else + \noexpand\expandafter\noexpand\secondoftwoarguments + \noexpand\fi} + + \permanent \protected \def \noexpand \doifinset#1#2% + {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% + \noexpand\expandafter\noexpand\firstofoneargument + \noexpand\else + \noexpand\expandafter\noexpand\gobbleoneargument + \noexpand\fi} + + \permanent \protected \def \noexpand \doifnotinset#1#2% + {\noexpand\ifhasxtoks{,\a!space#1,}{,#2,}% + \noexpand\expandafter\noexpand\gobbleoneargument + \noexpand\else + \noexpand\expandafter\noexpand\firstofoneargument + \noexpand\fi} + +} + +%D Done. + +\aliased\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} + +\permanent\protected\def\doifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} % todo: define in lua +\permanent\protected\def\doifcommon #1#2{\clf_doifcommon {#1}{#2}} % todo: define in lua +\permanent\protected\def\doifnotcommon #1#2{\clf_doifnotcommon {#1}{#2}} % todo: define in lua + +\aliased\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 Or expanded: +%D +%D \blank \getbuffer \blank +%D +%D The original definitions can be found elsewhere and need a bit more code. In case of +%D issues, consult the \MKIV\ variant or previous \LMTX\ variants in the repository. +%D +%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 this macro has its +%D limits. We use a new \LUAMETATEX\ feature that intercepts invalid macro arguments +%D by quitting when \type {\ignorearguments} is seen. That's why we act on the +%D arguments state. Again it permits leaner and meaner macro definitions with a bit +%D less clutter in tracing. + +\mutable\let\commalistcommand\empty + +\protected\def\syst_helpers_process_comma_item#+,% + {\ifarguments + \expandafter\syst_helpers_process_comma_item_gobble + \orelse\ifparameter#1\or + \commalistcommand{#1}% + \expandafter\syst_helpers_process_comma_item_next + \else + \expandafter\syst_helpers_process_comma_item_gobble + \fi} + +% \def\syst_helpers_process_comma_item_next +% {\expandafterspaces\syst_helpers_process_comma_item} + +% \protected\def\processcommalist[#1]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +% \protected\def\processcommacommand[#1]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +% \permanent\protected\def\processcommalist[#*#+]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} +% +% \permanent\protected\def\processcommacommand[#*#+]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +\tolerant\protected\def\syst_helpers_process_comma_item#*#1,% + {\ifarguments\or + \commalistcommand{#1}% + \expandafter\syst_helpers_process_comma_item_next + \fi} + +\def\syst_helpers_process_comma_item_next + {\expandafterspaces\syst_helpers_process_comma_item} + +\permanent\protected\def\processcommalist[#1]#2% + {\pushmacro\commalistcommand + \def\commalistcommand{#2}% + \syst_helpers_process_comma_item#1\ignorearguments\ignorearguments\ignorearguments + \popmacro\commalistcommand} + +\permanent\protected\def\processcommacommand[#1]#2% + {\pushmacro\commalistcommand + \def\commalistcommand{#2}% + \normalexpanded{\syst_helpers_process_comma_item#1}\ignorearguments\ignorearguments\ignorearguments + \popmacro\commalistcommand} + +% \let\syst_helpers_process_comma_item_next_a \syst_helpers_process_comma_item_next +% \def\syst_helpers_process_comma_item_next_b#0\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_a} +% \def\syst_helpers_process_comma_item_next_c#0\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} +% \def\syst_helpers_process_comma_item_gobble#0\ignorearguments{} + +\let\syst_helpers_process_comma_item_next_a \syst_helpers_process_comma_item_next +\def\syst_helpers_process_comma_item_next_b#-\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_a} +\def\syst_helpers_process_comma_item_next_c#-\ignorearguments{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} +\def\syst_helpers_process_comma_item_gobble#-\ignorearguments{} + +\permanent\protected\def\quitcommalist {\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_b} +\permanent\protected\def\quitprevcommalist{\let\syst_helpers_process_comma_item_next\syst_helpers_process_comma_item_next_c} + +%D \startbuffer +%D \def\foo#1{(#1)} +%D <\processcommalist[a,b,c,d]\foo> +%D +%D \def\foo#1{(#1)} +%D \def\oof#1{<\processcommalist[#1]\foo>} +%D <\processcommalist[{a,b},{c,d}]\oof> +%D +%D \def\foo#1{(#1)\quitcommalist} +%D <\processcommalist[a,b,c,d]\foo> +%D +%D \def\foo#1{(#1)} +%D \def\oof#1{<\processcommalist[#1]\foo\quitcommalist>} +%D <\processcommalist[{a,b},{c,d}]\oof> +%D +%D \def\foo#1{(#1)\quitcommalist} +%D \def\oof#1{<\processcommalist[#1]\foo>} +%D <\processcommalist[{a,b},{c,d},{e,f}]\oof> +%D +%D \def\foo#1{(#1)\quitprevcommalist} +%D \def\oof#1{<\processcommalist[#1]\foo>} +%D <\processcommalist[{a,b},{c,d},{e,f}]\oof> +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank + +%D The argument to \type{\command} is not delimited. Because we often use \type {[]} +%D 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 + +\permanent\protected\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 + +\mutable\let\currentcommalistitem\empty + +\permanent\protected\def\startprocesscommalist[#1]#2\stopprocesscommalist + {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% + \processcommalist[#1]\syst_helpers_comma_list_step} + +\permanent\protected\def\startprocesscommacommand[#1]#2\stopprocesscommacommand + {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% + \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step} + +\aliased\let\stopprocesscommalist \relax +\aliased\let\stopprocesscommacommand\relax + +%D \macros +%D {processaction, +%D processfirstactioninset, +%D processallactionsinset} +%D +%D \CONTEXT\ makes extensive use of a sort of case or switch command. Depending of +%D the presence of one or more provided items, some actions is taken. These macros +%D can be nested without problems. +%D +%D \starttyping +%D \processaction [x] [x=>a,y=>b,z=>c] +%D \processfirstactioninset [x,y,z] [x=>a,y=>b,z=>c] +%D \processallactionsinset [x,y,z] [x=>a,y=>b,z=>c] +%D \stoptyping +%D +%D We can supply both a \type {default} action and an action to be undertaken when +%D 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 the keyword \type +%D {default} and executed the related action if present. When \type {#1} is non +%D empty and not in the list, the action related to \type {unknown} is executed. +%D Both keywords must be at the end of list \type{#2}. Afterwards, the actually +%D found keyword is available in \type {\commalistelement}. An advanced example of +%D the use of this macro can be found in \PPCHTEX, where we completely rely on \TEX\ +%D for interpreting user supplied keywords like \type {SB}, \type {SB1..6}, \type +%D {SB125} etc. +%D +%D In the meantime we follow a different approach, often somewhat more heavy on the +%D number of control sequences used, but that is no lomger a real issue. The code +%D has been simplified and nwo uses the macro stack mechanism. If needed I can make +%D this more hip and a bit faster now but \unknown\ it's seldom used nowadays as we +%D have better ways now. + +\mutable\let\commalistelement\empty + +\protected\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} + +\protected\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 + \orelse\ifx\m_syst_string_two\s!unknown + \def\commalistelement{#3}% beware of loops + #2% + \fi} + +\permanent\protected\def\processaction[#1]#2[% + {\edef\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \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\syst_helpers_do_process_action[} + +\protected\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} + +\permanent\protected\def\processfirstactioninset[#1]% + {\edef\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \expandafter\processaction + \else + \expandafter\syst_helpers_process_first_action_in_set_indeed + \fi + [#1]} + +\tolerant\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#*[#2]% + {\def\syst_helpers_do_process_action##1% + {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}% + \processcommalist[#2]\syst_helpers_do_do_process_action}% + \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action} + +\protected\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]% + {\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} + +\tolerant\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#*[#2]% + {\globalpushmacro\syst_process_action_in_set_all + \def\syst_process_action_in_set##1% + {\def\syst_process_action_in_set_one####1{\syst_helpers_do_compare_process_action_d[####1][##1]}% + \processcommalist[#2]\syst_process_action_in_set_one}% + \processcommacommand[#1]\syst_process_action_in_set + \globalpopmacro\syst_process_action_in_set_all} + +\permanent\protected\def\processallactionsinset[#1]% + {\edef\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \expandafter\processaction + \else + \expandafter\syst_helpers_process_all_actions_in_set_indeed + \fi[#1]} + +%D These macros use: + +% \protected\def\processnextcommalist#1[#2#3]% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#1}% +% \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +\permanent\protected\def\processnextcommalist#1[#2#3]% + {\pushmacro\commalistcommand + \def\commalistcommand{#1}% + \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments + \popmacro\commalistcommand} + +%D \macros +%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter} +%D +%D Sometimes the action to be undertaken depends on the next character. This macro +%D get this character and puts it in \type {\firstcharacter}. +%D +%D \starttyping +%D \getfirstcharacter {string} +%D \stoptyping +%D +%D A two step expansion is used to prevent problems with complicated arguments, for +%D instance arguments that consist of two or more expandable tokens. + +\mutable\let\firstcharacter \empty +\mutable\let\remainingcharacters\empty + +\permanent\protected\def\getfirstcharacter #1{\clf_getfirstcharacter{#1}} +\permanent\protected\def\doifelsefirstchar #1#2{\clf_doifelsefirstchar{#1}{#2}} +\permanent\protected\def\thefirstcharacter #1{\clf_thefirstcharacter{#1}} +\permanent\protected\def\theremainingcharacters#1{\clf_theremainingcharacters{#1}} + +\aliased\let\doiffirstcharelse\doifelsefirstchar + +%D \macros +%D {doifinstringelse, doifincsnameelse} +%D +%D We can check for the presence of a substring in a given sequence of characters. +%D +%D \starttyping +%D \doifinstringelse {substring} {string} {then ...} {else ...} +%D \stoptyping +%D +%D \startbuffer +%D \doifinstringelse{abc}{foo bar abc}{Y}{N}=Y\par +%D \doifinstringelse{abc}{foo bar cab}{Y}{N}=N\par +%D \doifinstring {abc}{foo bar abc}{Y}=Y\par +%D \doifinstring {abc}{foo bar cab}{Y}\par +%D \doifnotinstring {abc}{foo bar abc}{Y}\par +%D \doifnotinstring {abc}{foo bar cab}{Y}=Y\par +%D \doifinstringelse{}{foo bar abc}{Y}{N}=N\par +%D \doifinstring {}{foo bar abc}{N}\par +%D \doifnotinstring {}{foo bar abc}{Y}=Y\par +%D \doifinstringelse{x}{}{Y}{N}=N\par +%D \doifinstring {x}{}{N}\par +%D \doifnotinstring {x}{}{Y}=Y\par +%D \doifinstringelse{}{}{Y}{N}=N\par +%D \doifinstring {}{}{N}\par +%D \doifnotinstring {}{}{Y}=Y\par +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank + +%D I keep the following as example code: + +% \let\syst_helpers_do_do_if_in_string_else\relax +% \let\syst_helpers_do_do_if_in_string \relax +% \let\syst_helpers_do_do_if_not_in_string \relax +% +% \let\m_syst_sub_string \empty +% +% \protected\def\doifelseinstring#1% +% {\edef\m_syst_sub_string{#1}% expand #1 here +% \ifempty\m_syst_sub_string +% \expandafter\thirdofthreearguments +% \else +% \expandafter\syst_helpers_do_if_in_string_else +% \fi} +% +% \let\doifinstringelse\doifelseinstring +% +% \protected\def\syst_helpers_do_if_in_string_else#1% ##2 can be {abc} +% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string_else##1\m_syst_sub_string##2}% +% {\ifarguments +% \or +% \expandafter\syst_helpers_do_if_in_string_else_nop +% \or +% \expandafter\syst_helpers_do_if_in_string_else_yes +% \fi}% +% \normalexpanded{\syst_helpers_do_do_if_in_string_else#1}\e_o_t\ignorearguments\ignorearguments} +% +% \protected\def\syst_helpers_do_if_in_string_else_delimited#1% ##2 can be {abc} +% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string_else##1,\m_syst_sub_string,##2}% +% {\ifarguments +% \or +% \expandafter\syst_helpers_do_if_in_string_else_nop +% \or +% \expandafter\syst_helpers_do_if_in_string_else_yes +% \fi}% +% \normalexpanded{\syst_helpers_do_do_if_in_string_else,#1,}\e_o_t\ignorearguments\ignorearguments} +% +% \protected\def\doifinstring#1% +% {\edef\m_syst_sub_string{#1}% expand #1 here +% \ifempty\m_syst_sub_string +% \expandafter\gobbletwoarguments +% \else +% \expandafter\syst_helpers_do_if_in_string +% \fi} +% +% \protected\def\syst_helpers_do_if_in_string#1% ##2 can be {abc} +% {\normalexpanded{\protected\def\syst_helpers_do_do_if_in_string##1\m_syst_sub_string##2}% +% {\ifarguments +% \or +% \expandafter\syst_helpers_do_if_in_string_nop +% \or +% \expandafter\syst_helpers_do_if_in_string_yes +% \fi}% +% \normalexpanded{\syst_helpers_do_do_if_in_string#1}\e_o_t\ignorearguments\ignorearguments} +% +% \protected\def\doifnotinstring#1% +% {\edef\m_syst_sub_string{#1}% expand #1 here +% \ifempty\m_syst_sub_string +% \expandafter\secondoftwoarguments +% \else +% \expandafter\syst_helpers_do_if_not_in_string +% \fi} +% +% \protected\def\syst_helpers_do_if_not_in_string#1% ##2 can be {abc} +% {\normalexpanded{\protected\def\syst_helpers_do_do_if_not_in_string##1\m_syst_sub_string##2}% +% {\ifarguments +% \or +% \expandafter\syst_helpers_do_if_not_in_string_nop +% \or +% \expandafter\syst_helpers_do_if_not_in_string_yes +% \fi}% +% \normalexpanded{\syst_helpers_do_do_if_not_in_string#1}\e_o_t\ignorearguments\ignorearguments} +% +% \def\syst_helpers_do_if_in_string_else_yes#0\ignorearguments\ignorearguments#2#0{#2} +% \def\syst_helpers_do_if_in_string_else_nop#0\ignorearguments#0#3{#3} +% \def\syst_helpers_do_if_in_string_yes #0\ignorearguments\ignorearguments#2{#2} +% \def\syst_helpers_do_if_in_string_nop #0\ignorearguments#0{} +% \def\syst_helpers_do_if_not_in_string_yes #0\ignorearguments\ignorearguments#0{} +% \def\syst_helpers_do_if_not_in_string_nop #0\ignorearguments#2{#2} + +\permanent\protected\def\doifelseinstring#1#2% + {\ifhasxtoks{#1}{#2}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifinstring#1#2% + {\ifhasxtoks{#1}{#2}% + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotinstring#1#2% + {\ifhasxtoks{#1}{#2}% + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\aliased\let\doifinstringelse\doifelseinstring + +%D The next one one of those variants that we used when speed was more of an issue +%D that today. Now we just expand the lot. We just use an alias now: + +\aliased\let\doifelseincsname\doifelseinstring +\aliased\let\doifincsnameelse\doifinstringelse + +%D \macros +%D {doifnumberelse,doifnumber,doifnotnumber} +%D +%D The next macro executes a command depending of the outcome of a test on numerals. +%D We now use a \LUATEX\ feature that permits a more robust checking, but you might +%D want to take a look at the originals. It's typically one of these new features +%D that probably only \CONTEXT\ will use, which is probably true for more such +%D features that no one ever asked for (but they are pretty generic in nature +%D anyway). + +\permanent\def\doifelsenumber#1% + {\ifchknum#1\or + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\def\doifnumber#1% + {\ifchknum#1\or + \expandafter\firstoftwoarguments + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\def\doifnotnumber#1% + {\ifchknum#1\or + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\aliased\let\doifnumberelse\doifelsenumber + +%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 + +% todo: use the push back dimen trickery + +\permanent\def\percentdimen#1#2% dimen percentage (with %) + {\dimexpr\clf_percentageof{#2}\dimexpr#1\relax} + +\permanent\protected\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 slow. When one is +%D desperately in need of faster alternatives and when the conditions are +%D predictable safe, the \type {\raw} alternatives come into focus. A major drawback +%D is that they do not take \type {\c!constants} into account, simply because no +%D expansion is done. This is no problem with \type {\rawprocesscommalist}, because +%D this macro does not 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, spoil the search process. +%D The gain in speed depends on the length of the argument (the longer the argument, +%D the less we gain). The question is: do we still need these raw variants? + +\permanent\protected\def\makerawcommalist[#1]#2% use \processnext ... here + {\scratchtoks\emptytoks + \def\syst_helpers_do_make_raw_comma_list##1{\iftok\scratchtoks\emptytoks\scratchtoks{##1}\else\toksapp\scratchtoks{,##1}\fi}% + \processcommalist[#1]\syst_helpers_do_make_raw_comma_list + \edef#2{\the\scratchtoks}} + +% beware: in mkiv { } were lost so it was not compatible with the non raw + +\aliased\let\rawprocesscommalist \processcommalist % can go +\aliased\let\rawprocesscommacommand\processcommacommand % can go + +%D Here is one without nesting .. still needed? + +\protected\def\syst_helpers_process_fast_comma_item#1,% + {\ifarguments + \expandafter\syst_helpers_process_comma_item_gobble + \or + \fastcommalistcommand{#1}% + \expandafter\syst_helpers_process_fast_comma_item_next + \fi} + +\protected\def\syst_helpers_process_fast_comma_item_next + {\expandafterspaces\syst_helpers_process_fast_comma_item} + +\permanent\protected\def\fastprocesscommalist[#1]#2% + {\let\fastcommalistcommand#2% + \expandafterspaces\syst_helpers_process_fast_comma_item#1\ignorearguments\ignorearguments\ignorearguments} + +\permanent\protected\def\fastprocesscommacommand[#1]#2% + {\let\fastcommalistcommand#2% + \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_fast_comma_item#1}\ignorearguments\ignorearguments\ignorearguments} + +% \def\rawdoifelseinset#1#2{\doifinstringelse{,#1,}{,#2,}} +% \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}} + +\def\syst_helpers_do_if_else_in_set#1% + {\ifhasxtoks{,\m_syst_sub_string,}{,#1,}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\rawdoifelseinset#1% + {\edef\m_syst_sub_string{#1}% expand #1 here + \ifempty\m_syst_sub_string + \expandafter\thirdofthreearguments + \else + \expandafter\syst_helpers_do_if_else_in_set + \fi} + +\aliased\let\rawdoifinsetelse\rawdoifelseinset + +\def\syst_helpers_do_if_in_set#1% + {\ifhasxtoks{,\m_syst_sub_string,}{,#1,}% + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\rawdoifinset#1% or just alias this one + {\edef\m_syst_sub_string{#1}% expand #1 here + \ifx\m_syst_sub_string\m_syst_two_commas + \expandafter\gobbletwoarguments + \else + \expandafter\syst_helpers_do_if_in_set + \fi} + +%D Some more raw material: + +\def\syst_helpers_raw_process_action#1=>#2,% + {\ifarguments + %\expandafter\syst_helpers_raw_process_action_gobble + \or + \expandafter\syst_helpers_raw_process_action_gobble + \or + \edef\m_syst_string_two{#1}% + \ifx\m_syst_string_one\m_syst_string_two + \def\m_syst_helpers_process_action{#2}% + \expandafter\expandafter\expandafter\syst_helpers_raw_process_action_gobble + \else + \ifx\s!unknown\m_syst_string_two + \def\m_syst_helpers_process_action_unknown{#2}% + \fi + \expandafter\expandafter\expandafter\syst_helpers_raw_process_action_next + \fi + \fi} + +\def\syst_helpers_raw_process_action_gobble#-\ignorearguments + {} + +\def\syst_helpers_raw_process_action_next + {\expandafterspaces\syst_helpers_raw_process_action} + +\protected\def\xrawprocessaction[#1]#2[#3]% + {\edef\m_syst_string_one{#1}% + \ifempty\m_syst_string_one + \let\m_syst_string_one\s!default + \fi + \let\m_syst_helpers_process_action\relax + \let\m_syst_helpers_process_action_unknown\relax + \syst_helpers_raw_process_action#3\ignorearguments\ignorearguments\ignorearguments + \ifx\m_syst_helpers_process_action\relax + \m_syst_helpers_process_action_unknown + \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 \type +%D {\let} and \type {\expandafter} in the test. +%D +%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{\defcsname #1#2\endcsname} % takes #3 +\def\dosetevalue #1#2{\edefcsname #1#2\endcsname} % takes #3 +\def\dosetgvalue #1#2{\global\edefcsname#1#2\endcsname} % takes #3 +\def\doresetvalue #1#2{\letcsname #1#2\endcsname\empty} +\def\doignorevalue#1#2#3{\letcsname #1#2\endcsname\empty} +\def\docopyvalue #1#2#3{\defcsname #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. + +\protected\def\showassignerror#1#2% + {\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}} + +\permanent\protected\def\doassignempty[#1][#2=#3]% kind of obsolete + {\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 + +\permanent\protected\def\getparameters {\dogetparameters\dosetvalue} +\permanent\protected\def\geteparameters {\dogetparameters\dosetevalue} +\permanent\protected\def\getgparameters {\dogetparameters\dosetgvalue} +\permanent\protected\def\getxparameters {\dogetparameters\dosetxvalue} +\permanent\protected\def\forgetparameters{\dogetparameters\doignorevalue} + +\aliased\let\getexpandedparameters\geteparameters + +\def\syst_helpers_grab_parameter_error#1% + {\showassignerror{#1}{\the\inputlineno\space(\m_syst_parameter_n)}} + +\def\syst_helpers_grab_parameter#1,% + {\ifarguments + % done + \else + \syst_helpers_grab_parameter_okay#1,\ignorearguments + \expandafter\syst_helpers_grab_parameter_next + \fi} + +\def\syst_helpers_grab_parameter_okay#1=#2,% + {\ifarguments + \or + \syst_helpers_grab_parameter_error{#1}% + \or + \m_syst_parameter_s\m_syst_parameter_n{#1}{#2}% + \fi} + +\def\syst_helpers_grab_parameter_next + {\expandafterspaces\syst_helpers_grab_parameter} + +\permanent\protected\def\dogetparameters#1[#2]#*[#3]% + {\def\m_syst_parameter_n{#2}% + \let\m_syst_parameter_s#1% + \expandafterspaces\syst_helpers_grab_parameter#3\ignorearguments\ignorearguments} + +%D \macros +%D {getemptyparameters} +%D +%D Sometimes we explicitly want variables to default to an empty string, so we +%D welcome: +%D +%D \starttyping +%D \getemptyparameters [label] [...=...,...=...] +%D \stoptyping + +\permanent\protected\def\getemptyparameters[#1]#*[#2]% + {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}% + \processcommalist[#2]\syst_helpers_get_empty_parameters} + +%D We now just alias these as there is no need for a speedup. These have not been used +%D for a long time in core code. + +\aliased\let\doassign \getparameters % obsolete, these will go +\aliased\let\doeassign \geteparameters % obsolete, these will go +\aliased\let\undoassign\forgetparameters % obsolete, these will go + +%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 worth the +%D trouble and tokens. + +\mutable\let\currentassignmentlistcommand\gobbletwoarguments +\mutable\let\currentassignmentlistkey \empty +\mutable\let\currentassignmentlistvalue \empty + +\permanent\protected\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]} + +\permanent\protected\def\processassignmentcommand[#1]% + {\normalexpanded{\processassignmentlist[#1]}} + +\permanent\protected\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist + {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}% + \processassignmentlist[#1]\currentassignmentlistcommand} + +\aliased\let\stopprocessassignmentlist\relax + +\permanent\protected\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand + {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}% + \normalexpanded{\processassignmentlist[#1]}\currentassignmentlistcommand} + +\aliased\let\stopprocessassignmentcommand\relax + +%D \macros +%D {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 {copyparameters} +%D +%D Some \CONTEXT\ commands take their default setups from others. All commands that +%D are able to provide backgounds or rules around some content, for instance default +%D to the standard command for ruled boxes. Is situations like this 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 for use in a +%D multi||lingual environment. + +\permanent\protected\def\copyparameters[#1]#*[#2]#*[#3]% + {\doifnot{#1}{#2} + {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#2}}% ##1 + \processcommalist[#3]\syst_helpers_copy_parameter}} + +% %D \macros +% %D {ifparameters,checkparameters} +% %D +% %D A slightly different one is \type {\checkparameters}, which also checks on the +% %D presence of a~\type {=}. +% %D +% %D The boolean \type {\ifparameters} can be used afterwards. Combining both in one +% %D \type {\if}||macro would lead to problems with nested \type {\if}'s. +% %D +% %D \starttyping +% %D \checkparameters[argument] +% %D \stoptyping +% +% \newif\ifparameters +% +% \protected\def\checkparameters[#1]% +% {\ifhastok={#1}\parameterstrue\else\parametersfalse\fi} + +%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 + +\mutable\def\commalistsize{0} + +\def\syst_helpers_get_comma_list_size#0,% no #- as we need to count + {\ifarguments\or + \advance\commalistcounter\plusone + \expandafter\syst_helpers_get_comma_list_size + \fi} + +\permanent\protected\def\getcommalistsize[% + {\futureexpand]\syst_helpers_get_comma_list_size_nop\syst_helpers_get_comma_list_size_yes} + +\def\syst_helpers_get_comma_list_size_yes#+]% + {\commalistcounter\zerocount + \syst_helpers_get_comma_list_size #1,\ignorearguments\ignorearguments + \edef\commalistsize{\the\commalistcounter}} + +\def\syst_helpers_get_comma_list_size_nop]% + {\commalistcounter\zerocount + \let\commalistsize\!!zerocount} + +\permanent\protected\def\getcommacommandsize[#1]% + {\normalexpanded{\getcommalistsize[#1]}} + +%D Filters: + +% \def\syst_helpers_gobble_comma_list#0\ignorearguments{} + +\def\syst_helpers_gobble_comma_list#-\ignorearguments{} + +\def\syst_helpers_get_from_comma_list#1,% + {\ifarguments \or + \advance\commalistcounter \minusone + \ifcase\commalistcounter + \def\commalistelement{#1}% + \expandafter\expandafter\expandafter\syst_helpers_gobble_comma_list + \else + \expandafter\expandafter\expandafter\syst_helpers_get_from_comma_list_next + \fi + \fi} + +\def\syst_helpers_get_from_comma_list_next + {\expandafterspaces\syst_helpers_get_from_comma_list} + +\permanent\protected\def\getfromcommalist[#1]#*[#2]% + {\let\commalistelement\empty + \commalistcounter#2\relax + \expandafterspaces\syst_helpers_get_from_comma_list#1\ignorearguments\ignorearguments} + +\permanent\protected\def\getfromcommacommand[#1]% + {\normalexpanded{\getfromcommalist[#1]}} + +%D Watertight (and efficient) solutions are hard to find, due to the handling of +%D braces during parameters passing and 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 alternative, which can +%D handle 9~elements at most. +%D +%D \starttyping +%D \dogetcommalistelement1\from a,b,c\to\commalistelement +%D \stoptyping + +\def\syst_helpers_get_comma_list_element#1,#2,#3,#4,#5,#6,#7,#8,#9,% + {\ifcase\scratchcounter\or#1\or#2\or#3\or#4\or#5\or#6\or#7\or#8\or#9\fi + \syst_helpers_gobble_comma_list} + +\permanent\protected\def\dogetcommacommandelement#1\from#2\to#3% + {\scratchcounter#1\relax + \edef#3{\normalexpanded{\syst_helpers_get_comma_list_element#2\ignorearguments\ignorearguments}}} + +%D \macros +%D {dosingleargument,dodoubleargument,dotripleargument, +%D doquadrupleargument,doquintupleargument,dosixtupleargument, +%D doseventupleargument} +%D +%D When working with delimited arguments, spaces and lineendings can interfere. The +%D next set of macros uses \TEX' internal scanner for grabbing everything between +%D arguments. Forgive me the funny names. +%D +%D \starttyping +%D \dosingleargument \command = \command[#1] +%D \dodoubleargument \command = \command[#1][#2] +%D \dotripleargument \command = \command[#1][#2][#3] +%D \doquadrupleargument \command = \command[#1][#2][#3][#4] +%D \doquintupleargument \command = \command[#1][#2][#3][#4][#5] +%D \dosixtupleargument \command = \command[#1][#2][#3][#4][#5][#6] +%D \doseventupleargument\command = \command[#1][#2][#3][#4][#5][#6][#7] +%D \stoptyping +%D +%D These macros can be used in the following way: +%D +%D \starttyping +%D \def\dosetupsomething[#1][#2]% +%D {... #1 ... #2 ...} +%D +%D \protected\def\setupsomething +%D {\dodoubleargument\dosetupsomething} +%D \stoptyping +%D +%D The implementation can be surprisingly simple and needs no further explanation, +%D 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 two||step solution when +%D getting five or more arguments. +%D +%D When developing more and more of the real \CONTEXT, we started using some +%D alternatives that provided empty arguments (in fact optional ones) whenever the +%D user failed to supply them. Because this more complicated macros enable us to do +%D some checking, we reimplemented the non||empty ones. + +%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 wanted arguments are +%D indeed supplied by the user. + +\newcount\nofarguments + +\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 use the \type +%D {\if...argument} boolean. For novice: watch the stepwise doubling of \type {#}'s. + +%D NB : experimental versions in cont-exp.mkiv + +%D Common: + +\newtoks\t_syst_aux + +% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux} +% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux} +% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux} +% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux} +% +% %D Single: +% +% \protected\def\dosingleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop} +% +% \def\syst_helpers_single_empty_one_nop +% {\firstargumentfalse +% \the\t_syst_aux[]} +% +% %D Double +% +% \protected\def\dodoubleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop} +% +% % \def\syst_helpers_double_empty_one_yes[#1]% +% % {\firstargumenttrue +% % \toksapp\t_syst_aux{[{#1}]}% +% % \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} +% % +% % nicer is: +% +% \def\syst_helpers_double_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} +% +% \def\syst_helpers_double_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_double_empty_two_nop +% {\secondargumentfalse +% \the\t_syst_aux[]} +% +% % Triple +% +% \protected\def\dotripleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop} +% +% \def\syst_helpers_triple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop} +% +% \def\syst_helpers_triple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop} +% +% \def\syst_helpers_triple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_triple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_triple_empty_three_nop +% {\thirdargumentfalse +% \the\t_syst_aux[]} +% +% %D Quadruple: +% +% \protected\def\doquadrupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop} +% +% \def\syst_helpers_quadruple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop} +% +% \def\syst_helpers_quadruple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop} +% +% \def\syst_helpers_quadruple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop} +% +% \def\syst_helpers_quadruple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_quadruple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_quadruple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_quadruple_empty_four_nop +% {\fourthargumentfalse +% \the\t_syst_aux[]} +% +% %D Quintuple: +% +% \protected\def\doquintupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop} +% +% \def\syst_helpers_quintuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop} +% +% \def\syst_helpers_quintuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop} +% +% \def\syst_helpers_quintuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop} +% +% \def\syst_helpers_quintuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop} +% +% \def\syst_helpers_quintuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_quintuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_quintuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_quintuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_quintuple_empty_five_nop +% {\fifthargumentfalse +% \the\t_syst_aux[]} +% +% %D Sixtuple: +% +% \protected\def\dosixtupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop} +% +% \def\syst_helpers_sixtuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop} +% +% \def\syst_helpers_sixtuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop} +% +% \def\syst_helpers_sixtuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop} +% +% \def\syst_helpers_sixtuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop} +% +% \def\syst_helpers_sixtuple_empty_five_yes[#+]% +% {\fifthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop} +% +% \def\syst_helpers_sixtuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][][][]} +% +% \def\syst_helpers_sixtuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_sixtuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_sixtuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_sixtuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_sixtuple_empty_six_nop +% {\sixthargumentfalse +% \the\t_syst_aux[]} +% +% %D Seventuple: +% +% \protected\def\doseventupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop} +% +% \def\syst_helpers_seventuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop} +% +% \def\syst_helpers_seventuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop} +% +% \def\syst_helpers_seventuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop} +% +% \def\syst_helpers_seventuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop} +% +% \def\syst_helpers_seventuple_empty_five_yes[#+]% +% {\fifthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop} +% +% \def\syst_helpers_seventuple_empty_six_yes[#+]% +% {\sixthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop} +% +% \def\syst_helpers_seventuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][][][]} +% +% \def\syst_helpers_seventuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][][]} +% +% \def\syst_helpers_seventuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_seventuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_seventuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_seventuple_empty_six_nop +% {\sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_seventuple_empty_seven_nop +% {\seventhargumentfalse +% \the\t_syst_aux[]} + +%tolerant\def\syst_single_empty#1\relax[#+]% +\tolerant\def\syst_single_empty#1\relax[#2]% + {\ifarguments + \or\firstargumentfalse + \or\firstargumenttrue + \fi + #1[#2]} + +%tolerant\def\syst_double_empty#1\relax[#2]#*[#3]% +\tolerant\def\syst_double_empty#1\relax[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse + \or\firstargumenttrue \secondargumentfalse + \or\firstargumenttrue \secondargumenttrue + \fi + #1[#2][#3]} + +%tolerant\def\syst_triple_empty#1\relax[#2]#*[#3]#*[#4]% +\tolerant\def\syst_triple_empty#1\relax[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue + \fi + #1[#2][#3][#4]} + +%tolerant\def\syst_quadruple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]% +\tolerant\def\syst_quadruple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue + \fi + #1[#2][#3][#4][#5]} + +%\tolerant\def\syst_quintuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]% +\tolerant\def\syst_quintuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue + \fi + #1[#2][#3][#4][#5][#6]} + +%tolerant\def\syst_sixtuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]% +\tolerant\def\syst_sixtuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue + \fi + #1[#2][#3][#4][#5][#6][#7]} + +%tolerant\def\syst_seventuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]#*[#8]% +\tolerant\def\syst_seventuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumenttrue + \fi + #1[#2][#3][#4][#5][#6][#7][#8]} + +\permanent\protected\def\dosingleempty #1{\syst_single_empty #1\relax} +\permanent\protected\def\dodoubleempty #1{\syst_double_empty #1\relax} +\permanent\protected\def\dotripleempty #1{\syst_triple_empty #1\relax} +\permanent\protected\def\doquadrupleempty #1{\syst_quadruple_empty #1\relax} +\permanent\protected\def\doquintupleempty #1{\syst_quintuple_empty #1\relax} +\permanent\protected\def\dosixtupleempty #1{\syst_sixtuple_empty #1\relax} +\permanent\protected\def\doseventupleempty#1{\syst_seventuple_empty#1\relax} + +%D Aliases: + +\aliased\let\dosingleargument \dosingleempty +\aliased\let\dodoubleargument \dodoubleempty +\aliased\let\dotripleargument \dotripleempty +\aliased\let\doquadrupleargument \doquadrupleempty +\aliased\let\doquintupleargument \doquintupleempty +\aliased\let\dosixtupleargument \dosixtupleempty +\aliased\let\doseventupleargument\doseventupleempty + +%D \macros +%D {strippedcsname} +%D +%D The next macro can be very useful when using \type{\csname} like in: +%D +%D \starttyping +%D \csname if\strippedcsname\something\endcsname +%D \stoptyping +%D +%D This expands to \type{\ifsomething}. + +\aliased\let\strippedcsname\csstring + +%D \macros +%D {complexorsimple,complexorsimpleempty} +%D +%D Setups can be optional. A command expecting a setup is prefixed by \type +%D {\complex}, a command without one gets the prefix \type {\simple}. Commands like +%D 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 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, but changed into more +%D versatile (more object oriented) ones using the \type {\get..argument} commands. + +\permanent\protected\def\complexorsimple#1% + {\doifelsenextoptional + {\firstargumenttrue \csname\s!complex\csstring#1\endcsname} + {\firstargumentfalse\csname\s!simple \csstring#1\endcsname}} + +\permanent\protected\def\complexorsimpleempty#1% + {\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 worthwile to offer two +%D more alternatives. Watch the build in protection. + +\protected\def\syst_helpers_complex_or_simple#1#2% + {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#2}} + +\protected\def\syst_helpers_complex_or_simple_empty#1% + {\doifelsenextoptional{\firstargumenttrue#1}{\firstargumentfalse#1[]}} + +\permanent\protected\def\definecomplexorsimple#1% + {\protected\edef#1{\syst_helpers_complex_or_simple + \expandafter\noexpand\csname\s!complex\csstring#1\endcsname + \expandafter\noexpand\csname\s!simple \csstring#1\endcsname}} + +\permanent\protected\def\definecomplexorsimpleempty#1% + {\protected\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 +%D We can add additional definitions later when we have defined \type {\appendtoks}. + +\newconditional\c_syst_helpers_permit_spaces_between_groups + +\permanent\protected\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups} +\permanent\protected\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 the lot in +%D pieces so that we have no nested \type {\nextarguments} potentially being an +%D \type {conditional} token. Okay, these macros are not called that often but it +%D saves crap when tracing. + +% \protected\def\dosinglegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop} +% +% \def\syst_helpers_single_group_empty_one_nop +% {\firstargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\dodoublegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop} +% +% % \def\syst_helpers_group_double_empty_one_yes#1% +% % {\firstargumenttrue +% % \toksapp\t_syst_aux{{#1}}% +% % \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} +% % +% % nicer is: +% +% \def\syst_helpers_group_double_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} +% +% \def\syst_helpers_group_double_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_double_empty_two_nop +% {\secondargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\dotriplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop} +% +% \def\syst_helpers_group_triple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop} +% +% \def\syst_helpers_group_triple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop} +% +% \def\syst_helpers_group_triple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_triple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_triple_empty_three_nop +% {\thirdargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\doquadruplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop} +% +% \def\syst_helpers_group_quadruple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop} +% +% \def\syst_helpers_group_quadruple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop} +% +% \def\syst_helpers_group_quadruple_empty_three_yes#+% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop} +% +% \def\syst_helpers_group_quadruple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}{}{}} +% +% \def\syst_helpers_group_quadruple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_quadruple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_quadruple_empty_four_nop +% {\fourthargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\doquintuplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop} +% +% \def\syst_helpers_group_quintuple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop} +% +% \def\syst_helpers_group_quintuple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop} +% +% \def\syst_helpers_group_quintuple_empty_three_yes#+% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop} +% +% \def\syst_helpers_group_quintuple_empty_four_yes#+% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop} +% +% \def\syst_helpers_group_quintuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_quintuple_empty_five_nop +% {\fifthargumentfalse +% \the\t_syst_aux{}} + +\tolerant\def\syst_single_group_empty#1\relax#_% + {\ifarguments + \or\firstargumentfalse + \or\firstargumenttrue + \fi + #1#2} + +\tolerant\def\syst_double_group_empty#1\relax#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse + \or\firstargumenttrue \secondargumentfalse + \or\firstargumenttrue \secondargumenttrue + \fi + #1#2#3} + +\tolerant\def\syst_triple_group_empty#1\relax#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue + \fi + #1#2#3#4} + +\tolerant\def\syst_quadruple_group_empty#1\relax#_#*#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue + \fi + #1#2#3#4#5} + +\tolerant\def\syst_quintuple_group_empty#1\relax#_#*#_#*#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue + \fi + #1#2#3#4#5#6} + +\permanent\protected\def\dosinglegroupempty #1{\syst_single_group_empty #1\relax} +\permanent\protected\def\dodoublegroupempty #1{\syst_double_group_empty #1\relax} +\permanent\protected\def\dotriplegroupempty #1{\syst_triple_group_empty #1\relax} +\permanent\protected\def\doquadruplegroupempty #1{\syst_quadruple_group_empty #1\relax} +\permanent\protected\def\doquintuplegroupempty #1{\syst_quintuple_group_empty #1\relax} + +%D These macros can explictly take care of spaces, which means that the next +%D definition and calls are valid: +%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 used to select +%D arguments. Their names explain their functionality. + +\permanent\def\firstofoneargument #1{#1} + +\permanent\def\firstoftwoarguments #1#-{#1} +\permanent\def\secondoftwoarguments #-#1{#1} + +\permanent\def\firstofthreearguments #1#-#-{#1} +\permanent\def\secondofthreearguments #-#1#-{#1} +\permanent\def\thirdofthreearguments #-#-#1{#1} + +\permanent\def\firstoffourarguments #1#-#-#-{#1} +\permanent\def\secondoffourarguments #-#1#-#-{#1} +\permanent\def\thirdoffourarguments #-#-#1#-{#1} +\permanent\def\fourthoffourarguments #-#-#-#1{#1} + +\permanent\def\firstoffivearguments #1#-#-#-#-{#1} +\permanent\def\secondoffivearguments #-#1#-#-#-{#1} +\permanent\def\thirdoffivearguments #-#-#1#-#-{#1} +\permanent\def\fourthoffivearguments #-#-#-#1#-{#1} +\permanent\def\fifthoffivearguments #-#-#-#-#1{#1} + +\permanent\def\firstofsixarguments #1#-#-#-#-#-{#1} +\permanent\def\secondofsixarguments#-#1#-#-#-#-{#1} +\permanent\def\thirdofsixarguments #-#-#1#-#-#-{#1} +\permanent\def\fourthofsixarguments#-#-#-#1#-#-{#1} +\permanent\def\fifthofsixarguments #-#-#-#-#1#-{#1} +\permanent\def\sixthofsixarguments #-#-#-#-#-#1{#1} + +\permanent\protected\def\firstofoneunexpanded #1{#1} + +\permanent\protected\def\firstoftwounexpanded #1#-{#1} +\permanent\protected\def\secondoftwounexpanded #-#1{#1} + +\permanent\protected\def\firstofthreeunexpanded #1#-#-{#1} +\permanent\protected\def\secondofthreeunexpanded#-#1#-{#1} +\permanent\protected\def\thirdofthreeunexpanded #-#-#1{#1} + +%D \macros +%D {globalletempty,letempty, +%D letvalueempty,letgvalueempty, +%D letvaluerelax,letgvaluerelax} +%D +%D Trivial: + +\permanent\protected\def\letempty #1{\let #1\empty} +\permanent\protected\def\globalletempty#1{\glet#1\empty} + +\permanent\protected\def\letvalueempty #1{\letcsname #1\endcsname\empty} +\permanent\protected\def\letgvalueempty#1{\gletcsname#1\endcsname\empty} +\permanent\protected\def\letvaluerelax #1{\letcsname #1\endcsname\relax} +\permanent\protected\def\letgvalurelax #1{\gletcsname#1\endcsname\relax} + +\permanent\protected\def\relaxvalueifundefined#1% + {\ifcsname#1\endcsname \else + \letcsname#1\endcsname\relax + \fi} + +%D \macros +%D {wait} +%D +%D The next macro hardly needs explanation. Because no nesting is to be expected, we +%D can reuse \type {\wait} within \type {\wait} itself. + +\protected\def\wait + {\begingroup + \read16 to \wait + \endgroup} + +%D \macros +%D {writestring,writeline, +%D writestatus,statuswidth,normalwritestatus} +%D +%D Maybe one didn't notice, but we've already introduced a macro for showing +%D messages. In the multi||lingual modules, we will also introduce a mechanism for +%D message passing. For 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 of the identification +%D string with the macro \type {\statuswidth}. + +\setnewconstant\statuswidth 15 +%setnewconstant\statuswrite 128 % \pluscxxviii + +\ifdefined\writestring \else + + \protected\def\writestring{\immediate\write\statuswrite} + \protected\def\writeline {\writestring{}} + +\fi + +\protected\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 / todo permanent at lua end + +%D \macros +%D {rawgetparameters} +%D +%D A raw and dirty alternative for \type {\getparameters}; no checking is done! + +\def\syst_helpers_grab_raw_parameter#1=#2,% + {\ifarguments\or\or + \defcsname\m_syst_parameter_n#1\endcsname{#2}% + \expandafter\syst_helpers_grab_raw_parameter_next + \fi} + +\def\syst_helpers_grab_raw_parameter_next + {\expandafterspaces\syst_helpers_grab_raw_parameter} + +\permanent\protected\def\rawgetparameters#1[#2]#*[#3]% + {\def\m_syst_parameter_n{#2}% + %\expandafterspaces\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} + \expandafter\expandafterspaces\expandafter\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} + +%D \macros +%D {doglobal, +%D redoglobal,dodoglobal,resetglobal} +%D +%D The two macros \type {\redoglobal} and \type{\dodoglobal} are used in this and +%D some other modules to enforce a user specified \type {\doglobal} action. The last +%D and often only global assignment in a macro is done with \type {\dodoglobal}, but +%D all preceding ones with \type {\redoglobal}. When using only alternatives, one +%D can reset this mechanism with \type {\resetglobal}. + +\permanent\protected\def\resetglobal + {\enforced\let\redoglobal\relax + \enforced\let\dodoglobal\relax} + +\resetglobal + +\permanent\protected\def\doglobal + {\ifx\redoglobal\relax + \enforced\let\redoglobal\global + \enforced\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 + {\enforced\let\redoglobal\syst_helpers_redo_global + \enforced\let\dodoglobal\syst_helpers_dodo_global} + +%D Whatever (will be overtoaded): + +\protected\def\define#1% + {\ifdefined#1% + \message{[\noexpand#1is already defined]}% + \protected\expandafter\def\expandafter\gobbleddefinition + \else + \protected\expandafter\def + \fi#1} + +\permanent\protected\def\redefine#1% + {\ifdefined#1% + \message{[\noexpand#1is redefined]}% + \fi + \protected\def#1} + +\permanent\protected\def\definemacro#1% + {\ifdefined#1% + \message{[\noexpand#1is already defined]}% + \protected\expandafter\def\expandafter\gobbleddefinition + \else + \protected\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] + +\bgroup \obeylines + +\permanent\protected\gdef\starttexdefinition% + {\bgroup% + \obeylines% + \syst_helpers_start_tex_definition} + +\gdef\syst_helpers_start_tex_definition#1 + {\catcode\endoflineasciicode\ignorecatcode% + \clf_texdefinition_one{#1}} + +\aliased\glet\stoptexdefinition\relax + +\permanent\gdef\dostarttexdefinition#1\stoptexdefinition% + {\egroup% + \clf_texdefinition_two{#1}} + +\egroup + +% \protected\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace + +\permanent\protected\def\texdefinition#1{\begincsname#1\endcsname} + +%D \macros +%D {newcounter, +%D increment,decrement} +%D +%D Unfortunately the number of \COUNTERS\ in \TEX\ is limited, but fortunately we +%D can store numbers in a macro. We can increment such pseudo \COUNTERS\ with \type +%D {\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 \type {\counter} is 20, 16, 17 +%D and~18. Of course there is 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 at~0. It is +%D nevertheless better to define a \COUNTER\ explicitly. One reason could be that +%D the \COUNTER\ can be part of a test with \type {\ifnum} and this conditional does +%D not accept undefined macro's. The \COUNTER\ in our example can for instance be +%D defined with: +%D +%D \starttyping +%D \newcounter\counter +%D \stoptyping +%D +%D The command \type {\newcounter} must not be confused with \type {\newcount}! Of +%D course this mechanism is much slower than using \TEX's \COUNTERS\ directly. In +%D practice \COUNTERS\ (and therefore our pseudo counters too) are seldom the +%D bottleneck in the processing of a text. Apart from some other incompatilities we +%D want to mention a pitfal 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 second number after +%D reading \type {\pseudocounter}, while in the second test, it stops reading after +%D having encountered a real one. Tests like the first one therefore can give +%D unexpected results, for instance execution of \type {\doif} even if both numbers +%D are unequal. + +\def\zerocountervalue{0} + +\permanent\protected\def\newcounter#1% + {\dodoglobal\let#1\zerocountervalue} + +%D Nowadays we don't mind a few more tokens if we can gain a 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% + {\def\m_syst_action_yes{\syst_helpers_do_do_do_increment#1}% + \def\m_syst_action_nop{\syst_helpers_do_do_do_increment#1,\plusone}% + \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop} + +\def\syst_helpers_do_do_decrement(#1% + {\def\m_syst_action_yes{\syst_helpers_do_do_do_decrement#1}% + \def\m_syst_action_nop{\syst_helpers_do_do_do_decrement#1,\plusone}% + \doifelsenextcharcs,\m_syst_action_yes\m_syst_action_nop} + +\permanent\protected\def\increment{\doifelsenextcharcs(\syst_helpers_do_do_increment\syst_helpers_do_increment} +\permanent\protected\def\decrement{\doifelsenextcharcs(\syst_helpers_do_do_decrement\syst_helpers_do_decrement} + +\permanent\protected\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}} +\permanent\protected\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}} + +\permanent\protected\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname} +\permanent\protected\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname} + +%D \macros +%D {newsignal} +%D +%D When writing advanced macros, we cannot do without signaling. A signal is a small +%D (invisible) kern or penalty that signals the next macro that something just +%D happened. This macro can take any action depending on the previous signal. +%D Signals must be unique and the next macro takes care of that. +%D +%D \starttyping +%D \newsignal\somesignal +%D \stoptyping +%D +%D Signals old dimensions and can be used in skips, kerns and tests like \type +%D {\ifdim}. + +\newdimen\d_syst_maximum_signal % step is about 0.00025pt + +\permanent\protected\def\newsignal#1% + {\ifdefined#1\else + \advance\d_syst_maximum_signal2\scaledpoint % to be save in rounding + \immutable\dimensiondef#1\d_syst_maximum_signal + \fi} + +%D \macros +%D {strippedcsname} +%D +%D The next macro can be very useful when using \type {\csname} like in: +%D +%D \starttyping +%D \csname if\strippedcsname\something\endcsname +%D \stoptyping + +\aliased\let\checkedstrippedcsname\csstring + +%D \macros +%D {savenormalmeaning} +%D +%D We will use this one in: + +\permanent\protected\def\savenormalmeaning#1% + {\ifcsname normal\csstring#1\endcsname \else + \letcsname 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 the other hand its +%D recursion engine is quite unique. We therefore identify the for||looping macros +%D by this method. The most simple alternative is the one that only needs a number. +%D +%D \starttyping +%D \dorecurse {n} {whatever we want} +%D \stoptyping +%D +%D This macro can be nested without problems and therefore be used in situations +%D where \PLAIN\ \TEX's \type {\loop} macro ungracefully fails. The current value of +%D the counter is available in \type {\recurselevel}, before as well as after the +%D \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 \type {\recurselevel} concern the +%D outer loop, while the third and fifth one concern the inner loop. The depth of +%D the nesting is available for inspection in \type {\recursedepth}. +%D +%D Both \type {\recurselevel} and \type {\recursedepth} are macros. The real +%D \COUNTERS\ are hidden from the user because we don't want any interference. +%D +%D We now use the macro stack which is somewhat leaner and meaner and a little +%D faster too. + +% left overs: too much \protected here + +\newcount\outerrecurse +\newcount\innerrecurse + +\mutable\def\recursedepth{\the\outerrecurse} +\mutable\def\recurselevel{0} + +\mutable\let\recurseaction\relax +\mutable\let\recursestring\empty + +% \let\syst_helpers_stepwise_next\relax + +% \protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step +% {\ifnum#1>#2\relax +% \expandafter\syst_helpers_stepwise_recurse_nop +% \else +% \def\recurselevel{#1}% +% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter +% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} + +\protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step + {\ifnum#1>#2\relax + \expandafter\gobblefourarguments + \else + \def\recurselevel{#1}% +% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter +% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} + \doubleexpandafter\syst_helpers_stepwise_recurse_yes + \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} + +\protected\def\syst_helpers_stepwise_recurse_yes + {\syst_helpers_recurse_content + \syst_helpers_stepwise_recurse} + +\protected\def\syst_helpers_stepwise_reverse#1#2#3% from to step + {\ifnum#1<#2\relax +% \expandafter\syst_helpers_stepwise_recurse_nop + \expandafter\gobblefourarguments + \else + \def\recurselevel{#1}% + \innerrecurse#1\relax + \advance\innerrecurse#3\relax +% \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter +% \fi\expandafter{\the\innerrecurse}{#2}{#3}} + \doubleexpandafter\syst_helpers_stepwise_reverse_yes + \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} + +\protected\def\syst_helpers_stepwise_reverse_yes + {\syst_helpers_recurse_content + \syst_helpers_stepwise_reverse} + +% \protected\def\syst_helpers_stepwise_exit +% {\syst_helpers_stepwise_recurse_nop\relax} + +\permanent\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 a special case of the +%D more general: +%D +%D \starttyping +%D \dostepwiserecurse {from} {to} {step} {action} +%D \stoptyping +%D +%D This commands accepts positive and negative steps. Illegal values are handles as +%D good as possible and the macro accepts numbers and \COUNTERS. +%D +%D \starttyping +%D \dostepwiserecurse {1} {10} {2} {...} +%D \dostepwiserecurse {10} {1} {-2} {...} +%D \stoptyping +%D +%D Because the simple case (n=1) is used often, we implement it more efficiently: + +\permanent\protected\def\dorecurse#1% + {\ifcase#1\relax + \expandafter\gobbletwoarguments + \or + \expandafter\syst_helpers_recurse_y + \else + \expandafter\syst_helpers_recurse_x + \fi{#1}} + +\protected\def\syst_helpers_recurse_indeed#1#2% from to +% {\ifnum#1>#2 % + {\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}} + +\protected\def\syst_helpers_recurse_indeed_yes + {\syst_helpers_recurse_content + \syst_helpers_recurse_indeed} + +\protected\def\syst_helpers_recurse_indeed_nop#0#0#0% + {} + +%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 + +\permanent\protected\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 (a combinations of) +%D conditions. We therefore implement a straightforward loop, which can only be left +%D when we explictly exit it. Nesting is supported. First we present a more +%D 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 \type {\loopdepth}. + +\aliased\let\endofloop\donothing % maybe \syst_helpers_loop_end + +\permanent\protected\def\doloop#1% + {\global\advance\outerrecurse \plusone + \globalpushmacro\recurseaction + \globalpushmacro\recurselevel + \protected\gdef\recurseaction##1##2{#1}% + \enforced\let\endofloop\syst_helpers_loop + \syst_helpers_loop1}% no \plusone else \recurselevel wrong + +\protected\def\syst_helpers_loop#1% + {\def\recurselevel{#1}% + \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}} + +\protected\def\syst_helpers_loop_yes + {\syst_helpers_recurse_content + \endofloop} + +\protected\def\syst_helpers_loop_nop#0% + {\enforced\let\endofloop\syst_helpers_loop + \globalpopmacro\recurselevel + \globalpopmacro\recurseaction + \global\advance\outerrecurse\minusone} + +\permanent\protected\def\exitloop % \exitloop quits at end + {\enforced\let\endofloop\syst_helpers_loop_nop} + +\permanent\protected\def\exitloopnow#0\endofloop % \exitloopnow quits directly + {\syst_helpers_loop_nop} + +%D The loop is executed at least once, so beware of situations 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} statement that should +%D 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 means of a +%D \type {#1}. I decided to pass the more frequently used level as \type {#1} and +%D the less favoured depth as \type {#2}. The 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 expansion here. +%D +%D \starttyping +%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}} +%D \stoptyping + +\def\syst_helpers_recurse_content + {\normalexpanded{\recurseaction{\recurselevel}{\the\outerrecurse}}} + +\protected\def\syst_helpers_recurse_x#1#2% + {\global\advance\outerrecurse\plusone + \globalpushmacro\recurseaction + \globalpushmacro\recurselevel + \protected\gdef\recurseaction##1##2{#2}% + \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}% + \globalpopmacro\recurselevel + \globalpopmacro\recurseaction + \global\advance\outerrecurse\minusone} + +\protected\def\syst_helpers_recurse_y#1#2% + {\global\advance\outerrecurse\plusone + \globalpushmacro\recurseaction + \globalpushmacro\recurselevel + \let\recurselevel\!!plusone + \protected\gdef\recurseaction##1##2{#2}% + \syst_helpers_recurse_content + \globalpopmacro\recurselevel + \globalpopmacro\recurseaction + \global\advance\outerrecurse\minusone} + +% \protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 +% {\global\advance\outerrecurse \plusone +% \globalpushmacro\recurseaction +% \globalpushmacro\recurselevel +% \protected\gdef\recurseaction##1##2{#4}% +% \normalexpanded{\ifcmpnum#3\zerocount +% \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's +% \syst_helpers_stepwise_exit +% \else +% \syst_helpers_stepwise_reverse +% \fi +% \or +% \syst_helpers_stepwise_exit +% \or +% \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's +% \syst_helpers_stepwise_exit +% \else +% \syst_helpers_stepwise_recurse +% \fi +% \fi{\number#1}{\number#2}{\number#3}}% +% \globalpopmacro\recurselevel +% \globalpopmacro\recurseaction +% \global\advance\outerrecurse\minusone} + +\permanent\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 ... todo: remove unused helpers + {\global\advance\outerrecurse \plusone + \globalpushmacro\recurseaction + \globalpushmacro\recurselevel + \protected\gdef\recurseaction##1##2{#4}% + \normalexpanded{\ifcmpnum#3\zerocount + \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's + \doubleexpandafter\gobbletwoarguments + \else + \tripleexpandafter\syst_helpers_stepwise_reverse + \fi + \or + \doubleexpandafter\gobbletwoarguments + \orelse\ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's + \doubleexpandafter\gobbletwoarguments + \else + \doubleexpandafter\syst_helpers_stepwise_recurse + \fi\normalexpanded{{\number#1}{\number#2}{\number#3}}}% + \globalpopmacro\recurselevel + \globalpopmacro\recurseaction + \global\advance\outerrecurse\minusone} + +% \protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0% +% {} + +\newcount\fastloopindex +\newcount\fastloopfinal + +\let\m_syst_helpers_fast_loop_cs\relax + +\permanent\protected\def\dofastloopcs#1% + {\fastloopfinal#1\relax + \ifcase\fastloopfinal + \expandafter\gobbleoneargument + \else + \expandafter\syst_helpers_fast_loop_cs + \fi} + +\protected\def\syst_helpers_fast_loop_cs#1% + {\let\m_syst_helpers_fast_loop_cs#1% + \fastloopindex\plusone + \syst_helpers_fast_loop_cs_step} + +\protected\def\syst_helpers_fast_loop_cs_step + {\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_step + \fi} + +% Helper: + +\permanent\protected\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 + +\permanent\protected\def\doloopoverlist#1#2% + {\global\advance\outerrecurse\plusone + \globalpushmacro\recurseaction + \globalpushmacro\recursestring + \protected\gdef\recurseaction##1{\edef\recursestring{##1}#2}% + \processcommacommand[#1]\recurseaction + \globalpopmacro\recursestring + \globalpopmacro\recurseaction + \global\advance\outerrecurse\minusone} + +%D This is some \LMTX\ experiment: +%D +%D Think of: +%D +%D \starttyping +%D \domatch {(\letterpercent w+) *(\letterpercent w*)} {aa bb cc dd} { +%D [ +%D \domatch{(\letterpercent w)(\letterpercent w)} {#1} {(##1 ##2)} +%D \domatch{(\letterpercent w)(\letterpercent w)} {#2} {(##1 ##2)} +%D ] +%D } +%D +%D and: +%D +%D \stoptyping +%D +%D \starttyping +%D \def\MyMacro#1{(#1)} \ctxluamatch \MyMacro {(.)} {abcd} +%D \stoptyping + +\aliased\let\matchloopcommand\relax + +\permanent\protected\def\doloopovermatch#1#2#3% + {\pushmacro\matchloopcommand + \enforced\def\matchloopcommand##1##2##3##4##5##6##7##8##9{#3}% + \ctxluamatch\matchloopcommand{#1}{#2}% + \popmacro\matchloopcommand} + +\permanent\def\doloopovermatched#1#2#3% + {\beginlocalcontrol + \pushmacro\matchloopcommand + \enforced\def\matchloopcommand##1##2##3##4##5##6##7##8##9{#3}% + \endlocalcontrol + \the\ctxluamatch\matchloopcommand{#1}{#2}% + \beginlocalcontrol + \popmacro\matchloopcommand + \endlocalcontrol} + +%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} + +\permanent\protected\def\newevery#1#2% + {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere + \ifx#2\relax\orelse\ifdefined#2\else + \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname + \frozen\protected\edef#2{\syst_helpers_every#1\csname\??extraevery\csstring#1\endcsname}% + \fi} + +\protected\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 + +\permanent\protected\def\forgeteverypar + {\everypar{\the\neverypar}} + +%D Which we're going to use indeed! When the second argument equals \type {\relax}, +%D the first token list is created unless it is already defined. +%D +%D Technically spoken we could have used the method we are going to present in the +%D visual debugger. First we save the primitive \type{\everypar}: +%D +%D \starttyping +%D \let\normaleverypar=\everypar +%D \stoptyping +%D +%D Next we allocate a \TOKENLIST\ named \type{\everypar}, which means that +%D \type{\everypar} is no longer a primitive but something like \type{\toks44}. +%D +%D \starttyping +%D \newtoks\everypar +%D \stoptyping +%D +%D Because \TEX\ now executes \type{\normaleverypar} instead of \type{\everypar}, we +%D are ready to assign some tokens to 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 every time he expects +%D 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 confusing situations, +%D especially when other packages are used, but it's this kind of tricks that make +%D \TEX\ so powerful. + +%D \macros +%D {convertargument,convertcommand,convertvalue} +%D +%D Some persistent experimenting led us to the next macro. This macro converts a +%D parameter or an expanded macro to it's 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 or the terminal +%D without problems. In \CONTEXT\ we use this macro for generating registers and +%D 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 assignments. + +\permanent\protected\def\convertvalue#1\to + {\expandafter\convertcommand\csname#1\endcsname\to} + +\permanent\protected\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 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 seperation. The next +%D command takes care of propper handling of such multi||faced commands. +%D +%D \starttyping +%D \doifassignmentelse {...} {then ...} {else ...} +%D \stoptyping +%D +%D So +%D \startbuffer +%D \doifelseassignment{a=b}{Y}{N} +%D \doifelseassignment{a+b}{Y}{N} +%D +%D \ifcondition\validassignment {a=b}Y\else N\fi +%D \ifcondition\novalidassignment{a=b}N\else Y\fi +%D \ifcondition\novalidassignment {ab}Y\else N\fi +%D \stopbuffer +%D +%D \typebuffer gives: \blank \getbuffer \blank + +\permanent\protected\def\doifelseassignment#1% + {\ifhastok={#1}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifelseassignmentcs#1#2#3% + {\ifhastok={#1}% + \expandafter#2% + \else + \expandafter#3% + \fi} + +\aliased\let\doifassignmentelse \doifelseassignment +\aliased\let\doifassignmentelsecs\doifelseassignmentcs + +\newif\ifassignment + +\permanent\protected\def\docheckassignment#1% + {\ifhastok={#1}% + \assignmenttrue + \else + \assignmentfalse + \fi} + +\permanent\protected\def\validassignment #1{\ifhastok={#1}} % can become: {\ifhastok=} as we enforce {} +\permanent\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone} % or use unless + +%D In \ETEX\ we can use \type {\detokenize} and gain some speed, but in general far +%D less that 1\% for \type {\convertargument} and nil for \type {\convertcommand}. +%D This macro is more robust than the pure \TEX\ one, something I found out when +%D primitives like \type {\jobname} were fed (or something undefined). + +\permanent\protected\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}} +\permanent\protected\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok + +\permanent\protected\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}} +\permanent\protected\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}} +\permanent\protected\def\edefconvertedargument#1#2{\edef#1{#2}% + \edef#1{\detokenize\expandafter{#1}}} +\permanent\protected\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}} +\permanent\protected\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}} +\permanent\protected\def\xdefconvertedargument#1#2{\xdef#1{#2}% + \xdef#1{\detokenize\expandafter{#1}}} + +%D When you try to convert a primitive command, you'll find out that the \ETEX\ +%D method fails on for instance \type {\jobname} in the sense that it returns the +%D filename instead of just \type {\jobname}. So far this does not give real +%D problems. + +%D This is typically a macro that one comes to after reading the \TEX book +%D carefully. Even then, the definite solution was found after rereading the \TEX +%D book. The first implementation was: +%D +%D \starttyping +%D \def\doconvertargument#1->#2\\\\{#2} +%D \stoptyping +%D +%D The \type {-}, the delimiter \type {\\\\} and the the second argument are +%D completely redundant. + +%D \macros +%D {showvalue} +%D +%D Ahandy macro, for testing purposes only: + +\permanent\protected\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 meanings expand to +%D something \type {->}. This is no problem in the \ETEX\ implementation, but since +%D we want 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. + +\permanent\protected\def\doifelsemeaning#1#2% + {\edef\m_syst_string_one{\normalmeaning#1}% + \def \m_syst_string_two{#2}% + \edef\m_syst_string_two{\normalmeaning\m_syst_string_two}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifmeaningelse\doifelsemeaning + +%D \macros +%D {doifsamestringselse,doifsamestring,doifnotsamestring} +%D +%D The next comparison macro converts the arguments into expanded strings. This +%D command can be used to compare for instance \type {\jobname} with a name stored +%D 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} + +\permanent\protected\def\doifelsesamestring{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments} +\permanent\protected\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument } +\permanent\protected\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument } + +\aliased\let\doifsamestringelse\doifelsesamestring + +%D These are obsolete in MTX: +%D +%D \starttyping +%D \ConvertToConstant #1#2#3 +%D \CheckConstantAfter #1#2 +%D \ConvertConstantAfter #1#2#3 +%D \stoptyping + +%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. + +\permanent\protected\def\assignifempty#1#2% + {\iftok{#1}\emptytoks \def#1{#2}\fi} + +%D \macros +%D {gobbleuntil,grabuntil,gobbleuntilrelax, +%D processbetween,processuntil} +%D +%D In \TEX\ gobbling usually stand for skipping arguments, so here are our gobbling +%D macros. +%D +%D In \CONTEXT\ we use a lot of \type {\start}||\type {\stop} like constructions. +%D Sometimes, the \type {\stop} is used as a hard coded delimiter like in: %D +%D \starttyping +%D \protected\def\startcommand#1\stopcommand% +%D {... #1 ...} +%D \stoptyping +%D +%D In many cases the \type {\start}||\type {\stop} pair is defined at format +%D generation time or during a job. This means that we cannot hardcode the \type +%D {\stop} criterium. Only after completely understanding \type {\csname} and \type +%D {\expandafter} I was able to to implement a solution, starting with: +%D +%D \starttyping +%D \grabuntil{stop}\command +%D \stoptyping +%D +%D This commands executes, after having encountered \type {\stop} the command \type +%D {\command}. This command receives as argument the text preceding the \type +%D {\stop}. This means that: +%D +%D \starttyping +%D \protected\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 + +\protected\def\syst_helpers_grab#1#2% + {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed} + +\permanent\protected\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 + +\permanent\protected\def\processbetween#1#2% + {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}} + +% \protected\def\gobbleuntil#1% +% {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed} +% +% \protected\def\gobbleuntilrelax#1\relax +% {} + +\permanent\protected\def\gobbleuntil#1% + {\def\syst_helpers_gobble_indeed##-#1{}\syst_helpers_gobble_indeed} + +\permanent\protected\def\gobbleuntilrelax#-\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 + +\permanent\protected\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 form \type{#1} are fixed +%D the the moment the argument is read in. Normally this is no problem, but for +%D instance verbatim environments adapt the \CATCODES\ of characters and therefore +%D are not always happy with already fixed tokens. +%D +%D Another problem arises when the argument is grouped not by \type {{}} but by +%D \type {\bgroup} and \type {\egroup}. Such an argument fails, because the \type +%D {\bgroup} is een as the argument (which is quite normal). +%D +%D The next macro offers a solution for both unwanted 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 at the end of the line. +%D The solution mentioned before does not work here. We also handle +%D +%D \starttyping +%D to be \bold{bold} or not, that's the question +%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 + +\protected\def\syst_helpers_handle_group_nop + {\ifnum\currentgrouptype=\semisimplegroupcode + \expandafter\syst_helpers_handle_group_nop_a + \else + \expandafter\syst_helpers_handle_group_nop_b + \fi} + +\def\syst_helpers_handle_group_nop_a + {\begingroup + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\endgroup + \m_syst_helpers_handle_group_b} + +\def\syst_helpers_handle_group_nop_b + {\bgroup + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\egroup + \m_syst_helpers_handle_group_b} + +\protected\def\syst_helpers_handle_group_normal + {\bgroup + \afterassignment\m_syst_helpers_handle_group_normal_before + \let\next=} + +\def\m_syst_helpers_handle_group_normal_before + {\bgroup + \m_syst_helpers_handle_group_b + \bgroup + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\egroup + \aftergroup\egroup} + +\protected\def\syst_helpers_handle_group_simple% no inner group (so no kerning interference) + {\bgroup + \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_b} + +\def\m_syst_helpers_handle_group_simple_after + {\m_syst_helpers_handle_group_a + \egroup}% + +\protected\def\syst_helpers_handle_group_pickup% no inner group (so no kerning interference) + {\bgroup + \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_a + \aftergroup\egroup + \aftergroup\m_syst_helpers_handle_group_p + \m_syst_helpers_handle_group_b} + +\protected\def\syst_helpers_handle_group_nop_x + {\ifnum\currentgrouptype=\semisimplegroupcode + \begingroup + \aftergroup\endgroup + \else + \bgroup + \aftergroup\egroup + \fi + \m_syst_helpers_handle_group_b} + +\protected\def\syst_helpers_handle_group_normal_x + {\bgroup + \afterassignment\m_syst_helpers_handle_group_normal_before_x + \let\next=} + +\def\m_syst_helpers_handle_group_normal_before_x + {\bgroup + \m_syst_helpers_handle_group_b + \bgroup + \aftergroup\egroup + \aftergroup\egroup} + +%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 fact that \type +%D {\futurelet} obeys blank spaces, and a line||ending token is treated as a blank +%D space. So the final implementation became: + +\permanent\protected\def\groupedcommand#1#2% + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} + +\permanent\protected\def\groupedcommandcs#1#2% + {\let\m_syst_helpers_handle_group_b#1% + \let\m_syst_helpers_handle_group_a#2% + \futureexpandis\bgroup\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} + +\permanent\protected\def\simplegroupedcommand#1#2% + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \futureexpandis\bgroup\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop} + +\permanent\protected\def\pickupgroupedcommand#1#2#3% + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \def\m_syst_helpers_handle_group_p{#3}% + \futureexpandis\bgroup\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop} + +\permanent\protected\def\triggergroupedcommand#1% + {\def\m_syst_helpers_handle_group_b{#1}% + \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} + +\permanent\protected\def\triggergroupedcommandcs#1% + {\let\m_syst_helpers_handle_group_b#1% + \futureexpandis\bgroup\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} + +%D Users should be aware of the fact that grouping can interfere with ones paragraph +%D settings that are executed after the paragraph is closed. One should therefore +%D explictly close the paragraph with \type {\par}, else the settings will be +%D forgotten and not applied. So it's: +%D +%D \starttyping +%D \def\BoldRaggedCenter% +%D {\groupedcommand{\raggedcenter\bf}{\par}} +%D \stoptyping + +% %D \macros +% %D {checkdefined} +% %D +% %D The bigger the system, the greater the change that user defined commands collide +% %D with those that are part of the system. The next macro gives a warning when a +% %D command is already defined. We considered blocking the definition, but this is +% %D 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 \type {CAPITALS}. This suggestion +% %D is feasible, because \CONTEXT only defines lowcased macros. These are obsolete: +% +% \protected\def\showdefinederror#1#2% +% {\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}} +% +% \protected\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 first grabbing the +%D contents of the paragraph and processing this contents grouped. The next macro +%D for instance typesets 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. When we started +%D typesetting with \TEX, we already had produced lots of text in plain \ASCII. In +%D producing such simple formatted texts, we adopted an open layout, and when +%D switching to \TEX, we continued this open habit. Although \TEX\ permits a cramped +%D and badly formatted source, it adds to confusion and sometimes introduces errors. +%D 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 specifications. The +%D definition of the macro handling \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 ways. The recent version, +%D the fourth one in a row, originally was far more complicated, but some +%D functionality has been moved to other macros. +%D +%D We start with the more simple but in some cases more appropriate alternative is +%D \type {\GotoPar}. This one leaves \type {\par} unchanged and is therefore more +%D robust. On the other hand, \type {\AfterPar} is not supported. + +\let\syst_helpers_par_before\relax +\let\syst_helpers_par_around\relax + +\permanent\protected\def\dowithpar#1#2% + {\globalpushmacro\syst_helpers_par_around + \def\syst_helpers_par_around##1\par{#1##1#2\globalpopmacro\syst_helpers_par_around}% + \expandafter\syst_helpers_par_around\ignorepars} + +\permanent\protected\def\dogotopar#1% + {\globalpushmacro\syst_helpers_par_before + \def\syst_helpers_par_before{#1\globalpopmacro\syst_helpers_par_before}% + \expandafter\syst_helpers_par_before\ignorepars} + +\aliased\let\dogotoparcs\dogotopar + +\permanent\protected\def\dogotoparstart + {\ignorepars} + +%D This is old and kind of obsolete: + +\newtoks\BeforePar +\newtoks\AfterPar + +\permanent\protected\def\GetPar + {\expanded + {\dowithpar + {\the\BeforePar + \BeforePar\emptytoks} + {\the\AfterPar + \BeforePar\emptytoks + \AfterPar\emptytoks}}} + +\permanent\protected\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 macros expect an +%D argument, it interprets a grouped sequence of characters a one token. While this +%D adds to robustness and less ambiguous situations, we sometimes want to be a bit +%D more flexible, or at least want to be a bit more tolerant 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 chapters, sections etc. The +%D commands responsible for these activities accept several alternative ways of +%D argument passing. In these examples, the \type {\par} can be omitted when an +%D 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 + +\permanent\protected\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. When we want to act +%D upon words we can use the \type{w} alternative. +%D +%D \starttyping +%D \dowithwargument\command +%D \dowithwargument{... \command ...} +%D \stoptyping +%D +%D The main difference bwteen two alternatives is in the handling of \type {\par}'s. +%D This time the space token acts 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 + +\permanent\protected\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 \type {\dorecurse}. The +%D next alternative however, suits 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 a row. In both +%D commands, the \type {n*} is optional. When this specification is missing, the +%D command executes once. + +\permanent\protected\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}% + \orelse\ifnum#1<\zerocount + %\normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}% + \dorecurse{-#1}{#4{-#2#3}}% + \orelse\ifx#2+% + \dorecurse{#1}{#4{#3}}% + \else + \dorecurse{#1}{#4{#2#3}}% + \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 are macros. This save +%D some unneeded expansion. But now we just alias. + +\aliased\let\doifelsestringinstring\doifelseinstring +\aliased\let\doifstringinstringelse\doifelseinstring + +%D \macros +%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce, +%D doifintokselse,flushtoks,dotoks} +%D +%D We use tokenlists sparsely within \CONTEXT, because the comma separated lists are +%D more suitable for the user 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 Knuth's \TEX book. + +\newtoks\t_syst_helpers_scratch +\let \m_syst_helpers_scratch\empty + +\permanent\protected\def\appendtoks#1\to#2% + {\ifx\dodoglobal\relax + \expandafter\toksapp + \else + \resetglobal + \expandafter\gtoksapp + \fi#2{#1}} + +\permanent\protected\def\prependtoks#1\to#2% + {\ifx\dodoglobal\relax + \expandafter\tokspre + \else + \resetglobal + \expandafter\gtokspre + \fi#2{#1}} + +% \def\syst_helpers_append_toks_indeed +% {\ifx\dodoglobal\relax +% \expandafter\toksapp +% \else +% \resetglobal +% \expandafter\gtoksapp +% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} +% +% \def\syst_helpers_prepend_toks_indeed +% {\ifx\dodoglobal\relax +% \expandafter\tokspre +% \else +% \resetglobal +% \expandafter\gtokspre +% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} +% +% \protected\def\appendtoksonce#1\to#2% +% {\let\m_syst_helpers_scratch#2% +% \t_syst_helpers_scratch{#1}% +% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else +% \syst_helpers_append_toks_indeed +% \fi} +% +% \protected\def\prependtoksonce#1\to#2% +% {\let\m_syst_helpers_scratch#2% +% \t_syst_helpers_scratch{#1}% +% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else +% \syst_helpers_prepend_toks_indeed +% \fi} + +\permanent\protected\def\appendtoksonce#1\to#2% + {\ifhasxtoks{#1}#2\else + \appendtoks#1\to#2% + \fi} + +\permanent\protected\def\prependtoksonce#1\to#2% + {\ifhasxtoks{#1}{#2}\m_syst_helpers_scratch\else + \prependtoks#1\to#2% + \fi} + +%D The test macro: + +\permanent\protected\def\doifelseintoks#1#2% #1 en #2 zijn toks + {\ifhasxtoks#1#2% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifintokselse\doifelseintoks + +%D Moved from \type {lxml-ini.tex} to here. This one is for generators that collect +%D stuff piecewise, which is sometimes hard on mechanisms that grab content using +%D 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 + +\aliased\let\stopcollect \relax +\aliased\let\stopexpandedcollect\relax + +\permanent\protected\def\startcollect #1\stopcollect {\toksapp \collectingtoks{#1}} +\permanent\protected\def\startexpandedcollect#1\stopexpandedcollect{\etoksapp\collectingtoks{#1}} + +\permanent\protected\def\startcollecting{\collectingtoks\emptytoks} +\permanent\protected\def\stopcollecting {\the\collectingtoks} + +\permanent\protected\def\collect {\toksapp \collectingtoks} +\permanent\protected\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]} + +\permanent\protected\def\removetoks#1\from#2% + {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3^^^^0004% + {\def\m_syst_string_one{##3}% + \ifempty\m_syst_string_one#2{##1}\else#2{##1##2}\fi}% + \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty^^^^0004} + +%D Also: + +\permanent\protected\def\appendetoks#1\to#2% + {\ifx\dodoglobal\relax + \expandafter\etoksapp + \else + \resetglobal + \expandafter\xtoksapp + \fi#2{#1}} + +\permanent\protected\def\prependetoks#1\to#2% + {\ifx\dodoglobal\relax + \expandafter\etokspre + \else + \resetglobal + \expandafter\xtokspre + \fi#2{#1}} + +%D Hm. + +\permanent\protected\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} + +\aliased\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 the second one. The +%D alternative looking more or less like the first one did not always give the +%D results we needed. Both implementations show some insight in the manipulation of +%D arguments. + +\let\syst_helpers_split_string\relax + +\permanent\protected\def\beforesplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##1#2##0^^^^0004% no #- as we need to count + {\ifarguments + \let#3\empty + \or + \let#3\empty + \else + \def#3{##1}% + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +\permanent\protected\def\aftersplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##0#2##2^^^^0004% no #- as we need to count + {\ifarguments + \let#3\empty + \or + \def#3{#1}% + \else + \def#3{##2}% + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +%D \macros +%D {splitstring,greedysplitstring} +%D +%D A bonus macro. + +\permanent\protected\def\splitstring#1\at#2\to#3\and#4% + {\def\syst_helpers_split_string##1#2##2^^^^0004% + {\ifarguments + \let#3\empty + \let#4\empty + \or + \def#3{#1}% + \let#4\empty + \else + \def#3{##1}% + \def#4{##2}% + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +\permanent\protected\def\greedysplitstring#1\at#2\to#3\and#4% + {\def\syst_helpers_split_string##1#2##2^^^^0004% + {\ifarguments + \let#3\empty + \let#4\empty + \or + \def#3{#1}% + \let#4\empty + \else + \def#3{##1}% + \def#4{##2}% + \def\syst_helpers_split_string####1#2####2^^^^0004% + {\ifarguments + \or + \else + \expandafter\def\expandafter#3\expandafter{#3####1}% + \def#4{####2}% + \syst_helpers_split_string####2^^^^0004\ignorearguments\ignorearguments + \fi}% + \syst_helpers_split_string##2^^^^0004\ignorearguments\ignorearguments + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +%D \macros +%D {beforetestandsplitstring, +%D aftertestandsplitstring, +%D testandsplitstring} + +\aliased\let\beforetestandsplitstring\beforesplitstring + +\permanent\protected\def\aftertestandsplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##0#2##2^^^^0004% no #- as we need to count + {\ifarguments + \let#3\empty + \or + \let#3\empty + \else + \def#3{##2}% + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +\permanent\protected\def\testandsplitstring#1\at#2\to#3\and#4% + {\def\syst_helpers_split_string##1#2##2^^^^0004% + {\ifarguments + \let#3\empty + \let#4\empty + \or + \let#3\empty + \let#4\empty + \else + \def#3{##1}% + \def#4{##2}% + \fi}% + \expandafter\syst_helpers_split_string#1^^^^0004\ignorearguments\ignorearguments} + +%D \macros +%D {splitatperiod, splitatcomma, splitatasterisk, splitatcolon, splitatcolons} + +\protected\def\syst_helpers_splitatperiod #1.#2.#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} +\protected\def\syst_helpers_splitatcomma #1,#2,#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} +\protected\def\syst_helpers_splitatasterisk #1*#2*#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} +\protected\def\syst_helpers_splitatcolon #1:#2:#-^^^^0004#3#4{\def #3{#1}\def #4{#2}} +\protected\def\syst_helpers_splitatcolons #1::#2::#-^^^^0004#3#4{\edef#3{#1}\edef#4{#2}} + +\permanent\protected\def\splitatperiod #1{\normalexpanded{\syst_helpers_splitatperiod #1}..^^^^0004} +\permanent\protected\def\splitatcomma #1{\normalexpanded{\syst_helpers_splitatcomma #1},,^^^^0004} % not at ", " +\permanent\protected\def\splitatasterisk#1{\normalexpanded{\syst_helpers_splitatasterisk#1}**^^^^0004} +\permanent\protected\def\splitatcolon #1{\normalexpanded{\syst_helpers_splitatcolon #1}::^^^^0004} +\permanent\protected\def\splitatcolons #1{\normalexpanded{\syst_helpers_splitatcolons #1}::::^^^^0004} + +%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: + +\permanent\protected\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 later want the tools to +%D append or remove items from such a list. When we add an item, we first check if +%D it's already 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 implementation of the +%D second command is more complecated, because we have to take leading spaces into +%D account. Keep in mind that users may provide lists with spaces after the commas. +%D When one item is left, we also have to get rid of 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. A fast appending alternative, +%D without any testing, is 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: + +\permanent\protected\def\appendtocommalist#1#2% + {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}} + +\permanent\protected\def\prependtocommalist#1#2% + {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}} + +\permanent\protected\def\addtocommalist#1#2% {item} \cs + {\rawdoifelseinset{#1}#2\resetglobal + {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}}} + +\permanent\protected\def\pretocommalist#1#2% {item} \cs + {\rawdoifelseinset{#1}#2\resetglobal + {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}}} + +\permanent\protected\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} + +\aliased\let\robustdoifinsetelse\robustdoifelseinset + +\permanent\protected\def\robustaddtocommalist#1#2% {item} \cs + {\robustdoifelseinset{#1}#2\resetglobal + {\dodoglobal\edef#2{\ifempty#2\else#2,\fi#1}}} + +\permanent\protected\def\robustpretocommalist#1#2% {item} \cs + {\robustdoifelseinset{#1}#2\resetglobal + {\dodoglobal\edef#2{#1\ifempty#2\else,#2\fi}}} + +\permanent\protected\def\xsplitstring#1#2% \cs {str} + %{\def\syst_helpers_split_string##1,#2,##2,#2,##3\\% + {\def\syst_helpers_split_string##1,#2,##2,#2,##-\\% + {\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} +\def\acleanedupcommalist#1,,#-\relax{#1} + +\permanent\protected\def\removefromcommalist#1#2% to be sped up + {\rawdoifelseinset{#1}#2% + {\normalexpanded{\xsplitstring\noexpand#2{#1}}% + \dodoglobal\edef#2% + {\ifempty\m_syst_string_one + \m_syst_string_two + \else + \m_syst_string_one\ifempty\m_syst_string_two\else,\m_syst_string_two\fi + \fi}} + \resetglobal} + +%D \macros +%D {substituteincommalist} +%D +%D Slow but seldom used, so for the moment we stick to this 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 + \ifempty\m_syst_string_two \else + \edef\m_syst_string_four{\ifempty\m_syst_string_four\else\m_syst_string_four,\fi\m_syst_string_two}% + \fi + \else + \edef\m_syst_string_four{\ifempty\m_syst_string_four\else\m_syst_string_four,\fi#1}% + \fi} + +\permanent\protected\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 + +\mutable\let\newcommalistelement\empty + +\def\syst_helpers_replace_in_comma_list_step#1% we can use #+ here too + {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax + \ifempty\newcommalistelement\else + \ifempty\m_syst_helpers_comma_list_target + \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 + \ifempty\m_syst_helpers_comma_list_target + \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} + +\permanent\protected\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 fact that the way they +%D handle expansion as well as the fact that they can be nested. This makes them +%D kind of useless for 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} + +\permanent\protected\def\globalprocesscommalist[#1]#2% + {\glet\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} +% +% Okay, not really an impressive extension to the engine, but better than some macro +% that is demonstrating deeper understanding of \TEX. It's anyway a trivial extension +% anyway. There are actually many examples of very advanced macros and exposure of +% how clever one is that could be done cheap in the engine. It's just that at the time +% that \TEX\ was written, it made no sense to add a lot of that. After decades we know +% what extras we need. + +\permanent\def\withoutpt#1{\thewithoutunit\dimexpr#1} % best use the primitive directly + +%D The capitals are needed because \type {p} and \type {t} have catcode~12, while +%D macronames only permit tokens with the catcode~11. As a result we cannot use the +%D \type {.group} primitives. Those who want to know more about this kind of +%D manipulations, we advice to study the \TEX book in detail. Because this macro +%D does not do any assignment, we can use it in the following way too. + +% \def\PtToCm#1% +% {\withoutpt\the\dimexpr0.0351459804\dimexpr#1\relax\relax cm} + +\permanent\def\PtToCm#1{\thewithoutunit\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} + +\permanent\def\dimensiontocount#1#2{#2\numexpr\dimexpr#1\relax/\maxcard\relax} +\permanent\def\numberofpoints #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax} + +%D \macros +%D {swapdimens,swapskips,swapcounts,swapmacros, +%D globalswapdimens,globalswapcounts,globalswapmacros} +%D +%D Simple but effective are the next two macros. There name exactly states their +%D purpose. + +\newdimen\d_syst_helpers_swapped +\newskip \s_syst_helpers_swapped +\newcount\c_syst_helpers_swapped +\let \m_syst_helpers_swapped\relax + +% \protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped} +% \protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped} +% \protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped} +% \protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped} + +\aliased\let\swapdimens\swapcsvalues +\aliased\let\swapskips \swapcsvalues +\aliased\let\swapcounts\swapcsvalues +\aliased\let\swapmacros\swapcsvalues + +% \protected\def\globalswapdimens#1#2{\d_syst_helpers_swapped#1\global#1#2\global#2\d_syst_helpers_swapped} +% \protected\def\globalswapskips #1#2{\s_syst_helpers_swapped#1\global#1#2\global#2\s_syst_helpers_swapped} +% \protected\def\globalswapcounts#1#2{\c_syst_helpers_swapped#1\global#1#2\global#2\c_syst_helpers_swapped} +% \protected\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet#1#2\glet#2\m_syst_helpers_swapped} + +\permanent\protected\def\globalswapdimens{\global\swapcsvalues} +\permanent\protected\def\globalswapskips {\global\swapcsvalues} +\permanent\protected\def\globalswapcounts{\global\swapcsvalues} +\permanent\protected\def\globalswapmacros{\global\swapcsvalues} + +%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 + +\permanent\let\pushmacro\localpushmacro +\permanent\let\popmacro \localpopmacro + +%D \macros +%D {setlocalhsize,distributedhsize} +%D +%D Sometimes we need to work with the \type{ \hsize} that is corrected for +%D indentation and left and right skips. The corrected value is available in \type +%D {\localhsize}, which needs to be calculated with \type {\setlocalhsize} first. %D +%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 value provided is added +%D to \type {\localhsize}. + +\newdimen\localhsize + +\permanent\protected\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} + +\permanent\def\availablehsize + {\dimexpr + \hsize-\leftskip-\rightskip + \ifnum\hangafter<\zerocount + \ifdim\hangindent>\zeropoint-\else+\fi\hangindent + \fi + \relax} + +\permanent\def\distributedhsize#1#2#3% + {\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax} + +\permanent\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 \type {\if} commands can be used to access macros (or variables) that are +%D normally accessed by using \type {\getvalue}. Using these alternatives safes us +%D three tokens per call. Anyone familiar with the not||values ones, can derive +%D their meaning from the definitions. + +\permanent\protected\def\doifvalue#1#2% + {\iftok{\csname#1\endcsname}{#2}% + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotvalue#1#2% + {\iftok{\csname#1\endcsname}{#2}% + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\doifelsevalue#1#2% + {\iftok{\csname#1\endcsname}{#2}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifnothing#1% + {\iftok{#1}\emptytoks + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifsomething#1% + {\iftok{#1}\emptytoks + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\doifelsenothing#1% + {\iftok{#1}\emptytoks + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\doifelsesomething#1% + {\iftok{#1}\emptytoks + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\permanent\protected\def\doifvaluenothing#1% + {\iftok{\csname#1\endcsname}\emptytoks + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifvaluesomething#1% + {\iftok{\csname#1\endcsname}\emptytoks + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\doifelsevaluenothing#1% + {\iftok{\csname#1\endcsname}\emptytoks + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifvalueelse \doifelsevalue +\aliased\let\doifnothingelse \doifelsenothing +\aliased\let\doifsomethingelse \doifelsesomething +\aliased\let\doifvaluenothingelse\doifelsevaluenothing + +%D \macros +%D {doifemptyelsevalue, doifemptyvalue, doifnotemptyvalue} +%D +%D Also handy: + +\permanent\def\doifelseemptyvalue#1% + {\expandafter\ifempty\csname#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifemptyvalueelse\doifelseemptyvalue + +\permanent\def\doifemptyvalue#1% + {\expandafter\ifempty\csname#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\def\doifnotemptyvalue#1% + {\expandafter\ifempty\csname#1\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +%D \macros +%D {doifallcommonelse} +%D +%D A complete match of two sets can be tested with \type {\doifallcommonelse}, where +%D the first two 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} + +\permanent\protected\def\doifelseallcommon{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments} +\permanent\protected\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument } +\permanent\protected\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments } + +\aliased\let\doifallcommonelse\doifelseallcommon + +%D \macros +%D {DOIF,DOIFELSE,DOIFNOT} +%D +%D \TEX\ is case sensitive. When comparing arguments, this feature sometimes is less +%D desirable, for instance when we compare filenames. The next three alternatives +%D upcase their 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: + +\protected\def\syst_helpers_do_IF#1#2% + {\uppercase{\iftok{#1}{#2}}% + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\protected\def\syst_helpers_do_IF_NOT#1#2% + {\uppercase{\iftok{#1}{#2}}% + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\protected\def\syst_helpers_do_IF_ELSE#1#2% + {\uppercase{\iftok{#1}{#2}}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\protected\def\syst_helpers_do_IF_INSTRING_ELSE#1#2% + {\uppercase{\doifelseinstring{#1}{#2}}} + +\permanent\protected\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete +\permanent\protected\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete +\permanent\protected\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete +\permanent\protected\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 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 in the set~\type +%D {#1}. The second one calls for \typ {\command [##1][#2]} and the third, well one +%D may guess. These commands support constructions like: +%D +%D \starttyping +%D \def\dodefinesomething[#1][#2]% +%D {\getparameters[\??xx#1][#2]} +%D +%D \protected\def\definesomething% +%D {\dodoubleargumentwithset\dodefinesomething} +%D \stoptyping +%D +%D Which accepts calls like: +%D +%D \starttyping +%D \definesomething[alfa,beta,...][variable=...,...] +%D \stoptyping + +%% \let\syst_helpers_with_set_step\relax +%% \let\m_syst_helpers_with_set_command\empty +%% +%% \def\syst_helpers_with_set_double[#1][#2]% +%% {\doifsomething{#1}% +%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}% +%% \processcommalist[#1]\syst_helpers_with_set_step}} +%% +%% \def\syst_helpers_with_set_triple[#1][#2][#3]% +%% {\doifsomething{#1}% +%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}% +%% \processcommalist[#1]\syst_helpers_with_set_step}} +%% +%% \def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command +%% \def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command +%% +%% \def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command +%% \def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command + +\let\syst_helpers_with_set_step\relax % maybe push pop + +\permanent\tolerant\protected\def\dodoubleemptywithset#1#*[#2]#*[#3]% + {\doifsomething{#2}% + {\def\syst_helpers_with_set_step##1{#1[##1][#3]}% + \processcommalist[#1]\syst_helpers_with_set_step}} + +\permanent\tolerant\protected\def\dotripleemptywithset#1#*[#2]#*[#3]#*[#4]% + {\doifsomething{#2}% + {\def\syst_helpers_with_set_step##1{#1[##1][#3][#4]}% + \processcommalist[#1]\syst_helpers_with_set_step}} + +\aliased\let\dodoubleargumentwithset\dodoubleemptywithset +\aliased\let\dotripleargumentwithset\dotripleemptywithset + +%D \macros +%D {stripcharacters,stripspaces} +%D +%D The next command was needed first when we implemented the \CONTEXT\ interactivity +%D macros. When we use labeled destinations, we often cannot use all the characters +%D we want. We therefore strip some of the troublemakers, like spaces, from the +%D labels before we write them to the \DVI||file, which passes them to for instance +%D a \POSTSCRIPT\ 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 to enclosed in \type +%D {{}}. + +\let\m_syst_helpers_strip_character\empty + +\permanent\protected\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} + +\permanent\protected\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, like \type +%D {\convert...}. + +\permanent\protected\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 tables of contents, +%D references, two||pass optimizations, sorted lists etc. This file is loaded as +%D many times as needed. During such a pass we skip the commands thate are of no use +%D at that moment. Because we don't want to come into trouble with undefined +%D auxiliary commands, we call the macros in a way similar to \type {\getvalue}. The +%D next macro take care of such executions and when not defined, gobbles the +%D unwanted arguments. +%D +%D \starttyping +%D \executeifdefined{name}\gobbleoneargument +%D \stoptyping +%D +%D We can of course gobble more arguments using the appropriate gobbling command. + +\permanent\def\executeifdefined#1% #2 / never change this one again + {\ifcsname#1\endcsname + \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +%D This one also has the advantage that it is fully expandable and that it can be +%D used after an assignment. + +%D \macros +%D {doifsomespaceelse} +%D +%D The next command checks a string on the presence of a space and executed a +%D command accordingly. +%D +%D \starttyping +%D \doifsomespaceelse {tekst} {then ...} {else ...} +%D \stoptyping +%D +%D We use this command in \CONTEXT\ for determing if an argument must be broken into +%D words when made interactive. Watch the use of \type {\noexpand}. + +%D Is this one still needed? + +% \def\syst_helpers_if_some_space_else#1 #2#3^^^^0004{\if\noexpand#2@} +% +% \def\doifelsesomespace#1% % #2#3% +% {\syst_helpers_if_some_space_else#1 @ @^^^^0004% #3\else#2\fi} +% \expandafter\secondoftwoarguments +% \else +% \expandafter\firstoftwoarguments +% \fi} + +\permanent\edef\doifelsesomespace#1% + {\noexpand\ifhastok\space{#1}% + \noexpand\expandafter\noexpand\firstoftwoarguments + \noexpand\else + \noexpand\expandafter\noexpand\secondoftwoarguments + \noexpand\fi} + +\aliased\let\doifsomespaceelse\doifelsesomespace + +%D \macros +%D {processseparatedlist} +%D +%D Maybe a bit late, but here is a more general version of the \type +%D {\processcommalist} command. This time we don't handle nesting but accept +%D 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 argument, which we remove +%D afterwards. + +\let\syst_helpers_process_separated_list_step\relax + +% \def\syst_helpers_process_separated_list#1]#*[#2]#3% +% {\def\syst_helpers_process_separated_list_step##1##2#2% +% {\def\m_syst_string_one{##2}% suggested by VZ +% \if]##1% +% \let\syst_helpers_process_separated_list_step\relax +% \orelse\ifx\blankspace\m_syst_string_one +% #3{##1}% +% \orelse\if]##2% +% \let\syst_helpers_process_separated_list_step\relax +% \else +% #3{##1##2}% +% \fi +% \syst_helpers_process_separated_list_step}% +% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} + +% \def\syst_helpers_process_separated_list#1]#*[#2]#3% +% {\def\syst_helpers_process_separated_list_step##1##2#2% +% {\def\m_syst_string_one{##2}% suggested by VZ +% \if]##1% +% \orelse\ifx\blankspace\m_syst_string_one +% #3{##1}% +% \expandafter\syst_helpers_process_separated_list_step +% \orelse\if]##2% +% \else +% #3{##1##2}% +% \expandafter\syst_helpers_process_separated_list_step +% \fi +% }% +% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} + +% \permanent\protected\def\processseparatedlist[% +% {\syst_helpers_process_separated_list\relax} + +\permanent\protected\def\processseparatedlist[#+]#*[#2]#3% + {\tolerant\def\syst_helpers_process_separated_list_step##1#2% + {\ifarguments\or + #3{##1}% + \expandafter\syst_helpers_process_separated_list_step + \fi}% + \syst_helpers_process_separated_list_step#1\ignorearguments\ignorearguments} + +%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 defined +%D 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 + +\permanent\protected\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 + \orelse\ifx#2####2% + \let\syst_helpers_process_any_list_step\relax + \else + #4{####1####2}% + \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 containing keywords. +%D Assignments are treated accordingly, 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 we decided best not +%D to do so. + +% \protected\def\processassignlist#1[#2]#3% +% {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]% +% {\doif{##3}\relax{#3{##1}}}% +% \def\syst_helpers_process_assign_list_step##1% +% {\syst_helpers_process_assign_list_assign[##1==\relax]}% +% \processcommalist[#2]\syst_helpers_process_assign_list_step} + +\permanent\protected\def\processassignlist#1[#2]#3% + {\def\syst_helpers_process_assign_list_assign[##1=##-=##2]% + {\doif{##2}\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 index entries, the next +%D 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 sort. + +\let\m_syst_helpers_untexed\empty + +\permanent\protected\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} + +\permanent\protected\def\untexargument{\untexsomething\convertargument} +\permanent\protected\def\untexcommand {\untexsomething\convertcommand} + +%D \macros +%D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints} +%D +%D One characteristic of \POSTSCRIPT\ and \PDF\ is that both used big points (\TEX's +%D bp). The next macros convert points and scaled points into big points. The magic +%D factor $72/72.27$ can be found in most \TEX\ related books. +%D +%D \starttyping +%D \ScaledPointsToBigPoints {number} \target +%D \ScaledPointsToWholeBigPoints {number} \target +%D \stoptyping + +\aliased\let\tobigpoints \clf_tobigpoints % todo: permanent at lua end +\aliased\let\towholebigpoints\clf_towholebigpoints % todo: permanent at lua end + +\permanent\protected\def\PointsToBigPoints #1#2{\edef#2{\tobigpoints #1}} % can be avoided +\permanent\protected\def\PointsToWholeBigPoints #1#2{\edef#2{\towholebigpoints#1}} % can be avoided +\permanent\protected\def\ScaledPointsToBigPoints #1#2{\edef#2{\tobigpoints #1\scaledpoint}} % obsolete +\permanent\protected\def\ScaledPointsToWholeBigPoints#1#2{\edef#2{\towholebigpoints#1\scaledpoint}} % obsolete + +%D \macros +%D {PointsToReal} +%D +%D Points can be stripped from their suffix by using \type {\withoutpt}. The next +%D macro enveloppes this macro. +%D +%D \starttyping +%D \PointsToReal {dimension} \target +%D \stoptyping + +% \protected\def\PointsToReal#1#2% +% {\edef#2{\withoutpt\the\dimexpr#1}} + +\permanent\protected\def\PointsToReal#1#2% + {\edef#2{\thewithoutunit\dimexpr#1}} + +%D \macros +%D {dontleavehmode} +%D +%D Sometimes when we enter a paragraph with some command, the first token gets the +%D whole first line. We can prevent this by saying: +%D +%D \starttyping +%D \dontleavehmode +%D \stoptyping +%D +%D This command is used in for instance the language module \type {lang-ini}. The +%D first version was: +%D +%D \starttyping +%D \def\dontleavehmode{\ifhmode\orelse\ifmmode\else$ $\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 interfering grouping +%D at the cost of a box. +%D +%D \starttyping +%D \newbox\b_syst_helpers_dlh +%D +%D \protected\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: + +\aliased\let\dontleavehmode\quitvmode + +%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}. +%D +%D These macros are sort of obsolete as we never use uppercase this way. But +%D nevertheless we provide them: + +\permanent\def\utfupper#1{\clf_upper{#1}} % expandable +\permanent\def\utflower#1{\clf_lower{#1}} % expandable + +\permanent\protected\def\uppercasestring#1\to#2{\dodoglobal\edef#2{\clf_upper{#1}}} +\permanent\protected\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 expansion. What we want is +%D 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 specific tokens in a +%D 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}, takes a real counter. +%D The macro can be preceded by \type {\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\privatescratchcounter\plusone + \fi + \expandafter\syst_helpers_count_token + \fi} + +\permanent\protected\def\counttoken#1\in#2\to#3% + {\privatescratchcounter\zerocount + \def\m_syst_string_one{#1}% + \def\m_syst_string_two{\end}% + \syst_helpers_count_token#2\end + \dodoglobal#3\privatescratchcounter} + +\permanent\protected\def\counttokens#1\to#2% + {\privatescratchcounter\zerocount + \def\syst_helpers_count_token##1{\advance\privatescratchcounter\plusone}% + \handletokens#1\with\syst_helpers_count_token + \dodoglobal#2\privatescratchcounter} + +%D \macros +%D {splitofftokens} +%D +%D Running this one not always gives the expected results. Consider for instance the +%D macro for which I originally wrote this token handler. + +\permanent\protected\def\splitofftokens#1\from#2\to#3% slow but hardly used + {\ifnum#1>\zerocount + \privatescratchcounter#1\relax + \def\syst_helpers_split_off_tokens##1% + {\ifnum\privatescratchcounter>\zerocount + \advance\privatescratchcounter \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 up there. The reason for this is not that logical but follows from \TEX's +%D However, the characters that we expect to find in \type {\test} just don't show +%D sometimes 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 that are \type {\let} +%D are not expanded! +%D +%D \unprotect\getbuffer[next]\protect +%D +%D That's why we finally end up with a macro that looks ahead by using an +%D assignment, this time by using \type {\futurelet}, and grabbing an argument as +%D well. That way we can handle the sentinal, a blank space and grouped tokens. + +\protected\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface + {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed} + +\permanent\protected\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 + \orelse\ifx\nexthandledtoken\end + \expandafter\gobbletwoarguments % also gobble the \end + \else + \expandafter\syst_helpers_handle_tokens_indeed_two + \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 one does a trial +%D typesetting run, for instance to determine dimensions. Some mechanisms, like +%D object inclusion, can fail on such trials. Temporary setting the next boolean to +%D true, helps a lot. The second boolena can be used to inhibit processing +%D completely. + +\newif\ifvisible \visibletrue + +\newtoks\everysettrialtypesetting +\newtoks\everyresettrialtypesetting + +\permanent\protected\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so +\permanent\protected\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 sometimes makes sense to +%D limit the precission. The next macro rounds a real number to two digits. It takes +%D one argument and only works in \ETEX. + +\permanent\def\integerrounding #1{\clf_rounded\zerocount\numexpr#1\relax} +\permanent\def\onedigitrounding #1{\clf_rounded\plusone \numexpr#1\relax} +\permanent\def\twodigitrounding #1{\clf_rounded\plustwo \numexpr#1\relax} +\permanent\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 \protected\def\starthans% +%D {\processcontent{stophans}\test{\message{\test}\wait}} +%D \stoptyping + +\permanent\protected\def\processcontent#1% + {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname} + +\protected\def\syst_helpers_process_content#1#2#3% + {\protected\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. + +\permanent\tolerant\protected\def\dogobblesingleempty [#-]{} +\permanent\tolerant\protected\def\dogobbledoubleempty[#-]#*[#-]{} + +\aliased\let\gobblesingleempty\dogobblesingleempty % also used +\aliased\let\gobbledoubleempty\dogobbledoubleempty % also used + +%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 assignment inside a box. +%D The \type {\empty}'s permits gobbling while preventing spurious \type {\relax}'s. + +\permanent\protected\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick + {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty} + +\permanent\protected\def\freezedimensionwithunit#1#2% + {\setdimensionwithunit\privatescratchdimen#1{#2}\edef#1{\the\privatescratchdimen}} + +%D \macros +%D {doifsometokselse, doifsometoks} +%D +%D Not that fast I guess, but here's a way to test for token registers being empty. + +\permanent\protected\def\doifelsesometoks#1% + {\iftok#1\emptytoks + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\permanent\protected\def\doifsometoks#1% + {\iftok#1\emptytoks + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\doifemptytoks#1% + {\iftok#1\emptytoks + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\aliased\let\doifsometokselse\doifelsesometoks + +%D \macros +%D {startstrictinspectnextcharacter} +%D +%D This one is for the bibliography module (still?): + +\let\syst_helpers_strict_inspect_next_character[ + +\def\syst_helpers_strict_inspect_next_character% no user macro ! + {\ifx\nexttoken[% + \expandafter\m_syst_action_yes + \else + \expandafter\m_syst_action_nop + \fi} + +\permanent\protected\def\strictdoifelsenextoptional#1#2% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% + \futurelet\nexttoken\syst_helpers_strict_inspect_next_character} + +\aliased\let\strictdoifnextoptionalelse\strictdoifelsenextoptional + +%D \macros +%D {gobblespacetokens} +%D +%D This macro needs a speed-up! + +%\def\gobblespacetokens +% {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do ! + +\permanent\def\gobblespacetokens + {\afterassignment\nexttoken\let\nexttoken=} + +%D \macros +%D {verbatimargument} +%D +%D As the name says, this macro converts its argument to a (rather safe) string. + +\aliased\let\verbatimstring\detokenize + +%D These are needed in ordinal number conversions: + +\permanent\def\lastdigit#1% + {\expandafter\thelastdigit\number#1\relax} + +\permanent\def\thelastdigit#1#2% + {\ifx#2\relax#1\else\expandafter\thelastdigit\expandafter#2\fi} + +\permanent\def\lasttwodigits#1% + {\expandafter\thelasttwodigits\expandafter0\number#1\relax} + +\permanent\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 + +\mutable\let\serializedcommalist\empty + +\def\syst_helpers_serialize_comma_list_step#1% + {\edef\serializedcommalist{\serializedcommalist#1}} + +\permanent\protected\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 number, especially in +%D full expandable macros where using \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 with a space- and +%D relax-less \type {\purenumber}. This macro works ok with \type {\the}, \type +%D {\number} as well as \ETEX's \type {\numexpr}. + +\permanent\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 macros mood}. + +\permanent\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} + +\permanent\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} + +\permanent\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} + +\permanent\tolerant\protected\def\definemeasure[#1]#*[#2]{\defcsname \??measure#1\endcsname{#2}} +\permanent\tolerant\protected\def\freezemeasure[#1]#*[#2]{\edefcsname\??measure#1\endcsname{\the\dimexpr#2}} + +\permanent\protected\def\setmeasure #1#2{\defcsname \??measure#1\endcsname{#2}} % quick way +\permanent\protected\def\setgmeasure#1#2{\gdefcsname\??measure#1\endcsname{#2}} % quick way +\permanent\protected\def\setemeasure#1#2{\edefcsname\??measure#1\endcsname{\the\dimexpr#2}} % quick way +\permanent\protected\def\setxmeasure#1#2{\xdefcsname\??measure#1\endcsname{\the\dimexpr#2}} % quick way + +\permanent\def\measure {\the\measured} +\permanent\def\measured#1{\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} + +% #2 could be omitted, but we want to support spaces +% +% \setmeasure {x} {1cm} +% \setmeasure {xx} {1cm} +% \setmeasure {xxx}{1cm} + +%D \macros +%D {definequantity} +%D +%D These do the same but for numbers. + +\installsystemnamespace{quantity} + +\permanent\tolerant\protected\def\definequantity[#1]#*[#2]{\defcsname \??quantity#1\endcsname{#2}} +\permanent\tolerant\protected\def\freezequantity[#1]#*[#2]{\edefcsname\??quantity#1\endcsname{\the\numexpr#2}} + +\permanent\protected\def\setquantity #1#2{\defcsname \??quantity#1\endcsname{#2}} % quick way +\permanent\protected\def\setgquantity#1#2{\gdefcsname\??quantity#1\endcsname{#2}} % quick way +\permanent\protected\def\setequantity#1#2{\edefcsname\??quantity#1\endcsname{\the\numexpr#2}} % quick way +\permanent\protected\def\setxquantity#1#2{\xdefcsname\??quantity#1\endcsname{\the\numexpr#2}} % quick way + +\permanent\def\quantity {\the\quantitied} +\permanent\def\quantitied #1{\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\def\directquantity#1{\the\numexpr#1\relax} + +% let\quantified\quantitied + +%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 + +\permanent\def\dividedsize#1#2#3% size gap n + {\dimexpr + \ifnum\dimexpr#1\relax>\plusone + (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1% + \fi + \relax} + +%D \macros +%D {doifdimensionelse} +%D +%D This is a dirty one: we simply append a unit and discard it when needed. + +\permanent\def\doifelsedimension#1% + {\ifchkdim#1\or + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifdimensionelse\doifelsedimension + +%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 + +\aliased\let\doifelsedimenstring\doifelsedimension +\aliased\let\doifdimenstringelse\doifelsedimenstring + +%D \macros +%D {comparedimension,comparedimensioneps} +%D +%D We no longer use the \MKIV\ dirty trick. These are obsolete anyway. + +\newdimen \roundingeps \roundingeps=10sp +\newconstant\compresult + +\permanent\def\comparedimension#1#2% + {\compresult + \ifdim#1<#2% + \zerocount + \orelse\ifdim#1<#2% + \plusone + \else + \plustwo + \fi} + +\permanent\def\comparedimensioneps#1#2% todo: use eps feature + {\compresult + \ifdim\dimexpr#1-#2\relax<\roudingeps + \zerocount + \orelse\ifdim\dimexpr#2-#1\relax<\roudingeps + \zerocount + \orelse\ifdim#1<#2% + \plusone + \else + \plustwo + \fi} + +% pretty ugly but fast + +% \copycsname xxx\endcsname\csname ..\endcsname + +\permanent\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} + +% \letcscsname \crap \csname ..\endcsname +% \letcsnamecs \csname ..\endcsname\crap +% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname + +\permanent\protected\def\letcscsname {\expandafter\let\expandafter} +\permanent\protected\def\letcsnamecs {\expandafter\let} +\permanent\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} + +% another one, add an item to a commalist + +\permanent\protected\def\addvalue#1#2% cs item + {\ifcsname#1\endcsname\else\letcsname#1\endcsname\empty\fi + \normalexpanded{\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}} + +%D Are these ever used? Anyway, these variants are somewhat more efficient than +%D the \MKIV variants for larger strings. + +% A variant: +% +% \permanent\def\unspaced#1% +% {\localcontrolled{\begingroup\catcode\spaceasciicode\ignorecatcode}% +% \tokenized{#1}% +% \localcontrolled{\endgroup}} +% +% but we can also do this: + +\permanent\def\unspaced#1% + {\tokenized \s!catcodetable \ctdcatcodes {#1}} + +\permanent\protected\def\unspaceargument#1\to#2% + {\edef#2{\tokenized \s!catcodetable \ctdcatcodes {#1}}} + +\permanent\protected\def\unspaceafter#1#2% + {\expandafter#1\expandafter{\tokenized \s!catcodetable \ctdcatcodes {#2}}} + +\permanent\protected\def\doifelsehasspace#1% + {\expandafter\ifhastok\space{#1}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifhasspaceelse\doifelsehasspace + +% this will replace loadfile once and alike !!! todo + +\installsystemnamespace{flag} + +\permanent\protected\def\setflag #1{\dodoglobal\letcsname\??flag#1\endcsname\zerocount} +\permanent\protected\def\resetflag#1{\dodoglobal\letcsname\??flag#1\endcsname\plusone} + +\permanent\def\flag#1{\csname\??flag#1\endcsname} + +\permanent\def\doifelseflagged#1% + {\expandafter\ifx\csname\??flag#1\endcsname\relax + \expandafter\secondoftwoarguments + \orelse\ifcase\csname\??flag#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifflaggedelse\doifelseflagged + +\permanent\def\doifnotflagged#1% + {\expandafter\ifx\csname\??flag#1\endcsname\relax + \expandafter\firstofoneargument + \orelse\ifcase\csname\??flag#1\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\protected\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey + {\defcsname#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\privatescratchcounter + \endgroup + \doubleexpandafter\secondoftwoarguments + \else + \endgroup + \doubleexpandafter\firstoftwoarguments + \fi + \else + \endgroup + \expandafter\secondoftwoarguments + \fi} + +% used ? + +\permanent\def\doifelsenonzeropositive#1% + {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\privatescratchcounter=0#1\relax\empty\end} + +\aliased\let\doifnonzeropositiveelse\doifelsenonzeropositive + +% here ? + +\protected\def\dosetrawvalue #1#2#3{\defcsname #1#2\endcsname{#3}} +\protected\def\dosetrawevalue#1#2#3{\edefcsname #1#2\endcsname{#3}} +\protected\def\dosetrawgvalue#1#2#3{\global\defcsname #1#2\endcsname{#3}} +\protected\def\dosetrawxvalue#1#2#3{\global\edefcsname#1#2\endcsname{#3}} + +\permanent\protected\def\getrawparameters {\dogetparameters\dosetrawvalue } +\permanent\protected\def\getraweparameters {\dogetparameters\dosetrawevalue} +\permanent\protected\def\getrawgparameters {\dogetparameters\dosetrawgvalue} +\permanent\protected\def\getrawxparameters {\dogetparameters\dosetrawxvalue} + +\permanent\protected\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete + +%D Sort of obsolete: + +\newcount\c_syst_helpers_mod + +\permanent\protected\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} + +\permanent\protected\def\dosetdivision#1#2#3% + {#3#1\divide#3 #2\relax} + +\permanent\protected\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}} +\permanent\protected\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}} + +\def\syst_helpers_unprotected#1\par + {#1\protect} + +\permanent\protected\def\unprotected + {\unprotect + \syst_helpers_unprotected} + +\aliased\let\resettimer \clf_resettimer % todo: at lua end +\aliased\let\elapsedtime \clf_elapsedtime % todo: at lua end +\aliased\let\elapsedseconds\elapsedtime + +\let\elapsedsteps\!!zerocount + +\permanent\protected\def\elapsedsteptime % unexpanded ! a bit useless but who knows ... + {\clf_elapsedsteptime\elapsedsteps\relax} + +\newcount\c_syst_helpers_test_feature_n +\newcount\c_syst_helpers_test_feature_m + +\def\currentfeaturetest{\number\c_syst_helpers_test_feature_n} + +\permanent\protected\def\testfeature#1#2% + {\c_syst_helpers_test_feature_m#1\relax + \xdef\elapsedsteps{\number\c_syst_helpers_test_feature_m}% + \def\syst_helpers_test_feature_yes + {\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_yes + \fi}% + \def\syst_helpers_test_feature_nop + {\advance\c_syst_helpers_test_feature_n\plusone + \ifnum\c_syst_helpers_test_feature_n>\c_syst_helpers_test_feature_m\else + \expandafter\syst_helpers_test_feature_nop + \fi}% + \retestfeature} + +\permanent\protected\def\retestfeature % timer support is new per 10/5/2005 + {\bgroup + \ifcase\interactionmode\let\wait\relax\fi + \clf_resettimer + \c_syst_helpers_test_feature_n\zerocount + \syst_helpers_test_feature_nop + \clf_benchmarktimer + \writestatus\m!system + {starting feature test: % + \number\c_syst_helpers_test_feature_m\space steps}% + \c_syst_helpers_test_feature_n\zerocount + \syst_helpers_test_feature_yes + \writestatus\m!system + {feature test done: % + \number\c_syst_helpers_test_feature_m\space steps, % + \clf_elapsedtime\space seconds, % + \clf_elapsedsteptime\elapsedsteps\space\space per step}% + \egroup} + +\permanent\protected\def\showtimer#1% + {\writestatus{runtime}{\elapsedseconds\space s / #1}} + +\permanent\protected\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 + +\permanent\protected\def\freezedimenmacro#1% + {\edef#1{\the\dimexpr#1}} + +%D The next macro negates a macro (dimension or number, or actually, whatever. It's +%D 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 +%D +%D Do we still need this? If not it will go away: + +\permanent\def\negated#1{\if-#1\else-#1\fi} % does only work in macros or text + +\def\gobbleassigndimen#1\\{} + +\permanent\def\assigndimen#1#2% + {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\} + +%D Maybe ... toksapp should deal with this ... + +\permanent\protected\def\appendvalue #1#2% + {\defcsname#1\expandafter\expandafter\expandafter\endcsname\expandafter\expandafter\expandafter + {\begincsname#1\endcsname#2}} + +\permanent\protected\def\prependvalue #1#2% + {\edefcsname#1\endcsname + {\normalunexpanded{#2}\expandafter\expandafter\expandafter\empty\begincsname#1\endcsname}} + +\permanent\protected\def\appendgvalue #1#2{\global\appendvalue} +\permanent\protected\def\prependgvalue#1#2{\global\prependvalue} + +%D \macros +%D {dowithrange} +%D +%D This one is for Mojca Miklavec, who made me aware of the fact that \type +%D {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 + \ifempty\m_syst_helpers_range_to\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}}}% + +\permanent\protected\def\processranges[#1]#2% #1= n:m,p,q:r + {\def\m_helpers_range_action{#2}% + \processcommacommand[#1]\syst_helpers_with_range} + +\permanent\protected\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 + +\permanent\protected\def\ignoreimplicitspaces + {\doifelsenextchar\relax\relax\relax} + +%D \macros +%D {processwords} +%D +%D Not that sophisticated but sometimes users (like in metafun). + +%D This will be overloaded. + +\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 + +\permanent\protected\def\startnointerference % not even grouped ! + {\setbox\b_syst_helpers_no_interference\vbox + \bgroup} + +\permanent\protected\def\stopnointerference + {\egroup + \setbox\b_syst_helpers_no_interference\emptybox} + +%D A variant for \type {\executeifdefined}: + +\permanent\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 is not +%D set in the font! (This will be overloaded) + +\protected\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. + +\permanent\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 + +\permanent\def\docheckedpair#1% + {\syst_helpers_checked_pair#1,,\_o_e_p_} + +% \def\syst_helpers_checked_pair#1,#2,#0\_o_e_p_ +% {#1,#2} + +\def\syst_helpers_checked_pair#1,#2,#-\_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). + +\permanent\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} + +\permanent\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} + +\permanent\def\constantdimen#1% + {\ifdim#1=\zeropoint + \zeropoint + \else + \the#1\relax + \fi} + +\permanent\def\constantdimenargument#1% + {\ifdim#1=\zeropoint + \zeropoint + \else + {\the#1}% + \fi} + +\permanent\def\constantemptyargument#1% + {\ifempty#1% + \noexpand\empty + \else + {#1}% + \fi} + +%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: + +\permanent\def\getsubstring#1#2#3{\clf_getsubstring{#3}{#1}{#2}} + +%D Other dimensions than pt (used in mb-mp) + +\permanent\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}} + +% \protected\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 +% \orelse\ifx\m_case_temp\s!default +% \expandafter\firstofoneargument +% \else +% \expandafter\syst_aux_case_nop +% \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 +\permanent\def\ntimes#1#2{\clf_ntimes{#1}\numexpr#2\relax} % 0.33 + +%D Experiment (sometimes looks nicer in code): + +\permanent\protected\def\sameargumentscondition#1#2% + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two} + +\permanent\protected\def\emptyargumentcondition#1% + {\edef\m_syst_string_one{#1}% + \ifempty\m_syst_string_one} + +%D New (also serves as an example): +%D +%D \starttyping +%D \commandflags\defineframed +%D \stoptyping + +\permanent\def\commandflags#1% + {\beginlocalcontrol\begingroup\scratchtoks\emptytoks\donefalse + \ifflags#1= \frozenflagcode\etoksapp\scratchtoks{\ifdone \space\fi frozen}\donetrue\fi + \ifflags#1=\permanentflagcode\etoksapp\scratchtoks{\ifdone \space\fi permanent}\donetrue\fi + \ifflags#1=\immutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi immutable}\donetrue\fi + \ifflags#1=\primitiveflagcode\etoksapp\scratchtoks{\ifdone \space\fi primitive}\donetrue\fi + \ifflags#1= \mutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi mutable}\donetrue\fi + \ifflags#1=\noalignedflagcode\etoksapp\scratchtoks{\ifdone \space\fi noaligned}\donetrue\fi + \ifflags#1= \instanceflagcode\etoksapp\scratchtoks{\ifdone \space\fi instance}\donetrue\fi + %\ifflags#1= \reservedflagcode\etoksapp\scratchtoks{\ifdone \space\fi reserved}\donetrue\fi + \ifflags#1= \tolerantflagcode\etoksapp\scratchtoks{\ifdone \space\fi tolerant}\donetrue\fi + \ifflags#1=\protectedflagcode\etoksapp\scratchtoks{\ifdone \space\fi protected}\donetrue\fi + \expandafter\endgroup\expandafter\endlocalcontrol\the\scratchtoks} + +%D \macros +%D {resetmacros} +%D +%D The next macro can be used to reset a macro: +%D +%D \starttyping +%D \resetmacros[startfoo,\stopfoo] +%D \stoptyping + +\permanent\protected\def\syst_reset_macro#1% + {\overloaded\letcsname\csstring#1\endcsname\undefined} % so only frozen (instances( + +\permanent\protected\def\resetmacros[#1]% + {\processcommalist[#1]\syst_reset_macro} + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-cmp.mkxl b/tex/context/base/mkxl/syst-cmp.mkxl new file mode 100644 index 000000000..a5ebdd8e3 --- /dev/null +++ b/tex/context/base/mkxl/syst-cmp.mkxl @@ -0,0 +1,22 @@ +%D \module +%D [ file=syst-cmp, +%D version=2018.12.05, +%D title=\CONTEXT\ System Macros, +%D subtitle=Compatibility, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Some code that has been laying around for generic compatibility is (and will be) +%D moved here, for instance because tikz needs it. At some point I will make an +%D indirect interface for generic code (if needed). + +\registerctxluafile{syst-cmp}{} + +\unprotect + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-con.mkxl b/tex/context/base/mkxl/syst-con.mkxl new file mode 100644 index 000000000..ed4a4f3c5 --- /dev/null +++ b/tex/context/base/mkxl/syst-con.mkxl @@ -0,0 +1,88 @@ +%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}{} + +\unprotect + +%D \macros{lchexnumber,uchexnumber,lchexnumbers,uchexnumbers} +%D +%D In addition to the uppercase hex conversion, as needed in math families, we +%D occasionally need a lowercase one. + +\permanent\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax} +\permanent\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax} +\permanent\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax} +\permanent\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax} + +\aliased\let\hexnumber\uchexnumber + +%D \macros{octnumber} +%D +%D For \UNICODE\ remapping purposes, we need octal numbers. + +\permanent\def\octnumber#1{\clf_octnumber\numexpr#1\relax} + +%D \macros{hexstringtonumber,octstringtonumber} +%D +%D This macro converts a two character hexadecimal number into a decimal number, +%D thereby taking care of lowercase characters as well. + +\permanent\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax} +\permanent\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax} + +%D \macros{rawcharacter} +%D +%D This macro can be used to produce proper 8 bit characters that we sometimes need +%D in backends and round||trips. + +\permanent\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax} + +%D \macros{twodigits, threedigits} +%D +%D These macros provides two or three digits always: + +\permanent\def\twodigits #1{\ifnum #1<10 0\fi\number#1} +\permanent\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1} + +%D \macros{modulonumber} +%D +%D In the conversion macros described in \type {core-con} we need a wrap||around +%D method. The following solution is provided by Taco. +%D +%D The \type {modulonumber} macro expands to the mathematical modulo of a positive +%D integer. It is crucial for it's application that this macro is fully exandable. +%D +%D The expression inside the \type {\numexpr} itself is somewhat bizarre because +%D \ETEX\ uses a rounding division instead of truncation. If \ETEX's division would +%D have behaved like \TEX's normal\type {\divide}, then the expression could have +%D been somewhat simpler, like \type {#2-(#2/#1)*#1}. This works just as well, but a +%D bit more complex. + +%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} +%permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} + +%D \macros{setcalculatedsin,setcalculatedcos,setcalculatedtan} + +\permanent\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}} +\permanent\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}} +\permanent\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}} + +%D \macros{formatted,format} + +\permanent \def\formatted#1{\ctxcommand{format(#1)}} % not clf +\permanent\protected\def\format #1{\ctxcommand{format(#1)}} % not clf + +%D The \type {\modulatednumber} and \type {\realnumber} macros have been removed. + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-fnt.mkxl b/tex/context/base/mkxl/syst-fnt.mkxl new file mode 100644 index 000000000..f0f023f6e --- /dev/null +++ b/tex/context/base/mkxl/syst-fnt.mkxl @@ -0,0 +1,47 @@ +%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 + +\immutable\protected\def\fontslantperpoint {\fontdimen\plusone } +\immutable\protected\def\fontinterwordspace {\fontdimen\plustwo } +\immutable\protected\def\fontinterwordstretch{\fontdimen\plusthree} +\immutable\protected\def\fontinterwordshrink {\fontdimen\plusfour } +\immutable\protected\def\fontexheight {\fontdimen\plusfive } +\immutable\protected\def\fontemwidth {\fontdimen\plussix } +\immutable\protected\def\fontextraspace {\fontdimen\plusseven} + +\immutable\protected\def\slantperpoint {\fontdimen\plusone \font} +\immutable\protected\def\interwordspace {\fontdimen\plustwo \font} +\immutable\protected\def\interwordstretch {\fontdimen\plusthree\font} +\immutable\protected\def\interwordshrink {\fontdimen\plusfour \font} +\immutable\protected\def\exheight {\fontdimen\plusfive \font} +\immutable\protected\def\emwidth {\fontdimen\plussix \font} +\immutable\protected\def\extraspace {\fontdimen\plusseven\font} + +\aliased\let\mathaxisheight\Umathaxis % takes style + +\permanent\def\currentspaceskip{\interwordspace\s!plus\interwordstretch\s!minus\interwordshrink\relax} + +\permanent\def\currentspacevalue{\the\interwordspace + \ifzeropt\interwordstretch\else{ plus }\the\interwordstretch\fi + \ifzeropt\interwordshrink \else{ minus }\the\interwordshrink \fi} + +\permanent\def\usedspacevalue{\ifzeropt\spaceskip\the\spaceskip\else\currentspacevalue\fi} + +\permanent\def\mathstacktotal{\dimexpr\Umathstacknumup\scriptstyle+\Umathstackdenomdown\scriptstyle\relax} +\permanent\def\mathstackvgap {\Umathstackvgap\scriptstyle} + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl new file mode 100644 index 000000000..50fe1c1bb --- /dev/null +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -0,0 +1,1107 @@ +%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. +%D +%D First we define a bunch of constants. Normally we would \type {\setconstant} +%D but we're prestine and have no macros defined yet. Abstraction also makes it +%D possible to avoid the \type {^^} in the input. + +\immutable\integerdef\escapecatcode 0 +\immutable\integerdef\begingroupcatcode 1 +\immutable\integerdef\endgroupcatcode 2 +\immutable\integerdef\mathshiftcatcode 3 +\immutable\integerdef\alignmentcatcode 4 +\immutable\integerdef\endoflinecatcode 5 +\immutable\integerdef\parametercatcode 6 +\immutable\integerdef\superscriptcatcode 7 +\immutable\integerdef\subscriptcatcode 8 +\immutable\integerdef\ignorecatcode 9 +\immutable\integerdef\spacecatcode 10 +\immutable\integerdef\lettercatcode 11 +\immutable\integerdef\othercatcode 12 % finally obsolete: \let\other \othercatcode +\immutable\integerdef\activecatcode 13 % finally obsolete: \let\active\activecatcode +\immutable\integerdef\commentcatcode 14 +\immutable\integerdef\invalidcatcode 15 + +%chardef\zeroasciicode 0 +\immutable\integerdef\tabasciicode 9 +\immutable\integerdef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode +\immutable\integerdef\formfeedasciicode 12 +\immutable\integerdef\endoflineasciicode 13 % somewhat messy but this can be the active \par +\immutable\integerdef\endoffileasciicode 26 +\immutable\integerdef\spaceasciicode 32 +\immutable\integerdef\exclamationmarkasciicode 33 % ! used in namespace protection +\immutable\integerdef\doublequoteasciicode 34 % " +\immutable\integerdef\hashasciicode 35 +\immutable\integerdef\dollarasciicode 36 +\immutable\integerdef\commentasciicode 37 +\immutable\integerdef\ampersandasciicode 38 +\immutable\integerdef\singlequoteasciicode 39 % ' +\immutable\integerdef\primeasciicode 39 % ' +\immutable\integerdef\leftparentasciicode 40 +\immutable\integerdef\rightparentasciicode 41 +\immutable\integerdef\commaasciicode 44 +\immutable\integerdef\hyphenasciicode 45 +\immutable\integerdef\periodasciicode 46 +\immutable\integerdef\forwardslashasciicode 47 % / +\immutable\integerdef\colonasciicode 58 +\immutable\integerdef\lessthanasciicode 60 % < used as alternative verbatim { +\immutable\integerdef\morethanasciicode 62 % > used as alternative verbatim } +\immutable\integerdef\questionmarkasciicode 63 % ? used in namespace protection +\immutable\integerdef\atsignasciicode 64 % @ used in namespace protection +\immutable\integerdef\leftbracketasciicode 91 +\immutable\integerdef\backslashasciicode 92 % `\\ +\immutable\integerdef\rightbracketasciicode 93 +\immutable\integerdef\circumflexasciicode 94 +\immutable\integerdef\underscoreasciicode 95 +\immutable\integerdef\leftbraceasciicode 123 % `\{ +\immutable\integerdef\barasciicode 124 % `\| +\immutable\integerdef\rightbraceasciicode 125 % `\} +\immutable\integerdef\tildeasciicode 126 % `\~ +\immutable\integerdef\delasciicode 127 + +\aliased\let\percentasciicode\commentasciicode + +%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored +\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space +\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later) +%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line +\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt) +%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space +\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character +\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift +%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character +\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab +%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character +\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts +\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts +\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character +\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character +\catcode\tildeasciicode \activecatcode % `\~ tilde is active +%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid + +\chardef\statuswrite 128 % we need to get rid of this one + +%D First we need to initialization the primitives. Because \CONTEXT\ is already a +%D pretty old macro package, we have a couple of issues with respect to primitives. +%D The \ETEX\ engine added a few as did \PDFTEX. The \LUATEX\ engine added even +%D more. This means that there can be a potential clash between primitives and +%D existing macros. The most noticeable ones are: +%D +%D \starttyping +%D \protected +%D \expanded +%D \unexpanded +%D \stoptyping +%D +%D Because we had macros like that before the primitives showed up. The protection +%D related macros were there before we even knew about extensions to the engine. +%D When the expansion related ones were introduced, we originally came up with +%D different names but due to requests we used the current names, somethng that in +%D retrospect was a bad idea: they should have gotten different names in \LUATEX, if +%D only because at that time only \CONTEXT\ was using them in rolling releases. +%D Anyway, we're now stuck with this situation, and it means that one should use the +%D \type {\normal...} variants in low level code: +%D +%D \starttyping +%D \normalexpanded +%D \normalprotected +%D \normalunexpanded +%D \stoptyping +%D +%D In the end not using different names in \LUATEX\ for these kind of backfires. It +%D makes not much sense to fix this in \LUAMETATEX\ because we're now to long on the +%D road. It is actually the reason why we have the option in \LUATEX\ to alias all +%D primitives in one go using a prefix. Actually this trick could be used to recover +%D a primitive meaning: just enable it with some prefix and \type {\let} the +%D original to that. But \unknown\ we prevent that trick below. +%D +%D The code below differs from \LUATEX: in \LUAMETATEX\ all primitives are already +%D available; it cannot limit itself to being \TEX\ or \ETEX. It could not do that +%D anyway because there are differences (no backend, to mention one). + +\directlua { + local primitives = tex.extraprimitives() % "tex","etex","luatex" + tex.enableprimitives("normal",primitives) % could default to everything + function tex.enableprimitives() end % so we kind of protect what's there +} + +\immutable\def\space{ } +\immutable\def\empty{} + +\immutable\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed +\immutable\letcharcode \tildeasciicode \ % tilde +\immutable\letcharcode \spaceasciicode \space % space + +\immutable\defcsname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab +\immutable\defcsname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed +\immutable\defcsname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return + +%D For now: + +\permanent\def\gobbleoneargument#-{} % will be defined later on anyway + +%D First we define a simplified version of the \CONTEXT\ protection mechanism. Later +%D we will implement a better variant. + +\def\unprotect + {\edef\protect + {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax + \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax + \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax + \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax + \let\protect\relax}% + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\underscoreasciicode \lettercatcode} + +\let\protect\relax + +\unprotect + +%D Some pretty important definitions: + +\immutable\let\bgroup={ +\immutable\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 + +% use \chardef instead for min and max +% +% will be blocked: \newfamily \newlanguage + +\permanent\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change +\permanent\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535 +\permanent\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0 +\permanent\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023 +\permanent\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 +\permanent\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191 +\permanent\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 +\permanent\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 +\permanent\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 +\permanent\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 +\permanent\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private +\permanent\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 +\permanent\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023 + +\permanent\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read +\permanent\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write +\permanent\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context +\permanent\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert +\permanent\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context +\permanent\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context + +\permanent\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end +\permanent\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end + +\immutable\integerdef\zerocount = 0 +\immutable\integerdef\plusone = 1 +\immutable\integerdef\minusone = -1 + +\immutable\integerdef\normalpagebox = 255 % hardcoded in pdftex/xetex + +% A few traditional allocations (these might go): + +\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. + +\protected\permanent\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register} +\protected\permanent\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register} +\protected\permanent\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register} +\protected\permanent\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register} +\protected\permanent\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \integerdef\c_syst_max_allocated_register} +\protected\permanent\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register} +\protected\permanent\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \integerdef\c_syst_max_allocated_read} +\protected\permanent\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \integerdef\c_syst_max_allocated_write} +\protected\permanent\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \integerdef\c_syst_max_allocated_register} +\protected\permanent\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert} +\protected\permanent\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\integerdef\c_syst_max_allocated_language} % not needed in context +\protected\permanent\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \integerdef\c_syst_max_allocated_family} % not needed in context + +\aliased\let\newfam\newfamily + +\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might become the default + +% Watch out, for the moment we disable the check for already being defined +% later we will revert this but first all chardefs must be replaced. + +\protected\def\setconstant {} +\protected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax} + +\protected\def\newconstant#1% + {\ifx#1\relax + %\writestatus{!!!!!!!!!!}{\string #1 => RELAX}% + \unletfrozen#1% + \newcount#1% + \orelse\ifdefined#1% + %\writestatus{!!!!!!!!!!}{\string #1 => DEFINED}% + \else + \newcount#1% + \fi} + +\protected\def\setnewconstant#1{\newconstant#1#1} + +% %D The next definitions are really needed (in \CONTEXT): + +\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J} + +%D One reason to start high with allocation is that it permits us to allocate +%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a +%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 + %\protected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}} + \frozen\protected\def\writestatus#1#2{\message{#1: #2}} +\fi + +\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name + {\ifnum#1<#4\relax + \global\advance#1\plusone + \permanent\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 + \orelse\ifx#5\relax + \expandafter\syst_basics_allocate_yes + \else + \expandafter\syst_basics_allocate_nop + \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}. + +% \protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register} +% \protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register} + +%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use +%D the attributes directly but always allocate then first. For instance attribute~0 +%D is reserved for special purposes (this might change). Attributes in the range +%D 128-1023 are private and should not be touched. + +\immutable\integerdef\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone + +% \permanent\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} + +% %D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force +% %D strings instead of tokens that take more memory. +% +% \permanent\protected\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. The private ones are used in cases where we don't want to +%D intrude on normal scratch ones. + +\newcount \scratchcounter \newcount \globalscratchcounter \newcount \privatescratchcounter +\newdimen \scratchdimen \newdimen \globalscratchdimen \newdimen \privatescratchdimen +\newskip \scratchskip \newskip \globalscratchskip \newskip \privatescratchskip +\newmuskip\scratchmuskip \newmuskip\globalscratchmuskip \newmuskip\privatescratchmuskip +\newtoks \scratchtoks \newtoks \globalscratchtoks \newtoks \privatescratchtoks +\newbox \scratchbox \newbox \globalscratchbox \newbox \privatescratchbox + +\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 + +\newcount\globalscratchcounterone +\newcount\globalscratchcountertwo +\newcount\globalscratchcounterthree + +\mutable\let\scratchmacro \relax +\mutable\let\scratchmacroone\relax +\mutable\let\scratchmacrotwo\relax + +%D \macros +%D {tempstring} + +\mutable\let\tempstring\empty + +%D \macros +%D {scratchwidth, scratchheight, scratchdepth, scratchoffset, scratchdistance} +%D +%D A few more scratch dimensions: + +\newdimen\scratchwidth +\newdimen\scratchheight +\newdimen\scratchdepth +\newdimen\scratchtotal + +\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 \immutable\zeroskip 0pt plus 0pt minus 0pt +\newdimen \zeropoint \immutable\zeropoint 0pt +\newdimen \onepoint \immutable\onepoint 1pt +\newdimen \halfapoint \immutable\halfapoint 0.5pt +\newdimen \maxdimen \immutable\maxdimen 16383.99999pt % 1073741823sp +\newcount \maxcount \immutable\maxcount 2147483647 +\newdimen \onebasepoint \immutable\onebasepoint 1bp +\newdimen \scaledpoint \immutable\scaledpoint 1sp +\newdimen \thousandpoint \immutable\thousandpoint 1000pt +\newmuskip\zeromuskip \immutable\zeromuskip 0mu +\newmuskip\onemuskip \immutable\onemuskip 1mu + +\newmuskip\muquad \immutable\muquad 18mu + +\aliased\let\points \onepoint +\aliased\let\halfpoint\halfapoint + +\newtoks \emptytoks + +%D And even more: (todo: countdefs 60+). Watch out, we need a count for a negative constant +%D but can use chardefs for positive ones. Actually, because we have plenty of counters we +%D can also use counts for those. + +%immutable\integerdef\minusone -1 +\immutable\integerdef\minustwo -2 +%immutable\integerdef\zerocount 0 +%immutable\integerdef\plusone 1 +\immutable\integerdef\plustwo 2 +\immutable\integerdef\plusthree 3 +\immutable\integerdef\plusfour 4 +\immutable\integerdef\plusfive 5 +\immutable\integerdef\plussix 6 +\immutable\integerdef\plusseven 7 +\immutable\integerdef\pluseight 8 +\immutable\integerdef\plusnine 9 +\immutable\integerdef\plusten 10 +\immutable\integerdef\pluseleven 11 +\immutable\integerdef\plustwelve 12 +\immutable\integerdef\plussixteen 16 +\immutable\integerdef\plusfifty 50 +\immutable\integerdef\plushundred 100 +\immutable\integerdef\plusonehundred 100 +\immutable\integerdef\plustwohundred 200 +\immutable\integerdef\plusfivehundred 500 +\immutable\integerdef\pluscxxvii 127 +\immutable\integerdef\pluscxxviii 128 +\immutable\integerdef\pluscclv 255 +\immutable\integerdef\pluscclvi 256 +\immutable\integerdef\plusthousand 1000 +\immutable\integerdef\plustenthousand 10000 +\immutable\integerdef\plustwentythousand 20000 +\immutable\integerdef\medcard 32768 +\immutable\integerdef\maxcard 65536 % pdftex has less mathchars +\immutable\integerdef\maxcardminusone 65535 + +%D \macros +%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded} +%D +%D A few handy shortcuts + +\permanent\let\singleexpandafter \expandafter +\permanent\def\doubleexpandafter{\expandafter\expandafter\expandafter} +\permanent\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter} + +%D We prefer the more readable variant than in plain \TEX. User should only +%D use \type {\emptybox}: + +\newbox\voidbox % public + +\permanent\def\unvoidbox{\unhbox\voidbox} +\permanent\def\emptybox {\box \voidbox} % used in initializations so no attributes +\permanent\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes +\permanent\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes + +\aliased\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode + +%D \macros +%D {dontcomplain} +%D +%D We need this one soon: + +\permanent\protected\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. + +\aliased\let\p@ \onepoint +\aliased\let\m@ne \minusone +\aliased\let\z@ \zeropoint +\aliased\let\@ne \plusone +\aliased\let\tw@ \plustwo +\aliased\let\thr@@ \plusthree +\aliased\let\sixt@@n\plussixteen +\aliased\let\@cclv \pluscclv +\aliased\let\@cclvi \pluscclvi +\aliased\let\voidb@x\voidbox + +\newtoks \toks@ %scratchtoks + +%D We define \type {\newif} a la plain \TEX, but will redefine it later. As Knuth +%D says: +%D +%D \startnarrower +%D And here's a different sort of allocation: for example, +%D +%D \starttyping +%D \newif\iffoo +%D \stoptyping +%D +%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}. +%D \stopnarrower + +% \protected\def\newif#1% +% {\count@\escapechar +% \escapechar\minusone +% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }% +% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}% +% \new_if#1{false}% the condition starts out false +% \escapechar\count@} +% +% \def\new_if#1#2% +% {\csname\expandafter\if@\string#1#2\endcsname} +% +% \bgroup % `if' is required +% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}} +% \egroup + +% We use \csstring so there is no need to push/pop escapechar. +% We use different names so that we get a better error message. +% +% \protected\def\newif#1% +% {\let\new_if_saved\newif +% \let\newif\new_if_check +% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }% +% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}% +% \new_if_cs#1{false}% +% \let\newif\new_if_saved} +% +% \protected\def\new_if_cs#1#2% +% {\csname\expandafter\newif\csstring#1#2\endcsname} +% +% We wrap all into one macro (the frozen stuff adds 10% runtime): + +\permanent\protected\def\newif#1% + {\permanent\protected\gdefcsname\expandafter\new_if_check\csstring#1true\endcsname {\overloaded\frozen\let#1\iftrue }% + \permanent\protected\gdefcsname\expandafter\new_if_check\csstring#1false\endcsname{\overloaded\frozen\let#1\iffalse}% + \csname\expandafter\new_if_check\csstring#1false\endcsname} + +\normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}} + +%D Let's test this one: + +\newif\ifdone +\newif\iffound + +\newif\ifscratchcondition +\newif\ifscratchconditionone +\newif\ifscratchconditiontwo + +\let\htdp\boxtotal + +%D A few shortcuts: + +% \permanent\protected\def\udef {\protected\def } +% \permanent\protected\def\ugdef{\protected\gdef} +% \permanent\protected\def\uedef{\protected\edef} +% \permanent\protected\def\uxdef{\protected\xdef} + +% For now: + +\permanent\protected\def\defUmathtopaccent #1#2#3#4{\global\immutable\protected\def#1{\Umathaccent "#2 "#3 "#4 }} +\permanent\protected\def\defUmathbotaccent #1#2#3#4{\global\immutable\protected\def#1{\Umathbotaccent "#2 "#3 "#4 }} +\permanent\protected\def\defUdelimiterover #1#2#3#4{\global\immutable\protected\def#1{\Udelimiterover "#2 "#3 }} +\permanent\protected\def\defUdelimiterunder #1#2#3#4{\global\immutable\protected\def#1{\Udelimiterunder "#2 "#3 }} +\permanent\protected\def\defUdelimiter #1#2#3#4{\global\immutable\protected\def#1{\Udelimiter "#2 "#3 "#4 }} +\permanent\protected\def\defUradical #1#2#3{\global\immutable\protected\def#1{\Uradical "#2 "#3 }} +\permanent\protected\def\defUroot #1#2#3{\global\immutable\protected\def#1{\Uroot "#2 "#3 }} +\permanent\protected\def\defUmathchar #1#2#3#4{\global\immutable\Umathchardef #1 "#2 "#3 "#4 } + +%D For a while we keep the following, as systems like tikz need it. Best not use +%D that one \CONTEXT. + +\aliased\let\active\activecatcode + +%D Constants to be used with \type {\interactionmode}. + +\immutable\integerdef\batchmodecode \zerocount +\immutable\integerdef\nonstopmodecode \plusone +\immutable\integerdef\scrollmodecode \plustwo +\immutable\integerdef\errorstopmodecode \plusthree + +%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 + +\permanent\protected\def\tracingall + {\tracingonline \plusone + \tracingcommands \plusthree + \tracingmacros \plustwo + \tracingoutput \plusone + \tracingpages \plusone + \tracingparagraphs\plusone + \tracingrestores \plusone + \tracinggroups \plusone + \tracingifs \plusone + \tracingnesting \plustwo + \tracingassigns \plustwo + \tracingmath \plusone + \tracingalignments\plusone + \showboxbreadth \maxcount + \showboxdepth \maxcount} + +\permanent\protected\def\loggingall + {\tracingall + \tracingonline \zerocount} + +\permanent\protected\def\tracingnone + {\showboxdepth \plusthree + \showboxbreadth \plusfive + \tracingalignments\zerocount + \tracingmath \zerocount + \tracingassigns \zerocount + \tracingnesting \zerocount + \tracingifs \zerocount + \tracinggroups \zerocount + \tracingrestores \zerocount + \tracingparagraphs\zerocount + \tracingpages \zerocount + \tracingoutput \zerocount + \tracingmacros \zerocount + \tracingcommands \zerocount + \tracingonline \zerocount} + +%D When we want to see a box we can as well show all of it. + +\showboxdepth \maxdimen +\showboxbreadth\maxdimen + +%D Just for tracing purposes we set: + +\tracingstats\plusone + +%D This is only used when we load \CONTEXT: + +\permanent\def\pushoverloadmode + {\edef\popoverloadmode{\overloadmode\the\overloadmode}% + \overloadmode\zerocount} + +\newtoks\everydump + +\pushoverloadmode + +\protected\def\dump + {\the\everydump + \global\everydump\emptytoks + \pushoverloadmode + \glet\dump\relax + \popoverloadmode + %let\pushoverloadmode\relax + %let\popoverloadmode\relax +% \tracingall + \normaldump} + +\permanent\protected\def\input + {\normalinput} + +\popoverloadmode + +%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: + +\aliased\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef +\aliased\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef + +% \permanent\protected\def\settrue #1{\integerdef#1\conditionaltrue } +% \permanent\protected\def\setfalse#1{\integerdef#1\conditionalfalse} +% +% \permanent\protected\def\settruevalue #1{\expandafter\integerdef\csname#1\endcsname\conditionaltrue } +% \permanent\protected\def\setfalsevalue#1{\expandafter\integerdef\csname#1\endcsname\conditionalfalse} + +\permanent\protected\def\settrue #1{\enforced\let#1\conditionaltrue } +\permanent\protected\def\setfalse #1{\enforced\let#1\conditionalfalse} +\permanent\protected\def\setconditional#1{\enforced\let#1} + +\permanent\protected\def\settruevalue #1{\enforced\letcsname#1\endcsname\conditionaltrue } +\permanent\protected\def\setfalsevalue#1{\enforced\letcsname#1\endcsname\conditionalfalse} + + +\aliased\let\newconditional\setfalse +\aliased\let\ifconditional \ifcase + +\aliased\let\then\relax % so that we can say: \ifnum1>2\then -) + +\permanent\def\truecondition {\iftrue} +\permanent\def\falsecondition{\iffalse} + +% This one has to be unprotected otherwise we get a files-ends-to-soon but it's ok +% as conditions expand anyway. + +\permanent\def\quitcondition{\orelse\iffalse} + +%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. + +\permanent\protected\def\newmacro #1{\let#1\empty} +\permanent\protected\def\setnewmacro#1{\let#1} + +\permanent\protected\def\newfraction#1{\let#1\!!plusone} + +\def\!!zerocount{0} % later redefined +\def\!!plusone {1} % later redefined + +%D It would be handy to have a primitive \type {\unless\ifcase} because then we +%D could use nicer values. Anyhow, this conditional code used to be in the \type +%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 + +\aliased\let\ifzeropt\ifcase + +% these token list helpers might move to syst-aux.mkiv +% +% we assume a \cs. not toks0 or so +% +% \protected\def\appendtotoks #1#{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=} +% \protected\def\prependtotoks#1#{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=} + +\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp + +\permanent\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=} +\permanent\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=} + +% \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}} +% \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}} + +\permanent\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=} +\permanent\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=} + +\def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}} +\def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}} + +\def\syst_toks_append_g {\global\syst_toks_append_l } +\def\syst_toks_prepend_g{\global\syst_toks_prepend_l} + +\permanent\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next} +\permanent\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next} + +\def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp} +\def\syst_toks_add_g{\global\syst_toks_add_l} + +\permanent\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes +\permanent\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes + +%D \macros +%D {begcsname} +%D +%D Handy for \ETEX-only usage (avoids making \type {\relax}'s: + +% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi} + +\aliased\let\begcsname\begincsname + +%D Now come a few macros that might be needed in successive loading. We redefine the +%D \type {\par} primitive pretty soon so that we get the equivalents right. + +% too tricky: \par is use more often than a par starts so we have too much change +% that we get assymetrical behaviour +% +% \newtoks\everyendpar +% +% \protected\def\endpar{\the\everyendpar\normalpar} +% \protected\def\par {\endpar} +% +% \protected\def\reseteverypar +% {\everypar \emptytoks +% \everyendpar\emptytoks} + +\permanent\protected\def\reseteverypar + {\everypar\emptytoks} + +\aliased\let\endgraf\par % plain, a kind of funny name +%aliased\let\endline\cr % plain, not needed and probably also confusing + +\permanent\protected\def\null{\hpack{}} + +%D The following two might be overloaded later on but some modules need then +%D earlier. These functionality is reflected in the name and will not change. + +% \bgroup +% \catcode`\^^M=\activecatcode% +% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}% +% \glet^^M\par% +% \egroup +% +% \bgroup +% \gdef\obeyspaces{\catcode`\ \activecatcode}% +% \obeyspaces\glet =\space% +% \egroup + +\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par } % check if these can be \permanent +\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} % check if these can be \permanent + +% %D A constant: +% +% \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}. + +\permanent\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go + +%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type +%D {\repeat} skippable (clever trick): + +\permanent\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: + +\permanent\countdef\pageno\zerocount \pageno\plusone % first page is number 1 + +%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides +%D the value. + +\permanent\def\folio{\the\pageno} % kind of expected and therefore reserved + +%D The following registers are kind of standard and (for the moment) we define +%D them here. This might change. + +\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 Sometimes kerns make more sense than glue but we need to be in the +%D right mode: + +\permanent\protected\def\vkern {\ifhmode\par \fi\kern} +\permanent\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} + +\permanent\protected\def\vpenalty{\ifhmode\par \fi\penalty} +\permanent\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} + +%D Again a few kind-of-extensions the core. These come from plain \TEX\ but +%D are probably not used in \CONTEXT. + +\newskip \hideskip \hideskip = -1000pt plus 1fill +\newskip \centering \centering = 0pt plus 1000pt minus 1000pt + +\permanent\def\hidewidth % for alignment entries that can stick out + {\hskip\hideskip} + +\permanent\def\ialign % initialized \halign + {\everycr\emptytoks + \tabskip\zeroskip + \halign} + +\newcount \mscount + +\permanent\def\spanomit{\span\omit} % bypass error message + +\permanent\def\multispan#1% + {\omit + \mscount#1\relax + \loop + \ifnum\mscount>\plusone + \spanomit \advance\mscount\minusone + \repeat} + +\let\nopdfcompression \relax % later +\let\onlypdfobjectcompression\relax % later +\let\maximumpdfcompression \relax % later +\let\normalpdfcompression \relax % later + +%D Basic status stuff. + +% \newif\ifproductionrun % already defined + +%D For those who expect this \unknown + +\ifx\fmtname \undefined \immutable\def\fmtname {ConTeXt Initial TeX} \fi +\ifx\fmtversion\undefined \immutable\def\fmtversion{3.1415926} \fi + +%D A few bonus macros: + +%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} +\permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} +\permanent\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax} + +%D These could be set at the \LUA\ end instead: + +\immutable\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}} +\immutable\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}} +\immutable\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}} + +%D We have no reason not to enable this: + +\savingvdiscards\plusone + +%D We only can set this one via directives (system.synctex) and we only support +%D the context variant. This will go away completely. + +\newcount\synctex % \let\normalsynctex\synctex + +%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero. + +% \voffset\zeropoint \overloaded\let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset +% \hoffset\zeropoint \overloaded\let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset + +\matheqnogapstep\zerocount % for now + +%D Now we define a few helpers that we need in a very early stage. We have no +%D message system yet but redundant definitions are fatal anyway. + +\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes + +\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>} +%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet + +\protected\def\installsystemnamespace#1% will be redefined + {\ifcsname ??#1\endcsname + \immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}% + \else + \global\advance\c_syst_helpers_n_of_namespaces\plusone + \immutable\edefcsname ??#1\endcsname{\v_interfaces_prefix_template_system}% + \fi} + +%D It makes more sense to have these here: + +\aliased\let\normalsuperscript \Usuperscript +\aliased\let\normalsubscript \Usubscript +\aliased\let\normalnosuperscript\Unosuperscript +\aliased\let\normalnosubscript \Unosubscript +\aliased\let\normalstartimath \Ustartmath +\aliased\let\normalstopimath \Ustopmath +\aliased\let\normalstartdmath \Ustartdisplaymath +\aliased\let\normalstopdmath \Ustopdisplaymath + +%D Also better here: + +\immutable\def\wildcardsymbol{*} + +%D For a while we will keep these useless numbers as for instance tikz checks for them: + +\immutable\integerdef\eTeXversion 2 +\immutable\def \eTeXrevision {2} + +%D Experiment: + +\glyphdimensionsmode\plusone + +%D Just in case users use this: + +\aliased\let\immediateassign \immediate +\aliased\let\immediateassigned\localcontrolled + +%D Needed: + +\mutable\let\nexttoken \relax +\mutable\let\next \relax +\mutable\let\nextnext \relax +\mutable\let\nextnextnext\relax + +%D For now here: will get a proper solution + +\pushoverloadmode +\mutable\let\par\par +\popoverloadmode + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-lua.lmt b/tex/context/base/mkxl/syst-lua.lmt new file mode 100644 index 000000000..673c99ae3 --- /dev/null +++ b/tex/context/base/mkxl/syst-lua.lmt @@ -0,0 +1,434 @@ +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 load, type, tonumber = load, type, tonumber +local find, gsub = string.find, string.gsub +local concat = table.concat +local utfchar = utf.char +local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat + +local xmath = xmath or math +local xcomplex = xcomplex or { } + +local scan_next = token.scan_next or token.get_next +local scan_cmdchr = token.scan_cmdchr_expanded +local scan_token = token.scan_token + +local get_csname = token.get_csname +----- get_macro = token.get_macro +----- put_next = token.put_next + +local cmd = tokens.commands +local letter_code = cmd.letter +local other_char_code = cmd.other_char +local spacer_code = cmd.spacer +local other_char_code = cmd.other_char +local relax_code = cmd.relax +local register_int_code = cmd.register_int +local internal_int_code = cmd.internal_int +local register_dimen_code = cmd.register_dimen +local internal_dimen_code = cmd.internal_dimen +local register_glue_code = cmd.register_glue +local internal_glue_code = cmd.internal_glue +local register_toks_code = cmd.register_toks +local internal_toks_code = cmd.internal_toks +local char_given_code = cmd.char_given +local math_given_code = cmd.math_given +local xmath_given_code = cmd.xmath_given +local some_item_code = cmd.some_item + +local getdimen = tex.getdimen +local getglue = tex.getglue +local getcount = tex.getcount +local gettoks = tex.gettoks +local gettex = tex.get + +local context = context +commands = commands or { } +local commands = commands +local context = context +local implement = interfaces.implement +local dimenfactors = number.dimenfactors + +local ctx_protected_cs = context.protected.cs -- more efficient +local ctx_firstoftwoarguments = context.firstoftwoarguments +local ctx_secondoftwoarguments = context.secondoftwoarguments +local ctx_firstofoneargument = context.firstofoneargument +local ctx_gobbleoneargument = context.gobbleoneargument + +implement { -- will be overloaded later + name = "writestatus", + arguments = "2 strings", + actions = logs.status, +} + +function commands.doifelse(b) + if b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doifelsesomething(b) + if b and b ~= "" then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doif(b) + if b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifsomething(b) + if b and b ~= "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifnot(b) + if b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end +end + +function commands.doifnotthing(b) + if b and b ~= "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + 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, + public = true, +} + +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 = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end + end +} + +implement { + name = "doifsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + end +} + +implement { + name = "doifnotsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + end +} + +-- This is a bit of a joke as I never really needed floating point expressions (okay, +-- maybe only with scaling because there one can get numbers that are too large for +-- dimensions to deal with). Of course one can write a parser in \TEX\ speak but then +-- one also needs to implement a bunch of functions. It doesn't pay of so we just +-- stick to the next gimmick. It looks inefficient but performance is actually quite +-- efficient. + +do + + local result = { "return " } + local word = { } + local r = 1 + local w = 0 + + local report = logs.reporter("system","expression") + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function expression() + local w = 0 + local r = 1 + while true do + local n, i = scan_cmdchr() + if n == letter_code then + w = w + 1 ; word[w] = utfchar(i) + else + if w > 0 then + -- we could use a metatable for all math, complex and factors + local s = concat(word,"",1,w) + local d = dimenfactors[s] + if d then + r = r + 1 ; result[r] = "*" + r = r + 1 ; result[r] = 1/d + else + if xmath[s] then + r = r + 1 ; result[r] = "xmath." + elseif xcomplex[s] then + r = r + 1 ; result[r] = "xcomplex." + end + r = r + 1 ; result[r] = s + end + w = 0 + end + if n == other_char_code then + r = r + 1 ; result[r] = utfchar(i) + elseif n == spacer_code then + -- r = r + 1 ; result[r] = " " + elseif n == relax_code then + break + elseif n == register_int_code or n == internal_int_code then + r = r + 1 ; result[r] = getcount(i) + elseif n == register_dimen_code or n == internal_dimen_code then + r = r + 1 ; result[r] = getdimen(i) + elseif n == register_glue_code or n == n == register_dimen_code_glue_code then + r = r + 1 ; result[r] = getglue(i) + elseif n == register_toks_code or n == n == register_dimen_code_toks_code then + r = r + 1 ; result[r] = gettoks(i) + elseif n == char_given_code or n == math_given_code or n == xmath_given_code then + r = r + 1 ; result[r] = i + elseif n == some_item_code then + local n = get_csname(t) + if n then + local s = gettex(n) + if s then + r = r + 1 ; result[r] = s + else + unexpected(c) + end + else + unexpected(c) + end + -- elseif n == call_code then + -- local n = get_csname(t) + -- if n then + -- local s = get_macro(n) + -- if s then + -- r = r + 1 ; result[r] = s + -- else + -- unexpected(c) + -- end + -- else + -- unexpected(c) + -- end + -- elseif n == the_code or n == convert_code or n == lua_expandable_call_code then + -- put_next(t) + -- scan_token() -- expands + else + unexpected(c) + end + end + end + local code = concat(result,"",1,r) + local func = load(code) + if type(func) == "function" then + context(func()) + else + report("invalid lua %a",code) + end + end + + implement { + public = true, + name = "expression", + actions = expression, + } + +end + +do + + -- This is some 20% slower than native but we only provide this for compatibility + -- reasons so we don't care that much about it. Eventually we can drop the + -- built-in method. + + local channels = { } + + local findbinfile = resolvers.findbinfile + local loadbinfile = resolvers.loadbinfile + local opentexfile = resolvers.opentexfile + + local scaninteger = tokens.scanners.integer + local scankeyword = tokens.scanners.keyword + local scanstring = tokens.scanners.string + local scancsname = tokens.scanners.csname + + local setmacro = tokens.setters.macro + local vrbcatcodes = tex.vrbcatcodes + + implement { + name = "openin", + public = true, + usage = "value", + actions = function() + local n = scaninteger() + scankeyword("=") + local s = scanstring(true) + local c = channels[n] + if c then + c:close() + end + local f = findbinfile(s,"tex") + if f then + channels[n] = opentexfile(f) + else + channels[n] = false + end + end, + } + + implement { + name = "closein", + public = true, + usage = "value", + actions = function() + local n = scaninteger() + local c = channels[n] + if c then + c:close() + end + channels[n] = false + end, + } + + implement { + name = "read", + public = true, + usage = "value", + actions = function(prefix) + local n = scaninteger() + scankeyword("to") + local m = scancsname(true) + local c = channels[n] + local s = c and c:reader() + if s then + s = gsub(s," *$"," ") -- or just "", no need to fake tex here + else + channels[n] = false + -- s = "\\par" + s = "" -- no need to fake tex here + end + setmacro(m, s, prefix) -- checks for frozen + end, + } + + implement { + name = "readline", + public = true, + usage = "value", + actions = function(prefix) + local n = scaninteger() + scankeyword("to") + local m = scancsname(true) + local c = channels[n] + local s = c and c:reader() + if s then + -- should we strip spaces at the end? + else + channels[n] = false + s = "" + end + setmacro(vrbcatcodes, m, s, prefix) -- checks for frozen + end, + } + + local boolean_value = tokens.values.boolean + + implement { + name = "ifeof", + public = true, + usage = "condition", + actions = function() + local n = scaninteger() + return boolean_value, not channels[n] + end, + } + + -- for the moment here: + + local getnest = tex.getnest + + implement { + name = "ifmvl", + public = true, + usage = "condition", + actions = function() + return boolean_value, getnest("ptr") == 0 + end, + } + +end diff --git a/tex/context/base/mkxl/syst-lua.mkxl b/tex/context/base/mkxl/syst-lua.mkxl new file mode 100644 index 000000000..158682399 --- /dev/null +++ b/tex/context/base/mkxl/syst-lua.mkxl @@ -0,0 +1,104 @@ +%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}{autosuffix} + +\unprotect + +\permanent\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}} +\permanent\def\expdoif #1#2{\clf_doifsame {#1}{#2}} +\permanent\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} + +%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road +%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type +%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see +%D other useful applications. + +\permanent\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} +\permanent\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\permanent\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} + +% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3 +% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5 + +\permanent\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} +\permanent\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}} + +\aliased\let\expdoifcommonelse\expdoifelsecommon +\aliased\let\expdoifinsetelse \expdoifelseinset + +%D We define these here, just in case. This permits \typefile {self} otherwise +%D nested b|/|e sep problems. + +\immutable\def\luastringsep{===} + +\immutable\edef\!!bs{[\luastringsep[} +\immutable\edef\!!es{]\luastringsep]} + +\pushoverloadmode + +\permanent\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}} + +\popoverloadmode + +%D We can omit the tex.ctxcatcodes here as nowadays we seldom change the regime at +%D the \TEX\ end: + +%def\luaexpr#1{\ctxlua{context (tostring(#1))}} % more efficient: +\permanent\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled + +%D But as we only use write 16 we could as well do all in \LUA\ and ignore the rest. +%D Okay, we still can do writes here but only when not blocked. + +\aliased\let\syst_write_execute\clf_execute % always {...} + +%D There is a probably rather useless \type {\expression} command that can mix \LUA\ numeric +%D expressions with \TEX\ commands (for as far that makes sense) that works like this: +%D +%D \starttyping +%D \mathchardef\foooo 1234 +%D \def \mymacro {123.45} +%D \scratchdimen 123pt +%D \scratchskip 123pt +%D \scratchtoks {34} +%D +%D \testfeatureonce{10000}{\edef\foo{\expression +%D round( +%D 12.3 * \scratchdimen +%D - (12.3 * \scratchskip) / 2 +%D + 2 ^ 3 +%D * ( +%D - sqrt(12) +%D - 10pt +%D - \foooo +%D + \luatexversion +%D - \mymacro +%D + \scratchtoks +%D + \the\scratchcounter +%D + \number\scratchcounter +%D ) +%D ) +%D \relax}} +%D +%D \expression string.format("\letterpercent f",\elapsedtime/50000) \relax +%D \stoptyping +%D +%D The final \type {\relax} is mandate because we also accept spaces. Of course we +%D could have avoided it by using outer parenthesis but this is cleaner anyway. +%D +%D The \LMTX\ version supports te \type {xmath} and \type {xcomplex} functions and +%D therefore one can have expressions that don't work in \MKIV. + +% maybe: \let\texexpr\expression + +\protect \endinput diff --git a/tex/context/base/mkxl/syst-mac.lmt b/tex/context/base/mkxl/syst-mac.lmt new file mode 100644 index 000000000..410a49f8b --- /dev/null +++ b/tex/context/base/mkxl/syst-mac.lmt @@ -0,0 +1,117 @@ +if not modules then modules = { } end modules ['syst-mac'] = { + 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" +} + +-- This is kind of tricky and might not work for all csnames but as long as we use +-- it in a controlled way, we're okay. The engine implementation might be changed +-- a bit (no need to go through strings, but fetching a cs index and passing that +-- back also takes time). + +-- Another approach is to have the predefined stack operate use private stacks and +-- then the pop doesn't need the cs. But ... we then also need to store stuff in +-- the format so that complicates maters more than I'm willing to do. + +local insert, remove = table.insert, table.remove + +local push_macro = token.push_macro +local pop_macro = token.pop_macro +local scan_csname = token.scan_csname +local create_token = token.create +local gobble_token = token.gobble + +local context = context +local implement = interfaces.implement + +local report = logs.reporter("system","macrostack") + +local stack = table.setmetatableindex("table") + +local function pushmacro(name,global) + local s = push_macro(name,global) + if s then + insert(stack[name],s) + else + report("no macro %a to push",name) + insert(stack[name],false) + end +end + +local function popmacro(name) + local s = remove(stack[name]) + if s then + pop_macro(s) + else + report("no macro %a to pop",name) + end +end + +tokens.pushmacro = pushmacro +tokens.popmacro = popmacro + +implement { + name = "localpushmacro", + public = true, + protected = true, + actions = function() + pushmacro(scan_csname()) + end +} + +implement { + name = "globalpushmacro", + public = true, + protected = true, + actions = function() + pushmacro(scan_csname(),true) + end +} + +implement { + name = "localpopmacro", + public = true, + protected = true, + actions = function() + popmacro(scan_csname()) + end +} + +implement { + name = "globalpopmacro", + public = true, + protected = true, + actions = function() + popmacro(scan_csname()) + end +} + +implement { + name = "showmacrostack", + public = true, + protected = true, + actions = function() + local n = scan_csname() + local s = stack[n] + local m = #s + report("%s : %i stack slots used",n,m) + for i=1,m do + report("% 3i %S",i,s[i]) + end + end +} + +implement { + name = "gobblenested", + public = true, + protected = true, + arguments = "3 strings", + actions = function(start,stop,command) + gobble_token(create_token(start),create_token(stop)) + if command then + context[command]() + end + end +} diff --git a/tex/context/base/mkxl/syst-mes.mkxl b/tex/context/base/mkxl/syst-mes.mkxl new file mode 100644 index 000000000..166be16e3 --- /dev/null +++ b/tex/context/base/mkxl/syst-mes.mkxl @@ -0,0 +1,20 @@ +%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. + +% These will be overloaded later on: + +\protected\def\writestring{\immediate\write\statuswrite} +\protected\def\writeline {\writestring{}} +% \let\message \normalmessage + +\endinput diff --git a/tex/context/base/mkxl/syst-pln.mkxl b/tex/context/base/mkxl/syst-pln.mkxl new file mode 100644 index 000000000..38ec9c4c1 --- /dev/null +++ b/tex/context/base/mkxl/syst-pln.mkxl @@ -0,0 +1,119 @@ +%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\ values. Later they might +%D be overloaded. There is not much difference between \MKII\ and \MKIV\ but at some +%D point they 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/tex/context/base/mkxl/syst-rtp.mkxl b/tex/context/base/mkxl/syst-rtp.mkxl new file mode 100644 index 000000000..73aa59ba9 --- /dev/null +++ b/tex/context/base/mkxl/syst-rtp.mkxl @@ -0,0 +1,18 @@ +%D \module +%D [ file=syst-rtp, +%D version=2006.10.13, +%D title=\CONTEXT\ Core Macros, +%D subtitle=Run Time Processes, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 + +\aliased\let\executesystemcommand\clf_execute % can be public implementor + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-com.mkxl b/tex/context/base/mkxl/tabl-com.mkxl new file mode 100644 index 000000000..791db656b --- /dev/null +++ b/tex/context/base/mkxl/tabl-com.mkxl @@ -0,0 +1,92 @@ +%D \module +%D [ file=tabl-com, +%D version=2009.08.22, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Common Code, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Common Code} + +\unprotect + +\pushoverloadmode + +% maybe frozen instead + +\permanent\let\AR\relax +\permanent\let\BA\relax +\permanent\let\BC\relax +\permanent\let\BH\relax +\permanent\let\BL\relax +\permanent\let\BR\relax +\permanent\let\CC\relax +\permanent\let\CL\relax +\permanent\let\CM\relax +\permanent\let\CR\relax +\permanent\let\DB\relax +\permanent\let\DC\relax +\permanent\let\DL\relax +\permanent\let\DR\relax +\permanent\let\DV\relax +\permanent\let\EH\relax +\permanent\let\EQ\relax +\permanent\let\ER\relax +\permanent\let\FB\relax +\permanent\let\FL\relax +\permanent\let\FR\relax +\permanent\let\HC\relax +\permanent\let\HL\relax +\permanent\let\HQ\relax +\permanent\let\HR\relax +\permanent\let\LB\relax +\permanent\let\LC\relax +\permanent\let\LT\relax +\permanent\let\LL\relax +\permanent\let\LR\relax +\permanent\let\MC\relax +\permanent\let\ML\relax +\permanent\let\MR\relax +\permanent\let\NA\relax +\permanent\let\NB\relax +\permanent\let\NC\relax +\permanent\let\ND\relax +\permanent\let\NF\relax +\permanent\let\NG\relax +\permanent\let\NI\relax +\permanent\let\NL\relax +\permanent\let\NN\relax +\permanent\let\NP\relax +\permanent\let\NR\relax +\permanent\let\PB\relax +\permanent\let\RC\relax +\permanent\let\RQ\relax +\permanent\let\SL\relax +\permanent\let\SM\relax +\permanent\let\SR\relax +\permanent\let\TB\relax +\permanent\let\TL\relax +\permanent\let\TR\relax +\permanent\let\VL\relax +\permanent\let\VC\relax +\permanent\let\VD\relax +\permanent\let\VN\relax +\permanent\let\VS\relax +\permanent\let\VT\relax +\permanent\let\XC\relax + +\popoverloadmode + +\installmacrostack\BC +\installmacrostack\EC +\installmacrostack\EQ +\installmacrostack\NC +\installmacrostack\NN +\installmacrostack\NR + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-frm.mkxl b/tex/context/base/mkxl/tabl-frm.mkxl new file mode 100644 index 000000000..9bbc510c5 --- /dev/null +++ b/tex/context/base/mkxl/tabl-frm.mkxl @@ -0,0 +1,261 @@ +%D \module +%D [ file=tabl-frm, +%D version=2017.04.11, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Framed Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D For Thomas Schmitz who needed 3000 pages long tables. + +\unprotect + +\writestatus{loading}{ConTeXt Table Macros / Framed Tables} + +\installcorenamespace{framedtable} +\installcorenamespace{framedtablerow} +\installcorenamespace{framedtablecolumn} + +\newcount\c_tabl_framed_c +\newcount\c_tabl_framed_r +\newdimen\d_tabl_framed_h +\newdimen\d_tabl_framed_d +\newdimen\b_tabl_framed + +\initializeboxstack\??framedtable + +\defineframed[\??framedtable] +\defineframed[\??framedtablerow][\??framedtable] +\defineframed[\??framedtablecolumn][\??framedtable] + +\setupframed + [\??framedtable] + [\c!distance=\zeropoint, + \c!before=, + \c!after=, + \c!inbetween=] + +\setupframed + [\??framedtablerow] + [\c!strut=\v!no, + \c!offset=\v!overlay] + +% \defineframedtable[foo] +% \defineframedtable[bar][foo] + +\permanent\tolerant\protected\def\defineframedtable[#1]#*[#2]% + {\ifarguments\or + \defineframed[\??framedtable#1][\??framedtable]% + \or + \defineframed[\??framedtable#1][\??framedtable#2]% + \fi} + +% \setupframedtable[foo][...] + +\permanent\tolerant\protected\def\setupframedtable[#1]#*[#2]% + {\ifarguments\or + \setupframed[\??framedtable][#1]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \setupframed[\??framedtable#1][#2]% + \fi} + +% \setupframedtable[1][...] +% \setupframedtable[foo][1][...] + +\permanent\tolerant\protected\def\setupframedtablerow[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \ifcsname\??framed:\??framedtablerow:#1\endcsname \else + \defineframed[\??framedtablerow:#1][\??framedtable]% + \fi + \setupframed[\??framedtablerow:#1][#2]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \ifcsname\??framed:\??framedtablerow#1:#2\endcsname \else + \defineframed[\??framedtablerow#1:#2][\??framedtable#1]% + \fi + \setupframed[\??framedtablerow#1:#2][#3]% + \fi} + +\permanent\tolerant\protected\def\setupframedtablecolumn[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \ifcsname\??framed:\??framedtablecolumn:#1\endcsname \else + \defineframed[\??framedtablecolumn:#1][\??framedtable]% + \fi + \setupframed[\??framedtablecolumn:#1][#2]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \ifcsname\??framed:\??framedtablecolumn#1:#2\endcsname \else + \defineframed[\??framedtablecolumn#1:#2][\??framedtable#1]% + \fi + \setupframed[\??framedtablecolumn#1:#2][#3]% + \fi} + +\permanent\tolerant\protected\def\startframedtable[#1]#*[#2]% + {\begingroup + \forgetall + \ifhastok={#1}% + \let\currentframedtable\empty + \setupframed[\??framedtable][#1]% + \else + \edef\currentframedtable{#1}% + \setupframed[\??framedtable][#2]% + \fi + \edef\currentframed{\??framedtable\currentframedtable}% + \c_tabl_framed_r\zerocount + \d_tabl_framed_d\framedparameter\c!distance + \framedparameter\c!before} + +\permanent\protected\def\stopframedtable + {\framedparameter\c!after + \endgroup} + +% a two pass variant that deals with the height .. so no catcode changes here + +\tolerant\protected\def\pack_framed_start_framed_whatever[#1]% + {\pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here ! + \pack_framed_process_indeed + \bgroup + \ignorespaces} + +% \permanent\protected\def\startframedrow +% {\advance\c_tabl_framed_r\plusone +% \c_tabl_framed_c\zerocount +% \d_tabl_framed_h\zeropoint +% \bgroup +% \edef\currentframed{\number\c_tabl_framed_r}% +% \edef\currentframed +% {\??framedtablerow\currentframedtable +% \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname +% :\currentframed +% \orelse\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname +% :\v!each +% \fi}% +% \pack_framed_start_framed_whatever} +% +% \permanent\protected\def\stopframedrow +% {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row +% \stopframed +% \nointerlineskip +% \vskip\zeropoint\relax +% \framedparameter\c!inbetween} + +\protected\def\tabl_framed_flush_row + {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% + \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} + +\newcount\c_tabl_framed_pass + +\permanent\let\stopframedrow\relax + +\permanent\protected\def\startframedrow#1\stopframedrow + {\advance\c_tabl_framed_r\plusone + \startframedrow_one#1\stopframedrow_one + \startframedrow_two#1\stopframedrow_two} + +\tolerant\def\startframedrow_one[#-]% + {\bgroup + \c_tabl_framed_pass\plusone + \c_tabl_framed_c\zerocount + \d_tabl_framed_h\zeropoint + \settrialtypesetting} + +\protected\def\stopframedrow_one + {\normalexpanded{\egroup\d_tabl_framed_h\the\d_tabl_framed_h\relax}} + +\def\startframedrow_two + {\bgroup + \c_tabl_framed_c\zerocount + \c_tabl_framed_pass\plustwo + \edef\currentframed{\number\c_tabl_framed_r}% + \edef\currentframed + {\??framedtablerow\currentframedtable + \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname + :\currentframed + \orelse\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname + :\v!each + \fi}% + \pack_framed_start_framed_whatever} + +\protected\def\stopframedrow_two + {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row + \stopframed + \nointerlineskip + \vskip\zeropoint\relax + \framedparameter\c!inbetween} + +\protected\def\tabl_framed_flush_row_two + {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% + \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} + +\permanent\protected\def\startframedcell + {\advance\c_tabl_framed_c\plusone + \setbox\b_tabl_framed\hpack\bgroup + %\bgroup + \edef\currentframed{\number\c_tabl_framed_c}% + \edef\currentframed + {\??framedtablecolumn\currentframedtable + \ifcsname\??framedtablecolumn\currentframedtable:\currentframed\endcsname + :\currentframed + \orelse\ifcsname\??framedtablecolumn\currentframedtable:\v!each\endcsname + :\v!each + \fi}% + \ifcase\c_tabl_framed_pass + \or + \letframedparameter\c!background\empty + \letframedparameter\c!frame\v!off + \or + \letframedparameter\c!height\d_tabl_framed_h + \fi + \pack_framed_start_framed_whatever} + +\permanent\protected\def\stopframedcell + {\stopframed + %\egroup + \ifcase\c_tabl_framed_pass + \or + \ifdim\ht\b_tabl_framed>\d_tabl_framed_h + \d_tabl_framed_h\ht\b_tabl_framed + \fi + \else + \savebox\??framedtable{\number\c_tabl_framed_c}{\box\b_tabl_framed}% + \fi} + +\protect \endinput + +\starttext + +\setupframedtablecolumn [1] [width=3cm,background=color,backgroundcolor=red] +\setupframedtablecolumn [2] [width=4cm,background=color,backgroundcolor=green,align=normal] +% \setupframedtablerow [each] [background=color,backgroundcolor=blue,strut=no] +% \setupframedtablerow [each] [strut=no,offset=overlay] + +\startframedtable[inbetween=\kern-0.4pt,distance=-0.4pt] + +\testfeatureonce{10000}{ +% \testfeatureonce{10}{ + \startframedrow + \startframedcell%[backgroundcolor=yellow] + test + \stopframedcell + \startframedcell + test \par test + \stopframedcell + \stopframedrow +} +\stopframedtable + +\stoptext diff --git a/tex/context/base/mkxl/tabl-ltb.mkxl b/tex/context/base/mkxl/tabl-ltb.mkxl new file mode 100644 index 000000000..f4558d797 --- /dev/null +++ b/tex/context/base/mkxl/tabl-ltb.mkxl @@ -0,0 +1,797 @@ +%D \module +%D [ file=tabl-ltb, +%D version=2002.10.31, % updated 2016.01.08 +%D title=\CONTEXT\ Table Macros, +%D subtitle=Line Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module was made for some special project where we needed to typeset tables +%D spanning spanning many pages horizontally and vertically, with repeated header +%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a +%D table, which is why the table can go into a buffer or file. As said, tables can +%D be real huge but performance is still quite okay (there is room for some speed +%D up). The code has been adapted to \MKIV\ but the functionality is the same as in +%D \MKII. + +% \BH \BC .. \EC \BC .. \EC \EH % append +% \BR \BC .. \EC \BC .. \EC \ER +% +% or +% +% \NC .. \NC .. \NC \NR (todo: optional last \NC) + +% alternative: +% +% (1) direct run, save content in macro, but only if needed +% +% todo +% +% (2) buffered table content +% +% \startbuffer +% \startlinetablehead +% \stoplinetablehead +% \startlinetablebody +% \stoplinetablebody +% \stopbuffer +% +% \processlinetablebuffer[buffer] +% +% in buffer : head and body +% +% (3) unbuffered run, multipass +% +% - run with starting width zero / prev run +% - clip on prev run +% - flush real widths + +\writestatus{loading}{ConTeXt Table Macros / Line Tables} + +\unprotect + +\installcorenamespace{linetable} +\installcorenamespace{linetablepart} +\installcorenamespace{linetablewidth} +\installcorenamespace{linetableheight} +\installcorenamespace{linetabledepth} + +\newconditional \c_tabl_lines_preroll +\newconditional \c_tabl_lines_in_table + +\newdimen \d_tabl_lines_width +\newdimen \d_tabl_lines_height +%newdimen \d_tabl_lines_depth + +\newbox \b_tabl_lines_cell + +\newcount \c_tabl_lines_n_of_columns +\newcount \c_tabl_lines_n_of_rows +\newcount \c_tabl_lines_n_of_lines +\newcount \c_tabl_lines_n_of_parts +\newcount \c_tabl_lines_part \c_tabl_lines_part\plusone +\newcount \c_tabl_lines_step \c_tabl_lines_step\plusone +\newcount \c_tabl_lines_line +\newcount \c_tabl_lines_row +\newcount \c_tabl_lines_rows +\newcount \c_tabl_lines_column +\newcount \c_tabl_lines_subcol + +\newconstant \c_tabl_lines_hmode +\newconstant \c_tabl_lines_page +\newconstant \c_tabl_lines_repeat +\newconstant \c_tabl_lines_split_state +\newconstant \c_tabl_lines_head_state +\newconstant \c_tabl_lines_mode + +\newtoks \t_tabl_lines_head + +\newconditional \linetableautoheight \settrue\linetableautoheight + +\initializetablebox\zerocount % holds repeater + +\pushoverloadmode + +\permanent\tolerant\protected\def\setuplinetable[#1]#*[#2]#*[#3]% + {\ifarguments\or + \getparameters[\??linetable][#1]% + \or + \getparameters[\??linetable#1:][#2]% + \or + \getparameters[\??linetable#1:#2][#3]% + \fi} + +\permanent\def\linetableparameter#1% + {\begincsname\??linetable#1\endcsname} + +\permanent\protected\def\doifelselinetablecparameter#1% + {\ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname + \expandafter\firstoftwoarguments + \orelse\ifcsname\??linetable c:#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflinetablecparameterelse\doifelselinetablecparameter + +\permanent\def\linetablecparameter#1% + {\begincsname + \??linetable + \ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname + c:\number\c_tabl_lines_column + \orelse\ifcsname\??linetable c:#1\endcsname + c:% + \fi + #1% + \endcsname} + +\permanent\def\linetablerparameter#1% faster, leaner and meaner + {\begincsname + \??linetable + \ifnum\c_tabl_lines_row=\zerocount % geen ifcase + \ifcsname\??linetable r:\v!header#1\endcsname + r:\v!header + \orelse\ifcsname\??linetable r:0#1\endcsname + r:0% + \fi + \else + \ifcsname\??linetable r:\number\c_tabl_lines_row#1\endcsname + r:\number\c_tabl_lines_row + \orelse\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname + r:\v!oddeven\c_tabl_lines_row + \fi + \fi + #1% + \endcsname} + +\protected\def\tabl_lines_set + {\edef\p_lines{\linetableparameter\c!lines}% + \ifx\p_lines\v!fit + \tabl_lines_set_indeed + \else + \global\c_tabl_lines_n_of_lines\p_lines + \fi} + +\protected\def\tabl_lines_set_indeed + {% whitespace already added by vertical strut + %\triggerpagebuilder + \scratchdimen + \ifdim\pagegoal<\maxdimen + \dimexpr\pagegoal-\pagetotal\relax + \else + \textheight + \fi + \getrawnoflines\scratchdimen + \global\c_tabl_lines_n_of_lines\noflines + \ifconditional\c_tabl_lines_preroll \else \ifnum\c_tabl_lines_n_of_lines<\plustwo + \page + \tabl_lines_set + \fi \fi} + +\def\tabl_lines_step_cell + {\advance\scratchdimen\linetablecparameter\c!width + \global\advance \c_tabl_lines_column\plusone + \advance\scratchskip \linetablecparameter\c!distance} + +\permanent\tolerant\protected\def\startlinetablecell[#1]% + {\global\setbox\b_tabl_lines_cell\hbox\bgroup + \ifparameter#1\or + \getparameters[\??linetable c:\number\c_tabl_lines_column][#1]% + \fi + \global\c_tabl_lines_step\linetablecparameter\c!nx\relax + \ifcase\c_tabl_lines_step\or + \scratchdimen\linetablecparameter\c!width + \scratchskip \linetablecparameter\c!distance + \else + \scratchdimen \zeropoint + \scratchskip \zeropoint + \scratchcounter\c_tabl_lines_column + \dorecurse\c_tabl_lines_step\tabl_lines_step_cell + \global\c_tabl_lines_column\scratchcounter + \fi + \c_tabl_lines_mode + \ifconditional\c_tabl_lines_preroll + \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi + \else + \zerocount + \fi + \ifcase\c_tabl_lines_mode + \ifcase\c_tabl_lines_hmode + % nothing + \or + % fit, keep it simple + \or + \c_tabl_lines_mode\plusone % line + \else + % some already calculated height + \fi + \fi + \setbox\scratchbox\hbox + \bgroup + \dontcomplain + \hskip\linetablecparameter\c!leftoffset\relax + % 0 = width, unknown height + % 1 = width, fixed height + % 2 = no width, auto hsize + \ifnum\c_tabl_lines_mode<\plustwo + \advance\scratchdimen-\linetablecparameter\c!leftoffset + \advance\scratchdimen-\linetablecparameter\c!rightoffset + \fi + \ifcase\c_tabl_lines_mode + \dosetraggedcommand{\linetablecparameter\c!align}% + \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup + \hsize\scratchdimen + \raggedcommand + \else + \setalignmentswitch{\linetablecparameter\c!align}% + \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup + \ifcase\alignmentswitch\hss\or\hss\fi + \fi + \dousestyleparameter{\linetablecparameter\c!style}% + \dousecolorparameter{\linetablecparameter\c!color}% + \begstrut \ignorespaces} + +\permanent\protected\def\stoplinetablecell + {\unskip \endstrut + \ifcase\c_tabl_lines_mode + \endgraf + \else + \ifcase\alignmentswitch\else\hss\fi + \fi + \egroup + \hskip\linetablecparameter\c!rightoffset + \egroup + \ifconditional\c_tabl_lines_preroll + \box\scratchbox + \else + \tabl_lines_wrap_up + \fi + \egroup} + +\def\tabl_lines_wrap_up + {\edef\p_background{\linetablecparameter\c!background}% + \ifx\p_background\v!color + \ifconditional\linetableautoheight + \tabl_lines_wrap_up_auto + \else + \tabl_lines_wrap_up_line + \fi + \else + \box\scratchbox + \fi} + +% \startuseMPgraphic{one} +% path p, q ; +% numeric r ; +% r := RuleThickness ; +% p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ; +% q := p topenlarged -r bottomenlarged -r ; +% draw q ; +% setbounds currentpicture to p; +% \stopuseMPgraphic +% +% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt] +% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt] +% +% \startlinetable +% \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +% \stoplinetable + +\def\tabl_lines_wrap_up_auto + {\edef\p_height{\linetablerparameter{x\c!height}}% + \edef\p_depth {\linetablerparameter{x\c!depth }}% + \hpack + {\blackrule + [ \c!color=\linetablecparameter\c!backgroundcolor, + \c!type=\linetablecparameter\c!type, + \c!mp=\linetablecparameter\c!mp, + \c!rulethickness=\linetablecparameter\c!rulethickness, + \c!height=\ifempty\p_height\ht\scratchbox\else\p_height\fi, + \c!depth=\ifempty\p_depth \dp\scratchbox\else\p_depth \fi, + \c!width=\wd\scratchbox]% + \hskip-\wd\scratchbox\box\scratchbox}} + +\def\tabl_lines_wrap_up_auto_r + {\hpack + {\blackrule + [ \c!color=\linetablerparameter\c!backgroundcolor, + \c!type=\linetablerparameter\c!type, + \c!mp=\linetablerparameter\c!mp, + \c!rulethickness=\linetablerparameter\c!rulethickness, + \c!height=\ht\scratchbox, + \c!depth=\dp\scratchbox, + \c!width=\wd\scratchbox]% + \hskip-\wd\scratchbox\box\scratchbox}} + +\def\tabl_lines_wrap_up_line + {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}} + +\def\tabl_lines_save_part + {\global\setbox\tablebox\c_tabl_lines_part + \ifcase\c_tabl_lines_part\relax + \box\scratchbox % just storing + \else + \vbox + {\ifvoid\tablebox\c_tabl_lines_part\else\unvbox\tablebox\c_tabl_lines_part\fi + \edef\p_background{\linetablerparameter\c!background}% + \ifx\p_background\v!color + \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}% + \else + \edef\p_type{\linetablerparameter\c!type}% + \ifempty\p_type + \box\scratchbox + \else + \tabl_lines_wrap_up_auto_r + \fi + \fi + \endgraf + \linetablerparameter\c!after}% + \fi} + +\def\tabl_lines_flush_parts + {\global\advance\c_tabl_lines_line\plusone + \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines + % keep collecting + \else + \ifconditional\c_tabl_lines_preroll + % forget about them + \else + \dorecurse\c_tabl_lines_n_of_parts + {\c_tabl_lines_part\recurselevel + \dp\tablebox\c_tabl_lines_part\strutdepth + % noindent en endgraf needed else whitespace mess-up! + \whitespace % here not after verticalstrut + \ifdim\topskipgap=\zeropoint\else + \verticalstrut + \nobreak + \kern-\struttotal + \kern-\parskip + \nobreak + \nointerlineskip % fix topskip + \fi + \noindent\strut + \hpack to \hsize{\box\tablebox\c_tabl_lines_part\hss}% + \endgraf + \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax + \linetableparameter\c!inbetween + \fi}% + \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows + \linetableparameter\c!inbetween + \else + % after, later + \fi + \c_tabl_lines_head_state\plusthree + \global\setbox\tablebox\zerocount\emptybox % here + \fi + % reset \c_tabl_lines_row will be an option, currently + % starts at zero after split + \global\c_tabl_lines_row\zerocount + \global\c_tabl_lines_line\zerocount + \global\c_tabl_lines_page\zerocount + \global\d_tabl_lines_width\zeropoint + \tabl_lines_set + \fi} + +\def\tabl_lines_start_part + {\global\c_tabl_lines_subcol\zerocount + \setbox\scratchbox\hbox\bgroup + \dousestyleparameter{\linetablerparameter\c!style}% + \dousecolorparameter{\linetablerparameter\c!color}% + \ignorespaces} + +\def\tabl_lines_stop_part + {\ifnum\c_tabl_lines_part>\zerocount + \unskip \unskip % remove last intercolumn skip (distance+fill) + \fi + \egroup + \ifconditional\c_tabl_lines_preroll \else + \ifcase\c_tabl_lines_part + % we're collecting the repeater + \else + \ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch\else + \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}% + \fi + \fi + \fi} + +\def\tabl_lines_check_part + {\global\advance\d_tabl_lines_width\wd\b_tabl_lines_cell + \global\advance\c_tabl_lines_column\c_tabl_lines_step + \global\advance\c_tabl_lines_subcol\c_tabl_lines_step + \relax + %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait + % from now on the column counter is already incremented + \ifcase\c_tabl_lines_split_state + \ifconditional\c_tabl_lines_preroll \else + \box\b_tabl_lines_cell + % the columncounter is one ahead ! + \hskip\scratchskip + \fi + %%% + \donefalse + \ifcase\c_tabl_lines_repeat\else + % calculate ahead + \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax + \donetrue % collecting repeater + \fi + \fi + %%%% + \ifdone + % collecting repeater + \else + \ifnum\c_tabl_lines_column>\csname\??linetablepart\number\c_tabl_lines_part\endcsname\relax + \donetrue + \fi + \fi + \ifdone + \tabl_lines_stop_part + \ifconditional\c_tabl_lines_preroll \else + \tabl_lines_save_part + \fi + \ifcase\c_tabl_lines_page \or + \global\c_tabl_lines_page \plustwo + \else + \global\c_tabl_lines_page \plusone + \fi + \global\advance\c_tabl_lines_part\plusone + \global\d_tabl_lines_width\wd\tablebox\zerocount + \tabl_lines_start_part + \fi + \else + \donefalse + \scratchconditiononefalse + \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 + \scratchconditiononetrue + % collecting repeater + \orelse\ifdim\d_tabl_lines_width>\hsize + \donetrue + \else + \global\advance\d_tabl_lines_width\scratchskip + \ifdim\d_tabl_lines_width>\hsize % ? + \donetrue + \fi + \fi + \ifdone + \tabl_lines_stop_part + \tabl_lines_save_part + \ifcase\c_tabl_lines_page \or + \global\c_tabl_lines_page \plustwo + \else + \global\c_tabl_lines_page \plusone + \fi + \global\advance\c_tabl_lines_part\plusone + \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts + \global\c_tabl_lines_n_of_parts\c_tabl_lines_part + \initializetablebox\c_tabl_lines_part + \fi + \global\d_tabl_lines_width\wd\b_tabl_lines_cell + \tabl_lines_start_part + \ifscratchconditionone \else \ifcase\c_tabl_lines_repeat \else + % check for left/right page + \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi\ifdone + % insert repeater + \global\advance\d_tabl_lines_width\wd\tablebox\zerocount + \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\tablebox\zerocount + \fi + \fi \fi + \fi + \ifconditional\c_tabl_lines_preroll \else + \box\b_tabl_lines_cell + % the columncounter is one ahead ! + %\dorecurse\c_tabl_lines_step{\strut\hfil}% + \strut + \hskip\scratchskip + \fi + \fi} + +\permanent\protected\def\startlinetablerun % to do: quit when nested + {\bgroup + \dontcomplain + \settrue\c_tabl_lines_in_table + % autowidth + \doif{\linetableparameter\c!maxwidth}\v!fit + {\setuplinetable[\c!maxwidth=\zeropoint]}% + \processaction + [\linetableparameter\c!stretch] + [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch + \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch + \c_tabl_lines_repeat\linetableparameter\c!nleft + \c_tabl_lines_split_state % = + \ifdim\linetableparameter\c!maxwidth>\zeropoint + \zerocount \else \plusone + \fi + % optional prevdepth correction + \ifconditional\c_tabl_lines_preroll + \global\c_tabl_lines_n_of_rows\zerocount + \else + \linetableparameter\c!before + \fi + \global\c_tabl_lines_rows\zerocount + \global\c_tabl_lines_n_of_columns\zerocount + \global\c_tabl_lines_n_of_parts\zerocount + \scratchcounter\zerocount + \def\docommand##1% + {\global\advance\c_tabl_lines_n_of_parts\plusone + \advance\scratchcounter##1% + \xdefcsname\??linetablepart\number\c_tabl_lines_n_of_parts\endcsname{\the\scratchcounter}}% + \processcommacommand[\linetableparameter\c!n]\docommand + \initializetableboxes\c_tabl_lines_n_of_parts + \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater + \global\c_tabl_lines_step\plusone + \global\c_tabl_lines_line\zerocount + \global\c_tabl_lines_row \zerocount + \global\c_tabl_lines_column\zerocount + \global\c_tabl_lines_subcol\zerocount + \global\d_tabl_lines_width\zeropoint + \ifconditional\c_tabl_lines_preroll \else \ifdim\pagetotal>\zeropoint + \verticalstrut\kern-\struttotal + \fi \fi + \tabl_lines_set + \tabl_lines_check_page + \enforced\let\BR\tabl_lines_BR + \enforced\let\ER\tabl_lines_ER + \enforced\let\BH\tabl_lines_BR + \enforced\let\EH\tabl_lines_ER + \enforced\let\BC\tabl_lines_BC + \enforced\let\EC\tabl_lines_EC + \enforced\let\NC\tabl_lines_NC + \enforced\let\NR\tabl_lines_NR + \tabl_lines_flush_head} + +\permanent\protected\def\stoplinetablerun + {\global\c_tabl_lines_line\maxcard + \c_tabl_lines_head_state\zerocount % blocked + \tabl_lines_flush_parts + \ifconditional\c_tabl_lines_preroll \else + \linetableparameter\c!after + \fi + \global\c_tabl_lines_part\zerocount + \global\c_tabl_lines_n_of_parts\zerocount + \egroup} + +\permanent\def\checklinecolumndimension#1#2#3% + {\global\edef#1\number#3\endcsname + {\expandafter\ifx\csname#1\number#3\endcsname\relax + \the#2\b_tabl_lines_cell + \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell + \the#2\b_tabl_lines_cell + \else + \csname#1\number#3\endcsname + \fi}} + +\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column} +\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row} +\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row} + +\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented + {\ifnum\c_tabl_lines_head_state=1\else + \global\advance\c_tabl_lines_row\plusone + \global\advance\c_tabl_lines_rows\plusone + \fi + \global\c_tabl_lines_column\plusone + \global\c_tabl_lines_subcol\plusone + \d_tabl_lines_height\zeropoint + \edef\p_height{\linetablerparameter\c!height}% + \ifempty\p_height + \c_tabl_lines_hmode \zerocount + \orelse\ifx\p_height\v!fit + \c_tabl_lines_hmode \plusone + \orelse\ifx\p_height\v!line + \c_tabl_lines_hmode \plustwo + \else + \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax + \fi + \tabl_lines_start_part} + +\permanent\protected\def\tabl_lines_BC + {\startlinetablecell} + +\permanent\protected\def\tabl_lines_EC + {\stoplinetablecell + \ifconditional\c_tabl_lines_preroll + \tabl_lines_check_width + \tabl_lines_check_height + \tabl_lines_check_depth + \fi + \tabl_lines_check_part} + +\permanent\protected\def\tabl_lines_ER + {% \stoplinetablecell + % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR + \tabl_lines_stop_part + \tabl_lines_save_part + \advance\c_tabl_lines_column \minusone + \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns + \global\c_tabl_lines_n_of_columns\c_tabl_lines_column + \fi + \tabl_lines_flush_parts + \global\c_tabl_lines_column\zerocount + \global\d_tabl_lines_width \zeropoint + \ifcase\c_tabl_lines_repeat + \global\c_tabl_lines_part\plusone + \else + \global\c_tabl_lines_part\zerocount % repeater + \fi + \tabl_lines_check_page + \tabl_lines_flush_head} + +\def\tabl_lines_check_page + {\global\c_tabl_lines_page\zerocount + \ifcase\c_tabl_lines_repeat \else \ifcase\c_tabl_lines_page + \doif{\linetableparameter\c!repeat}\v!no + {\global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo}% + \fi \fi} + +\def\tabl_lines_flush_head + {\ifcase\c_tabl_lines_head_state + % 0 blocked + \or + % 1 doing head + \or + % 2 head done + \or + % 3 trigger flush + \c_tabl_lines_head_state\plusone + \the\t_tabl_lines_head\relax + \c_tabl_lines_head_state\plustwo + \fi} + +\permanent\protected\def\tabl_lines_NC % first time special treatment + {\relax + \ifcase\c_tabl_lines_column + \tabl_lines_BR + \else + \tabl_lines_EC + \fi + \tabl_lines_BC} % beware, this will result in BR BC EC BC NR + +\permanent\protected\def\tabl_lines_NR + {\stoplinetablecell % dummy + \tabl_lines_ER} + +\permanent\protected\def\startlinetable + {\startlinetablerun} + +\permanent\protected\def\stoplinetable + {\stoplinetablerun} + +\permanent\protected\def\startlinetableanalysis + {\bgroup + \settrue\c_tabl_lines_preroll + \settrialtypesetting + \startlinetablerun} + +\permanent\protected\def\stoplinetableanalysis + {\stoplinetablerun + \egroup + \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows + \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n} + {\edefcsname\??linetable r:##1x\c!height\endcsname{\csname\??linetableheight##1\endcsname}% + \edefcsname\??linetable r:##1x\c!depth \endcsname{\csname\??linetabledepth ##1\endcsname}% + \gletcsname\??linetableheight##1\endcsname\zeropoint + \gletcsname\??linetabledepth ##1\endcsname\zeropoint} + \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n} + {\edefcsname\??linetable c:##1\c!width\endcsname{\csname\??linetablewidth##1\endcsname}% + \gletcsname\??linetablewidth##1\endcsname\zeropoint}} % init next table + +% todo: store in box instead of macro + +\aliased\let\stoplinetablehead\relax + +\permanent\protected\def\startlinetablehead#1\stoplinetablehead + {\ifconditional\c_tabl_lines_in_table + \t_tabl_lines_head\emptytoks + \fi + \c_tabl_lines_head_state\plusthree % full + \t_tabl_lines_head{#1}% + \ifconditional\c_tabl_lines_in_table + \tabl_lines_flush_head + \fi} + +\permanent\protected\def\tabl_lines_BH + {\ifx\EC\relax + % signal, grabbing lines + \else + \t_tabl_lines_head\emptytoks + \fi + \push_macro_BC + \push_macro_EC + \enforced\permanent\protected\def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}% + \enforced\permanent \let\EC\relax} % signal + +\permanent\protected\def\tabl_lines_EH + {\pop_macro_EC + \pop_macro_BC + \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead} + +\permanent\let\startlinetablebody\relax +\permanent\let\stoplinetablebody \relax + +\permanent\tolerant\protected\def\processlinetablebuffer[#1]% + {\bgroup + \enforced\let\startlinetable\relax + \enforced\let\stoplinetable \relax + \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis + \startlinetablerun \getbuffer[#1]\stoplinetablerun + \egroup} + +\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1] + {\bgroup + \enforced\let\startlinetable\relax + \enforced\let\stoplinetable \relax + \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis + \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun + \egroup} + +\popoverloadmode + +\setuplinetable + [\c!n=\maxcard, + \c!lines=\maxcard, + \c!nx=\plusone, + \c!nleft=\zerocount, + \c!repeat=\v!yes, % when nleft > 0, repeat on both pages + \c!before=, + \c!after=, + \c!inbetween=\page, + \c!distance=\zeropoint, + \c!stretch=\v!no, + \c!align=\c!right, + \c!leftoffset=.25\exheight, + \c!rightoffset=\linetableparameter\c!leftoffset, + \c!maxwidth=\zeropoint, + \c!width=5\emwidth, + \c!height=\v!fit, % \v!line = faster + \c!background=, + \c!backgroundcolor=, + \c!rulethickness=\linewidth] + +\protect + +\continueifinputfile{tabl-ltb.mkxl} + +\setuplinetable[n=6,m={2,2,2},lines=25] % m ? + +\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red] +\setuplinetable[c][4] [width=3cm,background=color,backgroundcolor=yellow] +\setuplinetable[c][6] [width=3cm,background=color,backgroundcolor=magenta] +\setuplinetable[r][odd] [background=color,backgroundcolor=gray] +\setuplinetable[r][even][background=color,backgroundcolor=green] + +\starttext + +\showframe \showstruts + +\setuppagenumbering[alternative=doublesided]\page[left] + +\startlinetable +\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR +\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +\stoplinetable + +\startlinetable +\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx + \NC yy \NC ddddd \NC eeee \NC ff \NC \NR +\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +\stoplinetable + +% \startbuffer[lt] +% \NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC ee \NC ff \NC \NR +% \NC aaa\crlf aaa \NC b \NC cc \NC ddd \NC eeee \NC f \NC \NR +% \stopbuffer +% +% \processlinetablebuffer[lt] + +\stoptext diff --git a/tex/context/base/mkxl/tabl-mis.mkxl b/tex/context/base/mkxl/tabl-mis.mkxl new file mode 100644 index 000000000..14bd08b46 --- /dev/null +++ b/tex/context/base/mkxl/tabl-mis.mkxl @@ -0,0 +1,294 @@ +%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 + +\permanent\tolerant\protected\def\somekindoftab[#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 \CONTEXT\ and +%D mostly served as a table mechanism capable of dealing with paragraphs. Nowadays +%D 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} + +\installframedcommandhandler \??paragraphs {paragraphs} \??paragraphs + +\setupparagraphs + [\c!n=3, + \c!offset=\zeropoint, + \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!frame=\v!off, + \c!top=\vss, + \c!bottom=\vfill] + +\aliased\let\typo_paragraphs_setup_saved\setupparagraphs + +\overloaded\permanent\tolerant\protected\def\setupparagraphs[#1]#*[#2]#*[#3]% we are downward compatible with [each] and [1,3] + {\ifarguments\or + \typo_paragraphs_setup_saved[#1]% + \or + \typo_paragraphs_setup_saved[#1][#2]% + \or + \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}% + \fi} + +\appendtoks + \frozen\instance\letvalue{\e!next \currentparagraphs}\nextparagraphs + \frozen\instance\letvalue\currentparagraphs\nextparagraphs + \frozen\instance\setuevalue{\e!start\currentparagraphs}{\startparagraphs[\currentparagraphs]}% + \frozen\instance\letvalue{\e!stop \currentparagraphs}\stopparagraphs + %frozen\instance\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 + +\permanent\protected\def\startparagraphs[#1]% quite slow + {\bgroup % (1) + \edef\currentparagraphs{#1}% + % \paragraphsparameter\c!before + \edef\p_width{\paragraphsparameter\c!width}% + \ifempty\p_width + \d_typo_paragraphs_width\availablehsize + \else + \d_typo_paragraphs_width\p_width\relax + \fi + \advance\d_typo_paragraphs_width-2\dimexpr\paragraphsparameter\c!offset\relax + \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}% + \ifempty\p_width + \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 + \enforced\let\\\typo_paragraphs_next % downward compatible + \edef\p_offset{\paragraphsparameter\c!offset}% + \doifelsedimension\p_offset + {\scratchoffset\p_offset}% + {\scratchoffset\zeropoint}% + \setbox\scratchbox\hpack + \bgroup % (2) + \forgetall + \advance\hsize-2\scratchoffset + \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} + +\permanent\protected\def\stopparagraphs + {\stopparagraphscell + \egroup % (2) + \letparagraphsparameter\c!align\v!flushleft % normal + \paragraphsparameter\c!before + \dontleavehmode\inheritedparagraphsframed{\box\scratchbox}% + \paragraphsparameter\c!after + \egroup} % (1) + +\permanent\protected\def\nextparagraphs + {\stopparagraphscell + \startparagraphscell} + +\permanent\protected\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 \ifempty\p_height \orelse\ifx\p_height\v!fit \else to \p_height \fi + \bgroup % (2) + \blank[\v!disable]% + \paragraphsparameter\c!top + \hsize\ifempty\p_width \d_typo_paragraphs_auto \else \p_width \fi \relax + \usealignparameter\paragraphsparameter + \paragraphsparameter\c!inner + \everypar{\begstrut\everypar\emptytoks}% + \ignorespaces + \paragraphsparameter\c!command} + +\permanent\protected\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/tex/context/base/mkxl/tabl-ntb.mkxl b/tex/context/base/mkxl/tabl-ntb.mkxl new file mode 100644 index 000000000..51e718b9a --- /dev/null +++ b/tex/context/base/mkxl/tabl-ntb.mkxl @@ -0,0 +1,2172 @@ +%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 different +%D approach with settings there, this mechanism will stay. In fact each of them has +%D its advantages. This module could be sped up a bit and made more efficient by +%D delegating some housekeeping to \LUA\ but it's not worth the effort. The code +%D could me made more readable but again, there is no real purpose in it. If needed +%D I can squeeze out a few more percentages 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 + +% \protected\def\startrow {\bTR} +% \protected\def\stoprow {\eTR} +% \protected\def\startcell#1\stopcell{\bTD#1\eTD} +% \let\stopcell \relax +% \let\startcelltable \bTABLE +% \let\stopcelltable \eTABLE + +% \starttext +% \startcelltable +% \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 trying to speed up +%D the many cell calculations, some optimizations were rejected in order not to +%D complicate this 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 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 + +\protected\def\tabl_ntb_cell_start + {% \inhibitblank + \dotagTABLEcell + %\tabl_ntb_next_level + \font_styles_math_reset + \usenaturaltablelocalstyleandcolor\c!style\c!color + \everypar\t_tabl_ntb_cell_start + \font_styles_math_start} + +\protected\def\tabl_ntb_cell_stop + {\font_styles_math_stop + \ifhmode + \the\t_tabl_ntb_cell_stop + \par % added 13/4/2006 + \orelse\ifdim\prevdepth<\zeropoint % =-1000pt ? + % not sure yet:\naturaltablelocalparameter\c!right + \vskip-\strutdp + \else + \removebottomthings + \fi} + +% maybe: +% +% \protected\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 +% \ifhmode +% % \removeunwantedspaces +% \orelse\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 For tagging and export: + +\newconstant \c_tabl_ntb_head +\newconstant \c_tabl_ntb_body +\newconstant \c_tabl_ntb_foot +\newconditional \c_tabl_ntb_okay + +%D We have already prepared the previous macros for nesting, so we only have to pop +%D in the right ones: + +\newcount\c_tabl_level + +\installglobalmacrostack\m_tabl_ntb_saved_row +\installglobalmacrostack\m_tabl_ntb_saved_col + +\protected\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}\push_macro_m_tabl_ntb_saved_row + \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\push_macro_m_tabl_ntb_saved_col + \else + \global\intabletrue + \fi} + +\protected\def\tabl_ntb_table_pop + {\ifnum\m_tabl_tbl_level>\plusone + \pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row + \pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col + \else + \global\intablefalse + \fi} + +\protected\def\tabl_ntb_next_level + {\advance\c_tabl_level\plusone + \edef\m_tabl_tbl_level{\the\c_tabl_level}} + +\protected\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 + +\permanent\protected\def\bTABLEnested{\tabl_ntb_next_level\bTABLE} +\permanent\protected\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level} + +\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{naturaltablebck} +%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{\gletcsname\??naturaltablegal\m_tabl_tbl_level\endcsname} +\def\tabl_ntb_get_gal{\csname\??naturaltablegal\m_tabl_tbl_level\endcsname} + +\def\tabl_ntb_let_tal#1{\gletcsname\??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{\letcsname\??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{\edefcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_set_col#1#2{\edefcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_set_row#1#2{\edefcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_let_tag#1#2{\letcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_let_col#1#2{\letcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_let_row#1#2{\letcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +%def\tabl_ntb_set_wd#1#2{\xdefcsname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +\def\tabl_ntb_set_ht#1#2{\xdefcsname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! + +%def\tabl_ntb_let_wd#1#2{\letcsname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +\def\tabl_ntb_let_ht#1#2{\letcsname\??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{\xdefcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_hei#1{\xdefcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_dis#1{\xdefcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_aut#1{\xdefcsname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! + +\def\tabl_ntb_let_wid#1{\gletcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_hei#1{\gletcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_dis#1{\gletcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_aut#1{\gletcsname\??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_let_bck#1#2{\global\expandafter\chardef\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_get_bck#1#2{\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\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} + +%D If we ever run into memory issues we can do: +% +% \def\tabl_ntb_let_tag#1#2#3% +% {\ifx#3\c_tabl_ntb_none\else +% \letcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname#3% +% \fi} +% +% \def\tabl_ntb_get_tag#1#2% +% {\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname +% \lastnamedcs +% \else +% \c_tabl_ntb_none +% \fi} + +\def\tabl_ntb_let_ref #1#2{\gletcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_set_ref #1#2{\xdefcsname\??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{\letcsname\??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} + +\protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% + {\defcsname\??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 + +\newconditional \c_tabl_ntb_trace_widths + +\installtextracker + {tables.natural.widths} + {\settrue \c_tabl_ntb_trace_widths} + {\setfalse\c_tabl_ntb_trace_widths} + +% so far + +\protected\def\tabl_ntb_cell_process#1#2[#3]{} + +\permanent\protected\def\bTC#1\eTC{\bTD#1\eTD} \aliased\let\eTC\relax +\permanent\protected\def\bTX#1\eTX{\bTD#1\eTD} \aliased\let\eTX\relax +\permanent\protected\def\bTY#1\eTY{\bTR#1\eTR} \aliased\let\eTY\relax + +\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal + +\permanent\tolerant\protected\def\setupTABLE[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreeoptionals + \or + \expandafter\tabl_ntb_setup_one + \or + \expandafter\tabl_ntb_setup_two + \or + \expandafter\tabl_ntb_setup_three + \fi[#1][#2][#3]} + +\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]{\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 + \enforced\def\tabl_ntb_parameters_get[##1]% + {\defcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname{\tabl_ntb_parameters_get[##1,#2]}}% + \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname + \enforced\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal + \else + \defcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname{\tabl_ntb_parameters_get[#2]}% + \fi + \else + \defcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname{\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 + +\protected\def\tabl_ntb_setup_cell#1#2% cell over col over row + {\tabl_ntb_setup_section % already forgotten + \edef\m_tabl_ntb_positive_row{\number#1}% + \edef\m_tabl_ntb_positive_col{\number#2}% + \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 + +\tolerant\protected\def\tabl_ntb_tr[#1]% + {\c_tabl_ntb_running_col\zerocount + \c_tabl_ntb_encountered_col\zerocount + \advance\c_tabl_ntb_maximum_row\plusone + \ifparameter#1\or + \expandafter\tabl_ntb_tr_yes + \else + \expandafter\gobbleoneoptional + \fi[#1]} + +\def\tabl_ntb_tr_yes[#1]% + {\defcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_maximum_row\endcsname{\setupcurrentnaturaltablelocal[#1]}} + +\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr} +\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc} + +\tolerant\protected\def\tabl_ntb_td[#1]% + {\advance\c_tabl_ntb_encountered_col\plusone + \ifparameter#1\or + \expandafter\tabl_ntb_td_yes + \else + \expandafter\tabl_ntb_td_nop + \fi[#1]} + +\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}% + % + \ifempty\m_tabl_ntb_n + \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax + \orelse\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else + \tabl_ntb_td_pass_n{#1}% + \fi + \ifempty\m_tabl_ntb_m \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 + +\tolerant\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} + +\tolerant\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 added +%D 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 as well as +%D the columndistance (although i changed the names -). Here 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 foot, dus state var + +\aliased\let\eTABLEhead\relax +\aliased\let\eTABLEnext\relax +\aliased\let\eTABLEbody\relax +\aliased\let\eTABLEfoot\relax + +\permanent\tolerant\protected\def\bTABLEhead[#1]#:#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} +\permanent\tolerant\protected\def\bTABLEnext[#1]#:#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} +\permanent\tolerant\protected\def\bTABLEbody[#1]#:#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} +\permanent\tolerant\protected\def\bTABLEfoot[#1]#:#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} + +\def\tabl_ntb_section[#1]#2% also used in tabl-nte + {\protected\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} + +\permanent\tolerant\protected\def\bTABLE[#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 + \enforced\let\bTR\tabl_ntb_bTR + \enforced\let\bTD\tabl_ntb_bTD + \enforced\let\bTH\tabl_ntb_bTH + \enforced\let\bTN\tabl_ntb_bTN} + +\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 + +% there is no gain in a \doifelsenextoptionalcs variant + +% todo with tolerant: + +\permanent\tolerant\protected\def\tabl_ntb_bTR{\tabl_ntb_tr} % also used in tabl-nte +\permanent\tolerant\protected\def\tabl_ntb_bTD{\tabl_ntb_td} % also used in tabl-nte +\permanent\tolerant\protected\def\tabl_ntb_bTH{\tabl_ntb_th} % also used in tabl-nte +\permanent\tolerant\protected\def\tabl_ntb_bTN{\tabl_ntb_tn} % also used in tabl-nte + +% permits \expanded{\bTD ... \eTD} + +\permanent\let\bTR\relax \permanent\protected\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows +\permanent\let\bTD\relax \permanent\protected\def\eTD{\ignorespaces} +\permanent\let\bTH\relax \permanent\protected\def\eTH{\ignorespaces} +\permanent\let\bTN\relax \permanent\protected\def\eTN{\ignorespaces} + +\permanent\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode + {% tricky and dirty order -) + \setfalse\c_tabl_ntb_okay + % head + \doifelsesometoks\t_tabl_ntb_head % slow, better a flag + {\c_tabl_ntb_head\numexpr\c_tabl_ntb_maximum_row+\plusone\relax + \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_head\zerocount + \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}% + % body + \c_tabl_ntb_body\numexpr\c_tabl_ntb_maximum_row+\plusone\relax + \the\t_tabl_ntb_body + % foot + \doifelsesometoks\t_tabl_ntb_foot + {\c_tabl_ntb_foot\numexpr\c_tabl_ntb_maximum_row+\plusone\relax + \the\t_tabl_ntb_foot}% + {\c_tabl_ntb_foot\zerocount}% + % done + \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 + \etoksapp\t_tabl_ntb + {% no need for init + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} + +\def\tabl_ntb_row_stop_split + {\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname + \tabl_ntb_row_stop_split_yes + \else + \tabl_ntb_row_stop_split_nop + \fi} + +\def\tabl_ntb_row_stop_split_nop + {\etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_reset + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} + +\def\tabl_ntb_row_stop_split_yes + {\begingroup + \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 + \etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}% + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} + +\protected\def\tabl_ntb_row_align_set#1#2#3% + {\xdef\m_tabl_ntb_before_split{#1}% + \xdef\m_tabl_ntb_after_split {#2}% + \xdef\m_tabl_ntb_same_page {#3}} + +\protected\def\tabl_ntb_row_align_reset + {\glet\m_tabl_ntb_before_split\empty + \glet\m_tabl_ntb_after_split \empty + \glet\m_tabl_ntb_same_page \empty} + +\def\tabl_ntb_prelocate_error + {\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}} + +% \prelocateTBLrows{1000} % may speed up large tables + +\permanent\protected\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway + {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone + {\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}% + \def\tabl_ntb_row_start + {\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 + {\etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_start + \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname + \tabl_ntb_row_align_stop}}% + \global\c_tabl_prelocated_rows#1\relax} + +\def\tabl_ntb_prelocate_okay + {\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks} + +%D We use aligments to handle the empty (skipped) columns, so that we don't have to +%D (re|)|calculate these. + +\let\m_tabl_ntb_saved_row\!!zerocount +\let\m_tabl_ntb_saved_col\!!zerocount + +\def\tabl_ntb_start_tagged + {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax + \ifnum\scratchcounter=\c_tabl_ntb_head + \ifconditional\c_tabl_ntb_okay + \dostoptagged + \else + \settrue\c_tabl_ntb_okay + \fi + \dostarttagged\t!tablehead\empty + \orelse\ifnum\scratchcounter=\c_tabl_ntb_body + \ifconditional\c_tabl_ntb_okay + \dostoptagged + \else + \settrue\c_tabl_ntb_okay + \fi + \dostarttagged\t!tablebody\empty + \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot + \ifconditional\c_tabl_ntb_okay + \dostoptagged + \else + \settrue\c_tabl_ntb_okay + \fi + \dostarttagged\t!tablefoot\empty + \fi + \dostarttagged\t!tablerow\empty} + +\def\tabl_ntb_stop_tagged + {\dostoptagged + \ifconditional\c_tabl_ntb_okay + \scratchcounter\numexpr\c_tabl_ntb_row+\plustwo\relax + \ifnum\scratchcounter=\c_tabl_ntb_body + \dostoptagged + \setfalse\c_tabl_ntb_okay + \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot + \dostoptagged + \setfalse\c_tabl_ntb_okay + \orelse\ifnum\scratchcounter>\c_tabl_ntb_maximum_row + \dostoptagged + \setfalse\c_tabl_ntb_okay + \fi + \fi} + +\protected\def\tabl_ntb_row_align_start + {\global\advance\c_tabl_ntb_row\plusone + \global\c_tabl_ntb_col\plusone + \global\c_tabl_ntb_spn\zerocount + \tabl_ntb_row_align_start_inject + \ifconditional\c_strc_tags_enabled + \tabl_ntb_start_tagged + \fi + \hbox\bgroup + \kern\dimexpr\d_tabl_ntb_leftmargindistance\relax} + +\protected\def\tabl_ntb_row_align_stop + {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax + \egroup + \ifconditional\c_strc_tags_enabled + \tabl_ntb_stop_tagged + \fi + \tabl_ntb_row_align_stop_inject} + +\protected\def\tabl_ntb_before_page + {\ifx\m_tabl_ntb_same_page\v!before + % \blank[\v!samepage,\v!strong]% + \unpenalty + \nobreak + \orelse\ifx\m_tabl_ntb_same_page\v!both + % \blank[\v!samepage,\v!strong]% + \unpenalty + \nobreak + \fi} + +\protected\def\tabl_ntb_after_page + {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines + \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount + \unpenalty + \ifx\m_tabl_ntb_same_page\v!after + % \blank[\v!samepage,\v!strong]% + \nobreak + \orelse\ifx\m_tabl_ntb_same_page\v!both + % \blank[\v!samepage,\v!strong]% + \nobreak + \else + % \blank[\v!preference,\v!weak]% + \allowbreak + \fi + \fi + \else + % \blank[\v!preference,\v!weak]% + \allowbreak % else no proper head split off + \fi} + +\protected\def\tabl_ntb_inbetween + {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax + \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax + \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax + \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}% + \ifempty\p_spaceinbetween\else + \blank[\p_spaceinbetween]% + \fi + \fi + \fi} + +\protected\def\tabl_ntb_row_align_start_inject + {\bgroup % protect local vars + \m_tabl_ntb_before_split + \egroup + \ifenableTBLbreak + \tabl_ntb_before_page + \fi} + +\protected\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} + +\protected\def\tabl_ntb_span#1% + {\hskip\tabl_ntb_get_dis\c_tabl_ntb_col + \dorecurse{#1} + {\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax + \global\advance\c_tabl_ntb_col\plusone}} + +\protected\def\tabl_ntb_skip#1% + {\global\advance\c_tabl_ntb_col#1\relax} + +\protected\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 + \etoksapp\t_tabl_ntb_row + {\tabl_ntb_span{\the\scratchcounter}}% + \fi} + +\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2% + {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens + \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax + \ifnum\scratchcounter>\zerocount + \etoksapp\t_tabl_ntb_row + {\ifnum\scratchcounter=\plusone + \tabl_ntb_plus + \else + \tabl_ntb_skip{\the\scratchcounter}% + \fi}% + \fi} + +\protected\def\tabl_ntb_cell#1#2% + {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}} + +\protected\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 + \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax + \ifcase\scratchcounterone\or + \advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + \relax + \advance\scratchcounter\plusone + \else + \dorecurse\scratchcounterone + {\advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + \ifnum\recurselevel<\scratchcounterone + +\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 + \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax + \scratchcountertwo\tabl_ntb_get_row{#1}{#2}\relax + \scratchheight\tabl_ntb_get_ht {#1}{#2}\relax + \tablecellcolumns\scratchcounterone % used later so don't adapt these + \tablecellrows \scratchcountertwo % used later so don't adapt these + \d_tabl_ntb_height\zeropoint + \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax + % case: nc=maxcolumns + \else + \scratchcounter#1\relax + \dorecurse\scratchcountertwo + {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter + \advance\scratchcounter\plusone}% + \ifdim\d_tabl_ntb_height<\scratchheight\relax + \d_tabl_ntb_height\scratchheight + \fi + \fi + % width + \d_tabl_ntb_width\zeropoint + \scratchcounter\c_tabl_ntb_col + \ifcase\scratchcounterone\or + \advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + \relax + \advance\scratchcounter\plusone + \else + \dorecurse\scratchcounterone + {\advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + \ifnum\recurselevel<\scratchcounterone + +\d_tabl_ntb_columndistance + +\tabl_ntb_get_dis\scratchcounter + \fi + \relax + \advance\scratchcounter\plusone}% + \fi + % cell + \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged \bgroup + \dotagTABLEsignal % maybe we need to add some packaging in this case + \tabl_ntb_get_txt{#1}{#2}% + \egroup + \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax + % case: nc=maxcolumns + \else + \scratchdimen\tabl_ntb_get_hei{#1}% + \setbox\scratchbox\hpack + {\lower\ht\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}}% + \ht\scratchbox\scratchdimen + \fi + \dp\scratchbox\zeropoint + \edef\scratchmacro{\tabl_ntb_get_ref{#1}{#2}}% + \ifempty\scratchmacro + \box\scratchbox + \else + \normalexpanded{\directgotobox{\box\scratchbox}[\scratchmacro]}% to be checked + \fi + \dostoptagged} % right spot + +\def\tabl_ntb_cell_finalize + {\ifx\localwidth\v!fit + % nothing + \orelse\ifx\localwidth\v!broad + % nothing + \orelse\ifempty\localwidth + % nothing (safeguard) + \else + \tabl_ntb_cell_finalize_indeed + \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_get_max_width + {\scratchdimen\wd\scratchbox\relax} + +% enable dper 2018-02-22 + +\def\tabl_ntb_table_get_max_width_step + {\advance\scratchdimen\tabl_ntb_get_wid\fastloopindex + \advance\scratchdimen\tabl_ntb_get_dis\fastloopindex} + +\def\tabl_ntb_table_get_max_width + {\scratchdimen\zeropoint + \dofastloopcs\c_tabl_ntb_maximum_col\tabl_ntb_table_get_max_width_step + \ifdim\scratchdimen<\wd\scratchbox\relax + \scratchdimen\wd\scratchbox\relax + \fi} + +\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 + % + \tabl_ntb_table_get_max_width % \scratchdimen\scratchbox + % + \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}% + % \orelse\ifdim\wd\scratchbox>\hsize + \orelse\ifdim\scratchdimen>\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 + \orelse\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 + \hsize\scratchdimen\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 + \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_ntb_split_nop + \orelse\ifenableTBLbreak + \tabl_ntb_split_yes + \else + \tabl_ntb_split_nop + \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 + \scratchdimenfour\zeropoint + \scratchdimenfive\dimexpr + \hsize + -\d_tabl_ntb_leftmargindistance + -\d_tabl_ntb_rightmargindistance + +\d_tabl_ntb_columndistance + \relax + \dorecurse\c_tabl_ntb_maximum_col + {\advance\scratchdimenfour\dimexpr + \tabl_ntb_get_wid\recurselevel + \relax + \advance\scratchdimenfive\dimexpr + -\tabl_ntb_get_dis\recurselevel + -\d_tabl_ntb_columndistance + \relax}% + \relax + % distribute width (stretch) + \ifdim\scratchdimenfour<\scratchdimenfive + \advance\scratchdimenfour-\scratchdimenfive + \divide\scratchdimenfour\c_tabl_ntb_maximum_col + \dorecurse\c_tabl_ntb_maximum_col + {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel-\scratchdimenfour\relax}}% + \fi + \fi} + +\def\tabl_ntb_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 + % no \dontleavehmode else too wide, otherwise we get a \hsized box + \else + \registerparoptions % (*) better here (also does a \dontleavehmode) + \ifhmode\else\dontleavehmode\fi + \fi + \box\b_tabl_ntb_final + \afterTABLEbox} + +\def\tabl_ntb_split_yes + {\ifinsidesplitfloat + \donetrue + \orelse\ifinsidefloat + \donefalse + \else + \donetrue + \fi + \ifdone + \expandafter\tabl_ntb_split_box + \else + \expandafter\tabl_ntb_split_nop + \fi} + +\newbox\TABLEsplitbox % public, don't change + +\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox + +\def\tabl_ntb_split_box + {\resettsplit + \c_split_minimum_free_lines\plustwo + \d_split_minimum_free_space\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax + \t_split_before_result{\beforeTABLEsplitbox}% + \t_split_after_result{\afterTABLEsplitbox}% + \t_split_after{\m_tabl_ntb_after_split}% + \t_split_before{\m_tabl_ntb_before_split}% not used (yet) + \setbox\b_split_content\vbox{\tabl_ntb_flush_content}% + \ifmultipleTBLheads + \dorecurse\c_tabl_ntb_n_of_head_lines + {\setbox\scratchbox\vsplit\b_split_content to \lineheight + \setbox\b_split_head\vbox{\unvcopy\b_split_head\unvcopy\scratchbox}}% \vpack ? + \dorecurse\c_tabl_ntb_n_of_next_lines + {\setbox\scratchbox\vsplit\b_split_content to \lineheight + \setbox\b_split_next\vbox{\unvcopy\b_split_next\unvcopy\scratchbox}}% \vpack ? + \fi + \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}% + \ifempty\p_spaceinbetween\else + \blank[\p_spaceinbetween]% + \fi + \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\b_split_result}}% + \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_indeed\zerocount} % 0 = trial run +\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone } % 1 = real run + +\def\tabl_ntb_check_widths_indeed#1% + {\ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths B#1\fi + \scratchcounterone\zerocount + \scratchdimenone\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\scratchdimenone\dimexpr + -\tabl_ntb_get_dis\recurselevel + -\d_tabl_ntb_columndistance + \relax + \ifdim\scratchdimen>\zeropoint\relax + \advance\scratchdimenone -\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\scratchcounterone \plusone + \orelse\ifdim\scratchdimen>\zeropoint\relax + \advance\scratchdimenone -\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\scratchcounterone \plusone % setting maxwidth to a large value also works + \fi + \fi + \fi}% + \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths M#1\fi + \ifcase\scratchcounterone \else \divide\scratchdimenone \scratchcounterone \fi + \dorecurse\c_tabl_ntb_maximum_col + {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax + \ifcase#1\relax + \ifdim\scratchdimen<\scratchdimenone % take natural width + \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}% + \fi + \else + \ifzeropt\scratchdimen % auto set width + \tabl_ntb_set_wid\recurselevel{\the\scratchdimenone}% + \fi + \fi}% + \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths E#1\fi} + +% todo: use scratchcounters, not !! ones + +\def\tabl_ntb_check_heights_one_indeed + {\scratchcountertwo\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax + % check row span + \ifnum\scratchcountertwo>\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 + \scratchcounterthree\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax + \ifnum\scratchcounterthree=\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 + \scratchcounterthree\c_tabl_ntb_current_row_three + \advance\scratchcounterthree\minusone + \dorecurse\scratchcountertwo + {\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=\scratchcountertwo\else + \tabl_ntb_set_nob\scratchcounterthree + \advance\scratchcounterthree\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 \scratchcountertwo + \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\scratchcountertwo + {\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}% + \orelse\ifdim\dimen4>\dimen0 + \iftightTBLrowspan + \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}% + \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#2% + {\begingroup + \scratchdimen\zeropoint + \dorecurse\c_tabl_ntb_maximum_col + {\advance\scratchdimen\tabl_ntb_get_wid\recurselevel\relax}% + \writestatus\m!TABLE{#1 \ifcase#2trial\else real\fi: hsize: \the\hsize, total: \the\scratchdimen}% + \dorecurse\c_tabl_ntb_maximum_col + {\writestatus\m!TABLE{\space\space\recurselevel: \the\dimexpr\tabl_ntb_get_wid\recurselevel}}% + \endgroup} + +\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}} + +\protected\def\tabl_ntb_cell_process_a_extra#1#2% + {\ifcase\tabl_ntb_get_tal{#2}\relax + \expandafter\tabl_ntb_cell_process_x + \else + \expandafter\tabl_ntb_cell_process_a + \fi{#1}{#2}} + +\protected\def\tabl_ntb_cell_process_x#1#2[#3]#4% + {} + +% problem: when span doesn't break we can have a span that is the sum of cells but +% 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}% + \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} + +\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} + +\protected\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 + \anch_backgrounds_text_level_start + \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}% + \anch_backgrounds_text_level_stop + \ifcase\c_anch_backgrounds_text_count\else + \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state + \fi + }% + \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 + \ifzeropt\scratchdimen + % 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}% + \orelse\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 + \setbox\scratchboxone\emptyhbox + \wd\scratchboxone\wd\scratchbox + \ht\scratchboxone\ht\scratchbox + \dp\scratchboxone\dp\scratchbox + \box\scratchboxone + \egroup} + +\protected\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5% + {\setbox\scratchbox\hbox + {\tabl_ntb_setup_cell{#2}{#3}% + \setupcurrentnaturaltablelocal[#4,#1]% + \letnaturaltablelocalparameter\c!background\empty + \letnaturaltablelocalparameter\c!frame\v!off + \inheritednaturaltablelocalframed{\tabl_ntb_cell_start#5\tabl_ntb_cell_stop}}% + \setbox2\emptyhbox % todo: \scratchboxtwo + \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 } + +\protected\def\tabl_ntb_cell_process_b#1#2[#3]#4% + {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax + \ifdim\scratchdimen>\zeropoint\relax + \else + \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}} + +\protected\def\tabl_ntb_cell_process_c + {\tabl_ntb_cell_process_b_c{}} + +\protected\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} + +\protected\def\tabl_ntb_cell_process_e#1#2[#3]#4% + {\tabl_ntb_setup_cell{#1}{#2}% + \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we + \color % handle color here prevents interference due to whatsit nodes + [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence + {\letnaturaltablelocalparameter\c!color\empty + \setnaturaltablelocalparameter\c!width{\d_tabl_ntb_width}% + \ifzeropt\d_tabl_ntb_height % case: nc=maxcolumns + \else + \setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}% + \fi + \ifcase\c_anch_backgrounds_text_count\else + \edef\p_region{\naturaltablelocalparameter\c!region}% + \ifempty\p_region\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount + \letnaturaltablelocalparameter\c!region\v!yes + \fi\fi + \fi + \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}% + \hskip\tabl_ntb_get_dis{#2}} + +\newtoks\everyresetTABLEyes +\newtoks\everyresetTABLEnop + +\appendtoks + \setupTABLE [% + % + % framed defaults + % + \c!width=\v!fit,% + \c!height=\v!fit,% + \c!lines=,% + \c!offset=.25\exheight,% + \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=\v!frame,% + \c!framecolor=,% + \c!frameoffset=.5\linewidth,% + % \c!backgroundcorner=\framedparameter\c!corner,% + % \c!backgrounddepth=\framedparameter\c!depth,% + % \c!backgroundradius=\framedparameter\c!radius,% + % \c!framecorner=\framedparameter\c!corner,% + % \c!framedepth=\framedparameter\c!depth,% + % \c!frameradius=\framedparameter\c!radius,% + \c!component=,% + \c!region=,% + \c!align=,% + \c!bottom=\vss,% + \c!top=,% + \c!strut=\v!yes,% + \c!autostrut=\v!no,% + \c!location=\v!normal,% + \c!orientation=,% + \c!autowidth=\v!yes,% + \c!setups=,% + \c!loffset=\zeropoint,% + \c!roffset=\zeropoint,% + \c!toffset=\zeropoint,% + \c!boffset=\zeropoint,% + % + % table specific + % + \c!aligncharacter=\v!no,% + \c!alignmentcharacter={,},% + \c!color=,% + \c!columndistance=\zeropoint,% each column (whole table) + \c!distance=\zeropoint,% individual column + \c!headcolor=,% + \c!header=,% + \c!headstyle=\v!bold,% + \c!left=,% + \c!leftmargindistance=\zeropoint,% whole table + \c!maxwidth=8\emwidth,% + \c!option=,% \v!stretch + \c!right=,% + \c!rightmargindistance=\zeropoint,% whole table + \c!spaceinbetween=,% + \c!split=\v!auto,% + \c!splitoffset=\zeropoint,% + \c!style=,% + \c!textwidth=\v!local,% was \hsize + ]% +\to \everyresetTABLEyes + +\appendtoks + \setupTABLE [% + \c!width=\v!fit,% + \c!height=\v!fit% + ]% +\to \everyresetTABLEnop + +\the\everyresetTABLEyes + +% \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 + \the\everyresetTABLEyes + \else + \the\everyresetTABLEnop + \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} + +\permanent\tolerant\protected\def\defineTABLEsetup[#1]#*[#2]% + {\ifarguments\else\defcsname\??naturaltablesetup#1\endcsname{#2}\fi} + +\permanent\let\eTDs\relax +\permanent\let\eTRs\relax + +\permanent\protected\def\bTDs[#1]#2\eTDs + {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD} + +\permanent\protected\def\bTRs[#1]#2\eTRs + {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR} + +\protect \endinput + +% todo: mode: first|next (of niets) diff --git a/tex/context/base/mkxl/tabl-nte.mkxl b/tex/context/base/mkxl/tabl-nte.mkxl new file mode 100644 index 000000000..e79e2a004 --- /dev/null +++ b/tex/context/base/mkxl/tabl-nte.mkxl @@ -0,0 +1,107 @@ +%D \module +%D [ file=core-nte, +%D version=2009.03.08, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Natural Tables Extensions, +%D author=Hans Hagen \& Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Module / Natural Tables Extensions} + +\unprotect + +%D This module is suggested by Wolfgang Schuster who also prototyped +%D it and came up with the rationale: +%D +%D This module provides an easy way to use natural in a similiar +%D way as the older table module (based on the \TABLE\ macros) and +%D the newer tabulate module. +%D +%D You can see the advantage in the following table, once created +%D with the new macros and once with the normal macros provided +%D with the natural table module. +%D +%D Let us start with the original macros: +%D +%D \startbuffer +%D \bTABLE +%D \bTR +%D \bTD Text 1 \eTD +%D \bTD Text 2 \eTD +%D \eTR +%D \bTR +%D \bTD Text 3 \eTD +%D \bTD Text 4 \eTD +%D \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Watch how the new macros use less code: +%D +%D \startbuffer +%D \startTABLE +%D \NC Text 1 \NC Text 2 \NC\NR +%D \NC Text 3 \NC Text 4 \NC\NR +%D \stopTABLE +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D The actual code differs from the prototype that it does not need +%D to collect whole rows and parse them but looks ahead instead. + +\newconditional\c_tabl_nte_in_nc + +\permanent\tolerant\protected\def\startTABLE[#1]% + {\bgroup + \bTABLE[#1]% + \enforced\let\NC\tabl_nte_start_nc + \enforced\let\NR\tabl_nte_start_nr + \enforced\let\bTR\relax + \enforced\let\bTD\relax + \enforced\let\bTH\relax + \enforced\let\bTN\relax} + +\permanent\protected\def\stopTABLE + {\eTABLE + \egroup} + +\permanent\protected\def\tabl_nte_start_nr + {\eTR + \setfalse\c_tabl_nte_in_nc} + +\permanent\protected\def\tabl_nte_start_nc + {\futurelet\nexttoken\tabl_nte_start_nc_indeed} + +\def\tabl_nte_start_nc_indeed + {\ifx\nexttoken\tabl_nte_start_nr \else + \expandafter\tabl_nte_start_nc_finish + \fi} + +\def\tabl_nte_start_nc_finish#1\NC + {\ifconditional\c_tabl_nte_in_nc \else + \settrue\c_tabl_nte_in_nc + \tabl_ntb_bTR[]% + \fi + \tabl_ntb_bTD#1\eTD\NC} + +%D The related structure commands are also available: + +\permanent\let\stopTABLEhead\relax +\permanent\let\stopTABLEnext\relax +\permanent\let\stopTABLEbody\relax +\permanent\let\stopTABLEfoot\relax + +\permanent\tolerant\protected\def\startTABLEhead[#1]#:#2\stopTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} +\permanent\tolerant\protected\def\startTABLEnext[#1]#:#2\stopTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} +\permanent\tolerant\protected\def\startTABLEbody[#1]#:#2\stopTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} +\permanent\tolerant\protected\def\startTABLEfoot[#1]#:#2\stopTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-tab.mkxl b/tex/context/base/mkxl/tabl-tab.mkxl new file mode 100644 index 000000000..5b053abb5 --- /dev/null +++ b/tex/context/base/mkxl/tabl-tab.mkxl @@ -0,0 +1,2232 @@ +%D \module +%D [ file=core-tab, +%D version=1997.10.10, +%D title=\CONTEXT\ Table Macros, +%D subtitle=\TABLE\ Embedding, +%D author=Hans Hagen with copied and patched code from MJ Wichura, +%D date=\currentdate] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / TaBlE Embedding} + +% Todo: just for the fun of it ... use lmtx features. + +% Todo: a bitmore namespace protection ... although we want to keep some of the +% original flavour. +% +% In \MKIV\ the old table macros are sort of obsolete. The color extensions have +% been removed and some code is stripped. For practical reasons the \TABLE\ macros +% that are used are embedded in this file. +% +% The following code is based on TABLE 1.0 by Michael J. Wichura (August 1988. We +% used a patched version with many overloads and extensions. The documented (and +% larger) source can be found in \type {thrd-tab.tex}. +% +% Some code has been stripped. Some color has been added. Some macros have been +% renamed. Registers have been replaces. And probably much more can be cleaned up. +% We also need to use \tabl_tab_ prefixes here. + +\unprotect + +\newconditional\c_tabl_table_spacing_left +\newconditional\c_tabl_table_spacing_right + +\newdimen \d_tabl_table_line_thickness_unit +\newdimen \d_tabl_table_strut_unit +\newskip \s_tabl_table_inter_column_space_unit +\newdimen \d_tabl_table_column_width_unit +\newdimen \d_tabl_table_kern_unit + +\def\tablestrutheightfactor {8} +\def\tablestrutdepthfactor {3} +\def\tableintercolumnspacefactor {3} +\def\tablecolumnwidthfactor {10} +\def\tablevspacefactor {2} +\def\tablekernfactor {1} +\def\tablelinethicknessfactor {4} + +\newtoks\everytable +\newtoks\everytableparbox + +\protected\def\tabl_table_begin_par_box#1% + {\setbox\scratchbox\vtop\bgroup % \setbox added + \hsize#1\relax + \dontcomplain + \tabl_table_restore_lineskips + \normalbaselines + \enforced\let~\fixedspace + \inhibitblank % \blank[\v!disable]% % added + \the\everytableparbox} + +\protected\def\tabl_table_end_par_box + {\removelastskip % itemize or so + \endgraf + \ifnum\prevgraf>\zerocount % we want at least + \verticalstrut \nowhitespace \vskip-\struttotal % one line of text + \egroup + \ifdim\dp\scratchbox>\lineheight % see (*) for an + \getnoflines{\dp\scratchbox}% % example of where + \dp\scratchbox\zeropoint % saving can go + \setbox\scratchbox % terrible wrong + \vtop to \noflines\lineheight{\box\scratchbox}% + \fi % esp between rows + \else % of paragraphs + \egroup + \fi + \box\scratchbox} + +\appendtoks + \parindent\zeropoint + \raggedright + \rightskip\zeropoint \s!plus 4em \relax +\to \everytableparbox + +\newskip \tablelefttabskip +\newskip \tablerighttabskip + +\newcount\!taColumnNumber +\newcount\!taRecursionLevel % (Initially 0) + +\newdimen\!taDimenA % used by \Enlarge +\newdimen\!taDimenB % used by \Enlarge +\newdimen\!taDimenC % used by numeric.tex +\newdimen\!taMinimumColumnWidth + +\newtoks \!taTableSpread +\newtoks \!taPreamble +\newtoks \!taDataColumnTemplate +\newtoks \!taRuleColumnTemplate +\newtoks \!taOldRuleColumnTemplate +\newtoks \!taLeftGlue +\newtoks \!taRightGlue + +\newskip \!taLastRegularTabskip + +\newif \if!taBeginFormat +\newif \if!taOnceOnlyTabskip + +\def\!thToksEdef#1#2% + {\edef\tempstring{#2}% + #1\expandafter{\tempstring}% + \ignorespaces} + +\def\!thLoop#1\repeat + {\def\!thIterate{#1\expandafter\!thIterate\fi}% + \!thIterate + \let\!thIterate\relax} + +\def\tabl_table_begin_format + {\!taPreamble\emptytoks + \!taColumnNumber\zerocount + \scratchskip\s_tabl_table_inter_column_space_unit + \multiply\scratchskip\tableintercolumnspacefactor + \divide\scratchskip\plustwo + \!taRuleColumnTemplate\expandafter{\expandafter\tabskip\the\scratchskip}% + \!taLastRegularTabskip\scratchskip + \!taOnceOnlyTabskipfalse + \!taBeginFormattrue + \let\!tfRowOfWidths\empty + \doreadtableformatkeys} + +\def\!tfSetWidth + {\ifempty\!tfRowOfWidths % true if no prior "w" keys + \ifnum\!taColumnNumber>\zerocount % true if "w" key is to right of first "|" + \begingroup % RowOfWidths={\aligntab\omit || n copies of \aligntab\omit\aligntab#\omit}, where n = number of column to the left of this one + \scratchcounter\plusone + \aftergroup\edef + \aftergroup\!tfRowOfWidths + \aftergroup{% + \aftergroup\aligntab + \aftergroup\omit + \!thLoop + \ifnum \scratchcounter<\!taColumnNumber + \advance\scratchcounter\plusone + \aftergroup\!tfAOAO + \repeat + \aftergroup}% + \endgroup + \fi + \fi + \ifx[\tempstring % \!tgGetValue sets \tempstring = token after w + \expandafter\!tfSetWidthText + \else + \expandafter\!tfSetWidthValue + \fi} + +\def\!tfAOAO{\aligntab\omit\aligntab\omit} + +\def\!tfSetWidthText[#1]% + {\def\!tfWidthText{#1}% + \doreadtableformatkeys} + +\def\!tfSetWidthValue + {\!taMinimumColumnWidth + \ifnum\!tgCode=\plusone + \ifempty\!tgValue \tablecolumnwidthfactor \else \!tgValue \fi \d_tabl_table_column_width_unit + \else + \!tgValue + \fi + \let\!tfWidthText\empty % Override possible prior `w[sample entry]' + \doreadtableformatkeys} + +\def\!tfSetTabskip + {\ifnum\!tgCode=\plusone + \scratchskip\s_tabl_table_inter_column_space_unit + \multiply\scratchskip \ifempty\!tgValue\tableintercolumnspacefactor\else\!tgValue\fi + \else + \scratchskip\!tgValue + \fi + \divide\scratchskip\plustwo + \ifnum\!taColumnNumber=\zerocount + %\!thToksEdef\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}% + \normalexpanded{\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}}% + \else + %\!thToksEdef\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}% + \normalexpanded{\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}}% + \fi + \if!taOnceOnlyTabskip\else + \!taLastRegularTabskip\scratchskip % Remember this Tabskip, for possible + \fi % restoration after a subsequent"OnceOnly" + \doreadtableformatkeys} + +\def\!tfSetVrule + {\!thToksEdef\!taRuleColumnTemplate + {\hfil + \vrule + \noexpand\s!width + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_vrule_thickness_factor + \else + \!tgValue + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue + \fi + \alignmark\alignmark\alignmark\alignmark + \hfil + \the\!taRuleColumnTemplate}% + \!tfAdjoinPriorColumn} + +\def\!tfSetAlternateVrule + {\afterassignment\!tfSetAlternateA\scratchtoks} + +\def\!tfSetAlternateA + {\!thToksEdef\!taRuleColumnTemplate{\the\scratchtoks\the\!taRuleColumnTemplate}% + \!tfAdjoinPriorColumn} + +\def\!tfAdjoinPriorColumn + {\ifnum\!taColumnNumber=\zerocount + \!taPreamble=\!taRuleColumnTemplate % New \tabskip may have been added + \else + \ifempty\!tfRowOfWidths\else % no "w" keys specified yet, not even this col + \!tfUpdateRowOfWidths + \fi + \!thToksEdef\!taDataColumnTemplate{\the\!taLeftGlue\the\!taDataColumnTemplate\the\!taRightGlue}% + \!thToksEdef\!taPreamble{\the\!taPreamble\aligntab\the\!taDataColumnTemplate\aligntab\the\!taRuleColumnTemplate}% + \fi + \advance\!taColumnNumber\plusone + \if!taOnceOnlyTabskip + \!thToksEdef\!taDataColumnTemplate{\alignmark\alignmark\alignmark\alignmark\tabskip\the\!taLastRegularTabskip}% + \else + \!taDataColumnTemplate{\alignmark\alignmark}% + \fi + \!taRuleColumnTemplate\emptytoks + \!taLeftGlue{\hfil}% + \!taRightGlue{\hfil}% + \!taMinimumColumnWidth\zeropoint + \let\!tfWidthText\empty + \!taOnceOnlyTabskipfalse + \doreadtableformatkeys} + +\def\!tfUpdateRowOfWidths + {\ifempty\!tfWidthText\else + \!tfComputeMinColWidth + \fi + \edef\!tfRowOfWidths + {\!tfRowOfWidths + \aligntab + \omit + \ifdim \!taMinimumColumnWidth>\zeropoint + \hskip \the\!taMinimumColumnWidth + \fi + \aligntab + \omit}} + +\def\!tfComputeMinColWidth + {\setbox\scratchbox\vbox + {\ialign{% Plain's initialized \halign; \tabskip=0pt \everycr={} + \span\the\!taDataColumnTemplate\cr + \!tfWidthText\cr}}% + \!taMinimumColumnWidth\wd\scratchbox} + +\def\!tfFinishFormat + {\!thToksEdef\!taPreamble{% + \alignmark\alignmark\alignmark\alignmark\tabskip\tablelefttabskip + \aligntab + \the\!taPreamble\tabskip\tablerighttabskip + \aligntab + \alignmark\alignmark\alignmark\alignmark\tabskip\zeropoint\cr} + \!taBeginFormatfalse + \!ttDoHalign} + +\def\tabl_table_reformat[#1]% will become local + {\omit + \!taDataColumnTemplate{\alignmark\alignmark}% + \!taLeftGlue\emptytoks + \!taRightGlue\emptytoks + \begingroup + \tabl_table_use_bar + \expanded{\endgroup\noexpand\doreadtableformatkeys#1]}}% appear in a \tabl_table_reformat cmd; this is here as a safeguard. + +\appendtoks + \enforced\let\ReFormat\tabl_table_reformat +\to \everytable + +\def\!tfEndReFormat + {\!tfReFormat} + +\appendtoks \tabl_table_paralignment \to \everytableparbox + +\def\!tfReFormat#1% + {\the \!taLeftGlue + \vbox{\forgetall\ialign{\span\the\!taDataColumnTemplate\cr#1\cr}}% + \the \!taRightGlue + \kern\zeropoint} % prevents \unskip / really needed + +\def\!tgGetValue#1% + {\def\!tgReturn{#1}% + \futurelet\tempstring\!tgCheckForParen} + +\def\!tgCheckForParen% + {\ifx\tempstring (% + \expandafter \!tgDoParen + \else + \expandafter \!tgCheckForSpace + \fi} + +\def\!tgDoParen(#1)% + {\def\!tgCode{2}% will be expanded + \def\!tgValue{#1}% + \!tgReturn} + +\def\!tgCheckForSpace + {\def\!tgCode{1}% + \let\!tgValue\empty + \ifx\tempstring\!thSpaceToken + \expandafter\!tgReturn + \else + \expandafter\!tgCheckForDigit + \fi} + +\def\!tgCheckForDigit % less tokens: (could be an ifcsname) + {\donetrue + \ifx 0\tempstring \orelse \ifx 1\tempstring \orelse + \ifx 2\tempstring \orelse \ifx 3\tempstring \orelse + \ifx 4\tempstring \orelse \ifx 5\tempstring \orelse + \ifx 6\tempstring \orelse \ifx 7\tempstring \orelse + \ifx 8\tempstring \orelse \ifx 9\tempstring \else + \donefalse + \fi + \ifdone + \expandafter\!tgGetNumber + \else + \expandafter\!tgReturn + \fi} + +% \def\!tgCheckForDigit % does not work +% {\relax\doifnumberelse\tempstring\!tgGetNumber\!tgReturn} + +\def\!tgGetNumber {\afterassignment\!tgGetNumberA\scratchcounter=} +\def\!tgGetNumberA{\edef\!tgValue{\the\scratchcounter}\!tgReturn} + +\def\!tgSetUpParBox + {\normalexpanded + {\noexpand \doreadtableformatkeys + b{\tabl_table_begin_par_box + {\ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablecolumnwidthfactor + \else + \!tgValue + \fi + \d_tabl_table_column_width_unit + \else + \!tgValue + \fi}}% + a{\tabl_table_end_par_box}}} + +\def\!tgInsertKern + {\edef\tempstring + {\kern + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablekernfactor + \else + \!tgValue + \fi + \d_tabl_table_kern_unit + \else + \!tgValue + \fi}% + \edef\tempstring + {\noexpand\doreadtableformatkeys + \ifconditional\c_tabl_table_spacing_left + b{\tempstring} + \fi + \ifconditional\c_tabl_table_spacing_right + a{\tempstring} + \fi}% + \tempstring} + +\def\newtableformatkey #1{\setvalue{!tk<\string#1>}} +\def\doreadtableformatkeys#1{\getvalue{!tk<\string#1>}} + +% Key "b": b{TOKENS} adds TOKENS to the left of (before) the template + +\newtableformatkey b#1% + {\expandafter\!tkJoin\expandafter{\the\!taDataColumnTemplate}{#1}% + \doreadtableformatkeys} + +\def\!tkJoin#1#2% + {\!taDataColumnTemplate{#2#1}}% + +% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template + +\newtableformatkey a#1% + {\toksapp\!taDataColumnTemplate{#1}% + \doreadtableformatkeys} + +% Key "\{": Enclose template in braces. + +\newtableformatkey \{% + {\!taDataColumnTemplate=\expandafter{\expandafter{\the\!taDataColumnTemplate}}% + \doreadtableformatkeys} + +% Key "*": "*{N}{KEY LETTERS}" is equivalent to specifying +% N times. +% KEY LETTERS may contain further * specifications + +\newtableformatkey *#1#2% + {\scratchcounter=#1\relax + \scratchtoks\emptytoks + \!thLoop + \ifnum\scratchcounter>\zerocount + \toksapp\scratchtoks{#2}% + \advance\scratchcounter\minusone + \repeat + \expandafter\doreadtableformatkeys\the\scratchtoks} + +% Key "\LeftGlue": Specifies the glue (usually \hfil, or nothing) to be +% added to extreme left of the template to position a column + +\newtableformatkey \LeftGlue#1% + {\!taLeftGlue{#1}% + \doreadtableformatkeys} + +\newtableformatkey \RightGlue#1% + {\!taRightGlue{#1}% + \doreadtableformatkeys} + +\newtableformatkey c% + {\prependtoks\raggedcenter\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\hfil} + +\newtableformatkey l% + {\prependtoks\raggedright\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\empty \RightGlue\hfil} + +\newtableformatkey r% + {\prependtoks\raggedleft\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} + +\newtableformatkey x% + {\prependtoks\notragged\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} + +% Key "k": Adds kerns to left and right of "#" This key and the two below use Plain +% TeX's \if@h as if it were \if@left, and \if@v as if it were \if@right. Table +% making goes on in a group, so even in the unlikely circumstance that a \phantom +% is currently under construction, there's no problem. + +\newtableformatkey k% + {\settrue\c_tabl_table_spacing_left + \settrue\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "i": Adds a kern to the left of "#" + +\newtableformatkey i% + {\settrue\c_tabl_table_spacing_left + \setfalse\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "j": Adds a kern to the right of "#" + +\newtableformatkey j% + {\setfalse\c_tabl_table_spacing_left + \settrue\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "n": numeric item , non-math mode. + +\newtableformatkey n% + {\def\!tnStyle{}% + \futurelet\!tnext\!tnTestForBracket} + +% Key "N": numeric item, math mode. + +\newtableformatkey N% + {\def\!tnStyle{$}% + \futurelet\!tnext\!tnTestForBracket} + +% Key "m": Math mode. + +\newtableformatkey m% + {\doreadtableformatkeys b{\normalstartimath} a{\normalstopimath}} + +% Key "M": Displaymath mode. + +\newtableformatkey M% + {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}} + +% Key "\m": Template ${}#\hfil$ + +\newtableformatkey \m% + {\doreadtableformatkeys l b{{}} m} + +% Key "\M": Template $\displaystyle{{}#\hfil}$ + +\newtableformatkey \M% + {\doreadtableformatkeys l b{{}} M} + +% Key "f": Set font (E.g., f\it sets up italic font (assuming \it +% has its usual meaning) + +\newtableformatkey f#1% + {\doreadtableformatkeys b{#1}} + +\newtableformatkey B{\doreadtableformatkeys f\bf} % Key "B": abbreviation for f\bf +\newtableformatkey I{\doreadtableformatkeys f\it} % Key "I": abbreviation for f\it +\newtableformatkey S{\doreadtableformatkeys f\sl} % Key "S": abbreviation for f\sl +\newtableformatkey R{\doreadtableformatkeys f\rm} % Key "R": abbreviation for f\rm +\newtableformatkey T{\doreadtableformatkeys f\tt} % Key "T": abbreviation for f\tt + +% Key "p": ParBox + +\newtableformatkey p% + {\!tgGetValue{\!tgSetUpParBox}} + +% Key "w": minimum column width + +\newtableformatkey w% + {\!tkTestForBeginFormat w{\!tgGetValue{\!tfSetWidth}}} + +% Key "s": Set tabskip for the inter-column space to the right of the current +% column, and all subsequent spaces, until overriden by a new "s" or "o" key. + +\newtableformatkey s% + {\!taOnceOnlyTabskipfalse % in case same column has a prior "o" key + \!tkTestForBeginFormat t{\!tgGetValue{\!tfSetTabskip}}} + +% Key "o": Apply the \tabskip stated for this column ONLY to the inter-column space +% just to the right of this column; restore the the previous \tabskip for +% subsequent columns. + +\newtableformatkey o% + {\!taOnceOnlyTabskiptrue + \!tkTestForBeginFormat o{\!tgGetValue{\!tfSetTabskip}}} + +% Key "|": Standard rule column designator + +\newtableformatkey |% + {\!tkTestForBeginFormat |{\!tgGetValue{\!tfSetVrule}}} + +% Key "\|": Non-standard rule column designator + +\newtableformatkey \|% + {\!tkTestForBeginFormat \|{\!tfSetAlternateVrule}} + +% Key ".": PERIOD -- end of \tabl_table_begin_format section. + +\newtableformatkey .% + {\!tkTestForBeginFormat.{\!tfFinishFormat}} + +% Key "\doendtableformat": Equivalent to "." + +\newtableformatkey \doendtableformat + {\!tkTestForBeginFormat\doendtableformat{\!tfFinishFormat}} + +% Key "]": End of \tabl_table_reformat section + +\newtableformatkey ]% + {\!tkTestForReFormat ] \!tfEndReFormat} + +% TEST FOR BEGIN FORMAT{}{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{}{Intended Action}: This test is run on the key "]", +% which can only be used by \tabl_table_reformat. + +\def\!tkTestForReFormat#1#2% + {\if!taBeginFormat + \toks0={#1}% + \toks2=\expandafter{\string\tabl_table_begin_format}% + \expandafter\!tkImproperUse + \else + \def\tempstring{#2}% + \expandafter\tempstring + \fi} + +% NOTE: THE SPACE BETWEEN A NUMERIC ENTRY AND THE FOLLOWING '|', '"', OR '\|' IS +% MANDATORY. EMPTY NUMERIC ENTRIES ARE NOT ALLOWED: USE '{}' OR '\omit' INSTEAD. + +\def\!tnTestForBracket + {\ifx[\!tnext + \expandafter\!tnGetArgument + \else + \expandafter\!tnGetCode + \fi} + +% GET CODE: E.g. "4", or "4.0", "0.4", or "10.2" + +\def\!tnGetCode#1 % + {\!tnConvertCode #1..!} + +% CONVERT CODE: E.g. converts above to [0000], [0000.], [.0000], [0000000000.00] + +\def\!tnConvertCode #1.#2.#3!% + {\begingroup + \aftergroup\edef \aftergroup\tempstring \aftergroup{% + \aftergroup[% + \scratchcounter#1\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \def\tempstring{#3}% + \ifempty\tempstring\else + \aftergroup. + \scratchcounter#2\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \fi + \aftergroup]\aftergroup}% + \endgroup\relax + \expandafter\!tnGetArgument\tempstring} + +% GET ARGUMENT: [ > + +\def\!tnGetArgument[#1]% + {\!tnMakeNumericTemplate\!tnStyle#1..!} + +% MAKE NUMERIC TEMPLATE + +\def\!tnMakeNumericTemplate#1#2.#3.#4!% #1= or $ + {\def\tempstring{#4}% + \ifempty\tempstring + \!taDimenC\zeropoint + \else + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1.#3#1}% + \!taDimenC\wd\scratchbox + \fi + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% + \!thToksEdef\!taDataColumnTemplate + {\noexpand\!tnSetNumericItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% + \the\!taDataColumnTemplate}% Might have tabskip glue in here + \doreadtableformatkeys} + +% SET NUMERIC ITEM + +\def\!tnSetNumericItem #1#2#3#4 % + {\!tnSetNumericItemA {#1}{#2}{#3}#4..!} + +\def\!tnSetNumericItemA #1#2#3#4.#5.#6!% + {\def\tempstring{#6}% + \hbox to #1{\hss \mathsurround\zeropoint #3#4#3}% + \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint #3.#5#3\fi\hss}} + +% extensions + +\newtableformatkey q% + {\let\!tqStyle\empty + \futurelet\!tnext\!tqTestForBracket} + +\newtableformatkey Q% + {\def\!tqStyle{$}% + \futurelet\!tnext\!tqTestForBracket} + +\def\!tqTestForBracket + {\ifx[\!tnext + \!thx\!tqGetArgument + \else + \!thx\!tqGetCode + \fi} + +\def\!tqGetCode#1 % note the blank + {\!tqConvertCode #1,,!} + +\def\!tqConvertCode #1,#2,#3!% + {\begingroup + \aftergroup\edef + \aftergroup\tempstring + \aftergroup{% + \aftergroup[% + \scratchcounter#1\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \def\tempstring{#3}% + \ifempty\tempstring\else + \aftergroup, + \scratchcounter#2\relax + \!thLoop + \ifnum\scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \fi + \aftergroup]\aftergroup}% + \endgroup\relax + \!thx\!tqGetArgument\tempstring} + +\def\!tqGetArgument[#1]% + {\!tqMakeQuantityTemplate\!tqStyle#1,,!} + +\def\!tqMakeQuantityTemplate#1#2,#3,#4!% #1= or $ + {\def\tempstring{#4}% + \ifempty\tempstring + \!taDimenC\zeropoint + \else + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1,#3#1}% + \!taDimenC\wd\scratchbox + \fi + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% + \!thToksEdef\!taDataColumnTemplate + {\noexpand\!tqSetQuantityItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% + \the\!taDataColumnTemplate}% + \doreadtableformatkeys} + +\def\!tqSetQuantityItem #1#2#3#4 % + {\!tqSetQuantityItemA{#1}{#2}{#3}#4,,!} + +\def\!tqSetQuantityItemA #1#2#3#4,#5,#6!% + {\def\tempstring{#6}% + \hbox to #1{\hss\mathsurround\zeropoint#3#4#3}% + \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint#3,#5#3\fi\hss}} + +% \Enlarge +% \enlarge + +\def\tabl_table_Enlarge#1#2% + {% 3rd argument is picked up later + % #1=extra height + % #2=extra depth + \!taDimenA=#1\relax + \!taDimenB=#2\relax + \let\!TsSpaceFactor\empty + \ifmmode + \expandafter\mathpalette + \expandafter\!TsEnlargeMath + \else + \expandafter\!TsEnlargeOther + \fi} + +\def\!TsEnlargeOther#1% + {\ifhmode + \setbox\scratchbox\hbox{#1\xdef\!TsSpaceFactor{\spacefactor\the\spacefactor}}% + \else + \setbox\scratchbox\hbox{#1}% + \fi + \!TsFinishEnlarge} + +\def\!TsEnlargeMath#1#2% + {\setbox\scratchbox\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% + \!TsFinishEnlarge} + +\def\!TsFinishEnlarge + {\ht\scratchbox\dimexpr\ht\scratchbox+\!taDimenA\relax + \dp\scratchbox\dimexpr\dp\scratchbox+\!taDimenB\relax + \box\scratchbox + \!TsSpaceFactor\relax} + +\def\tabl_table_enlarge#1#2% 3rd argument is picked up later + {\tabl_table_Enlarge{#1\d_tabl_table_strut_unit}{#2\d_tabl_table_strut_unit}} + +\appendtoks + \enforced\let\enlarge\tabl_table_enlarge + \enforced\let\Enlarge\tabl_table_Enlarge +\to \everytable + +% BEGIN TABLE + +\let\tabl_table_standard_end\relax + +\def\tabl_table_standard_begin[#1]% \!ttBeginTable (always argument) + {\if#1u% unboxed table + \ifmmode + \let\tabl_table_standard_end\relax % user had better be in display math mode and have only one table at the outer level + \else % user had better be in vertical mode + \bgroup + \let\tabl_table_standard_end\egroup + \fi + \else + \hbox\bgroup + \def\tabl_table_standard_end{\egroup\egroup}% + \if#1t% + \vtop + \orelse\if#1b% + \vbox + \else + \def\tabl_table_standard_end{\egroup\normalstopimath\egroup}% + \scratchtoks\everymath + \everymath\emptytoks + \normalstartimath + \everymath\scratchtoks + \vcenter + \fi + \bgroup % for the \vtop, \vbox, or \vcenter + \fi + \advance\!taRecursionLevel\plusone + \let\!ttRightGlue\relax + \everycr\emptytoks + \ifnum\!taRecursionLevel=\plusone + \the\everytable + \fi} + +\bgroup \catcode\tildeasciicode\activecatcode + + \appendtoks + \catcode\barasciicode\activecatcode + \enforced\protected\def ~{\kern.5em}% + \enforced\protected\def\\{\ifhmode\space\else\par\fi}% + \to \everytable + +\egroup + +\let\!ttRightGlue\relax % This may be changed, in a group, by \JustCenter, etc + +% DO HALIGN: Invoked by END FORMAT (or the key ".") + +\let\tabl_table_restore_lineskips\relax + +\def\!ttDoHalign + {\edef\tabl_table_restore_lineskips + {\baselineskip \the\baselineskip + \lineskiplimit\the\lineskiplimit + \lineskip \the\lineskip + \tabskip \the\tabskip + \relax}% + \baselineskip \zeropoint + \lineskiplimit\zeropoint + \lineskip \zeropoint + \tabskip \zeropoint + \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}% + % we are not in sync so: + \synchronizedisplaydirection + \synchronizeinlinedirection + \halign + \usedirectionparameterreverse\directtablesparameter + \ifempty\p_tabl_table_textwidth \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi + %\the\!taTableSpread + \bgroup + \span + \the\!taPreamble + \ifempty\!tfRowOfWidths\else + \!tfRowOfWidths\cr + \fi} + +% END TABLE + +\def\tabl_table_normal_end + {\egroup % finishes the \halign + \tabl_table_standard_end} % closes off the table envirnoment set up by \tablestandardbegin + +\def\tabl_table_normal_line_ending + {\cr} + +\def\tabl_table_normal_line_format#1#2% + {\vrule + \s!width \zeropoint + \s!height\dimexpr\tablestrutheightfactor\d_tabl_table_strut_unit+#1\d_tabl_table_strut_unit\relax + \s!depth \dimexpr\tablestrutdepthfactor \d_tabl_table_strut_unit+#2\d_tabl_table_strut_unit\relax + \relax + \cr} + +% INSERT VRULE + +\newcount\c_tabl_table_n_of_vrules \c_tabl_table_n_of_vrules\plusone + +\let\m_tabl_table_vrule_color\empty +\let\m_tabl_table_hrule_color\empty + +\def\do!ttInsertVrule + {\vrule\s!width + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_vrule_thickness_factor + \else + \!tgValue + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue + \fi + \hskip.125\emwidth\relax} + +\def\tabl_table_normal_line_simple_bar + {\unskip\!ttRightGlue\aligntab\aligntab} + +\def\tabl_table_normal_line_complex_bar + {\unskip\!ttRightGlue\aligntab\omit + \hfil + \ifempty\m_tabl_table_vrule_color\else + \switchtocolor[\m_tabl_table_vrule_color]% + \fi + \ifcase\c_tabl_table_n_of_vrules\or + \do!ttInsertVrule + \unskip + \else + \dorecurse\c_tabl_table_n_of_vrules\do!ttInsertVrule + \global\c_tabl_table_n_of_vrules\plusone + \unskip + \fi + \glet\m_tabl_table_vrule_color\empty + \hfil + \aligntab} + +\def\tabl_table_normal_no_bar + {\unskip\!ttRightGlue\aligntab\omit\aligntab} + +\def\tabl_table_normal_single_rule + {\aligntab\tabl_table_normal_long_rule\aligntab} + +\def\tabl_table_normal_multi_rule + {\aligntab\tabl_table_use\c_tabl_table_drule_span\tabl_table_normal_long_rule\aligntab} + +% USE + +\def\tabl_table_use#1% + {\ifnum#1>\plusone + \omit + \global\setfalse\c_tabl_table_is_division % added + \scratchcounter\currenttablecolumn % added + \advance\scratchcounter #1% % added + \advance\scratchcounter \minusone % added + \def\next % added + {\global\advance\currenttablecolumn #1% % added + \global\advance\currenttablecolumn \minusone % added + \scratchcounter#1% + \advance\scratchcounter \minusone + \advance\scratchcounter \scratchcounter + \!thLoop + \ifnum\scratchcounter>\plusone + \spanomit \advance\scratchcounter\minusone + \repeat + \span}% + \else % added + \def\next % conflicts with possible next \omit % added + {\global\advance\currenttablecolumn \plusone}%% added + \fi + \next} % added + +\def\tabl_table_Use#1[% + {\tabl_table_use{#1}% + \tabl_table_reformat[} + +\appendtoks + \enforced\let\use\tabl_table_use + \enforced\let\Use\tabl_table_Use +\to \everytable + +% rules + +\def\tabl_table_normal_full_rule + {\noalign\bgroup + \!ttGetHalfRuleThickness + \scratchdistance\directtablesparameter\c!openup + \ifzeropt\scratchdistance\else\kern\scratchdistance\fi + \hrule\s!height\scratchdimen\s!depth\scratchdimen + \ifzeropt\scratchdistance\else\kern\scratchdistance\fi + \egroup} + +\def\tabl_table_normal_short_rule % was: \!ttShortHrule + {\omit + \!ttGetHalfRuleThickness + \ifempty\m_tabl_table_hrule_color\else + \switchtocolor[\m_tabl_table_hrule_color]% see *DL* + \fi + \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill + \emptyhbox + \ignorespaces} + +\def\tabl_table_normal_long_rule % was: \!ttLongHrule + {\omit\span + \omit\span + \tabl_table_normal_short_rule} + +\def\!ttGetHalfRuleThickness + {\scratchdimen\dimexpr + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_hrule_thickness_factor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue % user-specified dimension + \fi + \divide\scratchdimen\plustwo} + +% \emptyhbox prevents \unskip + +\def\tabl_table_Left #1{#1\hfill\emptyhbox} +\def\tabl_table_Center#1{\hfill#1\hfill\emptyhbox} +\def\tabl_table_Right #1{\hfill#1} + +\def\tabl_table_OpenUp#1#2% + {\edef\tablestrutheightfactor{\withoutpt\the\dimexpr\tablestrutheightfactor\points+#1\points}% + \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr\tablestrutdepthfactor \points+#2\points}} + +% SetTableToWidth -> textwidth=dimension [to dimension] +% Expand -> textwidth=max [to \hsize] +% WidenTableBy -> [spread #1] +% \tablelefttabskip\zeropoint\s!plus1\s!fill +% \tablerighttabskip\tablelefttabskip +% LongLines -> [spread \hsize] + +\def\tabl_table_JustLeft {\omit\let\!ttRightGlue\hfill} +\def\tabl_table_JustCenter{\omit\hfill\emptyhbox\let\!ttRightGlue\hfill} +\def\tabl_table_JustRight {\omit\hfill\emptyhbox} + +\def\tabl_table_Smash + {\relax + \ifmmode + \expandafter\mathpalette + \expandafter\!thDoMathVCS + \else + \expandafter\!thDoVCS + \fi} + +\def\!thDoVCS#1% + {\setbox\zerocount\hbox{#1}% + \!thFinishVCS} + +\def\!thDoMathVCS#1#2% + {\setbox\zerocount\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% + \!thFinishVCS} + +\def\!thFinishVCS + {\vpack to\zeropoint{\vss\box\zerocount\vss}} + +\def\tabl_table_Raise + {\def\!thSign{+}% + \!tgGetValue\!thSetDimen} + +\def\tabl_table_Lower + {\def\!thSign{-}% + \!tgGetValue\!thSetDimen} + +\def\!thSetDimen + {\ifnum\!tgCode=\plusone + \ifempty\!tgValue + \!taDimenA\tablestrutheightfactor\d_tabl_table_strut_unit + \advance\!taDimenA\tablestrutdepthfactor\d_tabl_table_strut_unit + \divide\!taDimenA\plustwo + \else + \!taDimenA\!tgValue\d_tabl_table_strut_unit + \fi + \else + \!taDimenA\!tgValue + \fi + \!taDimenA\!thSign\!taDimenA\relax + \ifmmode + \expandafter\mathpalette + \expandafter\!thDoMathRaise + \else + \expandafter\!thDoSimpleRaise + \fi} + +\def\!thDoSimpleRaise#1% + {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{#1}}% + \!thFinishRaise} % From Plain TeX: \ht0=0pt \dp0=0pt \box0 + +\def\!thDoMathRaise#1#2% + {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}}% + \!thFinishRaise} + +\def\!thFinishRaise + {\ht\zerocount\zeropoint + \dp\zerocount\zeropoint + \box\zerocount} + +\def\tabl_table_BackSpace + {\!tgGetValue\!thKernBack} + +\def\!thKernBack + {\kern - + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablekernfactor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_kern_unit + \else + \!tgValue % user-specified dimension + \fi + \ignorespaces} + +\def\tabl_table_Vspace + {\noalign + \bgroup + \!tgGetValue\!thVspace} + +\def\!thVspace + {\vskip + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablevspacefactor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_strut_unit + \else + \!tgValue % user-specified skip + \fi + \egroup} % Ends the \noalign + +\appendtoks + \enforced\let\JustLeft \tabl_table_JustLeft + \enforced\let\JustCenter \tabl_table_JustCenter + \enforced\let\JustRight \tabl_table_JustRight + \enforced\let\Smash \tabl_table_Smash + \enforced\let\Raise \tabl_table_Raise + \enforced\let\Lower \tabl_table_Lower + \enforced\let\BackSpace \tabl_table_BackSpace + \enforced\let\Vspace \tabl_table_Vspace + \enforced\let\OpenUp \tabl_table_OpenUp + \enforced\let\TableLeft \tabl_table_Left + \enforced\let\TableCenter\tabl_table_Center + \enforced\let\TableRight \tabl_table_Right +\to \everytable + +%D \macros +%D {inintable, ifsplittables} +%D +%D First we declare some variables. These show a bit what we are dealing with. First +%D we introdoce some booleans that enable us, inside as well as outside this module, +%D to determine in what mode we are. + +\newif\ifintable +\newif\ifsplittables + +%D We show this feature in an example that also shows some of the basic table +%D typesetting commands. +%D +%D \startbuffer +%D \starttable[|||] +%D \HL +%D \VL first \VL second \VL\AR +%D \HL +%D \VL alfa \VL 1 \VL\AR +%D \VL beta \VL 2 \VL\AR +%D \VL gamma \VL 3 \VL\AR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D This table is specified as: +%D +%D \typebuffer +%D +%D This examples shows about the minimum of commands needed to typeset such a table. +%D In this table, the \type {\AR} is automatically translated into the more +%D primitive (but more verbose) commands \type {\SR}, \type {\FR}, \type {\MR} and +%D \type {\LR} commands. +%D +%D \startbuffer +%D \starttables[|||] +%D \HL +%D \VL first \VL second \VL\AR +%D \HL +%D \VL alfa \VL 1 \VL\AR +%D \VL beta \VL 2 \VL\AR +%D \VL gamma \VL 3 \VL\AR +%D \HL +%D \stoptables +%D \stopbuffer +%D +%D \getbuffer +%D +%D Some simple color support is provided: +%D +%D \startbuffer +%D \starttable[|c|c|] +%D \HL +%D \VL test \VL test \VL \SR +%D \HL[green,5] +%D \VL[red] test \VL test \VL \FR +%D \VL test \VL[10,red] test \VL \MR +%D \VL test \VL test \VL[10] \LR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace{tabletemplate} + +\immutable\def\m!TABLE{TABLE} + +%D We already saw that the table macros report errors and provide automatic spacing. +%D These features can only be implemented by keeping track of the state, often the +%D last command on a row. + +\newconstant\tableforcestate +\newconstant\tableactionstate + +\setnewconstant\tableunknownstate 0 + +\setnewconstant\tableseparaterowstate 1 +\setnewconstant\tablefirstrowstate 2 +\setnewconstant\tablemidrowstate 3 +\setnewconstant\tablelastrowstate 4 +\setnewconstant\tablerulestate 5 +%setnewconstant\tableskipstate 6 +%setnewconstant\tableautorowstate 7 + +\setnewconstant\tableforcefirstrowstate 1 +\setnewconstant\tableforcelastrowstate 2 + +\newconstant\tablerowfactor +\newconstant\TABLEendofrowdepth +\newconstant\TABLEendofrowheight +\newconstant\TABLEcr +\newconstant\tablerowzero +\newconstant\TABLEn + +%D We store these states using \type {constants}'s and like most variables, these +%D are global ones. When needed, especially when we flush the backgrounds, we can +%D temporary disable the assignment. + +\newconditional\tableactionstatepermitted + +\def\tabl_table_set_action#1{\ifconditional\tableactionstatepermitted\global\tableactionstate#1\fi} +\def\tabl_table_set_force #1{\ifconditional\tableactionstatepermitted\global\tableforcestate #1\fi} + +%D To give an impression of what the (well documented) source of \TABLE\ looks like, +%D we first implement an alternative for the numeric keys. The quantity keys +%D (\type{q} and \type{Q}) support the more european way of writing numbers: +%D +%D \startnarrower +%D 100.000.000,00 instead of 100,000,000.00 +%D \stopnarrower +%D +%D The next table shows how to use these keys. We use braces instead of brackets because +%D we need brackets to specify the format. +%D +%D \starttyping +%D \starttable{|q[00,000]|Q[00,00]|} +%D \HL +%D \VL -1,2 \VL 12,35 \VL\FR +%D \VL 11,203 \VL 2,4 \VL\LR +%D \HL +%D \stoptable +%D \stoptyping +%D +%D Although a more efficient implementation is possible |<|we can for instance share +%D common macros|>| we just adapt a copy of the numeric ones. To permit double +%D loading of this module, we check for the existence of one of the macros. +%D +%D To be compatible with the tabulate environment, we also support the \type {l}, +%D \type {c} and \type {r} keys for paragraph entries. +%D +%D All commands that are executed between rows are to be put in \type {\noalign}. We +%D can however not verify if we (that is \TABLE) does or did not enter this mode. A +%D moderate dirty but useful trick is using our own alternative:\footnote{Once one +%D has entered the stage of redefining \TEX\ primitives, such hacks become a second +%D nature. However, redefining \type {\omit} and \type{\span} is not that easy.} + +%D We no longer need this in \LUAMETATEX: +%D +%D \starttyping +%D \aliased\let\tablenoalign \noalign +%D \def\starttablenoalign{\noalign\bgroup} +%D \let\stoptablenoalign \egroup +%D \stoptyping + +%D \macros +%D {starttable} +%D +%D The rest of this module is not easy to comprehend, mainly because we have to take +%D care of: +%D +%D \startitemize[packed] +%D \item \type{\startitemize[template]} +%D \item \type{\startitemize{template}} +%D \item \type{\startitemize[predefined]} +%D \stopitemize +%D +%D as well as: +%D +%D \startitemize[continue] +%D \item restart after table break +%D \stopitemize +%D +%D The official specification of the start command is: +%D +%D \showsetup{starttable} + +\newconditional\c_tabl_table_repeat_head +\newconditional\c_tabl_table_repeat_tail + +\permanent\tolerant\protected\def\starttable[#1]#*[#2]% preamble optional-settings + {\bgroup + \ifarguments\or\or + \setupcurrenttables[#2]% + \fi + \edef\p_tabl_table_split{\directtablesparameter\c!split}% + \edef\p_tabl_table_frame{\directtablesparameter\c!frame}% + \ifx\p_tabl_table_split\v!auto + \ifinsidesplitfloat + \let\p_tabl_table_split\v!yes + \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode + \fi + \fi + \ifx\p_tabl_table_split\v!yes + \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead + \expandafter\starttables + \orelse\ifx\p_tabl_table_split\v!repeat + \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead + \expandafter\starttables + \else + \enforced\let\stoptable\table_table_stop + \ifempty\p_tabl_table_frame + \ifinsidefloat\else\startbaselinecorrection\fi + \else + \startframedcontent[\p_tabl_table_frame]% + \fi + \postponenotes + \expandafter\tabl_table_first_stage + \fi[#1]} + +% We cannot define the stopper as \type {\protected} because lookahead in +% alignments fail then, so we relax it and define it locally. Actually we +% now can. + +\permanent\let\stoptable\relax + +\permanent\def\table_table_stop + {\tabl_tables_chuck_auto_row % before the tail, else noalign problem + \tabl_table_insert_tail + \noalign\bgroup + \glet\tabl_table_head\empty + \glet\tabl_table_tail\empty + \egroup + \tabl_table_finish + \ifempty\p_tabl_table_frame + \ifinsidefloat\else + \stopbaselinecorrection + \goodbreak % compensates all the nobreaks + \fi + \else + \stopframedcontent + \fi + \egroup} + +\permanent\def\table_table_stop_g + {\table_table_stop_s\egroup} + +%D Before we can grab the argument, we have to make sure that the \CATCODES\ are +%D set. The first stage takes care of that. + +\def\tabl_table_first_stage + {\bgroup + \global\intabletrue + \tabl_table_second_stage} + +%D \macros +%D {definetabletemplate} +%D +%D The complex (and main) start macro first takes care of the predefined case. Such +%D a predefined setup looks like: +%D +%D \starttyping +%D \definetabletemplate[test][|||] +%D +%D \starttable[test] +%D \VL test \VL test \VL\AR +%D \VL test \VL test \VL\AR +%D \VL test \VL test \VL\AR +%D \stoptable +%D \stoptyping +%D +%D The implementation of the definition macro is not that complicated: + +\installcorenamespace{tablehead} +\installcorenamespace{tabletail} + +\permanent\protected\def\definetabletemplate % to be redone + {\bgroup + \catcode\barasciicode\othercatcode + \tabl_table_define_template} + +\tolerant\def\tabl_table_define_template[#1]#*[#2]#*[#3]#*[#4]% + {\ifarguments\or\else + \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}% + \fi + \egroup} + +\def\tabl_table_use_template#1#2#3% + {\gdef\tabl_table_head{\begincsname\??tablehead#2\endcsname}% + \gdef\tabl_table_tail{\begincsname\??tabletail#3\endcsname}% + \tabl_table_second_stage[#1]} + +%D The optional third and fourth arguments define which table head and tail to use. +%D +%D \starttyping +%D \definetabletemplate[test][|||][before][after] +%D \stoptyping +%D +%D This also means that one can define table heads and tails by name! +%D +%D \starttyping +%D \starttablehead[before] +%D \HL \VL first \VL second \VL \SR \HL +%D \stoptablehead +%D \stoptyping +%D +%D Templates defined this way get protected names, that cannot conflict with +%D existing commands. +%D +%D \showsetup{definetabletemplate} +%D +%D The second half of the next macro prepares table +%D splitting. + +\def\tabl_table_insert_head + {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometablehead}% + \tabl_table_head + \noalign{\global\setfalse\preventtablebreak}} + +\def\tabl_table_insert_tail + {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometabletail}% + \tabl_table_tail + \noalign{\global\setfalse\preventtablebreak}} + +% \def\doverysimpletableHL % todo +% {\noalign{\normalexpanded{\noexpand\tabl_table_normal_full_rule\m_tabl_table_HLheight}} + +\def\tabl_table_restart_indeed#1% + {\gdef\tabl_table_restart{#1}% + \tabl_table_restart +% \noalign{\globalpushmacro\simpletableHL\glet\simpletableHL\doverysimpletableHL}% + \tabl_table_insert_head + \ifsplittables \ifconditional \c_tabl_table_repeat_tail + \noalign{\goodbreak}% + \tabl_table_insert_tail + \noalign{\goodbreak}% + \fi \fi +% \noalign{\globalpopmacro\simpletableHL}% + } + +\bgroup \catcode\barasciicode\othercatcode + +\gdef\tabl_table_second_stage[#1]% brr nested mess + {\bgroup + \tabl_table_use_bar + \global\setfalse\tableactionstatepermitted + \global\setfalse\hassometablehead + \global\setfalse\hassometabletail + \expanded{\doifelseinstring{|}{#1}} + {\xdef\tabl_table_restart{\noexpand\tabl_table_restart_indeed{\noexpand\tabl_table_third_stage{#1}}}} + {\doifelsedefined{\??tabletemplate#1} + {\gdef\tabl_table_restart{\getvalue{\??tabletemplate#1}}} + {\gdef\tabl_table_restart{\tabl_table_restart_indeed{\getvalue{#1}}}}}% + \egroup + \tabl_table_restart} + +\egroup + +%D The third stage involves a lot of (re)sets, which we will explain later. + +\appendtoks + \fixedspaces + \enforced\let\_\normalunderscore +\to \everytable + +%D Now we can start the table. + +\newtoks\localtabledefinitions + +\def\tabl_table_third_stage#1% + {\global\settrue\tableactionstatepermitted + \tabl_table_set_action\tableunknownstate + \tabl_table_set_force\tableunknownstate + \tabl_table_resetVLvalues + \appendtoks\tabl_table_local_setups\to\everytable + \tabl_table_standard_begin[\ifsplittables u\else b\fi]% + \the\localtabledefinitions + \forgetall % added + \edef\currenttableformat{#1}% + \doifsomething\currenttableformat + {\dogettablenofcolumns\currenttableformat + % more modern is to use catcode tables + \expandafter\tabl_table_begin_format\currenttableformat\doendtableformat}} + +\def\tabl_table_finish + {\tabl_tables_chuck_auto_row + \unskip\crcr + \tabl_table_normal_end + \global\intablefalse + \egroup} + +%D \macros +%D {starttables} +%D +%D Split tables are specified using the plural form of the start and stop commands. +%D +%D \showsetup{starttables} +%D +%D For example: +%D +%D \starttyping +%D \starttables[|||] +%D \HL +%D \VL element \VL atom weight \VL\AR +%D \HL +%D \VL ....... \VL ........... \VL\AR +%D \VL ....... \VL ........... \VL\AR +%D \HL +%D \stoptables +%D \stoptyping + +\newbox\tablecontentbox + +\permanent\protected\def\starttables + {\bgroup + \enforced\let\stoptables\table_table_stop_s + \splittablestrue + \edef\p_tabl_table_split{\directtablesparameter\c!split}% + \ifx\p_tabl_table_split\v!repeat + \settrue\c_tabl_table_repeat_head + \settrue\c_tabl_table_repeat_tail + \else + \setfalse\c_tabl_table_repeat_head + \setfalse\c_tabl_table_repeat_tail + \fi + \flushnotes + \setbox\tablecontentbox\vbox\bgroup + \forgetall + \tabl_table_first_stage} + +\aliased\let\stoptables\relax % needed for \noalign + +\def\table_table_stop_s % not \protected as we need the lookahead (brrr) + {\tabl_tables_chuck_auto_row % AM: before the tail, else noalign problem + \ifconditional\c_tabl_table_repeat_tail\else\tabl_table_insert_tail\fi + \tabl_table_finish + \egroup + \dontcomplain + \tabl_table_split_box\tablecontentbox + \glet\tabl_table_head\empty % new here + \glet\tabl_table_tail\empty % new here + \flushnotes + \egroup} + +\def\tabl_table_split_box#1% + {\resettsplit + \c_split_minimum_free_lines\plustwo + \d_split_minimum_free_space\zeropoint + \setbox\b_split_content\box#1% + \ifconditional\c_tabl_table_repeat_head \ifconditional\hassometablehead + \setbox\b_split_head\vsplit\b_split_content to \lineheight + \setbox\b_split_head\vbox{\unvbox\b_split_head}% \vpack ? + \fi \fi + \ifconditional\c_tabl_table_repeat_tail \ifconditional\hassometabletail + \setbox\b_split_tail\vsplit\b_split_content to \lineheight + \setbox\b_split_tail\vbox{\unvbox\b_split_tail}% \vpack ? + \fi \fi + \ifinsidefloat\else + \t_split_before_result{\startbaselinecorrection}% + \t_split_after_result {\stopbaselinecorrection}% + \fi + \handletsplit} + +%D When the table in the previous example is split across pages, only the first gets +%D a head. We could have said something like: +%D +%D \starttyping +%D \starttablehead +%D \HL +%D \VL element \VL atom weight \VL\AR +%D \HL +%D \stoptablehead +%D +%D \starttabletail +%D \HL +%D \stoptabletail +%D +%D \starttables[|||] +%D \VL ....... \VL ........... \VL\AR +%D \VL ....... \VL ........... \VL\AR +%D \stoptables +%D \stoptyping +%D +%D This time each split table gets a head line and ends with a rule. Keep in mind +%D that such heads also apply to the unbroken ones and should be defined local +%D (grouped) if needed. The rather complicated definition below is due to the fact +%D that the stopcondition is interface language dependant. + +\let\tabl_table_head\empty % needs checking +\let\tabl_table_tail\empty % needs checking + +\letvalue{\e!start\v!tablehead}\relax % todo: frozen, but we use a grabber +\letvalue{\e!stop \v!tablehead}\relax % todo: frozen, but we use a grabber +\letvalue{\e!start\v!tabletail}\relax % todo: frozen, but we use a grabber +\letvalue{\e!stop \v!tabletail}\relax % todo: frozen, but we use a grabber + +%D The second argument is a dummy one, by scanning for it, we get rid of +%D interfering spaces. + +\newconditional\preventtablebreak +\newconditional\hassometablehead +\newconditional\hassometabletail + +% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} +% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} + +\permanent\protected\def\settablehead{\dodoubleempty\tabl_table_set_head} % todo: use pickup +\permanent\protected\def\settabletail{\dodoubleempty\tabl_table_set_tail} % todo: use pickup + +\def\tabl_table_set_head[#1][#2]#3\end + {\gdef\tabl_table_head{\begincsname\??tablehead#1\endcsname}% new + \setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} + +\def\tabl_table_set_tail[#1][#2]#3\end + {\gdef\tabl_table_tail{\begincsname\??tabletail#1\endcsname}% new + \setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} + +\normalexpanded { + \aliased\letcsname\e!stop\v!tablehead\endcsname\relax + \aliased\letcsname\e!stop\v!tabletail\endcsname\relax +} + +\normalexpanded { + \permanent\protected\def\csname\e!start\v!tablehead\endcsname#1\csname\e!stop\v!tablehead\endcsname{\settablehead#1\noexpand\end} + \permanent\protected\def\csname\e!start\v!tabletail\endcsname#1\csname\e!stop\v!tabletail\endcsname{\settabletail#1\noexpand\end} +} + +%D Redundant \type{\HL}'s are removed automatically, so mid||lines can be used +%D without problems. +%D +%D The order of the next macros is more or less random. First we implement error +%D recovery. Errors are reported to the screen and log file as well as visualized in +%D the table in teletype. + +\def\tabl_table_finish_row + {\crcr + \noalign\bgroup + \nobreak + \tabl_table_set_action\tableunknownstate + \glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty + \global\currenttablecolumn\zerocount + \egroup} + +%D Next we enter the more complicated area of column and row switching. I won't go +%D into much detail from now on, but just mention the general principles. +%D +%D \startitemize[3*ruim] +%D \sym{\type{\SR}} end a separate row (between rules) +%D \sym{\type{\FR}} end a first row (after a rule) +%D \sym{\type{\MR}} end a mid row (between text lines) +%D \sym{\type{\LR}} end a last row (before a rule) +%D \stopitemize +%D +%D and best of all: +%D +%D \startitemize[continue] +%D \sym{\type{\AR}} end a row with automatic spacing +%D \stopitemize +%D +%D As far as possible, we report confusing situations. In most cases one can use +%D \type{\AR}, which transfigurates itself into one of the other types. +%D +%D \starttyping +%D \starttable[||] +%D \HL +%D \VL a separate row \VL\SR +%D \HL +%D \VL a first row \VL\FR +%D \VL a mid row \VL\MR +%D \VL a last row \VL\LR +%D \HL +%D \stoptable +%D \stoptyping +%D +%D In this example we could have used \type{\AR} without problems. +%D +%D Color or gray scale backgrounds precede the content. They are passed over +%D horizontal (division) lines when needed. Errors in the color template are traced +%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\ +%D handles alignments, we cannot automate spacing for colored rows and columns. + +\tablerowzero\zerocount + +\appendtoks + \enforced\let\SR\tabl_table_SR + \enforced\let\FR\tabl_table_FR + \enforced\let\MR\tabl_table_MR + \enforced\let\LR\tabl_table_LR + \enforced\let\AR\tabl_table_AR +\to \localtabledefinitions + +\protected\def\tabl_table_SR + {\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \fi + \tabl_table_end_row_indeed\tableseparaterowstate\tablerowfactor\tablerowfactor} + +\protected\def\tabl_table_FR + {\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablelastrowstate + \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% + \fi + \tabl_table_end_row_indeed\tablefirstrowstate\tablerowfactor\tablerowzero} + +\protected\def\tabl_table_MR + {\ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{change \string\MR\space into \string\FR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablelastrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\FR}% + \fi + \tabl_table_end_row_indeed\tablemidrowstate00} + +\protected\def\tabl_table_LR + {\ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{change \string\LR\space into \string\FR/\string\SR}% + \fi + \tabl_table_end_row_indeed\tablelastrowstate\tablerowzero\tablerowfactor} + +%D \macros +%D {ifcheckTABLEcolums} +%D +%D The next macros handle the actual row ending. This macro also take care of space +%D corrections due to table splitting when \type{\MR} and collegues are used. When +%D tracing is enabled, the corrections as well as the values used to determine the +%D available space are shown (in color). By default checking is off. + +\def\tabl_table_end_row_indeed#1#2#3% + {\tabl_table_set_action#1% + \ifcase#1\relax + % unknown + \or + \tabl_tables_end_line\SR\SR\tablerowfactor\tablerowfactor + \or + \tabl_tables_end_line\FR\FR\tablerowfactor\tablerowzero + \or + \ifnum\tableforcestate=\tableforcelastrowstate + \tabl_tables_end_line\MR\LR\tablerowzero\tablerowfactor + \orelse\ifnum\tableforcestate=\tableforcefirstrowstate + \tabl_tables_end_line\MR\FR\tablerowfactor\tablerowzero + \else + \tabl_tables_end_line\MR\MR\tablerowzero\tablerowzero + \fi + \or + \tabl_tables_end_line\LR\LR\tablerowzero\tablerowfactor + \fi + \noalign\bgroup + \tabl_table_set_force\tableunknownstate + \global\currenttablecolumn\zerocount + \ifconditional\preventtablebreak + \nobreak + \else + \goodbreak + \fi + \egroup} + +%D Handling \type{\AR} is postponed till the next row. The check takes care of +%D the first and mid rows, the chuck macro |<|how about that name|>| handles +%D the last row. + +\protected\def\tabl_table_AR + {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed + \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} + +\let\tabl_tables_check_auto_row\empty +\let\tabl_tables_chuck_auto_row\empty + +\def\tabl_tables_check_auto_row_indeed + {\glet\tabl_tables_check_auto_row\empty + \ifnum\tableactionstate=\tablerulestate \FR\orelse + \ifnum\tableactionstate=\tableunknownstate\FR\else + \MR\fi} + +\def\tabl_tables_chuck_auto_row_indeed + {\glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty + \ifnum\tableactionstate=\tablerulestate \SR\orelse + \ifnum\tableactionstate=\tableunknownstate\SR\else + \LR\fi} + +%D When a table is split, we also add a tail and when present we repeat the table +%D head. If a gets split indeed, the spacing before and after a horizontal rule is +%D corrected according to what we expect. + +\def\tabl_tables_end_line#1#2#3#4% + {\ifx#1#2\else + \writestatus\m!TABLE{\string#1\space changed into \string#2}% + \fi + \expandafter\tabl_table_normal_line_format#3#4\crcr % \crcr nodig ? + \noalign{\nobreak\global\settrue\tableactionstatepermitted}} + +%D In order to prevent (as good as possible) alignment overflow and therefore \TEX\ +%D error messages, we check the maximum number of columns. We keep track of the +%D current column and maximum column by means of two \COUNTERS. Keep in mind that +%D the number of \type{|}'s and \type{\VL}'s or alike is always one more than the +%D number of columns. + +\newcount\currenttablecolumn + +% DWhile defining this macro we change the \CATCODE\ of \type{|}. When counting the +% Dbars, we use a non active representation of the bar, simply because we cannot be +% Dsure if the bar is active or not.\footnote{Normally it is, but \TABLE\ changes +% Dthe catcode when needed.} + +\bgroup + \catcode\barasciicode\othercatcode \permanent\gdef\tabl_table_bar{|} + \catcode\barasciicode\activecatcode\gdef\tabl_table_use_bar{\enforced\let|\tabl_table_bar} +\egroup + +\bgroup \catcode\barasciicode\othercatcode + +\gdef\dogettablenofcolumns#1% todo: also divert this to lua as with tabulate + {\bgroup + \cleanupfeatures % needed ! + \tabl_table_use_bar + \egroup} + +\egroup + +%D \startitemize[3*ruim] +%D \sym{\type{\VL}} a vertical line +%D \sym{\type{\VC}} a vertical colored line +%D \sym{\type{\HL}} a horizontal line +%D \sym{\type{\HC}} a horizontal colored line +%D \stopitemize + +\newcount\c_tabl_table_vrule_thickness_factor +\newcount\c_tabl_table_hrule_thickness_factor +\newcount\c_tabl_table_drule_span + +\let\m_tabl_table_vrule_color\empty +\let\m_tabl_table_hrule_color\empty + +\appendtoks + \enforced\let\VL\tabl_table_VL + \enforced\let\VC\tabl_table_VC + \enforced\let\HL\tabl_table_HL + \enforced\let\HC\tabl_table_HC + \enforced\let\VS\tabl_table_VS + \enforced\let\VD\tabl_table_VD + \enforced\let\VT\tabl_table_VT + \enforced\let\VN\tabl_table_VN +\to \localtabledefinitions + +\def\tabl_table_resetVLvalues + {\global\currenttablecolumn\zerocount} + +\def\tabl_table_vrulecommand#1% global assignments + {\doifelsenumber{#1} + {\global\c_tabl_table_vrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax} + {\xdef\m_tabl_table_vrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_VL[#1]% + {\tabl_tables_check_auto_row + \global\advance\currenttablecolumn\plusone + \glet\m_tabl_table_vrule_color\empty + \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax + \iftok{#1}\emptytoks\else + \rawprocesscommalist[#1]\tabl_table_vrulecommand + \fi + \tabl_table_normal_line_complex_bar}% \relax breaks \use + +\permanent\let\tabl_table_VC\tabl_table_VL % for mojca + +% \starttable[|||] +% \HL +% \VL test \VS test \VL \FR +% \VL test \VD test \VL \MR +% \VL test \VT test \VL \LR +% \HL +% \stoptable + +\permanent\protected\def\tabl_table_VS {\VN1} +\permanent\protected\def\tabl_table_VD {\VN2} +\permanent\protected\def\tabl_table_VT {\VN3} +\permanent\protected\def\tabl_table_VN#1{\global\c_tabl_table_n_of_vrules#1\relax\VL} + +\def\tabl_table_hrulecommand#1% global assignments + {\doifelsenumber{#1} + {\global\c_tabl_table_hrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax} + {\xdef\m_tabl_table_hrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_HL[#1]% + {\tabl_tables_chuck_auto_row + \tabl_table_finish_row + \noalign\bgroup + \nobreak + \ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{skipping \string\HL}% \statusmessage + \else + \ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\SR}% + \fi + \bgroup + \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax + \ifparameter#1\or + \glet\m_tabl_table_hrule_color\empty + \rawprocesscommalist[#1]\tabl_table_hrulecommand + \ifempty\m_tabl_table_hrule_color\else + \switchtocolor[\m_tabl_table_hrule_color]% + \fi + \fi + \tabl_table_normal_full_rule + \egroup + \tabl_table_account_width + \fi + \tabl_table_set_action\tablerulestate + \nobreak + \egroup} + +\aliased\let\tabl_table_HC\tabl_table_HL % for mojca + +%D \startitemize[3*ruim] +%D \sym{\type{\NL}} a vertical skip +%D \sym{\type{\NR}} goto the next row +%D \sym{\type{\NC}} goto the next column +%D \sym{\type{\FC}} a first column +%D \sym{\type{\MC}} a mid column +%D \sym{\type{\LC}} a last column +%D \stopitemize + +% \starttable[|||] +% \VL text \VL text \VL \AR +% \TB[small] +% \VL text \VL text \VL \AR +% \TB[4*big] +% \VL text \VL text \VL \AR +% \stoptable + +% n+1 uitleggen + +\appendtoks + \enforced\let\TB\tabl_table_TB + \enforced\let\NL\tabl_table_NL % old + \enforced\let\NR\tabl_table_NR + \enforced\let\NC\tabl_table_NC + \enforced\let\FC\tabl_table_NC + \enforced\let\MC\tabl_table_NC + \enforced\let\LC\tabl_table_NC +\to \localtabledefinitions + +\permanent\tolerant\protected\def\tabl_table_TB[#1]% + {\tabl_tables_chuck_auto_row + \tabl_table_finish_row + \noalign\bgroup + \blank[\iftok{#1}\emptytoks\directtablesparameter\c!NL\else#1\fi]% + \nobreak + \egroup} + +\aliased\let\tabl_table_NL\tabl_table_TB + +\protected\def\tabl_table_NR + {\global\currenttablecolumn\zerocount + \tabl_table_normal_line_ending + \noalign\bgroup + \nobreak + \tabl_table_set_action\tableunknownstate + \egroup} + +\protected\def\tabl_table_NC + {\tabl_tables_check_auto_row + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_no_bar} + +%D \startitemize[3*broad] +%D \sym{\type{\DL}} +%D \sym{\type{\DV}} (\type{\VD}) +%D \sym{\type{\DC}} +%D \sym{\type{\DR}} +%D \stopitemize + +\newconditional\c_tabl_table_is_division + +\appendtoks + \global\setfalse\c_tabl_table_is_division + \enforced\let\DL\tabl_table_DL + \enforced\let\DC\tabl_table_DC + \enforced\let\DV\tabl_table_DV + \enforced\let\DR\tabl_table_DR +\to \localtabledefinitions + +\def\tabl_table_check_division + {\ifconditional\c_tabl_table_is_division\else + \tabl_tables_chuck_auto_row + \global\currenttablecolumn\zerocount + \global\settrue\c_tabl_table_is_division + \fi} + +\def\tabl_table_drulecommand#1% global assignments + {\doifelsenumber{#1} + {\ifcase\c_tabl_table_drule_span + \global\c_tabl_table_drule_span#1\relax + \else + \global\c_tabl_table_hrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_VLwidth\relax + \fi} + {\xdef\m_tabl_table_hrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_DL[#1]% + {\tabl_table_check_division + \ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{skipping \string\DL}% + \else + \ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\SR}% + \fi + \tabl_table_set_action\tableunknownstate + \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax + \global\c_tabl_table_drule_span\zerocount + \iftok{#1}\emptytoks\else + \glet\m_tabl_table_hrule_color\empty + \rawprocesscommalist[#1]\tabl_table_drulecommand + % \ifempty\m_tabl_table_hrule_color\else + % \switchtocolor[\m_tabl_table_hrule_color]% see *DL* + % \fi + \fi + \ifcase\c_tabl_table_drule_span + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_single_rule + \or + \global\advance\currenttablecolumn \plustwo + \tabl_table_normal_single_rule + \else + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_multi_rule + \fi + \fi} + +\permanent\protected\def\tabl_table_DV + {\tabl_table_DCV\tabl_table_normal_line_simple_bar} + +\permanent\protected\def\tabl_table_DC + {\tabl_table_DCV\tabl_table_normal_no_bar} + +\permanent\protected\def\tabl_table_DCV#1% + {\tabl_table_check_division + \tabl_tables_check_auto_row + \global\advance\currenttablecolumn \plusone + #1} + +\permanent\protected\def\tabl_table_DR + {\global\currenttablecolumn\zerocount % nog check + \tabl_table_normal_line_ending + \noalign\bgroup + \nobreak + \global\setfalse\c_tabl_table_is_division + \tabl_table_account_width % temporary solution + \tabl_table_set_action\tablerulestate + \egroup} + +\def\tabl_table_account_width + {\scratchdimen\d_tabl_table_line_thickness_unit} + +\permanent\def\tabl_table_TWO {\use\plustwo} +\permanent\def\tabl_table_THREE{\use\plusthree} +\permanent\def\tabl_table_FOUR {\use\plusfour} +\permanent\def\tabl_table_FIVE {\use\plusfive} +\permanent\def\tabl_table_SIX {\use\plussix} + +\appendtoks + \enforced\let\TWO \tabl_table_TWO + \enforced\let\THREE\tabl_table_THREE + \enforced\let\FOUR \tabl_table_FOUR + \enforced\let\FIVE \tabl_table_FIVE + \enforced\let\SIX \tabl_table_SIX + \enforced\let\SPAN \use + \enforced\let\REF \tabl_table_reformat +\to \localtabledefinitions + +\installcorenamespace{tables} +\installcorenamespace{tabledistance} +\installcorenamespace{tablealign} + +\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables + +\setvalue{\??tabledistance\v!none }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} +\setvalue{\??tabledistance\v!small }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} % == baseline +\setvalue{\??tabledistance\v!medium}{\tabl_table_OpenUp11\def\LOW{\Lower7 }} +\setvalue{\??tabledistance\v!big }{\tabl_table_OpenUp22\def\LOW{\Lower8 }} + +\appendtoks + \expandnamespaceparameter\??tabledistance\directtablesparameter\c!distance\v!medium +\to \localtabledefinitions + +\setvalue{\??tablealign\v!right }{\def\tabl_table_paralignment{\raggedright}} +\setvalue{\??tablealign\v!left }{\def\tabl_table_paralignment{\raggedleft}} +\setvalue{\??tablealign\v!middle }{\def\tabl_table_paralignment{\raggedcenter}} +\setvalue{\??tablealign\s!unknown}{\def\tabl_table_paralignment{\notragged}} + +\appendtoks + \doifelse{\directtablesparameter\c!distance}\v!none + {\tablerowfactor\zerocount} + {\tablerowfactor\plustwo }% +\to \localtabledefinitions + +\def\dohandlebar % here ? + {\ifmmode + \expandafter\domathmodebar + \orelse\ifintable + \expandafter\domathmodebar + \else + \expandafter\dotextmodebar + \fi} + +\appendtoks + \expandnamespaceparameter\??tablealign\directtablesparameter\c!align\s!unknown + \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246% + \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246% +\to \everysetuptables + +\def\tabl_table_local_setups + {\directtablesparameter\c!commands\relax + \usebodyfontparameter\directtablesparameter + \d_tabl_table_line_thickness_unit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax + \edef\p_tabl_table_height{\directtablesparameter\c!height}% + \edef\p_tabl_table_depth{\directtablesparameter\c!depth}% + \ifx\p_tabl_table_height\v!strut + \let\tablestrutheightfactor\tablestrutheightfactor + \else + \let\tablestrutheightfactor\p_tabl_table_height + \fi + \ifx\p_tabl_table_depth\v!strut + \let\tablestrutdepthfactor\tablestrutdepthfactor + \else + \let\tablestrutdepthfactor\p_tabl_table_depth + \fi + \edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}% + \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}% + \d_tabl_table_strut_unit \dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont + \d_tabl_table_kern_unit .5em\relax + \s_tabl_table_inter_column_space_unit.5em plus 1fil minus .25em\relax + \d_tabl_table_column_width_unit \d_tabl_table_kern_unit + \d_tabl_table_kern_unit \d_tabl_table_kern_unit} + +%D As one can see, we didn't only add color, but also more control over spacing. +%D +%D \startbuffer[a] +%D \starttable[|c|] +%D \HL +%D \VL \strut test \VL \FR +%D \VL \strut test \VL \MR +%D \VL \strut test \VL \MR +%D \VL \strut test \VL \LR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \startbuffer[b] +%D \starttabulate[|c|] +%D \HL +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \HL +%D \stoptabulate +%D \stopbuffer +%D +%D In the next example, the first table is defined as: +%D +%D \typebuffer[a] +%D +%D and the second one as: +%D +%D \typebuffer[b] +%D +%D The first table is typeset using the default height and depth factors .8 and .4. +%D The second table has both factors set to \type {strut}, and the third table shows +%D what happens when we set the values to zero. The rightmost table is typeset using +%D the tabulate environment. +%D +%D \startcombination[4*1] +%D {$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=.8 d=.4}} +%D {\setuptables[height=strut,depth=strut]$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=d=\type{strut}}} +%D {\setuptables[height=0,depth=0]$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=d=0}} +%D {$\vcenter{\getbuffer[b]}$} +%D {\hbox{tabulate}} +%D \stopcombination + +\setuptables + [\c!HL=\v!medium, + \c!VL=\v!medium, + \c!NL=\v!small, + \c!frame=, + \c!align=\v!right, + \c!depth=.40, % \v!strut + \c!height=.80, % \v!strut + \c!textwidth=, + \c!rulethickness=\linewidth, + \c!rulecolor=, + \c!distance=\v!medium, + \c!bodyfont=, + \c!commands=, + \c!background=, + \c!backgroundcolor=, + \c!split=\v!auto, + \c!openup=\zeropoint] + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl new file mode 100644 index 000000000..9b3ec4750 --- /dev/null +++ b/tex/context/base/mkxl/tabl-tbl.mkxl @@ -0,0 +1,2929 @@ +%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}{} % experiment + +%D I can probably reimplement this using a \LUATEX\ combination but it does not pay +%D of in development time. If I need something else I will write it from scratch +%D anyway. This module looks a bit complex which is a consequence of it dealing with +%D paragraphs being split over pages and that there are several passes over the data +%D set. We can probably do some cleanup (combine/split). +%D +%D Caching the preamble does not save much (compared to other bits and pieces of +%D \CONTEXT). There are not that many ways to deal with preambles and this is just +%D one of them. The keys are 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 skip left of column +% j i skip right of column +% k i 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_every_real_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_max_vrulecolumn +\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_nofrealrows +\newcount \c_tabl_tabulate_autocolor + +\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser +\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count) +\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_kind % 1=strong 2=equals +\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 + +\newtoks \everytabulatepar % where used ? +\newtoks \everytabulate % public ? + +\protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles ! +\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated + +\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty + +\installcorenamespace{tabulatebox} +\installcorenamespace{tabulatesetup} +\installcorenamespace{tabulatehook} +\installcorenamespace{tabulatesplit} +\installcorenamespace{tabulateseparator} +\installcorenamespace{tabulatecolor} +\installcorenamespace{tabulateheader} +\installcorenamespace{tabulatealigning} +\installcorenamespace{tabulatepreamble} +\installcorenamespace{tabulatevrule} + +\installcorenamespace{tabulatehead} +\installcorenamespace{tabulatefoot} +\installcorenamespace{tabulatenext} + +\prependtoks + \global\c_tabl_tabulate_nofrealrows\zerocount +\to \t_tabl_tabulate_initializers_first + +\prependtoks + \global\c_tabl_tabulate_nofrealrows\zerocount +\to \t_tabl_tabulate_initializers_second + +\prependtoks + \global\advance\c_tabl_tabulate_nofrealrows\plusone +\to \t_tabl_tabulate_every_real_row + +\def\b_tabl_tabulate_current#1% + {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym + +\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 + \else + \tabl_tabulate_initialize_box_nop#1% + \fi} + +\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 + +% [|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} + +\installtextracker + {tables.tabulate.breaks} + {\let\tabl_tabulate_break_no_tracer\tabl_tabulate_nobreak_inject_tracer} + {\let\tabl_tabulate_break_no_tracer\donothing} + +\let\tabl_tabulate_break_no_tracer\donothing + +\def\tabl_tabulate_nobreak_inject_indeed + {\tabl_tabulate_break_no + \tabl_tabulate_break_no_tracer} + +\def\tabl_tabulate_nobreak_inject + {\noalign{\tabl_tabulate_nobreak_inject_indeed}} + +\protected\def\tabl_tabulate_hook_check + {\ifnum\c_tabl_tabulate_type<\plustwo + \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop + \else + \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes + \fi} + +\protected\def\tabl_tabulate_setups_check + {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname} + +\protected\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook} +\protected\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi} + +\protected\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 + +\protected\def\tabl_tabulate_check_local_color_first#1#2% + {\relax} + +\protected\def\tabl_tabulate_check_local_color_second#1#2% + {\relax + \ifempty\m_tabl_tabulate_color_local + \xdef\m_tabl_tabulate_color{#1}% + \else + \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local + \glet\m_tabl_tabulate_color_local\empty + \fi + \ifcase\c_tabl_tabulate_localcolorspan + \global\c_tabl_tabulate_colorspan#2\relax + \else + \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan + \global\c_tabl_tabulate_localcolorspan\zerocount + \fi} + +\protected\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} + +\protected\def\tabl_tabulate_check_local_vrule_color_first#1% + {\relax} + +\protected\def\tabl_tabulate_check_local_vrule_color_second#1% + {\relax + \ifempty\m_tabl_tabulate_vrule_color_local + \xdef\m_tabl_tabulate_vrule_color{#1}% + \else + \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local + \glet\m_tabl_tabulate_vrule_color_local\empty + \fi} + +\let\tabl_tabulate_check_local_color \gobbletwoarguments +\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 + +% \protected % we can expand this one +\def\tabl_tabulate_inject_pre_skip#1% + {\ifdim#1>\zeropoint + \kern#1\relax % was \hskip + \orelse\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} + +% \protected % we can expand this one +\def\tabl_tabulate_inject_post_skip#1% + {\ifdim#1>\zeropoint + \kern#1\relax % was \hskip + \orelse\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} + +\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 + \ifempty\m_tabl_tabulate_alignment \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 + \ifempty\m_tabl_tabulate_text_color + \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} + +\permanent\protected\def\installtabulatepreambleoption#1#2% + {\defcsname\??tabulatepreamble\string#1\endcsname{#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}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}% + \tabl_tabulate_set_preamble} +\installtabulatepreambleoption{g}{\tabl_tabulate_set_align} +\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.} +\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,} +\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span} +\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}% + \tabl_tabulate_set_preamble} +\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble} +\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment} + +%D We no longer deal with \type {~} here but map it onto \type {d} instead. Of +%D course we could prefix a key with \type {\meaning} instead, which works ok (and +%D is needed in order to pseudo expand \type {\next}, but is ugly at the same time. +%D The type {d} stands for digitspace. + +%D \starttyping +%D \installtabulatepreambleoption{~}{...} % see 'd' +%D \stoptyping +%D +%D Also, as there is always a key, we no longer do some after assigment or future +%D let but just pick up the key. + +% \installtabulatepreambleoption \s!unknown % +% {\writestatus{tabulate}{unknown preamble key [\normalmeaning\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% + {\defcsname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname{\setups[#1]}% + \tabl_tabulate_set_preamble} + +\def\tabl_tabulate_set_hook#1% + {\defcsname\??tabulatehook\the\c_tabl_tabulate_columns\endcsname{#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} + +% faster but seldom used +% +% \installcorenamespace{tabulatewidth} +% +% \setvalue{\??tabulatewidth\v!fit }{\c_tabl_tabulate_modus\plusthree} +% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak} +% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape} +% +% \def\tabl_tabulate_set_width_step#1% +% {\ifcsname\??tabulatewidth#1\endcsname +% \lastnamedcs +% \else +% \d_tabl_tabulate_width#1\relax +% \fi} +% +% \def\tabl_tabulate_set_width_indeed(#1)% +% {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step +% \ifconditional\c_tabl_tabulate_pwidth_set +% \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth +% \fi +% \tabl_tabulate_set_preamble} +% +\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi} +\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi} +\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi} +\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\orelse\if#1M\plustwo\orelse\if#1R\plusthree\else\zerocount\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 + \glet\m_tabl_tabulate_alignment\empty + \glet\m_tabl_tabulate_color\empty + \glet\m_tabl_tabulate_text_color\empty + \glet\m_tabl_tabulate_vrule_color\empty + \global\c_tabl_tabulate_colorspan\zerocount + \global\setfalse\c_tabl_auto_align_mode + \global\advance\c_tabl_tabulate_columns\plusone + \letcsname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ? + \edef\currenttabulationtrulespec{#1}% + \ifempty\currenttabulationtrulespec + \global\d_tabl_tabulate_vrulethickness\zeropoint + \else + \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default + % the lmtx raw processor handles {} like the normal one so we need to prune + \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command + \fi + \tabl_tabulate_set_preamble#2\relax\relax % permits i without n + \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 + {\glet\m_tabl_tabulate_color\empty + \glet\m_tabl_tabulate_vrule_color\empty + \edef\currenttabulationtrulespec{#1}% + \ifempty\currenttabulationtrulespec + \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} + +\protected\def\tabl_tabulate_hook_nop + {} + +\let\tabl_tabulate_hook\tabl_tabulate_hook_nop + +\def\tabl_tabulate_hook_yes{\begincsname\??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 + \orelse\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} + +\def\tabl_tabulate_pbreak_check + {\noalign\bgroup + \tabl_tabulate_pbreak_inject + \ifconditional\c_tabl_tabulate_splitoff_whitespace + \tabl_tabulate_whitespace + \fi + \egroup} + +%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 Because we want to be compatible we use an indirect way to implement the +%D definers. The next examples demonstrate 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] + +\permanent\tolerant\protected\def\definetabulate[#1]#*[#2]#*[#3]% + {\ifarguments + % ignore + \or + % [tag] + \definetabulation[#1][\c!format={|l|p|},\s!check=]% + \or + % [tag] [template] + \definetabulation[#1][\c!format={#2},\s!check=]% + \or + % [tag] [sub] [template] + \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else + \definetabulation[#1][\c!format={#3},\s!check=]% + \fi + \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]% + \fi} + +\permanent\tolerant\protected\def\setuptabulate[#1]#*[#2]#*[#3]% + {\ifarguments + % ignore + \or + % [tag] + \setuptabulation[#1]% + \or + % [tag] [settings] + \setuptabulation[#1][#2]% + \or + % [tag] [sub] [settings] + \setuptabulation[#1:#2][#3]% + \fi} + +\appendtoks + \enforced\permanent\protected\edefcsname\e!start \currenttabulation\endcsname{\tabl_start_defined[\currenttabulation]}% + \enforced\aliased \letcsname \e!stop \currenttabulation\endcsname\relax + \enforced\aliased \letcsname \??tabulatehead\currenttabulation\endcsname\empty + \enforced\aliased \letcsname \??tabulatefoot\currenttabulation\endcsname\empty +\to \everydefinetabulation + +\aliased \let\tabulateparameter\tabulationparameter % will stay for a while +\permanent\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 + {\noalign{\global\settrue\c_tabl_tabulate_someamble}% + \begincsname\??tabulatehead\currenttabulation\endcsname + \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% + +\def\tabl_tabulate_insert_foot_content + {\noalign{\global\settrue\c_tabl_tabulate_someamble}% + \begincsname\??tabulatefoot\currenttabulation\endcsname + \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% + +\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header + {\ifcsname\??tabulatehead\currenttabulation\endcsname + %\expandafter\ifempty\csname\??tabulatehead\currenttabulation\endcsname + \expandafter\ifempty\lastnamedcs + \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\ifempty\csname\??tabulatefoot\currenttabulation\endcsname + %\expandafter\ifempty\lastnamedcs + \let\tabl_tabulate_insert_foot\empty + \else + \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_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 + \noalign{\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 + \noalign{\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]} + +\protected\def\tabl_start_defined[#1]% + {\bgroup + \edef\currenttabulationparent{#1}% + \let\currenttabulation\currenttabulationparent + \iftok{\tabulationparameter\c!format}{\v!none}% + % this is special case: we need to define the generic english + % \starttabulate in other interfaces as well + \lettabulationparameter\c!format\tabl_default_format + \expandafter\tabl_start_regular + \else + \expandafter\tabl_start_defined_indeed + \fi} + +\tolerant\def\tabl_start_defined_indeed[#1]#*[#2]% + {\ifarguments\or + \ifhastok={#1}% + \setuptabulation[\currenttabulation][#1]% + \else + \edef\currenttabulation{\currenttabulation:#1}% + \fi + \else + \edef\currenttabulation{\currenttabulation:#1}% + \setuptabulation[\currenttabulation][#2]% + \fi + \tabl_tabulate_start_building} + +% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one + +\def\tabl_default_format{|l|p|} % actually format is always set + +\permanent\protected\setuvalue{\e!start\v!tabulate}% + {\bgroup % whole thing + \let\currenttabulationparent\empty + \tabl_start_regular} + +\tolerant\protected\def\tabl_start_regular[#1]#*[#2]% [format] | [settings] | [format] [settings] | [settings] [format] + {\let\currenttabulation\currenttabulationparent + \iftok{#1}\emptytoks + \ifhastok={#2}\relax + \setupcurrenttabulation[#2]% + \fi + \orelse\ifhastok={#1} + \ifhastok{#2}\relax + \settabulationparameter\c!format{#2}% + \fi + \setupcurrenttabulation[#1]% + \else + \settabulationparameter\c!format{#1}% + \ifhastok={#2}\relax + \setupcurrenttabulation[#2]% + \fi + \fi + \tabl_tabulate_start_building} + +\letvalue{\e!stop\v!tabulate }\relax +\letvalue{\e!stop\v!tabulatehead}\relax +\letvalue{\e!stop\v!tabulatetail}\relax + +\permanent\protected\def\tabl_tabulate_start_ignore % todo when we go frozen + {\em Nested tabulate is not (yet) supported.\relax + \expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname} + +\appendtoks + \enforced\letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one +\to \everytabulate + +\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split} +\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 + +% \let\tabl_tabulate_inside_before \relax +% \let\tabl_tabulate_inside_after \relax +% \let\tabl_tabulate_inside_inbetween\relax +% +% \def\tabl_tabulate_outside_before +% {\whitespace +% \tabulationparameter\c!before} +% +% \def\tabl_tabulate_outside_after +% {\tabulationparameter\c!after} + +% \showboxes +% +% \startcombination +% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} +% {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} +% \stopcombination +% +% \startcombination +% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {} +% {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {} +% \stopcombination +% +% \startcombination +% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} +% {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {} +% \stopcombination + +\let\tabl_tabulate_inside_after \relax +\let\tabl_tabulate_outside_after \relax +\let\tabl_tabulate_inside_inbetween \relax +\let\tabl_tabulate_outside_inbetween\relax + +\protected\def\tabl_tabulate_inside_before + {\ifhmode\par\fi + \ifhmode + \ifinsidesplitfloat + \let\tabl_tabulate_inside_after\relax + \else + \vbox\bgroup + \let\tabl_tabulate_inside_after\egroup + \fi + \else + \let\tabl_tabulate_inside_after\relax + \fi} + +\protected\def\tabl_tabulate_outside_before + {\ifhmode\par\fi + \ifhmode + \vbox\bgroup + \let\tabl_tabulate_outside_after \egroup + \let\tabl_tabulate_outside_inbetween\relax + \orelse\ifinner + \let\tabl_tabulate_outside_after \relax + \let\tabl_tabulate_outside_inbetween\relax + \else + \whitespace + \tabulationparameter\c!before + \relax + \let\tabl_tabulate_outside_after \tabl_tabulate_outside_after_indeed + \let\tabl_tabulate_outside_inbetween\tabl_tabulate_outside_inbetween_indeed + \fi} + +\def\tabl_tabulate_outside_after_indeed + {\tabulationparameter\c!after} + +\def\tabl_tabulate_outside_inbetween_indeed + {\doifempty{\tabulationparameter\c!after} + {\vskip\strutdp + \verticalstrut + \vskip-\struttotal}} + +\def\tabl_tabulate_inside_inbetween % needs checking + {\doifempty{\tabulationparameter\c!after} + {\vskip\strutdp + \verticalstrut + \vskip-\struttotal}} + +\protected\def\tabl_tabulate_start_building + {\ifinsidefloat + \tabl_tabulate_inside_before + \else + \tabl_tabulate_outside_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}% + \edef\p_keeptogether {\tabulationparameter\c!keeptogether}% + \edef\p_blank {\tabulationparameter\c!blank}% + % + \ifx\p_keeptogether\v!no + \settrue \c_tabl_tabulate_tolerant_break + %\setfalse\c_tabl_tabulate_handlepbreak + \else + \setfalse\c_tabl_tabulate_tolerant_break + %\settrue \c_tabl_tabulate_handlepbreak + \fi + % + \settrue\c_tabl_tabulate_split + \begincsname\??tabulatesplit\tabulationparameter\c!split\endcsname + % + \let\m_tabl_tabulate_blank_default\p_blank + % + \d_tabl_tabulate_unit\tabulationparameter\c!unit + \d_tabl_tabulate_margin\tabulationparameter\c!margin + \let\m_tabl_tabulate_vrule_color_default\p_rulecolor + \let\m_tabl_tabulate_hrule_color_default\p_rulecolor + \d_tabl_tabulate_vrulethickness_default\p_rulethickness + \d_tabl_tabulate_hrulethickness_default\p_rulethickness + \ifempty\p_bodyfont\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 % stoptabulate needs to match the frozen one + {\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifempty\currenttabulationparent\v!tabulate\else\currenttabulationparent\fi\fi} + \tabl_tabulate_insert_body + \tabl_tabulate_process} + +\def\tabulateEQ + {\ifconditional\c_tabl_tabulate_firstflushed\else + \dostarttaggedchained\t!ignore\empty\empty + \dostarttagged\t!ignore\empty + \tabulationparameter{EQ}% + \dostoptagged + \dostoptagged + \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 +\let\m_tabl_tabulate_blank_default \empty + +\appendtoks + \glet\m_tabl_tabulate_color_previous \empty + \glet\m_tabl_tabulate_color \empty + \glet\m_tabl_tabulate_text_color \empty + \glet\m_tabl_tabulate_color_local \empty + \glet\m_tabl_tabulate_vrule_color \empty + \glet\m_tabl_tabulate_vrule_color_local \empty + \global \d_tabl_tabulate_vrulethickness_local\zeropoint +\to \t_tabl_tabulate_every_row + +\protected\def\tabl_tabulate_color_side_right_second + {\ifempty\m_tabl_tabulate_color_previous \else + \tabl_tabulate_color_set\m_tabl_tabulate_color_previous + \glet\m_tabl_tabulate_color_previous\empty + \fi} + +\protected\def\tabl_tabulate_color_side_left_second + {\ifempty\m_tabl_tabulate_color \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} + +\protected\def\tabl_tabulate_color_side_both_second + {\ifempty\m_tabl_tabulate_color \else + \tabl_tabulate_color_set\m_tabl_tabulate_color + \ifcase\c_tabl_tabulate_colorspan + %\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 / todo + {\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\zerocount} + +\def\tabl_tabulate_set_color_column_yes#1[#2]% + {\xdef\m_tabl_tabulate_color_local{#2}% + \tabl_tabulate_column_normal\zerocount#1} + +% normal columns: + +\def\tabl_tabulate_column_normal#1#2% + {\unskip + \aligntab + \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi + \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn\else + \tabl_tabulate_column_vrule_setup + \fi + \aligntab + \global\c_tabl_tabulate_kind#1% + \global\c_tabl_tabulate_type#2% + \aligntab} + +% equal columns + +\def\tabl_tabulate_column_equal#1#2% + {\unskip + \aligntab + \tabulateequalpos + \aligntab + \global\c_tabl_tabulate_kind#1% + \global\c_tabl_tabulate_type#2% + \aligntab} + +% ruled columns + +\def\tabl_tabulate_column_vruled_preset + {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default + \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default} + +\def\tabl_tabulate_column_vruled#1#2% + {\unskip % 0-n + %\ifnum\c_tabl_tabulate_column=\plusone + % \global\c_tabl_tabulate_has_rule_spec_first\plusone + %\orelse\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns + % \global\c_tabl_tabulate_has_rule_spec_last\plusone + %\fi + \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn + \global\c_tabl_tabulate_max_vrulecolumn\c_tabl_tabulate_column + \fi + \doifelsefastoptionalcheck{\tabl_tabulate_column_vruled_yes#1#2}{\tabl_tabulate_column_vruled_nop#1#2}} + +\def\tabl_tabulate_column_vrule_setup + {\begincsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname} + +\def\tabl_tabulate_column_vruled_nop + {\gletcsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname\tabl_tabulate_column_vruled_preset + \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[#3]% + {\gdefcsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname + {\tabl_tabulate_column_vruled_preset + \rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step}% + \tabl_tabulate_column_normal#1#2} + +\def\tabl_tabulate_vrule_reset + {\ifcase\c_tabl_tabulate_max_vrulecolumn\else + \tabl_tabulate_vrule_reset_indeed + \fi} + +\def\tabl_tabulate_vrule_reset_indeed + {\dofastloopcs\c_tabl_tabulate_max_vrulecolumn\tabl_tabulate_vrule_reset_step + \global\c_tabl_tabulate_max_vrulecolumn\zerocount} + +\def\tabl_tabulate_vrule_reset_step % undefined or relax + {\gletcsname\??tabulatevrule\the\fastloopindex\endcsname\undefined} + +\appendtoks + \tabl_tabulate_vrule_reset +\to \t_tabl_tabulate_every_after_row + +\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} + +\protected\def\tabl_tabulate_column_vrule_inject_first + {\ifcase\d_tabl_tabulate_vrulethickness\else + \tabl_tabulate_column_vruled_normal % could be a skip instead + \fi + \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one + +\protected\def\tabl_tabulate_column_vrule_inject_second + {\ifcase\d_tabl_tabulate_vrulethickness\else + \ifempty\m_tabl_tabulate_vrule_color + \tabl_tabulate_column_vruled_normal + \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\zerocount + \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax + \expandafter\NR + \else + \expandafter\ignorespaces % interferes with the more tricky hooks + \fi} + +\protected\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public) + {\enforced\let#1\tabl_tabulate_column_inject_auto + \enforced\let\\\tabl_tabulate_column_inject_auto} % brrr, will go + +\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount} +\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp} +\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 + \ifempty\p_distance\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_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]% + {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default + \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default + \iftok{#1}\emptytoks\else\rawprocesscommalist[#1]\tabl_tabulate_hrule_preset_step\fi} + +\def\tabl_tabulate_hrule_inject_normal + {\autorule + \s!height.5\d_tabl_tabulate_hrulethickness_local + \s!depth .5\d_tabl_tabulate_hrulethickness_local + \s!left \d_tabl_tabulate_indent + \relax} + +\def\tabl_tabulate_hrule_inject_colored + {\dousecolorparameter\currenttabulationlocalhrulecolor + \tabl_tabulate_hrule_inject_normal} + +\protected\def\tabl_tabulate_hrule_inject_first + {\ifcase\d_tabl_tabulate_hrulethickness_local\else + \tabl_tabulate_hrule_inject_normal + \fi} + +\protected\def\tabl_tabulate_hrule_inject_second + {\ifcase\d_tabl_tabulate_hrulethickness_local\else + \ifempty\currenttabulationlocalhrulecolor + \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 + +\protected\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call + {\begingroup + \clf_enablebackgroundalign % was \node_backgrounds_align_initialize + \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second + \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 + \xdefcsname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}% + \hpack \thealignbackgroundcolorattr{#1}{}% pack ? + \endgroup} + +\def\tabl_tabulate_color_repeat_second % for split off lines + {\begingroup + \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly ! + \ifcsname\??tabulatecolor\the\scratchcounter\endcsname + % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ? + \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\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? + {\gletcsname\??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_indeed + {\hbox to \d_tabl_tabulate_indent % pack ? + {% we now have a local hsize, and since we want to + % register positional info (i.e. real hsizes) we + % need to reconstitute the original hsize + \advance\hsize\d_tabl_tabulate_indent + % this is indeed rather messy and took a few hours + % to dis/uncover + \the\t_tabl_tabulate_every_row + \hss}} + +\def\tabl_tabulate_flush_indent + {\ifnum\c_tabl_tabulate_column=\zerocount + \tabl_tabulate_flush_indent_indeed + \fi} + +\def\tabl_tabulate_digits{\digits} + +%D Beware, we cannot use \type {\protected} on \type {\HL} cum suis, since \TEX's +%D hard coded noalign lookahead fails on it! I mistakenly added this for a while. + +\setvalue{\??tabulatealigning\v!normal}{0} +\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} + +\protected\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} +\protected\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} +\protected\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} +\protected\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} + +\let\tabl_tabulate_bbskip\relax +\let\tabl_tabulate_eeskip\relax +\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_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 + +\permanent\protected\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone} +\permanent\protected\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo} +\permanent\protected\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount} +\permanent\protected\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone} +\permanent\protected\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo} + +\permanent\protected\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first +\permanent\protected\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake + +\permanent\protected\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row +\permanent\protected\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break + +\permanent\protected\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row +\permanent\protected\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break + +\permanent\protected\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount} + +%D Sort of special: +%D +%D \startbuffer +%D \startitemize[n] +%D \starttabulate[|||||] +%D \NC p \NC \itemtag \NC q \NC r \NC \NR +%D \NC p \NC \itemtag \NC q \NC r \NC \NR +%D \NC p \NC \itemtag \NC q \NC r \NC \NR +%D \NC p \NC \itemtag \NC q \NC r \NC \NR +%D \stoptabulate +%D \stopitemize +%D +%D \startitemize[n] +%D \starttabulate[|||||] +%D \NI b \NC c \NC d \NC \NR +%D \NC a \NI c \NC d \NC \NR +%D \NC a \NC b \NI d \NC \NR +%D \NC a \NC b \NC c \NI \NR +%D \stoptabulate +%D \stopitemize +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\permanent\tolerant\protected\def\tabl_tabulate_NI_first[#1]{\NC\itemtag[#1]\NC} + +%D The following shortcut is handy for tables where one needs bold headers: + +\permanent\protected\def\tabl_tabulate_BC_first + {\tabl_tabulate_column_normal\plusone\zerocount + \let\fontstyle\globalfontstyle + \bf} + +\appendtoks + \enforced\let\VL\tabl_tabulate_VL_first + \enforced\let\NC\tabl_tabulate_NC_first + \enforced\let\BC\tabl_tabulate_BC_first + \enforced\let\RC\tabl_tabulate_RC_first + \enforced\let\HC\tabl_tabulate_HC_first + \enforced\let\EQ\tabl_tabulate_EQ_first + \enforced\let\RQ\tabl_tabulate_RQ_first + \enforced\let\HQ\tabl_tabulate_HQ_first + \enforced\let\NG\tabl_tabulate_NG_first + \enforced\let\NN\tabl_tabulate_NN_first + \enforced\let\ND\tabl_tabulate_ND_first + \enforced\let\NR\tabl_tabulate_NR_first + \enforced\let\NB\tabl_tabulate_NB_first + \enforced\let\CC\tabl_tabulate_CC_first + \enforced\let\CL\tabl_tabulate_CL_first + \enforced\let\CM\tabl_tabulate_CM_first + \enforced\let\CR\tabl_tabulate_CR_first + \enforced\let\NI\tabl_tabulate_NI_first +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \enforced\let\NR\tabl_tabulate_NR_second + \enforced\let\NB\tabl_tabulate_NB_second +\to \t_tabl_tabulate_initializers_second + +\appendtoks + \enforced\let\SR\NR + \enforced\let\FR\NR + \enforced\let\MR\NR + \enforced\let\LR\NR + \enforced\let\AR\NR +\to \t_tabl_tabulate_initializers_first + +\permanent\protected\def\tabl_tabulate_NR_common#1#2% + {\global\advance\c_tabl_tabulate_noflines\plusone + \global\setfalse\c_tabl_tabulate_firstflushed + \global\setfalse\c_tabl_tabulate_equal + \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 + \noalign{\the\t_tabl_tabulate_every_after_row#2}} + +\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 + \orelse\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 + \global\setfalse\c_tabl_tabulate_firstflushed} + +\protected\def\tabl_tabulate_bbskip_second_split_yes + {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column + \ifempty\tabl_tabulate_flush_collected_indeed\else + \setbox0\hbox + \fi + \fi} + +\protected\def\tabl_tabulate_eskip_second + {\par\egroup + \tabl_tabulate_pheight_set + \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes + \tabl_tabulate_splitoff_box} + +\protected\def\tabl_tabulate_bskip_second_split_yes + {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column + % first line + \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox + \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} + +\protected\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip} +\protected\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip} + +\protected\def\tabl_tabulate_flush_second_indeed + {\glet\tabl_tabulate_flush_collected_indeed\empty + \global\c_tabl_tabulate_column\zerocount + \tabl_tabulate_pbreak_check + \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step + \global\settrue\c_tabl_tabulate_firstflushed} + +\protected\def\tabl_tabulate_flush_second_step + {\ifvoid\b_tabl_tabulate_current\fastloopindex\else + \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}% + \fi} + +\def\tabl_tabulate_flush_second + {\noalign{\tabl_tabulate_flush_second_indeed}% + \tabl_tabulate_flush_collected_indeed} + +\protected\def\tabl_tabulate_bskip_second_split_nop + {\vtop\bgroup + \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi + % \begstrut % interferes with pre-\pars + % evt: \appendtoks\begstrut\to\everypar + \ignorespaces} + +\protected\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 + +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_XX_none [#1]{\noalign{\tabl_tabulate_break_state_set}} + +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_FL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_FL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_ML_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_ML_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_LL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_LL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_TL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_BL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_BL_second_indeed}} + +\protected\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} + +\def\spac_vspacing_no_topskip % use grouped + {\c_attr_skipcategory\plusten} + +\protected\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} + +\protected\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 + \tabl_tabulate_inside_inbetween + \else + \tabl_tabulate_outside_inbetween + \fi} + +\protected\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} + +\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed + +\permanent\def\tabl_tabulate_HL_second + {\csname + \ifnum\c_tabl_tabulate_noflines=\zerocount F\orelse + \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else + M\fi + L\endcsname} + +\appendtoks + \enforced\let\FL\tabl_tabulate_XX_none + \enforced\let\ML\tabl_tabulate_XX_none + \enforced\let\LL\tabl_tabulate_XX_none + \enforced\let\TL\tabl_tabulate_XX_none + \enforced\let\BL\tabl_tabulate_XX_none + \enforced\let\HL\tabl_tabulate_XX_none + \enforced\let\HR\tabl_tabulate_XX_none +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \enforced\let\FL\tabl_tabulate_FL_second + \enforced\let\ML\tabl_tabulate_ML_second + \enforced\let\LL\tabl_tabulate_LL_second + \enforced\let\TL\tabl_tabulate_TL_second + \enforced\let\BL\tabl_tabulate_BL_second + \enforced\let\HL\tabl_tabulate_HL_second + \enforced\let\HR\tabl_tabulate_HL_second +\to \t_tabl_tabulate_initializers_second + +% \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: + +\permanent\def\tabulaterule {\HR} % a rule with lineheight +\permanent\def\tabulateline {\HL} % just a spaced rule +\permanent\def\tabulateautorule{\HR}% +\permanent\def\tabulateautoline{\HL} % no longer different (to be looked into) + +%D When support for vertical rules we needed a way to pick up the specification for +%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to +%D become more complex and I was not in the mood for messing up the code too much. +%D Therefore from now on the preamble is split by \LUA. There are definitely more +%D places where we can use \LUA\ code (for instance in alignment of numbers. The +%D 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_check_side_float % new per 29-07-2016 + {\ifdefined\page_sides_check_floats_indeed + \page_sides_check_floats_indeed + \ifdim\hangindent>\zeropoint + \advance\d_tabl_tabulate_indent\hangindent + \fi + \fi} + +\def\tabl_tabulate_set_local_hsize + {\setlocalhsize + \hsize\localhsize} + +% test case for pre/post spacing: +% +% \ruledvbox{\starttabulate[|l|] \FL\NC xxx \NC \NR\LL\stoptabulate} +% \ruledvbox{\starttabulate[|l|l|]\FL\NC xxx \NC xxx \NC \NR\LL\stoptabulate} +% \ruledvbox{\starttabulate[|l|] \NC xxx \NC \NR \stoptabulate} +% \ruledvbox{\starttabulate[|lj8|] \NC xxx \NC \NR \stoptabulate} +% \ruledvbox{\starttabulate[|k8|] \NC xxx \NC \NR \stoptabulate} +% \ruledvbox{\starttabulate[|l|l|] \NC xxx \NC xxx \NC \NR \stoptabulate} + +\def\tabl_tabulate_process + {\c_tabl_tabulate_pass\plusone + \tabl_tabulate_check_full_content + \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}% + \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\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 + \orelse\ifinsidefloat + \donefalse + \else + \donetrue + \fi + \global\c_tabl_tabulate_repeathead + \ifdone + \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname + \lastnamedcs + \else + \zerocount + \fi + \else + \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_check_side_float + \tabl_tabulate_set_local_hsize + \fi + \dontcomplain + \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved + \everypar\everytabulatepar + \setbox\scratchbox\vbox % outside \if because of line counting + {\notesenabledfalse + \d_tabl_tabulate_indent\zeropoint + \settrialtypesetting % very important + \anch_backgrounds_text_level_start + \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}% + \anch_backgrounds_text_level_stop + \ifcase\c_anch_backgrounds_text_state\else + \global\settrue\tablehaspositions + \fi + \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-\wd\scratchbox-\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 + \setbox\scratchbox\emptybox % free memory + \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 + \enforced\let\HL\HR + \enforced\let\tabulateautoline\tabulateautorule + \enforced\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\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}% +% \toksapp\everycr{\noalign{\the\t_tabl_tabulate_every_real_row\dostoptagged\dostarttagged\t!tabulaterow\empty}}% + \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}% + \dostoptagged + \dostoptagged + \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 + \tabl_tabulate_inside_after + \else + \tabl_tabulate_outside_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% + \orelse\ifinsidefloat + \unvbox#1% + \else + \tabl_split_box_indeed#1% + \fi} + +\def\tabl_split_box_indeed#1% + {\resettsplit + \c_split_minimum_free_lines\plustwo + \d_split_minimum_free_space\zeropoint + \setbox\b_split_content\box#1% + \ifcase\c_tabl_tabulate_repeathead\or + \setbox\b_split_head\vsplit\b_split_content to \lineheight + \setbox\b_split_head\vbox{\unvbox\b_split_head}% + \or + \setbox\b_split_head\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 + +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TB[#1]% + {\noalign\bgroup + \unless\iftok{#1}\emptytoks + \blank[#1] + \orelse\ifempty\m_tabl_tabulate_blank_default + \blank + \else + \blank[\m_tabl_tabulate_blank_default]% + \fi + \egroup} + +\appendtoks + \enforced\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 sometimes use the english command in tracing macros. In +%D fact, most detailed tracing macros that are done with \LUA\ only work in the +%D english interface anyway. + +% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here + +\newconditional\c_tabl_generic + +\pushoverloadmode + +\permanent\protected\setuvalue{starttabulate}% + {\bgroup % whole thing + \settrue\c_tabl_generic + \let\currenttabulationparent\empty + \tabl_start_regular} + +\permanent\letvalue{stoptabulate}\relax % testcase cvs-002.tex + +\popoverloadmode + +%D The following helpers are just there because we also have them at the \LUA\ end: +%D +%D \startbuffer +%D \starttabulate[|l|c|r|] +%D \tabulaterow {a,b,c} +%D \tabulaterowbold{aa,bb,cc} +%D \tabulaterowtype{aaa,bbb,ccc} +%D \tabulaterowtyp {aaaa,bbbb,cccc} +%D \stoptabulate +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\def\tabl_tabulate_compact_row#1#2% + {\NC\tabl_tabulate_compact_step#1#2,\end,} + +\def\tabl_tabulate_compact_step#1#2#3,% + {\ifx#2\end + \NR + \expandafter\gobbleoneargument + \else + #1{#2#3}\NC + \expandafter\tabl_tabulate_compact_step + \fi#1} + +\permanent\protected\def\tabulaterow {\tabl_tabulate_compact_row\relax} +\permanent\protected\def\tabulaterowbold{\tabl_tabulate_compact_row\bold} +\permanent\protected\def\tabulaterowtype{\tabl_tabulate_compact_row\type} +\permanent\protected\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ} + +%D Here we plug in a row background feature. As we only have support for +%D \type {frame=name} we can use these variables. +%D +%D \starttyping +%D \startuseMPgraphic{foo} +%D fill unitsquare +%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) +%D randomized ExHeight +%D shifted (-ExHeight/8,ExHeight/16) +%D withcolor RuleColor ; +%D \stopuseMPgraphic +%D +%D \setuptabulate % wel only have frame=name so we can use these: +%D [background=foo, +%D backgroundcolor=darkred, +%D foregroundcolor=white] +%D +%D \definelinefiller[foo][mp=foo,color=darkgreen] +%D \definelinefiller[bar][mp=foo,color=darkred] +%D +%D \starttabulate[|||] +%D \DB foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate[|||] +%D \PB foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate[|||] +%D \FB[bar] foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \startnarrower +%D \starttabulate[|||] +%D \DB foo \DB bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D \stopnarrower +%D +%D \starttabulate[|||] +%D \BC foo \BC bar \BC \NR +%D \NL[magenta] foo \NC bar \NC \NR +%D \NL[yellow] foo \NC bar \NC \NR +%D \NL[cyan] foo \NC bar \NC \NR +%D \NL[gray] foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate +%D \NL[red] foo \NC bar \NC \NR +%D \NL[green] foo \NL[red] bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NL[blue] foo \NC \input tufte \NC \NR +%D \NL[gray] foo \NC bar \NC \NR +%D \NL[yellow] foo \NC bar \NC \NR +%D \stoptabulate +%D \stoptyping + +% \setuptabulate +% [\c!background=, +% \c!backgroundcolor=, +% \c!foregroundcolor=, +% \c!foregroundstyle=] + +\let\m_table_current_row_background \empty +\let\m_table_current_row_background_default \empty +\let\m_table_current_row_background_filler \empty +\let\m_table_current_row_background_defaultfiller\empty +\let\m_table_current_row_background_auto \empty + +\protected\def\tabl_register_row_background#1% + {\xdef\m_table_current_row_background{#1}} + +\protected\def\tabl_register_row_background_filler#1% + {\xdef\m_table_current_row_background_filler{#1}} + +\protected\def\tabl_synchronize_row_background + {\iftrialtypesetting\else + \ifempty\m_table_current_row_background_filler + \ifempty\m_table_current_row_background + % nothing + \tabl_synchronize_row_background_dummy + \else + \tabl_synchronize_row_background_indeed\m_table_current_row_background + \fi + \else + \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler + \fi + \fi} + +\protected\def\tabl_synchronize_row_background_dummy + {\iftrialtypesetting\else + \begingroup + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint + \endgroup + \fi} + +\protected\def\tabl_synchronize_row_background_indeed#1% + {\iftrialtypesetting\else + \begingroup + \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata + \dousecolorparameter{#1}% + \setbox\scratchbox\hpack{}% + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent + \endgroup + \fi} + +\protected\def\tabl_synchronize_row_background_filler_indeed#1% + {\iftrialtypesetting\else + \begingroup + \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata + \node_linefiller_set{#1}% + \setbox\scratchbox\hpack{}% + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent + \endgroup + \fi} + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty + \global\c_tabl_tabulate_nofrealrows\zerocount + \global\c_tabl_tabulate_autocolor\zerocount + \clf_resetbackgroundrowdata +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty + \global\c_tabl_tabulate_nofrealrows\zerocount + \global\c_tabl_tabulate_autocolor\zerocount + \clf_resetbackgroundrowdata +\to \t_tabl_tabulate_initializers_second + +\appendtoks + \tabl_synchronize_row_background +\to \t_tabl_tabulate_every_real_row + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty +\to \t_tabl_tabulate_every_after_row + +\permanent\protected\def\tabl_tabulate_NL_first[#1]% + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background{#1}% + \fi + \ignorespaces} + +\pushoverloadmode + + % redefinition needs checking + + \permanent\overloaded\protected\def\tabl_tabulate_ND_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background\m_table_current_row_background_default + \fi + \ignorespaces} + +\popoverloadmode + +\permanent\protected\def\tabl_tabulate_LB_first[#1]% + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background{#1}% + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_DB_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background\m_table_current_row_background_default + \fi + \enforced\let\fontstyle\globalfontstyle + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_NF_first[#1]% + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler{#1}% + \fi + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_NP_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler\m_table_current_row_background_default_filler + \fi + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_FB_first[#1]% + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler{#1}% + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_PB_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler\m_table_current_row_background_default_filler + \fi + \enforced\let\fontstyle\globalfontstyle + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\pushoverloadmode + + \permanent\overloaded\protected\def\tabl_tabulate_BC_first + {\tabl_tabulate_column_normal\plusone\zerocount + \enforced\let\fontstyle\globalfontstyle + \ifempty\m_table_current_row_background + \ifempty\m_table_current_row_background_filler + \usetabulationstyleandcolor\c!headstyle\c!headcolor + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi} + +\popoverloadmode + +\permanent\protected\def\tabl_tabulate_A_first + {\global\advance\c_tabl_tabulate_autocolor\plusone + \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% + \ifempty\m_table_current_row_background_auto + \global\c_tabl_tabulate_autocolor\plusone + \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% + \fi + \ifempty\m_table_current_row_background_auto + \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default + \fi + \tabl_register_row_background{\m_table_current_row_background_auto}} + +\permanent\protected\def\tabl_tabulate_NA_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \iftrialtypesetting\else + \ifcase\c_tabl_tabulate_column\or + \tabl_tabulate_A_first + \fi + \fi + \ignorespaces} + +\permanent\protected\def\tabl_tabulate_BA_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \iftrialtypesetting\else + \ifcase\c_tabl_tabulate_column\or + \tabl_tabulate_A_first + \fi + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\appendtoks + \enforced\let\NL\tabl_tabulate_NL_first % NC with Line + \enforced\let\ND\tabl_tabulate_ND_first % NC with Default Line + \enforced\let\LB\tabl_tabulate_LB_first % BC with Line + \enforced\let\DB\tabl_tabulate_DB_first % BC with Default Line + \enforced\let\NF\tabl_tabulate_NF_first % NC with Filler + \enforced\let\NP\tabl_tabulate_NP_first % NC with Predefined Filler + \enforced\let\FB\tabl_tabulate_FB_first % BC with Filler + \enforced\let\PB\tabl_tabulate_PB_first % BC with Predefined Filler + \enforced\let\NA\tabl_tabulate_NA_first % NC with Auto Line + \enforced\let\BA\tabl_tabulate_BA_first % NC with Auto Line +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \edef\m_table_current_row_background_default {\tabulateparameter\c!backgroundcolor}% + \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}% + \let \m_table_current_row_background_auto \empty +\to \everytabulate + +\setuptabulate + [\c!headcolor=, + \c!headstyle=\bf, + \c!backgroundcolor=\tabulationparameter\c!rulecolor, + \c!foregroundcolor=, + \c!foregroundstyle=\tabulationparameter\c!headstyle] + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-tsp.mkxl b/tex/context/base/mkxl/tabl-tsp.mkxl new file mode 100644 index 000000000..f09a5d9d8 --- /dev/null +++ b/tex/context/base/mkxl/tabl-tsp.mkxl @@ -0,0 +1,575 @@ +%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 a mkiv cleanup. +%D As it mostly targets at tables the code lives in the tabl and page namespaces. + +% work in progress + +\unprotect + +%D Although the name resembles floats, and therefore this should be a page module, +%D we decided to make it core functionality because the table code depends on it. +%D Othrwise there would be too much overloading afterwards involved. Actually, the +%D float part is rather generic and not that related to floats. + +% \splitfloat [settings] {\placetable[optional args]{test}} {content} + +%D When \type {inbetween} is made empty instead of the default \type {\page}, we +%D will get delayed flushing 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 + +\mutable\let \floatcaptionsuffix \empty + +\permanent\tolerant\protected\def\splitfloat[#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 + +\protected\def\page_split_float_suffix + {\begingroup + \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix + \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits + \endgroup} + +\protected\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}% + \ifempty\p_inbetween + \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=]% + % This controls samepage resetting too but it also messes up the numbering + % so I need another fix. +% \settrialtypesetting + \splitfloatcommand{\hbox to #1{\strut}}% dummy line +% \resettrialtypesetting + \setbox\scratchbox\vbox{\flushlocalfloats}% \vpack ? + \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} + +\permanent\protected\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\b_split_content +\newbox\b_split_result +\newbox\b_split_head +\newbox\b_split_next +\newbox\b_split_tail + +\newtoks\t_split_before_result +\newtoks\t_split_after_result +\newtoks\t_split_before +\newtoks\t_split_inbetween +\newtoks\t_split_after + +\newtoks\everyresettsplit + +\newcount\c_split_minimum_free_lines + +\newdimen\d_split_minimum_free_space +\newdimen\d_split_available_height +\newdimen\d_split_inbetween_height + +\newconditional\c_tabl_split_done +\newconditional\c_tabl_split_head +\newconditional\c_tabl_split_full + +\newconditional\tabl_split_forced_page + +\appendtoks + \c_split_minimum_free_lines\zerocount + \d_split_minimum_free_space\zeropoint + \setbox\b_split_content \emptyvbox + \setbox\b_split_result \emptyvbox + \setbox\b_split_head \emptyvbox + \setbox\b_split_next \emptyvbox + \setbox\b_split_tail \emptyvbox + \t_split_before_result \emptytoks + \t_split_after_result \emptytoks + \t_split_inbetween \emptytoks + \t_split_before \emptytoks + \t_split_after \emptytoks + \let\postprocesstsplit \donothing +\to \everyresettsplit + +\permanent\protected\def\resettsplit + {\the\everyresettsplit} + +\resettsplit + +\def\tsplitdirectwidth{\hsize} + +\protected\def\handletsplit + {\page_split_float_check_caption{\wd\b_split_content}% + \global\setfalse\splitfloatfirstdone + \testpagesync % new, sync, but still tricky + [\number\c_split_minimum_free_lines] + [\dimexpr\d_split_minimum_free_space+\extrasplitfloatlines\lineheight\relax]% + \setbox\scratchbox\vbox{\the\t_split_inbetween}% + \d_split_inbetween_height\htdp\scratchbox + \setfalse\c_tabl_split_done + \doloop\tabl_split_loop_body + \global\setfalse\usesamefloatnumber % new, prevent next increment + \global\setfalse\splitfloatfirstdone} % we can use this one for tests + +\def\tabl_split_loop_body + {\ifinsidecolumns + % brrr, assumes empty columns + \global\setfalse\splitfloatfirstdone + \d_split_available_height\textheight + \settrue\c_tabl_split_full + \else + \ifconditional\splitfloatfirstdone + \d_split_available_height\textheight + \settrue\c_tabl_split_full + \orelse\ifdim\pagegoal<\maxdimen + \d_split_available_height\dimexpr\pagegoal-\pagetotal\relax + \setfalse\c_tabl_split_full + \else + \d_split_available_height\textheight + \settrue\c_tabl_split_full + \fi + \fi + \d_split_available_height \dimexpr + \d_split_available_height + -\d_split_inbetween_height + -\d_split_minimum_free_space + -\extrasplitfloatlines\lineheight + \relax + \ifdim\htdp\b_split_tail>\zeropoint + \advance\d_split_available_height-\htdp\b_split_tail + \fi + \setbox\b_split_result\vbox + {\ifdim\ht\b_split_head>\zeropoint + \unvcopy\b_split_head + \the\t_split_inbetween + \fi}% + \ifconditional\c_tabl_split_done \else + \ifdim\ht\b_split_next>\zeropoint + \setbox\b_split_head\box\b_split_next + \fi + \fi + \settrue\c_tabl_split_done + \ifdim\ht\b_split_result>\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\b_split_content to \onepoint % \lineheight + \setbox\scratchbox\vbox % \vpack + {\unvbox\scratchbox + \setbox\scratchbox\vbox % \vpack + {\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\b_split_result\vbox + {\unvbox\b_split_result + \the\t_split_inbetween + \unvbox\scratchbox}% + \exitloop + \orelse\ifdim\dimexpr\d_split_available_height-\htdp\scratchbox-\htdp\b_split_result\relax>\zeropoint + \setbox\b_split_result\vbox + {\unvbox\b_split_result + \the\t_split_inbetween + \unvbox\scratchbox}% + \ifvoid\b_split_content \exitloop \fi + \orelse\ifconditional\c_tabl_split_head + % we only have a tablehead so far + \setbox\b_split_result\vbox{\unvbox\b_split_result\unvbox\scratchbox}% \vpack + \exitloop + \orelse\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\b_split_result\vbox + {\unvbox\b_split_result + \the\t_split_inbetween + \unvbox\scratchbox}% + \exitloop + \else + \setbox\b_split_content\vbox + {\unvbox\scratchbox + \the\t_split_inbetween + \ifvoid\b_split_content\else\unvbox\b_split_content\fi}% + \exitloop + \fi + \setfalse\c_tabl_split_head + \setfalse\c_tabl_split_full}% + \postprocesstsplit + \page_split_float_check_content\b_split_content + \ifvoid\b_split_content + \setbox\b_split_result\vbox + {\unvbox\b_split_result + \the\t_split_inbetween + \unvcopy\b_split_tail}% + \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% + \doifnotinsidesplitfloat{\the\t_split_after}% + \endgraf + \exitloop + \else + % hack + \ifdim\pagegoal<\maxdimen + \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex + \fi + % brrr + \ifdim\ht\b_split_result>\zeropoint + \setbox\b_split_result\vbox + {\unvbox\b_split_result + \the\t_split_inbetween + \unvcopy\b_split_tail}% + \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% + \doifnotinsidesplitfloat{\the\t_split_after}% + \endgraf + \global\settrue\usesamefloatnumber % new, prevent next increment + \fi + \ifinsidecolumns + \goodbreak % was \doifnotinsidesplitfloat\goodbreak + \else + \page % was \doifnotinsidesplitfloat\page + \fi + \fi} + +%D The next one assumes that the split takes place elsewhere. This is used in +%D xtables. + +\aliased\let\resetdirecttsplit\resettsplit + +\permanent\protected\def\handledirecttsplit + {\page_split_float_check_caption{\tsplitdirectwidth}% + \global\setfalse\splitfloatfirstdone + \testpagesync % new, sync, but still tricky + [\number\c_split_minimum_free_lines] + [\dimexpr\d_split_minimum_free_space+\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_split_available_height\textheight + \orelse\ifconditional\splitfloatfirstdone + \d_split_available_height\textheight + \orelse\ifdim\pagegoal<\maxdimen + \d_split_available_height\dimexpr\pagegoal-\pagetotal\relax + \else + \d_split_available_height\textheight + \fi + \d_split_available_height\dimexpr + \d_split_available_height + -\d_split_minimum_free_space + -\extrasplitfloatlines\lineheight + \relax + \tsplitdirectsplitter\d_split_available_height % also sets state + \ifdim\ht\b_split_result>\zeropoint + \ifconditional\somenextsplitofffloat + \global\setfalse\onlyonesplitofffloat + \fi + \ifdim\pagegoal<\maxdimen + \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex + \fi + \page_split_float_process{\the\t_split_before_result\box\b_split_result\the\t_split_after_result}% + \global\settrue\usesamefloatnumber % new, prevent next increment + \endgraf + \ifconditional\somenextsplitofffloat + \ifinsidecolumns + \goodbreak + \else + \page + \fi + \fi + \global\settrue\splitfloatfirstdone + \orelse\ifconditional\somenextsplitofffloat + \ifinsidecolumns + \goodbreak + \else + \page % no room + \fi + \else + \exitloop + \fi} + +%D Maybe handy: +%D +%D \starttyping +%D \splitfloat +%D {\placefigure{some caption}} +%D {\startsplittext +%D \typefile[option=TEX,before=,after=]{oeps.tex} +%D \stopsplittext} +%D \stoptyping + +\permanent\def\handlesplittext#1% + {\setbox\b_split_result\vbox + {\vsplit\b_split_content to \dimexpr#1-\lineheight\relax}} + +\permanent\protected\def\startsplittext + {\begingroup + \resettsplit + \c_split_minimum_free_lines\zerocount + \d_split_minimum_free_space\zeropoint + \let\extrasplitfloatlines \!!plusone + \let\tsplitdirectsplitter \handlesplittext + \setbox\b_split_content\vbox\bgroup + \insidefloattrue} + +\permanent\protected\def\stopsplittext + {\egroup + \handledirecttsplit + \endgroup} + +\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/tex/context/base/mkxl/tabl-xnt.mklx b/tex/context/base/mkxl/tabl-xnt.mklx new file mode 100644 index 000000000..f2a41c500 --- /dev/null +++ b/tex/context/base/mkxl/tabl-xnt.mklx @@ -0,0 +1,142 @@ +% macros=mkvi + +%D \module +%D [ file=tabl-xtb, +%D version=2011.10.28, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Natural to Xtreme Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Natural to Xtreme Tables} + +\unprotect + +%D Don't expect wonders but it might come in handy: +%D +%D \starttyping +%D \mapTABLEtoxtable +%D \restoreTABLEfromxtable +%D \stoptyping +%D +%D We stick to a simple example: +%D +%D \startbuffer +%D \bTABLE +%D \bTR +%D \bTD[width=1cm,background=color,backgroundcolor=red] one \eTD +%D \bTD[width=2cm] two \eTD +%D \eTR +%D \bTR +%D \bTD alpha \eTD +%D \bTD beta \eTD +%D \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startbuffer +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D \startlinecorrection +%D \mapTABLEtoxtable \getbuffer +%D \stoplinecorrection +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\pushoverloadmode % this file is runtime loaded + +\overloaded\permanent\let\tabl_x_normal_bTABLEhead\bTABLEhead +\overloaded\permanent\let\tabl_x_normal_eTABLEhead\eTABLEhead +\overloaded\permanent\let\tabl_x_normal_bTABLEnext\bTABLEnext +\overloaded\permanent\let\tabl_x_normal_eTABLEnext\eTABLEnext +\overloaded\permanent\let\tabl_x_normal_bTABLEfoot\bTABLEfoot +\overloaded\permanent\let\tabl_x_normal_eTABLEfoot\eTABLEfoot +\overloaded\permanent\let\tabl_x_normal_bTABLEbody\bTABLEbody +\overloaded\permanent\let\tabl_x_normal_eTABLEbody\eTABLEbody +\overloaded\permanent\let\tabl_x_normal_bTR \bTR +\overloaded\permanent\let\tabl_x_normal_eTR \eTR +\overloaded\permanent\let\tabl_x_normal_bTD \bTD +\overloaded\permanent\let\tabl_x_normal_eTD \eTD +\overloaded\permanent\let\tabl_x_normal_bTH \bTH +\overloaded\permanent\let\tabl_x_normal_eTH \eTH +\overloaded\permanent\let\tabl_x_normal_setupTABLE\setupTABLE +\overloaded\permanent\let\tabl_x_normal_bTABLE \bTABLE +\overloaded\permanent\let\tabl_x_normal_eTABLE \eTABLE + +\permanent\protected\def\restoreTABLEfromxtable + {\enforced\let\bTABLEhead\tabl_x_normal_bTABLEhead + \enforced\let\eTABLEhead\tabl_x_normal_eTABLEhead + \enforced\let\bTABLEnext\tabl_x_normal_bTABLEnext + \enforced\let\eTABLEnext\tabl_x_normal_eTABLEnext + \enforced\let\bTABLEfoot\tabl_x_normal_bTABLEfoot + \enforced\let\eTABLEfoot\tabl_x_normal_eTABLEfoot + \enforced\let\bTABLEbody\tabl_x_normal_bTABLEbody + \enforced\let\eTABLEbody\tabl_x_normal_eTABLEbody + \enforced\let\bTR \tabl_x_normal_bTR + \enforced\let\eTR \tabl_x_normal_eTR + \enforced\let\bTD \tabl_x_normal_bTD + \enforced\let\eTD \tabl_x_normal_eTD + \enforced\let\bTH \tabl_x_normal_bTH + \enforced\let\eTH \tabl_x_normal_eTH + \enforced\let\setupTABLE\tabl_x_normal_setupTABLE + \enforced\let\bTABLE \tabl_x_normal_bTABLE + \enforced\let\eTABLE \tabl_x_normal_eTABLE} + +\permanent\protected\def\mapTABLEtoxtable + {\enforced\let\bTABLEhead\startxtablehead + \enforced\let\eTABLEhead\stopxtablehead + \enforced\let\bTABLEnext\startxtablefoot + \enforced\let\eTABLEnext\stopxtablefoot + \enforced\let\bTABLEfoot\startxtablefoot + \enforced\let\eTABLEfoot\stopxtablefoot + \enforced\let\bTABLEbody\startxtablebody + \enforced\let\eTABLEbody\stopxtablebody + \enforced\let\bTR \startxrow + \enforced\let\eTR \stopxrow + \enforced\let\bTD \startxcell + \enforced\let\eTD \stopxcell + \enforced\let\bTH \tabl_x_TABLE_TH_start_cell + \enforced\let\eTH \tabl_x_TABLE_TH_stop_cell + \enforced\let\setupTABLE\tabl_x_TABLE_setup + \enforced\let\bTABLE \tabl_x_TABLE_start + \enforced\let\eTABLE \tabl_x_TABLE_stop} + +\popoverloadmode + +\permanent\protected\def\tabl_x_TABLE_TH_start_cell + {\startxcellgroup[\c!foregroundstyle=\v!bold]% + \startxcell} + +\permanent\protected\def\tabl_x_TABLE_TH_stop_cell + {\stopxcell + \stopxcellgroup} + +\permanent\protected\tolerant\def\tabl_x_TABLE_setup[#settings]% + {\ifarguments\or + %\ifparameter#1\or + \setupxtable[#settings]% + \fi} + +\permanent\protected\tolerant\def\tabl_x_TABLE_start[#settings]% + {\bgroup + \ifarguments\or + %\ifparameter#1\or + \tabl_x_prepare{#settings}% + \fi + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process\zerocount} + +\permanent\protected\def\tabl_x_TABLE_stop + {\stopxtable} + +\protect \endinput diff --git a/tex/context/base/mkxl/tabl-xtb.mklx b/tex/context/base/mkxl/tabl-xtb.mklx new file mode 100644 index 000000000..267168ac1 --- /dev/null +++ b/tex/context/base/mkxl/tabl-xtb.mklx @@ -0,0 +1,976 @@ +% macros=mkvi + +%D \module +%D [ file=tabl-xtb, +%D version=2011.10.26, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Xtreme, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Xtreme} + +\registerctxluafile{tabl-xtb}{} + +% todo: +% +% - yes or no: foregroundstyle/color <- style/color +% - template alignment +% - maybe split horizontal (a la linetables) +% - before/after and wrapping (linecorrection) +% - maybe also some before/after commands +% - maybe correction when non float usage +% - tagging needs to be checked +% - maybe only tag the box +% - scale to fit +% +% - buffers permit verbatim but are not always handy + +%D This module started as an afternoon experiment and surprisingly could be +%D mostly finished the same evening. Of course it builds upon existing +%D functionality. The main reason for writing it is that we occasionally +%D run into pretty large tables that take tens of pages and need to be split +%D into floats. Speed is one issue there, avoiding to use vsplit is another. +%D +%D \starttyping +%D \definextable [tag] | [tag][parent] +%D \setupxtable [settings] | [tag][settings] +%D +%D \startxtable[tag|settings] +%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot +%D \startxrowgroup[tag|settings] +%D \startxrow[settings] +%D \startxcellgroup[tag|settings] +%D \startxcell[settings] ... \stopxcell +%D \stopxcellgroup +%D \stopxrow +%D \startxrowgroup +%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot +%D \stopxtable +%D \stoptyping +%D +%D See xtables-001.tex etc for some examples. + +% We can avoid some checking by using the fastoptionalcheckcs helpers +% instead of dosingleempty but the speed gain is neglectable. + +\unprotect + +% option=stretch : equal distribution +% option={stretch,width} : proportional distribution +% option={max} : prefer max over forced width/height +% +% cells: option=fixed : nils autostretch (not yet complete) + +% \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged {...} + +\aliased\let\dotagxtablecell \relax % names will change +\aliased\let\dotagxtablesignal\relax % names will change + +\appendtoks + \enforced\permanent\protected\def\dotagxtablecell + {\clf_settagtablecell + \numexpr\tablecellrows\relax + \numexpr\tablecellcolumns\relax + \numexpr\raggedstatus\relax}% + \enforced\permanent\protected\def\dotagxtablesignal + {\signalcharacter}% not used +\to \everyenableelements + +\newdimen\d_tabl_x_width +\newdimen\d_tabl_x_height +\newdimen\d_tabl_x_depth % not used +\newdimen\d_tabl_x_distance +\newcount\c_tabl_x_nx +\newcount\c_tabl_x_ny +\newcount\c_tabl_x_mode +\newbox \b_tabl_x +\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft +\newdimen\d_tabl_x_final_width +\newcount\c_tabl_x_nesting +\newcount\c_tabl_x_skip_mode % 1 = skip +\newdimen\d_tabl_x_textwidth +\newcount\c_tabl_x_swapped +\newcount\c_tabl_x_swapped_max + +\let\m_tabl_x_swapped_settings\empty + +\aliased\let\currentxtablerow \clf_x_table_r +\aliased\let\currentxtablecolumn\clf_x_table_c + +% \setupxtable[one][parent][a=b,c=d] +% \setupxtable[one] [a=b,c=d] +% \setupxtable [a=b,c=d] + +\installcorenamespace{xtable} +\installcorenamespace{xtablecheck} +\installcorenamespace{xtableswap} + +\installframedautocommandhandler \??xtable {xtable} \??xtable + +\appendtoks + \checkxtableparent % so we can deal with undefined settings, not that it's efficient +\to \everysetupxtable + +\setupxtable[% + \c!nr=\plusone, + \c!nc=\plusone, + \c!nx=\plusone, % slow + \c!ny=\plusone, % slow + \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE + \c!frameoffset=.5\linewidth, + \c!backgroundoffset=\v!frame, + % \c!framecolor=\s!black, + % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere + % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere + % \c!bodyfont=, + \c!width=\v!fit, + \c!height=\v!fit, + \c!maxwidth=8\emwidth, + \c!autowidth=\v!yes, % controls framed + \c!rulethickness=\linewidth, + \c!strut=\v!yes, + \c!autostrut=\v!no, + \c!split=\v!auto, % a number will take that many lines + \c!splitoffset=\zeropoint, % extra space taken + \c!aligncharacter=\v!no, + \c!alignmentcharacter={,}, + \c!alignmentleftsample=, + \c!alignmentrightsample=, + \c!alignmentleftwidth=\zeropoint, + \c!alignmentrightwidth=\zeropoint, + % \c!option=, % \v!stretch {\v!stretch,\v!width} + % \c!footer=, + % \c!header=, + \c!spaceinbetween=, + \c!textwidth=\v!local, % was \hsize, + \c!textheight=\vsize, % used for vertical spread + \c!distance=\zeropoint, % individual column + \c!columndistance=\zeropoint, % each column (whole table) + \c!leftmargindistance=\zeropoint, % whole table + \c!rightmargindistance=\zeropoint,% whole table +] + +\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting} +\let\tabl_x_current_buffer\empty + +\permanent\protected\def\startxtable{\tabl_x_start_table} + +\protected\tolerant\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings] + {\bgroup + \tabl_x_prepare{#settings}% + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process\zerocount} + +% \permanent\protected\aliased\startxtable\tabl_x_start_table + +\aliased\permanent\let\stopxtable\relax + +% These direct buffers can be somewhat faster but it's probably neglectable. +% Anyway, no nesting is supported as we then need to catch (e.g.) rows and keep +% track of nesting and have a more complex redefinition of nested instanced +% \unknown\ it's not worth the trouble. Only use them when you really need them and +% use the embeddedxtable command when nesting them. Implementing nesting would be +% slower than not using direct buffers. + +\permanent\tolerant\protected\def\processxtablebuffer[#name]% + {\bgroup + \let\tabl_x_start_table\tabl_x_process_buffer + \edef\tabl_x_current_buffer{#name}% + \tabl_x_get_buffer % settings + \tabl_x_process} + +\protected\tolerant\def\tabl_x_start_ignore[#settings]% + {} + +\protected\tolerant\def\tabl_x_process_buffer[#settings]% + {\tabl_x_prepare{#settings}% + \let\tabl_x_start_table\tabl_x_start_ignore + \gobbleuntil\stopxtable} % nested xtables are not supported, + +%D A bonus: you have to use the following construct inside a macro or +%D direct buffer. + +\permanent\tolerant\protected\def\startembeddedxtable[#settings]#:#content\stopembeddedxtable + {\tabl_x_prepare{#settings}% + \clf_assignbuffer{embedded_x_table}{\detokenize{#content}}\catcodetable\relax + \bgroup + \let\tabl_x_start_table\tabl_x_process_buffer + \edef\tabl_x_current_buffer{embedded_x_table}% + \tabl_x_process} + +\aliased\permanent\let\stopembeddedxtable\relax + +%D We can also define xtables. + +\appendtoks + \permanent\setuevalue{\e!start\currentxtable}{\tabl_x_start_named[\currentxtable]}% + \permanent\setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}% +\to \everydefinextable + +\protected\def\tabl_x_start_named[#tag]#spacer[#settings]% + {\bgroup + \edef\currentxtable{#tag}% + \advance\c_tabl_x_nesting\plusone + \dostarttaggedchained\t!table\empty\??xtable + \setupcurrentxtable[#settings]% + \tabl_x_check_textwidth + %\forgetall % else whitespace mess + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process\zerocount}} + +\protected\def\tabl_x_stop_named + {} + +%D Now we come to processing: + +\protected\def\tabl_x_check_textwidth + {\edef\p_textwidth{\xtableparameter\c!textwidth}% + \ifx\p_textwidth\v!local + \d_tabl_x_textwidth\availablehsize + \else + \d_tabl_x_textwidth\p_textwidth + \fi} + +\newtoks\everypreparextable + +\protected\def\tabl_x_prepare#settings% + {\advance\c_tabl_x_nesting\plusone + \dostarttaggedchained\t!table\empty\??xtable + \tabl_x_set_checked{#settings}% + \tabl_x_check_textwidth + \the\everypreparextable + }% else whitespace mess + +\def\tabl_x_get_buffer + {\clf_gettexbuffer{\tabl_x_current_buffer}} + +\let\tabl_x_start_row_yes \relax +\let\tabl_x_start_row_nop \relax +\let\tabl_x_stop_row \relax +\let\tabl_x_start_cell_yes\relax +\let\tabl_x_start_cell_nop\relax +\let\tabl_x_stop_cell \relax + +\newtoks\t_table_x_cleanup + +\protected\def\tabl_x_process + {\begingroup % * + \forgetall % moved here + \dontcomplain % for the moment here till we figure out where we get the overflow + \usebodyfontparameter\xtableparameter + \setbox\scratchbox\vbox + {\doifsomething{\xtableparameter\c!spaceinbetween}{\blank[\xtableparameter\c!spaceinbetween]}}% + \clf_x_table_create + option {\xtableparameter\c!option}% + textwidth \d_tabl_x_textwidth + textheight \dimexpr\xtableparameter\c!textheight\relax + maxwidth \dimexpr\xtableparameter\c!maxwidth\relax + lineheight \openlineheight + columndistance \dimexpr\xtableparameter\c!columndistance\relax + leftmargindistance \dimexpr\xtableparameter\c!leftmargindistance\relax + rightmargindistance \dimexpr\xtableparameter\c!rightmargindistance\relax + rowdistance \ht\scratchbox + header {\xtableparameter\c!header}% + footer {\xtableparameter\c!footer}% + \relax + % + \letxtableparameter\c!option\empty + % not so nice but needed as we use this in the setup + \linewidth\xtableparameter\c!rulethickness\relax + % so we freeze it + \c_tabl_x_swapped_max\zerocount + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop + \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width + \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width + \settrialtypesetting + \tabl_x_get_buffer + \ifcase\c_tabl_x_swapped_max + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_reflow_width + \endgroup + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop + \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height + \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height + \settrialtypesetting + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_reflow_height + \endgroup + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop + \let\tabl_x_stop_row \tabl_x_stop_row_construct + \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_construct + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_construct + \endgroup + \endgroup % * + \ifinsidesplitfloat + \tabl_x_flush_float_split + \orelse\ifinsidefloat + \tabl_x_flush_float_normal + \else + \tabl_x_flush_text_checked + \fi + \clf_x_table_cleanup + \dostoptagged + \resetbuffer[\tabl_x_current_buffer]% + \resetcharacteralign + \the\t_table_x_cleanup + \egroup} + +% text flow split modes + +\installcorenamespace{xtableflushsplit} + +\protected\def\tabl_x_flush_text_checked + {\expandnamespaceparameter\??xtableflushsplit\xtableparameter\c!split\v!no} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!yes}% + {\clf_x_table_flush + method {\v!split}% + \relax} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!no}% + {% \noindent % gives extra line after table + % \noindentation % messes up the next indentation + % \dontleavehmode % no leftskip + \kern\zeropoint % yet another guess + \ignorespaces + \clf_x_table_flush + method {\v!normal}% + \relax + \removeunwantedspaces} + +% in text flow: headers and footers get repeated + +\setvalue{\??xtableflushsplit\v!repeat}% + {\doloop + {\clf_x_table_flush + method {\v!split}% + height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi + \relax + \ifcase\c_tabl_x_state + \exitloop + \else + \page + \fi}} + +% \setvalue{\??xtableflushsplit\v!setups}% +% {\directsetup{xtable:split:user}} +% +% \startsetups[xtable:split:user] +% \doloop { +% \xtablesplitflush % uses \xtablesplitvsize (a macro) +% \ifcase\xtablesplitstate +% \exitloop +% \else +% \page +% \fi +% } +% \stopsetups +% +% \protected\def\xtablesplitflush +% {\clf_x_table_flush +% method {\v!split}% +% height \dimexpr\xtablesplitvsize\relax +% \relax} +% +% \def\xtablesplitvsize +% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi} +% +% \let\xtablesplitstate\c_tabl_x_state + +\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it + +\protected\def\tabl_x_flush_float_normal + {\clf_x_table_flush + method {\v!normal}% + \relax} + +\protected\def\tabl_x_flush_float_split + {\resetdirecttsplit + \edef\extrasplitfloatlines{\xtableparameter\c!split}% + \d_split_minimum_free_space\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax + %\c_split_minimum_free_lines\plustwo % not needed here as we're precise enough + \let\tsplitdirectsplitter\tabl_x_split_splitter + \let\tsplitdirectwidth \d_tabl_x_final_width + \handledirecttsplit} + +\protected\def\tabl_x_split_splitter#height% + {\setbox\b_split_result\vbox + {\clf_x_table_flush + method {\v!split}% + height \dimexpr#height\relax + \relax}% + \ifcase\c_tabl_x_state + \global\setfalse\somenextsplitofffloat + \else + \global\settrue \somenextsplitofffloat + \fi} + +% \permanent\protected\def\startxrow +% {\begingroup +% \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} + +% \permanent\protected\def\stopxrow +% {\tabl_x_stop_row +% \endgroup} + +\protected\def\tabl_x_start_row_reflow_width_yes[#settings]% + {\setupcurrentxtable[#settings]% + \clf_x_table_next_row} + +\protected\def\tabl_x_start_row_reflow_width_nop + {\clf_x_table_next_row} + +\protected\def\tabl_x_stop_row_reflow_width + {} + +\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes +\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop +\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width + +\protected\def\tabl_x_start_row_construct_yes[#settings]% + {\setupcurrentxtable[#settings]% + \dostarttagged\t!tablerow\empty + \clf_x_table_next_row_option{\xtableparameter\c!samepage}} + +\protected\def\tabl_x_start_row_construct_nop + {\dostarttagged\t!tablerow\empty + \clf_x_table_next_row} + +\protected\def\tabl_x_stop_row_construct + {\clf_x_table_finish_row + \dostoptagged} + +\permanent\protected\def\dummyxcell + {\begingroup + \enforced\let\inheritedxtableframed\relax + \tabl_x_start_cell_nop + \tabl_x_stop_cell + \endgroup} + +\def\tabl_x_setup_character_align + {\edef\p_left {\directxtableparameter\c!alignmentleftsample}% + \edef\p_right{\directxtableparameter\c!alignmentrightsample}% + \ifempty\p_left + \scratchdimenone\dimexpr\directxtableparameter\c!alignmentleftwidth\relax + \else + \setbox\scratchbox\hbox{\p_left}% + \scratchdimenone\wd\scratchbox + \fi + \ifempty\p_right + \scratchdimentwo\dimexpr\directxtableparameter\c!alignmentrightwidth\relax + \else + \setbox\scratchbox\hbox{\p_right}% + \scratchdimentwo\wd\scratchbox + \fi + \clf_setcharacteraligndetail + \clf_x_table_c + {\directxtableparameter\c!alignmentcharacter}% + \scratchdimenone + \scratchdimentwo + \relax} + +\newtoks\t_tabl_x_every_cell + +% \appendtoks +% \inhibitblank % already in framed +% \to \t_tabl_x_every_cell + +\appendtoks + \edef\p_characteralign{\directxtableparameter\c!aligncharacter}% + \ifx\p_characteralign\v!yes + \ifcase\clf_x_table_r\or + \tabl_x_setup_character_align + \fi + \signalcharacteralign\clf_x_table_c\clf_x_table_r + \fi +\to \t_tabl_x_every_cell + +\protected\def\tabl_x_begin_of_cell + {\the\t_tabl_x_every_cell + \everypar{\delayedbegstrut}} + +\protected\def\tabl_x_end_of_cell + {\ifhmode + \delayedendstrut + \par + \else + \par + \ifdim\prevdepth<\zeropoint % =-1000pt ? + \vskip-\strutdp + \else + \removebottomthings + \fi + \fi} + +% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes +% obsolete some day. The let as well as the direct speed things up a bit. We +% could also consider a \defaultxtableparameter. +% +% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone} +% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone} +% +% Although this becomes kind of messy. It saves already time that we only check +% for it when we have settings. + +% \def\tabl_x_set_hsize +% {\hsize.25\maxdimen} % let's be reasonable + +% \def\tabl_x_set_hsize +% {\edef\p_width{\xtableparameter\c!width}% +% \ifempty\p_width +% \hsize.25\maxdimen % is this really needed +% \fi} + +\let\tabl_x_set_hsize\relax + +\protected\def\tabl_x_start_cell_reflow_width_yes[#settings]% + {\setbox\b_tabl_x\hpack\bgroup + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!width \v!fit % overloads given width + \letxtableparameter\c!height\v!fit % overloads given height + \fi + % + \letxtableparameter\c!nx\plusone + \letxtableparameter\c!ny\plusone + \letxtableparameter\c!nc\plusone + \letxtableparameter\c!nr\plusone + % + \setupcurrentxtable[#settings]% + % + \c_tabl_x_nx\directxtableparameter\c!nc\relax + \c_tabl_x_ny\directxtableparameter\c!nr\relax + \ifnum\c_tabl_x_nx=\plusone + \c_tabl_x_nx\directxtableparameter\c!nx\relax + \fi + \ifnum\c_tabl_x_ny=\plusone + \c_tabl_x_ny\directxtableparameter\c!ny\relax + \fi + % + \d_tabl_x_distance\xtableparameter\c!distance\relax + \clf_x_table_init_reflow_width_option{\xtableparameter\c!option}% + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \tabl_x_set_hsize} + +\protected\def\tabl_x_start_cell_reflow_width_nop + {\setbox\b_tabl_x\hpack\bgroup + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!width \v!fit % overloads given width + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \c_tabl_x_nx\plusone + \c_tabl_x_ny\plusone + \d_tabl_x_distance\xtableparameter\c!distance\relax + \clf_x_table_init_reflow_width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \tabl_x_set_hsize} + +\protected\def\tabl_x_stop_cell_reflow_width + {\tabl_x_end_of_cell + \egroup + \egroup + \clf_x_table_set_reflow_width} + +\protected\def\tabl_x_start_cell_reflow_height_yes[#settings]% + {\setbox\b_tabl_x\hpack\bgroup + \clf_x_table_init_reflow_height + \ifcase\c_tabl_x_skip_mode % can be sped up + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \setupcurrentxtable[#settings]% + \relax + \letxtableparameter\c!width\d_tabl_x_width % overloads given width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \fi} + +\protected\def\tabl_x_start_cell_reflow_height_nop + {\setbox\b_tabl_x\hpack\bgroup + \clf_x_table_init_reflow_height + \ifcase\c_tabl_x_skip_mode % can be sped up + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \relax + \letxtableparameter\c!width\d_tabl_x_width % overloads given width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \fi} + +\protected\def\tabl_x_stop_cell_reflow_height + {\ifcase\c_tabl_x_skip_mode + \tabl_x_end_of_cell + \egroup + \fi + \egroup + \clf_x_table_set_reflow_height} + +\protected\def\tabl_x_start_cell_construct_yes[#settings]% + {\dostarttagged\t!tablecell\empty % can't we just tag the box + \setbox\b_tabl_x\hpack\bgroup + \setupcurrentxtable[#settings]% + \letxtableparameter\c!width \d_tabl_x_width % overloads given width + \letxtableparameter\c!height\d_tabl_x_height % overloads given height + \clf_x_table_init_construct + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \dotagxtablecell} + +\protected\def\tabl_x_start_cell_construct_nop + {\dostarttagged\t!tablecell\empty % can't we just tag the box + \setbox\b_tabl_x\hpack\bgroup + \letxtableparameter\c!width \d_tabl_x_width % overloads given width + \letxtableparameter\c!height\d_tabl_x_height % overloads given height (commenting it ... nice option) + \clf_x_table_init_construct + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \dotagxtablecell} + +\protected\def\tabl_x_stop_cell_construct + {\tabl_x_end_of_cell + \egroup + \dotagxtablesignal % harmless spot + \egroup + \clf_x_table_set_construct + \dostoptagged} + +% \permanent\tolerant\protected\def\startxcellgroup[#settings]% +% {\begingroup +% \ifarguments\or +% \tabl_x_set_checked{#settings}% +% \fi} +% +% \permanent\protected\def\stopxcellgroup +% {\endgroup} +% +% \permanent\tolerant\protected\def\startxrowgroup[#settings]% +% {\begingroup +% \ifarguments\or +% \tabl_x_set_checked{#settings}% +% \fi} +% +% \permanent\protected\def\stopxrowgroup +% {\dostoptagged +% \endgroup} + +\protected\def\tabl_x_set_checked#settings% + {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname + \edef\currentxtable{#settings}% + \else + \setupcurrentxtable[#settings]% + \fi} + +\permanent\protected\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \tabl_x_start_partition} +\permanent\protected\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \tabl_x_start_partition} +\permanent\protected\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\tabl_x_start_partition} +\permanent\protected\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \tabl_x_start_partition} + +\permanent\tolerant\protected\def\tabl_x_start_partition[#settings]#spacer% + {\ifarguments\or + \tabl_x_set_checked{#settings}% + \fi} + +\permanent\protected\def\tabl_x_stop_partition + {\endgroup} + +\aliased\let\stopxtablehead\tabl_x_stop_partition +\aliased\let\stopxtablefoot\tabl_x_stop_partition +\aliased\let\stopxtablenext\tabl_x_stop_partition +\aliased\let\stopxtablebody\tabl_x_stop_partition + +%D This is an experiment! Beware: you can create loops by using nested +%D references to already chained settings. +%D +%D \startbuffer +%D \setupxtable[suffix][align=middle,foregroundcolor=red] +%D \setupxtable[blabla][foregroundstyle=slanted] +%D \setupxtable[crap] [foregroundcolor=blue] +%D \setupxtable[bold] [crap][foregroundstyle=bold] +%D +%D \startxtable[frame=off] +%D \startxtablehead +%D \startxrow[bold] +%D \startxcell[suffix] a 0 \stopxcell +%D \startxcell[blabla] a 1 \stopxcell +%D \startxcell a 2 \stopxcell +%D \stopxrow +%D \stopxtablehead +%D \startxtablebody +%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow +%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow +%D \stopxtablebody +%D \stopxtable +%D \stopbuffer +%D +%D \typebuffer \placetable{}{\getbuffer} + +\appendtoks + \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent +\to \everysetupxtable + +% \definefontfamily[newtimes][serif][TeX Gyre Termes] +% \setupxtable[newtimes][foregroundstyle=\newtimes] +% \startxcell[newtimes] ...\stopxcell +% \startxcell[foregroundstyle=\newtimes] ...\stopxcell + +% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname +% % \ifcsname\??xtablecheck#tag\endcsname +% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords +% \expandafter\whatever % but more tolerant for tricky key=value +% \else +% \expandafter\whatever +% \fi[#tag] + +% groups + +\permanent\protected\def\startxgroup + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_group_delayed_one\relax} + +\permanent\protected\def\stopxgroup + {\endgroup} + +\protected\def\tabl_x_start_group_delayed_one[#tag]% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_group_delayed_two + \else + \expandafter\setupcurrentxtable + \fi[#tag]} + +\protected\def\tabl_x_start_group_delayed_two[#tag]% + {\ifempty\currentxtable \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\setupcurrentxtable\relax} + +\aliased\let\startxrowgroup \startxgroup +\aliased\let\stopxrowgroup \stopxgroup +\aliased\let\startxcellgroup\startxgroup +\aliased\let\stopxcellgroup \stopxgroup + +% cells (maybe also check for 1 etc but it becomes messy) + +\permanent\protected\def\startxcell + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop} + +\tolerant\protected\def\tabl_x_start_cell_delayed_one[#tag]#spacer% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_cell_delayed_two + \else + \expandafter\tabl_x_start_cell_yes + \fi[#tag]} + +\tolerant\protected\def\tabl_x_start_cell_delayed_two[#tag]#spacer% + {\ifempty\currentxtable \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} + +\permanent\protected\def\stopxcell + {\tabl_x_stop_cell + \endgroup} + +% rows + +\permanent\protected\def\startxrow + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_row_delayed_one\tabl_x_start_row_nop} + +\protected\def\tabl_x_start_row_delayed_one[#tag]% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_row_delayed_two + \else + \expandafter\tabl_x_start_row_yes + \fi[#tag]} + +\permanent\protected\def\tabl_x_start_row_delayed_two[#tag]% + {\ifempty\currentxtable \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} + +\permanent\protected\def\stopxrow + {\tabl_x_stop_row + \endgroup} + +%D A bonus, not advertised but some like it this way: + +\protected\def\tabl_x_nc + {\startxrow + \enforced\let\NC\tabl_x_nc_next + \enforced\let\NR\tabl_x_nr + \startxcell} + +\protected\def\tabl_x_nc_next + {\stopxcell + \startxcell} + +\protected\def\tabl_x_nr + {\stopxcell + \stopxrow + \enforced\let\NC\tabl_x_nc} + +\appendtoks + \enforced\let\NC\tabl_x_nc + \enforced\let\NR\tabl_x_nr +\to \everypreparextable + +%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting. + +\protected\def\tabl_x_c_cell_start#settings% + {\begingroup + \tabl_x_set_checked{#settings}% + \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} + +\protected\def\tabl_x_c_cell_stop + {\tabl_x_stop_cell + \endgroup} + +% \protected\def\dummyxcell +% {\tabl_x_start_cell_nop +% \tabl_x_stop_cell} + +\mutable\let\t_tabl_x_swapped\relax + +\def\tabl_x_flush_swapped + {\dorecurse\c_tabl_x_swapped_max + {\expandafter + \startxrow + \the\csname\??xtableswap##1\endcsname\relax + \stopxrow}} + +\def\tabl_x_collect_allocate + {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname} + +\def\tabl_x_collect_advance + {\global\advance\c_tabl_x_swapped\plusone + \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max + \global\c_tabl_x_swapped_max\c_tabl_x_swapped + \fi + \mutable\expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \ifx\t_tabl_x_swapped\relax + \tabl_x_collect_allocate + \fi} + +\protected\def\tabl_x_collect_cell_start + {\doifelsenextoptionalcs + \tabl_x_collect_cell_start_yes + \tabl_x_collect_cell_start_nop} + +\def\tabl_x_collect_cell_start_nop#content\stopxcell + {\tabl_x_collect_advance + \ifempty\m_tabl_x_swapped_settings + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}% + \fi} + +\tolerant\def\tabl_x_collect_cell_start_yes[#settings]#spacer#content\stopxcell + {\tabl_x_collect_advance + \ifempty\m_tabl_x_swapped_settings + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}% + \fi + \getdummyparameters[\c!ny=1,#settings]% + \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax + \ifcase\scratchcounter\else + \dorecurse\scratchcounter\tabl_x_collect_advance + \fi} + +\permanent\tolerant\protected\def\startxcolumn[#settings]#spacer% + {\begingroup + \global\c_tabl_x_swapped\zerocount + \enforced\let\startxcell\tabl_x_collect_cell_start + \enforced\let\stopxcell \relax + \xdef\m_tabl_x_swapped_settings{#settings}} + +\permanent\protected\def\stopxcolumn + {\endgroup} + +\appendtoks + \dorecurse\c_tabl_x_swapped_max + {\global\csname\??xtableswap\number#1\endcsname\emptytoks}% +\to \t_table_x_cleanup + +%D \startbuffer +%D \setupxtable[one][foregroundcolor=red] +%D \setupxtable[two][foregroundcolor=blue] +%D +%D \startlinecorrection +%D \startxtable +%D \startxrow[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxrow +%D \startxrow[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxrow +%D \stopxtable +%D \stoplinecorrection +%D +%D \startlinecorrection +%D \startxtable +%D \startxcolumn[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxcolumn +%D \startxcolumn[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxcolumn +%D \stopxtable +%D \stoplinecorrection +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\protect \endinput diff --git a/tex/context/base/mkxl/task-ini.mkxl b/tex/context/base/mkxl/task-ini.mkxl new file mode 100644 index 000000000..77e4fa985 --- /dev/null +++ b/tex/context/base/mkxl/task-ini.mkxl @@ -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}{} + +\protect \endinput diff --git a/tex/context/base/mkxl/toks-aux.lmt b/tex/context/base/mkxl/toks-aux.lmt new file mode 100644 index 000000000..03f4dc2c1 --- /dev/null +++ b/tex/context/base/mkxl/toks-aux.lmt @@ -0,0 +1,183 @@ +if not modules then modules = { } end modules ['toks-aux'] = { + version = 1.001, + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring +local max = math.max +local formatters, gsub, char = string.formatters, string.gsub, string.char +local concat = table.concat + +local function flags(t) + if type(t) == "string" then + t = token.create(t) + end + local r = { } + if t.frozen then r[#r+1] = "frozen" end + if t.permanent then r[#r+1] = "permanent" end + if t.immutable then r[#r+1] = "immutable" end + if t.primitive then r[#r+1] = "primitive" end + if t.mutable then r[#r+1] = "mutable" end + if t.noaligned then r[#r+1] = "noaligned" end + if t.instance then r[#r+1] = "instance" end + if t.tolerant then r[#r+1] = "tolerant" end + if t.protected then r[#r+1] = "protected" end + return r +end + +tokens.flags= flags + +interfaces.implement { + name = "showluatokens", + public = true, + protected = true, + actions = function() + local f0 = formatters["%s: %s"] + local nl = logs.newline + local wr = logs.writer + local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) + local n = "" + local w = "" + local c = t.cmdname + if c == "left_brace" then + w = "given token list" + t = token.scan_toks(false) + elseif c == "register_toks" then + token.scan_next() + w = "token register" + n = t.csname or t.index + t = tex.gettoks(n,true) + elseif c == "internal_toks" then + token.scan_next() + w = "internal token variable" + n = t.csname or t.index + t = tex.gettoks(n,true) + else + n = token.scan_csname() + local r = flags(t) + local m = token.get_meaning(n,true) + r[#r+1] = "control sequence" + if type(m) == "table" then + t = m + else + t = { t } + end + w = concat(r, " ") + end + wr(f0(w,n)) + nl() + if type(t) == "table" then + local w1 = 4 + local w2 = 1 + local w3 = 3 + local w4 = 3 + for i=1,#t do + local ti = t[i] + w1 = max(w1,#tostring(ti.id)) + w2 = max(w2,#tostring(ti.command)) + w3 = max(w3,#tostring(ti.index)) + w4 = max(w4,#ti.cmdname) + end + local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] + local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] + local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] + for i=1,#t do + local ti = t[i] + local cs = ti.csname + local id = ti.id + local ix = ti.index + local cd = ti.command + local cn = ti.cmdname + if cn == "prefix" and not cs then + cs = "always enforced" + end + cn = gsub(cn,"_"," ") + if cs then + wr(f1(id,cd,ix,cn,cs)) + elseif cn == "letter" or cn == "other char" then + wr(f3(id,cd,ix,cn,ix)) + elseif cn == "match" then + local s + if ix == 32 then s = "optional spacer" -- space + elseif ix == 42 then s = "skip spaces" -- * + elseif ix == 43 then s = "keep braces" -- + + elseif ix == 45 then s = "thrash" -- - + elseif ix == 47 then s = "prune" -- / + elseif ix == 58 then s = "continue" -- : + elseif ix == 59 then s = "quit" -- ; + elseif ix == 61 then s = "mandate braces" -- = + elseif ix == 94 then s = "keep spaces" -- ^ + elseif ix == 95 then s = "keep mandate braces" -- _ + else s = "argument " .. char(ix) + end + wr(f1(id,cd,ix,cn,s)) + else + wr(f2(id,cd,ix,cn)) + if cn == "end match" then + wr("--------------") + end + end + end + nl() + end + end +} + +-- For the moment here, will move to initex only (also see node-ini.lua); we need +-- to actually store these. + +local groupcodes = { } +local glyphoptioncodes = { } +local hyphenationcodes = { } +local frozenparcodes = { } +local flagcodes = { } +local normalizecodes = { } + +for k, v in next, tex.getgroupvalues() do + groupcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.gethyphenationvalues() do + hyphenationcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getglyphoptionvalues() do + glyphoptioncodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getfrozenparvalues() do + frozenparcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getflagvalues() do + flagcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getnormalizevalues() do + normalizecodes[k] = gsub(v,"[_ ]","") +end + + +if environment.initex then + + local texintegerdef = tex.integerdef + + for k, v in next, groupcodes do texintegerdef(v .. "groupcode", k,"immutable") end + for k, v in next, glyphoptioncodes do texintegerdef(v .. "code", k,"immutable") end + for k, v in next, hyphenationcodes do texintegerdef(v .. "hyphenationmodecode",k,"immutable") end + for k, v in next, frozenparcodes do texintegerdef("frozen" .. v .. "code", k,"immutable") end + for k, v in next, flagcodes do texintegerdef(v .. "flagcode", k,"immutable") end + for k, v in next, normalizecodes do texintegerdef(v .. "code", k,"immutable") end + +end + +groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes)) +glyphoptioncodes = utilities.storage.allocate(table.swapped(glyphoptioncodes,glyphoptioncodes)) +hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodes)) +frozenparcodes = utilities.storage.allocate(table.swapped(frozenparcodes, frozenparcodes)) +flagcodes = utilities.storage.allocate(table.swapped(flagcodes, flagcodes)) +normalizecodes = utilities.storage.allocate(table.swapped(normalizecodes, normalizecodes)) + +tex.groupcodes = groupcodes +tex.glyphoptioncodes = glyphoptioncodes +tex.hyphenationcodes = hyphenationcodes +tex.frozenparcodes = frozenparcodes +tex.flagcodes = flagcodes +tex.normalizecodes = normalizecodes diff --git a/tex/context/base/mkxl/toks-aux.mkxl b/tex/context/base/mkxl/toks-aux.mkxl new file mode 100644 index 000000000..4563014ec --- /dev/null +++ b/tex/context/base/mkxl/toks-aux.mkxl @@ -0,0 +1,68 @@ +%D \module +%D [ file=toks-aux, +%D version=2018.11.29, +%D title=\CONTEXT\ Token Support, +%D subtitle=Helpers, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Token Support / Helpers} + +\unprotect + +%D The older \type {\scantokens} overload has been replace by a more modern one (in +%D \LMTX): +%D +%D \starttyping +%D \protected\def\whatever#1[#2](#3)\relax{oeps #1 and #2 and #3 done ## error} +%D \scratchtoks{foo \framed{\red 123}456} +%D +%D \showluatokens{123\what} +%D \showluatokens\whatever +%D \showluatokens\framed +%D +%D \showluatokens\scratchtoks +%D \showluatokens\everypar +%D \stoptyping + +\registerctxluafile{toks-aux}{autosuffix} + +\installcorenamespace {tokenlist} + +\permanent\protected\def\definetokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \global\lastnamedcs\emptytoks + \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi} + +\permanent\protected\def\starttokenlist[#1]#2\stoptokenlist + {\ifcsname\??tokenlist#1\endcsname \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi + \toksapp\lastnamedcs{#2}} + +\aliased\let\stoptokenlist\relax + +\permanent\def\gettokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \the\lastnamedcs + \fi} + +\permanent\protected\def\settokenlist[#1]#2% + {\ifcsname\??tokenlist#1\endcsname \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi + \toksapp\lastnamedcs{#2}} + +\permanent\protected\def\resettokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \lastnamedcs\emptytoks + \fi} + +\protect diff --git a/tex/context/base/mkxl/toks-ini.lmt b/tex/context/base/mkxl/toks-ini.lmt new file mode 100644 index 000000000..4b2d1facc --- /dev/null +++ b/tex/context/base/mkxl/toks-ini.lmt @@ -0,0 +1,332 @@ +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 next = next +local tonumber = tonumber +local tostring = tostring +local utfchar = utf.char +local char = string.char +local printtable = table.print +local concat = table.concat +local format = string.format + +local commands = token.getcommandvalues() +local values = token.getfunctionvalues() +values.dimen = values.dimension +values.count = values.integer +tokens.values = utilities.storage.allocate(table.swapped(values, values)) +tokens.commands = utilities.storage.allocate(table.swapped(commands,commands)) + +local scan_toks = token.scan_toks +local scan_string = token.scan_string +local scan_argument = token.scan_argument +local scan_delimited = token.scan_delimited +local scan_tokenlist = token.scan_tokenlist or scan_string +local scan_integer = token.scan_integer or token.scan_int +local scan_cardinal = token.scan_cardinal +local scan_code = token.scan_code +local scan_token_code = token.scan_token_code +local scan_dimen = token.scan_dimen +local scan_glue = token.scan_glue +local scan_skip = token.scan_skip +local scan_keyword = token.scan_keyword +local scan_keyword_cs = token.scan_keyword_cs or scan_keyword +local scan_token = token.scan_token +local scan_box = token.scan_box +local scan_word = token.scan_word +local scan_letters = token.scan_letters or scan_word -- lmtx +local scan_key = token.scan_key +local scan_value = token.scan_value +local scan_char = token.scan_char +local scan_number = token.scan_number -- not defined +local scan_csname = token.scan_csname +local scan_real = token.scan_real +local scan_float = token.scan_float +local scan_luanumber = token.scan_luanumber or scan_float -- only lmtx +local scan_luainteger = token.scan_luainteger or scan_integer -- only lmtx +local scan_luacardinal = token.scan_luacardinal or scan_cardinal -- only lmtx + +local scan_integer_argument = token.scan_integer_argument +local scan_dimen_argument = token.scan_dimen_argument + +-- todo: gobble_integer -- might go away +-- todo: gobble_dimension -- might go away + +local set_macro = token.set_macro +local set_char = token.set_char +local set_lua = token.set_lua + +local create_token = token.create +local new_token = token.new +local is_defined = token.is_defined +local is_token = token.is_token + +tokens.new = new_token +tokens.create = create_token +tokens.istoken = is_token +tokens.isdefined = is_defined +tokens.defined = is_defined + +tokens.getinteger = token.get_integer +tokens.setinteger = token.set_integer + +local bits = { + escape = 0x00000001, -- 2^00 + begingroup = 0x00000002, -- 2^01 + endgroup = 0x00000004, -- 2^02 + mathshift = 0x00000008, -- 2^03 + alignment = 0x00000010, -- 2^04 + endofline = 0x00000020, -- 2^05 + parameter = 0x00000040, -- 2^06 + superscript = 0x00000080, -- 2^07 + subscript = 0x00000100, -- 2^08 + ignore = 0x00000200, -- 2^09 + space = 0x00000400, -- 2^10 -- 1024 + letter = 0x00000800, -- 2^11 + other = 0x00001000, -- 2^12 + active = 0x00002000, -- 2^13 + comment = 0x00004000, -- 2^14 + invalid = 0x00008000, -- 2^15 + -- + character = 0x00001800, -- 2^11 + 2^12 + whitespace = 0x00002400, -- 2^13 + 2^10 -- / needs more checking + -- + open = 0x00000402, -- 2^10 + 2^01 -- space + begingroup + close = 0x00000404, -- 2^10 + 2^02 -- space + endgroup +} + +-- for k, v in next, bits do bits[v] = k end + +tokens.bits = bits + +-- words are space or \relax terminated and the trailing space is gobbled; a word +-- can contain any non-space letter/other (see archive for implementation in lua) + +if not scan_number 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 + +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 + +local function scan_verbatim() + return scan_argument(false) +end + +if not scan_box then + + local scan_list = token.scan_list + local put_next = token.put_next + + scan_box = function(s) + if s == "hbox" or s == "vbox" or s == "vtop" then + put_next(create_token(s)) + end + return scan_list() + end + + token.scan_box = scan_box + +end + +tokens.scanners = { -- these expand + token = scan_token, + toks = scan_toks, + tokens = scan_toks, + box = scan_box, + hbox = function() return scan_box("hbox") end, + vbox = function() return scan_box("vbox") end, + vtop = function() return scan_box("vtop") end, + dimen = scan_dimen, + dimension = scan_dimen, + glue = scan_glue, + gluevalues = function() return scan_glue(false,false,true) end, + gluespec = scan_skip, + integer = scan_integer, + cardinal = scan_cardinal, + real = scan_real, + float = scan_float, + luanumber = scan_luanumber, + luainteger = scan_luainteger, + luacardinal = scan_luacardinal, + count = scan_integer, + string = scan_string, + argument = scan_argument, + delimited = scan_delimited, + tokenlist = scan_tokenlist, + verbatim = scan_verbatim, -- detokenize + code = scan_code, + tokencode = scan_token_code, + word = scan_word, + letters = scan_letters, + key = scan_key, + value = scan_value, + char = scan_char, + number = scan_number, + boolean = scan_boolean, + keyword = scan_keyword, + keywordcs = scan_keyword_cs, + csname = scan_csname, + + next = token.scan_next, + nextexpanded = token.scan_next_expanded, + + peek = token.peek_next, + peekexpanded = token.peek_next_expanded, + peekchar = token.peek_next_char, + + skip = token.skip_next, + skipexpanded = token.skip_next_expanded, + + cmdchr = token.scan_cmdchr, + cmdchrexpanded = token.scan_cmdchr_expanded, + + ischar = token.is_next_char, + + integerargument = scan_integer_argument, + dimenargument = scan_dimen_argument, +} + +tokens.getters = { -- these don't expand + meaning = token.get_meaning, + macro = token.get_macro, + token = token.scan_next or token.get_next, -- not here, use scanners.next or token + cstoken = token.get_cstoken, + 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, + char = set_char, + lua = set_lua, + count = tex.setcount, + dimen = tex.setdimen, + skip = tex.setglue, + glue = tex.setglue, + skip = tex.setmuglue, + glue = tex.setmuglue, + box = tex.setbox, +} + +token.accessors = { + command = token.get_command, + cmd = token.get_command, + cmdname = token.get_cmdname, + name = token.get_cmdname, + csname = token.get_csname, + index = token.get_index, + active = token.get_active, + frozen = token.get_frozen, + protected = token.get_protected, + expandable = token.get_protected, + user = token.get_user, + cmdchrcs = token.get_cmdchrcs, + active = token.get_active, + range = token.get_range, +} + +-- 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; +-- } + +if setinspector then + + local simple = { letter = "letter", other_char = "other" } + + local astable = function(t) + if t and is_token(t) then + local cmdname = t.cmdname + local simple = simple[cmdname] + if simple then + return { + id = t.id, + category = simple, + character = utfchar(t.index) or nil, + } + else + return { + id = t.id, + command = t.command, + index = t.index, + csname = t.csname, + cmdname = cmdname, + active = t.active, + expandable = t.expandable, + frozen = t.frozen, + tolerant = t.tolerant, + protected = t.protected, + primitive = t.primitive, + permanent = t.permanent, + noaligned = t.noaligned, + instance = t.instance, + immutable = t.imutable, + user = t.user, + } + end + end + end + + tokens.astable = astable + + setinspector("token",function(v) local t = astable(v) if t then printtable(t,tostring(v)) return true end end) + +end + +tokens.cache = table.setmetatableindex(function(t,k) + if not is_defined(k) then + set_macro(k,"","global") + end + local v = create_token(k) + t[k] = v + return v +end) diff --git a/tex/context/base/mkxl/toks-ini.mkxl b/tex/context/base/mkxl/toks-ini.mkxl new file mode 100644 index 000000000..c7d7bceb3 --- /dev/null +++ b/tex/context/base/mkxl/toks-ini.mkxl @@ -0,0 +1,20 @@ +%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} + +\unprotect + +\registerctxluafile{toks-ini}{autosuffix} + +\protect \endinput diff --git a/tex/context/base/mkxl/toks-scn.lmt b/tex/context/base/mkxl/toks-scn.lmt new file mode 100644 index 000000000..93e0af09a --- /dev/null +++ b/tex/context/base/mkxl/toks-scn.lmt @@ -0,0 +1,592 @@ +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 scanargument = scanners.argument +local scandelimited = scanners.delimited -- lmtx +local scanverbatim = scanners.verbatim +local scantokenlist = scanners.tokenlist +local scantoks = scanners.toks +local scaninteger = scanners.integer +local scancardinal = scanners.cardinal +local scannumber = scanners.number +local scankeyword = scanners.keyword +local scankeywordcs = scanners.keywordcs +local scanword = scanners.word +local scanletters = scanners.letters +local scankey = scanners.key +local scancode = scanners.code +local scanboolean = scanners.boolean +local scandimen = scanners.dimen +local scanglue = scanners.glue +local scangluevalues = scanners.gluevalues +local scangluespec = scanners.gluespec +local scancsname = scanners.csname +local scanintegerargument = scanners.integerargument +local scandimenargument = scanners.dimenargument + +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 + +local function scantable(t,data) + if not data then + data = { } + end + if t then + local wrapped = scanopen() + while true do + local key = scanword(true) + 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 + end + return data +end + +function tokens.constant(s) + if type(s) == "string" then + return "'" .. s .. "'" + else + return s + end +end + +scanners.list = scanlist +scanners.table = scantable +scanners.conditional = scanconditional + +function scanners.whd() + local width, height, depth + while true do + if scankeyword("width") then + width = scandimen() + elseif scankeyword("height") then + height = scandimen() + elseif scankeyword("depth") then + depth = scandimen() + else + break + end + end + if width or height or depth then + return width or 0, height or 0, depth or 0 + else + -- we inherit + end +end + +-- begin lmtx + +local l = utf.byte("[") +local r = utf.byte("]") + +local function scanbracketed() + local s = scandelimited(l, r) + if s then + return s + else + local readstate = status.getreadstate() + report_scan("missing argument in line %i of %a", readstate.linenumber, readstate.filename) + return "" + end +end + +local function scanoptional() + return scandelimited(l, r) or "" +end + +local function scanbracketedasis() + return scandelimited(l, r, false) +end + +local function scanargumentasis() + return scanargument(false) +end + +scanners.bracketed = scanbracketed +scanners.optional = scanoptional +scanners.bracketedasis = scanbracketedasis +scanners.argumentasis = scanargumentasis + +-- end lmtx + +local shortcuts = { + tokens = tokens, + bits = tokenbits, + open = open, + close = close, + scanners = scanners, + scanstring = scanstring, + scanargument = scanargument, + scanverbatim = scanverbatim, + scantokenlist = scantokenlist, + scantoks = scantoks, + scaninteger = scaninteger, + scancardinal = scancardinal, + scannumber = scannumber, + scantable = scantable, -- not directly useable + scankeyword = scankeyword, + scankeywordcs = scankeywordcs, + scanword = scanword, + scanletters = scanletters, + -- scankey = scankey, + scancode = scancode, + scanboolean = scanboolean, + scanglue = scanglue, -- list + scangluespec = scangluespec, + scangluevalues = scangluevalues, + scandimen = scandimen, + scandimension = scandimen, + scanbox = scanners.box, + scanhbox = scanners.hbox, + scanvbox = scanners.vbox, + scanvtop = scanners.vtop, + scanconditional = scanconditional, + scanopen = scanopen, + scanclose = scanclose, + scanlist = scanlist, + scancsname = scancsname, + todimen = todimen, + tonumber = tonumber, + tostring = tostring, + toboolean = toboolean, + inspect = inspect, + report = report_scan, + -- lmtx + scandelimited = scandelimited, -- not directly useable + scanbracketed = scanbracketed, + scanoptional = scanoptional, + scanbracketedasis = scanbracketedasis, + scanargumentasis = scanargumentasis, + -- + scanintegerargument = scanintegerargument, + scandimenargument = scandimenargument, +} + +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", +} + +-- We could just pickup a keyword but then we really need to make sure that no number +-- follows it when that is the assignment and adding an optional = defeats the gain +-- in speed. Currently we have sources with no spaces (\startcontextdefinitioncode +-- ...) so it fails there. +-- +-- Another drawback is that we then need to use { } instead of ending with \relax (as +-- we can do now) but that is no big deal. It's just that I then need to check the TeX +-- end. More pain than gain and a bit risky too. Using scanletters works better, but +-- the gain is only some 10 percent but if we don't have keywords with numbers it might +-- make sense in the end, some day. + +local f_if = formatters[ " if scankeywordcs('%s') then data['%s'] = scan%s()"] +local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = scan%s()"] + +----- f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] +----- f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] + +-- if CONTEXTLMTXMODE > 0 then +-- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"] +-- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"] +-- end + +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 scankeywordcs('%s') then data['%s'] = %s(scan%s())"] +local f_elseif_c = formatters[" elseif scankeywordcs('%s') then data['%s'] = %s(scan%s())"] +local f_scan_c = formatters["%s(scan%s())"] + +-- see above + +-- if CONTEXTLMTXMODE > 0 then +-- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"] +-- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"] +-- end + +local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"] +local f_any_c = formatters[" else local key = scanword(true) 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(true) if key then data[key] = scan%s() else break end"] +local f_any_all_c= formatters[" local key = scanword(true) 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_singular = formatters["%\nt\n%\nt\n\nreturn function(%s)\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 = scanopen() + while true do + ]] .. "%\nt\n" .. [[ + %s + end + if wrapped then + scanclose() + end +]] ] + +-- using these shortcuts saves temporary small tables (okay, it looks uglier) + +local presets = { + ["1 string" ] = { "string" }, + ["2 strings"] = { "string", "string" }, + ["3 strings"] = { "string", "string", "string" }, + ["4 strings"] = { "string", "string", "string", "string" }, + ["5 strings"] = { "string", "string", "string", "string", "string" }, + ["6 strings"] = { "string", "string", "string", "string", "string", "string" }, + ["7 strings"] = { "string", "string", "string", "string", "string", "string", "string" }, + ["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" }, + + ["1 argument" ] = { "argument" }, + ["2 arguments"] = { "argument", "argument" }, + ["3 arguments"] = { "argument", "argument", "argument" }, + ["4 arguments"] = { "argument", "argument", "argument", "argument" }, +} + +tokens.presets = presets + +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 args + 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) + -- r[m] = (m > 1 and f_elseif_x or f_if_x)(t1,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 p = t and presets[t] -- already done in implement + if p then + t = p + 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) + n = n + 1 + f[n] = 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) + n = n + 1 + f[n] = 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) + n = n + 1 + f[n] = f_action_s(i,i) + end + code = f_simple(f,code) + else + return scanners[ti] + end + elseif #t == 0 then + if specification.usage == "value" then + code = "b" + args = "_,b" + else + code = "" + args = "" + end + if a then + tokens._action = a + for i=1,#a do + code = f_action_f(i,code) + n = n + 1 + f[n] = f_action_s(i,i) + end + end + code = f_singular(c,f,args,code) + 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) + n = n + 1 + f[n] = 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() diff --git a/tex/context/base/mkxl/toks-scn.mkxl b/tex/context/base/mkxl/toks-scn.mkxl new file mode 100644 index 000000000..12abf0cb8 --- /dev/null +++ b/tex/context/base/mkxl/toks-scn.mkxl @@ -0,0 +1,26 @@ +%D \module +%D [ file=toks-ini, +%D version=2007.03.03, +%D title=\CONTEXT\ Token Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Token Support / Scanners} + +\unprotect + +\registerctxluafile{toks-scn}{} +\registerctxluafile{cldf-scn}{} +\registerctxluafile{cldf-stp}{} + +\ifcase \contextlmtxmode \else + \registerctxluafile{cldf-lmt}{} +\fi + +\protect \endinput diff --git a/tex/context/base/mkxl/trac-ctx.mkxl b/tex/context/base/mkxl/trac-ctx.mkxl new file mode 100644 index 000000000..656a7a9aa --- /dev/null +++ b/tex/context/base/mkxl/trac-ctx.mkxl @@ -0,0 +1,58 @@ +%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}{} + +\unprotect + +\permanent\protected\def\installtextracker #1#2#3{\clf_installtextracker {#1}{\detokenize{#2}}{\detokenize{#3}}} +\permanent\protected\def\installtexdirective #1#2#3{\clf_installtexdirective {#1}{\detokenize{#2}}{\detokenize{#3}}} +\permanent\protected\def\installtexexperiment#1#2#3{\clf_installtexexperiment{#1}{\detokenize{#2}}{\detokenize{#3}}} + +\appendtoks + \clf_initializetextrackers + \clf_initializetexdirectives + \clf_initializetexexperiments +\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/tex/context/base/mkxl/trac-deb.lmt b/tex/context/base/mkxl/trac-deb.lmt new file mode 100644 index 000000000..b9827c3a9 --- /dev/null +++ b/tex/context/base/mkxl/trac-deb.lmt @@ -0,0 +1,419 @@ +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" +} + +-- This is an old mechanism, a result of some experiments in the early days of +-- luatex and mkiv, but still nice anyway. I will clean it up in lmtx. + +local status = status + +local tonumber, tostring, type = tonumber, tostring, type +local format, concat, match, find, gsub = string.format, table.concat, string.match, string.find, string.gsub + +local report_nl = logs.newline +local report_str = logs.writer + +tracers = tracers or { } +local tracers = tracers + +local implement = interfaces.implement + +local ioflush = io.flush +local ioread = io.read +local writenl = texio.write_nl +local write = texio.write + +local runlocal = tex.runlocal +local terminaldata = false +local context = context + +interfaces.implement { + name = "fetchterminaldata", + actions = function() + context(terminaldata) + end, +} + +function texio.terminal() + writenl("\n" .. "entering interactive mode, use \\quit to abort reading" .."\n\n") + while true do + write(">") + ioflush() + terminaldata = ioread() + if terminaldata == "\\quit" then + terminaldata = false + break + else + runlocal("t_syst_terminal_data",nil,nil,true) -- obeymode + end + end +end + +interfaces.implement { + name = "readfromterminal", + public = true, + protected = true, + actions = texio.terminal, +} + +local savedluaerror = nil +local usescitelexer = nil +local quitonerror = true + +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 scite = usescitelexer and require("util-sci") + if scite then + return utilities.scite.tohtml(data,"tex",linenumber or true,false) + else + 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 "" + 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 "" + end + end +end + +-- 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,errortype) + local readstate = status.readstate + local filename = readstate.filename + local linenumber = readstate.linenumber + local skiplinenumber = readstate.skiplinenumber + local errorstate = status.errorstate + local lastcontext = errorstate.errorcontext + local lasttexerror = errorstate.error or "?" + local lastluaerror = errorstate.luaerror or "?" -- lasttexerror + local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0) + local lastmpserror = match(lasttexerror,[[^.-mp%serror:%s*(.*)$]]) + resetmessages() + lastluaerror = gsub(lastluaerror,"%[\\directlua%]","[ctxlua]") + tracers.printerror { + filename = filename, + linenumber = linenumber, + skiplinenumber = skiplinenumber, + offset = tonumber(offset) or 10, + lasttexerror = lasttexerror, + lastmpserror = lastmpserror, + lastluaerror = lastluaerror, -- can be the same as lasttexerror + luaerrorline = luaerrorline, + lastcontext = lastcontext, + lasttexhelp = tex.gethelptext and tex.gethelptext() or nil, + errortype = errortype, + } + if job and type(job.disablesave) == "function" then + job.disablesave() + end +end + +directives.register("system.quitonerror",function(v) + quitonerror = toboolean(v) +end) + +directives.register("system.usescitelexer",function(v) + usescitelexer = toboolean(v) +end) + +local busy = false + +function tracers.printerror(specification) + if not busy then + busy = true + local errorvalues = table.swapped(tex.geterrorvalues()) + local filename = specification.filename + local linenumber = specification.linenumber + local lasttexerror = specification.lasttexerror + local lastmpserror = specification.lastmpserror + local lastluaerror = specification.lastluaerror + local lastcontext = specification.lastcontext + local luaerrorline = specification.luaerrorline + local errortype = specification.errortype + local offset = specification.offset + local endoffile = specification.endoffile + local report = errorreporter(luaerrorline) + if errortype == errorvalues.warning then + report("warning error: %s",lasttexerror or "-") + busy = false; + return; + elseif errortype == errorvalues.eof then + report("runaway error: %s",lasttexerror or "-") + if not quitonerror and texio.terminal then + texio.terminal() -- not well tested + end + elseif errortype == errorvalues.condition then + linenumber = specification.skiplinenumber + if linenumber > 0 then + report("condition error on line %s in file %s: %s",linenumber,filename,lasttexerror) + report_nl() + report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline))) + report_nl() + else + report("runaway condition error: %s",lasttexerror or "-") + end + quitonerror = true + elseif not filename then + report("fuzzy error:") + report(" tex: %s",lasttexerror or "-") + report(" lua: %s",lastluaerror or "-") + report(" mps: %s",lastmpserror or "-") + elseif type(filename) == "number" then + report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror) + else + report_nl() + if luaerrorline then + if linenumber == 0 or not filename or filename == "" then + print("\nfatal lua error:\n\n",lastluaerror,"\n") + luatex.abort() + return + else + report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror) + end + elseif lastmpserror then + report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror) + else + report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror) + if lastcontext then + report_nl() + report_str(lastcontext) + report_nl() + else + report_nl() + -- tex.showcontext() + end + if lastluaerror and not match(lastluaerror,"^%s*[%?]*%s*$") then + print("\nlua error:\n\n",lastluaerror,"\n") + quitonerror = true + end + end + report_nl() + report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline))) + report_nl() + end + local errname = file.addsuffix(tex.jobname .. "-error","log") + if quitonerror then + table.save(errname,specification) + local help = specification.lasttexhelp + if help and #help > 0 then + report_nl() + report_str(help) + report_nl() + report_nl() + end + luatex.abort() + end + busy = false + end +end + +luatex.wrapup(function() os.remove(file.addsuffix(tex.jobname .. "-error","log")) end) + +local function processwarning(offset) + local warningstate = status.warningstate + local lastwarning = warningstate.warning or "?" + local lastlocation = warningstate.warningtag or "?" + resetmessages() + tracers.printwarning { + 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('intercept_lua_error', function() processerror(v) end) + register('intercept_tex_error', function(mode,eof) processerror(v,eof) return mode end) + else + register('show_error_message', nil) + register('show_warning_message', nil) + register('intercept_lua_error', nil) + register('intercept_tex_error', 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 + +local function reportback(lmxname,default,variables) + if lmxname == false then + return variables + else + local name = lmx.show(type(lmxname) == "string" and lmxname or default,variables) + if name then + logs.report("context report","file: %s",name) + end + end +end + +local function showerror(lmxname) + local readstate = status.readstate() + local filename = readstate.filename + local linenumber = tonumber(readstate.linenumber) or 0 + local errorcontext = "" + if not filename then + filename = status.iocodes[readstate.iocode] + errorcontext = 'error in filename' + else + errorcontext = tracers.showlines(filename,linenumber,offset) + end + local variables = { + ['title'] = 'ConTeXt Error Information', + ['errormessage'] = status.errorstatus.error or "?", + ['linenumber'] = linenumber, + ['color-background-one'] = lmx.get('color-background-yellow'), + ['color-background-two'] = lmx.get('color-background-purple'), + ['filename'] = filename, + ['errorcontext'] = errorcontext, + } + reportback(lmxname,"context-error.lmx",variables) + luatex.abort() +end + +lmx.showerror = showerror + +function lmx.overloaderror(v) + if v == "scite" then + usescitelexer = true + end + callback.register('show_error_message', function() showerror() end) + callback.register('intercept_lua_error', function() showerror() end) + callback.register('intercept_tex_error', function() showerror() end) +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 + +-- Obsolete ... not that usefull as normally one runs from an editor and +-- when run unattended it makes no sense either. + +-- local editor = [[scite "-open:%filename%" -goto:%linenumber%]] +-- +-- directives.register("system.editor",function(v) +-- editor = v +-- end) +-- +-- callback.register("call_edit",function(filename,linenumber) +-- if editor then +-- editor = gsub(editor,"%%s",filename) +-- editor = gsub(editor,"%%d",linenumber) +-- editor = gsub(editor,"%%filename%%",filename) +-- editor = gsub(editor,"%%linenumber%%",linenumber) +-- logs.report("system","starting editor: %s",editor) +-- os.execute(editor) +-- end +-- end) + +local implement = interfaces.implement + +implement { name = "showtrackers", public = true, protected = true, actions = trackers.show } +implement { name = "enabletrackers", public = true, protected = true, actions = trackers.enable, arguments = "optional" } +implement { name = "disabletrackers", public = true, protected = true, actions = trackers.disable, arguments = "optional" } +implement { name = "resettrackers", public = true, protected = true, actions = trackers.reset } + +implement { name = "showdirectives", public = true, protected = true, actions = directives.show } +implement { name = "enabledirectives", public = true, protected = true, actions = directives.enable, arguments = "optional" } +implement { name = "disabledirectives", public = true, protected = true, actions = directives.disable, arguments = "optional" } + +implement { name = "showexperiments", public = true, protected = true, actions = experiments.show } +implement { name = "enableexperiments", public = true, protected = true, actions = experiments.enable, arguments = "optional" } +implement { name = "disableexperiments", public = true, protected = true, actions = experiments.disable, arguments = "optional" } + +implement { name = "overloaderror", public = true, protected = true, actions = lmx.overloaderror } +implement { name = "showlogcategories", public = true, protected = true, actions = logs.show } + +local debugger = utilities.debugger + +directives.register("system.profile",function(n) + luatex.registerstopactions(function() + debugger.disable() + debugger.savestats("luatex-profile.log",tonumber(n) or 0) + report_nl() + logs.report("system","profiler stopped, log saved in %a","luatex-profile.log") + report_nl() + end) + logs.report("system","profiler started") + debugger.enable() +end) diff --git a/tex/context/base/mkxl/trac-deb.mkxl b/tex/context/base/mkxl/trac-deb.mkxl new file mode 100644 index 000000000..37a901aa3 --- /dev/null +++ b/tex/context/base/mkxl/trac-deb.mkxl @@ -0,0 +1,48 @@ +%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} + +%registerctxluafile{trac-lmx}{} +\registerctxluafile{trac-deb}{autosuffix} + +\unprotect + +\permanent\protected\def\breakpoint{\showdebuginfo\wait} + +% \showtrackers % defined at the lua end +% \enabletrackers [#1] % defined at the lua end +% \disabletrackers [#1] % defined at the lua end +% \resettrackers % defined at the lua end +% +% \showdirectives % defined at the lua end +% \enabledirectives [#1] % defined at the lua end +% \disabledirectives [#1] % defined at the lua end +% +% \showexperiments % defined at the lua end +% \enableexperiments [#1] % defined at the lua end +% \disableexperiments[#1] % defined at the lua end +% +% \showdebuginfo % defined at the lua end +% \overloaderror % defined at the lua end +% +% \showlogcategories % defined at the lua end + +% \enabledirectives[system.showerror] + +\newtoks \t_syst_terminal_data + +%t_syst_terminal_data {\beginlocalcontrol\clf_fetchterminaldata\endlocalcontrol} +\t_syst_terminal_data {\clf_fetchterminaldata} + +\protect \endinput diff --git a/tex/context/base/mkxl/trac-inf.lmt b/tex/context/base/mkxl/trac-inf.lmt new file mode 100644 index 000000000..9207d5b45 --- /dev/null +++ b/tex/context/base/mkxl/trac-inf.lmt @@ -0,0 +1,425 @@ +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, gsub, rep = string.format, string.lower, string.find, string.gsub, string.rep +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, offset = 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, offset = 0 } +end + +local ticks = clock +local seconds = function(n) return n or 0 end + +ticks = lua.getpreciseticks +seconds = lua.getpreciseseconds + +local function starttiming(instance,reset) + local timer = timers[instance or "notimer"] + local it = timer.timing + if reset then + it = 0 + timer.loadtime = 0 + end + if it == 0 then + timer.starttime = ticks() + if not timer.loadtime then + 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 and starttime > 0 then + local stoptime = ticks() + local loadtime = stoptime - starttime + timer.stoptime = stoptime + timer.loadtime = timer.loadtime + loadtime + timer.timing = 0 + timer.starttime = 0 + return loadtime + end + end + return 0 +end + +local function benchmarktimer(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 and starttime > 0 then + timer.offset = ticks() - starttime + else + timer.offset = 0 + end + end +end + +local function elapsed(instance) + if type(instance) == "number" then + return instance + else + local timer = timers[instance or "notimer"] + return timer and seconds(timer.loadtime - 2*(timer.offset or 0)) or 0 + end +end + +local function currenttime(instance) + if type(instance) == "number" then + return instance + else + local timer = timers[instance or "notimer"] + local it = timer.timing + if it > 1 then + -- whatever + else + local starttime = timer.starttime + if starttime and starttime > 0 then + return seconds(timer.loadtime + ticks() - starttime - 2*(timer.offset or 0)) + end + end + return 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.currenttime = currenttime +statistics.elapsed = elapsed +statistics.elapsedtime = elapsedtime +statistics.elapsedindeed = elapsedindeed +statistics.elapsedseconds = elapsedseconds +statistics.benchmarktimer = benchmarktimer + +-- general function .. we might split this module + +function statistics.register(tag,fnc) + if statistics.enable and type(fnc) == "function" then + -- second load can overload: + 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("used engine", function() + return format("%s version: %s, functionality level: %s, format id: %s, compiler: %s", + LUATEXENGINE, LUATEXVERSION, LUATEXFUNCTIONALITY, LUATEXFORMATID, status.used_compiler) + end) + register("tex properties", function() + local t = status.gethashstate() + local m = status.gettexstate() + return format("%s hash slots used of %s, approximate memory usage: %i MB", + t.top, t.max, m.approximate // (1024 * 1024)) + end) + register("callbacks", statistics.callbacks) + -- so far + register("lua properties",function() + local hash = lua.gethashchars() + local mask = load([[τεχ = 1]]) and "utf" or "ascii" + return format("engine: %s %s, used memory: %s, hash chars: min(%i,40), symbol mask: %s (%s)", + "lua", LUAVERSION, statistics.memused(), hash, 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 + local luastate = status.getluastate() + return format("%s MB, ctx: %s MB, max: %s MB", + round(collectgarbage("count")//1024), + round(luastate.state_bytes//1048576), + luastate.state_bytes_max and round(luastate.state_bytes_max//1048576) or "unknown" + ) +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) + -- stoptiming(statistics) -- somehow we can start the timer twice, but where + local runtime = lua.getruntime and lua.getruntime() or elapsedtime(statistics) + return statistics.formatruntime(runtime) +end + +local report = logs.reporter("system") + +function statistics.timed(action,all) + starttiming("run") + action() + stoptiming("run") + local runtime = tonumber(elapsedtime("run")) + if all then + local alltime = tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics)) + if alltime and alltime > 0 then + report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime) + return + end + end + report("total runtime: %0.3f seconds",runtime) +end + +-- goodie + +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 + +-- now here + +status.iocodes = setmetatableindex(tex.getiovalues(), function() return "unknown" end) + +local report = logs.reporter("system") + +function statistics.showusage(when) + local s = status.list() + local c = status.getcallbackstate() -- status.callbacks + local m = mplib.getcallbackstate() + local b = backends.getcallbackstate() + -- + local estatus = s.expandstate + local tstatus = s.texstate + local lstatus = s.luastate + local rstatus = s.readstate + -- + local pstatus = logs.private.getpagetiming() + -- + local iocode = status.iocodes[rstatus.iocode] + -- + local mpinstances, mpmemory = metapost.getstatistics(true) + -- + report("") + if when == "finish" then + report("status after finishing run") + else + report("status after shipping out page %s",tex.getcount("realpageno")) + end + report("") + local list = { + "stringstate", "poolstate", "hashstate", "lookupstate", + "nodestate", "extrastate", "tokenstate", + "bufferstate", "inputstate", "filestate", + "neststate", "parameterstate", "savestate", + "fontstate", "languagestate", "markstate", "sparsestate", + } + local fields = { "max", "min", "set", "stp", false, "mem", "all", false, "ini", "ptr", "top" } + local line = rep("-",190) + do + local t = { } + for i=1,#list do + t[i] = gsub(list[i],"state","") + end + report("%w%s",2,line) + report("%w%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",5,unpack(t)) + report("%w%s",2,line) + end + for i=1,#fields do + local f = fields[i] + if f then + local t = { } + for i=1,#list do + local n = s[list[i]][f] + t[i] = n < 0 and formatters["%w"](11) or formatters["%11i"](n) + end + report(" %3s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",f,unpack(t)) + else + report("") + end + end + report("%w%s",2,line) + report("") + report(" current input type : %s", iocode) + if iocode == "file" then + report(" current file name : %s", rstatus.filename or "") + report(" current line number : %s", rstatus.linenumber) + end + report("") + report(" approximate memory : %s (%s MB)", tstatus.approximate, tstatus.approximate // 1048576) + report("") + report(" expansion depth : min: %s, max: %s, set: %s, top: %s", estatus.min, estatus.max, estatus.set, estatus.top) + report("") + report(" luabytecode registers : %s", lstatus.bytecodes) + report(" luabytecode bytes : %s (%s MB)", lstatus.bytecode_bytes, lstatus.bytecode_bytes // 1048576) + report(" luastate bytes now : %s (%s MB)", lstatus.state_bytes, lstatus.state_bytes // 1048576) + report(" luastate bytes max : %s (%s MB)", lstatus.state_bytes_max, lstatus.state_bytes_max // 1048576) + report("") + report(" file callbacks : %s", c.file) + report(" saved callbacks : %s", c.saved) + report(" direct callbacks : %s", c.direct) + report(" function callbacks : %s", c["function"]) + report(" value callbacks : %s", c.value) + report(" message callbacks : %s", c.message) + report(" bytecode callbacks : %s", c.bytecode) + report("") + report(" mp instances : %s", mpinstances) + report(" mp estimated memory : %s (%s MB)", mpmemory, mpmemory // 1048576) + report(" mp file callbacks : %s", m.file) + report(" mp text callbacks : %s", m.text) + report(" mp script callbacks : %s", m.script) + report(" mp log callbacks : %s", m.log) + report("") + report(" total callbacks : %s", c.count) + report(" mp total callbacks : %s", m.count) + report(" backend callbacks : %s", b.count) + report("") + report(" page numbers : realpage %s, userpage %s, subpage %s",pstatus.page.real,pstatus.page.user,pstatus.page.sub) + report(" page timing : total %0.03f, page %0.03f, average %0.03f",pstatus.time.elapsed,pstatus.time.page,pstatus.time.average) + report("") +end + +function statistics.showmemory(when) + local s = status.list() + -- + report("") + report("memory configuration") + report("") + local list = { + "stringstate", "poolstate", "hashstate", "lookupstate", + "nodestate", "tokenstate", + "bufferstate", "inputstate", "filestate", + "neststate", "parameterstate", "savestate", + "fontstate", "languagestate", "markstate", + } + local fields = { "max", "min", "set", "stp" } + local line = rep("-",168) + do + local t = { } + for i=1,#list do + t[i] = gsub(list[i],"state","") + end + report("%w%s",2,line) + report("%w%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",5,unpack(t)) + report("%w%s",2,line) + end + for i=1,#fields do + local f = fields[i] + if f then + local t = { } + for i=1,#list do + local n = s[list[i]][f] + t[i] = n < 0 and formatters["%w"](11) or formatters["%11i"](n) + end + report(" %3s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s%11s",f,unpack(t)) + else + report("") + end + end + report("%w%s",2,line) + report("") +end + +local registered = false +local enabled = false + +trackers.register("system.usage", function(v) + if v and not registered then + logs.private.enablepagetiming() + if v ~= "summary" then + luatex.registerpageactions(function() + if enabled then + statistics.showusage("page") + end + end) + end + luatex.registerstopactions(function() + if enabled then + statistics.showusage("finish") + end + end) + registered = true + end + enabled = v +end) diff --git a/tex/context/base/mkxl/trac-jus.mkxl b/tex/context/base/mkxl/trac-jus.mkxl new file mode 100644 index 000000000..3375e5ee7 --- /dev/null +++ b/tex/context/base/mkxl/trac-jus.mkxl @@ -0,0 +1,24 @@ +%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}{} + +\unprotect + +\definesystemattribute [justification] [public] + +\permanent\protected\def\showjustification{\clf_showjustification} % currently no argument (default 1), todo: public implementor + +\protect \endinput diff --git a/tex/context/base/mkxl/trac-tex.mkxl b/tex/context/base/mkxl/trac-tex.mkxl new file mode 100644 index 000000000..f9c763c4f --- /dev/null +++ b/tex/context/base/mkxl/trac-tex.mkxl @@ -0,0 +1,69 @@ +%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}{} + +%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{...} + +\mutable\let\alltextracers\empty % so that we can report available tracers + +\permanent\protected\def\installtextracer#1% + {\addtocommalist{#1}\alltextracers} + +\permanent\protected\def\enabletextracers [#1]{\processcommalist[#1]\syst_textracers_enable } +\permanent\protected\def\disabletextracers[#1]{\processcommalist[#1]\syst_textracers_disable} + +\def\syst_textracers_enable #1{\begincsname enabletracer#1\endcsname} +\def\syst_textracers_disable#1{\begincsname disabletracer#1\endcsname} + +% The next one is for Taco, although we can use directives as well: + +\protected\def\nomkivstatistics{\enabledirectives[system.nostatistics]} + +%D This is not really a tracker but for decades it lived in my \type {cont-loc} +%D file. I moved it here because I wanted someone else to use it. This macro is not +%D really useful for users. I kept the \LUA\ variant in \type {cont-loc.mkiv}. + +\installcorenamespace{profilemacrocount} +\installcorenamespace{profilemacromacro} + +\newtoks\t_syst_profile + +\appendtoks + \the\t_syst_profile +\to \everystoptext + +\permanent\protected\def\profilemacro#1% an oldie, but modernized a bit + {\edef\p_name{\csstring#1}% + \ifcsname\??profilemacrocount\p_name\endcsname \else + \expandafter\newcount\csname\??profilemacrocount\p_name\endcsname + \letcsname\??profilemacromacro\p_name\endcsname#1% + \xtoksapp\t_syst_profile + {\writestatus + {profile}% + {\string#1: \noexpand\the\csname\??profilemacrocount\p_name\endcsname}}% + \enforced\protected\xdef#1% + {\global\advance\csname\??profilemacrocount\p_name\endcsname\plusone + \expandafter\noexpand\csname\??profilemacromacro\p_name\endcsname}% + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/trac-tim.lmt b/tex/context/base/mkxl/trac-tim.lmt new file mode 100644 index 000000000..fcba7f132 --- /dev/null +++ b/tex/context/base/mkxl/trac-tim.lmt @@ -0,0 +1,178 @@ +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.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 function convert(name) + name = name ~= "" and name or progress.defaultfilename + if not processed[name] then + local pages = 0 + local names = { } + local top = { } + local bot = { } + local siz = { } + local paths = { } + local data = table.load(name .. ".lut") + if data then + pages = #data + if pages > 1 then + + local factor = 100 + + local function path(tag,subtag,tagname) + local tagname = tag .. ": " .. subtag + local b, t, s = nil, nil, { } + for k=1,#data do + local v = data[k][tag] + v = v and v[subtag] + if v then + if type(v) == "table" then + set[tagname] = tonumber(v.set) + v = tonumber(v.top) + else + v = tonumber(v) + end + if v then + if b then + if v > t then t = v end + if v < b then b = v end + else + t = v + b = v + end + else + v = 0 + end + else + v = 0 + end + s[k] = v + end + if not b then + -- safeguard against updates + b = 0 + t = 0 + end + 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,"--") + return tagname + end + + local function collect(category) + if data[1][category] then + local keys = { } + for k=1,#data do + for k, v in next, data[k][category] do + keys[k] = true + end + end + for k=1,#data do + local m = data[k][category] + for k, v in next, keys do + if not m[k] then m[k] = 0 end + end + end + for k in next, keys do + names[#names+1] = path(category,k) + end + end + end + + collect("nodes") + collect("stock") + collect("memories") + collect("variables") + collect("texvariables") + collect("luavariables") + collect("texcallbacks") + collect("mpcallbacks") + collect("backendcallbacks") + + pages = pages - 1 -- hm + end + end + + sort(names) + + processed[name] = { + names = names, + top = top, + bot = bot, + set = set, + pages = pages, + paths = paths, + } + end + return processed[name] +end + +progress.convert = convert + +function progress.set(name,tag) + return convert(name).set[tag] or 0 +end + +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.names(name) + return convert(name).names or { } +end + diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt new file mode 100644 index 000000000..7ac5964da --- /dev/null +++ b/tex/context/base/mkxl/trac-vis.lmt @@ -0,0 +1,1700 @@ +if not modules then modules = { } end modules ['trac-vis'] = { + version = 1.001, + optimize = true, + comment = "companion to trac-vis.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local node, nodes, attributes, tex = node, nodes, attributes, tex +local type, tonumber, next, rawget = type, tonumber, next, rawget +local gmatch = string.gmatch +local formatters = string.formatters +local round = math.round + +-- This module started out in the early days of mkiv and luatex with visualizing +-- kerns related to fonts. In the process of cleaning up the visual debugger code it +-- made sense to integrate some other code that I had laying around and replace the +-- old supp-vis debugging code. As only a subset of the old visual debugger makes +-- sense it has become a different implementation. Soms of the m-visual +-- functionality will also be ported. The code is rather trivial. The caching is not +-- really needed but saves upto 50% of the time needed to add visualization. Of +-- course the overall runtime is larger because of color and layer processing in the +-- backend (can be times as much) so the runtime is somewhat larger with full +-- visualization enabled. In practice this will never happen unless one is demoing. + +-- todo: global switch (so no attributes) +-- todo: maybe also xoffset, yoffset of glyph +-- todo: inline concat (more efficient) +-- todo: tags can also be numbers (just add to hash) +-- todo: make a lmtx variant (a few more efficient fetchers) + +local nodecodes = nodes.nodecodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local setboth = nuts.setboth +local setlink = nuts.setlink +local setdisc = nuts.setdisc +local setlist = nuts.setlist +local setleader = nuts.setleader +local setsubtype = nuts.setsubtype +local setattr = nuts.setattr +local setwidth = nuts.setwidth +local setshift = nuts.setshift + +local getid = nuts.getid +local getfont = nuts.getfont +local getattr = nuts.getattr +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getlist = nuts.getlist +local getleader = nuts.getleader +local getnext = nuts.getnext +local getboth = nuts.getboth +local getdisc = nuts.getdisc +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getpenalty = nuts.getpenalty +local getwidth = nuts.getwidth +local getdepth = nuts.getdepth +local getshift = nuts.getshift +local getexpansion = nuts.getexpansion +local getdirection = nuts.getdirection +local getstate = nuts.getstate + +local isglyph = nuts.isglyph + +local hpack_nodes = nuts.hpack +local vpack_nodes = nuts.vpack +local copy_list = nuts.copy_list +local copy_node = nuts.copy_node +local flush_node_list = nuts.flush_list +local insert_node_before = nuts.insert_before +local insert_node_after = nuts.insert_after +local apply_to_nodes = nuts.apply +local effectiveglue = nuts.effective_glue + +local hpack_string = nuts.typesetters.tohpack + +local texgetattribute = tex.getattribute +local texsetattribute = tex.setattribute + +local setmetatableindex = table.setmetatableindex + +local unsetvalue = attributes.unsetvalue + +local current_font = font.current + +local fonthashes = fonts.hashes +local chardata = fonthashes.characters +local exheights = fonthashes.exheights +local emwidths = fonthashes.emwidths +local pt_factor = number.dimenfactors.pt + +local nodepool = nuts.pool +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_glue = nodepool.glue +local new_hlist = nodepool.hlist +local new_vlist = nodepool.vlist + +local tracers = nodes.tracers +local visualizers = nodes.visualizers + +local setcolor = tracers.colors.set +local setlistcolor = tracers.colors.setlist +local settransparency = tracers.transparencies.set +local setlisttransparency = tracers.transparencies.setlist + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local a_visual = attributes.private("visual") +local a_layer = attributes.private("viewerlayer") + +local band = bit32.band +local bor = bit32.bor + +local enableaction = nodes.tasks.enableaction + +-- local trace_hbox +-- local trace_vbox +-- local trace_vtop +-- local trace_kern +-- local trace_glue +-- local trace_penalty +-- local trace_fontkern +-- local trace_strut +-- local trace_whatsit +-- local trace_user +-- local trace_math +-- local trace_italic +-- local trace_discretionary +-- local trace_expansion +-- local trace_line +-- local trace_space + +local report_visualize = logs.reporter("visualize") + +local modes = { + hbox = 0x000001, + vbox = 0x000002, + vtop = 0x000004, + kern = 0x000008, + glue = 0x000010, + penalty = 0x000020, + fontkern = 0x000040, + strut = 0x000080, + whatsit = 0x000100, + glyph = 0x000200, + simple = 0x000400, + simplehbox = 0x000401, + simplevbox = 0x000402, + simplevtop = 0x000404, + user = 0x000800, + math = 0x001000, + italic = 0x002000, + origin = 0x004000, + discretionary = 0x008000, + expansion = 0x010000, + line = 0x020000, + space = 0x040000, + depth = 0x080000, + marginkern = 0x100000, + mathlistkern = 0x200000, + dir = 0x400000, + par = 0x800000, +} + +local usedfont, exheight, emwidth +local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_marginkern, l_mathlistkern, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth, + l_dir, l_whatsit + +local enabled = false +local layers = { } + +local preset_boxes = modes.hbox + modes.vbox + modes.vtop + modes.origin +local preset_makeup = preset_boxes + + modes.kern + modes.glue + modes.penalty +local preset_all = preset_makeup + + modes.fontkern + modes.marginkern + modes.mathlistkern + + modes.whatsit + modes.glyph + modes.user + modes.math + + modes.dir + modes.whatsit + +function visualizers.setfont(id) + usedfont = id or current_font() + exheight = exheights[usedfont] + emwidth = emwidths[usedfont] +end + +-- we can preset a bunch of bits + +local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") + +local function initialize() + -- + if not usedfont then + -- we use a narrow monospaced font -- infofont ? + visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") }) + end + -- + for mode, value in next, modes do + local tag = formatters["v_%s"](mode) + attributes.viewerlayers.define { + tag = tag, + title = formatters["visualizer %s"](mode), + visible = "start", + editable = "yes", + printable = "yes" + } + layers[mode] = attributes.viewerlayers.register(tag,true) + end + l_hbox = layers.hbox + l_vbox = layers.vbox + l_vtop = layers.vtop + l_glue = layers.glue + l_kern = layers.kern + l_penalty = layers.penalty + l_fontkern = layers.fontkern + l_strut = layers.strut + l_whatsit = layers.whatsit + l_glyph = layers.glyph + l_user = layers.user + l_math = layers.math + l_italic = layers.italic + l_marginkern = layers.marginkern + l_mathlistkern = layers.mathlistkern + l_origin = layers.origin + l_discretionary = layers.discretionary + l_expansion = layers.expansion + l_line = layers.line + l_space = layers.space + l_depth = layers.depth + l_dir = layers.dir + l_par = layers.par + -- + if not userrule then + userrule = nuts.rules.userrule + end + -- + if not outlinerule then + outlinerule = nuts.pool.outlinerule + end + initialize = false +end + +local function enable() + if initialize then + initialize() + end + enableaction("shipouts","nodes.visualizers.handler") + report_visualize("enabled") + enabled = true + tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end +end + +local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in + if not n or n == "reset" then + return unsetvalue + elseif n == true or n == "makeup" then + if not a or a == 0 or a == unsetvalue then + a = preset_makeup + else + a = bor(a,preset_makeup) + end + elseif n == "boxes" then + if not a or a == 0 or a == unsetvalue then + a = preset_boxes + else + a = bor(a,preset_boxes) + end + elseif n == "all" then + if what == false then + return unsetvalue + elseif not a or a == 0 or a == unsetvalue then + a = preset_all + else + a = bor(a,preset_all) + end + else + for s in gmatch(n,"[a-z]+") do + local m = modes[s] + if not m then + -- go on + elseif not a or a == 0 or a == unsetvalue then + a = m + else + a = bor(a,m) + end + end + end + if not a or a == 0 or a == unsetvalue then + return unsetvalue + elseif not enabled then -- must happen at runtime (as we don't store layers yet) + enable() + end + return a +end + +function nuts.setvisual(n,mode) + setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true)) +end + +function nuts.setvisuals(n,mode) -- currently the same + setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true,true)) +end + +-- fast setters + +do + + local cached = setmetatableindex(function(t,k) + if k == true then + return texgetattribute(a_visual) + elseif not k then + t[k] = unsetvalue + return unsetvalue + else + local v = setvisual(k) + t[k] = v + return v + end + end) + + -- local function applyvisuals(n,mode) + -- local a = cached[mode] + -- apply_to_nodes(n,function(n) setattr(n,a_visual,a) end) + -- end + + local a = unsetvalue + + local f = function(n) setattr(n,a_visual,a) end + + local function applyvisuals(n,mode) + a = cached[mode] + apply_to_nodes(n,f) + end + + nuts.applyvisuals = applyvisuals + + function nodes.applyvisuals(n,mode) + applyvisuals(tonut(n),mode) + end + + function visualizers.attribute(mode) + return cached[mode] + end + + visualizers.attributes = cached + +end + +function nuts.copyvisual(n,m) + setattr(n,a_visual,getattr(m,a_visual)) +end + +function visualizers.setvisual(n) + texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual))) +end + +function visualizers.setlayer(n) + texsetattribute(a_layer,layers[n] or unsetvalue) +end + +local function set(mode,v) + texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v)) +end + +for mode, value in next, modes do + trackers.register(formatters["visualizers.%s"](mode), function(v) set(mode,v) end) +end + +local fraction = 10 + +trackers .register("visualizers.reset", function(v) set("reset", v) end) +trackers .register("visualizers.all", function(v) set("all", v) end) +trackers .register("visualizers.makeup", function(v) set("makeup",v) end) +trackers .register("visualizers.boxes", function(v) set("boxes", v) end) +directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end) + +local c_positive = "trace:b" +local c_negative = "trace:r" +local c_zero = "trace:g" +local c_text = "trace:s" +local c_space = "trace:y" +local c_space_x = "trace:m" +local c_skip_a = "trace:c" +local c_skip_b = "trace:m" +local c_glyph = "trace:o" +local c_ligature = "trace:s" +local c_white = "trace:w" +----- c_math = "trace:s" +----- c_origin = "trace:o" +----- c_discretionary = "trace:d" +----- c_expansion = "trace:o" +local c_depth = "trace:o" +local c_indent = "trace:s" + +local c_positive_d = "trace:db" +local c_negative_d = "trace:dr" +local c_zero_d = "trace:dg" +local c_text_d = "trace:ds" +local c_space_d = "trace:dy" +local c_space_x_d = "trace:dm" +local c_skip_a_d = "trace:dc" +local c_skip_b_d = "trace:dm" +local c_glyph_d = "trace:do" +local c_ligature_d = "trace:ds" +local c_white_d = "trace:dw" +local c_math_d = "trace:dr" +local c_origin_d = "trace:do" +local c_discretionary_d = "trace:dd" +----- c_expansion_d = "trace:do" +----- c_depth_d = "trace:do" +----- c_indent_d = "trace:ds" + +local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed + local text = hpack_string(str,usedfont) + local size = getwidth(text) + local rule = new_rule(size,2*exheight,exheight/2) + local kern = new_kern(-size) + if color then + setcolor(rule,color) + end + if textcolor then + setlistcolor(getlist(text),textcolor) + end + local info = setlink(rule,kern,text) + setlisttransparency(info,c_zero) + info = hpack_nodes(info) + local width = getwidth(info) + if lap then + info = new_hlist(setlink(new_kern(-width),info)) + else + info = new_hlist(info) -- a bit overkill: double wrapped + end + if layer then + setattr(info,a_layer,layer) + end + return info, width +end + +local function someblob(str,layer,color,textcolor,width) + local text = hpack_string(str,usedfont) + local size = getwidth(text) + local rule = new_rule(width,2*exheight,exheight/2) + local kern = new_kern(-width + (width-size)/2) + if color then + setcolor(rule,color) + end + if textcolor then + setlistcolor(getlist(text),textcolor) + end + local info = setlink(rule,kern,text) + setlisttransparency(info,c_zero) + info = hpack_nodes(info) + local width = getwidth(info) + info = new_hlist(info) + if layer then + setattr(info,a_layer,layer) + end + return info, width +end + +local caches = setmetatableindex("table") + +local fontkern, italickern, marginkern, mathlistkern do + + local f_cache = caches["fontkern"] + local i_cache = caches["italickern"] + local m_cache = caches["marginkern"] + local l_cache = caches["mathlistkern"] + + local function somekern(head,current,cache,color,layer) + local width = getkern(current) + local extra = getexpansion(current) + local kern = width + extra + local info = cache[kern] + if not info then + local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont) + local rule = new_rule(emwidth/fraction,6*exheight,2*exheight) + local list = getlist(text) + if kern > 0 then + setlistcolor(list,c_positive_d) + elseif kern < 0 then + setlistcolor(list,c_negative_d) + else + setlistcolor(list,c_zero_d) + end + setlisttransparency(list,color) + setcolor(rule,color) + settransparency(rule,color) + setshift(text,-5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,layer) + f_cache[kern] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + + fontkern = function(head,current) + return somekern(head,current,f_cache,c_text_d,l_fontkern) + end + + italickern = function(head,current) + return somekern(head,current,i_cache,c_glyph_d,l_italic) + end + + marginkern = function(head,current) + return somekern(head,current,m_cache,c_glyph_d,l_marginkern) + end + + mathlistkern = function(head,current) + return somekern(head,current,l_cache,c_glyph_d,l_mathlistkern) + end + +end + +local glyphexpansion do + + local f_cache = caches["glyphexpansion"] + + glyphexpansion = function(head,current) + local extra = getexpansion(current) + if extra and extra ~= 0 then + extra = extra / 1000 + local info = f_cache[extra] + if not info then + local text = hpack_string(round(extra),usedfont) + local rule = new_rule(emwidth/fraction,exheight,2*exheight) + local list = getlist(text) + if extra > 0 then + setlistcolor(list,c_positive_d) + elseif extra < 0 then + setlistcolor(list,c_negative_d) + end + setlisttransparency(list,c_text_d) + setcolor(rule,c_text_d) + settransparency(rule,c_text_d) + setshift(text,1.5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,l_expansion) + f_cache[extra] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + return head, current + end + +end + +local kernexpansion do + + local f_cache = caches["kernexpansion"] + + -- in mkiv we actually need to reconstruct but let's not do that now + + kernexpansion = function(head,current) + local extra = getexpansion(current) + if extra ~= 0 then + extra = extra / 1000 + local info = f_cache[extra] + if not info then + local text = hpack_string(round(extra),usedfont) + local rule = new_rule(emwidth/fraction,exheight,4*exheight) + local list = getlist(text) + if extra > 0 then + setlistcolor(list,c_positive_d) + elseif extra < 0 then + setlistcolor(list,c_negative_d) + end + setlisttransparency(list,c_text_d) + setcolor(rule,c_text_d) + settransparency(rule,c_text_d) + setshift(text,3.5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,l_expansion) + f_cache[extra] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + return head, current + end + +end + +local whatsit do + + local whatsitcodes = nodes.whatsitcodes + local w_cache = caches["whatsit"] + + local tags = { + open = "OPN", + write = "WRI", + close = "CLS", + special = "SPE", + latelua = "LUA", + savepos = "POS", + userdefined = "USR", + literal = "LIT", + setmatrix = "MAT", + save = "SAV", + restore = "RES", + } + + whatsit = function(head,current) + local what = getsubtype(current) + local info = w_cache[what] + if info then + -- print("hit whatsit") + else + info = sometext(formatters["W:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_whatsit) + w_cache[what] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local dir, par do + + local dircodes = nodes.dircodes + local dirvalues = nodes.dirvalues + + local cancel_code = dircodes.cancel + local l2r_code = dirvalues.l2r + local r2l_code = dirvalues.r2l + + local d_cache = caches["dir"] + + local tags = { + l2r = "L2R", + r2l = "R2L", + cancel = "CAN", + par = "PAR", + } + + par = function(head,current) + local what = "par" -- getsubtype(current) + local info = d_cache[what] + if info then + -- print("hit par") + else + info = sometext(formatters["L:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_dir) + d_cache[what] = info + end + return head, current + end + + dir = function(head,current) + local what = getsubtype(current) + if what == cancelcode then + what = "cancel" + elseif getdirection(current) == r2l_code then + what = "r2l" + else + what = "l2r" + end + local info = d_cache[what] + if info then + -- print("hit dir") + else + info = sometext(formatters["D:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_dir) + d_cache[what] = info + end + return head, current + end + +end + +local user do + + local u_cache = caches["user"] + + user = function(head,current) + local what = getsubtype(current) + local info = u_cache[what] + if info then + -- print("hit user") + else + info = sometext(formatters["U:%s"](what),usedfont) + setattr(info,a_layer,l_user) + u_cache[what] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local math do + + local mathcodes = nodes.mathcodes + local m_cache = { + beginmath = caches["bmath"], + endmath = caches["emath"], + } + local tags = { + beginmath = "B", + endmath = "E", + } + + math = function(head,current) + local what = getsubtype(current) + local tag = mathcodes[what] + local skip = getkern(current) + getwidth(current) -- surround + local info = m_cache[tag][skip] + if info then + -- print("hit math") + else + local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d) + local rule = new_rule(skip,-655360/fraction,2*655360/fraction) + setcolor(rule,c_math_d) + settransparency(rule,c_math_d) + setattr(rule,a_layer,l_math) + if tag == "beginmath" then + info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text)) + else + info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text)) + end + setattr(info,a_layer,l_math) + m_cache[tag][skip] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local ruleddepth do + + ruleddepth = function(current,wd,ht,dp) + local wd, ht, dp = getwhd(current) + if dp ~= 0 then + local rule = new_rule(wd,0,dp) + setcolor(rule,c_depth) + settransparency(rule,c_zero) + setattr(rule,a_layer,l_depth) + setlist(current,setlink(rule,new_kern(-wd),getlist(current))) + end + end + +end + +local ruledbox do + + local b_cache = caches["box"] + local o_cache = caches["origin"] + + setmetatableindex(o_cache,function(t,size) + local rule = new_rule(2*size,size,size) + local origin = hpack_nodes(rule) + setcolor(rule,c_origin_d) + settransparency(rule,c_origin_d) + setattr(rule,a_layer,l_origin) + t[size] = origin + return origin + end) + + ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent) + local wd, ht, dp = getwhd(current) + if wd ~= 0 then + local shift = getshift(current) + local next = getnext(current) + local prev = previous + setboth(current) + local linewidth = emwidth/fraction + local size = 2*linewidth + local this + if not simple then + this = b_cache[what] + if not this then + local text = hpack_string(what,usedfont) + this = setlink(new_kern(-getwidth(text)),text) + setlisttransparency(this,c_text) + this = new_hlist(this) + b_cache[what] = this + end + end + -- we need to trigger the right mode (else sometimes no whatits) + local info = setlink( + this and copy_list(this) or nil, + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { + width = wd, + height = ht, + depth = dp, + line = linewidth, + type = "box", + dashed = 3*size, + } + ) + -- + setlisttransparency(info,c_text) + info = new_hlist(info) -- important + -- + setattr(info,a_layer,layer) + if vertical then + if shift == 0 then + info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) + elseif trace_origin then + local size = 2*size + local origin = o_cache[size] + origin = copy_list(origin) + if getid(parent) == vlist_code then + setshift(origin,-shift) + info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info) + else + -- todo .. i need an example + info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) + end + setshift(current,0) + else + info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info) + setshift(current,0) + end + info = new_vlist(info,wd,ht,dp,shift) + else + if shift == 0 then + info = setlink(current,new_kern(-wd),info) + elseif trace_origin then + local size = 2*size + local origin = o_cache[size] + origin = copy_list(origin) + if getid(parent) == vlist_code then + info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info) + else + setshift(origin,-shift) + info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info) + end + setshift(current,0) + else + info = setlink(current,new_kern(-wd),info) + setshift(current,0) + end + info = new_hlist(info,wd,ht,dp,shift) + end + if next then + setlink(info,next) + end + if prev and prev > 0 then + setlink(prev,info) + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end + end + +end + +local ruledglyph do + + -- see boundingbox feature .. maybe a pdf stream is more efficient, after all we + -- have a frozen color anyway or i need a more detailed cache .. below is a more + -- texie approach + + ruledglyph = function(head,current,previous) -- wrong for vertical glyphs + local wd = getwidth(current) + if wd ~= 0 then + local wd, ht, dp = getwhd(current) + local next = getnext(current) + local prev = previous + setboth(current) + local linewidth = emwidth/(2*fraction) + local info + -- + info = setlink( + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { + width = wd, + height = ht, + depth = dp, + line = linewidth, + type = "box", + }, + new_kern(-wd) + ) + -- + local c, f = isglyph(current) + local char = chardata[f][c] + if char and type(char.unicode) == "table" then -- hackery test + setlistcolor(info,c_ligature) + setlisttransparency(info,c_ligature_d) + else + setlistcolor(info,c_glyph) + setlisttransparency(info,c_glyph_d) + end + info = new_hlist(info) + setattr(info,a_layer,l_glyph) + local info = setlink(current,new_kern(-wd),info) + info = hpack_nodes(info) + setwidth(info,wd) + if next then + setlink(info,next) + end + if prev then + setlink(prev,info) + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end + end + + function visualizers.setruledglyph(f) + ruledglyph = f or ruledglyph + end + +end + +local ruledglue do + + local gluecodes = nodes.gluecodes + + local userskip_code = gluecodes.userskip + local spaceskip_code = gluecodes.spaceskip + local xspaceskip_code = gluecodes.xspaceskip + local zerospaceskip_code = gluecodes.zerospaceskip or gluecodes.userskip + -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip + local leftskip_code = gluecodes.leftskip + local rightskip_code = gluecodes.rightskip + local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code + local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code + local indentskip_code = gluecodes.indentskip + local correctionskip_code = gluecodes.correctionskip + + local g_cache_v = caches["vglue"] + local g_cache_h = caches["hglue"] + + local tags = { + -- [userskip_code] = "US", + [gluecodes.lineskip] = "LI", + [gluecodes.baselineskip] = "BS", + [gluecodes.parskip] = "PS", + [gluecodes.abovedisplayskip] = "DA", + [gluecodes.belowdisplayskip] = "DB", + [gluecodes.abovedisplayshortskip] = "SA", + [gluecodes.belowdisplayshortskip] = "SB", + [gluecodes.topskip] = "TS", + [gluecodes.splittopskip] = "ST", + [gluecodes.tabskip] = "AS", + [gluecodes.lefthangskip] = "LH", + [gluecodes.righthangskip] = "RH", + [gluecodes.thinmuskip] = "MS", + [gluecodes.medmuskip] = "MM", + [gluecodes.thickmuskip] = "ML", + [gluecodes.intermathskip] = "IM", + [gluecodes.keepskip or 99] = "KS", + [gluecodes.mathskip] = "MT", + [gluecodes.leaders] = "NL", + [gluecodes.cleaders] = "CL", + [gluecodes.xleaders] = "XL", + [gluecodes.gleaders] = "GL", + -- true = "VS", + -- false = "HS", + [leftskip_code] = "LS", + [rightskip_code] = "RS", + [spaceskip_code] = "SP", + [xspaceskip_code] = "XS", + [zerospaceskip_code] = "ZS", + [parfillleftskip_code] = "PL", + [parfillrightskip_code] = "PR", + [indentskip_code] = "IN", + [correctionskip_code] = "CS", + } + + -- we sometimes pass previous as we can have issues in math (not watertight for all) + + ruledglue = function(head,current,vertical,parent) + local subtype = getsubtype(current) + local width = effectiveglue(current,parent) + local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) + local info = (vertical and g_cache_v or g_cache_h)[amount] + if info then + -- print("glue hit") + else + if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then + info = sometext(amount,l_glue,c_space) + elseif subtype == leftskip_code or subtype == rightskip_code then + info = sometext(amount,l_glue,c_skip_a) + elseif subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then + info = sometext(amount,l_glue,c_indent) + elseif subtype == userskip_code then + if width > 0 then + info = sometext(amount,l_glue,c_positive) + elseif width < 0 then + info = sometext(amount,l_glue,c_negative) + else + info = sometext(amount,l_glue,c_zero) + end + else + info = sometext(amount,l_glue,c_skip_b) + end + (vertical and g_cache_v or g_cache_h)[amount] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + + -- ruledspace = function(head,current,parent) + -- local subtype = getsubtype(current) + -- if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then + -- local width = effectiveglue(current,parent) + -- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor) + -- local info = g_cache_h[amount] + -- if info then + -- -- print("space hit") + -- else + -- info = sometext(amount,l_glue,c_space) + -- g_cache_h[amount] = info + -- end + -- info = copy_list(info) + -- head, current = insert_node_before(head,current,info) + -- return head, getnext(current) + -- else + -- return head, current + -- end + -- end + + local g_cache_s = caches["space"] + local g_cache_x = caches["xspace"] + + ruledspace = function(head,current,parent) + local subtype = getsubtype(current) + if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then -- not yet all space + local width = effectiveglue(current,parent) + local info + if subtype == spaceskip_code then + info = g_cache_s[width] + if not info then + info = someblob("SP",l_glue,c_space,nil,width) + g_cache_s[width] = info + end + else + info = g_cache_x[width] + if not info then + info = someblob("XS",l_glue,c_space_x,nil,width) + g_cache_x[width] = info + end + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + else + return head, current + end + end + +end + +local ruledkern do + + local k_cache_v = caches["vkern"] + local k_cache_h = caches["hkern"] + + ruledkern = function(head,current,vertical,mk) + local kern = getkern(current) + local cache = vertical and k_cache_v or k_cache_h + local info = cache[kern] + if not info then + local amount = formatters["%s:%0.3f"](vertical and "VK" or (mk and "MK") or "HK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_kern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_kern,c_negative) + else + info = sometext(amount,l_kern,c_zero) + end + cache[kern] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruleditalic do + + local i_cache = caches["italic"] + + ruleditalic = function(head,current) + local kern = getkern(current) + local info = i_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_kern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_kern,c_negative) + else + info = sometext(amount,l_kern,c_zero) + end + i_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruledmarginkern do + + local m_cache = caches["marginkern"] + + ruledmarginkern = function(head,current) + local kern = getkern(current) + local info = m_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("MK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_marginkern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_marginkern,c_negative) + else + info = sometext(amount,l_marginkern,c_zero) + end + m_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruledmathlistkern do + + local l_cache = caches["mathlistkern"] + + ruledmathlistkern = function(head,current) + local kern = getkern(current) + local info = l_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("LK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_mathlistkern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_mathlistkern,c_negative) + else + info = sometext(amount,l_mathlistkern,c_zero) + end + l_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruleddiscretionary do + + local d_cache = caches["discretionary"] + + ruleddiscretionary = function(head,current) + local d = d_cache[true] + if not the_discretionary then + local rule = new_rule(4*emwidth/fraction,4*exheight,exheight) + local kern = new_kern(-2*emwidth/fraction) + setlink(kern,rule) + setcolor(rule,c_discretionary_d) + settransparency(rule,c_discretionary_d) + setattr(rule,a_layer,l_discretionary) + d = new_hlist(kern) + d_cache[true] = d + end + insert_node_after(head,current,copy_list(d)) + return head, current + end + +end + +local ruledpenalty do + + local p_cache_v = caches["vpenalty"] + local p_cache_h = caches["hpenalty"] + + local raisepenalties = false + + directives.register("visualizers.raisepenalties",function(v) raisepenalties = v end) + + ruledpenalty = function(head,current,vertical) + local penalty = getpenalty(current) + local info = (vertical and p_cache_v or p_cache_h)[penalty] + if info then + -- print("penalty hit") + else + local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty) + if penalty > 0 then + info = sometext(amount,l_penalty,c_positive) + elseif penalty < 0 then + info = sometext(amount,l_penalty,c_negative) + else + info = sometext(amount,l_penalty,c_zero) + end + (vertical and p_cache_v or p_cache_h)[penalty] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + elseif raisepenalties then + setshift(info,-65536*4) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +do + + local disc_code = nodecodes.disc + local kern_code = nodecodes.kern + local glyph_code = nodecodes.glyph + local glue_code = nodecodes.glue + local penalty_code = nodecodes.penalty + local whatsit_code = nodecodes.whatsit + local user_code = nodecodes.user + local math_code = nodecodes.math + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local marginkern_code = nodecodes.marginkern + local mathlistkern_code = nodecodes.mathlistkern + local dir_code = nodecodes.dir + local par_code = nodecodes.par + + local kerncodes = nodes.kerncodes + local fontkern_code = kerncodes.fontkern + local italickern_code = kerncodes.italiccorrection + local leftmarginkern_code = kerncodes.leftmarginkern + local rightmarginkern_code = kerncodes.rightmarginkern + local mathlistkern_code = kerncodes.mathlistkern + ----- userkern_code = kerncodes.userkern + + local listcodes = nodes.listcodes + local linelist_code = listcodes.line + + local vtop_package_state = 3 -- todo: symbolic + + local cache + + local function visualize(head,vertical,forced,parent) + local trace_hbox = false + local trace_vbox = false + local trace_vtop = false + local trace_kern = false + local trace_glue = false + local trace_penalty = false + local trace_fontkern = false + local trace_strut = false + local trace_whatsit = false + local trace_glyph = false + local trace_simple = false + local trace_user = false + local trace_math = false + local trace_italic = false + local trace_origin = false + local trace_discretionary = false + local trace_expansion = false + local trace_line = false + local trace_space = false + local trace_depth = false + local trace_dir = false + local trace_par = false + local current = head + local previous = nil + local attr = unsetvalue + local prev_trace_fontkern = nil + local prev_trace_italic = nil + local prev_trace_marginkern = nil +-- local prev_trace_mathlist = nil + local prev_trace_expansion = nil + + while current do + local id = getid(current) + local a = forced or getattr(current,a_visual) or unsetvalue + local subtype + if a ~= attr then + prev_trace_fontkern = trace_fontkern + prev_trace_italic = trace_italic + prev_trace_marginkern = trace_marginkern +-- prev_trace_mathlistkern = trace_mathlistkern + prev_trace_expansion = trace_expansion + attr = a + if a == unsetvalue then + trace_hbox = false + trace_vbox = false + trace_vtop = false + trace_kern = false + trace_glue = false + trace_penalty = false + trace_fontkern = false + trace_strut = false + trace_whatsit = false + trace_glyph = false + trace_simple = false + trace_user = false + trace_math = false + trace_italic = false + trace_origin = false + trace_discretionary = false + trace_expansion = false + trace_line = false + trace_space = false + trace_depth = false + trace_marginkern = false + trace_mathlistkern = false + trace_dir = false + trace_par = false + if id == kern_code then + goto kern + else + goto list + end + else -- dead slow: + -- cache[a]() + trace_hbox = band(a,0x000001) ~= 0 + trace_vbox = band(a,0x000002) ~= 0 + trace_vtop = band(a,0x000004) ~= 0 + trace_kern = band(a,0x000008) ~= 0 + trace_glue = band(a,0x000010) ~= 0 + trace_penalty = band(a,0x000020) ~= 0 + trace_fontkern = band(a,0x000040) ~= 0 + trace_strut = band(a,0x000080) ~= 0 + trace_whatsit = band(a,0x000100) ~= 0 + trace_glyph = band(a,0x000200) ~= 0 + trace_simple = band(a,0x000400) ~= 0 + trace_user = band(a,0x000800) ~= 0 + trace_math = band(a,0x001000) ~= 0 + trace_italic = band(a,0x002000) ~= 0 + trace_origin = band(a,0x004000) ~= 0 + trace_discretionary = band(a,0x008000) ~= 0 + trace_expansion = band(a,0x010000) ~= 0 + trace_line = band(a,0x020000) ~= 0 + trace_space = band(a,0x040000) ~= 0 + trace_depth = band(a,0x080000) ~= 0 + trace_marginkern = band(a,0x100000) ~= 0 + trace_mathlistkern = band(a,0x200000) ~= 0 + trace_dir = band(a,0x400000) ~= 0 + trace_whatsit = band(a,0x800000) ~= 0 + end + elseif a == unsetvalue then + goto list + end + if trace_strut then + setattr(current,a_layer,l_strut) + elseif id == glyph_code then + if trace_glyph then + head, current = ruledglyph(head,current,previous) + end + if trace_expansion then + head, current = glyphexpansion(head,current) + end + elseif id == disc_code then + if trace_discretionary then + head, current = ruleddiscretionary(head,current) + end + local pre, post, replace = getdisc(current) + if pre then + pre = visualize(pre,false,a,parent) + end + if post then + post = visualize(post,false,a,parent) + end + if replace then + replace = visualize(replace,false,a,parent) + end + setdisc(current,pre,post,replace) + elseif id == kern_code then + goto kern + elseif id == glue_code then + local content = getleader(current) + if content then + setleader(current,visualize(content,false,nil,parent)) + elseif trace_glue then + head, current = ruledglue(head,current,vertical,parent) + elseif trace_space then + head, current = ruledspace(head,current,parent) + end + elseif id == penalty_code then + if trace_penalty then + head, current = ruledpenalty(head,current,vertical) + end + elseif id == hlist_code or id == vlist_code then + goto list + elseif id == whatsit_code then + if trace_whatsit then + head, current = whatsit(head,current) + end + elseif id == user_code then + if trace_user then + head, current = user(head,current) + end + elseif id == math_code then + if trace_math then + head, current = math(head,current) + end + elseif id == marginkern_code then + if trace_kern then + head, current = ruledkern(head,current,vertical,true) + end + elseif id == dir_code then + if trace_dir then + head, current = dir(head,current) + end + elseif id == par_code then + if trace_par then + head, current = par(head,current) + end + end + goto next + ::kern:: + subtype = getsubtype(current) + if subtype == fontkern_code then + if trace_fontkern or prev_trace_fontkern then + head, current = fontkern(head,current) + end + if trace_expansion or prev_trace_expansion then + head, current = kernexpansion(head,current) + end + elseif subtype == italickern_code then + if trace_italic or prev_trace_italic then + head, current = italickern(head,current) + elseif trace_kern then + head, current = ruleditalic(head,current) + end + elseif subtype == leftmarginkern_code or subtype == rightmarginkern_code then + if trace_marginkern or prev_trace_marginkern then + head, current = marginkern(head,current) + elseif trace_kern then + head, current = ruledmarginkern(head,current) + end + elseif subtype == mathlistkern_code then + if trace_mathlist then -- or prev_trace_mathlist then + head, current = mathlistkern(head,current) + elseif trace_kern then + head, current = ruledmathlistkern(head,current) + end + else + if trace_kern then + head, current = ruledkern(head,current,vertical) + end + end + goto next; + ::list:: + if id == hlist_code then + local content = getlist(current) + if content then + setlist(current,visualize(content,false,nil,current)) + end + if trace_depth then + ruleddepth(current) + end + if trace_line and getsubtype(current) == linelist_code then + head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent) + elseif trace_hbox then + head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent) + end + elseif id == vlist_code then + local content = getlist(current) + local isvtop = getstate(current) == vtop_package_state + local tag = nil + local layer = nil + if content then + setlist(current,visualize(content,true,nil,current)) + end + if trace_vtop then + if isvtop then + tag = "_T_" + layer = l_vtop + elseif trace_vbox then + tag = "__V" + layer = l_vbox + end + elseif trace_vbox then + if not isvtop then + tag = "__V" + layer = l_vbox + end + end + if tag then + head, current = ruledbox(head,current,true,layer,tag,trace_simple,previous,trace_origin,parent) + end + end + ::next:: + previous = current + current = getnext(current) + end + return head + end + + local function cleanup() + for tag, cache in next, caches do + for k, v in next, cache do + flush_node_list(v) + end + end + cleanup = function() + report_visualize("error, duplicate cleanup") + end + end + + luatex.registerstopactions(cleanup) + + function visualizers.handler(head) + if usedfont then + starttiming(visualizers) + head = visualize(head,true) + stoptiming(visualizers) + return head, true + else + return head, false + end + end + + function visualizers.box(n) + if usedfont then + starttiming(visualizers) + local box = getbox(n) + if box then + setlist(box,visualize(getlist(box),getid(box) == vlist_code)) + end + stoptiming(visualizers) + return head, true + else + return head, false + end + end + +end + +do + + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local nextnode = nuts.traversers.node + + local last = nil + local used = nil + + local mark = { + "trace:1", "trace:2", "trace:3", + "trace:4", "trace:5", "trace:6", + "trace:7", + } + + local function markfonts(list) + for n, id in nextnode, list do + if id == glyph_code then + local font = getfont(n) + local okay = used[font] + if not okay then + last = last + 1 + okay = mark[last] + used[font] = okay + end + setcolor(n,okay) + elseif id == hlist_code or id == vlist_code then + markfonts(getlist(n)) + end + end + end + + function visualizers.markfonts(list) + last, used = 0, { } + markfonts(type(n) == "number" and getlist(getbox(n)) or n) + end + +end + +statistics.register("visualization time",function() + if enabled then + -- cleanup() -- in case we don't don't do it each time + return formatters["%s seconds"](statistics.elapsedtime(visualizers)) + end +end) + +-- interface + +do + + local implement = interfaces.implement + + implement { + name = "setvisual", + arguments = "string", + actions = visualizers.setvisual + } + + implement { + name = "setvisuals", + arguments = "string", + actions = visualizers.setvisual + } + + implement { + name = "getvisual", + arguments = "string", + actions = { setvisual, context } + } + + implement { + name = "setvisuallayer", + arguments = "string", + actions = visualizers.setlayer + } + + implement { + name = "markvisualfonts", + arguments = "integer", + actions = visualizers.markfonts + } + + implement { + name = "setvisualfont", + arguments = "integer", + actions = visualizers.setfont + } + +end + +-- Here for now: + +do + + local function make(str,forecolor,rulecolor,layer) + if initialize then + initialize() + end + local rule = new_rule(emwidth/fraction,exheight,4*exheight) + setcolor(rule,rulecolor) + settransparency(rule,rulecolor) + local info + if str == "" then + info = new_hlist(rule) + else + local text = hpack_string(str,usedfont) + local list = getlist(text) + setlistcolor(list,textcolor) + setlisttransparency(list,textcolor) + setshift(text,3.5 * exheight) + info = new_hlist(setlink(rule,text)) + end + setattr(info,a_layer,layer) + return info + end + + function visualizers.register(name,textcolor,rulecolor) + if rawget(layers,name) then + -- message + return + end + local cache = caches[name] + local layer = layers[name] + if not textcolor then + textcolor = c_text_d + end + if not rulecolor then + rulecolor = c_origin_d + end + return function(str) + if not str then + str = "" + end + local info = cache[str] + if not info then + info = make(str,textcolor,rulecolor,layer) + cache[str] = info + end + return copy_node(info) + end + end + +end diff --git a/tex/context/base/mkxl/trac-vis.mkxl b/tex/context/base/mkxl/trac-vis.mkxl new file mode 100644 index 000000000..dd69e0bb8 --- /dev/null +++ b/tex/context/base/mkxl/trac-vis.mkxl @@ -0,0 +1,219 @@ +%D \module +%D [ file=trac-vis, % replaces supp-vis plus some s-* modules +%D version=2012.06.23, % 1996.10.21, +%D title=\CONTEXT\ Tracing Macros, +%D subtitle=Visualization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D The old visual debugger dates from 1996 and started out as joke. In practice +%D it's not used that often although the \type {\ruledhbox} cum suis macros come +%D in handy when writing code. In the process of luafication some additional +%D tracing options were tested, for instance showing font kerns. As part of the +%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider +%D all these features. The old code is gone and the new code will get extended +%D when needed. We still provide placeholders for some old visualization commands +%D but they might go away. +%D +%D Control over what gets visualized happens with the tracker command: +%D +%D \enabletrackers[visualizers.*] +%D +%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type +%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type +%D {makeup}, \type {whatsit}, \type{glyph}. +%D +%D In due time some special visualzation of math will move here as well. + +\writestatus{loading}{ConTeXt Tracing Macros / Visualization} + +\registerctxluafile{trac-vis}{autosuffix,optimize} + +\unprotect + +\newconstant\c_syst_visualizers_state +\newtoks \t_syst_visualizers_optimize + +% \definesystemattribute[visual][public,global] % already defined + +% no, but can become an option: +% +% \appendtoks +% \c_attr_visual\attributeunsetvalue +% \to \everybeforepagebody + +%D We only provide box visualizers as they can come in handy for testing +%D macros. In due time we will move some of the m-visual code here too. + +\aliased\let\syst_visualizers_hbox \hbox +\aliased\let\syst_visualizers_vbox \vbox +\aliased\let\syst_visualizers_vtop \vtop +\aliased\let\syst_visualizers_vcenter\vcenter +\aliased\let\syst_visualizers_hpack \hpack +\aliased\let\syst_visualizers_vpack \vpack +\aliased\let\syst_visualizers_tpack \tpack + +\permanent\protected\def\ruledhbox {\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} } +\permanent\protected\def\ruledhpack {\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} } +\permanent\protected\def\ruledvbox {\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledvpack {\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledvtop {\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} } +\permanent\protected\def\ruledtpack {\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} } +\permanent\protected\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledmbox #1{\ruledhbox{\startimath#1\stopimath}} + +\appendtoks + \ifcase\c_syst_visualizers_state\else + \syst_visualizers_speedup + \fi +\to \everyshipout + +\appendtoks + \glet\syst_visualizers_speedup\relax + \global\t_syst_visualizers_optimize\emptytoks +\to \t_syst_visualizers_optimize + +\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize} + +\appendtoks +% \enforced\global\protected\edef\ruledhbox {\syst_visualizers_hbox attr \visualattribute \number\clf_getvisual{simplehbox} } +% \enforced\global\protected\edef\ruledhpack {\syst_visualizers_hpack attr \visualattribute \number\clf_getvisual{simplehbox} } +% \enforced\global\protected\edef\ruledvbox {\syst_visualizers_vbox attr \visualattribute \number\clf_getvisual{simplevbox} } +% \enforced\global\protected\edef\ruledvpack {\syst_visualizers_vpack attr \visualattribute \number\clf_getvisual{simplevbox} } +% \enforced\global\protected\edef\ruledvtop {\syst_visualizers_vtop attr \visualattribute \number\clf_getvisual{simplevtop} } +% \enforced\global\protected\edef\ruledtpack {\syst_visualizers_tpack attr \visualattribute \number\clf_getvisual{simplevtop} } +% \enforced\global\protected\edef\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \number\clf_getvisual{simplevbox} } +\to \t_syst_visualizers_optimize + +\permanent\tolerant\protected\def\showmakeup[#1]% + {\ifarguments + \clf_setvisual{makeup}% + \else + \clf_setvisual{#1}% + \fi} + +\permanent\protected\def\showallmakeup {\clf_setvisual{all}\showstruts} +\permanent\protected\def\showboxes {\clf_setvisual{boxes}} +\permanent\protected\def\showglyphs {\clf_setvisual{glyph}} +\permanent\protected\def\showfontkerns {\clf_setvisual{fontkern}} +\permanent\protected\def\showfontitalics {\clf_setvisual{italic}} +\permanent\protected\def\showglyphdata {\showglyphs\showfontkerns\showfontitalics} +\permanent\protected\def\showfontexpansion{\clf_setvisual{expansion}} + +\permanent\tolerant\protected\def\setvisualizerfont[#1]% somename at 4pt + {\begingroup + \iftok{#1}\emptytoks + \definedfont[Mono at 4pt]% + \else + \definedfont[#1]% + \fi + \clf_setvisualfont\fontid\font + \endgroup} + +\permanent\protected\def\resetvisualizers + {\c_attr_visual\attributeunsetvalue} + +%D New (these might also be a visualizers): + +% \definecolor[f:r:t][a=1,t=.25,r=1] +% \definecolor[f:g:t][a=1,t=.25,g=1] +% \definecolor[f:b:t][a=1,t=.25,b=1] +% \definecolor[f:c:t][a=1,t=.25,c=1] +% \definecolor[f:m:t][a=1,t=.25,m=1] +% \definecolor[f:y:t][a=1,t=.25,y=1] +% \definecolor[f:k:t][a=1,t=.25,s=0] + +\permanent\protected\def\filledhboxr{\node_backgrounds_boxes_add\hbox[f:r:t]} +\permanent\protected\def\filledhboxg{\node_backgrounds_boxes_add\hbox[f:g:t]} +\permanent\protected\def\filledhboxb{\node_backgrounds_boxes_add\hbox[f:b:t]} +\permanent\protected\def\filledhboxc{\node_backgrounds_boxes_add\hbox[f:c:t]} +\permanent\protected\def\filledhboxm{\node_backgrounds_boxes_add\hbox[f:m:t]} +\permanent\protected\def\filledhboxy{\node_backgrounds_boxes_add\hbox[f:y:t]} +\permanent\protected\def\filledhboxk{\node_backgrounds_boxes_add\hbox[f:k:t]} + +%D Overload: + +\protected\def\spac_struts_vide_hbox + {\hbox attr \visualattribute \clf_getvisual{strut} } + +\appendtoks + \normalexpanded{\protected\xdef\spac_struts_vide_hbox\expandafter{\spac_struts_vide_hbox}}% +\to \t_syst_visualizers_optimize + +%D For manuals: + +\permanent\protected\def\markfonts#1% + {\dontleavehmode + \begingroup + \setbox\scratchbox\hbox{\getbuffer}% + \clf_markvisualfonts\scratchbox + \unhbox\scratchbox + \endgroup} + +% As demo: +% +% \startbuffer +% \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}} +% \blank +% \moveleft1cm\hbox{left} +% \blank +% \hbox{normal} +% \blank +% \moveright1cm\hbox{right} +% \blank +% \stopbuffer +% +% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer +% +% \startbuffer +% \moveleft1cm\vbox{left} +% \blank +% \vbox{normal} +% \blank +% \moveright1cm\vbox{right} +% \blank +% \stopbuffer +% +% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer + +%D We keep this one: + +\permanent\protected\def\dontinterfere + {\reseteverypar + \parindent\zeropoint + \parskip \zeropoint + \leftskip \zeropoint + \rightskip\zeropoint + \relax} + +%D We keep these for a while: + +% \aliased\let\ruledhss \hss +% \aliased\let\ruledhfil \hfil +% \aliased\let\ruledhfill \hfill +% \aliased\let\ruledhfilll \hfilll +% \aliased\let\ruledhfilneg \hfilneg +% \aliased\let\ruledhfillneg \hfillneg +% \aliased\let\ruledhfilllneg \hfilllneg +% \aliased\let\ruledvss \vss +% \aliased\let\ruledvfil \vfil +% \aliased\let\ruledvfill \vfill +% \aliased\let\ruledvfilll \vfilll +% \aliased\let\ruledvfilneg \vfilneg +% \aliased\let\ruledvfillneg \vfillneg +% \aliased\let\ruledvfilllneg \vfilllneg +% \aliased\let\ruledhskip \hskip +% \aliased\let\ruledvskip \vskip +% \aliased\let\ruledkern \kern +% \aliased\let\ruledhglue \hglue +% \aliased\let\ruledvglue \vglue +% \aliased\let\ruledmkern \mkern +% \aliased\let\ruledmskip \mskip +% \aliased\let\ruledpenalty \penalty + +\protect \endinput diff --git a/tex/context/base/mkxl/type-def.mkxl b/tex/context/base/mkxl/type-def.mkxl new file mode 100644 index 000000000..a80b4f7bd --- /dev/null +++ b/tex/context/base/mkxl/type-def.mkxl @@ -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/tex/context/base/mkxl/type-fbk.mkxl b/tex/context/base/mkxl/type-fbk.mkxl new file mode 100644 index 000000000..4ac381787 --- /dev/null +++ b/tex/context/base/mkxl/type-fbk.mkxl @@ -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/tex/context/base/mkxl/type-ini.mklx b/tex/context/base/mkxl/type-ini.mklx new file mode 100644 index 000000000..23c277f99 --- /dev/null +++ b/tex/context/base/mkxl/type-ini.mklx @@ -0,0 +1,615 @@ +%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}{} + +%D The default fontclass is empty. We could demand always using fontclasses, and +%D then make the calling macros simplier (always assume fontclass) but apart from +%D downward compatibility issues, it would make global, class spanning definitions a +%D 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 mutual +%D dependencies. +%D +%D At some point we will only store in memory so some code can go away. + +\unprotect + +\newcount \c_font_typescripts_n_of_preloaded +\newconditional\c_font_typescripts_quit +\newtoks \c_font_typescripts_document +\newconditional\c_font_typescripts_preload +\newconditional\c_font_typescripts_first_pass \settrue\c_font_typescripts_first_pass + +\newif \iftypescriptfound % will become a mode +\newif \iftracetypescripts + +\newtoks \everybeforedefinetypeface +\newtoks \everyafterdefinetypeface + +\mutable\let\typescriptfiles \empty +\mutable\let\currenttypescripts\empty +\mutable\let\currenttypefile \empty + +\installmacrostack\currenttypefile + +\mutable\let\typescriptone \empty % public, used in typescripts +\mutable\let\typescripttwo \empty % public, used in typescripts +\mutable\let\typescriptthree\empty % public, used in typescripts + +\installmacrostack\typescriptone +\installmacrostack\typescripttwo +\installmacrostack\typescriptthree + +\mutable\let\fontclassstyle \empty + +\installmacrostack\fontclassstyle + +\let\m_font_typescripts_one \empty +\let\m_font_typescripts_two \empty +\let\m_font_typescripts_three\empty +\let\m_font_typescripts_check\empty +\let\m_font_typescripts_match\empty + +\installmacrostack\m_font_typescripts_one +\installmacrostack\m_font_typescripts_two +\installmacrostack\m_font_typescripts_three + +\mutable\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 + +\installmacrostack\typescriptmethod +\installmacrostack\typescriptstate + +%D When these are loaded it is possible to get spaces but the whole idea is to do +%D that loading in vertical mode. Adding \type {\pushendofline} and \type +%D {\popendofline} is an option but not watertight as it can still interfere, for +%D instance work comments and leading spaces. Also, in horizontal mode it is likely +%D that one is also grouped and loading bodyfonts grouped is a real bad idea. +%D Ignoring all spaces is also not a solution. So, our verdict is: no catch. + +\permanent\protected\def\starttypescriptcollection % redefined on the fly + {\dosingleempty\font_typescripts_collection_start} + +\def\font_typescripts_collection_start[#tag]% + {} + +\permanent\let\stoptypescriptcollection\relax + +\permanent\protected\def\usetypescriptfile[#filename]% + {\iftok{#filename}{\v!reset}% + \let\typescriptfiles\empty + \else + \splitfilename{#filename}% + \addtocommalist\splitoffbase\typescriptfiles + \fi} + +\installmacrostack\stoptypescript + +% \permanent\protected\def\usetypescript {\dotripleempty\font_typescripts_use_one} +% \permanent\protected\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two} +% +% \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} +% \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} +% +% \protected\def\font_typescripts_use[#one][#two][#three]% + +% todo: just pass the method ... also further on then .. first test + +\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} +\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} + +\permanent\protected\def\usetypescript {\font_typescripts_use_one} +\permanent\protected\def\usetypescriptexact{\font_typescripts_use_two} + +\tolerant\protected\def\font_typescripts_use[#one]#spacer[#two]#spacer[#three]% + {\push_macro_m_font_typescripts_one + \push_macro_m_font_typescripts_two + \push_macro_m_font_typescripts_three + \edef\m_font_typescripts_one {\truetypescript{#one}}% + \edef\m_font_typescripts_two {\truetypescript{#two}}% + \edef\m_font_typescripts_three{\truetypescript{#three}}% + \push_macro_typescriptone + \push_macro_typescripttwo + \push_macro_typescriptthree + \push_macro_typescriptmethod + \push_macro_typescriptstate + \push_macro_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 + \pop_macro_stoptypescript + \pop_macro_typescriptstate + \pop_macro_typescriptmethod + \pop_macro_typescriptthree + \pop_macro_typescripttwo + \pop_macro_typescriptone + \pop_macro_m_font_typescripts_three + \pop_macro_m_font_typescripts_two + \pop_macro_m_font_typescripts_one} + +\def\font_typescripts_use_display + {\processcommacommand[\typescriptfiles]\font_typescripts_load_file + \the\c_font_typescripts_document} + +\let\font_typescripts_use_inline\font_typescripts_use_display + +\permanent\protected\def\preloadtypescripts + {\ifproductionrun\settrue\c_font_typescripts_preload\fi} + +\prependtoks + \preloadtypescripts +\to \everyjob + +\permanent\protected\def\loadtypescriptfile[#1]% + {\push_macro_typescriptstate + \let\typescriptstate\plustwo % assumes 2 at the outer level + \clf_loadtypescriptfile{#1}% + \pop_macro_typescriptstate} + +\permanent\protected\def\loadfoundtypescriptfile#1#2% name foundname / not a user command + {\startreadingfile + \unprotect + \pushendofline + \input{#2}% + \popendofline + \protect + \stopreadingfile} + +\permanent\protected\def\quittypescriptscanning + {\settrue\c_font_typescripts_quit} % public + +\permanent\protected\def\font_typescripts_start_store#definitions\stoptypescript + {\global\advance\c_font_typescripts_n_of_preloaded\plusone + \gdefcsname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname + {\starttypescript#definitions\stoptypescript}% + \gtoksapp\t_font_typescripts\expandafter + {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} + +\permanent\protected\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection + {\global\advance\c_font_typescripts_n_of_preloaded\plusone + \gdefcsname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname + {\starttypescriptcollection#definitions\stoptypescriptcollection}% + \gtoksapp\t_font_typescripts\expandafter + {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} + +\def\font_typescripts_load_file#filename% + {\setfalse\c_font_typescripts_quit + \push_macro_currenttypefile + \def\currenttypefile{#filename}% + \ifconditional\c_font_typescripts_preload + \font_typescript_process_typescript_file_and_store + \else + \font_typescript_process_typescript_file + \fi + \pop_macro_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 +% {\aliased\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 + \enforced\let\starttypescript \font_typescripts_start_store + \enforced\let\starttypescriptcollection\font_typescripts_collection_start_store + \font_typescript_process_typescript_file + \endgroup + \letcsname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts} + +\def\font_typescript_process_typescript_file + {\clf_doprocesstypescriptfile{\currenttypefile}} + +\permanent\tolerant\protected\def\usetypescriptonce[#one]#spacer[#two]#spacer[#three]% + {\ifcsname\??typescriptonce#one:#two:#three\endcsname + \writestatus\m!fonts{once (#one) (#two) (#three)}% + \else + \letcsname\??typescriptonce#one:#two:#three\endcsname\relax + \font_typescripts_use[#one][#two][#three]% + \fi} + +% \definetypescriptsynonym[lbr][cmr] + +\permanent\tolerant\protected\def\definetypescriptsynonym[#name]#spacer[#synonym]% + {\ifarguments\or\or\edefcsname\??typescriptsynonyms#name\endcsname{#synonym}\fi} + +\permanent\def\truetypescript#name% recursive 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 + +\permanent\protected\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#ignore\stoptypescript{} + +\def\font_typescripts_start_document#definitions\stoptypescript + {\toksapp\c_font_typescripts_document{\starttypescript#definitions\stoptypescript}} + +\def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed + {\let\typescriptone \m_font_typescripts_one + \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 + {\push_macro_fontclass} + +\permanent\protected\def\stoptypescript + {\pop_macro_fontclass} + +\def\font_typescripts_check#asked#target#followup[#value]% script use value next + {\donefalse + \edef\m_font_typescripts_check{#value}% + \ifempty\m_font_typescripts_check % no longer needed / met + \ifcase\typescriptmethod\or\donetrue\fi + \orelse\ifx#asked\s!all + \donetrue + \orelse\ifx\m_font_typescripts_check\s!all + \donetrue + \orelse\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 + \ifdone + \iftracetypescripts\extendtypescriptmatch\fi + \expandafter#followup% + \else + \expandafter\font_typescripts_start_gobble + \fi} + +\permanent\protected\def\extendtypescriptmatch + {\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}} + +%D Map files will go away in \LUATEX, but till that happens we use stripped down +%D support for loading them. + +\permanent\tolerant\protected\def\loadmapfile [#filename]{\clf_loadmapfile{#filename}} +\permanent\tolerant\protected\def\loadmapline [#kind]#spacer[#data]{\clf_loadmapline{#kind}{#data}} +\permanent \protected\def\forgetmapfiles {\clf_resetmapfiles} + +% \prependtoks +% \loadmapfile[mkiv-base.map]% can't we preload this one? +% \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 + +\permanent\tolerant\protected\def\definetypescriptprefix[#name]#spacer[#prefix]% + {\gdefcsname\??typescriptprefix#name\endcsname{#prefix}} % made global + +\permanent\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] + +\appendtoks + \font_helpers_reset_fontclass_math_families\fontclass +\to \everybeforedefinetypeface + +%D This hooks into the font switcher: + +\settrue\autotypescripts + +\protected\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: + +\permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]% + {\ifarguments + \expandafter\font_typefaces_define_e + \or + \expandafter\font_typefaces_define_d + \or + \expandafter\font_typefaces_define_d + \or + \expandafter\font_typefaces_define_c + \or + \expandafter\font_typefaces_define_b + \or + \expandafter\font_typefaces_define_a + \or + \expandafter\font_typefaces_define_a + \fi[#name][#style][#fontshape][#fontname][#fontsize][#settings]} + +\def\font_typefaces_define_e[#name][#style][#fontshape][#fontname][#fontsize][#settings]% + {} + +\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]% + {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi + \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 + \orelse\ifconditional\autotypescripts + \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi + \usetypescriptfile[#fontname]% + \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% + \fi + \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% + \font_typefaces_defining_stop} + +\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#discard][#discard]% + {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#discard]} + +\def\font_typefaces_define_c[#name][#style][#discard][#discard][#discard][#discard]% + {\font_typefaces_define_indeed[#name][#style]} + +\def\font_typefaces_define_d[#name][#specification][#discard][#discard][#discard][#discard]% use definitions in lfg file + {\clf_definetypeface{#name}{#specification}} + +\def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition + {\doifsomething{#name} + {\ifcsname\??typescriptdefaultstyles#name\endcsname \else + \registerfontclass{#name}% + \gdefcsname\??typescriptdefaultstyles#name\endcsname{#style}% + \fi + \ifcsname#name\endcsname \else + \protected\gdefcsname#name\endcsname{\switchtotypeface[#name][#style]}% + \fi}} + +\def\font_typefaces_defining_start#name#style#settings% + {\let\m_ts_rscale \!!plusone % as we push/pop + \let\m_ts_features \empty + \let\m_ts_fallbacks \empty + \let\m_ts_goodies \empty + \let\m_ts_direction \empty + \let\m_ts_designsize\empty + \geteparameters[m_ts_][#settings]% todo raw ... no need for key interpretation + \push_macro_fontclass + \push_macro_fontclassstyle + \setcurrentfontclass{#name}% + \savefontclassparameters{#style}\m_ts_rscale\m_ts_features\m_ts_fallbacks\m_ts_goodies\m_ts_designsize\m_ts_direction + \the\everybeforedefinetypeface} + +\permanent\def\tsvar#key#default% undocumented and unofficial + {\expandafter\ifempty\csname\??ts#key\endcsname + #default% + \else + \csname\??ts#key\endcsname + \fi} + +\def\font_typefaces_defining_stop + {\the\everyafterdefinetypeface + \pop_macro_fontclassstyle + \pop_macro_fontclass} + +\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d) + {\font_typefaces_define_indeed[#name][#style]% + \font_typefaces_defining_start{#name}{#style}{#settings}% + \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% + \font_typefaces_defining_stop} + +\permanent\tolerant\protected\def\setuptypeface[#class]#spacer[#settings]% + {\ifarguments + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\fontclass + \ifempty\fontclass + \setupbodyfont[\s!rm]% + \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname + \expandafter\setupbodyfont\expandafter[\lastnamedcs]% + \else + \setupbodyfont[\s!rm]% + \fi + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\fontclass + \setupbodyfont[#settings]% + \fi + \ifmmode\mr\else\tf\fi} % needed ? + +\permanent\tolerant\protected\def\switchtotypeface[#class]#spacer[#settings]% + {\ifarguments + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\globalfontclass + \ifempty\fontclass + \switchtobodyfont[\s!rm]% + \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname + \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% + \else + \switchtobodyfont[\s!rm]% + \fi + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\globalfontclass + \switchtobodyfont[#settings]% + \fi + \ifmmode\mr\else\tf\fi} % needed ? + +%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 + +\permanent\tolerant\protected\def\inherittypeface[#name]#spacer[#styles]#spacer[#parentclass]% + {\iftok{#styles}\emptytoks + \font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]% + \orelse\iftok{#name}{#parentclass}\else + \glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed + \def\font_typescripts_inherit_check_step#style{\edefcsname\??typescriptinheritances#name:#style\endcsname{#parentclass}}% + \processcommalist[#styles]\font_typescripts_inherit_check_step + \fi} + +\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 + +\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 % no \orelse ! + \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!ss \s!Sans \else % no \orelse ! + \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else % no \orelse ! + \s!Serif \fi\fi\fi} + +\protected\def\font_helpers_set_fontstyle_of_fontclass + {\ifempty\fontclass + \let\fontstyle\s!rm + \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname + %\edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}% + \edef\fontstyle{\lastnamedcs}% + \else + \let\fontstyle\s!rm + \fi} + +\protect \endinput diff --git a/tex/context/base/mkxl/type-lua.mkxl b/tex/context/base/mkxl/type-lua.mkxl new file mode 100644 index 000000000..fac6c3867 --- /dev/null +++ b/tex/context/base/mkxl/type-lua.mkxl @@ -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/tex/context/base/mkxl/type-set.mkxl b/tex/context/base/mkxl/type-set.mkxl new file mode 100644 index 000000000..4a22b59a5 --- /dev/null +++ b/tex/context/base/mkxl/type-set.mkxl @@ -0,0 +1,139 @@ +%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 + + % beware: these are low level calls, so not user commands ! + + \loadfoundtypescriptfile\empty{type-def.mkxl} + \loadfoundtypescriptfile\empty{type-lua.mkxl} + \loadfoundtypescriptfile\empty{type-siz.mkxl} + \loadfoundtypescriptfile\empty{type-fbk.mkxl} + \loadfoundtypescriptfile\empty{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-latin-modern.mkiv] [type-imp-latinmodern.mkiv] +\definefilesynonym [type-imp-modern-latin.mkiv] [type-imp-modernlatin.mkiv] + +\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] + +\definefilesynonym [type-imp-cows.mkiv] [type-imp-koeielettersot.mkiv] +\definefilesynonym [type-imp-sheep.mkiv] [type-imp-koeielettersot.mkiv] +\definefilesynonym [type-imp-coloredcows.mkiv] [type-imp-koeielettersot.mkiv] +\definefilesynonym [type-imp-coloredsheep.mkiv] [type-imp-koeielettersot.mkiv] +\definefilesynonym [type-imp-koeieletters.mkiv] [type-imp-koeielettersot.mkiv] + +\definefilesynonym [type-imp-stixtwo.mkiv] [type-imp-stix.mkiv] + +\definefilesynonym [type-imp-ibmplex.mkiv] [type-imp-plex.mkiv] + +\protect \endinput diff --git a/tex/context/base/mkxl/type-siz.mkxl b/tex/context/base/mkxl/type-siz.mkxl new file mode 100644 index 000000000..d4c90b182 --- /dev/null +++ b/tex/context/base/mkxl/type-siz.mkxl @@ -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/tex/context/base/mkxl/typo-bld.mkxl b/tex/context/base/mkxl/typo-bld.mkxl new file mode 100644 index 000000000..d170397fc --- /dev/null +++ b/tex/context/base/mkxl/typo-bld.mkxl @@ -0,0 +1,62 @@ +%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}{} + +\definesystemattribute[parbuilder][public] + +\installcorenamespace {parbuilder} + +\permanent\protected\def\defineparbuilder [#1]{\clf_defineparbuilder{#1}} +\permanent\protected\def\setmainparbuilder[#1]{\clf_setparbuilder{#1}} + +\permanent\protected\def\startparbuilder [#1]{\ifhmode\par\fi\clf_startparbuilder{#1}} +\permanent\protected\def\stopparbuilder {\ifhmode\par\fi\clf_stopparbuilder} + +%D There is no high level interface because after all implementing a linebreaker +%D is not something that the average user will do. + +\defineparbuilder[default] % just for testing +\defineparbuilder[oneline] % just for testing +\defineparbuilder[basic] % just for testing + +%D This hooks in otr so we need to pickup. + +\permanent\protected\def\enableparbuilders {\clf_enableparbuilder } % can be public implementor +\permanent\protected\def\disableparbuilders{\clf_disableparbuilder} % can be public implementor + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-brk.mkxl b/tex/context/base/mkxl/typo-brk.mkxl new file mode 100644 index 000000000..51abc1034 --- /dev/null +++ b/tex/context/base/mkxl/typo-brk.mkxl @@ -0,0 +1,94 @@ +%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}{} + +\definesystemattribute[breakpoint][public,global] + +% see below: \exhyphenchar \minusone % we use a different order than base tex, so we really need this + +\permanent\tolerant\protected\def\definebreakpoints[#1]% + {\clf_definebreakpoints{#1}} % todo: public implementor + +\permanent\tolerant\protected\def\definebreakpoint[#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} + +\permanent\protected\def\setbreakpoints[#1]% + {\exhyphenchar\minusone % we use a different order than base tex, so we really need this + \clf_setbreakpoints{#1}} + +\permanent\protected\def\resetbreakpoints + {\exhyphenchar\hyphenasciicode % 2020.03.05 + \c_attr_breakpoint\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=-) + +\aliased\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/tex/context/base/mkxl/typo-cap.mkxl b/tex/context/base/mkxl/typo-cap.mkxl new file mode 100644 index 000000000..587ab62ef --- /dev/null +++ b/tex/context/base/mkxl/typo-cap.mkxl @@ -0,0 +1,269 @@ +%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}{optimize} + +% \definesystemattribute[case][public] % already predefined + +%D \macros +%D {setupcapitals} +%D +%D By default we use pseudo small caps in titles. This can be 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] % 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 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 + +\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}\fontid\font} % can be public implementor + +\protected\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font} +\protected\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font} +\protected\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font} +\protected\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font} +\protected\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font} + +\pushoverloadmode + +\permanent\protected\def\WORD {\triggergroupedcommandcs\typo_capitale_WORD } +\permanent\protected\def\word {\triggergroupedcommandcs\typo_capitale_word } +\permanent\protected\def\Word {\triggergroupedcommandcs\typo_capitale_Word } +\permanent\protected\def\Words{\triggergroupedcommandcs\typo_capitale_Words} +\permanent\protected\def\camel{\triggergroupedcommandcs\typo_capitale_camel} + +\aliased\let\WORDS\WORD +\aliased\let\words\word + +\popoverloadmode + +%D \macros +%D {kap,KAP,Kap,Kaps,nokap,userealcaps,usepseudocaps} +%D +%D We already introduced \type {\cap} as way to capitalize words. This command comes +%D 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 \type {\cap}. +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D These macros show te main reason why we introduced the smaller \type {\tx} and +%D \type {\txx}. +%D +%D \starttyping +%D \cap\romannumerals{1995} +%D \stoptyping +%D +%D This at first sight unusual capitilization is completely 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 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 \type {\groupedcommand}. + +\newconditional\c_typo_capitals_pseudo + +\permanent\protected\def\usepseudocaps{\settrue \c_typo_capitals_pseudo} +\permanent\protected\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} + +\permanent\protected\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped} +\permanent\protected\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped} +\permanent\protected\def\pseudoSmallCapped{\triggergroupedcommandcs\font_style_pseudoSmallCapped} +\permanent\protected\def\pseudoMixedCapped{\triggergroupedcommandcs\font_style_pseudoMixedCapped} + +\permanent\protected\def\realsmallcapped {\triggergroupedcommandcs\font_style_realsmallcapped} +\permanent\protected\def\realSmallcapped {\triggergroupedcommandcs\font_style_realSmallcapped} +\permanent\protected\def\realSmallCapped {\triggergroupedcommandcs\font_style_realSmallCapped} + +\permanent\protected\def\notsmallcapped {\triggergroupedcommandcs\font_style_notsmallcapped} + +\protected\def\font_style_pseudosmallcapped{\typo_capitals_set_fake\v!WORD } % all upper +\protected\def\font_style_pseudoSmallcapped{\typo_capitals_set_fake\v!capital} % one upper + font +\protected\def\font_style_pseudoSmallCapped{\typo_capitals_set_fake\v!Capital} % some upper + font +\protected\def\font_style_pseudoMixedCapped{\typo_capitals_set_fake\v!mixed } + +\protected\def\font_style_realsmallcapped {\typo_capitals_set_real\v!WORD } % all lower +\protected\def\font_style_realSmallcapped {\typo_capitals_set_real\v!Word } % one upper + font +\protected\def\font_style_realSmallCapped {\typo_capitals_set_real\v!Words } % some upper + +\protected\def\font_style_notsmallcapped {\typo_capitals_set_fake\v!word } + +\protected\def\typo_capitals_smallcaps + {\ifconditional\c_typo_capitals_pseudo + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\protected\def\smallcapped{\typo_capitals_smallcaps\pseudosmallcapped\realsmallcapped} +\permanent\protected\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped} +\permanent\protected\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped} + +\permanent\protected\def\font_style_smallcapped{\typo_capitals_smallcaps\font_style_pseudosmallcapped\font_style_realsmallcapped} +\permanent\protected\def\font_style_Smallcapped{\typo_capitals_smallcaps\font_style_pseudoSmallcapped\font_style_realSmallcapped} +\permanent\protected\def\font_style_SmallCapped{\typo_capitals_smallcaps\font_style_pseudoSmallCapped\font_style_realSmallCapped} + +\permanent\protected\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi} + +\prependtoks + \enforced\let\normalcap\cap % mathmode cap +\to \everydump + +\appendtoks + \enforced\let\cap\autocap +\to \everydump + +\aliased\let\kap\cap % for old times sake +\aliased\let\Caps\SmallCapped % for old times sake + +\aliased\let\mixedcaps\pseudoMixedCapped + +\aliased\let\normalsmallcapped\smallcapped +\aliased\let\normalWORD \WORD +\aliased\let\normalword \word + +\aliased\let\font_style_normalsmallcapped\font_style_smallcapped +\aliased\let\font_style_normalWORD \WORD +\aliased\let\font_style_normalword \word + +\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 + +\aliased\let\uppercased\normalWORD +\aliased\let\lowercased\normalword + +\setupcapitals + [\c!title=\v!yes, + \c!style=\tx, + \s!sc=\v!no] % no \c!sc any longer + +\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=] + +% \protected\def\randomizetext{\groupedcommand{\c_attr_case\pluseight}{}} + +\permanent\protected\def\randomizetext{\triggergroupedcommand{\c_attr_case\pluseight}} + +\definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=] + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-chr.mkxl b/tex/context/base/mkxl/typo-chr.mkxl new file mode 100644 index 000000000..c4fbeba17 --- /dev/null +++ b/tex/context/base/mkxl/typo-chr.mkxl @@ -0,0 +1,87 @@ +%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}{} + +\definesystemattribute[marked][public] + +\permanent\protected\def\removepunctuation{\clf_pickuppunctuation action{remove}\relax} +\permanent\protected\def\pushpunctuation {\clf_pickuppunctuation action{push}\relax} +\permanent\protected\def\poppunctuation {\clf_pickuppunctuation action{pop}\relax} + +\permanent\tolerant\protected\def\markcontent[#1]#:#2% + {\dontleavehmode + \bgroup + \clf_markcontent{#1}% + \bgroup + #2% double grouping makes aftergroups work ok + \egroup + \egroup} + +\permanent\tolerant\protected\def\startmarkedcontent[#1]% + {\dontleavehmode + \bgroup + \clf_markcontent{#1}% + % double grouping makes aftergroups work ok + \bgroup} + +\permanent\protected\def\stopmarkedcontent + {\egroup + \egroup} + +\permanent\tolerant\protected\def\removemarkedcontent[#1]% + {\clf_pickupmarkedcontent action{remove}mark{#1}\relax} + +\permanent\protected\def\doifelsemarkedcontent#1% + {\clf_doifelsemarkedcontent{#1}} + +%D A few helpers (put here for convenience): +%D +%D \starttyping +%D test test\doifelselastnode{boundary}{word}{YES}{NOP}test +%D test test\wordboundary \doifelselastnode{boundary}{word}{YES}{NOP}test +%D test test\wordboundary \doifelseatwordboundary{YES}{NOP}test +%D test test \lastnodeidstring test +%D test test\lastnodeidstring test +%D test test\number\lastnodeid test +%D \stoptyping + +\newcount\c_syst_last_node_id + +\permanent\protected\def\doifelselastnode {\clf_lastnodeequals} % can be public implementors +\permanent\protected\def\doifelseatwordboundary{\clf_atwordboundary} % can be public implementors +\permanent\protected\def\lastnodeid {\clf_lastnodeid\c_syst_last_node_id} % can be public implementors + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-cln.mkxl b/tex/context/base/mkxl/typo-cln.mkxl new file mode 100644 index 000000000..84fc1d235 --- /dev/null +++ b/tex/context/base/mkxl/typo-cln.mkxl @@ -0,0 +1,32 @@ +%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}{} + +\definesystemattribute[cleaner][public] + +%D Currently there is no interface. +%D +%D 1: Autocap first character of a line + +\permanent\protected\def\setcharactercleaning[#1]{\clf_setcharactercleaning{#1}} % also accepts reset, todo: public implementor + +% \appendtoks +% \c_attr_cleaner\attributeunsetvalue +% \to \everyforgetall + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-del.mkxl b/tex/context/base/mkxl/typo-del.mkxl new file mode 100644 index 000000000..ab25f72d8 --- /dev/null +++ b/tex/context/base/mkxl/typo-del.mkxl @@ -0,0 +1,922 @@ +%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) + +\permanent\permanent\protected\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] + +\permanent\protected\def\normalhyphen + {\hbox{\directsymbol\empty\c!hyphen}} + +\permanent\protected\def\composedhyphen + {\hbox{\directsymbol\empty\c!compoundhyphen}} + +\permanent\protected\def\normalhyphendiscretionary + {\discretionary + {\hbox{\directsymbol\empty\c!righthyphen}} + {\hbox{\directsymbol\empty\c!lefthyphen}} + {\hbox{\directsymbol\empty\c!hyphen}}} + +\permanent\protected\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 + +% old: skip symbol skip +% new: bound skip symbol skip bound + +\permanent\protected\def\midboundarycharacter#1#2% + {\ifcase\boundarycharactermode + \or + \removeunwantedspaces + \wordboundary + \hskip\hspaceamount\currentusedlanguage{#2}% + \usedlanguageparameter#1% + \hskip\hspaceamount\currentusedlanguage{#2}% + \wordboundary + \ignorespaces + \or + \usedlanguageparameter#1% + \fi + \boundarycharactermode\plusone} + +% old: symbol nobreak skip +% new: symbol nobreak skip wordboundary + +\permanent\protected\def\leftboundarycharacter#1#2% + {\ifcase\boundarycharactermode + \or + \usedlanguageparameter#1% + \nobreak + \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern + \wordboundary + \or + \usedlanguageparameter#1% + \fi + \boundarycharactermode\plusone} + +% old: preword skip symbol +% new: bound nobreak skip symbol + +\permanent\protected\def\rightboundarycharacter#1#2% + {\ifcase\boundarycharactermode + \or + \wordboundary + \nobreak + \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern + \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} + +\newconditional\c_typo_subsentence_cleanup \settrue\c_typo_subsentence_cleanup + +\def\typo_subsentence_cleanup_start + {\ifconditional\c_typo_subsentence_cleanup + \expandafter\ignorespaces + \fi} + +\def\typo_subsentence_cleanup_stop + {\ifconditional\c_typo_subsentence_cleanup + \removeunwantedspaces + \fi} + +\permanent\protected\def\midsentence + {\dostarttagged\t!subsentencesymbol\empty + \dotagsetsubsentencesymbol\s!middle + \symbol[\c!midsentence]% + \dostoptagged} + +\permanent\protected\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 + \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 + \typo_subsentence_cleanup_start} + +\permanent\protected\def\endofsubsentence % relax prevents space gobbling + {\typo_subsentence_cleanup_stop + \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} + +\permanent\protected\def\beginofsubsentencespacing % relax prevents space gobbling + {\kern\d_typo_subsentence_signal\relax}% \ignorespaces} + +\permanent\protected\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 + +\permanent\protected\def\startsubsentence{\beginofsubsentence\wordboundary\beginofsubsentencespacing\wordboundary\typo_subsentence_cleanup_start} +\permanent\protected\def\stopsubsentence {\typo_subsentence_cleanup_stop\wordboundary\endofsubsentencespacing\wordboundary\endofsubsentence} +\permanent\protected\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence} +\permanent\protected\def\midsubsentence {\typo_subsentence_cleanup_start\wordboundary\midsentence\wordboundary\typo_subsentence_cleanup_stop} + +\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 + \enforced\permanent\def\quotation#1{"#1"}% + \enforced\permanent\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 + +\installglobalmacrostack\currentdelimitedtext + +\let\delimitedtextlevel\!!zerocount + +\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname} + +% the \setlanguageparameter macro sets but we are ungrouped .. only used here +% +% \currentusedlanguage +% \usedlanguageparameter + +%D The optional argument can be a language, a narrower spec, or a outer:inner language +%D specification. +%D +%D \starttabulate +%D \NC [en] \NC {\tttf en} \quotation[en] {{\tttf } something french} \NC \NR +%D \NC [fr] \NC {\tttf en} \quotation[fr] {{\tttf } something french} \NC \NR +%D \NC [fr:] \NC {\tttf fr} \quotation[fr:] {{\tttf } something french} \NC \NR +%D \NC [:fr] \NC {\tttf en} \quotation[:fr] {{\tttf } something french} \NC \NR +%D \NC [fr:fr] \NC {\tttf fr} \quotation[fr:fr]{{\tttf } something french} \NC \NR +%D \NC [en:fr] \NC {\tttf en} \quotation[en:fr]{{\tttf } something french} \NC \NR +%D \NC [fr:en] \NC {\tttf fr} \quotation[fr:en]{{\tttf } something french} \NC \NR +%D \stoptabulate + +\let\currentdelimitedlanguage\empty + +\installglobalmacrostack\currentdelimitedlanguage + +\def\typo_delimited_set_language_nop + {\setusedlanguage{\delimitedtextparameter\c!language}} + +\def\typo_delimited_set_language_yes + {\doiflanguageelse\m_delimited_argument + \typo_delimited_set_language_yes_a + {\doifelseinstring:\m_delimited_argument + \typo_delimited_set_language_yes_b + \typo_delimited_set_language_nop}} + +\def\typo_delimited_set_language_yes_b + {\splitatcolon\m_delimited_argument\outerdelimitedlanguage\innerdelimitedlanguage + \ifempty\outerdelimitedlanguage + \typo_delimited_set_language_nop + \else + \doiflanguageelse\outerdelimitedlanguage + {\setusedlanguage\outerdelimitedlanguage}% + \typo_delimited_set_language_nop + \fi + \ifempty\innerdelimitedlanguage\else + \doiflanguageelse\innerdelimitedlanguage + {\let\currentdelimitedlanguage\innerdelimitedlanguage}% + \donothing + \fi + \let\m_delimited_argument\empty} + +\def\typo_delimited_set_language_yes_a + {\let\currentdelimitedlanguage\m_delimited_argument + \let\m_delimited_argument\empty} + +\def\typo_delimited_push#1#2% + {\push_macro_currentdelimitedtext % can we combine these two + \push_macro_currentdelimitedlanguage % the language used for hyphenation + \edef\currentdelimitedtext{#1}% + \edef\m_delimited_argument{#2}% + \ifempty\m_delimited_argument + \typo_delimited_set_language_nop + \else + \typo_delimited_set_language_yes + \fi + \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 + \pop_macro_currentdelimitedlanguage + \pop_macro_currentdelimitedtext} + +\installcorenamespace{delimitedtext} +\installcorenamespace{delimitedtextlevel} + +\installcommandhandler \??delimitedtext {delimitedtext} \??delimitedtext + +\appendtoks + \expandafter\newcount\csname\??delimitedtextlevel\currentdelimitedtext\endcsname + \frozen\instance\setuevalue{\currentdelimitedtext }{\delimitedtext[\currentdelimitedtext]}% + \frozen\instance\setuevalue{\e!start\currentdelimitedtext}{\startdelimitedtext[\currentdelimitedtext]}% + \frozen\instance\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!language=\v!local, + \c!repeat=\v!no] + +\def\typo_delimited_repeat_indeed + {\relax\ifcase\delimitedtextlevel\else + \typo_delimited_handle_middle\c!middle + \fi} + +\let\typo_delimited_repeat\relax + +\permanent\tolerant\protected\def\startdelimitedtext[#1]#*[#2]% + {\begingroup + \typo_delimited_push{#1}{#2}% + \dostarttaggedchained\t!delimitedblock\currentdelimitedtext\??delimitedtext + \edef\p_delimited_method{\delimitedtextparameter\c!method}% + \ifx\p_delimited_method\v!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} + +\newconditional\c_typo_delimited_repeating + +\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 + \setfalse\c_typo_delimited_repeating + \edef\p_delimited_location{\delimitedtextparameter\c!location}% + \ifx\p_delimited_location\v!paragraph + \expandafter\typo_delimited_start_par + \orelse\ifx\p_delimited_location\v!margin + \expandafter\typo_delimited_start_par + \else + \expandafter\typo_delimited_start_txt + \fi} + +\def\typo_delimitedtexts_finish_font + {\removeunwantedspaces % again ? + \dostarttagged\t!delimitedsymbol\empty + \dotagsetdelimitedsymbol\s!right + \delimitedtextparameter\c!right + \dostoptagged} + +\def\typo_delimited_show_language_indeed#1#2% + {\begingroup + \infofont + \setbox\scratchbox\hpack{\lower\strutht\hbox to \zeropoint{\darkred#1\currentlanguage:\currentdelimitedlanguage#2}}% + \vsmashbox\scratchbox + \box\scratchbox + \endgroup} + +\let\typo_delimited_show_language\gobbletwoarguments + +\installtextracker{delimited.language} + {\let\typo_delimited_show_language\typo_delimited_show_language_indeed} + {\let\typo_delimited_show_language\gobbletwoarguments} + +\def\typo_delimited_start_content + {\dostarttagged\t!delimitedcontent\empty + \begingroup + \douselanguageparameter\currentdelimitedlanguage + \typo_delimited_show_language<\hss + \ignorespaces} + +\def\typo_delimited_stop_content + {\removeunwantedspaces + \removelastskip % redundant + \typo_delimited_show_language\hss<% + \endgroup + \dostoptagged} + +\tolerant\def\typo_delimited_start_par[#1]% + {\let\typo_delimited_stop\typo_delimited_stop_par + \edef\p_delimited_spacebefore{\delimitedtextparameter\c!spacebefore}% + \ifempty\p_delimited_spacebefore \else + \blank[\p_delimited_spacebefore]% + \fi + \delimitedtextparameter\c!before + \edef\m_delimited_argument{#1}% + \ifempty\m_delimited_argument + \let\m_delimited_argument\m_delimited_argument + \fi + \ifempty\m_delimited_argument + \endgraf + \doadaptleftskip {\delimitedtextparameter\c!leftmargin}% + \doadaptrightskip{\delimitedtextparameter\c!rightmargin}% + \let\typo_delimited_stop_par_indeed\endgraf + \else % backward compatible direct directive + \startnarrower[\m_delimited_argument]% + \let\typo_delimited_stop_par_indeed\stopnarrower + \fi + % so far + \push_macro_checkindentation + \useindentingparameter\delimitedtextparameter + % + \begingroup + \usedelimitedtextstyleandcolor\c!style\c!color + % + \begingroup + \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 + % + \typo_delimited_start_content} + +\let\typo_delimited_stop_par_indeed\endgraf + +\def\typo_delimited_stop_par + {\typo_delimited_stop_content + \rightdelimitedtextmark + \rightdelimitedtextmark + \carryoverpar\endgroup + \endgraf + \endgroup + \pop_macro_checkindentation + \typo_delimited_stop_par_indeed + \delimitedtextparameter\c!after + \edef\p_delimited_spaceafter{\delimitedtextparameter\c!spaceafter}% + \ifempty\p_delimited_spaceafter \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 + \typo_delimited_start_content} + +\def\typo_delimited_stop_txt + {\typo_delimited_stop_content + \typo_delimited_handle_right\c!right + \endgroup} + +\permanent\protected\def\stopdelimitedtext + {\typo_delimited_stop + \dostoptagged + \typo_delimited_pop + \endgroup} + +\permanent\tolerant\protected\def\delimitedtext[#1]#*[#2]% + {\dontleavehmode % following ones can be omited + \typo_delimited_push{#1}{#2}% + \edef\p_delimited_method{\delimitedtextparameter\c!method}% + \ifx\p_delimited_method\v!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 + \expandafter\typo_delimited_par + \orelse\ifx\p_delimited_location\v!margin + \expandafter\typo_delimited_par + \else + \expandafter\typo_delimited_txt + \fi} + +% shortcuts + +\permanent\protected\def\startdelimited{\startdelimitedtext} +\permanent\protected\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned +\permanent \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 + +\permanent\protected\def\setnextleftdelimitedtextmark + {\ifempty\p_delimited_nextleft + % nothing + \orelse\ifx\p_delimited_nextleft\v!left + \typo_delimited_nextleft_symbol\p_delimited_left + \orelse\ifx\p_delimited_nextleft\v!right + \typo_delimited_nextleft_symbol\p_delimited_right + \else + \typo_delimited_nextleft_symbol\p_delimited_nextleft + \fi} + +\permanent\protected\def\setnextrightdelimitedtextmark + {\ifempty\p_delimited_nextright + % nothing + \orelse\ifx\p_delimited_nextright\v!right + \typo_delimited_nextright_symbol\p_delimited_right + \orelse\ifx\p_delimited_nextright\v!left + \typo_delimited_nextright_symbol\p_delimited_left + \else + \typo_delimited_nextright_symbol\p_delimited_nextright + \fi} + +\permanent\protected\def\leftdelimitedtextmark + {\ifempty\p_delimited_left + % nothing + \else + \typo_delimited_left_symbol\p_delimited_left + \fi} + +\permanent\protected\def\rightdelimitedtextmark + {\ifempty\p_delimited_right + % 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% + {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed + \localleftbox\bgroup + \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter + \boundarycharactermode\plusone + \typo_delimited_left_symbol#1% + \egroup} + +\def\typo_delimited_nextright_symbol#1% + {\let\typo_delimited_reset_next_symbol\typo_delimited_reset_next_symbol_indeed + \localrightbox\bgroup + \enforced\swapmacros\leftboundarycharacter\rightboundarycharacter + \boundarycharactermode\plusone + \typo_delimited_right_symbol#1% + \egroup} + +\protected\def\typo_delimited_reset_next_symbol_indeed + {\localleftbox {}% + \localrightbox{}}% + +\let\typo_delimited_reset_next_symbol\relax + +\appendtoks + \typo_delimited_reset_next_symbol +\to \everyforgetall + +% \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 + +% We have no real test case for this and it's broken already for a while, +% even in \MKII. Maybe we should to this in \LUA. Only Italian has the +% middlespeech parameter set. + +\def\typo_delimited_handle_middle#1% special case + {\ifconditional\c_typo_delimited_repeating + \begingroup + \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor + \setbox\scratchbox\hbox{\delimitedtextparameter#1}% + \ifdim\wd\scratchbox>\zeropoint + \ifdim\lastkern=\d_typo_delimited_signal + \unkern + \hskip\hspaceamount\currentusedlanguage{interquotation}% + \else % maybe an option: + %\edef\p_delimited_margin{\delimitedtextparameter\c!location}% + %\ifx\p_delimited_margin\v!margin + % \hskip-\wd\scratchbox + %\fi + \fi + \strut % new, needed below + \dostarttagged\t!delimitedsymbol\empty + \dotagsetdelimitedsymbol\s!middle + \delimitedtextparameter#1% unhbox\scratchbox + \dostoptagged + % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods + \kern\d_typo_delimited_signal % +- \prewordbreak + \fi + \endgroup + \else + \settrue\c_typo_delimited_repeating + \fi} + +\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}% + \orelse\ifdim\lastskip=\d_typo_delimited_signal + \unskip + \hskip\hspaceamount\currentusedlanguage{interquotation}% + \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}% + \orelse\ifdim\lastskip=\d_typo_delimited_signal + \unskip + \penalty\plustenthousand + \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!right + \delimitedtextparameter#1% unhbox\scratchbox + \dostoptagged + \kern\d_typo_delimited_signal % +- \prewordbreak + \fi + \endgroup} + +\protected\def\typo_delimited_par + {\groupedcommand + {\dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext % block? + \usedelimitedtextstyleandcolor\c!style\c!color + \typo_delimited_handle_left\c!left + \typo_delimited_start_content} + {\typo_delimited_stop_content + \typo_delimited_handle_right\c!right + \removelastskip % hm + \dostoptagged + \typo_delimited_pop}} + +\protected\def\typo_delimited_txt + {\edef\p_left_right{\delimitedtextparameter\c!left\delimitedtextparameter\c!right}% + \ifempty\p_left_right + \expandafter\typo_delimited_attributed + \else + \expandafter\typo_delimited_quoted + \fi} + +\def\typo_delimited_quoted + {\dontleavehmode + \begingroup + \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext + \typo_delimited_handle_left\c!left + \usedelimitedtextstyleandcolor\c!style\c!color + \typo_delimited_start_content + \bgroup + \aftergroup\typo_delimited_quoted_e + \let\next=} + +\def\typo_delimited_quoted_e + {\typo_delimited_stop_content + \typo_delimited_handle_right\c!right + \removelastskip % ? + \dostoptagged + \typo_delimited_pop + \endgroup} + +\def\typo_delimited_attributed + {\dontleavehmode + \begingroup + \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext + \usedelimitedtextstyleandcolor\c!style\c!color + \typo_delimited_start_content + \bgroup + \aftergroup\typo_delimited_attributed_e + \let\next=} + +\def\typo_delimited_attributed_e + {\typo_delimited_stop_content + \dostoptagged + \typo_delimited_pop + \endgroup} + +\def\typo_delimited_fontdriven + {\dontleavehmode + \begingroup + \dostarttaggedchained\t!delimited\currentdelimitedtext\??delimitedtext + \usedlanguageparameter{\c!left\currentparentdelimitedtext}% was: \currentdelimitedtext + \usedelimitedtextstyleandcolor\c!style\c!color + \typo_delimited_start_content + \bgroup + \aftergroup\typo_delimited_fontdriven_e + \let\next=} + +\def\typo_delimited_fontdriven_e + {\typo_delimited_stop_content + \usedlanguageparameter{\c!right\currentparentdelimitedtext}% was: \currentdelimitedtext + \dostoptagged + \typo_delimited_pop + \endgroup} + +% 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] + +\permanent\protected\def\setupquotation{\setupdelimitedtext[\v!quotation]} +\permanent\protected\def\setupquote {\setupdelimitedtext[\v!quote]} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-dig.mkxl b/tex/context/base/mkxl/typo-dig.mkxl new file mode 100644 index 000000000..822fa0d34 --- /dev/null +++ b/tex/context/base/mkxl/typo-dig.mkxl @@ -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}{} + +\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 + +\permanent\protected\def\setdigitsmanipulation[#1]% can be public implementor + {\clf_setdigitsmanipulation{#1}} + +\permanent\protected\def\resetdigitsmanipulation + {\c_attr_digits\attributeunsetvalue} + +\appendtoks + \resetdigitsmanipulation +\to \everyresettypesetting + +\permanent\protected\def\equaldigits{\groupedcommand{\setdigitsmanipulation[\number\plusone]}{}} +\permanent\protected\def\dummydigit {\hphantom {\setdigitsmanipulation[\number\plusone]0}} + +\appendtoks + \resetdigitsmanipulation +\to \everyinitializeverbatim + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-dir.mkxl b/tex/context/base/mkxl/typo-dir.mkxl new file mode 100644 index 000000000..a8ba1fc70 --- /dev/null +++ b/tex/context/base/mkxl/typo-dir.mkxl @@ -0,0 +1,202 @@ +%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}{optimize} +\registerctxluafile{typo-dha}{} +%registerctxluafile{typo-dua}{} +%registerctxluafile{typo-dub}{} +\registerctxluafile{typo-duc}{} + +\definesystemattribute[directions][public,pickup] + +\installcorenamespace{directions} +\installcorenamespace{directionsbidimode} + +% plural as we can have a combination but maybe better singular + +\installsimplecommandhandler \??directions {directions} \??directions % no \define... yet + +\immutable\edef\lefttorightmark{\normalUchar"200E} \aliased\let\lrm\lefttorightmark % expandable +\immutable\edef\righttoleftmark{\normalUchar"200F} \aliased\let\rlm\righttoleftmark % expandable + +\permanent\protected\def\setdirection[#1]% todo: symbolic names + {\clf_setdirection#1\relax} + +\permanent\protected\def\resetdirection + {\c_attr_directions\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}% + }% + \gletcsname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode} + +\appendtoks + \edef\p_bidi{\directionsparameter\c!bidi}% + \edef\currentbidistamp + {\p_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 + \ifx\p_bidi\v!global + \pickupdirectionsattribute + \else + \forgetdirectionsattribute + \fi +\to \everysetupdirections + +\appendtoks + \edef\p_option{\directionsparameter\c!break}% name can change + \bitwiseflip\normalizelinemode\ifx\p_option\v!both\else-\fi\breakafterdircode +\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!break=\v!both, % experimental value, maybe \v!no will be default (bad name too) + \c!fences=\v!yes] + +\permanent\protected\edef\bidilre{\normalUchar"202A} +\permanent\protected\edef\bidirle{\normalUchar"202B} +\permanent\protected\edef\bidipop{\normalUchar"202C} +\permanent\protected\edef\bidilro{\normalUchar"202D} +\permanent\protected\edef\bidirlo{\normalUchar"202E} + +\permanent\protected\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi} +\permanent\protected\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi} +\permanent\protected\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi} +\permanent\protected\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi} + +% for the moment: \setdirection[\plusone] + +\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 +% +% \protected\def\biditest#1#2#3% font text raw +% {\dontleavehmode\hbox +% {\framed[offset=overlay]{\tttf#2}\quad +% \enabletrackers[typesetters.directions]% +% \framed[offset=overlay]{#1#3}\quad +% \disabletrackers[typesetters.directions]% +% \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}} +% +% \startbuffer[bidi-sample] +% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{LATIN ARAB}{\lefttoright{\bidilro \LATIN\ \ARAB}}\par % right -> left +% \biditest\Arabic{LATIN ARAB}{\righttoleft{\bidilro \LATIN\ \ARAB}}\par % right -> left +% \biditest\Arabic{BARA NITAL}{\lefttoright{\bidirlo \LATIN\ \ARAB}}\par % left -> right +% \biditest\Arabic{BARA NITAL}{\righttoleft{\bidirlo \LATIN\ \ARAB}}\par % left -> right +% \stopbuffer +% +% \startbuffer[bidi-sample] +% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{LATIN ARAB}{\lefttoright\bidilro \LATIN\ \ARAB}\par % right -> left +% \biditest\Arabic{LATIN ARAB}{\righttoleft\bidilro \LATIN\ \ARAB}\par % right -> left +% \biditest\Arabic{BARA NITAL}{\lefttoright\bidirlo \LATIN\ \ARAB}\par % left -> right +% \biditest\Arabic{BARA NITAL}{\righttoleft\bidirlo \LATIN\ \ARAB}\par % left -> right +% \stopbuffer +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=off] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=global] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=local] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-sample] +% \setupdirections[bidi=global] +% +% \hbox{\righttoleft\arabicfont (0001)}\par +% \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par +% {\righttoleft\arabicfont (0003)\par} +% {\righttoleft\arabicfont (0004)}\par +% \dontleavehmode{\righttoleft\arabicfont (0005)\par} +% \dontleavehmode{\righttoleft\arabicfont (0006)}\par +% \rtlhbox{\arabicfont (0007)}\par +% \ltrhbox{\arabicfont (0008)}\par +% \dontleavehmode\rtlhbox{\arabicfont (0009)}\par +% \dontleavehmode\ltrhbox{\arabicfont (0010)}\par +% \stopsetups +% +% {\typebuffer[bidi-sample] \getbuffer[bidi-sample]} +% +% \stoptext diff --git a/tex/context/base/mkxl/typo-drp.mkxl b/tex/context/base/mkxl/typo-drp.mkxl new file mode 100644 index 000000000..9a6ae7603 --- /dev/null +++ b/tex/context/base/mkxl/typo-drp.mkxl @@ -0,0 +1,129 @@ +%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}{} + +\definesystemattribute[initial][public] + +\appendtoks + \c_attr_initial\attributeunsetvalue +\to \everyforgetall + +%D For the moment here: dropped caps redone. In addition to the parameters shown in +%D the example you can use the \type {style} and more low level \type {font} keys to +%D set up the font where the first one wins. If you don't like the behaviour you can +%D always 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, + % \c!font=Bold sa 4, + % \c!font=Bold ht \measure{initial:n}, + \c!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] + +\permanent\tolerant\protected\def\placeinitial[#1]% old command + {\par + \namedinitialparameter{#1}\c!before + \edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{}}} + +\permanent\tolerant\protected\def\setinitial[#1]#*[#2]% + {\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{#2}}} + +\protected\def\typo_initial_handle_indeed#1#2% + {\dontleavehmode + \begingroup + \edef\currentinitial{#1}% + \setupcurrentinitial[#2]% + \resetfontfeature % might be needed in more places + \doifelsenothing{\initialparameter\c!style} + {\definedfont[\initialparameter\c!font]} + {\useinitialstyleparameter\c!style}% + \useinitialcolorparameter\c!color + \edef\p_voffset{\initialparameter\c!voffset}% + \scratchcounter \initialparameter\c!n\relax + \scratchvoffset\dimexpr\ifx\p_voffset\v!line\scratchcounter\lineheight-\lineheight\else\p_voffset\fi\relax + \clf_setinitial + location {\initialparameter\c!location}% + enabled true\space + n \scratchcounter + m \numexpr\initialparameter\c!m\relax + method {\initialparameter\c!method}% + distance \dimexpr\initialparameter\c!distance\relax + hoffset \dimexpr\initialparameter\c!hoffset\relax + voffset \scratchvoffset + ma \c_attr_colormodel + ca \c_attr_color + ta \c_attr_transparency + font \fontid\font + dynamic \font_dynamic_value % it's a bit over the top to support this here + \relax + \c_attr_initial\plusone + \initialparameter\c!text + \endgroup + \glet\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/tex/context/base/mkxl/typo-fkr.mkxl b/tex/context/base/mkxl/typo-fkr.mkxl new file mode 100644 index 000000000..f56294dc0 --- /dev/null +++ b/tex/context/base/mkxl/typo-fkr.mkxl @@ -0,0 +1,38 @@ +%D \module +%D [ file=typo-fkr, +%D version=2016.10.10, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Additional Font Kerning, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Additional Font Kerning} + +\registerctxluafile{typo-fkr}{} + +\definesystemattribute[extrafontkern][public] + +\unprotect + +% none : not across fonts (but still within) +% min : min value across fonts +% max : max value across fonts +% mixed : mean value across fonts +% reset : disable + +\permanent\protected\def\setextrafontkerns[#1]% % can be public implementor + {\clf_setextrafontkerns{#1}} + +\permanent\protected\def\resetextrafontkerns + {\c_attr_extrafontkern\attributeunsetvalue} + +\appendtoks + \resetextrafontkerns +\to \everyresettypesetting + +\protect diff --git a/tex/context/base/mkxl/typo-fln.mkxl b/tex/context/base/mkxl/typo-fln.mkxl new file mode 100644 index 000000000..2696dd06b --- /dev/null +++ b/tex/context/base/mkxl/typo-fln.mkxl @@ -0,0 +1,109 @@ +%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}{} + +\definesystemattribute[firstline][public] + +\appendtoks + \c_attr_firstline\attributeunsetvalue +\to \everyforgetall + +\installcorenamespace {firstline} + +\installcommandhandler \??firstline {firstline} \??firstline + +\setupfirstline + [\c!alternative=\v!line, + %\c!style=, + %\c!color=, + \c!n=1] + +\permanent\tolerant\protected\def\setfirstline[#1]% + {\edef\typo_firstline_handle{\typo_firstline_handle_indeed{#1}}} + +\protected\def\typo_firstline_handle_indeed#1% + {\dontleavehmode + \begingroup + \edef\currentfirstline{#1}% + \usefirstlinestyleandcolor\c!style\c!color + \clf_setfirstline + alternative {\firstlineparameter\c!alternative}% + ma \c_attr_colormodel + ca \c_attr_color + ta \c_attr_transparency + n \numexpr\firstlineparameter\c!n\relax + font \fontid\font + dynamic \font_dynamic_value + \relax +% \kern\zeropoint % we need a node +% \hskip\zeropoint\s!plus\emwidth\relax % can be an option + \endgroup + \glet\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] + +\permanent\protected\def\applytofirstcharacter#1% + {\begingroup + \dowithnextbox + {\clf_applytofirstcharacter\nextbox{\csstring#1}% + \unhbox\nextbox + \endgroup}% + \hbox} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-ini.mkxl b/tex/context/base/mkxl/typo-ini.mkxl new file mode 100644 index 000000000..3e0790af0 --- /dev/null +++ b/tex/context/base/mkxl/typo-ini.mkxl @@ -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}{} + +\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/tex/context/base/mkxl/typo-inj.mkxl b/tex/context/base/mkxl/typo-inj.mkxl new file mode 100644 index 000000000..7bd01aac0 --- /dev/null +++ b/tex/context/base/mkxl/typo-inj.mkxl @@ -0,0 +1,75 @@ +%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}{} + +% 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 + +\permanent \protected\def\resetinjector [#1]{\clf_resetinjector{#1}} +\permanent \protected\def\markinjector [#1]{\dontleavehmode\clf_markinjector{#1}} +\permanent\tolerant\protected\def\checkinjector [#1]#*[#2]{\clf_checkinjector{#1}{#2}} +\permanent \protected\def\checknextinjector [#1]{\clf_checkinjector{#1}{\v!next}} +\permanent \protected\def\checkpreviousinjector [#1]{\clf_checkinjector{#1}{\v!previous}} +%permanent \protected\def\checknextinjector [#1]{\clf_checknextinjector{#1}} +%permanent \protected\def\checkpreviousinjector [#1]{\clf_checkpreviousinjector{#1}} +\permanent\tolerant\protected\def\setinjector [#1]#*[#2]#*[#3]{\clf_setinjector{#1}{#2}{#3}} +\permanent\tolerant\protected\def\showinjector [#1]{\clf_showinjector{#1}} + +\permanent\protected\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 + +\permanent\protected\def\doinstallinjector#1% + {\letvalue{typo_injectors_mark_#1}\donothing + \letvalue{typo_injectors_check_#1}\donothing} + +\permanent\protected\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}}} + +\permanent\protected\def\dotestinjector#1% only for testing outside unprotect + {\begincsname typo_injectors_check_#1\endcsname + \begincsname typo_injectors_mark_#1\endcsname} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-itc.mklx b/tex/context/base/mkxl/typo-itc.mklx new file mode 100644 index 000000000..f979261c8 --- /dev/null +++ b/tex/context/base/mkxl/typo-itc.mklx @@ -0,0 +1,60 @@ +%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}{} + +\definesystemattribute[italics] [public] +\definesystemattribute[mathitalics][public] + +% \let\/=/ +% \let\emphasiscorrection\donothing + +\ifdefined \normalitaliccorrection \else + \aliased\let\normalitaliccorrection\italiccorrection +\fi + +\permanent\protected\def\italiccorrection + {\ifnum\c_attr_italics<\plusone\normalitaliccorrection\fi} + +\pushoverloadmode + \aliased\let\/\italiccorrection +\popoverloadmode + +% 1 = end of word +% 2 = end of word and end of a list + +\permanent\protected\def\setitaliccorrection [#code]{\clf_setitaliccorrection#code\relax} % todo: public implementor +\permanent\protected\def\resetitaliccorrection {\clf_resetitaliccorrection} % todo: public implementor +\permanent\protected\def\setupitaliccorrection[#settings]{\clf_setupitaliccorrection{#settings}} % todo: public implementor + +% global : no attributes, just always (faster and less memory) +% text : only text +% always : text and boxes +% none : - + +\appendtoks + \c_attr_italics\attributeunsetvalue +\to \everymathematics + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-itm.mkxl b/tex/context/base/mkxl/typo-itm.mkxl new file mode 100644 index 000000000..3a2e2ce17 --- /dev/null +++ b/tex/context/base/mkxl/typo-itm.mkxl @@ -0,0 +1,270 @@ +%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] + +\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 + +\permanent\tolerant\protected\def\items[#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}% + \ifempty\p_typo_items_textwidth + \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}% + \ifempty\p_typo_items_width + \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}% + \ifempty\p_typo_items_distance + \d_typo_items_distance\zeropoint + \else + \d_typo_items_distance\p_typo_items_distance\relax + \fi + % + \edef\p_typo_items_symbol{\itemsparameter\c!symbol}% + \ifempty\p_typo_items_symbol + \let\m_typo_items_symbol\firstofoneargument + \orelse\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 + % + \edef\p_typo_items_align{\itemsparameter\c!align}% + \edef\p_typo_items_textalign{\itemsparameter\c!textalign}% + % + \edef\p_typo_items_n{\itemsparameter\c!n}% + \ifempty\p_typo_items_n + \getcommalistsize[#2]% + \c_typo_items_n\commalistsize\relax % \commalistcounter + \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}}% + \ifempty\p_typo_items_symbol + \setbox\b_typo_items_symbols\emptyhbox + \else + \setbox\b_typo_items_symbols\hbox + {\c_typo_items_m\zerocount + \let\m_typo_items_align\p_typo_items_align + \scratchwidth\d_typo_items_symbol_width + \useitemsstyleandcolor\c!style\c!color + \typo_items_make{\dorecurse\c_typo_items_n{\typo_items_item{\strut\m_typo_items_symbol\recurselevel}}}}% + \fi} + +% alternatives: + +\defineitems[\v!top][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align] + +\setvalue{\??itemsalternatives\v!top}#1% + {\let\typo_items_make\typo_items_make_horizontal + \let\typo_items_item\typo_items_item_horizontal + \typo_items_construct_items_boxes{#1}% + \noindent\vbox\bgroup + \forgetall + \ifvoid\b_typo_items_symbols \else + \box\b_typo_items_symbols + \itemsparameter\c!inbetween + \nointerlineskip + \fi + \box\b_typo_items_texts\ + \egroup} + +\defineitems[\v!bottom][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align] + +\setvalue{\??itemsalternatives\v!bottom}#1% + {\let\typo_items_make\typo_items_make_horizontal + \let\typo_items_item\typo_items_item_horizontal + \typo_items_construct_items_boxes{#1}% + \noindent\vbox\bgroup + \forgetall + \box\b_typo_items_texts + \ifvoid\b_typo_items_symbols \else + \itemsparameter\c!inbetween + \nointerlineskip + \box\b_typo_items_symbols + \fi + \egroup} + +\defineitems[\v!inmargin][\c!width=1.5\emwidth,\c!align=\v!flushright,\c!distance=\leftmargindistance] + +\setvalue{\??itemsalternatives\v!inmargin}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \ifvoid\b_typo_items_symbols \else + \llap{\box\b_typo_items_symbols\hskip\d_typo_items_distance}% + \fi + \box\b_typo_items_texts + \egroup} + +\defineitems[\v!left][\c!width=1.5\emwidth,\c!align=\v!flushleft] + +\setvalue{\??itemsalternatives\v!left}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \ifvoid\b_typo_items_symbols \else + \box\b_typo_items_symbols + \kern\d_typo_items_distance + \fi + \box\b_typo_items_texts + \egroup} + +\defineitems[\v!right][\c!width=1.5\emwidth,\c!align=\v!flushright] + +\setvalue{\??itemsalternatives\v!right}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \box\b_typo_items_texts + \ifvoid\b_typo_items_symbols \else + \kern\d_typo_items_distance + \box\b_typo_items_symbols + \fi + \egroup} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-krn.mkxl b/tex/context/base/mkxl/typo-krn.mkxl new file mode 100644 index 000000000..5573fc529 --- /dev/null +++ b/tex/context/base/mkxl/typo-krn.mkxl @@ -0,0 +1,143 @@ +%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}{} + +\definesystemattribute[kern][public] + +% more +% +% {\setcharacterkerning[extrakerning]\input davis\relax} + +\installcorenamespace{characterkerning} + +\installcommandhandler \??characterkerning {characterkerning} \??characterkerning + +\permanent\protected\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}} + +\permanent\protected\def\resetcharacterkerning % fast one + {\c_attr_kern\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) \unknown\ this +%D 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 then we always +%D would get a command defined which is not beforehand a good idea. +%D +%D Here we need to keep the groupedcommand solution as it is used as modifier. + +\appendtoks + \frozen\instance\setuevalue{\currentcharacterkerning}% + {\doifelsenextoptional + {\typo_kerning_apply_yes{\currentcharacterkerning}}% + {\typo_kerning_apply_nop{\currentcharacterkerning}}}% +\to \everydefinecharacterkerning + +\protected\def\typo_kerning_apply_yes#1[#2]% + {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}{#2}}\donothing} + +\protected\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 murder. Nevertheless +%D we support this manipulation for use in 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] + +\permanent\protected\def\setupstretched + {\setupcharacterkerning[\v!stretched]} + +\pushoverloadmode + +\enforced\permanent\tolerant\protected\def\stretched[#1]#:#2% + {\begingroup + \let\currentcharacterkerning\v!stretched + \ifparameter#1\or + \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} + +\popoverloadmode + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-lan.mkxl b/tex/context/base/mkxl/typo-lan.mkxl new file mode 100644 index 000000000..9d137f5a5 --- /dev/null +++ b/tex/context/base/mkxl/typo-lan.mkxl @@ -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}{} + +%D \macros +%D {averagecharwidth, charwidthlanguage} +%D +%D This is a more \MKIV-ish variant of lang-frq.mkiv. The methods are gone as one +%D doesn't need the tables for them. The main macro is \type {\averagecharwidth} +%D which behaves like a dimension register. +%D +%D I finally decided to reimplement this as I needed it for a manual (which is often +%D a reason for such a rewrite). With some inspiring Porcupine Tree in the +%D background it's not the worst thing to do. + +\mutable\def\charwidthlanguage{\currentmainlanguage} + +\permanent\def\averagecharwidth {\dimexpr\clf_averagecharwidth{\charwidthlanguage}\scaledpoint\relax} +\permanent\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/tex/context/base/mkxl/typo-lig.mkxl b/tex/context/base/mkxl/typo-lig.mkxl new file mode 100644 index 000000000..e30774d8e --- /dev/null +++ b/tex/context/base/mkxl/typo-lig.mkxl @@ -0,0 +1,23 @@ +%D \module +%D [ file=typo-lig, +%D version=2014.12.01, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Ligatures, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Typesetting Macros / Ligatures} + +%D The original macro was mostly used for testing an attribute that blocks ligatures +%D in the nodemode handler. In \LMTX\ things are done differently. + +\unprotect + +\permanent\protected\def\noligature{\dontleavehmode\groupedcommandcs\noligaturing\donothing} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-lin.lmt b/tex/context/base/mkxl/typo-lin.lmt new file mode 100644 index 000000000..e49f13b60 --- /dev/null +++ b/tex/context/base/mkxl/typo-lin.lmt @@ -0,0 +1,475 @@ +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 par node is no longer of any use so we remove it (each line has the +-- direction attached). We might at some point also strip the disc nodes as they no longer serve +-- a purpose but that can better be a helper. Anchoring left has advantage of keeping page +-- stream. +-- +-- 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 linelist_code = listcodes.line +----- par_code = nodecodes.par +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip +local parfillskip_code = gluecodes.parfillskip + +local tonut = nodes.tonut +local tonode = nodes.tonode + +local nexthlist = nuts.traversers.hlist +local insert_before = nuts.insert_before +local insert_after = nuts.insert_after +local find_tail = nuts.tail +local rehpack = nuts.rehpack +----- 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 setlink = nuts.setlink +local setkern = nuts.setkern +local getkern = nuts.getkern +local getdirection = nuts.getdirection +local getshift = nuts.getshift +local setshift = nuts.setshift +local getwidth = nuts.getwidth +local setwidth = nuts.setwidth + +local setprop = nuts.setprop +local getprop = nuts.rawprop -- getprop + +local effectiveglue = nuts.effective_glue + +local nodepool = nuts.pool +local new_kern = nodepool.kern +local new_leftskip = nodepool.leftskip +local new_rightskip = nodepool.rightskip +local new_hlist = nodepool.hlist +local new_rule = nodepool.rule +local new_glue = nodepool.glue + +local righttoleft_code = nodes.dirvalues.righttoleft + +local texgetcount = tex.getcount +local texgetglue = tex.getglue +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters + +local jobpositions = job.positions +local getposition = jobpositions.get +local getreserved = jobpositions.getreserved + +local paragraphs = { } +typesetters.paragraphs = paragraphs + +local addskips = false -- todo: use engine normalizer +local noflines = 0 + +-- This is the third version, a mix between immediate (prestine lines) and delayed +-- as we don't want anchors that are not used. + +-- I will make a better variant once lmtx is stable i.e. less clutter. + +local function finalize(prop,key) -- delayed calculations + local line = prop.line + local hsize = prop.hsize + local width = prop.width + local shift = getshift(line) -- dangerous as it can be vertical as well + local reverse = getdirection(line) == righttoleft_code 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 = getwidth(line) + 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 = getwidth(head) or 0 + end + current = getnext(head) + id = getid(current) + end + -- no: + -- if id == par_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 = getwidth(current) 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 + +-- do we still need this: + +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 + -- normalizer : todo, get the data, no need to normalize + for line, subtype in nexthlist, head do + if subtype == linelist_code and not getprop(line,"line") then + normalize(line) + end + end + return head, true -- true is obsolete +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 + anchor = new_hlist(setlink( + anchor, + new_kern(-65536/4), + new_rule(65536/2,4*65536,4*65536), + new_kern(-65536/4-4*65536), + new_rule(8*65536,65536/4,65536/4) + )) + setwidth(anchor,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 + setkern(prev,getkern(prev) + dx) + end + if next and getid(next) == kern_code then + setkern(next,getkern(next) - dx) + end + end + if dy ~= 0 then + if getid(blob) == hlist_code then + setshift(blob,getshift(blob) + dy) + end + end + else +-- report("no line") + end + end +end + +local latelua = nodepool.latelua +local setposition = jobpositions.setspec + +local function setanchor(h_anchor) + return latelua { + action = setposition, + name = "md:h", + index = h_anchor, + value = { x = true, c = true }, + } +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/tex/context/base/mkxl/typo-lin.mkxl b/tex/context/base/mkxl/typo-lin.mkxl new file mode 100644 index 000000000..6b142b32d --- /dev/null +++ b/tex/context/base/mkxl/typo-lin.mkxl @@ -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}{autosuffix} + +\unprotect + +% nothing yet / experimental + +\protect \endinput + diff --git a/tex/context/base/mkxl/typo-mar.mkxl b/tex/context/base/mkxl/typo-mar.mkxl new file mode 100644 index 000000000..5d6f15f21 --- /dev/null +++ b/tex/context/base/mkxl/typo-mar.mkxl @@ -0,0 +1,471 @@ +% 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 one of the things +%D that I really need myself, for instance when rendering rather unpredictable +%D (educational) tests encoded in XML. This module permits anchoring for instance +%D item numbers and also overload them when they have subnumbers. In the future it +%D might replace the current maginal note mechanism (that then will be just an +%D instance). +%D +%D In spite of what might be expected, the more advanced \LUA\ based variant is upto +%D twice as fast on simple entries. Also, we no longer need an extra pass to get +%D inner and outer alignments in sync with the pagebuilder. + +\registerctxluafile{typo-mar}{} + +%definesystemattribute[margindata] % only at the lua end + +%D In \MKII\ we have three categories and their historically meaning is as follows: +%D +%D marginlines: These are flushed relative to the start of a line and need to be +%D invoked there. +%D +%D marginwords: These can be issued in the text flow and will migrate sidewards; in +%D spite of the name, it can be a paragraph of text as well, but normally it's +%D words. +%D +%D margintexts: These can be set beforehand and are flushed at the next paragraph of +%D 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. It can be +%D anchored in the text or given beforehand in which case it gets flushed at the +%D first occasion. +%D +%D margintext: This runs on top of margindata and the only difference is that it +%D uses the framed mechanism for packaging. +%D +%D Stacking is done differently as is inner and outer alignment (in most cases more +%D efficient). The functionality is mostly the same as in \MKII, but there are a few +%D additions, like names entries, where later ones overload preceding not yet +%D flushed ones. Data can get catagorized and is then treated as a group (e.g. when +%D stacking is needed). +%D +%D The amount of \TEX\ code is less than in \MKII\ because we do all trickery in at +%D the \LUA\ end. At the end of this file we define several commands, like \type +%D {\inleftmargin} and \type {\inleft}. You can configure them individually or as a +%D group. There is an 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 on +%D 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!stackname=, + % \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, % so by default we scale the strut to the font ! + \c!offset=\v!overlay, + \c!fr!analyze=\v!yes, + \c!frame=\v!off, + \c!width=\margindataparameter\c!width, + \c!align=\margindataparameter\c!align] + +\appendtoks + \frozen\instance\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 + \pickupattributes +\to \everymargindatacontent + +% trialtypesetting: no need for margin stuff while trialing as +% is has no dimensions + +\newcount\nofmargintexts +\newcount\c_typo_margins_n + +\ifdefined\dotagmarginanchor \else \let\dotagmarginanchor\gobbleoneargument \fi +\ifdefined\dotagmargintext \else \let\dotagmargintext \gobbleoneargument \fi + +\definepagestate[\s!margintext] + +\protected\def\typo_margins_data_synchronize + {\doforcedtrackpagestate\s!margintext\nofmargintexts % includes increment + \docheckpagestate\s!margintext\nofmargintexts + %\doifelserightpagestate\s!margintext\nofmargintexts\relax\relax + \realpageno\realpagestateno + \swapmargins} + +\permanent\protected\def\margindata + {\iftrialtypesetting + \expandafter\typo_margins_data_nop + \else + \expandafter\typo_margins_data_yes + \fi} + +\permanent\tolerant\protected\def\typo_margins_data_nop[#name]#spacer[#dataparameters]#spacer[#textparameters]#:#content% + {} + +\permanent\tolerant\protected\def\typo_margins_data_yes[#name]#spacer[#dataparameters]#spacer[#textparameters]#:#content% + {\setfalse\inhibitmargindata % flushing afterwards + \begingroup + %\settrue\inhibitmargindata % no flushing in here + \def\currentmargindata{#name}% + \let\currentmarginframed\currentmargindata + \ifparameter#dataparameters\or + \setupcurrentmargindata[#dataparameters]% + \fi + \doifelsenothing{#content}\donefalse\donetrue + \global\advance\c_typo_margins_n\plusone + \ifdone + \edef\currentmarginreference{\margindataparameter\c!reference}% + \ifempty\currentmarginreference \else + \strc_references_set_page_only_destination_box_attribute\currentmarginreference\currentmarginreference + \fi + \edef\currentmargindatastrut{\margindataparameter\c!strut}% + \dostarttaggedchained\t!margintext\currentmargindata\??margindata + \dotagmargintext\c_typo_margins_n + \ifcsname\currentmarginframedhash\s!parent\endcsname + \setbox\nextbox\naturalhbox \currentmarginreference \bgroup + \the\everymargindatacontent + \usemargindatastyleandcolor\c!style\c!color + \setupcurrentmarginframed[\c!location=\v!normal,#textparameters]% + \typo_margins_data_synchronize + \inheritedmarginframedframed\bgroup + \ifempty\currentmargindatastrut \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}% + \ifempty\currentmargindatawidth + \setbox\nextbox\naturalhbox \currentmarginreference \bgroup + \typo_margins_data_synchronize + \the\everymargindatacontent + \usemargindatastyleandcolor\c!style\c!color + \ifempty\currentmargindatastrut \else + \synchronizestrut\currentmargindatastrut + \fi + \begstrut + \strc_references_flush_destination_nodes + \margindataparameter\c!command{#content}% + \endstrut + \egroup + \let\currentmarginfirstheight\empty + \else + \setbox\nextbox\naturalhbox \currentmarginreference \bgroup + \typo_margins_data_synchronize + \dosetraggedcommand{\margindataparameter\c!align}% + \vtop \bgroup + \the\everymargindatacontent + \usemargindatastyleandcolor\c!style\c!color + \hsize\currentmargindatawidth + \raggedcommand + \ifempty\currentmargindatastrut \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 + \dostarttagged\t!marginanchor\empty + \dotagmarginanchor\c_typo_margins_n + \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 + \ifempty\currentmarginfirstheight \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 + stackname {\margindataparameter\c!stackname}% + stack {\margindataparameter\c!stack}% + index \c_typo_margins_n + \relax + \dostoptagged + \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: + +\appendtoks + \enforced\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] + +\aliased\let\marginword \margintext +\aliased\let\margintitle \margintext +\aliased\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 ... it will disappear from lmtx: + +\permanent\tolerant\protected\def\defineinmargin[#name]#spacer[#location]#spacer[#align]#spacer[#settings]% not completely compatible + {\ifarguments\else + \definemargindata[#name][\c!location=#location,\c!align=#align,#settings]% + \definemarginframed[#name][#location][\c!align=#align,#settings]% + \fi} + +\aliased\let\definemarginline\definemargindata % for old times sake +\aliased\let\setupinmargin \setupmargindata % only partial (no framed), for old times sake + +% 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 + +%D Here because in strc-ren we are too early: + +% % \definemargindata +% % [margintext:chapter] +% % [margintext:section] +% % +% % \defineheadalternative +% % [margintext:chapter] +% % [margintext] +% % [margintext=margintext:chapter] +% % +% % \setuphead +% % [chapter] +% % [alternative=margintext:chapter] +% +% \setuphead +% [chapter] +% [alternative=margintext] + +\definemargindata + [\v!margintext:\v!section] + [\v!left] + [\c!margin=\v!margin, + \c!width=\leftmarginwidth, + \c!align=\v!flushright] + +\defineheadalternative + [\v!margintext] + [\c!alternative=\v!somewhere, + \c!margintext=\v!margintext:\v!section, + \c!renderingsetup=\??headrenderings:\v!margintext] + +\startsetups[\??headrenderings:\v!margintext] + \executeifdefined{\headalternativeparameter\c!margintext}\margintext { + \ifconditional\headshownumber + \headnumbercontent + \hskip\headnumberdistance + \fi + \headtextcontent + } +\stopsetups + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-ovl.mkxl b/tex/context/base/mkxl/typo-ovl.mkxl new file mode 100644 index 000000000..8ad4cce26 --- /dev/null +++ b/tex/context/base/mkxl/typo-ovl.mkxl @@ -0,0 +1,116 @@ +%D \module +%D [ file=lang-ovl, +%D version=2016.02.03, % about that time (maybe earlier) +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Overloads, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Overloads} + +\unprotect + +%D See \LUA\ file for comments. I'll probably never use this code outside the +%D project where it had some experimental use. (Occasionally we do some spell +%D checking and suspicious word usage marking.) So there is not much documentation +%D here. Keep in mind that overloading only makes sense for content that gets +%D replaced as otherwise normal attributes make more sense. Using this otherwise +%D is weird but one never knows what users come up with. + +\registerctxluafile{typo-ovl}{} + +\definesystemattribute[overloads][public,global] + +\installcorenamespace{overloads} + +%D Watch how we abuse highlights. + +\newcount\c_typo_overload_font_id + +\protected\def\typo_overloads_define#1% + {\begingroup + % we pack so we avoid interference (and for sure don't process!) + \setbox\scratchbox\hpack\bgroup + \global\c_typo_overload_font_id\fontid\font + \resetallattributes % so we only change what gets set + \highlight[#1]% + \signalcharacter + \global\c_typo_overload_font_id + \ifnum\c_typo_overload_font_id=\fontid\font + \zerocount + \else + \fontid\font + \fi + \egroup + \global\expandafter\chardef\csname\??overloads#1\endcsname + \clf_overloadsattribute{#1}\c_typo_overload_font_id\scratchbox + \endgroup} + +\permanent\protected\def\setoverloads[#1]% + {\ifcsname\??overloads#1\endcsname\else + \typo_overloads_define{#1}% + \fi + \c_attr_overloads\csname\??overloads#1\endcsname} + +\permanent\protected\def\registeroverloads[#1]% + {\ifcsname\??overloads#1\endcsname\else + \typo_overloads_define{#1}% + \fi} + +\permanent\protected\def\resetoverloads + {\c_attr_overloads\attributeunsetvalue} + +%D We hook this into the replacement module, probably the only place where it makes +%D sense. Here is an adapted version of an example: +%D +%D \starttyping +%D \replaceword[basics][new] [old] +%D \replaceword[basics][now] [hl3->never] +%D \replaceword[basics][never][now] +%D \replaceword[basics][heck] [] +%D +%D \definehighlight[hl1][style={\setbar[underbar]\red\setcharactercasing[WORD]\bf}] +%D \definehighlight[hl2][style={\setbar[overbar]\blue\setcharactercasing[Words]}] +%D \definehighlight[hl3][style={\setbar[overstrike]\green\bs}] +%D +%D \registeroverloads[hl1] +%D \registeroverloads[hl2] +%D \registeroverloads[hl3] +%D +%D \start \setreplacements[basics][hl1] What the heck, it's now or never, isn't it new? \stop \par +%D \start \setreplacements[basics][hl2] What the heck, it's now or never, isn't it new? \stop \par +%D \start \setreplacements[basics][hl1] What the heck, it's now or never, isn't it new? \stop \par +%D \start \setreplacements[basics] What the heck, it's now or never, isn't it new? \stop \par +%D \stoptyping +%D +%D We used it to mark synonyms that should not be corrected by the editor. Sort of the +%D reverse of not having a word in a vetted wordlist. A bit out of place in a typesetting +%D system. If really needed we can support multiple words seperataed by spaces but I didn't +%D need it. And \unknown\ fonts are supported but at fixed size! + +\ifdefined\setreplacements + + \pushoverloadmode + + \permanent\tolerant\protected\def\setreplacements[#1]#*[#2]% + {\clf_setreplacements{#1}% + \ifparameter#2\or + \setoverloads[#2]% + \else + \resetoverloads + \fi} + + \popoverloadmode + +\else + + % something weird + +\fi + +\protect diff --git a/tex/context/base/mkxl/typo-pag.mkxl b/tex/context/base/mkxl/typo-pag.mkxl new file mode 100644 index 000000000..07443eb16 --- /dev/null +++ b/tex/context/base/mkxl/typo-pag.mkxl @@ -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}{} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-par.mkxl b/tex/context/base/mkxl/typo-par.mkxl new file mode 100644 index 000000000..de40c6568 --- /dev/null +++ b/tex/context/base/mkxl/typo-par.mkxl @@ -0,0 +1,30 @@ +%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}{optimize} +\registerctxluafile{node-ltp}{} +\registerctxluafile{trac-par}{} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-plc.mkxl b/tex/context/base/mkxl/typo-plc.mkxl new file mode 100644 index 000000000..e6e90db73 --- /dev/null +++ b/tex/context/base/mkxl/typo-plc.mkxl @@ -0,0 +1,39 @@ +%D \module +%D [ file=typo-plc, +%D version=2020.07.01, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Placeholders, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Placeholders} + +\unprotect + +\installcorenamespace {placeholder} + +\installcommandhandler \??placeholder {placeholder} \??placeholder + +\permanent\protected\def\placeholder[#1]% + {\begingroup + \edef\currentplaceholder{#1}% + \placeholderparameter\c!before + \useplaceholderstyleandcolor\c!style\c!color + \placeholderparameter\c!text + \placeholderparameter\c!after + \endgroup} + +\defineplaceholder + [todo] + %[\c!text={Still to be written!}, + [\c!text=todo, % labeltext ? + \c!style=\v!bold, + \c!before=\blank, + \c!after=\blank] + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-pnc.mkxl b/tex/context/base/mkxl/typo-pnc.mkxl new file mode 100644 index 000000000..b5b1a17d6 --- /dev/null +++ b/tex/context/base/mkxl/typo-pnc.mkxl @@ -0,0 +1,55 @@ +%D \module +%D [ file=typo-pnc, +%D version=2017.06.23, % experiment in project +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Punctuation, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This 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 / Punctuation} + +\unprotect + +% In manuals we often have "foo e.g. bar" where we then have to compensate spaces +% with "foo e.g.\ bar" so let's see if we can automate that and at the same time +% inject spaces between the snippets. It gets boring writing this kind of code. + +\registerctxluafile{typo-pnc}{} + +\definesystemattribute[periodkern][public,global] + +\installcorenamespace{periodkerning} + +\installcommandhandler \??periodkerning {periodkerning} \??periodkerning + +\permanent\protected\def\setperiodkerning[#1]% + {\edef\currentperiodkerning{#1}% + \ifx\currentperiodkerning\s!reset + \resetperiodkerning + \else + \typo_periodkerning_set + \fi} + +\def\typo_periodkerning_set + {\clf_setperiodkerning{\periodkerningparameter\c!factor}} + +\permanent\protected\def\resetperiodkerning % fast one + {\c_attr_periodkern\attributeunsetvalue} + +\appendtoks + \resetperiodkerning +\to \everyresettypesetting + +\defineperiodkerning [zerospaceperiods] [\c!factor=0] +\defineperiodkerning [smallspaceperiods] [\c!factor=.25] +\defineperiodkerning [halfspaceperiods] [\c!factor=.5] + +% If we ever need a command, see typo-krn.mkiv but it doesn't make much sense +% to have it. + +\protect diff --git a/tex/context/base/mkxl/typo-prc.mklx b/tex/context/base/mkxl/typo-prc.mklx new file mode 100644 index 000000000..fa8bf2c07 --- /dev/null +++ b/tex/context/base/mkxl/typo-prc.mklx @@ -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 category +%D as processors. This might change. (They are used in publications.) + +\registerctxluafile{typo-prc}{} +\registerctxluafile{typo-man}{} + +\unprotect + +%D Processors are used when we cannot easily associate typesetting directives with +%D (for instance) structural elements. Instead of ending up with numerous additional +%D 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 for +%D 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 up +%D 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 +%D {left}, \type {right}, and \type {command} (the given command takes one +%D 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 invoked behind +%D the screens. After all, processor prefixes need to be split off first. At the +%D \LUA\ end we do check for a processor being registered anyway. + +\permanent\protected\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/tex/context/base/mkxl/typo-rep.mkxl b/tex/context/base/mkxl/typo-rep.mkxl new file mode 100644 index 000000000..6e0a9a22c --- /dev/null +++ b/tex/context/base/mkxl/typo-rep.mkxl @@ -0,0 +1,42 @@ +%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} + +%D Here we implement an experimental stripper. I might cook up a few more +%D variants when there is real demand. It might even go away. +%D +%D \starttyping +%D \definefontfeature[default][default][mode=node,formatters=strip] +%D +%D \setcharacterstripping[1] +%D \stoptyping + +\unprotect + +\registerctxluafile{typo-rep}{} + +\definesystemattribute[stripping][public] + +\permanent\protected\def\setcharacterstripping[#1]% + {\clf_setcharacterstripping{#1}} + +\permanent\protected\def\resetcharacterstripping + {\c_attr_stripping\attributeunsetvalue} + +% maybe .. this might disappear, but is handy for testing + +\permanent\protected\def\forcecharacterstripping % secret command + {\ctxlua{fonts.handlers.otf.features.register("formatters",true)}} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-rub.mkxl b/tex/context/base/mkxl/typo-rub.mkxl new file mode 100644 index 000000000..b7265a9c8 --- /dev/null +++ b/tex/context/base/mkxl/typo-rub.mkxl @@ -0,0 +1,173 @@ +%D \module +%D [ file=typo-rub, +%D version=2016.10.10, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Rubies, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%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 and unfinished. + +% todo: distance + +\writestatus{loading}{ConTeXt Typesetting Macros / Rubies} + +\unprotect + +\registerctxluafile{typo-rub}{} + +\definesystemattribute[ruby][public] + +\installcorenamespace {ruby} +\installcorenamespace {rubyanalyze} +\installcorenamespace {rubyplacement} +\installcorenamespace {rubynumber} + +\installcommandhandler \??ruby {ruby} \??ruby + +% \appendtoks +% \clf_defineruby +% align {\rubyparameter\c!align} +% stretch {\rubyparameter\c!stretch} +% hoffset \rubyparameter\c!hoffset +% voffset \rubyparameter\c!voffset +% \relax +% \to \everydefineruby + +\permanent\tolerant\protected\def\ruby[#1]#:#2#3% + {\dontleavehmode + \begingroup + \enforced\let\ruby\noruby + \edef\currentruby{#1}% + \edef\p_location{\rubyparameter\c!location}% + \enforced\let|\relax + \ifcsname\??rubyanalyze\p_location\endcsname + \expandafter\lastnamedcs\else\expandafter\typo_ruby_analyze + \fi{#2}{#3}% + \endgroup} + +\permanent\tolerant\protected\def\noruby[#1]#:#2#3% + {#2} + +\def\typo_ruby_analyze#1#2% + {\clf_ruby + base {#1}% + comment {#2} + \relax} + +\setvalue{\??rubyanalyze\v!top}#1#2% + {\clf_ruby + align {\rubyparameter\c!align}% + stretch {\rubyparameter\c!stretch}% + hoffset \rubyparameter\c!hoffset + voffset \rubyparameter\c!voffset + base {#1}% + comment {#2} + \relax} + +\setvalue{\??rubyplacement\v!top}#1#2% + {\setbox\scratchbox\hbox\bgroup + \userubystyleandcolor\c!style\c!color + #2% + \egroup + \clf_setruby \scratchbox + \relax + #1} + +\setvalue{\??rubyplacement\v!right}#1#2% + {#1% + \edef\p_distance{\rubyparameter\c!distance}% + \ifx\p_distance\empty\orelse\ifx\p_distance\v!none\else\hskip\p_distance\fi + \begingroup + \userubystyleandcolor\c!style\c!color + \rubyparameter\c!left#2\rubyparameter\c!right + \endgroup} + +\setvalue{\??rubyplacement\v!left}#1#2% + {\begingroup + \userubystyleandcolor\c!style\c!color + \rubyparameter\c!left#2\rubyparameter\c!right + \endgroup + \edef\p_distance{\rubyparameter\c!distance}% + \ifx\p_distance\empty\orelse\ifx\p_distance\v!none\else\hskip\p_distance\fi + #1} + +\permanent\protected\def\setruby#1#2% + {\begingroup + \ifcsname\??rubyplacement\p_location\endcsname + \lastnamedcs{#1}{#2}% + \else + #1% + \fi + \endgroup} + +\permanent\tolerant\protected\def\startruby[#1]% + {\dontleavehmode + \begingroup + \enforced\aliased\startruby\begingroup + \edef\currentruby{#1}% + \clf_startruby + align {\rubyparameter\c!align}% + stretch {\rubyparameter\c!stretch}% + hoffset \rubyparameter\c!hoffset + voffset \rubyparameter\c!voffset + \relax} + +\permanent\protected\def\stopruby + {\endgroup} + +\setupruby + [\c!style=\txx, + \c!location=\v!top, + \c!left=(, + \c!right=), + \c!distance=\zeropoint, % \v!none means no skip at all so no break either + \c!hoffset=\zeropoint, + \c!voffset=-2\exheight] + +%D Experiment too: + +\permanent\protected\def\numberedruby[#1]#2% + {\doifnotcounter{\??rubynumber#1}{\definecounter[\??rubynumber#1]\setcounter[\??rubynumber#1][1]}% + \ruby[#1]{#2}{\convertedcounter[\??rubynumber#1]}% + \incrementcounter[\??rubynumber#1]% + \relax} + +\protect \endinput + +% \usemodule[art-01]\setupbodyfont[dejavu,12pt] +% +% \defineruby[auto] [align=auto,color=darkred] +% \defineruby[left] [align=flushleft,color=darkred] +% \defineruby[right] [align=flushright,color=darkred] +% \defineruby[spread][stretch=yes] +% +% \showframe \showglyphs \showfontkerns \setupinterlinespace[22pt] +% +% \starttext +% +% \startbuffer +% \dorecurse{20}{\ruby{XYZ}{a|bc|d} }\par +% \dorecurse{20}{\ruby{PQR}{p|q|r} }\par +% \dorecurse{20}{\ruby{XYZ}{1|22|333} }\par +% \dorecurse{20}{\ruby{XYZ}{111|222|333} }\par +% \dorecurse{20}{\ruby{XYZ}{foobar} }\par +% \dorecurse{20}{\ruby{XYZ}{fooledbar} }\par +% \dorecurse{20}{\ruby[spread]{XYZ}{fooledbar} }\par +% \dorecurse{20}{\ruby{extremely}{wide} }\par +% \dorecurse{20}{\ruby{wide}{extremely} }\par +% stopbuffer +% +% \testfeatureonce{1}{\start \setupinterlinespace[16pt] \setupruby[location=none] \getbuffer \stop \page} +% \testfeatureonce{1}{\start \setupinterlinespace[16pt] \setupruby[location=right] \getbuffer \stop \page} +% \testfeatureonce{1}{\start \setupinterlinespace[28pt] \setupruby[align=auto,color=darkred] \getbuffer \stop \page} +% \testfeatureonce{1}{\start \setupinterlinespace[28pt] \setupruby[align=flushleft,color=darkgreen] \getbuffer \stop \page} +% \testfeatureonce{1}{\start \setupinterlinespace[28pt] \setupruby[align=flushright,color=darkblue] \getbuffer \stop \page} +% \testfeatureonce{1}{\start \setupinterlinespace[28pt] \setupruby[align=middle,color=darkyellow] \getbuffer \stop \page} +% +% \stoptext diff --git a/tex/context/base/mkxl/typo-scr.mkxl b/tex/context/base/mkxl/typo-scr.mkxl new file mode 100644 index 000000000..36e2997e2 --- /dev/null +++ b/tex/context/base/mkxl/typo-scr.mkxl @@ -0,0 +1,266 @@ +%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 + +\protected\def\typo_scripts_low[#1]#2% + {\dontleavehmode + \begingroup + \edef\currentlow{#1}% + \kern\lowparameter\c!distance\relax + \setbox\scratchbox\runninghbox\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} + +\protected\def\typo_scripts_high[#1]#2% + {\dontleavehmode + \begingroup + \edef\currenthigh{#1}% + \kern\highparameter\c!distance\relax + \setbox\scratchbox\runninghbox\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} + +\permanent\protected\def\low {\typo_scripts_low []} +\permanent\protected\def\high{\typo_scripts_high[]} + +%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 + \frozen\setuevalue\currentlowhigh{\typo_scripts_lowhigh[\currentlowhigh]}% +\to \everydefinelowhigh + +\tolerant\protected\def\typo_scripts_lowhigh[#1]#*[#2]#:#3#4% todo: align .. [#1] is compatible hack + {\dontleavehmode + \runninghbox\bgroup + \edef\currentlowhigh{#1}% + \dostarttagged\t!subsup\currentlowhigh + \scratchdimen\lowhighparameter\c!distance\relax + \setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#3}}% + \setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#4}}% + \edef\p_align{#2}% + \ifx\p_align\v!left + \ifdim\wd\plusfour<\wd\plussix + \setbox\plusfour\hpack to \wd\plussix {\hss\box\plusfour}% + \else + \setbox\plussix \hpack to \wd\plusfour{\hss\box\plussix }% + \fi + \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% + {\kern\scratchdimen + \setbox\scratchbox\hpack\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} + +\permanent\tolerant\protected\def\typo_scripts_highlow[#1]#*[#2]#:#3#4% + {\typo_scripts_lowhigh[#1][#2]{#4}{#3}} + +\permanent\protected\def\lohi{\typo_scripts_lowhigh[]} +\permanent\protected\def\hilo{\typo_scripts_highlow[]} + +%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 + \frozen\setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh[\currentlowmidhigh]}% +\to \everydefinelowmidhigh + +\protected\def\typo_scripts_lowmidhigh[#1]#2#3#4% + {\dontleavehmode + \runninghbox\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 \hpack to \scratchdimen{\hss\lower\lowmidhighparameter\c!down\box\plustwo \hss}% + \setbox\plusfour\hpack to \scratchdimen{\hss \box\plusfour\hss}% + \setbox\plussix \hpack to \scratchdimen{\hss\raise\lowmidhighparameter\c!up \box\plussix \hss}% + \wd\plustwo \zeropoint + \wd\plusfour\zeropoint + \box\plusfour + \box\plustwo + \box\plussix + \dostoptagged + \egroup} + +\permanent\protected\def\lomihi {\typo_scripts_lowmidhigh[]} +\permanent\protected\def\himilo#1#2#3{\typo_scripts_lowmidhigh[]{#3}{#2}{#1}} + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-spa.mkxl b/tex/context/base/mkxl/typo-spa.mkxl new file mode 100644 index 000000000..4daaac100 --- /dev/null +++ b/tex/context/base/mkxl/typo-spa.mkxl @@ -0,0 +1,78 @@ +%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}{} + +\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] + +\permanent\protected\def\definecharacterspacing[#1]% + {\clf_definecharacterspacing{#1}} + +\permanent\tolerant\protected\def\setupcharacterspacing[#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} + +\permanent\protected\def\setcharacterspacing[#1]% we can store the attribute if we want speed + {\clf_setcharacterspacing{#1}} + +\permanent\protected\def\resetcharacterspacing % fast one + {\c_attr_spacing\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/tex/context/base/mkxl/typo-sus.mkxl b/tex/context/base/mkxl/typo-sus.mkxl new file mode 100644 index 000000000..7b62b8aca --- /dev/null +++ b/tex/context/base/mkxl/typo-sus.mkxl @@ -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}{} + +\permanent\protected\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 \protected\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/tex/context/base/mkxl/typo-tal.mkxl b/tex/context/base/mkxl/typo-tal.mkxl new file mode 100644 index 000000000..86a90020c --- /dev/null +++ b/tex/context/base/mkxl/typo-tal.mkxl @@ -0,0 +1,303 @@ +%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}{} + +\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 + +\permanent\protected\def\signalcharacteralign #1#2{\c_attr_characteralign\numexpr#1*\maxcardminusone+#2\relax} % 0xFFFF +\permanent\protected\def\setcharacteralign #1#2{\clf_setcharacteralign#1{#2}} +\permanent\protected\def\resetcharacteralign {\clf_resetcharacteralign} +\permanent\protected\def\nocharacteralign {\c_attr_characteralign\attributeunsetvalue} +\permanent\protected\def\setcharacteraligndetail#1#2#3#4{\clf_setcharacteraligndetail#1{#2}#3#4\relax} + +%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 +%D \startbuffer +%D \startcharacteralign[leftsample=123.456,rightsample=00,character={,}] +%D \checkcharacteralign{123.456,78}\par +%D \checkcharacteralign {456}\par +%D \checkcharacteralign {23.456}\par +%D \checkcharacteralign {78,9}\par +%D \checkcharacteralign {78}\par +%D \stopcharacteralign +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D +%D \startbuffer +%D \startcharacteralign[leftwidth=123.456,rightwidth=00,character={,}] +%D \checkcharacteralign{123.456,78}\par +%D \checkcharacteralign {456}\par +%D \checkcharacteralign {23.456}\par +%D \checkcharacteralign {78,9}\par +%D \checkcharacteralign {78}\par +%D \stopcharacteralign +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D +%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 method to apply). +%D +%D One can use \type {\nocharacteralign} to disable this mechanism, for instance in +%D a table cell. + +\mutable\def\alignmentcharacter{,} + +\installcorenamespace{characteralign} + +\installparameterhandler\??characteralign {characteralign} +\installsetuphandler \??characteralign {characteralign} + +\setupcharacteralign + [\c!leftwidth =\zeropoint, + \c!rightwidth =\zeropoint, + \c!leftsample =, + \c!rightsample=, + \c!character =\alignmentcharacter] + +\permanent\protected\def\typo_charalign_pass_one + {\advance\scratchcounter\plusone + \setbox\scratchbox\typo_charalign_pass} + +\permanent\protected\def\typo_charalign_pass_two + {\advance\scratchcounter\plusone + \typo_charalign_pass} + +\def\typo_charalign_pass + {\hbox\bgroup\signalcharacteralign\plusone\scratchcounter\let\next} + +\permanent\tolerant\protected\def\startcharacteralign[#1]% + {\doifelseassignment{#1}\typo_charalign_start_one\typo_charalign_start_two{#1}} + +\def\typo_charalign_start_one#1#2\stopcharacteralign + {\bgroup + % for now no instances + \setupcurrentcharacteralign[#1]% + \edef\p_left {\characteralignparameter\c!leftsample}% + \edef\p_right{\characteralignparameter\c!rightsample}% + \ifempty\p_left + \scratchdimenone\dimexpr\characteralignparameter\c!leftwidth\relax + \else + \setbox\scratchbox\hbox{\p_left}% + \scratchdimenone\wd\scratchbox + \fi + \ifempty\p_right + \scratchdimentwo\dimexpr\characteralignparameter\c!rightwidth\relax + \else + \setbox\scratchbox\hbox{\p_right}% + \scratchdimentwo\wd\scratchbox + \fi + \ifzeropt\scratchdimenone + \ifzeropt\scratchdimentwo + \donefalse + \else + \donetrue + \fi + \else + \donetrue + \fi + \edef\alignmentcharacter{\characteralignparameter\c!character}% + \ifdone + \clf_setcharacteraligndetail + \plusone + \alignmentcharacter + \scratchdimenone + \scratchdimentwo + \else + \clf_setcharacteralign + \plusone + \alignmentcharacter + \begingroup + \scratchcounter\zerocount + \enforced\let\checkcharacteralign\typo_charalign_pass_one + \settrialtypesetting + #2\relax + \endgroup + \fi + \begingroup + \scratchcounter\zerocount + \enforced\let\checkcharacteralign\typo_charalign_pass_two + #2\relax + \endgroup + \resetcharacteralign + \egroup} + +\def\typo_charalign_start_two#1#2\stopcharacteralign + {\bgroup + \edef\m_temp{#1}% + \ifempty\m_temp \else + \let\alignmentcharacter\m_temp + \fi + \clf_setcharacteralign + \plusone + \alignmentcharacter + \begingroup + \scratchcounter\zerocount + \enforced\let\checkcharacteralign\typo_charalign_pass_one + \settrialtypesetting + #2\relax + \endgroup + \begingroup + \scratchcounter\zerocount + \enforced\let\checkcharacteralign\typo_charalign_pass_two + #2\relax + \endgroup + \resetcharacteralign + \egroup} + +\aliased\let\stopcharacteralign \relax +\aliased\let\checkcharacteralign\gobbleoneargument + +\permanent\protected\def\setfirstpasscharacteralign {\enforced\let\checkcharacteralign\gobbleoneargument} +\permanent\protected\def\setsecondpasscharacteralign{\enforced\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} + +\protected\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} + +%D Another example: +%D +%D \starttyping +%D \setupTABLE[c][2][alignmentcharacter={number->,},aligncharacter=yes,align={flushleft}] +%D \bTABLE +%D \bTR \bTD 1 \eTD \bTD 125 cm \eTD \eTR +%D \bTR \bTD 2 \eTD \bTD 1 125,80 cm \eTD \eTR +%D \bTR \bTD 6 \eTD \bTD 1 125,80 $\pi^2$ \eTD \eTR +%D \bTR \bTD 7 \eTD \bTD 129,3 \unit{square centimeter} \eTD \eTR +%D \eTABLE +%D +%D \setupTABLE[c][2][alignmentcharacter={number->,},aligncharacter=yes,align={flushleft}] +%D \bTABLE +%D \bTR \bTD 1 \eTD \bTD 125 cm \eTD \eTR +%D \bTR \bTD 2 \eTD \bTD 1 125,80 cm \eTD \eTR +%D \bTR \bTD 6 \eTD \bTD 1 125,80 $\pi^2$ \eTD \eTR +%D \bTR \bTD 7 \eTD \bTD 129,3 \unit{square centimeter} \eTD \eTR +%D \eTABLE +%D +%D \setupTABLE[c][2][alignmentcharacter={number->,},aligncharacter=yes,align={middle}] +%D \bTABLE +%D \bTR \bTD 1 \eTD \bTD 125 \eTD \eTR +%D \bTR \bTD 6 \eTD \bTD 1 125,80 \eTD \eTR +%D \bTR \bTD 7 \eTD \bTD 129,3 \eTD \eTR +%D \eTABLE +%D +%D \setupTABLE[c][2][alignmentcharacter={text->,},aligncharacter=yes,align={middle}] +%D \bTABLE +%D \bTR \bTD 1 \eTD \bTD 125 \eTD \eTR +%D \bTR \bTD 6 \eTD \bTD 1 125,80 \eTD \eTR +%D \bTR \bTD 7 \eTD \bTD 129,3 \eTD \eTR +%D \eTABLE +%D \stoptyping + +\protect \endinput diff --git a/tex/context/base/mkxl/typo-txt.mklx b/tex/context/base/mkxl/typo-txt.mklx new file mode 100644 index 000000000..bb92c8cd3 --- /dev/null +++ b/tex/context/base/mkxl/typo-txt.mklx @@ -0,0 +1,240 @@ +%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}{} + +%D \macros +%D {normalizefontheight,normalizefontwidth,normalizedfontsize} +%D +%D Next we introduce some font manipulation macros. When we want to typeset some +%D text spread in a well defined area, it can be considered bad practice to +%D manipulate character and word spacing. In such situations the next few macros can +%D be 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\enforced\edef\noexpand\normalizedfontsize{\the\typo_normalizers_size{#axis}{#size}}}% + \definefont[\strippedcsname#cs][#font at \normalizedfontsize]} + +\protected\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} + +\mutable\def\normalizedfontsize{\bodyfontsize} + +\permanent\protected\def\normalizetextwidth {\typo_normalizers_text_at_size\wd} +\permanent\protected\def\normalizetextheight{\typo_normalizers_text_at_size\ht} +\permanent\protected\def\normalizetextdepth {\typo_normalizers_text_at_size\dp} +\permanent\protected\def\normalizetextline {\typo_normalizers_text_at_size\htdp} + +\permanent\protected\def\normalizefontwidth {\typo_normalizers_font_at_size\wd} +\permanent\protected\def\normalizefontheight{\typo_normalizers_font_at_size\ht} +\permanent\protected\def\normalizefontdepth {\typo_normalizers_font_at_size\dp} +\permanent\protected\def\normalizefontline {\typo_normalizers_font_at_size\htdp} + +\permanent\protected\def\widthspanningtext #text#size#specification{\hbox{\normalizefontwidth \temp{#text}{#size}{#specification}\temp#text}} +\permanent\protected\def\heightspanningtext#text#size#specification{\hbox{\normalizefontheight\temp{#text}{#size}{#specification}\temp#text}} +\permanent\protected\def\depthspanningtext #text#size#specification{\hbox{\normalizefontdepth \temp{#text}{#size}{#specification}\temp#text}} +\permanent\protected\def\linespanningtext #text#size#specification{\hbox{\normalizefontline \temp{#text}{#size}{#specification}\temp#text}} + +%D Traditionally we use UpperCasedNames for this kind of functionality. + +\aliased\let\NormalizeFontHeight \normalizefontheight +\aliased\let\NormalizeFontWidth \normalizefontwidth +\aliased\let\NormalizeTextHeight \normalizetextheight +\aliased\let\NormalizeTextWidth \normalizetextwidth + +\aliased\let\WidthSpanningText \widthspanningtext + +\permanent\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{/}] + +\permanent\protected\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 % \aliased ? + +%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. + +\permanent\tolerant\protected\def\startnicelyfilledbox[#1]% + {\vbox\bgroup + \forgetall + \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} + +\permanent\protected\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/tex/context/base/mkxl/typo-wrp.mkxl b/tex/context/base/mkxl/typo-wrp.mkxl new file mode 100644 index 000000000..b552c151a --- /dev/null +++ b/tex/context/base/mkxl/typo-wrp.mkxl @@ -0,0 +1,58 @@ +%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}{} + +\permanent\protected\def\crlf + {\ifhmode + \expandafter\spac_crlf + \fi} + +\protected\def\spac_crlf + {\clf_enablecrlf % once + \unskip + \spac_crlf_placeholder + \ifcase\raggedstatus\hfil\or\or\or\hfil\fi + % in bad usage this can lead to: [break -10000] [wordboundary] [line(break)penalty] [parfillskip] + \break + \wordboundary + % which we then remove (maybe we should flag the wordboundary with an attribute but not now + \ignorespaces} + +\protected\def\spac_crlf_placeholder + {\strut} + +\protected\def\spac_crlf_placeholder_show + {\wordboundary + %\nobreak + \hpack to \zeropoint{\strut{\infofont\kern.25\emwidth}\lohi{\infofont CR}{\infofont LF}\hss}} + +\permanent\protected\def\settestcrlf + {\let\spac_crlf_placeholder\spac_crlf_placeholder_show} + +\permanent\protected\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/tex/context/base/mkxl/unic-ini.mkxl b/tex/context/base/mkxl/unic-ini.mkxl new file mode 100644 index 000000000..3fccd2feb --- /dev/null +++ b/tex/context/base/mkxl/unic-ini.mkxl @@ -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}{} + +\unprotect + +\permanent\def\unicodenumber #1{\the\numexpr#1\relax} % no lookahead +\permanent\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 + +\permanent\def\unicodechar#1{\clf_unicodechar{#1}} + +\permanent\protected\def\unknownchar + {\dontleavehmode\hpack{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}} + +\ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace + +\protect \endinput diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml index ec8c15ee2..fb3969277 100644 --- a/tex/context/interface/mkii/keys-de.xml +++ b/tex/context/interface/mkii/keys-de.xml @@ -780,6 +780,7 @@ + @@ -2085,7 +2086,7 @@ - + @@ -2128,7 +2129,7 @@ - + diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml index 6cf0cfa0f..59ecba8ec 100644 --- a/tex/context/interface/mkiv/context-en.xml +++ b/tex/context/interface/mkiv/context-en.xml @@ -3089,6 +3089,14 @@ + + + + + + + + @@ -3796,7 +3804,7 @@ - + @@ -5387,6 +5395,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7109,6 +7171,9 @@ + + + @@ -8438,6 +8503,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8445,6 +8536,9 @@ + + + @@ -8472,6 +8566,9 @@ + + + @@ -10157,104 +10254,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -13166,7 +13165,6 @@ - @@ -14511,6 +14509,9 @@ + + + @@ -14636,6 +14637,10 @@ + + + + @@ -16229,7 +16234,6 @@ - @@ -16245,9 +16249,9 @@ - - - + + + @@ -16257,7 +16261,7 @@ - + @@ -16267,7 +16271,7 @@ - + @@ -16277,7 +16281,7 @@ - + @@ -16287,7 +16291,7 @@ - + @@ -16297,30 +16301,30 @@ - + - - - + + + - + - + @@ -16603,6 +16607,14 @@ + + + + + + + + @@ -17981,181 +17993,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -18380,6 +18217,8 @@ + + @@ -18602,6 +18441,8 @@ + + @@ -18824,6 +18665,8 @@ + + @@ -19051,6 +18894,8 @@ + + @@ -20955,8 +20800,8 @@ - - + + @@ -20973,6 +20818,15 @@ + + + + + + + + + @@ -20983,15 +20837,6 @@ - - - - - - - - - @@ -22646,6 +22491,16 @@ + + + + + + + + + + @@ -22660,11 +22515,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -23223,6 +23112,7 @@ + @@ -24695,15 +24585,22 @@ + - + - + + + + + + + @@ -27701,7 +27598,7 @@ - + @@ -29117,6 +29014,7 @@ + @@ -30253,6 +30151,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37024,7 +36998,7 @@ - + @@ -37038,6 +37012,9 @@ + + + @@ -39842,6 +39819,10 @@ + + + + @@ -42230,7 +42211,6 @@ - @@ -42463,6 +42443,20 @@ + + + + + + + + + + + + + + @@ -48848,6 +48842,16 @@ + + + + + + + + + + @@ -49999,16 +50003,6 @@ - - - - - - - - - - diff --git a/tex/context/interface/mkiv/i-boxes.xml b/tex/context/interface/mkiv/i-boxes.xml index e18243811..b13c8c3ab 100644 --- a/tex/context/interface/mkiv/i-boxes.xml +++ b/tex/context/interface/mkiv/i-boxes.xml @@ -1256,4 +1256,10 @@ + + + + + + diff --git a/tex/context/interface/mkiv/i-catcodes.xml b/tex/context/interface/mkiv/i-catcodes.xml index 4e112c491..561cd9af6 100644 --- a/tex/context/interface/mkiv/i-catcodes.xml +++ b/tex/context/interface/mkiv/i-catcodes.xml @@ -4,7 +4,7 @@ - + diff --git a/tex/context/interface/mkiv/i-columns.xml b/tex/context/interface/mkiv/i-columns.xml index 72260b820..9890ec46f 100644 --- a/tex/context/interface/mkiv/i-columns.xml +++ b/tex/context/interface/mkiv/i-columns.xml @@ -4,8 +4,19 @@ - + + + + + + + + + + + + @@ -13,112 +24,31 @@ - - - - - - - - - - - - - + - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + - - + - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/tex/context/interface/mkiv/i-common-argument.xml b/tex/context/interface/mkiv/i-common-argument.xml index 5741a1c8a..c1b2f8cb3 100644 --- a/tex/context/interface/mkiv/i-common-argument.xml +++ b/tex/context/interface/mkiv/i-common-argument.xml @@ -594,4 +594,15 @@ + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-common-instance.xml b/tex/context/interface/mkiv/i-common-instance.xml index 025dafc4a..07ca3ac15 100644 --- a/tex/context/interface/mkiv/i-common-instance.xml +++ b/tex/context/interface/mkiv/i-common-instance.xml @@ -182,6 +182,11 @@ + + + + + diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf index 7950faf9f..f1ee11be3 100644 Binary files a/tex/context/interface/mkiv/i-context.pdf and b/tex/context/interface/mkiv/i-context.pdf differ diff --git a/tex/context/interface/mkiv/i-context.xml b/tex/context/interface/mkiv/i-context.xml index 2afbdfee2..a1f53f470 100644 --- a/tex/context/interface/mkiv/i-context.xml +++ b/tex/context/interface/mkiv/i-context.xml @@ -53,6 +53,7 @@ + @@ -107,7 +108,6 @@ - @@ -177,6 +177,7 @@ + diff --git a/tex/context/interface/mkiv/i-counter.xml b/tex/context/interface/mkiv/i-counter.xml index 7879fe27d..f3e622e5f 100644 --- a/tex/context/interface/mkiv/i-counter.xml +++ b/tex/context/interface/mkiv/i-counter.xml @@ -26,6 +26,9 @@ + + + diff --git a/tex/context/interface/mkiv/i-document.xml b/tex/context/interface/mkiv/i-document.xml index 5886aa8eb..3ea0d0eeb 100644 --- a/tex/context/interface/mkiv/i-document.xml +++ b/tex/context/interface/mkiv/i-document.xml @@ -164,6 +164,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -172,6 +192,7 @@ + @@ -200,6 +221,7 @@ + diff --git a/tex/context/interface/mkiv/i-filler.xml b/tex/context/interface/mkiv/i-filler.xml index 078dc4b7a..2e425a3f7 100644 --- a/tex/context/interface/mkiv/i-filler.xml +++ b/tex/context/interface/mkiv/i-filler.xml @@ -129,98 +129,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tex/context/interface/mkiv/i-fonts.xml b/tex/context/interface/mkiv/i-fonts.xml index 7cb1cbe99..a32aa1672 100644 --- a/tex/context/interface/mkiv/i-fonts.xml +++ b/tex/context/interface/mkiv/i-fonts.xml @@ -1153,8 +1153,6 @@ - - diff --git a/tex/context/interface/mkiv/i-framed.xml b/tex/context/interface/mkiv/i-framed.xml index d57a66969..ad8080a9d 100644 --- a/tex/context/interface/mkiv/i-framed.xml +++ b/tex/context/interface/mkiv/i-framed.xml @@ -103,6 +103,9 @@ + + + @@ -234,6 +237,10 @@ + + + + diff --git a/tex/context/interface/mkiv/i-hspace.xml b/tex/context/interface/mkiv/i-hspace.xml index 878063106..222317468 100644 --- a/tex/context/interface/mkiv/i-hspace.xml +++ b/tex/context/interface/mkiv/i-hspace.xml @@ -87,8 +87,6 @@ - - @@ -111,11 +109,11 @@ - + - + - + @@ -123,7 +121,7 @@ - + @@ -131,7 +129,7 @@ - + @@ -139,7 +137,7 @@ - + @@ -147,7 +145,7 @@ - + @@ -161,29 +159,29 @@ - + - + - + - + - + - + diff --git a/tex/context/interface/mkiv/i-hyphenation.xml b/tex/context/interface/mkiv/i-hyphenation.xml index 4ab4fe1d8..5437c81c0 100644 --- a/tex/context/interface/mkiv/i-hyphenation.xml +++ b/tex/context/interface/mkiv/i-hyphenation.xml @@ -261,4 +261,16 @@ + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-itemgroup.xml b/tex/context/interface/mkiv/i-itemgroup.xml index 6d687f381..81fc3ba5a 100644 --- a/tex/context/interface/mkiv/i-itemgroup.xml +++ b/tex/context/interface/mkiv/i-itemgroup.xml @@ -163,6 +163,8 @@ + + @@ -353,6 +355,8 @@ + + diff --git a/tex/context/interface/mkiv/i-linefiller.xml b/tex/context/interface/mkiv/i-linefiller.xml index aeb14046d..74803cbe5 100644 --- a/tex/context/interface/mkiv/i-linefiller.xml +++ b/tex/context/interface/mkiv/i-linefiller.xml @@ -29,9 +29,14 @@ - - + + + @@ -47,9 +52,15 @@ - + + + + + + + + + @@ -59,15 +70,6 @@ - - - - - - - - - diff --git a/tex/context/interface/mkiv/i-lua.xml b/tex/context/interface/mkiv/i-lua.xml index 94f25d0f7..424622507 100644 --- a/tex/context/interface/mkiv/i-lua.xml +++ b/tex/context/interface/mkiv/i-lua.xml @@ -172,6 +172,13 @@ + + + + + + + @@ -184,10 +191,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-marking.xml b/tex/context/interface/mkiv/i-marking.xml index 84273ee3b..8eb17f6ed 100644 --- a/tex/context/interface/mkiv/i-marking.xml +++ b/tex/context/interface/mkiv/i-marking.xml @@ -52,7 +52,10 @@ - + + + + diff --git a/tex/context/interface/mkiv/i-mathmatrix.xml b/tex/context/interface/mkiv/i-mathmatrix.xml index d22e8141f..3b8076407 100644 --- a/tex/context/interface/mkiv/i-mathmatrix.xml +++ b/tex/context/interface/mkiv/i-mathmatrix.xml @@ -70,13 +70,19 @@ - + - + + + + + + + diff --git a/tex/context/interface/mkiv/i-note.xml b/tex/context/interface/mkiv/i-note.xml index b76335765..bd1ebca24 100644 --- a/tex/context/interface/mkiv/i-note.xml +++ b/tex/context/interface/mkiv/i-note.xml @@ -672,7 +672,7 @@ - + diff --git a/tex/context/interface/mkiv/i-pagenumber.xml b/tex/context/interface/mkiv/i-pagenumber.xml index 47563984e..ae3f38cd3 100644 --- a/tex/context/interface/mkiv/i-pagenumber.xml +++ b/tex/context/interface/mkiv/i-pagenumber.xml @@ -102,6 +102,7 @@ + diff --git a/tex/context/interface/mkiv/i-parwrapper.xml b/tex/context/interface/mkiv/i-parwrapper.xml new file mode 100644 index 000000000..2cb5ee071 --- /dev/null +++ b/tex/context/interface/mkiv/i-parwrapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf index 97b40da43..2e51059b1 100644 Binary files a/tex/context/interface/mkiv/i-readme.pdf and b/tex/context/interface/mkiv/i-readme.pdf differ diff --git a/tex/context/interface/mkiv/i-replacement.xml b/tex/context/interface/mkiv/i-replacement.xml index 8e21c1f17..dec893bef 100644 --- a/tex/context/interface/mkiv/i-replacement.xml +++ b/tex/context/interface/mkiv/i-replacement.xml @@ -7,7 +7,7 @@ - + @@ -18,6 +18,8 @@ + + diff --git a/tex/context/interface/mkiv/i-setup.xml b/tex/context/interface/mkiv/i-setup.xml index fcfed31bf..0cfb216bd 100644 --- a/tex/context/interface/mkiv/i-setup.xml +++ b/tex/context/interface/mkiv/i-setup.xml @@ -167,4 +167,10 @@ + + + + + + diff --git a/tex/context/interface/mkiv/i-synonym.xml b/tex/context/interface/mkiv/i-synonym.xml index ca3053fe4..8bc9ed87e 100644 --- a/tex/context/interface/mkiv/i-synonym.xml +++ b/tex/context/interface/mkiv/i-synonym.xml @@ -91,6 +91,10 @@ + + + + diff --git a/tex/context/interface/mkiv/i-system.xml b/tex/context/interface/mkiv/i-system.xml index 08a4a917d..72b51760d 100644 --- a/tex/context/interface/mkiv/i-system.xml +++ b/tex/context/interface/mkiv/i-system.xml @@ -1619,8 +1619,6 @@ - - @@ -1834,6 +1832,18 @@ + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-vspace.xml b/tex/context/interface/mkiv/i-vspace.xml index e79e4e736..653ae169e 100644 --- a/tex/context/interface/mkiv/i-vspace.xml +++ b/tex/context/interface/mkiv/i-vspace.xml @@ -106,6 +106,18 @@ + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-xml.xml b/tex/context/interface/mkiv/i-xml.xml index d911b58c5..5c63416d7 100644 --- a/tex/context/interface/mkiv/i-xml.xml +++ b/tex/context/interface/mkiv/i-xml.xml @@ -726,16 +726,7 @@ - - - - - - - - - - + diff --git a/tex/context/modules/mkiv/m-chart.mkvi b/tex/context/modules/mkiv/m-chart.mkvi index e1ecd3f0c..4dee9c7ef 100644 --- a/tex/context/modules/mkiv/m-chart.mkvi +++ b/tex/context/modules/mkiv/m-chart.mkvi @@ -276,7 +276,7 @@ \let\location \FLOW_location \let\text \FLOW_text \let\label \FLOW_label - \let\comment \FLOW_comment + \overloaded\let\comment \FLOW_comment \let\exit \FLOW_exit \let\connection \FLOW_connection \let\include \FLOW_include diff --git a/tex/context/modules/mkiv/m-gnuplot.mkxl b/tex/context/modules/mkiv/m-gnuplot.mkxl index 2077b1741..e844edd1b 100644 --- a/tex/context/modules/mkiv/m-gnuplot.mkxl +++ b/tex/context/modules/mkiv/m-gnuplot.mkxl @@ -14,7 +14,7 @@ %D This is a variant on the \GNUPLOT\ terminal code. At some point (when there is a %D reason) I will make a proper environment that can be used for embedded code. -\unexpanded\def\includegnuplotsvgfile[#1]% +\permanent\protected\def\includegnuplotsvgfile[#1]% {\hbox\bgroup \ctxlua{metapost.startsvghashing()}% \includesvgfile[#1]% diff --git a/tex/context/modules/mkiv/m-timing.mkxl b/tex/context/modules/mkiv/m-timing.mkxl index 97f13a700..3edfd14e2 100644 --- a/tex/context/modules/mkiv/m-timing.mkxl +++ b/tex/context/modules/mkiv/m-timing.mkxl @@ -56,7 +56,7 @@ end \ctxlua{luatex.registerstopactions(function() moduledata.progress.save() end)} \stopnotmode -\unexpanded\def\ShowNamedUsage#1#2#3% +\permanent\protected\def\ShowNamedUsage#1#2#3% {\setbox\scratchbox\vbox\bgroup \startMPcode{doublefun} begingroup ; save p, q, b, h, w ; @@ -103,11 +103,11 @@ end \stoplinecorrection \fi} -\unexpanded\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}} -\unexpanded\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",".*", "variables: elapsed")}} -\unexpanded\def\ShowMemoryUsage #1{\ctxlua{moduledata.progress.show("#1","memory:.*","variables: elapsed")}} -\unexpanded\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1","nodes:.*", "variables: elapsed")}} -\unexpanded\def\ShowFilteredUsage#1#2{\ctxlua{moduledata.progress.show("#1","#2", "variables: elapsed")}} -\unexpanded\def\ShowSimpleUsage #1#2{\ctxlua{moduledata.progress.show("#1","#2")}} +\permanent\protected\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}} +\permanent\protected\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",".*", "variables: elapsed")}} +\permanent\protected\def\ShowMemoryUsage #1{\ctxlua{moduledata.progress.show("#1","memory:.*","variables: elapsed")}} +\permanent\protected\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1","nodes:.*", "variables: elapsed")}} +\permanent\protected\def\ShowFilteredUsage#1#2{\ctxlua{moduledata.progress.show("#1","#2", "variables: elapsed")}} +\permanent\protected\def\ShowSimpleUsage #1#2{\ctxlua{moduledata.progress.show("#1","#2")}} \endinput diff --git a/tex/context/modules/mkiv/s-system-macros.mkxl b/tex/context/modules/mkiv/s-system-macros.mkxl index 91aad763a..72fd3b7c2 100644 --- a/tex/context/modules/mkiv/s-system-macros.mkxl +++ b/tex/context/modules/mkiv/s-system-macros.mkxl @@ -22,7 +22,8 @@ \continueifinputfile{s-system-macros.mkxl} -\usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt] +% \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt] +\usemodule[article-basic] \setuplayout[tight] \setupbodyfont[5pt,tt] \setuppapersize [A4,landscape] @@ -97,22 +98,27 @@ local k = list[i] if check(k) then local v = create(k) + local mutable = v.mutable and "mutable" + local immutable = v.immutable and "immutable" local frozen = v.frozen and "frozen" local permanent = v.permanent and "permanent" - local immutable = v.immutable and "immutable" local primitive = v.primitive and "primitive" - local mutable = v.mutable and "mutable" - local noaligned = v.noaligned and "noaligned" local instance = v.instance and "instance" + local dealtwith = mutable or immutable or frozen or permanent or primitive -- beware: we can have combinations + local whatever = find(k,"^[a-z][a-z][a-z]+_") + local cscommand = gsub(v.cmdname or "","_"," ") + local undefined = cscommand == "undefined cs" + local marked = (dealtwith and "+") or (whatever and "-") or (instance and "!") +--if not marked then +if not marked and not find(k,"^[pvm]_") and not find(k,"^![tT]") then local parameters = v.parameters - local dealtwith = mutable or immutable or frozen or permanent or primitive -- beware: we can have combinations - local cscommand = gsub(v.cmdname or "","_"," ") - local whatever = find(k,"^[a-z][a-z][a-z]+_") - local filename = files[k] - local csname = context.escape(k) - ctx_NC() if dealtwith then context("+") - elseif whatever then context("-") - elseif instance then context("!") end + local noaligned = v.noaligned and "noaligned" + local filename = files[k] + local csname = context.escape(k) + if undefined then + marked = "?" + end + ctx_NC() if marked then context(marked) end ctx_NC() if primitive then ctx_bold(csname) else context(csname) end ctx_NC() if parameters then context(parameters > 0 and parameters or "-") end @@ -126,6 +132,7 @@ ctx_NC() if noaligned then context(noaligned) end ctx_NC() if filename then context(hashnames[filename]) end ctx_NC() ctx_NR() +end if visible then total = total + 1 if dealtwith then diff --git a/tex/context/modules/mkiv/s-system-tokens.mkxl b/tex/context/modules/mkiv/s-system-tokens.mkxl index 3b32b0627..b83a4f47b 100644 --- a/tex/context/modules/mkiv/s-system-tokens.mkxl +++ b/tex/context/modules/mkiv/s-system-tokens.mkxl @@ -15,8 +15,7 @@ \registerctxluafile{s-system-tokens}{} -\unexpanded\def\showsystemtokens - {\ctxlua{moduledata.system.tokens.showlist()}} +\permanent\protected\def\showsystemtokens{\ctxlua{moduledata.system.tokens.showlist()}} % can be public implementor \stopmodule diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 92109f0ce..38dcce9aa 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2020-11-19 11:23 +-- merge date : 2020-11-23 18:34 do -- begin closure to overcome local limits and interference -- cgit v1.2.3