diff options
Diffstat (limited to 'tex')
39 files changed, 5129 insertions, 131 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 17509ed5e..0f3413948 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.08 12:31} +\newcontextversion{2020.11.13 19:08} %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 2674b49a3..11b1da79f 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.08 12:31} +\edef\contextversion{2020.11.13 19:08} %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 e85272cea..17d730d24 100644 --- a/tex/context/base/mkii/mult-de.mkii +++ b/tex/context/base/mkii/mult-de.mkii @@ -283,6 +283,7 @@ \setinterfacevariable{intermezzo}{intermezzo} \setinterfacevariable{intext}{imtext} \setinterfacevariable{intro}{intro} +\setinterfacevariable{invertedshort}{invertedshort} \setinterfacevariable{italic}{italic} \setinterfacevariable{italicbold}{italicfett} \setinterfacevariable{item}{pos} @@ -386,6 +387,7 @@ \setinterfacevariable{nonumber}{nonumber} \setinterfacevariable{norepeat}{norepeat} \setinterfacevariable{normal}{normal} +\setinterfacevariable{normalshort}{normalshort} \setinterfacevariable{nospacing}{nospacing} \setinterfacevariable{nostopper}{nostopper} \setinterfacevariable{not}{nicht} @@ -453,6 +455,7 @@ \setinterfacevariable{rectangular}{rechteckig} \setinterfacevariable{reference}{referenz} \setinterfacevariable{referral}{merkmal} +\setinterfacevariable{region}{region} \setinterfacevariable{register}{register} \setinterfacevariable{regular}{regular} \setinterfacevariable{relative}{relativ} @@ -1805,7 +1808,7 @@ \setinterfacecommand{resetpath}{resetpath} \setinterfacecommand{resetperiodkerning}{resetperiodkerning} \setinterfacecommand{resetsystemmode}{resetsystemmode} -\setinterfacecommand{resettext}{resettextcontent} +\setinterfacecommand{resettextcontent}{resettextcontent} \setinterfacecommand{resetvisualizers}{resetvisualizers} \setinterfacecommand{restoreglobalbodyfont}{restoreglobalbodyfont} \setinterfacecommand{retestfeature}{retestfeature} diff --git a/tex/context/base/mkiv/anch-tab.mkxl b/tex/context/base/mkiv/anch-tab.mkxl index 075668ab7..0cc0b6dc9 100644 --- a/tex/context/base/mkiv/anch-tab.mkxl +++ b/tex/context/base/mkiv/anch-tab.mkxl @@ -87,10 +87,10 @@ \protected\def\tablepos {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}} -\permanent\tolerant\protected\def\tbXC [#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_XC [#1]\else\expandafter\NC\fi} -\permanent\tolerant\protected\def\tbGSC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi} -\permanent\tolerant\protected\def\tbGFC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi} -\permanent\tolerant\protected\def\tbGTC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi} +\permanent\tolerant\protected\def\tbXC [#1]{\anch_table_check_state\ifparameters#1\or\anch_tables_indeed_XC [#1]\else\expandafter\NC\fi} +\permanent\tolerant\protected\def\tbGSC[#1]{\anch_table_check_state\ifparameters#1\or\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi} +\permanent\tolerant\protected\def\tbGFC[#1]{\anch_table_check_state\ifparameters#1\or\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi} +\permanent\tolerant\protected\def\tbGTC[#1]{\anch_table_check_state\ifparameters#1\or\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi} \def\anch_table_check_state {\iftrialtypesetting diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 0b99557c4..0043f9277 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.08 12:31} +\newcontextversion{2020.11.13 19:08} %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 diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 9e91a2475..56a1bfa72 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.08 12:31} +\edef\contextversion{2020.11.13 19:08} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index c00ca6194..0ae593a20 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.11.08 12:31} +\edef\contextversion{2020.11.13 19:08} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -296,7 +296,7 @@ % \loadmarkfile{core-sys} \loadmarkfile{page-var} -\loadmkvifile{page-otr} +\loadmklxfile{page-otr} \loadmkxlfile{page-ini} \loadmarkfile{page-ins} \loadmarkfile{page-fac} @@ -305,8 +305,8 @@ \loadmarkfile{page-inf} \loadmarkfile{page-flt} \loadmkxlfile{page-bck} -\loadmarkfile{page-not} -\loadmarkfile{page-one} +\loadmkxlfile{page-not} +\loadmkxlfile{page-one} \loadmkxlfile{page-lay} \loadmkvifile{page-box} \loadmklxfile{page-txt} @@ -481,7 +481,7 @@ \loadmarkfile{math-def} % also saves some meanings \loadmkxlfile{math-ali} %loadmarkfile{math-arr} -\loadmkvifile{math-stc} +\loadmklxfile{math-stc} \loadmkxlfile{math-frc} \loadmarkfile{math-mis} \loadmarkfile{math-scr} @@ -495,15 +495,13 @@ %loadmarkfile{math-lan} \loadmkxlfile{math-toy} -%loadmarkfile{phys-dim} % moved to after typo-scr - \loadmarkfile{strc-mat} \loadmarkfile{chem-ini} \loadmkxlfile{chem-str} \loadmkxlfile{typo-scr} -\loadmarkfile{phys-dim} +\loadmkxlfile{phys-dim} \loadmarkfile{node-rul} % beware, defined \underbar so after math \loadmklxfile{font-sol} % font solutions @@ -518,9 +516,9 @@ \loadmkxlfile{grph-trf} \loadmkxlfile{grph-inc} -\loadmarkfile{grph-fig} -\loadmarkfile{grph-raw} -\loadmarkfile{grph-rul} +\loadmkxlfile{grph-fig} +\loadmkxlfile{grph-raw} +\loadmkxlfile{grph-rul} \loadmkxlfile{grph-pat} \loadmkxlfile{pack-box} @@ -578,7 +576,7 @@ \loadmarkfile{mlib-pps} \loadmarkfile{meta-pdf} \loadmarkfile{meta-blb} -\loadmarkfile{grph-epd} +\loadmkxlfile{grph-epd} \loadmarkfile{math-inc} % an experiment \loadmarkfile{publ-inc} % an experiment diff --git a/tex/context/base/mkiv/file-mod.mklx b/tex/context/base/mkiv/file-mod.mklx index 60237ae26..bf9b948bf 100644 --- a/tex/context/base/mkiv/file-mod.mklx +++ b/tex/context/base/mkiv/file-mod.mklx @@ -114,7 +114,7 @@ \fi \the\everysetupmodule} -\def\syst_modules_setup_yes[#name]#spacer[#parameters]% +\tolerant\def\syst_modules_setup_yes[#name]#spacer[#parameters]% {\scratchtoks\expandafter{\currentmoduleparameters}% \ifparameters \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% diff --git a/tex/context/base/mkiv/grph-epd.mkxl b/tex/context/base/mkiv/grph-epd.mkxl new file mode 100644 index 000000000..a0fcc51da --- /dev/null +++ b/tex/context/base/mkiv/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/mkiv/grph-fig.mkxl b/tex/context/base/mkiv/grph-fig.mkxl new file mode 100644 index 000000000..d28427d40 --- /dev/null +++ b/tex/context/base/mkiv/grph-fig.mkxl @@ -0,0 +1,357 @@ +%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]% <name> options settings-a + {\ifparameter#1\or\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}\fi} + +\tolerant\permanent\protected\def\typesetfile[#1]#*[#2]#*[#3]% <name> 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-raw.mkxl b/tex/context/base/mkiv/grph-raw.mkxl new file mode 100644 index 000000000..66194551b --- /dev/null +++ b/tex/context/base/mkiv/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/mkiv/grph-rul.mkxl b/tex/context/base/mkiv/grph-rul.mkxl new file mode 100644 index 000000000..ef65b1fe4 --- /dev/null +++ b/tex/context/base/mkiv/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/mkiv/math-ali.mkxl b/tex/context/base/mkiv/math-ali.mkxl index 72a9767d2..364760a0f 100644 --- a/tex/context/base/mkiv/math-ali.mkxl +++ b/tex/context/base/mkiv/math-ali.mkxl @@ -299,26 +299,33 @@ \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 @@ -700,6 +707,7 @@ \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 @@ -731,7 +739,7 @@ \noaligned\permanent\protected\def\math_cases_stop {\crcr \egroup - \popmacro\math_cases_NC + \pop_macro_math_cases_NC \egroup \mathcasesparameter\c!right \endgroup} @@ -890,6 +898,7 @@ \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 % diff --git a/tex/context/base/mkiv/math-stc.mklx b/tex/context/base/mkiv/math-stc.mklx new file mode 100644 index 000000000..2017fec1d --- /dev/null +++ b/tex/context/base/mkiv/math-stc.mklx @@ -0,0 +1,1378 @@ +%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] + +% We don't use overline and underline. This is one of the overlooked aspects of +% unicode cq. opentype math: why treat rules different than e.g. arrows and +% accents. It is a bit unfortunate that the opportunity to move math to new +% technologies happened outside the tex domain (and/or some aspects were kept while +% in fact they were side effects of limitations of traditional fonts). From the +% unicode aware tex engines' implementation point of view things could have been +% done a bit nicer but then: the community didn't seem to care too much and just +% has to follow now. +% +% Anyhow, we use a character based approach so that at least we get unicode stuff +% in the backend (okay, we still need to deal with some cut and paste issues but at +% least we now know what we deal with. + +% alternatively we can move the original to FE* + +\definemathoverextensible [\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<number> + +\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] [.....] + +%defineextensiblefiller [overbarfill] ["FE33E] % untested +%defineextensiblefiller [underbarfill] ["FE33F] % untested +\defineextensiblefiller [overbracefill] ["FE3DE] % untested +\defineextensiblefiller [underbracefill] ["FE3DF] % untested +\defineextensiblefiller [overparentfill] ["FE3DC] % untested +\defineextensiblefiller [underparentfill] ["FE3DD] % untested +\defineextensiblefiller [overbracketfill] ["FE3B4] % untested +\defineextensiblefiller [underbracketfill] ["FE3B5] % untested + +%D Extra: + +\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-stc.mkvi b/tex/context/base/mkiv/math-stc.mkvi index 19f710061..8f2a20440 100644 --- a/tex/context/base/mkiv/math-stc.mkvi +++ b/tex/context/base/mkiv/math-stc.mkvi @@ -16,12 +16,12 @@ \unprotect -%D WARNING: If the code here changes, the export needs to be checked! Stackers are rather -%D special because the order in mathml matters, so we flush in [base under over] order. We -%D also do some analysis at the \TEX\ end (passing the right variant). It's easy in the -%D export to deal with it but in the pdf stream less trivial as we don't actually analyze -%D there. - +%D 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: @@ -42,11 +42,11 @@ %D to support the traditional Latin Modern Virtual math font those were extended %D with a couple of virtual extensibles as well. %D -%D {\em For the moment we still have some mess here: we can deal with known dimensions, but -%D fillers (like \type {\rightarrowfil} don't work with \OPENTYPE\ extensibles yet -%D because there is no way to let them stretch like leaders. At some point \LUATEX\ -%D might provide a auto||fit||to||encapsulated||box and if not I will cook up a \LUA\ -%D based variant.} +%D {\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 @@ -54,9 +54,9 @@ %D %D In the end we have a more flexible mechanism which also handles text variants. -%D When wrapping up some math developments I decided to add mp support here -%D as well. A nice evening job with Joe Bonamassa performing live on the big -%D screen (real nice bluray's). See meta-imp-mat.mkiv for examples. +%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: % @@ -433,20 +433,15 @@ \ifcsname\??mathstackerslocation\p_location\endcsname \ifcase\csname\??mathstackerslocation\p_location\endcsname\relax \scratchdistance\zeropoint - \or - % top + \or % top \scratchdistance\zeropoint - \or - % high + \or % high \scratchdistance.25\htdp\scratchboxthree - \or - % centered + \or % centered \scratchdistance.5\htdp\scratchboxthree - \or - % low + \or % low \scratchdistance.75\htdp\scratchboxthree - \or - % bottom + \or % bottom \scratchdistance\htdp\scratchboxthree \else \scratchdistance\zeropoint @@ -1069,8 +1064,8 @@ %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): +% Be careful in choosing what accents you take (the code below uses a combining +% one): % % \startbuffer % % $\Umathaccent top 0 0 "20D7 {example}$ @@ -1224,15 +1219,15 @@ % We don't use overline and underline. This is one of the overlooked aspects of % unicode cq. opentype math: why treat rules different than e.g. arrows and % accents. It is a bit unfortunate that the opportunity to move math to new -% technologies happened outside the tex domain (and/or some aspects were kept -% while in fact they were side effects of limitations of traditional fonts). -% From the unicode aware tex engines' implementation point of view things -% could have been done a bit nicer but then: the community didn't seem to care -% too much and just has to follow now. +% technologies happened outside the tex domain (and/or some aspects were kept while +% in fact they were side effects of limitations of traditional fonts). From the +% unicode aware tex engines' implementation point of view things could have been +% done a bit nicer but then: the community didn't seem to care too much and just +% has to follow now. % -% Anyhow, we use a character based approach so that at least we get unicode -% stuff in the backend (okay, we still need to deal with some cut and paste -% issues but at least we now know what we deal with. +% Anyhow, we use a character based approach so that at least we get unicode stuff +% in the backend (okay, we still need to deal with some cut and paste issues but at +% least we now know what we deal with. % alternatively we can move the original to FE* diff --git a/tex/context/base/mkiv/meta-ini.mkxl b/tex/context/base/mkiv/meta-ini.mkxl index fecd07b9d..5422f3f1c 100644 --- a/tex/context/base/mkiv/meta-ini.mkxl +++ b/tex/context/base/mkiv/meta-ini.mkxl @@ -1228,10 +1228,10 @@ \permanent\let\stopstaticMPgraphic\relax \permanent\tolerant\protected\def\usestaticMPfigure[#1]#*[#2]% - {\ifsecondargument - \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% - \else + {\ifarguments\or \reuseMPgraphic{\??mpstaticgraphic#1}% + \else + \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% \fi} %D Goody for preventing overflows: diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 3685ab0a0..e94eb7772 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -331,6 +331,7 @@ return { "immediate", "immutable", "initcatcodetable", + "insertheights", "insertht", "instance", "integerdef", diff --git a/tex/context/base/mkiv/node-rul.mkiv b/tex/context/base/mkiv/node-rul.mkiv index 02e610de3..660c0d4e6 100644 --- a/tex/context/base/mkiv/node-rul.mkiv +++ b/tex/context/base/mkiv/node-rul.mkiv @@ -221,6 +221,8 @@ % \definebar[touchbar] [\c!method=0,\c!dy=-0.4,\c!offset=-0.0] % \definebar[touchbars] [touchbar] [\c!continue=\v!yes] +\pushoverloadmode + \let\normalmathoverbar \overbar \let\normalmathunderbar \underbar \let\normalmathoverstrike \overstrike @@ -230,6 +232,8 @@ \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] +\popoverloadmode + \definebar [\v!understrike] [\c!method=0, diff --git a/tex/context/base/mkiv/pack-box.mkxl b/tex/context/base/mkiv/pack-box.mkxl index 8ed2f65c0..b638dda3b 100644 --- a/tex/context/base/mkiv/pack-box.mkxl +++ b/tex/context/base/mkiv/pack-box.mkxl @@ -153,7 +153,7 @@ \ifarguments \dowithnextbox {\endgroup}% - \or + \else \dowithnextbox {\checkpositionoverlays \setbox\b_pack_anchors\box\nextbox diff --git a/tex/context/base/mkiv/page-mcl.mkxl b/tex/context/base/mkiv/page-mcl.mkxl index 6874e4fb2..112d9931d 100644 --- a/tex/context/base/mkiv/page-mcl.mkxl +++ b/tex/context/base/mkiv/page-mcl.mkxl @@ -125,15 +125,24 @@ \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 - {%%\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 + {\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 @@ -518,8 +527,11 @@ \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\relax} -\def\strc_itemgroups_stop_columns_new {\stopmulticolumns} +\def\strc_itemgroups_start_columns_new + {\startmulticolumns[\c!n=\itemgroupparameter\c!n]} + +\def\strc_itemgroups_stop_columns_new + {\stopmulticolumns} \installtexexperiment {itemize.columns} diff --git a/tex/context/base/mkiv/page-mix.mkiv b/tex/context/base/mkiv/page-mix.mkiv index b491a57a1..e38ad7406 100644 --- a/tex/context/base/mkiv/page-mix.mkiv +++ b/tex/context/base/mkiv/page-mix.mkiv @@ -125,6 +125,7 @@ \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 @@ -253,9 +254,15 @@ %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_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments + \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. @@ -300,9 +307,11 @@ \def\page_mix_enable_grid_snapping {\edef\p_grid{\mixedcolumnsparameter\c!grid}% + \setfalse\c_page_mix_grid_snapping \ifx\p_grid\empty % 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 @@ -795,7 +804,6 @@ % \hss % \egroup} - \unexpanded\def\page_mix_routine_continue {\bgroup \forgetall @@ -803,7 +811,7 @@ \setbox\b_page_mix_collected\vpack{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua) \page_mix_routine_construct\v!no \page_mix_routine_package - \page_otr_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments + \page_mix_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments \clf_mixflushrest \clf_mixcleanup \egroup} @@ -841,7 +849,7 @@ % 1 = we have stuff left, so flush and rebalance %writestatus\m!columns{flush continue}% \page_mix_routine_package - \page_otr_construct_and_shipout\box\b_page_mix_collected\zerocount % three arguments + \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 @@ -1005,7 +1013,7 @@ {\page_one_place_float_force} \unexpanded\def\page_mix_command_side_float_output - {\page_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments + {\page_mix_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments \unexpanded\def\page_mix_command_synchronize_side_floats {\page_sides_forget_floats} diff --git a/tex/context/base/mkiv/page-mix.mkxl b/tex/context/base/mkiv/page-mix.mkxl new file mode 100644 index 000000000..20f4ff3ca --- /dev/null +++ b/tex/context/base/mkiv/page-mix.mkxl @@ -0,0 +1,1092 @@ +%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.mkiv b/tex/context/base/mkiv/page-not.mkiv index d6f63846f..6d71539d5 100644 --- a/tex/context/base/mkiv/page-not.mkiv +++ b/tex/context/base/mkiv/page-not.mkiv @@ -22,23 +22,6 @@ \unprotect -% \def\checkbegincolumnfootnotes % should happen inside otr -% {\ifcase\c_strc_notes_page_location -% \erasenotebackup -% \else -% \flushnotes -% \savenotecontent -% \fi -% \savenotedata} - -% \def\checkendcolumnfootnotes -% {\restorenotedata -% \ifcase\c_strc_notes_page_location\else -% \restorenotecontent -% \fi} - -\let\checksinglecolumnfootnotes\relax - \newdimen\totalinsertionheight \unexpanded\def\settotalinsertionheight diff --git a/tex/context/base/mkiv/page-not.mkxl b/tex/context/base/mkiv/page-not.mkxl new file mode 100644 index 000000000..2d1c3fea6 --- /dev/null +++ b/tex/context/base/mkiv/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 + +\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.mkiv b/tex/context/base/mkiv/page-one.mkiv index f362a2fab..54e53035f 100644 --- a/tex/context/base/mkiv/page-one.mkiv +++ b/tex/context/base/mkiv/page-one.mkiv @@ -189,8 +189,7 @@ \scratchoffset\ht\b_page_one_contents \fi \setbox\b_page_one_bottom_notes\hpack - {\checksinglecolumnfootnotes % why this check? *** - \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% kerns makes notes sit on bottom % pack ? + {\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 diff --git a/tex/context/base/mkiv/page-one.mkxl b/tex/context/base/mkiv/page-one.mkxl new file mode 100644 index 000000000..3e7d3e2a8 --- /dev/null +++ b/tex/context/base/mkiv/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<n> \unvbox<n> % this one will be redone (checked) + {\bgroup + \strc_notes_check_if_bottom_present + \d_page_one_natural_depth\dp#2\relax + % we need to set the height as otherwise the shrink will not kick in so the following + % no longer applies: + % + % \setbox\b_page_one_contents\vbox \ifconditional\c_notes_bottom_present to \textheight \fi + % + \setbox\b_page_one_contents\vbox to \textheight % probably no pack + {\page_otr_command_flush_top_insertions + % this is messy ... we will provide a more tight area (no big deal as we can + % do that at the lua end) +% \parfillskip\zeropoint + \page_one_registered_text_area_a#1#2% \unvbox <box> + % + \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 new file mode 100644 index 000000000..797e31274 --- /dev/null +++ b/tex/context/base/mkiv/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 + +\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-pcl.mkiv b/tex/context/base/mkiv/page-pcl.mkiv index 09368c537..43ba4feb3 100644 --- a/tex/context/base/mkiv/page-pcl.mkiv +++ b/tex/context/base/mkiv/page-pcl.mkiv @@ -173,8 +173,7 @@ \scratchoffset\ht\b_page_one_contents \fi \setbox\b_page_one_bottom_notes\hpack - {\checksinglecolumnfootnotes % ? - \hsize\d_page_col_column_width + {\hsize\d_page_col_column_width \setupnotes[\c!width=\textwidth]% \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% \ht\b_page_one_contents \zeropoint diff --git a/tex/context/base/mkiv/phys-dim.mkxl b/tex/context/base/mkiv/phys-dim.mkxl new file mode 100644 index 000000000..3102650bf --- /dev/null +++ b/tex/context/base/mkiv/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/mkiv/spac-ver.lmt b/tex/context/base/mkiv/spac-ver.lmt index bfbcdf772..2cda39586 100644 --- a/tex/context/base/mkiv/spac-ver.lmt +++ b/tex/context/base/mkiv/spac-ver.lmt @@ -33,13 +33,12 @@ if not modules then modules = { } end modules ['spac-ver'] = { local next, type, tonumber = next, type, tonumber local gmatch, concat = string.gmatch, table.concat -local ceil, floor = math.ceil, math.floor +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 abs = math.abs local nodes = nodes local trackers = trackers @@ -51,6 +50,7 @@ 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 @@ -119,7 +119,6 @@ local a_snapvbox = attributes.private('snapvbox') local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local setlink = nuts.setlink @@ -943,7 +942,7 @@ do -- local cmd = token.create("vspacingfromtempstring") local cmd = token.create("vspacingpredefinedvalue") - local function handler(amount, keyword, detail) + local function handler(multiplier, keyword, detail) if not keyword then report_vspacing("unknown directive %a",s) else @@ -978,11 +977,11 @@ do flush() end else - amount = tonumber(amount) or 1 + local amount, stretch, shrink + multiplier = tonumber(multiplier) or 1 local sk = skip[keyword] if sk then - -- amount, keyword - b_done = true + -- multiplier, keyword -- best, for now, todo: runlocal with arguments -- expandmacro("vspacingpredefinedvalue",true,keyword) expandmacro(cmd,true,keyword) @@ -997,11 +996,21 @@ do -- setmacro("tempstring",keyword) -- runlocal(ctx_vspacingfromtempstring) -- - b_amount = b_amount + amount * texgetdimen("scratchdimen") - else -- no check - b_done = true - b_amount = b_amount + amount * toscaled(keyword) + amount, stretch, shrink = texgetglue("scratchskip") + 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 diff --git a/tex/context/base/mkiv/spac-ver.mkxl b/tex/context/base/mkiv/spac-ver.mkxl index 7a4688791..fd9b5d7dd 100644 --- a/tex/context/base/mkiv/spac-ver.mkxl +++ b/tex/context/base/mkiv/spac-ver.mkxl @@ -2581,7 +2581,7 @@ % experimental (for the moment only for hh and ws) %def\vspacingfromscratchtoks {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax} -\def\vspacingpredefinedvalue#1{\scratchdimen\dimexpr\csname\??vspacingamount#1\endcsname\relax} +\def\vspacingpredefinedvalue#1{\scratchskip\glueexpr\csname\??vspacingamount#1\endcsname\relax} %def\vspacingfromtempstring {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax} \let\spac_vspacing_yes_indeed_old\spac_vspacing_yes_indeed @@ -2606,21 +2606,29 @@ \protected\def\directvskip_new #1{\ifmmode\else\par\ifvmode\clf_injectvskip #1\relax\fi\fi} \protected\def\inhibitblank_new {\ifmmode\else\par\ifvmode\clf_injectdisable \fi\fi} -\installtexdirective - {vspacing.experimental} +% we need to ensure \enforced + +\def\spac_vspacing_temp_yes {\writestatus{vspacing}{enabling experimental handler}% - \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_new - \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_new + \enforced\let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_new + \enforced\let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_new \enforced\let\directvspacing\directvspacing_new \enforced\let\directvpenalty\directvpenalty_new \enforced\let\directvskip\directvskip_new \enforced\let\inhibitblank\inhibitblank_new} + +\def\spac_vspacing_temp_nop {\writestatus{vspacing}{disabling experimental handler}% - \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_old - \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_old + \enforced\let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_old + \enforced\let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_old \enforced\let\directvspacing\directvspacing_old \enforced\let\directvpenalty\directvpenalty_old \enforced\let\directvskip\directvskip_old \enforced\let\inhibitblank\inhibitblank_old} +\installtexdirective + {vspacing.experimental} + {\spac_vspacing_temp_yes} + {\spac_vspacing_temp_nop} + \protect \endinput diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex a71011ae0..df60b4a67 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 39b3b5304..fc2245599 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-num.mkxl b/tex/context/base/mkiv/strc-num.mkxl index 12306781b..1ddbd511d 100644 --- a/tex/context/base/mkiv/strc-num.mkxl +++ b/tex/context/base/mkiv/strc-num.mkxl @@ -104,72 +104,84 @@ \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} @@ -312,9 +324,9 @@ \permanent\tolerant\protected\def\convertedsubcounter[#1]#*[#2]#*[#3]% #2 can be n or n:m {\ifarguments\or - \strc_counters_converted[#1][]% + \convertedcounter[#1][]% \else - \strc_counters_converted[#1][\c!numbersegments=#2,#3]% + \convertedcounter[#1][\c!numbersegments=#2,#3]% \fi} \permanent\protected\def\doifdefinedcounter {\doifcommandhandler \??counter} diff --git a/tex/context/base/mkiv/tabl-tab.mkxl b/tex/context/base/mkiv/tabl-tab.mkxl index 7b26aca05..96eade4b4 100644 --- a/tex/context/base/mkiv/tabl-tab.mkxl +++ b/tex/context/base/mkiv/tabl-tab.mkxl @@ -1919,7 +1919,7 @@ \fi \bgroup \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax - \iffirstargument + \ifparameter#1\or \glet\m_tabl_table_hrule_color\empty \rawprocesscommalist[#1]\tabl_table_hrulecommand \ifempty\m_tabl_table_hrule_color\else @@ -1969,7 +1969,7 @@ {\tabl_tables_chuck_auto_row \tabl_table_finish_row \noalign\bgroup - \blank[\iftok{#1}\emptytoks\c!NL\else#1\fi]% + \blank[\iftok{#1}\emptytoks\directtablesparameter\c!NL\else#1\fi]% \nobreak \egroup} diff --git a/tex/context/base/mkiv/type-ini.mklx b/tex/context/base/mkiv/type-ini.mklx index 97035f5cb..afbbfea47 100644 --- a/tex/context/base/mkiv/type-ini.mklx +++ b/tex/context/base/mkiv/type-ini.mklx @@ -254,7 +254,7 @@ % \definetypescriptsynonym[lbr][cmr] \permanent\tolerant\protected\def\definetypescriptsynonym[#name]#spacer[#synonym]% - {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi} + {\ifarguments\or\or\setevalue{\??typescriptsynonyms#name}{#synonym}\fi} \permanent\def\truetypescript#name% recursive so no \lastnamedcs {\ifcsname\??typescriptsynonyms#name\endcsname @@ -690,7 +690,7 @@ % \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!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} diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml index 54a91b1d6..828ef7138 100644 --- a/tex/context/interface/mkii/keys-de.xml +++ b/tex/context/interface/mkii/keys-de.xml @@ -286,6 +286,7 @@ <cd:variable name='intermezzo' value='intermezzo'/> <cd:variable name='intext' value='imtext'/> <cd:variable name='intro' value='intro'/> + <cd:variable name='invertedshort' value='invertedshort'/> <cd:variable name='italic' value='italic'/> <cd:variable name='italicbold' value='italicfett'/> <cd:variable name='item' value='pos'/> @@ -389,6 +390,7 @@ <cd:variable name='nonumber' value='nonumber'/> <cd:variable name='norepeat' value='norepeat'/> <cd:variable name='normal' value='normal'/> + <cd:variable name='normalshort' value='normalshort'/> <cd:variable name='nospacing' value='nospacing'/> <cd:variable name='nostopper' value='nostopper'/> <cd:variable name='not' value='nicht'/> @@ -456,6 +458,7 @@ <cd:variable name='rectangular' value='rechteckig'/> <cd:variable name='reference' value='referenz'/> <cd:variable name='referral' value='merkmal'/> + <cd:variable name='region' value='region'/> <cd:variable name='register' value='register'/> <cd:variable name='regular' value='regular'/> <cd:variable name='relative' value='relativ'/> @@ -1817,7 +1820,7 @@ <cd:command name='resetpath' value='resetpath'/> <cd:command name='resetperiodkerning' value='resetperiodkerning'/> <cd:command name='resetsystemmode' value='resetsystemmode'/> - <cd:command name='resettext' value='resettextcontent'/> + <cd:command name='resettextcontent' value='resettextcontent'/> <cd:command name='resetvisualizers' value='resetvisualizers'/> <cd:command name='restoreglobalbodyfont' value='restoreglobalbodyfont'/> <cd:command name='retestfeature' value='retestfeature'/> diff --git a/tex/context/modules/mkiv/s-system-macros.mkxl b/tex/context/modules/mkiv/s-system-macros.mkxl index 0a7b9c179..58360b4bf 100644 --- a/tex/context/modules/mkiv/s-system-macros.mkxl +++ b/tex/context/modules/mkiv/s-system-macros.mkxl @@ -115,14 +115,14 @@ ctx_NC() if primitive then ctx_bold(csname) else context(csname) end ctx_NC() if parameters > 0 then context(parameters) end ctx_NC() context(cscommand) - -- ctx_NC() if tolerant then context(tolerant) end - ctx_NC() if primitive then context(primitive) end - ctx_NC() if permanent then context(permanent) end - ctx_NC() if frozen then context(frozen) end - ctx_NC() if immutable then context(immutable) end - ctx_NC() if mutable then context(mutable) end - ctx_NC() if noaligned then context(noaligned) end - ctx_NC() if filename then context(hashnames[filename]) end + -- ctx_NC() if tolerant then context(tolerant) end + ctx_NC() if primitive then context(primitive) end + ctx_NC() if permanent then context(permanent) end + ctx_NC() if frozen then context(frozen) end + ctx_NC() if immutable then context(immutable) end + ctx_NC() if mutable then context(mutable) end + ctx_NC() if noaligned then context(noaligned) end + ctx_NC() if filename then context(hashnames[filename]) end ctx_NC() ctx_NR() if visible then total = total + 1 diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index da9e5bc11..dc2576979 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-08 12:31 +-- merge date : 2020-11-13 19:08 do -- begin closure to overcome local limits and interference |