diff options
Diffstat (limited to 'tex/context/base/supp-box.tex')
-rw-r--r-- | tex/context/base/supp-box.tex | 486 |
1 files changed, 368 insertions, 118 deletions
diff --git a/tex/context/base/supp-box.tex b/tex/context/base/supp-box.tex index abc14fc67..aa6f3a7d5 100644 --- a/tex/context/base/supp-box.tex +++ b/tex/context/base/supp-box.tex @@ -18,6 +18,12 @@ \writestatus{loading}{Context Support Macros / Boxes} \unprotect + +%D First a hack to make this module loadable in plain \TEX. + +\ifx\outer\relax \else + \def\newbox{\alloc@4\box\chardef\insc@unt} +\fi %D \macros %D {nextdepth} @@ -111,8 +117,7 @@ %D \stoptypen \def\getboxheight#1\of#2\box#3% - {#1=\ht#3% - \advance#1 by \dp#3\relax} + {#1=\ht#3\advance#1 by \dp#3\relax} %D \macros %D {doiftextelse, doiftext} @@ -183,6 +188,9 @@ \afterassignment\dododowithnextbox \setbox\nextbox} +\def\dododowithnextbox% + {\aftergroup\dodowithnextbox} + % Better but first to be checked: % %\long\def\dowithnextbox#1% @@ -190,9 +198,6 @@ % \afterassignment\dododowithnextbox % \setbox\nextbox} -\def\dododowithnextbox% - {\aftergroup\dodowithnextbox} - %D So in fact we get: %D %D \starttypen @@ -225,7 +230,29 @@ %D \stoptypen %D %D This alternative also accepts \type{\box0} and alike, but -%D we don't really need this functionality now. +%D we don't really need this functionality now. + +%D \macros +%D {dowithnextboxcontent} +%D +%D But, occasionally we do need to pass some local settings +%D without wanting to use additional grouping. Therefore we +%D provide: +%D +%D \starttypen +%D \dowithnextboxcontent{inside}{after}{box content} +%D \stoptypen + +\long\def\dowithnextboxcontent#1#2% inside, after + {\long\def\dodowithnextbox{#2}% + \def\dododowithnextbox{#1\aftergroup\dodowithnextbox}% + \afterassignment\dododowithnextbox + \setbox\nextbox} + +%D Now we can redefine \type {\dowithnextbox} as follows: + +\def\dowithnextbox% + {\dowithnextboxcontent{}} %D \macros %D {beginofshapebox, @@ -363,7 +390,7 @@ \newcount\shapecounter -\def\reshapebox#1% +\def\reshapebox#1% {\doreshapebox {#1} {\penalty\shapepenalty} @@ -376,50 +403,50 @@ \unvcopy\oldshapebox \setbox\newshapebox=\box\voidb@x \shapecounter=0 - \loop - \someshapelefttrue - \ifdim\lastskip=\!!zeropoint\relax - \ifdim\lastkern=\!!zeropoint\relax - \ifnum\lastpenalty=0 - \setbox\shapebox=\lastbox - \ifvoid\shapebox - \unskip\unpenalty\unkern - \else - \ifdim\wd\shapebox=\shapesignal\relax - \someshapeleftfalse - \else - \shapecounter=0 - \setbox\newshapebox= - \normalvbox{#1\unvbox\newshapebox} - \fi - \fi - \else - \shapepenalty=\lastpenalty - \setbox\newshapebox= - \normalvbox{#2\unvbox\newshapebox} - \unpenalty - \fi + \doloop{\dodoreshapebox{#1}{#2}{#3}{#4}}% + \unvbox\newshapebox + \egroup} + +\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip + {\ifdim\lastskip=\!!zeropoint\relax + \ifdim\lastkern=\!!zeropoint\relax + \ifnum\lastpenalty=0 + \setbox\shapebox=\lastbox + \ifvoid\shapebox + \unskip\unpenalty\unkern + \else + \ifdim\wd\shapebox=\shapesignal\relax + \exitloop \else - \shapekern=\lastkern + \shapecounter=0 \setbox\newshapebox= - \normalvbox{#3\unvbox\newshapebox} - \unkern + \normalvbox{#1\unvbox\newshapebox} \fi - \else - \shapeskip=\lastskip - \setbox\newshapebox= - \normalvbox{#4\unvbox\newshapebox} - \unskip \fi - \ifnum\shapecounter>100 % can be less - \message{<<forced exit from shapebox>>}% - \someshapeleftfalse \else - \advance\shapecounter by 1 + \shapepenalty=\lastpenalty + \setbox\newshapebox= + \normalvbox{#2\unvbox\newshapebox} + \unpenalty \fi - \ifsomeshapeleft \repeat - \unvbox\newshapebox - \egroup} + \else + \shapekern=\lastkern + \setbox\newshapebox= + \normalvbox{#3\unvbox\newshapebox} + \unkern + \fi + \else + \shapeskip=\lastskip + \setbox\newshapebox= + \normalvbox{#4\unvbox\newshapebox} + \unskip + \fi + \ifnum\shapecounter>100 % can be less + \message{<<forced exit from shapebox>>}% + \exitloop + \else + \advance\shapecounter by 1 + \fi} \def\beginofshapebox% {\setbox\oldshapebox=\normalvbox @@ -493,6 +520,21 @@ %D \som \type{\shapekern} %D \som \type{\shapeskip} %D \stopopsomming + +%D \macros +%D {shapedhbox} +%D +%D When constructing a new box, using the content of \type +%D {\shapebox}, one can best use \type {\shapedhbox} instead +%D of \type {\hbox}, since it manages the height and depth of +%D the line. + +\def\shapedhbox% + {\dowithnextbox + {\ht\nextbox=\!!zeropoint + \dp\nextbox=\!!zeropoint + \box\nextbox} + \hbox} %D \macros %D {hyphenatedword, @@ -586,32 +628,48 @@ %D third argument into account, which leads to a bit more %D complex macro than needed at first sight. +% \def\dodoboundtext#1% +% {\setbox0=\hbox{\unhcopy0 #1}% +% \ifdim\wd0>\dimen0 +% \let\dodoboundtext=\gobbleoneargument +% \else +% #1\relax +% \fi} +% +% \def\doboundtext#1#2#3% +% {\hbox +% {\setbox0=\hbox{#1}% +% \dimen0=#2\relax +% \ifdim\wd0>\dimen0 +% \setbox2=\hbox{#3}% +% \advance\dimen0 by -\wd2 +% \setbox0=\hbox{}% +% \processtokens +% {\dodoboundtext} +% {\dodoboundtext} +% {} +% {\space} +% {#1}% +% \box2 +% \else +% \box0 +% \fi}} + \def\dodoboundtext#1% - {\setbox0=\hbox{\unhcopy0 #1}% - \ifdim\wd0>\dimen0 - \let\dodoboundtext=\gobbleoneargument - \else - #1\relax - \fi} + {\setbox2=\hbox{#1}% + \advance\dimen0 by -\wd2 + \ifdim\dimen0>\!!zeropoint\relax#1\fi}% \def\doboundtext#1#2#3% {\hbox {\setbox0=\hbox{#1}% \dimen0=#2\relax \ifdim\wd0>\dimen0 - \setbox2=\hbox{#3}% - \advance\dimen0 by -\wd2 - \setbox0=\hbox{}% - \processtokens - {\dodoboundtext} - {\dodoboundtext} - {} - {\space} - {#1}% - \box2 - \else - \box0 - \fi}} + \setbox0=\hbox{#3}% + \advance\dimen0 by -\wd0 + \handletokens#1\with\dodoboundtext + \fi + \box0}} %D \macros %D {limitatetext} @@ -630,33 +688,104 @@ \ifx\fakecompoundhyphen\undefined \let\fakecompoundhyphen\relax \fi +%D The simple alternative is as follows: +%D +%D \starttypen +%D \unexpanded\def\limitatetext% +%D {\bgroup % evt \setstrut +%D \fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! ! +%D \dowithnextbox\dolimitatetext\hbox} +%D +%D \def\dolimitatetext#1#2% +%D {\doifelsenothing{#1} +%D {\unhbox\nextbox} +%D {\widowpenalty=0 +%D \clubpenalty=0 +%D \scratchdimen=#1\relax +%D \ifdim\wd\nextbox>\scratchdimen +%D \setbox\scratchbox=\hbox{ #2}% +%D \advance\scratchdimen by -\wd\scratchbox +%D \setbox\nextbox=\vbox +%D {\hsize=\scratchdimen +%D \hfuzz\maxdimen +%D \veryraggedright +%D \strut\unhcopy\nextbox}% +%D \ifdim\ht\nextbox>\ht\strutbox \else +%D \setbox\scratchbox\null % overfull and not split +%D \fi +%D \setbox\nextbox=\vbox % if omitted: missing brace reported +%D {\splittopskip=\openstrutheight +%D \setbox\nextbox=\vsplit\nextbox to \ht\strutbox +%D \unvbox\nextbox +%D \setbox\nextbox=\lastbox +%D \global\setbox1=\hbox +%D {\unhbox\nextbox\unskip\kern\!!zeropoint\box\scratchbox\unskip}}% +%D \unhbox1 +%D \else +%D \unhbox\nextbox +%D \fi}% +%D \egroup} +%D \stoptypen +%D +%D The next alternative accepts a negative width. A negative +%D value crops the beginning. The macro thereby becomes less +%D readable, which is why we kept the original here too. + \unexpanded\def\limitatetext% - {\bgroup + {\bgroup % evt \setstrut + \fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! ! \dowithnextbox\dolimitatetext\hbox} - + \def\dolimitatetext#1#2% {\doifelsenothing{#1} {\unhbox\nextbox} - {\fakecompoundhyphen - \widowpenalty=0 + {\widowpenalty=0 \clubpenalty=0 \scratchdimen=#1\relax + \ifdim\scratchdimen<\!!zeropoint\relax % we'll take the last line + \donefalse + \scratchdimen=-\scratchdimen + \else + \donetrue + \fi \ifdim\wd\nextbox>\scratchdimen - \setbox\scratchbox=\hbox{ #2}% + \setbox\scratchbox=\hbox{\ifdone\space#2\else#2\space\fi}% \advance\scratchdimen by -\wd\scratchbox + \setbox0=\box\nextbox \setbox\nextbox=\vbox {\hsize=\scratchdimen \hfuzz\maxdimen \veryraggedright - \strut\unhbox\nextbox}% - \setbox\nextbox=\vbox % if omitted: missing brace reported - {\splittopskip=\openstrutheight - \setbox\nextbox=\vsplit\nextbox to \ht\strutbox - \unvbox\nextbox - \setbox\nextbox=\lastbox - \global\setbox1=\hbox - {\unhbox\nextbox\unskip\kern\!!zeropoint\box\scratchbox\unskip}}% - \unhbox1 + \strut + \ifdone \else + \parfillskip=\!!zeropoint + \rightskip=\!!zeropoint + \hskip\!!zeropoint \!!plus 1\!!fill % \hsize + \fi + \unhcopy0}% + \ifdim\ht\nextbox>\ht\strutbox + \setbox\nextbox=\vbox % if omitted: missing brace reported + {\splittopskip=\openstrutheight + \ifdone + \setbox\nextbox=\vsplit\nextbox to \ht\strutbox + \else + \doloop + {\setbox0=\vsplit\nextbox to \ht\strutbox + \ifdim\ht\nextbox>\ht\strutbox \else \exitloop \fi}% + \fi + \unvbox\nextbox + \setbox\nextbox=\lastbox + \global\setbox1=\hbox + {\ifdone + \unhbox\nextbox\unskip\kern\!!zeropoint\box\scratchbox + \else + \box\scratchbox\unhbox\nextbox + \fi + \unskip}}% + \unhbox1 + \else + \unhbox0 + \fi \else \unhbox\nextbox \fi}% @@ -757,6 +886,8 @@ %D In order to prevent problems with nested isolated words, we %D do process them, but only split at the outermost level. +\newskip\isolatedlastskip + \def\processisolatedwords#1#2% todo: vbox ipv hbox ivm afbreken! {\bgroup % todo: doloop \fakecompoundhyphen @@ -768,7 +899,7 @@ \global\let\localbetweenisolatedwords\betweenisolatedwords \setbox0=\hbox % we default to spaces, but from inside out {\ignorespaces#1% \localbetweenisolatedwords can be overruled - \xdef\isolatedlastskip{\the\lastskip}}% + \global\isolatedlastskip=\lastskip}% \setbox2=\vbox {%\hyphenpenalty10000 % this one fails in \url breaking, \lefthyphenmin=\!!maxcard % but this trick works ok, due to them @@ -792,11 +923,20 @@ \vbox % outer \hbox needed {\unvbox4 % for nested use \setbox4=\lastbox - \hbox{#2{\hbox{\unhbox4}}}}}% - \ifdim\ht2>\!!zeropoint \localbetweenisolatedwords \repeat + \hbox{#2{\hbox + {\unhbox4 + \unskip\unpenalty % remove end of line stuff + \global\dimen1=\lastkern}}}}}% + \ifdim\ht2>\!!zeropoint\relax + \ifdim\dimen1=\compoundbreakpoint + \allowbreak + \else + \localbetweenisolatedwords + \fi + \repeat \unskip}% \unhbox0\unskip - \ifdim\isolatedlastskip=\!!zeropoint\else % added + \ifdim\isolatedlastskip=\!!zeropoint\relax\else % added \hskip\isolatedlastskip \fi \fi @@ -1003,45 +1143,41 @@ \advance\hsize by \scratchdimen \divide\hsize by #3\relax} +\newbox\rigidcolumnbox + \def\rigidcolumnbalance#1% - {\global\chardef\rigidcolumnbox=#1\relax - \ifnum\rigidcolumns=1 - \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi\rigidcolumnbox + {\ifnum\rigidcolumns=1 % tzt ook h/d correctie + \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax \else - \hbox to \savedrigidhsize % was \hsize - {\vbadness=10000 - \tabskip\!!zeropoint + \vbox + {\forgetall + \dontcomplain \setbox\rigidcolumnbox=\vbox - {\unvbox\rigidcolumnbox - \unpenalty\removelastskip}% get rid of \blank's - %\splittopskip=\openstrutheight - \splittopskip=\!!zeropoint - %\scratchdimen=\ht\rigidcolumnbox % sensitive for overflow - %\divide\scratchdimen by \rigidcolumns % therefore we need the hack: - \scratchdimen=1pt - \divide\scratchdimen by \rigidcolumns - \expanded{\scratchdimen=\withoutpt{\the\scratchdimen}\ht\rigidcolumnbox}% - \advance\scratchdimen by \ht\strutbox - \valign{##\vfill\cr\dorigidcolumnsplits}}% - \fi} - -\def\dorigidcolumnsplits% - {\ifnum\rigidcolumns>0 - \setbox\scratchbox=\vsplit\rigidcolumnbox to \scratchdimen - \hbox to \hsize - \bgroup - \ifalignrigidcolumns - \vbox to \ifstretchrigidcolumns\vsize\else\scratchdimen\fi - {\unvbox\scratchbox}% - \else - \vbox{\unvbox\scratchbox}% - \fi - \hss - \egroup - \doglobal\decrement\rigidcolumns - \cr - \ifnum\rigidcolumns>0\noalign{\hfil}\fi - \expandafter\dorigidcolumnsplits + {\line{}\goodbreak\unvbox#1\removebottomthings}% + \splittopskip=\openstrutheight + \setbox\scratchbox=\vsplit\rigidcolumnbox to \!!zeropoint + \scratchdimen=\ht\rigidcolumnbox + \divide\scratchdimen by \rigidcolumns + \getnoflines\scratchdimen + \scratchdimen=\noflines\lineheight + \setbox\scratchbox=\hbox to \savedrigidhsize + {\dorecurse{\rigidcolumns} + {\setbox\scratchbox=\vsplit\rigidcolumnbox to \scratchdimen + \dp\scratchbox=\openstrutdepth + \setbox\scratchbox=\vtop + \ifalignrigidcolumns to + \ifstretchrigidcolumns\vsize\else\scratchdimen\fi + \fi + {\unvbox\scratchbox}% + \wd\scratchbox=\hsize + \box\scratchbox + \hfill}% + \hfillneg}% + \advance\scratchdimen by -\openstrutdepth + \setbox\scratchbox\hbox{\raise\scratchdimen\box\scratchbox} + \dp\scratchbox=\openstrutdepth + \ht\scratchbox=\scratchdimen + \box\scratchbox} \fi} %D \macros @@ -1492,6 +1628,19 @@ \egroup} \hbox} +%D \macros +%D {lhbox,mhbox,rhbox} +%D +%D A few more boxes. + +\def\lhbox{\dowithnextbox{\hbox to \hsize{\box\nextbox\hss }}\hbox} +\def\mhbox{\dowithnextbox{\hbox to \hsize{\hss\box\nextbox\hss}}\hbox} +\def\rhbox{\dowithnextbox{\hbox to \hsize{\hss\box\nextbox }}\hbox} + +\let\lefthbox =\lhbox +\let\midhbox =\mhbox +\let\righthbox=\rhbox + %D \macros %D {boxofsize} %D @@ -1641,6 +1790,71 @@ \def\middlebox#1% {\hbox{\setbox0=\placedbox{#1}\boxoffset=-.5\wd0\rightbox{\box0}}} +%D \macros +%D {initializeboxstack,savebox,foundbox} +%D +%D At the cost of some memory, but saving box registers, we +%D have implemented a box repository. +%D +%D \starttypen +%D \initializeboxstack{one} +%D +%D \savebox{one}{a}{test a} +%D \savebox{one}{p}{test p} +%D \savebox{one}{q}{test q} +%D +%D \hbox{a:\foundbox{one}{a}} \par +%D \hbox{q:\foundbox{one}{q}} \par +%D \hbox{p:\foundbox{one}{p}} \par +%D \hbox{x:\foundbox{one}{x}} \par +%D \hbox{y:\foundbox{two}{a}} \par +%D \stoptypen + +\def\@@stackbox{boxstack:b:} +\def\@@stackmax{boxstack:m:} +\def\@@stacktag{boxstack:t:} + +\def\initializeboxstack#1% + {\ifundefined{\@@stackbox#1}% + \@EA\newbox\csname\@@stackbox#1\endcsname + \else + \@EA\global\@EA\setbox\csname\@@stackbox#1\endcsname\vbox{}% + \fi + % actually we should erase the old values + \setgvalue{\@@stackmax#1}{0}} + +\def\savebox#1#2% stack name + {\dowithnextbox + {\doifdefined{\@@stackbox#1} + {\@EA\doglobal\@EA\increment\csname\@@stackmax#1\endcsname + \setxvalue{\@@stacktag#2}{\csname\@@stackmax#1\endcsname}% + \global\setbox\csname\@@stackbox#1\endcsname=\vbox + {\forgetall + \setbox\scratchbox=\vbox{\box\nextbox} + \ht\scratchbox=\!!onepoint + \dp\scratchbox=\!!zeropoint + \unvbox\csname\@@stackbox#1\endcsname + \offinterlineskip + \allowbreak + \box\scratchbox}}}% + \vbox} + +\def\foundbox#1#2% + {\vbox + {\doifdefined{\@@stackbox#1} + {\doifdefined{\@@stacktag#2} + {\setbox\scratchbox=\vbox + {\splittopskip\!!zeropoint + \setbox0=\copy\csname\@@stackbox#1\endcsname + \dimen0=\getvalue{\@@stacktag#2}pt + \advance\dimen0 by -\!!onepoint + \setbox2=\vsplit0 to \dimen0 + \ifdim\ht0>\!!onepoint + \setbox0=\vsplit0 to \!!onepoint + \fi + \unvbox0\setbox0=\lastbox\unvbox0}% + \unvbox\scratchbox}}}} + %D \macros %D {removedepth, obeydepth} %D @@ -1654,6 +1868,42 @@ \def\obeydepth% {\par \removedepth \ifvmode \kern\dp\strutbox \fi} +%D \macros +%D {removebottomthings, removelastskip} +%D +%D A funny (but rather stupid) one, plus a redefinition. + +\def\removebottomthings% + {\dorecurse{5}{\unskip\unkern\unpenalty}} + +\def\removelastskip% \ifvmode the plain tex one \fi + {\ifvmode\ifdim\lastskip=\z@\else\vskip-\lastskip\fi\fi} + +%D \macros +%D {raisebox,lowerbox} +%D +%D Some more box stuff, related to positioning (under +%D construction). Nice stuff for a tips and tricks maps +%D article. +%D +%D \starttypen +%D \raisebox{100pt}\hbox{test} +%D \raisebox50pt\hbox{test} +%D \hsmash{\raisebox{100pt}\hbox{test}} +%D \stoptypen + +\def\doraiselowerbox#1#2% a nice trick us used to accept + {\def\next% % both direct and {} dimensions + {\dowithnextbox + {\setbox\nextbox=\hbox{#1\scratchdimen\box\nextbox}% + \ht\nextbox=\ht\strutbox + \dp\nextbox=\dp\strutbox + \box\nextbox}}% + \afterassignment\next\scratchdimen=#2} + +\def\raisebox{\doraiselowerbox\raise} +\def\lowerbox{\doraiselowerbox\raise} + % maybe some day we need this % % \def\appendvbox#1% % uses \box8 |