diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/pack-rul.mkiv')
-rw-r--r-- | Master/texmf-dist/tex/context/base/pack-rul.mkiv | 3585 |
1 files changed, 3585 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/pack-rul.mkiv b/Master/texmf-dist/tex/context/base/pack-rul.mkiv new file mode 100644 index 00000000000..26fdaadeaf5 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/pack-rul.mkiv @@ -0,0 +1,3585 @@ +%D \module +%D [ file=pack-rul, % was core-rul, +%D version=1998.10.16, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Ruled Content, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content} + +%D After a few months testing this solution is now added +%D to the core. This introduces a possible incompatibility +%D between \MKII\ and \MKIV\ but for the better. + +\registerctxluafile{pack-rul}{1.001} + +% old off new +% 4 lines oeps : 3.6 2.8 3.0 +% tufte 7.5 4.1 4.3 + +\unprotect + +%D We have removed the rather old and out dated raster methods. They +%D have not been used for ages. You can still find the old code in +%D the \MKII\ counterpart of this module. + +%D This module is rather optimized so sometimes readability has been +%D sacrisfied for speed. This is because the framing mechanism is used +%D all over the place. + +%D \macros +%D {linewidth, setuplinewidth} +%D +%D This module deals with rules (lines) in several ways. First +%D we introduce two macros that can be used to set some common +%D characteristics. +%D +%D \showsetup{setuplinewidth} +%D +%D The linewidth is available in \type{\linewidth}. The +%D preset value of .4pt equals the default hard coded \TEX\ +%D rule width. + +\newdimen\linewidth + +\def\dosetuplinewidth[#1]% + {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}} + +\def\setuplinewidth + {\dosingleargument\dosetuplinewidth} + +%D \macros +%D {ruledlinewidth, inheritruledlinewidth} +%D +%D Inside framed boxed we will use a private dimensions. As +%D an option one can let the linewidth inherit its value from +%D this one. + +\newdimen\ruledlinewidth \newif\ifinheritruledlinewidth + +%D \macros +%D {setupscreens} +%D +%D The previous macro uses a predefined constant +%D \type{\@@rsfactor}. This factor can be set by: +%D +%D \showsetup{setupscreens} + +\def\setupscreens + {\dodoubleargument\getparameters[\??rs]} + +%D We will communicate through module specific variables, current +%D framed parameters and some reserved dimension registers. + +\newdimen \frameddimenwd +\newdimen \frameddimenht +\newdimen \frameddimendp + +%D We don't have to stick to a \TEX\ drawn rule, but +%D also can use rounded or even fancier shapes, as we will +%D see later on. + +\def\dofilledbox + {\bgroup + \edef\@@framedfilledmod{\framedparameter\c!backgroundcorner}% + \ifx\@@framedfilledmod\v!rectangular + \dofilledlinedbox + \else\ifzeropt\dimexpr\framedparameter\c!backgroundradius\relax % just in case of .x\bodyfontsize + \dofilledlinedbox + \else + \dofilledroundbox + \fi\fi + \egroup} + +\def\dophantombox + {\hphantom{\dofilledbox}} + +\def\dofilledlinedbox + {\vrule\!!width\frameddimenwd\!!height\frameddimenht\!!depth\frameddimendp\relax}% + +\def\dostrokedroundbox + {\doif{\framedparameter\c!frame}\v!on\dodostrokedroundbox} + +\def\dodostrokedroundbox + {\bgroup + \edef\ovalmod{\framedparameter\c!framecorner}% + \ifx\ovalmod\v!round + \let\ovalmod\!!zerocount + \else + \edef\ovalmod{\number\ovalmod}% + \fi + \edef\ovalwid{\the\frameddimenwd}% + \edef\ovalhei{\the\frameddimenht}% + \edef\ovaldep{\the\frameddimendp}% + \edef\ovallin{\the\dimexpr\ruledlinewidth}% + \edef\ovalrad{\the\dimexpr\framedparameter\c!frameradius}% + \let\ovalstr\!!plusone + \let\ovalfil\!!zerocount +% \forcecolorhack + \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod + \egroup} + +\def\dofilledroundbox + {\bgroup + \edef\ovalmod{\framedparameter\c!backgroundcorner}% + \ifx\ovalmod\v!round + \let\ovalmod\!!zerocount + \else + \edef\ovalmod{\number\ovalmod}% + \fi + \edef\ovalwid{\the\frameddimenwd}% + \edef\ovalhei{\the\frameddimenht}% + \edef\ovaldep{\the\frameddimendp}% + \edef\ovallin{\the\dimexpr\ruledlinewidth\relax}% + \edef\ovalrad{\the\dimexpr\framedparameter\c!backgroundradius\relax}% + \let\ovalstr\!!zerocount + \let\ovalfil\!!plusone +% \forcecolorhack + \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod + \egroup} + +% a lot of weird corners +% +% \startTEXpage +% \dontleavehmode\framed +% [corner=0,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \vskip1em +% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \stopTEXpage + +%D The oval box is drawn using a special macro, depending on +%D the driver in use. + +\def\dograybox % avoid black rules when no gray + {\doifelsenothing{\framedparameter\c!backgroundscreen} + {\dophantombox} + {\raster[\framedparameter\c!backgroundscreen]{\dofilledbox}}} + +%D It won't be a surprise that we not only provide gray boxes, +%D but also colored ones. Here it is: + +\def\dobackgroundcolorbox + {\hbox{\faststartcolor[\framedbackgroundcolor]\dofilledbox\faststopcolor}} + %{\hbox{\doactivatecolor\framedbackgroundcolor\dofilledbox}} + +\def\docolorbox % can be more of \color[] -> \faststartcolor in mkiv + {\ifincolor + \edef\framedbackgroundcolor{\framedparameter\c!backgroundcolor}% + \ifx\framedbackgroundcolor\empty + \dophantombox + \else + \doifcolorelse\framedbackgroundcolor\dobackgroundcolorbox\dophantombox + \fi + \else + \dophantombox + \fi} + +%D \macros +%D {defineoverlay, doifoverlayelse, overlayoffset, +%D overlaywidth, overlayheight, overlaydepth, +%D overlaycolor, overlaylinecolor, overlaylinewidth} +%D +%D Before we define the macro that actually takes card of the +%D backgrounds, we introduce overlays. An overlay is something +%D that contrary to its name lays {\em under} the text. An +%D example of an overlay definition is: +%D +%D \startbuffer[tmp-1] +%D \defineoverlay +%D [fancy] +%D [{\externalfigure +%D [mp-cont.502] +%D [width=\overlaywidth, +%D height=\overlayheight]}] +%D \stopbuffer +%D +%D \typebuffer[tmp-1] +%D +%D That for instance can be uses in: +%D +%D \startbuffer[tmp-2] +%D \framed[backgroundachtergrond=fancy]{How Fancy!} +%D \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!} +%D \stopbuffer +%D +%D and looks like: +%D +%D \startlinecorrection +%D \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]} +%D \stoplinecorrection +%D +%D The formal definition is: +%D +%D \showsetup{defineoverlay} +%D +%D This macro's definition is a bit obscure, due the many +%D non||used arguments and the two step call that enable the +%D setting of the width, height and depth variables. +%D Multiple backgrounds are possible and are specified as: +%D +%D \starttyping +%D \framed[background={one,two,three}]{Three backgrounds!} +%D \stoptyping +%D +%D Most drawing packages only know width and height. Therefore +%D the dimensions have a slightly different meaning here: +%D +%D \startitemize[packed] +%D \item \type{\overlaywidth }: width of the overlay +%D \item \type{\overlayheight}: height plus depth of the overlay +%D \item \type{\overlaydepth }: depth of the overlay +%D \stopitemize +%D +%D The resulting box is lowered to the right depth. + +\def\overlaywidth {\the\hsize\space} % We preset the variables +\def\overlayheight {\the\vsize\space} % to some reasonable default +\let\overlaydepth \!!zeropoint % values. The attributes +\let\overlayoffset \!!zeropoint % of the frame can be (are) +\let\overlaycolor \empty % set somewhere else. +\let\overlaylinewidth \!!zeropoint % +\let\overlaylinecolor \empty % + +%D The next register is used to initialize overlays. + +\newtoks\everyoverlay + +%D An example of an initialization is the following (overlays +%D can contain text and be executed under an regime where +%D interlineskip is off). + +\appendtoks \oninterlineskip \to \everyoverlay + +\def\defineoverlay + {\dodoubleargument\dodefineoverlay} + +\def\dodefineoverlay[#1][#2]% + {\def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}% + \processcommalist[#1]\docommand} + +\prependtoks + \hsize\overlaywidth + \vsize\overlayheight +\to\everyoverlay + +\long\def\executedefinedoverlay#1#2% + {\bgroup + \setlayoutcomponentattribute\v!overlay{#1}% + \edef\overlaywidth {\the\frameddimenwd\space}% + \edef\overlayheight{\the\dimexpr\frameddimenht+\frameddimendp\relax\space}% + \edef\overlaydepth {\the\frameddimendp\space}% + \edef\overlaycolor {\framedparameter\c!backgroundcolor}% + %\edef\overlaycorner{\framedparameter\c!backgroundcorner}% + %\edef\overlayradius{\framedparameter\c!backgroundradius}% + \let\overlayoffset\backgroundoffset % we steal this one + \setbox\scratchbox\hbox{\lower\overlaydepth\hbox{\the\everyoverlay#2}}% + \setbox\scratchbox\hbox \layoutcomponentboxattribute + {\hskip-.5\dimexpr\wd\scratchbox-\overlaywidth \relax + \raise-.5\dimexpr\ht\scratchbox-\frameddimenht\relax % not overlayheight ! + \box\scratchbox}% + \wd\scratchbox\frameddimenwd + \ht\scratchbox\frameddimenht + \dp\scratchbox\frameddimendp + \box\scratchbox + \egroup} + +%D The empty case is: + +\let\executeoverlay\gobblesevenarguments + +%D For testing we provide: + +\def\doifoverlayelse#1% + {\ifcsname\??ov#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +%D We predefine two already familiar backgrounds: + +\setvalue{\??ov\v!screen}{\dograybox } +\setvalue{\??ov\v!color }{\docolorbox} + +% %D After all these preparations, the background macro does no +% %D bring to many surprises. One has to keep in mind that this +% %D macro starts up a call chain, depending on the background +% %D one needs: +% %D +% %D \startitemize[packed] +% %D \item a raster, color or user defined shape +% %D \item square or round corners +% %D \item a \TEX\ or driver based method +% %D \stopitemize +% %D +% %D The macro can be extended by adding commands to the token +% %D list register \type {\everybackgroundbox}. For this +% %D purpose, the name of the current background is available in +% %D \type {\currentbackgound}. + +%D The content of the box will be (temporary) saved in a box. We +%D also have an extra box for backgrounds. + +\newbox\framebox +\newbox\extraframebox + +\newtoks\everybackgroundbox + +\let\currentbackground\empty + +\def\dodobackgroundbox + {\bgroup + \ifcsname\??ov\currentbackground\endcsname + \the\everybackgroundbox + \setbox\extraframebox\hbox{\vbox{\moveleft\backgroundoffset\hbox{\csname\??ov\currentbackground\endcsname}}}% + \wd\extraframebox\zeropoint % \backgroundwidth + \ht\extraframebox\backgroundheight + \dp\extraframebox\backgrounddepth + \box\extraframebox % \hskip-\backgroundwidth + \fi + \egroup} + +\def\dododobackgroundbox#1,#2% #2 gobbles spaces + {\edef\currentbackground{#1}% + \ifx\currentbackground\s!unknown\else % use $ instead of s!unknown + \dodobackgroundbox\expandafter\dododobackgroundbox + \fi#2} + +\let\backgroundoffset\!!zeropoint +\let\backgrounddepth \!!zeropoint +\def\backgroundwidth {\the\hsize} +\def\backgroundheight{\the\vsize} + +\def\normalforegroundbox% fuzzy but needed hack, this \vss, otherwise + {\vbox to \backgroundheight{\vss\box\framebox\vss}}% vertical shift + +\def\dobackedbox + {\setbox\framebox\vbox + {\framedforgetall + \boxmaxdepth\maxdimen + \frameddimenwd\dimexpr\wd\framebox+2\!!framedbackgroundoffset\relax + \frameddimenht\dimexpr\ht\framebox+ \!!framedbackgroundoffset\relax + \frameddimendp\dimexpr\dp\framebox+ \!!framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax + \edef\backgroundoffset{\the\!!framedbackgroundoffset}% + \edef\backgroundwidth {\the\wd\framebox}% + \edef\backgroundheight{\the\ht\framebox}% + \edef\backgrounddepth {\the\dp\framebox}% + %\edef\foregroundbox{\box#1}% + \edef\component{\framedparameter\c!component}% + \ifx\component\empty + \resetlayoutcomponentattribute + \else + \setlayoutcomponentattribute\v!background\component + \fi + \let\foregroundbox\normalforegroundbox + \hbox to \backgroundwidth \layoutcomponentboxattribute % width in case 'foreground' is used as overlay + {\expandafter\dododobackgroundbox\framedbackground,\s!unknown,\relax % hm, messy .. look into it + \box\framebox\hss}}} + +%D One can explictly insert the foreground box. For that +%D purpose we introduce the overlay \type {foreground}. + +\defineoverlay[\v!foreground][\foregroundbox] + +%D We can specify overlays as a comma separated list of +%D overlays, a sometimes handy feature. + +%D Besides backgrounds (overlays) we also need some macros to +%D draw outlines (ruled borders). Again we have to deal with +%D square and round corners. The first category can be handled +%D by \TEX\ itself, the latter one depends on the driver. This +%D macro also support a negative offset. + +\def\dooutlinebox % we needed to move the color command in order to apply attributes properly + {\setbox\framebox\vbox % rules on top of box + {\frameddimenwd\dimexpr\wd\framebox+2\!!framedframeoffset\relax + \frameddimenht\dimexpr\ht\framebox+ \!!framedframeoffset\relax + \frameddimendp\dimexpr\dp\framebox+ \!!framedframeoffset+\framedparameter\c!framedepth\relax + \ifdim\frameddimendp<\zeropoint + \advance\frameddimenht \frameddimendp + \scratchdimen-\frameddimendp + \frameddimendp\zeropoint + \else + \scratchdimen\zeropoint + \fi + \setbox\extraframebox\hbox + {\doifsomething{\framedparameter\c!framecolor}{\color[\framedparameter\c!framecolor]}{\dostrokedbox}}% + \setbox\extraframebox\hbox + {\raise\scratchdimen\vbox + {\moveleft\!!framedframeoffset + \box\extraframebox}}% + \wd\extraframebox\wd\framebox + \ht\extraframebox\ht\framebox + \dp\extraframebox\dp\framebox + \hbox{\box\framebox\hskip-\wd\extraframebox\box\extraframebox}}} + +\def\dostrokedbox + {\edef\@@framedcornermod{\framedparameter\c!framecorner}% + \ifx\@@framedcornermod\v!rectangular + \dostrokedlinedbox + \else\ifzeropt\dimexpr\framedparameter\c!frameradius\relax % just in case of .x\bodyfontsize + \dostrokedlinedbox + \else + \dostrokedroundbox + \fi\fi} + +\def\dostrokedlinedbox + {\setbox\scratchbox\null + \wd\scratchbox\frameddimenwd + \ht\scratchbox\frameddimenht + \dp\scratchbox\frameddimendp + \setbox\scratchbox\vbox \bgroup + \csname t\@@frame@@\framedparameter\c!frame\framedparameter\c!topframe \endcsname + \hbox \bgroup + \csname l\@@frame@@\framedparameter\c!frame\framedparameter\c!leftframe \endcsname + \box\scratchbox + \csname r\@@frame@@\framedparameter\c!frame\framedparameter\c!rightframe \endcsname + \egroup + \csname b\@@frame@@\framedparameter\c!frame\framedparameter\c!bottomframe\endcsname + \egroup + \wd\scratchbox\frameddimenwd + \ht\scratchbox\frameddimenht + \dp\scratchbox\frameddimendp + \box\scratchbox} + +\def\@@frame@@{@@frame@@} + +% \setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth} +% \setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth} +% \setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth} +% \setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth} +% \setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth} +% \setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth} +% \setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth} + +\def\@@frame@@trule{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth} +\def\@@frame@@brule{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth} +\def\@@frame@@rrule{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth} +\def\@@frame@@lrule{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth} + +\letvalue{t\@@frame@@\v!on \v!on}\@@frame@@trule +\letvalue{t\@@frame@@\v!off\v!on}\@@frame@@trule +\letvalue{t\@@frame@@\v!on }\@@frame@@trule + +\letvalue{b\@@frame@@\v!on \v!on}\@@frame@@brule +\letvalue{b\@@frame@@\v!off\v!on}\@@frame@@brule +\letvalue{b\@@frame@@\v!on }\@@frame@@brule + +\letvalue{l\@@frame@@\v!on \v!on}\@@frame@@lrule +\letvalue{l\@@frame@@\v!off\v!on}\@@frame@@lrule +\letvalue{l\@@frame@@\v!on }\@@frame@@lrule + +\letvalue{r\@@frame@@\v!on \v!on}\@@frame@@rrule +\letvalue{r\@@frame@@\v!off\v!on}\@@frame@@rrule +\letvalue{r\@@frame@@\v!on }\@@frame@@rrule + +% no overlapping rules + +\def\@@frame@@trules{\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}\nointerlineskip\kern-\ruledlinewidth} +\def\@@frame@@brules{\kern-\ruledlinewidth\nointerlineskip\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}} +\def\@@frame@@rrules{\kern-\ruledlinewidth\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth} +\def\@@frame@@lrules{\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth\kern-\ruledlinewidth} + +% small is relatively new + +\letvalue{t\@@frame@@\v!small\v!small}\@@frame@@trules +\letvalue{t\@@frame@@\v!off \v!small}\@@frame@@trules +\letvalue{t\@@frame@@\v!small }\@@frame@@trules + +\letvalue{b\@@frame@@\v!small\v!small}\@@frame@@brules +\letvalue{b\@@frame@@\v!off \v!small}\@@frame@@brules +\letvalue{b\@@frame@@\v!small }\@@frame@@brules + +\letvalue{l\@@frame@@\v!small\v!small}\@@frame@@lrules +\letvalue{l\@@frame@@\v!off \v!small}\@@frame@@lrules +\letvalue{l\@@frame@@\v!small }\@@frame@@lrules + +\letvalue{r\@@frame@@\v!small\v!small}\@@frame@@rrules +\letvalue{r\@@frame@@\v!off \v!small}\@@frame@@rrules +\letvalue{r\@@frame@@\v!small }\@@frame@@rrules + +%D I condidered using the low level support command +%D \type{\ruledhbox}, but this would slow down processing by a +%D factor~3. + +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on] +% {} +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small] +% {} +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on] +% {} + +%D The next few macros are probably the most misused ones in +%D \CONTEXT. They deal with putting rules around boxes, provide +%D backgrounds, offer alignment features, and some more. We +%D start with defining some booleans. These give an impression +%D of what we are going to take into account. + +% todo: chardefs + +\newif\ifboxhasoffset +\newif\ifboxhaswidth +\newif\ifboxhasheight +\newif\ifboxhasformat +\newif\ifboxhasstrut +\newif\ifboxisoverlaid +\newif\ifboxhasframe +\newif\ifdelayedstrut +\newif\ifboxhasextraoffset + +%D We also need a few \DIMENSIONS: + +\newdimen\@@localoffset +\newdimen\@@globalwidth + +%D \macros +%D {framed, setupframed} +%D +%D Ruled boxes are typeset using \type{\framed}. This command +%D is quite versatile and, although some users will probably +%D seldom use it, one cannot overlook its features. +%D +%D \showsetup{setupframed} +%D \showsetup{framed} +%D +%D This general macro is a special version of an even more +%D general case, that can easily be linked into other macros +%D that need some kind of framing. The local version is called +%D with an extra parameter: the variable identifier. The reason +%D for passing this identifier between brackets lays in the +%D mere fact that this way we can use the optional argument +%D grabbers. + +\def\defaultframeoffset{.25ex} + +\def\presetlocalframed [#1]{\letvalue{#1\s!parent}\??oi} +\def\inheritlocalframed[#1]#2[#3]{\letvalue{#1\s!parent}#3} +\def\copylocalframed [#1]#2[#3]{\setvalue{#1\s!parent}{#3}} + +\presetlocalframed[\??ol] + +\newcount\framednesting + +\unexpanded\def\framed + {\bgroup + \advance\framednesting\plusone + \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol + \dodoubleempty\startlocalframed[\??ol:\the\framednesting]} + +\def\setupframed + {\dodoubleempty\dosetupframed} + +\def\dosetupframed + {\ifsecondargument + \@EA\dodoublesetupframed + \else + \@EA\dosinglesetupframed + \fi} + +\def\dosinglesetupframed[#1][#2]% + {\getparameters[\??ol][#1]} + +\def\dodoublesetupframed[#1][#2]% + {\bgroup + \let\dodoubleempty\empty + \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}% + \getvalue{#1}% + \egroup + \letvalue{#1}\globalredefinedframed} + +%D \startbuffer +%D \setupframed [framecolor=yellow] \framed{A} +%D \defineframed[myframed] [framecolor=blue] \myframed{B} +%D \setupframed [myframed] [framecolor=red] \myframed{C} +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \presetlocalframed[myframed] +%D \setuplocalframed[myframed][width=4cm,height=2cm] +%D \localframed[myframed][framecolor=green]{oeps} +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {ifinframed} +%D +%D The normal case first presets all parameters and next starts +%D looking for the user supplied ones. The first step is +%D omitted in the local case, because these are preset at +%D declaration time and keep their values unless explictly +%D changed. By presetting the variables everytime the normal +%D command is called, we can use this command nested, without +%D the unwanted side effect of inheritance. The boolean is +%D used to speed up the color stack. + +\newif\ifinframed + +\def\localframed + {\bgroup + \dodoubleempty\startlocalframed} + +%D The next one is faster on multiple backgrounds per page. No +%D dimensions can be set, only frames and backgrounds. + +\def\fastlocalframed[#1]#2[#3]#4% 3-4 + {\bgroup + \inframedtrue + \edef\@@framed{#1}% + \setbox\framebox\hbox{#4}% + \getparameters[\@@framed][#3]% no \expanded ! + \!!framedframeoffset\framedparameter\c!frameoffset + \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}% + \ifx\@@framedbackgroundoffset\v!frame + \!!framedbackgroundoffset\!!framedframeoffset + \else + \!!framedbackgroundoffset\@@framedbackgroundoffset + \fi + % not here, in calling macro: setups + \removeframedboxdepth +% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}% +% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi + \edef\overlaylinecolor{\framedparameter\c!framecolor}% + \edef\overlaylinewidth{\the\ruledlinewidth}% + \edef\@@localframing {\framedparameter\c!frame}% + \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else + \edef\framedrulethickness{\framedparameter\c!rulethickness}% + \ifx\framedrulethickness\empty\else + \ruledlinewidth\framedrulethickness\relax + \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi + \fi + \dooutlinebox % real or invisible frame + \fi \fi + \edef\framedbackground{\framedparameter\c!background}% + \ifx\framedbackground\empty\else\dobackedbox\fi + \restoreframedboxdepth + \box\framebox + \egroup} + +%D Here is another fast one: + +\def\localbackgroundframed#1#2#3#4% tag box wd ht + {\setbox#2\vbox\bgroup + \inframedtrue + \edef\@@framed{\??ma#1}% + \expandafter\def\csname\??ma#1\c!component\endcsname{#1}% + \expandafter\def\csname\??ma#1\c!width \endcsname{#3}% + \expandafter\def\csname\??ma#1\c!height \endcsname{#4}% + \!!framedframeoffset\framedparameter\c!frameoffset + \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}% + \ifx\@@framedbackgroundoffset\v!frame + \!!framedbackgroundoffset\!!framedframeoffset + \else + \!!framedbackgroundoffset\@@framedbackgroundoffset + \fi + \setbox\framebox\box#2% + \dp\framebox\zeropoint +% \removeframedboxdepth +% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}% +% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi + \edef\overlaylinecolor{\framedparameter\c!framecolor}% + \edef\overlaylinewidth{\the\ruledlinewidth}% + \edef\@@localframing {\framedparameter\c!frame}% + \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else + \edef\framedrulethickness{\framedparameter\c!rulethickness}% + \ifx\framedrulethickness\empty\else + \ruledlinewidth\framedrulethickness\relax + \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi + \fi + \dooutlinebox % real or invisible frame + \fi \fi + \edef\framedbackground{\framedparameter\c!background}% + \ifx\framedbackground\empty\else\dobackedbox\fi +% \restoreframedboxdepth + \box\framebox + \egroup} + +%D Before we go into details, we present (and implement) the +%D main framing routine. I saw no real reason for splitting the +%D next two macros into smaller pieces. The content will be +%D collected in a horizontal or vertical box with fixed or free +%D dimensions and specific settings concerning aligment and +%D offsets. +%D +%D In the first few lines, we pre||expand the frame and +%D background offsets. We do so, because the can be defined in +%D terms of the main offset. However, see for instance page +%D backgrounds, when \type {#2} sets the offset to \type +%D {overlay}, both offsets become invalid. +%D +%D Because it is used so often the he next macro is (and +%D looks) rather optimized. + +\let\postprocessframebox\relax + +\let\@@framed\s!unknown + +\def\framedparameter #1{\csname\doframedparameter\@@framed#1\endcsname} +\def\framedparameterhash#1{\doframedparameterhash \@@framed#1} + +\def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname#2\fi} +\def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi} + +\def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1#2\fi} +\def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi} + +% \def\s!root{root} % maybe configurable + +\def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1#2\fi} +\def\doframedrootparameter #1{\ifcsname\??oi#1\endcsname\??oi#1\else\s!empty\fi} + +\def\dosetframedattributes#1#2% style color + {\edef\fontattributehash {\framedparameterhash#1}% + \edef\colorattributehash{\framedparameterhash#2}% + \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi + \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi} + +% defaults, kind of isolated now + +\getparameters + [\??oi] + [\c!width=\v!fit, + \c!height=\v!broad, + %\c!lines=, + \c!offset=0.25ex, % \defaultframeoffset + \c!empty=\v!no, + \c!frame=\v!on, + %\c!topframe=, + %\c!bottomframe=, + %\c!leftframe=, + %\c!rightframe=, + \c!radius=.5\bodyfontsize, + \c!rulethickness=\linewidth, + \c!corner=\v!rectangular, + \c!depth=\zeropoint, + %\c!foregroundcolor=, + %\c!foregroundstyle=, + %\c!background=, + %\c!backgroundscreen=, + %\c!backgroundcolor=, + \c!backgroundoffset=\zeropoint, + %\c!framecolor=, + \c!frameoffset=\zeropoint, + \c!backgroundcorner=\framedparameter\c!corner, + \c!backgroundradius=\framedparameter\c!radius, + \c!backgrounddepth=\framedparameter\c!depth, + \c!framecorner=\framedparameter\c!corner, + \c!frameradius=\framedparameter\c!radius, + \c!framedepth=\framedparameter\c!depth, + %\c!component=, + %\c!align=, + \c!bottom=\vss, + %\c!top=, + \c!strut=\v!yes, + \c!autostrut=\v!yes, + \c!location=\v!normal, + %\c!orientation=, + \c!autowidth=\v!yes, + %\c!setups= +] + +\getparameters + [\??od] % for fast version + [\c!frame=\v!off, + \c!depth=\zeropoint, + \c!offset=\v!overlay, + %\c!component=, + \c!radius=.5\bodyfontsize, + \c!rulethickness=\linewidth, + \c!corner=\v!rectangular, + \c!backgroundoffset=\zeropoint, + \c!frameoffset=\zeropoint, + \c!backgroundcorner=\framedparameter\c!corner, + \c!backgroundradius=\framedparameter\c!radius, + \c!backgrounddepth=\framedparameter\c!depth, + \c!framecorner=\framedparameter\c!corner, + \c!frameradius=\framedparameter\c!radius, + \c!framedepth=\framedparameter\c!depth, + \c!location=\v!normal] + +% so far + +\newdimen\!!framedwidth +\newdimen\!!framedheight +\newdimen\!!framedscratch % so that users can use \scratchdimen +\newdimen\!!framedframeoffset +\newdimen\!!framedbackgroundoffset + +\let\setextraframedoffsets \relax +\let\applyextraframedoffsets\relax + +% todo: protect local \framednames + +\def\startlocalframed[#1][#2]% + {\bgroup + \inframedtrue + \edef\@@framed{#1}% + \ifsecondargument % faster + \getparameters[\@@framed][#2]% here ! + \fi + \!!framedframeoffset\framedparameter\c!frameoffset + \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}% + \ifx\@@framedbackgroundoffset\v!frame + \!!framedbackgroundoffset\!!framedframeoffset + \else + \!!framedbackgroundoffset\@@framedbackgroundoffset + \fi + % new, experimental dirty hook + \framedparameter\c!extras + % to get the right spacing + \edef\fontattributehash{\framedparameterhash\c!foregroundstyle}% + \ifx\fontattributehash\empty\else\dosetfontattribute \fontattributehash\c!foregroundstyle\fi + % beware, both the frame and background offset can be overruled + % + \edef\doframedsetups{\framedparameter\c!setups}% + \ifx\doframedsetups\empty\else + \edef\doframedsetups{\noexpand\setups[\doframedsetups]}% + \fi + % the next macros are visible + \edef\localoffset{\framedparameter\c!offset}% + \edef\localwidth {\framedparameter\c!width}% + \edef\localheight{\framedparameter\c!height}% + \edef\localformat{\framedparameter\c!align}% + \edef\localstrut {\framedparameter\c!strut}% + % these are not + \edef\@@localautostrut {\framedparameter\c!autostrut}% + \edef\@@localframing {\framedparameter\c!frame}% + \edef\@@locallocation {\framedparameter\c!location}% + \edef\@@localorientation{\framedparameter\c!orientation}% + % + \edef\@@localautowidth {\framedparameter\c!autowidth}% + % + \ifx\@@localframing\v!overlay % no frame, no offset, no framewidth + \boxhasframefalse + \let\localoffset\v!overlay + \else\ifx\@@localframing\v!none % no frame, no framewidth + \boxhasframefalse + \else + \boxhasframetrue + \fi\fi + \ifboxhasframe + \edef\framedrulethickness{\framedparameter\c!rulethickness}% + \ifx\framedrulethickness\empty\else + \ruledlinewidth\framedrulethickness\relax + \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi + \fi + \else + \ruledlinewidth\zeropoint + \fi + \ifx\localformat\empty + \boxhasformatfalse + \else + \boxhasformattrue + \dosetraggedcommand\localformat + \edef\dobeforeframedbox{\raggedtopcommand\framedparameter\c!top}% + \edef\doafterframedbox {\framedparameter\c!bottom\raggedbottomcommand}% + \fi + \ifx\localoffset\v!none + \boxhasoffsetfalse + \boxhasstrutfalse + \boxisoverlaidfalse + \@@localoffset\ruledlinewidth + \else\ifx\localoffset\v!overlay + % \ifx\@@localframing\v!no \boxhasframefalse \fi % test first + \boxhasoffsetfalse + \boxhasstrutfalse + \boxisoverlaidtrue + \@@localoffset\zeropoint + \else + \boxhasoffsettrue + \boxhasstruttrue + \boxisoverlaidfalse + \ifx\localoffset\v!default % new per 2-6-2000 + \let\localoffset\defaultframeoffset + \expandafter\let\csname\@@framed\c!offset\endcsname\defaultframeoffset + \else + \let\defaultframeoffset\localoffset + \fi + \@@localoffset\dimexpr\localoffset+\ruledlinewidth\relax + \fi\fi + \!!framedheight\zeropoint + \!!framedwidth \zeropoint + \ifx\localwidth\v!fit + \ifboxhasformat + \boxhaswidthtrue + \!!framedwidth\hsize + \else + \boxhaswidthfalse + \fi + \else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox + \ifboxhasformat + \boxhaswidthtrue + \!!framedwidth\hsize + \else + \boxhaswidthfalse + \fi + \else\ifx\localwidth\v!broad + \boxhaswidthtrue + \!!framedwidth\hsize + \else\ifx\localwidth\v!local + \boxhaswidthtrue + \setlocalhsize + \!!framedwidth\localhsize + \else + \boxhaswidthtrue + \!!framedwidth\localwidth + \fi\fi\fi\fi + \ifx\localheight\v!fit + \boxhasheightfalse % no longer: \boxhasstrutfalse + \else\ifx\localheight\v!broad + \boxhasheightfalse + \else + \boxhasheighttrue + \!!framedheight\localheight + \fi\fi + \ifboxhasheight + % obey user set height, also downward compatible + \else + \edef\@@framedlines{\framedparameter\c!lines}% + \ifx\@@framedlines\empty\else + \ifcase\@@framedlines\else + \!!framedheight\@@framedlines\lineheight + \edef\localheight{\the\!!framedheight}% + \boxhasheighttrue + \fi + \fi + \fi + % this is now an option: width=local + % + % \ifdim\!!framedwidth=\hsize + % \parindent\zeropoint + % \setlocalhsize + % \!!framedwidth\localhsize + % \fi + % i.e. disable (colsetbackgroundproblemintechniek) + \advance\!!framedwidth -2\@@localoffset + \advance\!!framedheight -2\@@localoffset + \ifx\localstrut\v!no + \boxhasstrutfalse + \else\ifx\localstrut\v!global + \setstrut + \else\ifx\localstrut\v!local + \setfontstrut + \else + \setstrut + \fi\fi\fi + \ifboxhasstrut + \let\localbegstrut\begstrut + \let\localendstrut\endstrut + \let\localstrut \strut + \else + \let\localbegstrut\pseudobegstrut % was: \relax + \let\localendstrut\pseudoendstrut % was: \relax + \let\localstrut \pseudostrut % was: \relax + %\ifboxhasheight\ifdim\!!framedheight<\strutht % saveguard + % \let\localbegstrut\relax % but not that + % \let\localstrut \relax % save after all + %\fi\fi + \fi + \ifx\@@localautostrut\v!yes + \let\delayedbegstrut\relax + \let\delayedendstrut\relax + \let\delayedstrut \relax + \else + \let\delayedbegstrut\localbegstrut + \let\delayedendstrut\localendstrut + \let\delayedstrut \localstrut + \let\localbegstrut \relax + \let\localendstrut \relax + \let\localstrut \relax + \fi + \ifboxhasheight + \let\\\vboxednewline + \ifboxhaswidth + \let\hairline\vboxedhairline + \ifboxhasformat + \let\next\doformatboxSomeFormat + \else + \let\next\doformatboxNoFormat + \fi + \else + \let\hairline\hboxedhairline + \ifboxhasformat + \let\next\doformatboxHeight + \else + \let\next\doformatboxVSize + \fi + \fi + \else + \ifboxhaswidth + \ifboxhasformat + \let\hairline\vboxedhairline + \let\\\vboxednewline + \let\next\doformatboxWidth + \else + \let\hairline\hboxedhairline + \let\\\hboxednewline + \let\next\doformatboxHSize + \fi + \else + \let\hairline\hboxedhairline + \let\\\hboxednewline + \let\next\doformatboxNoSize + \fi + \fi + \setextraframedoffsets + \edef\framedbackground{\framedparameter\c!background}% + \ifx\framedbackground\empty + \let\framedforgetall\forgetall + \else + \let\framedforgetall\relax + \forgetall + \fi + \edef\framedwidth {\ifdim\!!framedwidth >\zeropoint\the\!!framedwidth \else\!!zeropoint\fi}% a new feature, visible for user + \edef\framedheight{\ifdim\!!framedheight>\zeropoint\the\!!framedheight\else\!!zeropoint\fi}% a new feature, visible for user + \@@startframedorientation + \afterassignment\dodowithframebox + \setbox\framebox\next} + +\def\dowithframebox + {% moved : \let\postprocessframebox\relax + \stoplocalframed} + +\def\dodowithframebox + {\aftergroup\dowithframebox} + +\let\doafterframedbox \relax +\let\dobeforeframedbox\relax + +%D Carefull analysis of this macro will learn us that not all +%D branches in the last conditionals can be encountered, that +%D is, some assignments to \type{\next} will never occur. +%D Nevertheless we implement the whole scheme, if not for +%D future extensions. + +%D \macros +%D {ifreshapeframebox} +%D +%D The last few lines tell what to do after the content of the +%D box is collected and passed to the next macro. In the case +%D of a fixed width and centered alignment, the content is +%D evaluated and used to determine the most natural width. The +%D rest of the code deals with backgrounds and frames. + +\newif\ifreshapeframebox \reshapeframeboxtrue + +%D Beware: setting \type {top} and \type {bottom} to nothing, may +%D result in a frame that is larger that the given height! try: +%D +%D \starttyping +%D \framed +%D [height=3cm,top=,bottom=,offset=overlay] +%D {\strut test \shapefill \strut test} +%D \stoptyping +%D +%D This is intended behaviour and not a bug! One can always set +%D +%D \starttyping +%D ...,bottom=\kern0pt,... +%D \stoptyping + +\def\stoplocalframed + {\dontshowcomposition + \@@stopframedorientation % hm, wrong place ! should rotate the result (after reshape) + \handleframedlocator\c!before\@@locallocation + \ifboxhasformat + \ifx\@@localautowidth\v!force + \ifreshapeframebox\doreshapeframedbox\fi + \boxhaswidthfalse + \else + \ifx\localwidth\v!fit + \ifx\@@localautowidth\v!yes + \ifreshapeframebox\doreshapeframedbox\fi + \fi + \boxhaswidthfalse + \else\ifx\localwidth\v!fixed + \boxhaswidthfalse + \else + \resetshapeframebox + \fi\fi + \fi + \ifconditional\boxcontentneedsprocessing + \mkdoprocessboxcontents\framebox + \fi + \else + \resetshapeframebox + \fi + \ifboxhaswidth + \wd\framebox\!!framedwidth + \fi + \ifboxhasheight + \ht\framebox\!!framedheight + \fi + \doif{\framedparameter\c!empty}\v!yes\dosetfakedframebox + \ifboxhasextraoffset + \applyextraframedoffsets + \fi + \ifboxhasoffset + \dooffsetframebox + \fi + \ifboxisoverlaid \else + \dolocateframebox + \fi + \ifx\postprocessframebox\relax \else + \let\next\postprocessframebox + \let\postprocessframebox\relax % prevent nesting + \next\framebox + \fi + \edef\overlaylinecolor{\framedparameter\c!framecolor}% + \edef\overlaylinewidth{\the\ruledlinewidth}% \@@... + \ifboxhasframe % real or invisible frame + \dooutlinebox + \fi + \ifx\framedbackground\empty\else\dobackedbox\fi + \handleframedlocator\c!after\@@locallocation + \box\framebox + \egroup + \egroup} + +\def\dosetfakedframebox + {\setbox\scratchbox\null + \wd\scratchbox\wd\framebox + \ht\scratchbox\ht\framebox + \dp\scratchbox\dp\framebox + \setbox\framebox\box\scratchbox} + +% test: (saves one forgetall) +% +% \edef\framedbackground{\framedparameter\c!background}% +% \ifx\framedbackground\empty +% \let\framedforgetall\forgetall +% \else +% \let\framedforgetall\relax +% \forgetall +% \fi + +\def\installframedlocator#1#2#3% + {\setvalue{\??oi:\c!location:\c!before:#1}{#2}% + \setvalue{\??oi:\c!location:\c!after :#1}{#3}} + +\def\handleframedlocator#1#2% + {\csname\??oi:\c!location:#1:#2\endcsname} + +\def\doprelocframedbox#1% + {\scratchdimen\dimexpr#1+\ruledlinewidth\relax + \ifboxhasoffset + \advance\scratchdimen \framedparameter\c!offset + \fi + \scratchskip\dimexpr\ht\framebox-\scratchdimen\relax} + +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=hanging]{location\\equals\\hanging} +% \framed[width=2cm,align=middle,location=depth] {location\\equals\\depth} +% \framed[width=2cm,align=middle,location=height] {location\\equals\\height} +% B} +% \vskip2cm +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=low] {location\\equals\\low} +% \framed[width=2cm,align=middle,location=line] {location\\equals\\line} +% \framed[width=2cm,align=middle,location=high] {location\\equals\\high} +% B} +% \vskip2cm +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=top] {location\\equals\\top} +% \framed[width=2cm,align=middle,location=bottom] {location\\equals\\bottom} +% \framed[width=2cm,align=middle,location=lohi] {location\\equals\\lohi} +% \framed[width=2cm,align=middle,location=middle] {location\\equals\\middle} +% B} + +\installframedlocator \v!hanging % best with strut=no + {} + {\dp\framebox\ht\framebox + \ht\framebox\zeropoint} + +\installframedlocator \v!depth + {} + {\ht\framebox\dimexpr\ht\framebox-\strutdp\relax + \dp\framebox\strutdp + \box\framebox} + +\installframedlocator \v!height + {} + {\dp\framebox\dimexpr\ht\framebox-\strutht\relax + \ht\framebox\strutht + \box\framebox} + +\installframedlocator \v!high + {} + {\doprelocframedbox\strutht + \setbox\framebox\hbox{\lower\scratchskip\box\framebox}% + \ht\framebox\strutht + \dp\framebox\strutdp + \hbox{\box\framebox}} + +\installframedlocator \v!line + {} + {\setbox\framebox\hbox{\lower.5\ht\framebox\box\framebox}% + \ht\framebox.5\lineheight + \dp\framebox.5\lineheight + \hbox{\box\framebox}} + +\installframedlocator \v!low + {} + {\doprelocframedbox\strutdp + \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}% + \ht\framebox\strutht + \dp\framebox\strutdp + \box\framebox} + +\installframedlocator \v!top + {} + {\doprelocframedbox\strutht + \setbox\framebox\hbox{\lower\scratchskip\box\framebox}% + \ht\framebox\scratchdimen + \dp\framebox\scratchskip + \hbox{\box\framebox}} + +\installframedlocator \v!middle + {} + {\scratchdimen.5\ht\framebox + \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}% + \ht\framebox\scratchdimen + \dp\framebox\scratchdimen + \hbox{\box\framebox}} + +\installframedlocator \v!lohi + {\handleframedlocator\c!before\v!middle} + {\handleframedlocator\c!after \v!middle} + +\installframedlocator \v!bottom + {} + {\doprelocframedbox\strutdp + \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}% + \ht\framebox\scratchskip + \dp\framebox\scratchdimen + \hbox{\box\framebox}} + +\installframedlocator \v!keep % retains height/depth + {\removeframedboxdepth} + {\restoreframedboxdepth} + +% also used in fastlocalframed + +\newdimen\originalframedwd +\newdimen\originalframedht +\newdimen\originalframeddp + +\def\removeframedboxdepth + {\originalframedwd\wd\framebox + \originalframedht\ht\framebox + \originalframeddp\dp\framebox + \ifzeropt\originalframeddp\else\setbox\framebox\hbox{\raise\originalframeddp\box\framebox}\fi + \wd\framebox\originalframedwd + \ht\framebox\dimexpr\originalframedht+\originalframeddp\relax + \dp\framebox\zeropoint} + +\def\restoreframedboxdepth + {\ifzeropt\originalframeddp\else\setbox\framebox\hbox{\lower\originalframeddp\box\framebox}\fi + \wd\framebox\originalframedwd + \ht\framebox\originalframedht + \dp\framebox\originalframeddp} + +% \let\@@startframedorientation\relax +% \let\@@stopframedorientation \relax + +% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=180]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=270]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-90]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax} + +\def\@@startframedorientation + {\let\@@stopframedorientation \relax + \ifx\@@localorientation\empty\else + \ifcase\@@localorientation\else + \scratchcounter\@@localorientation + \divide\scratchcounter\plustwo + \ifodd\scratchcounter + \swapmacros\framedwidth \framedheight + \swapmacros\localwidth \localheight + \swapdimens\!!framedheight\!!framedwidth + \def\@@stopframedorientation{\@@dostopframedorientation\plusone}% + \else + \def\@@stopframedorientation{\@@dostopframedorientation\zerocount}% + \fi + \fi + \fi} + +\def\@@dostopframedorientation#1% + {\ifcase#1\else + \swapmacros\framedwidth \framedheight + \swapmacros\localwidth \localheight + \swapdimens\!!framedheight\!!framedwidth + \fi + \setbox\framebox\hbox{\dorotatebox\@@localorientation\hbox{\box\framebox}}} + +%D The last conditional takes care of the special situation of +%D in||line \inframed[height=3cm]{framed} boxes. Such boxes have +%D to be \inframed{aligned} with the running text. + +\def\doinframed[#1]% we could omit #1] but readibility ... + {\framed[\c!location=\v!low,#1]} + +\unexpanded\def\inframed + {\dosingleempty\doinframed} + +%D When we set \type{empty} to \type{yes}, we get +%D ourselves a frame and/or background, but no content, so +%D actually we have a sort of phantom framed box. + +%D Because color marks and specials can interfere with +%D spacing, we provide a way to specify a foregroundcolor. + +\def\docolorframebox + {\doifcolor\framedforegroundcolor + {\setbox\framebox\hbox{\faststartcolor[\framedforegroundcolor]\box\framebox\faststopcolor}}} + %{\setbox\framebox\hbox{\doactivatecolor\framedforegroundcolor\box\framebox}}} + +%D \macros +%D {mframed, minframed} +%D +%D When Tobias asked how to frame mathematical elements in +%D formulas, Taco's posted the next macro: +%D +%D \starttyping +%D \def\mframed#1% +%D {\relax +%D \ifmmode +%D \vcenter{\hbox{\framed{$\ifinner\else\displaystyle\fi#1$}}}% +%D \else +%D \framed{$#1$}% +%D \fi} +%D \stoptyping +%D +%D Because \type {\ifinner} does not (always) reports what +%D one would expect, we move the test to the outer level. We +%D also want to pass arguments, +%D +%D \starttyping +%D \def\mframed% +%D {\dosingleempty\domframed} +%D +%D \def\domframed[#1]#2% % tzt \dowithnextmathbox ? +%D {\relax +%D \ifmmode +%D \ifinner +%D \inframed[#1]{$#2$}% +%D \else +%D \vcenter{\hbox{\framed[#1]{$\displaystyle#2$}}}% +%D \fi +%D \else +%D \inframed[#1]{$#2$}% +%D \fi} +%D \stoptyping +%D +%D Still better is the next alternative, if only because it +%D takes care of setting the super- and subscripts styles + +\newcount\mframedstyle + +\def\doinlinemframed[#1]#2% + {\begingroup + \mframedstyle\mathstyle\relax + \inframed[#1]{$\triggermathstyle\mframedstyle#2$}% + \endgroup} + +\def\dodisplaymframed[#1]#2% + {\begingroup + \mframedstyle\mathstyle\relax + \def\normalstrut{$\triggermathstyle\mframedstyle\vphantom{(}$}% + \framed[#1]{$\triggermathstyle\mframedstyle#2$}% + \endgroup} + +\def\mframed {\dosingleempty\dodisplaymframed} +\def\inmframed{\dosingleempty\doinlinemframed } + +%D So instead of the rather versatile \type {\framed}, we ue +%D the \type {\mframed}. +%D +%D \startbuffer +%D \startformula +%D x \times \mframed{y} \times y^{z_z} +%D x \times \inmframed{y} \times y^{z_z} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D However, we got into troubles when we want to nest sub- and +%D superscripts, like in +%D +%D \startbuffer +%D \startformula +%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D Therefore, we can best use \type {\super} and \type {\suber} +%D instead of \type {^} and \type {_}. Both commands take care +%D of proper font switching. +%D +%D \startbuffer +%D \startformula +%D x \times \mframed{y} \times y\super{\mframed{z}\suber{\mframed{z}}} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D As usual, one can specify in what way the text should be +%D framed. One should be aware of the fact that, inorder to +%D preserve the proper spacing, the \type {offset} is set to +%D \type {overlay} and \type {frameoffset} is used used +%D instead. +%D +%D \startbuffer +%D \startformula +%D x \times y\super{\mframed[framecolor=red]{z}\suber{z}} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D For inline use, we also provide the \type {\inmframed} +%D alternative: we want $x \times \inmframed{y}$ in inline +%D math, right? + +%D This previous framing macros needs a lot of alternatives for +%D putting rules around boxes, inserting offsets and aligning +%D text. Each step is handled by separate macros. + +\def\dowidenframebox#1% + {\setbox\framebox\vbox + {\kern#1\hbox{\kern#1\box\framebox\kern#1}\kern#1}} + +\def\dooffsetframebox{\dowidenframebox\localoffset} +\def\dolocateframebox{\dowidenframebox\ruledlinewidth} + +%D Let's hope that the next few examples show us enough of +%D what needs to be done by the auxiliary macros. +%D +%D \startbuffer +%D \framed[height=1cm,offset=.5cm] {rule based learning} +%D \framed[height=1cm,offset=0cm] {rule based learning} +%D \framed[height=1cm,offset=none] {rule based learning} +%D \framed[height=1cm,offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[offset=.5cm] {rule based learning} +%D \framed[offset=0cm] {rule based learning} +%D \framed[offset=none] {rule based learning} +%D \framed[offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[strut=nee,offset=.5cm] {rule based learning} +%D \framed[strut=nee,offset=0cm] {rule based learning} +%D \framed[strut=nee,offset=none] {rule based learning} +%D \framed[strut=nee,offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[width=3cm,align=left] {rule\\based\\learning} +%D \framed[width=3cm,align=middle] {rule\\based\\learning} +%D \framed[width=3cm,align=right] {rule\\based\\learning} +%D \framed[width=fit,align=middle] {rule\\based\\learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\dontcomplain\getbuffer} +%D \stoplinecorrection +%D +%D So now we're ready for the complicated stuff. We distinguish +%D between borders with straight lines and those with round +%D corners. When using the first alternative it is possible to +%D turn off one or more lines. More fancy shapes are also +%D possible by specifying dedicated backgrounds. Turning lines +%D on and off is implemented as efficient as possible and as a +%D result is interface language dependant. This next +%D implementation evolved from simpler ones. It puts for +%D instance the rules on top of the content and provides +%D additional offset capabilities. The lot of calls to other +%D macros makes this mechanism not that easy to comprehend. + +%D We handle left, right or middle alignment as well as fixed +%D or free widths and heights. Each combination gets its own +%D macro. + +%D The following code handles one-liners: \type{align={line,flushright}}. +%D Beware, since we entered a group and either or not grab the next +%D bgroup token, we need to finish the group in the oneliner mode. + +\ifx\raggedoneliner\undefined \chardef\raggedoneliner\zerocount \fi + +\def\doformatonelinerbox % beware: assumes explicit preceding bgroup + {\ifcase\raggedoneliner + \expandafter\nodoformatonelinerbox + \else + \expandafter\dodoformatonelinerbox + \fi} + +\def\dodoformatonelinerbox + {\dowithnextboxcontent + {\ignorespaces} + {\hbox to \hsize + {\ifcase\raggedstatus\or\hss\or\hss\fi + \unhbox\nextbox \removeunwantedspaces + \ifcase\raggedstatus\or \or\hss\or\hss\fi}% + \egroup} + \hbox} + +\def\nodoformatonelinerbox % grabs { + {\let\next=} + +%D The handlers: + +\def\framedforgetall{\forgetall} + +\def\setframedforegroundcolor + {\edef\colorattributehash{\framedparameterhash\c!foregroundcolor}% + \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash\c!foregroundcolor\fi} + +\def\doformatboxSomeFormat + {\vbox to \!!framedheight + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \oninterlineskip + \hsize\!!framedwidth + \vsize\!!framedheight + \doframedsetups + \raggedcommand + \dobeforeframedbox + \bgroup + \localbegstrut + \aftergroup\localendstrut + \aftergroup\doafterframedbox + \aftergroup\egroup + \doformatonelinerbox} + +\def\doformatboxNoFormat + {\vbox to \!!framedheight + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \oninterlineskip + \hsize\!!framedwidth + \vsize\!!framedheight + \doframedsetups + \raggedcenter + \vss + \bgroup + \localbegstrut + \aftergroup\localendstrut + \aftergroup\vss + \aftergroup\egroup + \doformatonelinerbox} + +\def\doformatboxHeight + {\vbox to \!!framedheight + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \oninterlineskip + \doframedsetups + \raggedcommand + \vss + \bgroup + \aftergroup\localendstrut + \aftergroup\vss + \aftergroup\egroup + \localbegstrut + \doformatonelinerbox} + +\def\doformatboxWidth + {\vbox + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \oninterlineskip + \hsize\!!framedwidth + \doframedsetups + \raggedcommand + \dobeforeframedbox + \bgroup + \localbegstrut + \aftergroup\localendstrut + \aftergroup\doafterframedbox + \aftergroup\egroup + \doformatonelinerbox} + +\def\doformatboxVSize + {\vbox to \!!framedheight + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \vsize\!!framedheight + \doframedsetups + \vss + \bgroup + \aftergroup\vss + \aftergroup\egroup + \hbox + \bgroup + \aftergroup\egroup + \localstrut + \doformatonelinerbox} + +\def\doformatboxHSize + {\hbox to \!!framedwidth + \bgroup + \let\postprocessframebox\relax + \framedforgetall + \setframedforegroundcolor + \doframedsetups + \hss + \localstrut + \bgroup + \aftergroup\hss + \aftergroup\egroup + \doformatonelinerbox} + +\def\doformatboxNoSize + {\hbox + \bgroup + \setframedforegroundcolor + \let\postprocessframebox\relax + \doframedsetups + \localstrut + \doformatonelinerbox} + +\let\doframedsetups\relax + +%D On the next page we show some examples of how these macros +%D come into action. The examples show us how +%D \type {fit}, \type {broad} dimensions influence the +%D formatting. Watch the visualized struts. \footnote {Here we +%D used \type {\showstruts}.} +%D +%D \startpostponing +%D \bgroup +%D \showstruts +%D \dontcomplain +%D \startlinecorrection +%D \halign{#\enskip&#\enskip&#\enskip&#\enskip&#\enskip&#\cr +%D \framed[width=.2\hsize, height=.2\hsize, align=] {a\par b\par c}& +%D \framed[width=.2\hsize, height=broad, align=] {a\par b\par c}& +%D \framed[width=.2\hsize, height=fit, align=] {a\par b\par c}& +%D \framed[width=fit, height=.2\hsize, align=] {a\par b\par c}& +%D \framed[width=fit, height=broad, align=] {a\par b\par c}& +%D \framed[width=fit, height=fit, align=] {a\par b\par c}\cr +%D \noalign{\vskip1em} +%D \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\par b\par c}& +%D \framed[width=.2\hsize, height=broad, align=yes] {a\par b\par c}& +%D \framed[width=.2\hsize, height=fit, align=yes] {a\par b\par c}& +%D \framed[width=fit, height=.2\hsize, align=yes] {a\par b\par c}& +%D \framed[width=fit, height=broad, align=yes] {a\par b\par c}& +%D \framed[width=fit, height=fit, align=yes] {a\par b\par c}\cr +%D \noalign{\vskip1em} +%D \framed[width=.2\hsize, height=.2\hsize, align=right] {a\par b\par c}& +%D \framed[width=.2\hsize, height=broad, align=right] {a\par b\par c}& +%D \framed[width=.2\hsize, height=fit, align=right] {a\par b\par c}& +%D \framed[width=fit, height=.2\hsize, align=right] {a\par b\par c}& +%D \framed[width=fit, height=broad, align=right] {a\par b\par c}& +%D \framed[width=fit, height=fit, align=right] {a\par b\par c}\cr +%D \noalign{\vskip1em} +%D \framed[width=.2\hsize, height=.2\hsize, align=left] {a\par b\par c}& +%D \framed[width=.2\hsize, height=broad, align=left] {a\par b\par c}& +%D \framed[width=.2\hsize, height=fit, align=left] {a\par b\par c}& +%D \framed[width=fit, height=.2\hsize, align=left] {a\par b\par c}& +%D \framed[width=fit, height=broad, align=left] {a\par b\par c}& +%D \framed[width=fit, height=fit, align=left] {a\par b\par c}\cr +%D \noalign{\vskip1em} +%D \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\par b\par c}& +%D \framed[width=.2\hsize, height=broad, align=middle] {a\par b\par c}& +%D \framed[width=.2\hsize, height=fit, align=middle] {a\par b\par c}& +%D \framed[width=fit, height=.2\hsize, align=middle] {a\par b\par c}& +%D \framed[width=fit, height=broad, align=middle] {a\par b\par c}& +%D \framed[width=fit, height=fit, align=middle] {a\par b\par c}\cr} +%D \stoplinecorrection +%D \blank[2*big] +%D \egroup +%D \stoppostponing + +%D \macros +%D {framednoflines, framedlastlength} +%D +%D It is possible to let the frame macro calculate the width +%D of a centered box automatically (\type {fit}). When +%D doing so, we need to reshape the box: + +\newcount\framednoflines +\newdimen\framedlastlength + +\def\resetshapeframebox + {\framednoflines \zerocount + \framedlastlength\zeropoint} + +\let\framedboxwidth \!!zeropoint +\let\framedboxheight\!!zeropoint +\let\framedboxdepth \!!zeropoint + +\def\doreshapeframedbox{\ifvbox\framebox\ctxlua{commands.doreshapeframedbox(\number\framebox)}\fi} + +%D The two variables \type {\framednoflines} and \type +%D {\framedlastlength} can be used in a second pass to +%D optimized framed material. + +% torture test / strange case (much depth) / method 2 needed +% +% \startTEXpage[frame=on] +% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula +% test outside formula +% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula +% \blank[big] +% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula +% test outside formula +% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula +% \stopTEXpage + +%D The examples on the next page show how one can give the +%D frame as well as the background an additional offset and +%D even a bit more depth. The blue outline is the frame, the +%D red box is the background and the small black outline is the +%D visualization of the resulting box, that is, we applied +%D \type{\ruledhbox} to the result. + +%D \startpostponing +%D \bgroup +%D \unprotect +%D \dontcomplain +%D +%D \startbuffer +%D \vbox to \vsize +%D \bgroup +%D \startalignment[middle] +%D \vss +%D \dontleavehmode\vbox to .8\vsize +%D \bgroup +%D \hsize=300pt +%D \setupframed +%D [background=color, +%D backgroundcolorachtergrondkleur=darkred, +%D width=300pt, +%D height=60pt, +%D framecolorkaderkleur=DemoBlue, +%D rulethickness=2pt] +%D \def\status% +%D {backgroundoffset=\framedparameter\c!backgroundoffset\\ +%D frameoffset=\framedparameter\c!frameoffset\\ +%D depth=\framedparameter\c!depth} +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=0pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=0pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=5pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=2pt,frameoffset=5pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=2pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=5pt]{\status}} +%D \egroup +%D \vss +%D \stopalignment +%D \egroup +%D \stopbuffer +%D +%D \getbuffer \page +%D +%D {\setupframed[depth=4pt]\getbuffer} \page +%D +%D \protect +%D \egroup +%D \stoppostponing + +%D When typesetting the framed box inline, we have to keep the +%D baseline intact outside as well as inside the framed box. + +\def\doinlineframedbox + {\scratchdimen\dimexpr\strutdp+\ruledlinewidth\relax + \ifboxhasoffset + \advance\scratchdimen \framedparameter\c!offset + \fi + \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}% + \ht\framebox\strutht + \dp\framebox\strutdp + \box\framebox} + +%D We can also lower the box over the natural depth of the +%D line. + +\def\doloweredframedbox + {\ht\framebox\dimexpr\ht\framebox+\dp\framebox-\strutdp\relax + \dp\framebox\strutdp + \box\framebox} + +%D Hanging the content is mainly meant for cases like the +%D following: +%D +%D \starttyping +%D \framed[strut=no] +%D {\framed[height=2cm,location=hanging]{test}% +%D \framed[height=1cm,location=hanging]{test}} +%D \stoptyping + +\def\dohangingframedbox % best with strut=no + {\scratchdimen\dimexpr\ht\framebox+\dp\framebox\relax + \ht\framebox\zeropoint + \dp\framebox\scratchdimen} + +%D We can draw lines from left to right and top to bottom by +%D using the normal \type{\hairline} command. Both directions +%D need a different treatment. +%D +%D \startbuffer +%D \framed[width=4cm] {alfa\hairline beta\hairline gamma} +%D \framed[height=2cm] {alfa\hairline beta\hairline gamma} +%D \framed[width=4cm,height=2cm]{alfa\hairline beta\hairline gamma} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D These macros try to adapt their behaviour as good as +%D possible to the circumstances and act as natural as +%D possible. + +\def\vboxedhairline + {\bgroup + \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi + \dimen4=\dimexpr\dimen2+\ruledlinewidth\relax + \setbox0\vbox + {\advance\hsize 2\dimen4 + \vskip\dimen2 + \hrule + \!!height\ruledlinewidth + \!!depth\zeropoint + \!!width\hsize + \vskip\dimen2}% + %\endgraf\nointerlineskip\endgraf + %\moveleft\dimen4\box0 + %\endgraf\nointerlineskip\localbegstrut + \endgraf\obeydepth\nointerlineskip + \moveleft\dimen4\box0 + \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight + \egroup} % so this must not be changed + +\def\hboxedhairline % use framed dimen + {\bgroup + \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi + \ifboxhasheight + \dimen4\dimexpr\localheight/2+\strutdp-2\ruledlinewidth\relax + \dimen6\dimexpr\localheight/2-\strutdp+2\ruledlinewidth\relax + \else + \dimen4\dimexpr\strutht+\dimen2\relax + \dimen6\dimexpr\strutdp+\dimen2\relax + \fi + \unskip + \setbox\scratchbox\hbox + {\hskip\dimen2 + \vrule\!!height\dimen4\!!depth\dimen6\!!width\ruledlinewidth + \hskip\dimen2}% + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \box\scratchbox + \ignorespaces + \egroup} + +%D The argument of the frame command accepts \type{\\} as a +%D sort of newline signal. In horizontal boxes it expands to a +%D space. + +\def\vboxednewline + {\endgraf\ignorespaces} + +\def\hboxednewline + {\unskip\normalspace\ignorespaces} + +%D We can set each rule on or off. The default setting is +%D inherited from \type{frame}. An earlier implementation +%D use a bit different approach, but the new one seems more +%D natural: +%D +%D \bgroup +%D \setuptyping[margin=0pt] +%D \startlinecorrection +%D \startbuffer +%D \framed[offset=overlay,frame=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=on,bottomframe=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=on,bottomframe=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off,bottomframe=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off,bottomframe=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D \stoplinecorrection +%D \egroup + +%D \macros +%D {setupblackrules} +%D +%D The graphic capabilities of \TEX\ do not go beyond simple +%D filled rules, except of course when using specials. Let's +%D start with a warning: using this commands is far more slower +%D than using the \TEX\ primitives \type{\hrule} and +%D \type{\vrule}, but they save us some tokens. The +%D characteristics of these rule drawing command can be set by: +%D +%D \showsetup{setupblackrules} + +\def\setupblackrules + {\dodoubleargument\getparameters[\??bj]} + +%D \macros +%D {blackrule} +%D +%D The simple command draws only one rule. Its optional +%D argument can be used to specify the dimensions. By setting +%D the width, height or depth to \type {max}, one gets the +%D natural dimensions. +%D +%D \showsetup{blackrule} + +\def\complexblackrule[#1]% + {\hbox\bgroup\getparameters[\??bj][#1]\domakeblackrule\egroup} + +\def\simpleblackrule + {\hbox\bgroup\domakeblackrule\egroup} + +\def\domakeblackrule + {\doif\@@bjwidth \v!max{\def\@@bjwidth {1em}}% + \doif\@@bjheight\v!max{\setstrut\let\setstrut\relax\def\@@bjheight{\strutht}}% + \doif\@@bjdepth \v!max{\setstrut\def\@@bjdepth {\strutdp}}% + \startcolor[\@@bjcolor]% can be made faster, just direct attr + \vrule + \!!width \@@bjwidth + \!!height\@@bjheight + \!!depth \@@bjdepth + \stopcolor} + +\definecomplexorsimple\blackrule + +%D \macros +%D {blackrules} +%D +%D One can call for a sequence of black rules, if needed +%D equally spaced over the given width. +%D +%D \showsetup{blackrules} +%D +%D The two alternative calls are therefore: +%D +%D \startbuffer +%D Tell me, is this according to the \blackrules[n=6]? +%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear. +%D \stopbuffer +%D +%D \typebuffer +%D +%D or: +%D +%D \startvoorbeeld +%D \startlines +%D \getbuffer +%D \stoplines +%D \stopvoorbeeld +%D +%D We could of course have implemented this macro using +%D \type{\leaders}, but this would probably have taken more +%D tokens. + +\def\doblackrules[#1]% + {\hbox\bgroup + \getparameters[\??bj][#1]% + \!!widtha\@@bjwidth + \!!widthb\@@bjdistance + \doif\@@bjalternative\c!b + {\scratchcounter\@@bjn + \ifnum\scratchcounter=\plusone + \!!widthb\zeropoint + \else + \advance\scratchcounter \minusone + \advance\!!widtha -\scratchcounter\!!widthb + \divide \!!widtha \@@bjn + \fi}% + \startcolor[\@@bjcolor]% + \dorecurse\@@bjn + {\vrule + \!!width \!!widtha + \!!height\@@bjheight + \!!depth \@@bjdepth + \hskip\!!widthb}% + \unskip + \stopcolor + \egroup} + +\unexpanded\def\blackrules + {\dosingleempty\doblackrules} + +%D The next commands can be used to draw margin rules. We +%D support two methods: \marginrule{one for in||line use} and +%D one that acts on a paragraph. Drawing a margin rule is +%D rather straightforward because we can use the commands that +%D put text in the margin. + +\def\dodrawmarginrule + {\setbox\scratchbox\hbox + {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}% + \smashbox\scratchbox % no \vsmash !!! + \box\scratchbox} + +\def\drawmarginrule + {\strut\inleft{\dodrawmarginrule}} + +%D \macros +%D {marginrule} +%D +%D The first method gobbles words and simply puts a bar in the +%D margin. This method is not entirely robust. +%D +%D \showsetup{marginrule} + +\definecomplexorsimple\marginrule + +\def\simplemarginrule + {\let\processword\drawmarginrule + \processwords} + +\def\complexmarginrule[#1]% + {\ifnum#1<\@@kalevel\relax \else + \def\@@kadefaultwidth{#1}% + \expandafter\simplemarginrule + \fi} + +%D We need an auxiliary variable + +\def\@@kadefaultwidth{1} + +%D \macros +%D {setupmarginrules} +%D +%D This macro definitions show us that we can pass an optional +%D level, which is matched against the previous set one. The +%D level can be set up with +%D +%D \showsetup{setupmarginrules} + +\def\setupmarginrules + {\dodoubleargument\getparameters[\??ka]} + +%D \macros +%D {startmarginrule} +%D +%D The second method collects text and reformats it afterwards, +%D using the shapebox macros. We prevent local margin rules. +%D +%D \showsetup{startmarginrule} + +\definecomplexorsimple\startmarginrule + +\def\simplestartmarginrule + {\bgroup + \let\drawmarginrule\relax + \let\stopmarginrule\dostopmarginrule + \beginofshapebox} + +\def\complexstartmarginrule[#1]% + {\bgroup + \let\drawmarginrule\relax + \ifnum#1<\@@kalevel\relax + \let\stopmarginrule\egroup + \else + \def\@@kadefaultwidth{#1}% + \let\stopmarginrule\dostopmarginrule + \expandafter\beginofshapebox + \fi} + +\def\dostopmarginrule + {\endofshapebox + \reshapebox + {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}% + \flushshapebox + \egroup} + +%D \startbuffer +%D \setupmarginrules[level=5] +%D +%D \startmarginrule[1] +%D First we set the level at~5. Next we typeset this first +%D paragraph as a level~1 one. As expected no rule show up. +%D \stopmarginrule +%D +%D \startmarginrule[5] +%D The second paragraph is a level~5 one. As we can see here, +%D the marginal rule gets a width according to its level. +%D \stopmarginrule +%D +%D \startmarginrule[8] +%D It will of course be no surprise that this third paragraph +%D has a even thicker margin rule. This behavior can be +%D overruled by specifying the width explictly. +%D \stopmarginrule +%D \stopbuffer +%D +%D In next example we show most features. Watch the rule +%D thickness adapting itself to the level. +%D +%D \startvoorbeeld +%D \getbuffer +%D \stopvoorbeeld +%D +%D We just said: +%D +%D \typebuffer + +%D \macros +%D {vl, hl} +%D +%D The command \type{\vl} draws a vertical rule \vl\ with strut +%D dimensions, multiplied with the factor specified in the +%D optional argument. The height and depth are clipped \vl[3] +%D to the baselinedistance. Its horizontal counterpart +%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em, +%D multiplied with the optional factor. The horizontal rule is +%D drawn on top of the baseline. +%D +%D \showsetup{vl} +%D \showsetup{hl} + +\def\complexvl[#1]% + {\bgroup + \!!dimena#1\strutht + \!!dimenb#1\strutdp + \setbox\scratchbox\hbox + {\vrule + \!!width \linewidth + \!!height\!!dimena + \!!depth \!!dimenb}% + \dp\scratchbox\strutdp + \ht\scratchbox\strutht + \box\scratchbox + \egroup} + +\def\complexhl[#1]% + {\hbox + {\vrule + \!!width #1\s!em + \!!height\linewidth + \!!depth \zeropoint}} + +\definecomplexorsimple\vl \def\simplevl{\complexvl[1]} +\definecomplexorsimple\hl \def\simplehl{\complexhl[1]} + +%D \macros +%D {hairline, thinrule, thinrules, setupthinrules} +%D +%D Drawing thin lines can of course easily be accomplished by +%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The +%D next few macros however free us from some specifications. +%D +%D \startbuffer +%D some text +%D +%D \hairline +%D +%D some more text +%D +%D \thinrule +%D +%D more and more text +%D +%D hi \thinrule\ there +%D +%D and then the final text +%D \stopbuffer +%D +%D \typebuffer +%D +%D becomes +%D +%D \startvoorbeeld +%D \getbuffer +%D \stopvoorbeeld +%D +%D So we've got +%D +%D \showsetup{hairline} +%D \showsetup{thinrule} +%D +%D Both can be set up with: +%D +%D \showsetup{setupthinrules} +%D +%D We also have +%D +%D \showsetup{thinrules} +%D +%D which looks like: \thinrules[n=2] + +\def\thinrule + {\strut + \bgroup + \chardef\ruletype\plusone + \processaction + [\@@dlalternative] + [ \v!a=>\chardef\ruletype0,% no line + %\v!b=>\chardef\ruletype1,% height/depth + \v!c=>\chardef\ruletype2,% topheight/botdepth + % 11=>\chardef\ruletype1,% fallback for backgrounds + 0=>\chardef\ruletype0,% compatible with backgrounds + % 1=>\chardef\ruletype1,% compatible with backgrounds + 2=>\chardef\ruletype2]% compatible with backgrounds + \doifsomething\@@dlrulethickness + {\linewidth\@@dlrulethickness}% + \ifdim\linewidth=\zeropoint + \chardef\ruletype\zerocount + \else + \doifnot\@@dlframe\v!on{\chardef\ruletype\zerocount}% + \fi + \ifnum\ruletype=\plusone + \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}% + \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}% + \else + \let\@@dlheight\!!plusone + \let\@@dldepth\!!plusone + \fi + \freezedimensionwithunit\@@dlheight\strutht + \freezedimensionwithunit\@@dldepth\strutdp + \divide\linewidth \plustwo + \doifelse\@@dlbackground\v!color + {\startcolor[\@@dlbackgroundcolor]% + \ifnum\ruletype=\plustwo % prevent overshoot due to rounding + \leaders + \hrule + \!!height\dimexpr\@@dlheight-.5\linewidth\relax + \!!depth \dimexpr\@@dldepth -.5\linewidth\relax + \hfill + \else + \leaders + \hrule + \!!height\@@dlheight + \!!depth \@@dldepth + \hfill + \fi + \stopcolor + \ifcase\ruletype + % no rule + \or + \startcolor[\@@dlcolor]% + \hfillneg + \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill + \stopcolor + \or + \startcolor[\@@dlcolor]% + \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill + \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill + \stopcolor + \fi} + {\ifcase\ruletype \else + \startcolor[\@@dlcolor]% + \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill + \stopcolor + \fi}% + \strut + \carryoverpar\egroup} + +\def\hairline + {\endgraf + \thinrule + \endgraf} + +\def\dosetupthinrules[#1]% + {\getparameters[\??dl][#1]} + +\def\setupthinrules + {\dosingleargument\dosetupthinrules} + +\def\dothinrules[#1]% + {\bgroup + \dosetupthinrules[#1]% + \@@dlbefore + \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}% + \spacing\@@dlinterlinespace + \dorecurse\@@dln + {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else + \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi + \thinrule + \ifnum\recurselevel<\@@dln\relax + % test needed, else messed up whitespace + \ifx\@@dlinbetween\empty + \softbreak + \else + \endgraf + \nowhitespace + \@@dlinbetween + \fi + \fi}% + \doifelsenothing\@@dlafter + {\carryoverpar\egroup} + {\@@dlafter\egroup}} + +\def\thinrules + {\dosingleempty\dothinrules} + +%D A couple of examples are given below. +%D +%D \startbuffer +%D \setupthinrules[n=3,inbetween=,color=gray] +%D +%D test test \thinrules\ test test \par +%D test test \thinrules [color=green] test test \par +%D test test \thinrules [height=max, depth=max] test test \par +%D +%D \setupthinrules[height=.9,depth=.9] +%D +%D test test \thinrules\ test test \par +%D test test \thinrules [alternativevariant=b] test test \par +%D test test \thinrules [alternativevariant=c] test test \par +%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par +%D \stopbuffer +%D +%D \typebuffer {\getbuffer} +%D +%D There are a couple of alternative ways to visualize rules +%D using backgrounds. At first sight these may look strange, +%D but they make sense in educational settings. The +%D alternatives are more or less compatible with the more +%D advanced \METAPOST\ based implementation. +%D +%D \startbuffer[a] +%D \setupthinrules +%D [n=2, +%D backgroundcolor=gray , +%D rulethickness=1pt, +%D colorkleur=donkerblauw, +%D after=\blank, +%D before=\blank] +%D \stopbuffer +%D +%D \typebuffer[a] +%D +%D \startbuffer[b] +%D \thinrules[alternativevariant=a] +%D \thinrules[alternativevariant=b] +%D \thinrules[alternativevariant=c] +%D \stopbuffer +%D +%D \typebuffer[b] \getbuffer[a,b] +%D +%D \startbuffer[b] +%D \thinrules[alternativevariant=a,background=color] +%D \thinrules[alternativevariant=b,background=color] +%D \thinrules[alternativevariant=c,background=color] +%D \stopbuffer +%D +%D \typebuffer[b] \getbuffer[a,b] +%D +%D \startbuffer[b] +%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color] +%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color] +%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color] +%D \stopbuffer +%D +%D \typebuffer[b] \getbuffer[a,b] + +%D \macros +%D {optimizethinrules} +%D +%D By saying \type {\thinrulestrue} or \type {-false}, we +%D can influence the way dangling lines are handled. + +\newif\ifoptimizethinrules \optimizethinrulestrue + +\def\dothinrulesnobreak + {\ifoptimizethinrules\penalty500\fi} + +%D \macros +%D {startframedtext, setupframedtexts, defineframedtext} +%D +%D The general framing command we discussed previously, is not +%D entirely suited for what we call framed texts, as for +%D instance used in intermezzo's. The next examples show what +%D we have in mind. +%D +%D \startbuffer[framed-0] +%D \setupframedtexts +%D [frame=off, +%D width=\hsize, +%D background=screen] +%D +%D \startframedtext +%D By default the framed text is centered \dots +%D \stopframedtext +%D +%D \startframedtext[right] +%D \dots\ but we can also align left, middle and right. +%D \stopframedtext +%D \stopbuffer +%D +%D \startbuffer[framed-1] +%D \defineframedtext +%D [Example] +%D [width=6cm, +%D height=5cm] +%D +%D \startExample +%D \typebuffer[framed-1] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-2] +%D \defineframedtext +%D [Example] +%D [width=6cm] +%D +%D \startExample +%D \typebuffer[framed-2] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-3] +%D \defineframedtext +%D [Example] +%D [height=5cm] +%D +%D \startExample +%D \typebuffer[framed-3] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-4] +%D \defineframedtext +%D [Example] +%D [width=fit,height=broad] +%D +%D \Example{a very exciting example} +%D \stopbuffer +%D +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-0] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-1] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-2] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup +%D +%D Here we can see that we have a predefined framed text class +%D as well as the tools for defining our own. So we have: +%D +%D \showsetup{setupframedtexts} +%D +%D as well as the definition command: +%D +%D \showsetup{defineframedtext} +%D +%D that generates two commands: +%D +%D \showsetup{start<<framedtext>>} +%D \showsetup{<<framedtext>>} +%D +%D The next definition shows the defaults. + +\def\dodefineframedtext[#1][#2]% + {\presetlocalframed[\??kd#1]% + \getparameters[\??kd#1] + [\c!width=0.75\hsize, + \c!height=\v!fit, + \c!align=\v!yes, + \c!top=, + \c!bottom=\vfill, + \c!offset=1em, + \c!bodyfont=, + \c!style=, + \c!color=, + \c!left=, + \c!right=\hfill, + \c!before=\blank, + \c!after=\blank, + \c!inner=, + \c!frame=\v!on, + \c!topframe=, + \c!bottomframe=, + \c!leftframe=, + \c!rightframe=, + \c!radius=.5\bodyfontsize, + \c!corner=\v!rectangular, + \c!foregroundcolor=, + \c!foregroundstyle=, + \c!background=, + \c!backgroundcolor=, + \c!backgroundscreen=\@@rsscreen, + \c!linecorrection=\v!on, + \c!depthcorrection=\v!on, + \c!margin=\v!standard, + \c!orientation=, + \c!indenting=, + #2]% + \setvalue{\e!start#1}{\dostartframedtext[#1]}% + \setvalue{\e!stop #1}{\dostopframedtext }% + \setvalue {#1}{\doframedtext [#1]}} + +\def\defineframedtext + {\dodoubleempty\dodefineframedtext} + +%D We define the general (and original) case by just saying: + +\defineframedtext[\v!framedtext] + +%D We need several steps before the actual job is done, +%D because we have to handle an optional identifier (and +%D because these commands evolved out of a single case). + +\def\framedtextparameter#1#2% + {\csname\??kd#1#2\endcsname} + +\def\dosetupframedtexts[#1][#2]% + {\ifsecondargument + \def\docommand##1{\getparameters[\??kd##1][#2]}% + \processcommacommand[#1]\docommand % new, #1 may be macro + \else + \getparameters[\??kd\v!framedtext][#1]% + \fi} + +\def\setupframedtexts + {\dodoubleempty\dosetupframedtexts} + +\def\dostartframedtext + {\bgroup\dotripleempty\dodostartframedtext} + +\def\dodostartframedtext[#1][#2][#3]% + {\doifassignmentelse{#2} + {\dododostartframedtext[#1][][#2]} + {\dododostartframedtext[#1][#2][#3]}} + +\setfalse\framedtextlocationnone + +\def\checkframedtext % messy dependency + {\ifinsidefloat + \localhsize\hsize + \else\ifdim\sidefloatvsize>\zeropoint % will be proper handle + % \strut % rather clean way to invoke the sidefloat OTR + % \setbox0=\lastbox % and get the widths set, so from now on we + % \setlocalhsize % can have framed texts alongside sidefloats + \checksidefloat + \setlocalhsize + \else + \localhsize\hsize + \fi\fi} + +\def\dododostartframedtext[#1][#2][#3]% #3 only passed to framed, not to framedtext + {\doifsomething{#2}{\setvalue{\??kd#1\c!location}{#2}}% does not listen to #3 + \setfalse\framedtextlocationnone + \processaction % \v!low en \v!depth are already taken ! + [\framedtextparameter{#1}\c!location] + [ \v!left=>\letvalue{\??kd#1\c!left }\relax + \letvalue{\??kd#1\c!right}\hfill, + \v!right=>\letvalue{\??kd#1\c!left }\hfill + \letvalue{\??kd#1\c!right}\relax, + \v!middle=>\letvalue{\??kd#1\c!left }\hfill + \letvalue{\??kd#1\c!right}\hfill, + \v!none=>\letvalue{\??kd#1\c!left }\relax % new + \letvalue{\??kd#1\c!right}\relax % new + \settrue\framedtextlocationnone]% + \letvalue{\??kd#1\c!location}\empty + % removed 06/2001 + % \forgetparindent + % added 06/2001 [see demo-bbv] + \localhsize\hsize \checkframedtext + % so far + \setbox\framebox\vbox + \startboxedcontent + \hsize\localhsize + % \insidefloattrue % ? better + \normalexpanded{\noexpand\switchtobodyfont[\framedtextparameter{#1}\c!bodyfont]}% + \startcolor[\framedtextparameter{#1}\c!color]% + \localframed[\??kd#1][\c!strut=\v!no,#3]% todo: use delayedstrut + \bgroup + \let\\=\endgraf + \framedtextparameter{#1}\c!inner % oud spul + \doifvalue{\??kd#1\c!depthcorrection}\v!on % new, inside box + {\bgroup + \verticalstrut + % we need \nowhitespace in case of setups setting whitespace + % nb, not safe, text vs \vbox as next + \vskip-\struttotal + \nowhitespace % na vskip ! new 20/05/2004, fails with next content being box (\scale{..}) + }% + \doinhibitblank % \blank[\v!disable]% plaatst signal +\setupindenting[\framedtextparameter{#1}\c!indenting]% + \doconvertfont{\framedtextparameter{#1}\c!style}\empty + \def\dostopframedtext{\dodostopframedtext{#1}{#2}}} + +%D The \type {none} option is handy for nested usage, as +%D in the presentation styles, where we don't want +%D interference. + +\def\dodostopframedtext#1#2% % no \baselinecorrection, see faq docs + {\endgraf + \removelastskip + \doifvalue{\??kd#1\c!depthcorrection}\v!on % local and global + {\forgetall + \vskip-\struttotal + \verticalstrut + \egroup + \forgetall % brrr too often + \vskip-\lineheight + % will be an option, not default + % \setbaselinecorrections + % \donegbotbaselinecorrection + \verticalstrut} + \stopboxedcontent + \stopcolor + \ifconditional\framedtextlocationnone + \egroup + \box\framebox + \else\ifinsidefloat + \egroup + \box\framebox + \else + \egroup + \doplacement[\??kd#1][\c!depthcorrection=\v!off]{\box\framebox}% + \fi\fi + \egroup} + +%D Placement can be ignored: +%D +%D \starttyping +%D \hbox to \hsize \bgroup +%D \startframedtext[none][width=.5\textwidth] \input tufte \stopframedtext +%D \startframedtext[none][width=.5\textwidth] \input zapf \stopframedtext +%D \egroup +%D +%D \hbox to \hsize \bgroup +%D \setupframedtexts[location=none]% +%D \startframedtext[width=.5\textwidth] \input zapf \stopframedtext +%D \startframedtext[width=.5\textwidth] \input tufte \stopframedtext +%D \egroup +%D \stoptyping + +%D The simple brace (or group) delimited case is typeset +%D slightly different and is not aligned. + +\def\doframedtext + {\bgroup\dodoubleempty\dodoframedtext} + +\def\dodoframedtext[#1][#2]% beware! + {\normalexpanded{\noexpand\switchtobodyfont[\getvalue{\??kd#1\c!bodyfont}]}% + \localframed[\??kd#1][\c!strut=\v!no,#2]% + \bgroup + \blank[\v!disable]% + \let\\=\endgraf + \getvalue{\??kd#1\c!inner}% % kleur naar outer level + \dostartattributes{\??kd#1}\c!style\c!color\empty + \bgroup + \aftergroup\docloseframedtext + \let\next=} + +\def\docloseframedtext + {\removelastskip + \dostopattributes + \egroup + \egroup} + +%D \macros +%D {defineframed} +%D +%D One can also define simple framed texts, using: +%D +%D \showsetup{defineframed} + +\def\defineframed + {\dodoubleempty\dodefineframed} + +\def\dodefineframed[#1][#2]% + {\iffirstargument + \setvalue{#1}{\dodoubleempty\doframed[#2]}% + \fi} + +\def\doframed[#1][#2]% + {\framed[#1,#2]} + +%D \macros +%D {textrule, starttextrule, setuptextrules} +%D +%D Putting rules before and after a paragraph is very space +%D sensitive, but the next command handles that quite well. It +%D comes in two disguises: +%D +%D \startbuffer +%D \textrule[top]{fragments} +%D \input reich +%D \textrule +%D \stopbuffer +%D +%D \bgroup \typebuffer \getbuffer \egroup +%D +%D \startbuffer +%D \setuptextrules +%D [width=90pt,distance=12pt,rulecolor=blue, +%D bodyfont=small,style=\sc,color=red] +%D +%D \starttextrule{Ship Building Tools} +%D \nl \setuptolerance[tolerant] \input materie +%D \stoptextrule +%D \stopbuffer +%D +%D \bgroup \typebuffer \getbuffer \egroup +%D +%D \startbuffer +%D \setuptextrules +%D [location=inmargin, +%D bodyfont=small,style=slantedbold] +%D +%D \starttextrule{wonderful} +%D \input tufte +%D \stoptextrule +%D \stopbuffer +%D +%D \bgroup \typebuffer \getbuffer \egroup +%D +%D The formal definition of these commands is: +%D +%D \showsetup{textrule} +%D \showsetup{starttextrule} +%D \showsetup{setuptextrules} +%D +%D The implementation looks a bit complicated due to the +%D optional arguments. + +\def\setuptextrules + {\dodoubleargument\getparameters[\??tl]} + +\def\complextextrule[#1]% if needed we can make it installable + {\let\next\dobottomtextrule + \processaction + [#1] + [ \v!top=>\let\next\dotoptextrule, + \v!middle=>\let\next\domiddletextrule, + \v!bottom=>\let\next\dobottomtextrule]% + \dosinglegroupempty\next} + +\definecomplexorsimple\textrule + +\def\simpletextrule + {\dosinglegroupempty\dounknowntextrule} + +\def\docomplextextrule#1% + {\bgroup + \advance\hsize\dimexpr-\rightskip-\leftskip\relax + \setbox\scratchbox\hbox to \hsize + {\dimen4\dimexpr .5ex+.5\linewidth\relax + \dimen6\dimexpr-.5ex+.5\linewidth\relax + \doifnothing{#1}\firstargumentfalse + \iffirstargument + \doifelse\@@tllocation\v!inmargin + {\llap{\doattributes\??tl\c!style\c!color{#1}\hskip\leftmargindistance}} + {\color[\@@tlrulecolor] + {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}% + \hbox spread 2\dimexpr\@@tldistance\relax + {\hss\doattributes\??tl\c!style\c!color{\strut#1}\hss}}% + \fi + \color[\@@tlrulecolor] + {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}% + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \noindent\box\scratchbox +%\nobreak\verticalstrut\kern-\struttotal +% evt \witruimte + \egroup} + +\def\dotoptextrule#1% + {\page[\v!preference] % interferes + %\whitespace % no + \@@tlbefore + \docomplextextrule{#1}% +% todo, option: \doifnothing{#1}{\ruledvskip-.5ex} + \nowhitespace + \@@tlinbetween + \endgraf} + +\def\dodobottomtextrule#1#2% + {\ifhmode + \endgraf + \fi + \dimen0\strutdp + \ifdim\prevdepth>\strutdp\else % was <\strutdp + \ifdim\prevdepth>\zeropoint + \advance\dimen0 -\prevdepth + \fi + \fi + \advance\dimen0 .5ex + \vskip\dimen0 +% == +% \vskip\dimexpr \strutdp + .5ex +% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax +% + \@@tlinbetween + \doifelsenothing{#2} + {\bgroup + \advance\hsize\dimexpr-\rightskip-\leftskip\relax + \nointerlineskip + \moveleft-\leftskip\vbox + {\color[\@@tlrulecolor] + {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}% + \egroup} + {\docomplextextrule{#2}}% + \ifvmode\prevdepth\zeropoint\fi + #1% + \page[\v!preference]} + +\def\dobottomtextrule + {\dodobottomtextrule\@@tlafter} + +\def\domiddletextrule + {\dodobottomtextrule\@@tlinbetween} + +\def\dounknowntextrule + {\iffirstargument + \@EA\dotoptextrule + \else + \@EA\dobottomtextrule\@EA\empty + \fi} + +%D The grouped commands also supports bodyfont switching: + +\def\starttextrule#1% + {\bgroup + \def\dounknowntextrule{\domiddletextrule} + \dotoptextrule{#1} + \bgroup + \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}} + +\def\stoptextrule + {\par + \egroup + \dobottomtextrule\empty + \egroup} + +%D \macros +%D {fillinrules, setupfillinrules} +%D +%D The next few commands do not really deserve a place in a +%D core module, because they deal with specific typography. +%D Nevertheless I decided to make them part of the core, +%D because they permit us to make questionaires. Let's start +%D with some examples. +%D +%D \fillinrules[n=2,width=fit]{first} +%D \fillinrules[n=2,width=broad]{first} +%D \fillinrules[n=2,width=3cm]{first} +%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first} +%D \fillinrules[n=2]{first}{last} +%D \fillintext{first}{last} \input reich \par +%D +%D The main command is \type{\fillinrules}. This command takes +%D one and an optional second argument and sets a paragraph with +%D empty visualized lines. +%D +%D \showsetup{fillinrules} +%D \showsetup{setupfillinrules} + +\def\setupfillinrules + {\dodoubleargument\getparameters[\??il]} + +\definecomplexorsimpleempty\fillinrules + +\def\complexfillinrules[#1]% + {\def\docomplexfillinrules##1##2% + {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules + [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}% + \dodoublegroupempty\docomplexfillinrules} + +\def\dodocomplexfillinrules[#1]#2#3#4% + {\endgraf + \@@ilbefore + \begingroup + \setupfillinrules[#1]% + \noindent + \doifsomething{#2} + {\doifelse\@@ilwidth\v!fit + {\let\@@ildistance\!!zeropoint + \hbox} + {\doifelse\@@ilwidth\v!broad + {\hbox} + {\hbox to \@@ilwidth}}% + \bgroup + \doattributes\??il\c!style\c!color{\strut#2\hfill\@@ilseparator}% + \hskip\@@ildistance + \egroup}% + %\hangindent=\wd0\relax % tzt hang=yes,n + %\parindent=\hangindent + %\box0\relax + \setupwhitespace[\v!big]% + \ignorespaces + #4% + \doifsomething{#3} + {\kern\@@ildistance + \doattributes\??il\c!style\c!color{#3\strut}}% + \endgroup + \endgraf + \@@ilafter} + +%D \macros +%D {fillintext} +%D +%D To provide compatible layouts when texts and lines are +%D mixed, one can typeset a paragraph by using the command +%D \type{\fillintext}. +%D +%D \showsetup{fillintext} + +\definecomplexorsimpleempty\fillintext + +\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal + {\def\docomplexfillintext##1##2% + {\dowithnextbox + {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}% + \hbox\bgroup\let\par\egroup\ignorespaces}% + \dodoublegroupempty\docomplexfillintext} + +%D \macros +%D {fillinline, setupfillinlines} +%D +%D Another member of the family takes care of putting a (often +%D small) rule after a piece of text, like +%D +%D \startbuffer +%D \fillinline \input reich \par +%D \fillinline[margin=0cm] \input reich \par +%D \stopbuffer +%D +%D \startvoorbeeld +%D \getbuffer +%D \stopvoorbeeld +%D +%D which was typeset by saying: +%D +%D \typebuffer +%D +%D The two commands that take care of this are: +%D +%D \showsetup{fillinline} +%D \showsetup{setupfillinlines} + +\def\setupfillinlines + {\dodoubleargument\getparameters[\??iv]} + +\definecomplexorsimpleempty\fillinline + +\def\complexfillinline[#1]% + {%\endgraf % interferes with \definedescription cum suis + \@@ivbefore + \begingroup + \setupfillinlines[#1]% + \advance\rightskip \@@ivmargin + \parfillskip\zeropoint + \def\par % very dangerous + {\let\par\endgraf % -) + \ifhmode\unskip\hfill\fi + \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax + \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi + {\kern\@@ivdistance + \vrule + \!!width \scratchdimen + \!!height.5\linewidth + \!!depth .5\linewidth}% + \endgraf % ! + \endgroup + \endgraf % ! + \@@ilafter}} + +%D \stopdocumentation +%D \bgroup +%D +%D \setupframedtexts +%D [setuptext] +%D [background=color,backgroundcolor=white] +%D +%D \startbuffer +%D \setupbackground +%D [backgroundoffset=4pt, +%D background=screen, +%D frame=on, +%D framecolor=red, +%D leftoffset=2pt] +%D \stopbuffer +%D +%D \getbuffer +%D +%D \startbackground +%D +%D \macros +%D {setupbackground,startbackground,background} +%D +%D The section deals with backgrounds in the running text. This +%D means that texts is to be collected and split over pages. To +%D show what can be done, we provide this part of the +%D documentation with some gray background and a red frame. +%D Both the background and frame can have all characteristics +%D of \type{\framed}. This time we used the setting: +%D +%D \typebuffer +%D +%D The implementation is not that sophisticated, but suffices. +%D The main problem with this kind of functionality is to get +%D the spacing all right. + +%D Specifying the background is more or less the same as +%D specifying a framed box. +%D +%D \showsetup{setupbackground} + +\presetlocalframed[\??ag] + +\def\dosetupbackground[#1]% + {\getparameters[\??ag][#1]% + \doifelse\@@agstate\v!start + {\let\startbackground\dostartbackground + \let\stopbackground \dostopbackground + \let\background \dobackground} + {\let\startbackground\relax + \let\stopbackground \relax + \let\background \relax}} + +\def\setupbackground + {\dosingleargument\dosetupbackground} + +%D Actually typesetting the background is implemented rather +%D straightforward. We need to handle some spacing as well as +%D the (often) a bit smaller horizontal size. +%D +%D \showsetup{startbackground} +%D +%D Although we could have used a scratch one, we first +%D declare a boolean. + +% 0=no-split, 1=no-split+indent, 2=split, 3=split+indent + +\chardef\backgroundsplitmode\plusthree + +%D The \type{\vbox to \lineheight{}\vskip\zeropoint} +%D construction gives the first real line a decent height by +%D adding a dummy line. + +\def\dostartbackground + {\endgraf + \bgroup + \setbox0\vbox\bgroup + \vbox to \lineheight{}\vskip\zeropoint + \blank[\v!disable] + % \advance\hsize -\@@agleftoffset + % \advance\hsize -\@@agrightoffset + \leftskip \@@agleftoffset % new ** + \rightskip\@@agrightoffset} % new ** + +%D This dummy line is removed by \type{\setbox2=\vsplit0 to +%D \lineheight}. That way \type{\topskip} takes care of the +%D lineheight. I'll probably forget to apply this trick +%D elsewhere. + +\def\dostopbackground % improved version (i hope) + {\endgraf + \removelastskip + \egroup + \dimen2\leftskip % new ** + \forgetall + \ifinsidefloat + \chardef\backgroundsplitmode\zerocount + \fi + \ifcase\backgroundsplitmode + \localframed[\??ag][\c!offset=\v!overlay]{\box0}% + \or + \hskip\dimen2 + \localframed[\??ag][\c!offset=\v!overlay]{\box0}% + \else + \splitmaxdepth\boxmaxdepth + \splittopskip\topskip + \setbox2\vsplit0 to \lineheight % get rid of fake line + \loop + \ifdim\pagetotal=\zeropoint % empty page + \scratchdimen\textheight + \chardef\backgroundsplit\plusone % split to max height + \else + \setbox\scratchbox\vbox{\@@agbefore}% + \scratchdimen\dimexpr\pagegoal-\ht\scratchbox-\pagetotal\relax + \chardef\backgroundsplit\plustwo % split to partial height + \fi + \advance\scratchdimen\dimexpr-\@@agtopoffset-\@@agbottomoffset\relax + \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable + \ifdim\ht0>\scratchdimen % larger than page + \setbox2\vsplit0 to \scratchdimen + \else + \setbox2\box0 + \chardef\backgroundsplit\zerocount % no split + \fi + \setbox2\vbox \ifcase\backgroundsplit\or to \textheight \fi % max split + {\vskip\@@agtopoffset + \unvcopy2 + \prevdepth\dp2 + \obeydepth + \vskip\@@agbottomoffset + \vfill} + \@@agbefore + \ifcase\backgroundsplit\or\or % partial split + \ifdim\pagegoal<\maxdimen + \pagegoal=1.2\pagegoal % be a bit more tolerant + \fi + \fi + \startlinecorrection + %\localframed[\??ag][\c!offset=\v!overlay]{\hskip\@@agleftoffset\box2\hskip\@@agrightoffset}% + \ifnum\backgroundsplitmode=\plusthree \hskip\dimen2 \fi % + \localframed[\??ag][\c!offset=\v!overlay]{\box2}% new ** + \stoplinecorrection + \ifcase\backgroundsplit % no split + \@@agafter + \else % some split + \vfill\eject % geen \page ! + \fi + \else + \page + \fi + \ifdim\ht0>\zeropoint \repeat + \fi + \egroup + \endgraf} + +%D As a bonus we also have a short command, that is of not +%D much use, but kept there for historic reasons. +%D +%D \showsetup{background} + +\def\dobackground + {\bgroup + \dowithnextbox + {\localframed[\??ag][\c!offset=\v!overlay]{\flushnextbox}\egroup} + \vbox} + +%D \stopdocumentation +%D \stopbackground +%D \egroup + +%D New, for the moment private; let's see when GB finds out +%D about this one and its obscure usage. It's used in: +%D +%D \startbuffer +%D \defineframedtext +%D [tabulateframe] +%D [offset=overlay, +%D backgroundoffset=3pt, +%D background=color, +%D backgroundcolor=green] +%D +%D \setuptabulate +%D [tabulate] +%D [frame=tabulateframe] +%D +%D \setuptables +%D [frame=tabulateframe] +%D +%D \input tufte +%D +%D \starttabulate[|l|l|] +%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR +%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR +%D \stoptabulate +%D +%D \input tufte +%D +%D \starttable[|l|l|] +%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR +%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR +%D \stoptable +%D \stopbuffer +%D +%D \typebuffer + +\def\defineframedcontent + {\dodoubleempty\dodefineframedcontent} + +\def\dodefineframedcontent[#1][#2]% + {\presetlocalframed[\??fc#1]% + \getparameters[\??fc#1] + [\c!leftoffset=\zeropoint, + \c!rightoffset=\getvalue{\??fc#1\c!leftoffset}, + \c!topoffset=\zeropoint, + \c!bottomoffset=\getvalue{\??fc#1\c!topoffset}, + \c!strut=\v!no, + \c!offset=\v!overlay, + \c!linecorrection=\v!no, + \c!left=, + \c!right=, + #2]} + +\let\setuplocalframed\getparameters + +\def\setupframedcontent + {\dodoubleempty\dosetupframedcontent} + +\def\dosetupframedcontent[#1][#2]% + {\def\docommand##1{\getparameters[\??fc##1][#2]}% + \processcommacommand[#1]\docommand} + +\def\startframedcontent[#1]% + {\bgroup + \doifelse{#1}\v!off + {\let\stopframedcontent\egroup} + {\ifcsname\??fc#1\c!frame\endcsname + \dostartframedcontent{#1}% + \fi}} + +\def\dostartframedcontent#1% + {\def\stopframedcontent{\dostopframedcontent{#1}}% + \setbox\framebox\hbox\bgroup + \setlocalhsize + \hsize\localhsize + \advance\hsize\dimexpr-\getvalue{\??fc#1\c!leftoffset}-\getvalue{\??fc#1\c!rightoffset} \relax + \advance\vsize\dimexpr-\getvalue{\??fc#1\c!topoffset} -\getvalue{\??fc#1\c!bottomoffset}\relax + \hskip\getvalue{\??fc#1\c!leftoffset}% + \vbox\bgroup + \vskip\getvalue{\??fc#1\c!topoffset}% + \vbox\bgroup + \forgetall + \blank[\v!disable]} + +\def\dostopframedcontent#1% + {\removelastskip + \egroup + \vskip\getvalue{\??fc#1\c!bottomoffset}% + \egroup + \hskip\getvalue{\??fc#1\c!rightoffset}% + \egroup + \doifvalue{\??fc#1\c!width}\v!fit + {\letvalue{\??fc#1\c!width}\v!fixed}% no shapebox + \ifinsidefloat + \donefalse + \else + \doifelsevalue{\??fc#1\c!linecorrection}\v!yes\donetrue\donefalse + \fi + % plaats ? + \ifdone\startlinecorrection\fi + \getvalue{\??fc#1\c!left}% new + \localframed[\??fc#1]{\box\framebox}% + \getvalue{\??fc#1\c!right}% new + \ifdone\stoplinecorrection\fi + \egroup} + +%D \macros +%D {backgroundline} +%D +%D For the moment an undocumented feature, but a cancidate +%D for going public. + +\def\backgroundline[#1]% + %{\doifsomething{#1}{\dobackgroundline{#1}}\hbox} + {\doifcolorelse{#1}{\dobackgroundline{#1}\hbox}\hbox} + +% \def\backgroundline[#1]% +% {\doifcolor{#1}{\dobackgroundline{#1}}\hbox} + +\def\dobackgroundline#1% + {\dowithnextbox + {\hbox + {\startcolor[#1]% + \vrule + \!!width \nextboxwd + \!!height\nextboxht + \!!depth \nextboxdp + \stopcolor + \hskip-\nextboxwd + \flushnextbox}}} + +%D \macros +%D {encircled} +%D +%D Some not so robust left||overs (borrowed from Knuth, +%D \TEX Book\ page 356): + +\def\encircled#1% + {{\ooalign{\hfil\raise0.07ex\hbox{{\tx#1}}\hfil\crcr\mathhexbox20D}}} + +\let\omcirkeld\encircled + +\setuplinewidth + [\v!medium] + +\setupframed + [\c!width=\v!fit, + \c!height=\v!broad, + \c!lines=, + \c!offset=0.25ex, % \defaultframeoffset + \c!empty=\v!no, + \c!frame=\v!on, + \c!topframe=, + \c!bottomframe=, + \c!leftframe=, + \c!rightframe=, + \c!radius=.5\bodyfontsize, + \c!rulethickness=\linewidth, + \c!corner=\v!rectangular, + \c!depth=\zeropoint, + \c!foregroundcolor=, + \c!foregroundstyle=, + \c!background=, + \c!backgroundscreen=\@@rsscreen, + \c!backgroundcolor=, + \c!backgroundoffset=\zeropoint, + \c!framecolor=, + \c!frameoffset=\zeropoint, + \c!backgroundcorner=\framedparameter\c!corner, + \c!backgroundradius=\framedparameter\c!radius, + \c!backgrounddepth=\framedparameter\c!depth, + \c!framecorner=\framedparameter\c!corner, + \c!frameradius=\framedparameter\c!radius, + \c!framedepth=\framedparameter\c!depth, + \c!component=, + \c!align=, + \c!bottom=\vss, + \c!top=, + \c!strut=\v!yes, + \c!autostrut=\v!yes, + \c!location=\v!normal, + \c!orientation=, + \c!autowidth=\v!yes, + \c!setups=] + +\setupscreens + [%\c!factor=1.0, % obsolete + %\c!method=\v!external, % obsolete + \c!screen=0.95] + +\setupblackrules + [\c!n=3, + \c!width=1em, + \c!height=1ex, + \c!depth=\!!zeropoint, + \c!alternative=\c!a, + \c!distance=.25ex, + \c!color=] + +\setupmarginrules + [\c!level=0, + \c!rulethickness=\@@kadefaultwidth\linewidth] + +\setupthinrules + [\c!interlinespace=\v!small, + \c!n=3, + \c!before=, + \c!inbetween={\blank[\v!white]}, + \c!after=, + \c!color=, + \c!height=.5\linewidth, + \c!depth=.5\linewidth, + \c!frame=\v!on, % compatible with textbackgrounds + \c!alternative=\v!b, + \c!backgroundcolor=, + \c!background=, + \c!rulethickness=] + +\setuptextrules + [\c!location=\v!left, + \c!before=\blank, + \c!after=\blank, + \c!inbetween=, + \c!width=2em, + \c!style=\v!bold, + \c!color=, + \c!rulecolor=, + \c!bodyfont=, + \c!distance=.5em] + +\setupfillinrules + [\c!width=\v!broad, + \c!distance=1em, + \c!before=\blank, + \c!after=\blank, + \c!n=1, + \c!interlinespace=\v!small, + \c!separator=, + \c!style=\v!normal, + \c!color=] + +\setupfillinlines + [\c!width=3cm, + \c!margin=\@@ivwidth, + \c!distance=1em, + \c!before=\blank, + \c!after=\blank] + +\setupbackground + [\c!leftoffset=.5\bodyfontsize, + \c!rightoffset=\@@agleftoffset, + \c!topoffset=\!!zeropoint, + \c!bottomoffset=\@@agtopoffset, + \c!state=\v!start, + \c!radius=.5\bodyfontsize, + \c!corner=\v!rectangular, + \c!frame=\v!off, + \c!color=, + \c!depth=\!!zeropoint, + \c!background=\v!screen, + \c!backgroundcolor=\@@agcolor, + \c!screen=\@@rsscreen, + \c!before=, + \c!after=] + +% Experimental extension: + +\def\c!loffset{loffset} +\def\c!roffset{roffset} +\def\c!toffset{toffset} +\def\c!boffset{boffset} + +\getparameters + [\??oi] + [\c!loffset=\zeropoint, + \c!roffset=\zeropoint, + \c!toffset=\zeropoint, + \c!boffset=\zeropoint] + +\newdimen\!!framedloffset +\newdimen\!!framedroffset +\newdimen\!!framedtoffset +\newdimen\!!framedboffset + +\def\setextraframedoffsets + {\boxhasextraoffsetfalse + \!!framedloffset\framedparameter\c!loffset + \!!framedroffset\framedparameter\c!roffset + \!!framedtoffset\framedparameter\c!toffset + \!!framedboffset\framedparameter\c!boffset + \ifzeropt\!!framedloffset\else \advance\!!framedwidth -\!!framedloffset \boxhasextraoffsettrue \fi + \ifzeropt\!!framedroffset\else \advance\!!framedwidth -\!!framedroffset \boxhasextraoffsettrue \fi + \ifzeropt\!!framedtoffset\else \advance\!!framedheight-\!!framedtoffset \boxhasextraoffsettrue \fi + \ifzeropt\!!framedboffset\else \advance\!!framedheight-\!!framedboffset \boxhasextraoffsettrue \fi} + +\def\applyextraframedoffsets + {\setbox\framebox\vbox\bgroup + \vskip\!!framedtoffset + \hbox\bgroup + \hskip\!!framedloffset + \box\framebox + \hskip\!!framedroffset + \egroup + \vskip\!!framedboffset + \egroup} + +\protect \endinput |