From 18499e46a49b8ccf4346686d1cf626ada33935b8 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 23 Nov 2020 19:48:34 +0100 Subject: 2020-11-23 18:39:00 --- tex/context/base/mkxl/pack-rul.mkxl | 3001 +++++++++++++++++++++++++++++++++++ 1 file changed, 3001 insertions(+) create mode 100644 tex/context/base/mkxl/pack-rul.mkxl (limited to 'tex/context/base/mkxl/pack-rul.mkxl') diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl new file mode 100644 index 000000000..28fed1c51 --- /dev/null +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -0,0 +1,3001 @@ +%D \module +%D [ file=pack-rul, % was core-rul, +%D version=1998.10.16, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Ruled Content, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content} + +%D The code here is expanded lots of time as framed is used in many places. This is +%D why the code here is (and gets) optimized as much as possible. Also, by avoiding +%D packaging and expansion we also keep tracing reasonable. For instance, multiple +%D stacked backgrounds can slow down a run if not optimized this way. + +\registerctxluafile{pack-rul}{autosuffix,optimize} + +\unprotect + +% \definesystemvariable {ol} % OmLijnd -> check scrn-fld too + +%D \macros +%D {linewidth, setuplinewidth} +%D +%D This module deals with rules (lines) in several ways. First we introduce two +%D macros that can be used to set some common characteristics. +%D +%D \showsetup{setuplinewidth} +%D +%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals +%D the default hard coded \TEX\ rule width. + +\newdimen\linewidth + +\permanent\tolerant\protected\def\setuplinewidth[#1]% + {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}} + +%D The parameter handler: + +\installcorenamespace{framed} +\installcorenamespace{framedtop} +\installcorenamespace{framedbottom} +\installcorenamespace{framedleft} +\installcorenamespace{framedright} + +\installcorenamespace{regularframed} +\installcorenamespace{simplifiedframed} + +\installcommandhandler \??framed {framed} \??framed + +\let\pack_framed_framedparameter \framedparameter +\let\pack_framed_framedparameterhash\framedparameterhash +\let\pack_framed_setupcurrentframed \setupcurrentframed + +\def\pack_framed_initialize + {\enforced\let\framedparameter \pack_framed_framedparameter + \enforced\let\framedparameterhash\pack_framed_framedparameterhash + \enforced\let\setupcurrentframed \pack_framed_setupcurrentframed + \inframedtrue} + +%D A helper: + +\permanent\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax} + +%D Inheritance: + +\permanent\protected\def\installinheritedframed#1% + {\normalexpanded{\mult_interfaces_install_inherited_framed + \expandafter\noexpand\csname current#1\endcsname + \expandafter\noexpand\csname #1parameter\endcsname + \expandafter\noexpand\csname #1parameterhash\endcsname + \expandafter\noexpand\csname do#1parameter\endcsname + \expandafter\noexpand\csname do#1parentparameter\endcsname + \expandafter\noexpand\csname do#1rootparameter\endcsname + \expandafter\noexpand\csname setupcurrent#1\endcsname + \expandafter\noexpand\csname inherited#1framed\endcsname + \expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new + +\protected\def\mult_interfaces_install_inherited_framed#1#2#3#4#5#6#7#8#9% + {\enforced\frozen\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% + \enforced\frozen\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root + \frozen\instance\protected\def#8% + {\bgroup + \bgroup + \inframedtrue + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% + \pack_framed_process_indeed}% + \frozen\instance\protected\def#9% + {\bgroup + \inframedtrue + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% + \pack_framed_process_box_indeed}} + +\permanent\protected\def\installframedcommandhandler#1#2#3% + {\installcommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +\permanent\protected\def\installframedautocommandhandler#1#2#3% + {\installautocommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +\permanent\protected\def\installsimpleframedcommandhandler#1#2#3% + {\installsimplecommandhandler{#1}{#2}{#3}% + \installinheritedframed{#2}} + +% for regular framed + +\setupframed + [\c!width=\v!fit, + \c!height=\v!broad, + %\c!minheight=\zeropoint, + %\c!lines=, + \c!offset=.25\exheight, % \defaultframeoffset + \c!empty=\v!no, + \c!frame=\v!on, + %\c!topframe=, + %\c!bottomframe=, + %\c!leftframe=, + %\c!rightframe=, + \c!radius=.5\bodyfontsize, + \c!rulethickness=\linewidth, + \c!corner=\v!rectangular, + \c!depth=\zeropoint, + %\c!foregroundcolor=, + %\c!foregroundstyle=, + %\c!background=, + %\c!backgroundcolor=, + \c!backgroundoffset=\zeropoint, + %\c!framecolor=, + \c!frameoffset=\zeropoint, + \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here + \c!backgroundradius=\framedparameter\c!radius, + \c!backgrounddepth=\framedparameter\c!depth, + \c!framecorner=\framedparameter\c!corner, + \c!frameradius=\framedparameter\c!radius, + \c!framedepth=\framedparameter\c!depth, + %\c!component=, + %\c!region=, + %\c!align=, + \c!bottom=\vss, + %\c!top=, + \c!strut=\v!yes, + \c!autostrut=\v!yes, + \c!location=\v!normal, + %\c!orientation=, + %\c!anchoring=, + \c!autowidth=\v!yes, + %\c!setups=, + \c!loffset=\zeropoint, + \c!roffset=\zeropoint, + \c!toffset=\zeropoint, + \c!boffset=\zeropoint] + +%D For backgrounds and such: + +\defineframed + [\??simplifiedframed] + [\c!frame=\v!off, + \c!depth=\zeropoint, + \c!offset=\v!overlay, + \c!component=, + \c!region=, + \c!radius=.5\bodyfontsize, + \c!rulethickness=\linewidth, + \c!corner=\v!rectangular, + \c!backgroundoffset=\zeropoint, + \c!frameoffset=\zeropoint, + \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here + \c!backgroundradius=\framedparameter\c!radius, + \c!backgrounddepth=\framedparameter\c!depth, + \c!framecorner=\framedparameter\c!corner, + \c!frameradius=\framedparameter\c!radius, + \c!framedepth=\framedparameter\c!depth, + \c!location=\v!normal, + \c!loffset=\zeropoint, + \c!roffset=\zeropoint, + \c!toffset=\zeropoint, + \c!boffset=\zeropoint] + +\permanent\protected\def\definesimplifiedframed[#1]% no settings + {\defineframed[#1][\??simplifiedframed]% + \enforced\letcsname#1\endcsname\undefined} + +\letcsname\??simplifiedframed\endcsname\undefined + +%D We will communicate through module specific variables, current framed +%D parameters and some reserved dimension registers. + +\newdimen\d_framed_target_wd +\newdimen\d_framed_target_ht +\newdimen\d_framed_target_dp +\newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end + +\let\p_framed_frame \empty % \framedparameter\c!frame +\let\p_framed_backgroundoffset\empty +\let\p_framed_foregroundstyle \empty +\let\p_framed_autostrut \empty +\let\p_framed_location \empty +\let\p_framed_orientation \empty +\let\p_framed_anchoring \empty +\let\p_framed_autowidth \empty +\let\p_framed_franalyze \empty +\let\p_framed_backgroundcorner\empty +\let\p_framed_backgroundradius\empty +\let\p_framed_framecorner \empty +\let\p_framed_frameradius \empty +\let\p_framed_lines \empty +\let\p_framed_empty \empty +\let\p_framed_backgroundcolor \empty +\let\p_framed_framecolor \empty +\let\p_framed_component \empty +\let\p_framed_background \empty +\let\p_framed_rulethickness \empty +\let\p_framed_foregroundcolor \empty +\let\p_framed_setups \empty + +%D We don't have to stick to a \TEX\ drawn rule, but also can use rounded +%D or even fancier shapes, as we will see later on. + +\def\pack_framed_filled_box + {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}% + \ifx\p_framed_backgroundcorner\v!rectangular + \pack_framed_filled_box_normal + \else + \pack_framed_filled_box_radius + \fi} + +\def\pack_framed_filled_box_normal + {\vrule + \s!width \d_framed_target_wd + \s!height\d_framed_target_ht + \s!depth \d_framed_target_dp + \relax} + +\def\pack_framed_filled_box_radius + {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}% + \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize + \pack_framed_filled_box_normal + \else + \pack_framed_filled_box_round + \fi} + +\def\pack_framed_filled_box_round + {\raise\d_framed_target_dp\hpack{\frule + type fill + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_backgroundradius\space + corner {\p_framed_backgroundcorner} + \relax}} + +\def\pack_framed_stroked_box + {\edef\p_framed_framecorner{\framedparameter\c!framecorner}% + \ifx\p_framed_framecorner\v!rectangular + \pack_framed_stroked_box_normal + \else + \pack_framed_stroked_box_radius + \fi} + +\def\pack_framed_stroked_box_radius + {\edef\p_framed_frameradius{\framedparameter\c!frameradius}% + \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize + \pack_framed_stroked_box_normal + \orelse\ifx\p_framed_frame\v!on + \pack_framed_stroked_box_round + \fi} + +% \pack_framed_stroked_box_normal % later + +\def\pack_framed_stroked_box_round + {\raise\d_framed_target_dp\hpack{\frule + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_frameradius\space + corner {\p_framed_framecorner} + \relax}} + +% a lot of weird corners +% +% \startTEXpage +% \dontleavehmode\framed +% [corner=0,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \vskip1em +% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green, +% background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \vskip1em +% \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed +% [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% +% \quad} +% \stopTEXpage + +%D It won't be a surprise that we not only provide gray boxes, but also colored +%D ones. Here it is: + +\def\pack_framed_background_box_color + {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}% + \ifempty\p_framed_backgroundcolor \else + \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed + \fi} + +\def\pack_framed_background_box_color_indeed + {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}} + +%D \macros +%D {defineoverlay, doifoverlayelse, overlayoffset, +%D overlaywidth, overlayheight, overlaydepth, +%D overlaycolor, overlaylinecolor, overlaylinewidth} +%D +%D Before we define the macro that actually takes card of the backgrounds, we +%D introduce overlays. An overlay is something that contrary to its name lays {\em +%D under} the text. An example of an overlay definition is: +%D +%D \startbuffer[tmp-1] +%D \defineoverlay +%D [fancy] +%D [{\externalfigure +%D [mp-cont.502] +%D [width=\overlaywidth, +%D height=\overlayheight]}] +%D \stopbuffer +%D +%D \typebuffer[tmp-1] +%D +%D That for instance can be uses in: +%D +%D \startbuffer[tmp-2] +%D \framed[backgroundachtergrond=fancy]{How Fancy!} +%D \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!} +%D \stopbuffer +%D +%D and looks like: +%D +%D \startlinecorrection +%D \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]} +%D \stoplinecorrection +%D +%D The formal definition is: +%D +%D \showsetup{defineoverlay} +%D +%D This macro's definition is a bit obscure, due the many non||used arguments and +%D the two step call that enable the setting of the width, height and depth +%D variables. Multiple backgrounds are possible and are specified as: +%D +%D \starttyping +%D \framed[background={one,two,three}]{Three backgrounds!} +%D \stoptyping +%D +%D Most drawing packages only know width and height. Therefore the dimensions have a +%D slightly different meaning here: +%D +%D \startitemize[packed] +%D \item \type{\overlaywidth }: width of the overlay +%D \item \type{\overlayheight}: height plus depth of the overlay +%D \item \type{\overlaydepth }: depth of the overlay +%D \stopitemize +%D +%D The resulting box is lowered to the right depth. + +\newdimen\d_overlay_width +\newdimen\d_overlay_height +\newdimen\d_overlay_depth +\newdimen\d_overlay_offset +\newdimen\d_overlay_linewidth + +\let\m_overlay_region\empty + +% expandable ... in a future version the space will go (in mp one can use Overlay*) + +\mutable \def\overlaywidth {\the\d_overlay_width \space} % We preset the variables +\mutable \def\overlayheight {\the\d_overlay_height \space} % to some reasonable default +\mutable \def\overlaydepth {\the\d_overlay_depth \space} % values. +\mutable \def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) +\mutable \def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. +\mutable \def\overlayregion {\m_overlay_region} + +\mutable \def\overlayradius {\framedparameter\c!frameradius} +\mutable \def\overlaycolor {\framedparameter\c!backgroundcolor} +\mutable \def\overlaylinecolor {\framedparameter\c!framecolor} +%mutable \edef\overlaycorner {\framedparameter\c!backgroundcorner} +%mutable \edef\overlayradius {\framedparameter\c!backgroundradius} + +\permanent\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} +\permanent\def\usedoverlayheight {\dimexpr\d_overlay_height \relax} +\permanent\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} +\permanent\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} +\permanent\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax} + +%D The next register is used to initialize overlays. + +\newtoks\everyoverlay + +%D An example of an initialization is the following (overlays can contain text +%D and be executed under an regime where interlineskip is off). + +\installcorenamespace{overlay} +\installcorenamespace{overlaybuiltin} + +\appendtoks + \oninterlineskip +\to \everyoverlay + +\prependtoks + \hsize\d_overlay_width + \vsize\d_overlay_height +\to \everyoverlay + +\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded + {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% + \processcommalist[#1]\pack_framed_define_overlay_indeed} + +\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions + {\bgroup % redundant grouping + \setlayoutcomponentattribute{\v!overlay:#1}% + \setbox\scratchbox\hbox \layoutcomponentboxattribute{\the\everyoverlay#2}% + \boxxoffset\scratchbox-.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width + \boxyoffset\scratchbox-.5\dimexpr\ht\scratchbox-\d_framed_target_ht+\d_framed_target_dp\relax % not \d_overlay_height ! + \wd\scratchbox\d_framed_target_wd + \ht\scratchbox\d_framed_target_ht + \dp\scratchbox\d_framed_target_dp + \box\scratchbox + \egroup} + +%D \macros +%D {overlayfakebox} + +\permanent\protected\def\overlayfakebox + {\hpack % redundant but needs testing + {\novrule + \s!width \d_overlay_width + \s!height\d_overlay_height + \s!depth \zeropoint}} + +%D For testing we provide: + +\permanent\def\doifelseoverlay#1% only tests external overlays + {\ifcsname\??overlay#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifoverlayelse\doifelseoverlay + +%D The content of the box will be (temporary) saved in a box. We also have an +%D extra box for backgrounds. + +\newbox\b_framed_normal +\newbox\b_framed_extra + +\newtoks\everybackgroundbox + +\let\m_framed_background\empty % we might need a public name + +\def\pack_framed_process_background + {\ifcsname\??overlaybuiltin\m_framed_background\endcsname + \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs + \orelse\ifcsname\??overlay\m_framed_background\endcsname + \expandafter\pack_framed_process_background_indeed_external\lastnamedcs + \fi} + +\def\pack_framed_process_background_indeed_internal#1% % : in name + {\bgroup + \setbox\b_framed_extra\hpack\bgroup + \ifzeropt\framedbackgroundoffset\else + \kern-\framedbackgroundoffset + \fi + \hbox\bgroup#1\egroup + \egroup + \wd\b_framed_extra\zeropoint + \ht\b_framed_extra\framedbackgroundheight + \dp\b_framed_extra\framedbackgrounddepth + \box\b_framed_extra + \egroup} + +\def\pack_framed_process_background_indeed_external + {\pack_framed_overlay_initialize + \pack_framed_process_background_indeed_internal} + +\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground) + {\edef\m_framed_background{#1}% + \ifx\m_framed_background\s!unknown\else + \pack_framed_process_background + \expandafter\pack_framed_process_backgrounds + \fi#2} + +%D Beware, a backgroundbox can be empty which is another reason why we set the +%D width to zero instead of back-skipping. + +\newdimen\framedbackgroundwidth +\newdimen\framedbackgroundheight +\newdimen\framedbackgrounddepth +\newdimen\framedbackgroundoffset + +\def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise + {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight + +\def\pack_framed_set_region % experiment + {\ifx\m_overlay_region\v!yes + \edef\m_overlay_region{\reservedautoregiontag}% + \fi} + +\def\pack_framed_add_region % experiment + {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} + +\def\pack_framed_add_background + {\setbox\b_framed_normal\hpack % was vbox % see also *1* + {%\pack_framed_forgetall % can be relaxed + \boxmaxdepth\maxdimen + \framedbackgroundoffset\d_framed_backgroundoffset + \framedbackgroundwidth \wd\b_framed_normal + \framedbackgroundheight\ht\b_framed_normal + \framedbackgrounddepth \dp\b_framed_normal + \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax + \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax + \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax + \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed + \ifempty\p_framed_component + \resetlayoutcomponentattribute + \else + \setlayoutcomponentattribute{\v!background:\p_framed_component}% + \fi + \let\foregroundbox\pack_framed_background_box_content + \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay + \the\everybackgroundbox % moved + \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it + \box\b_framed_normal + \hss + \egroup}} + +\def\pack_framed_overlay_initialize_indeed + {\d_overlay_width \d_framed_target_wd + \d_overlay_height \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax + \d_overlay_depth \d_framed_target_dp + \d_overlay_linewidth \d_framed_linewidth + \d_overlay_offset \framedbackgroundoffset\relax + % We expand these once: + \edef\overlaycolor {\framedparameter\c!backgroundcolor}% + \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers + % + \let\pack_framed_overlay_initialize\relax} + +%D One can explictly insert the foreground box. For that purpose we introduce the +%D overlay \type {foreground}. +%D +%D We predefine two already familiar backgrounds: + +%letvalue{\??overlaybuiltin\v!screen }\pack_framed_background_box_gray +\letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color +\letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox] + +%D We can specify overlays as a comma separated list of overlays, a sometimes +%D handy feature. +%D +%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled +%D borders). Again we have to deal with square and round corners. The first category +%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro +%D also support a negative offset. + +\def\pack_framed_add_outline + {\setbox\b_framed_normal\hpack % rules on top of box + {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax + \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax + \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax + \ifdim\d_framed_target_dp<\zeropoint + \advance\d_framed_target_ht \d_framed_target_dp + \scratchdimen-\d_framed_target_dp + \d_framed_target_dp\zeropoint + \else + \scratchdimen\zeropoint + \fi + \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background + \setbox\b_framed_extra\hpack + {\kern-\d_framed_frameoffset + \raise\scratchdimen + \hpack{\ifempty\overlaylinecolor\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}% + \wd\b_framed_extra\wd\b_framed_normal + \ht\b_framed_extra\ht\b_framed_normal + \dp\b_framed_extra\dp\b_framed_normal + \wd\b_framed_normal\zeropoint + \box\b_framed_normal + \box\b_framed_extra}} + +\def\pack_framed_stroked_box_normal_opened + {\setbox\scratchbox\vpack \bgroup + \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname + \nointerlineskip % new (needed for fences) + \hpack \bgroup + \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname + \novrule + \s!width \d_framed_target_wd + \s!height\d_framed_target_ht + \s!depth \d_framed_target_dp + \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname + \egroup + \nointerlineskip % new (needed for fences) + \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname + \egroup + \wd\scratchbox\d_framed_target_wd + \ht\scratchbox\d_framed_target_ht + \dp\scratchbox\d_framed_target_dp + \box\scratchbox} + +\def\pack_framed_stroked_box_normal_closed + {\hpack\bgroup + \scratchdimen.5\d_framed_linewidth + \hskip\scratchdimen + \clf_framedoutline + \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax + \dimexpr\d_framed_target_ht-\scratchdimen\relax + \dimexpr\d_framed_target_dp-\scratchdimen\relax + \d_framed_linewidth + \relax + \egroup} + +\def\pack_framed_stroked_box_normal + {\ifx\p_framed_frame\v!closed + \pack_framed_stroked_box_normal_closed + \else + \pack_framed_stroked_box_normal_opened + \fi} + +\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} +\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} +\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} +\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth} + +\letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule +\letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule +\letvalue{\??framedtop \v!on }\pack_framed_t_rule + +\letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule +\letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule +\letvalue{\??framedbottom\v!on }\pack_framed_b_rule + +\letvalue{\??framedleft \v!on \v!on}\pack_framed_l_rule +\letvalue{\??framedleft \v!off\v!on}\pack_framed_l_rule +\letvalue{\??framedleft \v!on }\pack_framed_l_rule + +\letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule +\letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule +\letvalue{\??framedright \v!on }\pack_framed_r_rule + +% no overlapping rules + +\def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} +\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} +\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} +\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} + +\letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules +\letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules +\letvalue{\??framedtop \v!small }\pack_framed_t_rules + +\letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules +\letvalue{\??framedbottom\v!off \v!small}\pack_framed_b_rules +\letvalue{\??framedbottom\v!small }\pack_framed_b_rules + +\letvalue{\??framedleft \v!small\v!small}\pack_framed_l_rules +\letvalue{\??framedleft \v!off \v!small}\pack_framed_l_rules +\letvalue{\??framedleft \v!small }\pack_framed_l_rules + +\letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules +\letvalue{\??framedright \v!off \v!small}\pack_framed_r_rules +\letvalue{\??framedright \v!small }\pack_framed_r_rules + +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on] +% {} +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small] +% {} +% \framed +% [width=4cm,height=3cm,rulethickness=3mm, +% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on] +% {} + +%D The next few macros are probably the most misused ones in \CONTEXT. They deal +%D with putting rules around boxes, provide backgrounds, offer alignment features, +%D and some more. We start with defining some booleans. These give an impression of +%D what we are going to take into account. + +% todo : \c_framed_hasoffset +% faster : \let\c_framed_hasoffset\falseconditional + +\newconditional\c_framed_has_offset +\newconditional\c_framed_has_width +\newconditional\c_framed_has_height +\newconditional\c_framed_has_format +\newconditional\c_framed_is_overlaid +\newconditional\c_framed_has_frame +\newconditional\c_framed_has_extra_offset +\newconditional\c_framed_text_location_none + +\newconstant \c_framed_has_strut % 0=relaxes 1=pseudostruts 2=realstruts + +%D \macros +%D {framed, setupframed} +%D +%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile +%D and, although some users will probably seldom use it, one cannot overlook its +%D features. +%D +%D \showsetup{setupframed} +%D \showsetup{framed} +%D +%D This general macro is a special version of an even more general case, that can +%D easily be linked into other macros that need some kind of framing. The local +%D version is called with an extra parameter: the variable identifier. The reason +%D for passing this identifier between brackets lays in the mere fact that this way +%D we can use the optional argument grabbers. + +\def\defaultframeoffset{.25\exheight} + +\installcorenamespace{regularframedlevel} + +\permanent\protected\def\installregularframed#1% + {\defineframed[#1]} + +\permanent\protected\def\presetlocalframed[#1]% + {\defineframed[#1]} + +% \presetlocalframed[\??framed] + +\newcount\c_pack_framed_nesting + +\permanent\tolerant\protected\def\framed[#1]% + {\bgroup + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here !, seldom no argument so no need to optimize + \pack_framed_process_indeed} + +\permanent\tolerant\protected\def\startframed[#1]#*[#2]% + {\bgroup + \ifarguments + \pack_framed_initialize + \bgroup + \or + \ifhastok={#1}% + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here ! + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \fi + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#2]% here ! + \fi + \pack_framed_process_indeed + \bgroup + \ignorespaces} + +% till here + +\permanent\protected\def\stopframed + {\removeunwantedspaces + \egroup} + +\permanent\protected\def\normalframedwithsettings[#1]% + {\bgroup + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \bgroup + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \setupcurrentframed[#1]% + \pack_framed_process_indeed} + +%D \startbuffer +%D \setupframed [framecolor=yellow] \framed{A} +%D \defineframed[myframed] [framecolor=blue] \myframed{B} +%D \setupframed [myframed] [framecolor=red] \myframed{C} +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \presetlocalframed[myframed] +%D \localframed[myframed][framecolor=green]{oeps} +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {ifinframed} +%D +%D The normal case first presets all parameters and next starts looking for the user +%D supplied ones. The first step is omitted in the local case, because these are +%D preset at declaration time and keep their values unless explictly changed. By +%D presetting the variables everytime the normal command is called, we can use this +%D command nested, without the unwanted side effect of inheritance. The boolean is +%D used to speed up the color stack. + +\newif\ifinframed + +%D The next one is faster on multiple backgrounds per page. No dimensions can be +%D set, only frames and backgrounds. + +%% \protected\def\fastlocalframed[#1]#2[#3]#4% 3-4 + +\permanent\protected\def\fastlocalframed[#1]#*[#2]#3% + {\bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \setbox\b_framed_normal\hbox{#3}% + \iftrialtypesetting \else + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_region + \fi + \fi + \setupcurrentframed[#2]% + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds + \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds + \edef\p_framed_frame{\framedparameter\c!frame}% + \edef\p_framed_background{\framedparameter\c!background}% + % not here, in calling macro: setups + \pack_framed_remove_depth + \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else + \ifempty\p_framed_rulethickness\else + \d_framed_linewidth\p_framed_rulethickness\relax + \fi + \pack_framed_add_outline % real or invisible frame + \fi + \ifempty\p_framed_background \else + \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% + \d_framed_backgroundoffset + \ifx\p_framed_backgroundoffset\v!frame + \d_framed_frameoffset + \else + \p_framed_backgroundoffset + \fi + \edef\p_framed_component{\framedparameter\c!component}% + \pack_framed_add_background + \fi + \pack_framed_restore_depth + \iftrialtypesetting\orelse\ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \box\b_framed_normal + \egroup} + +%D The next macro uses a box and takes its natural width and height so these +%D can better be correct. + +\protected\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) + {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2 + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_region + \fi + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds + \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds + \edef\p_framed_frame{\framedparameter\c!frame}% + \edef\p_framed_background{\framedparameter\c!background}% + \ifx\p_framed_frame\v!overlay \orelse \ifx\p_framed_frame\v!none \else + \ifempty\p_framed_rulethickness \else + \d_framed_linewidth\p_framed_rulethickness\relax + \fi + \pack_framed_add_outline % real or invisible frame + \fi + \ifempty\p_framed_background \else + \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% + \d_framed_backgroundoffset + \ifx\p_framed_backgroundoffset\v!frame + \d_framed_frameoffset + \else + \p_framed_backgroundoffset + \fi + \edef\p_framed_component{#1}% + \pack_framed_add_background + \fi + \ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \box\b_framed_normal + \egroup} + +\protected\def\localbackgroundframed#1% namespace component box + {\bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \pack_framed_process_box_indeed} % group ends here + +\let\postprocessframebox\relax + +%D A nice example by Aditya: +%D +%D \starttyping +%D \setupframed +%D [loffset=\framedparameter{hoffset}, +%D roffset=\framedparameter{hoffset}, +%D hoffset=\zeropoint] +%D +%D \defineframed[test][hoffset=1cm] +%D \stoptyping + +\newdimen\d_framed_width +\newdimen\d_framed_height +\newdimen\d_framed_frameoffset +\newdimen\d_framed_backgroundoffset +\newdimen\d_framed_local_offset + +% todo: protect local \framednames + +\permanent\tolerant\protected\def\localframed[#1]#*[#2]% + {\bgroup + \bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \setupcurrentframed[#2]% here ! + \pack_framed_process_indeed} + +\permanent\protected\def\directlocalframed[#1]% no optional + {\bgroup + \bgroup + \edef\currentframed{#1}% + \pack_framed_initialize + \pack_framed_process_indeed} + +\aliased\let\localframedwithsettings\localframed + +% done + +\defineinterfaceconstant {fr!analyze} {fr:analyze} % private option + +\let\delayedbegstrut\relax +\let\delayedendstrut\relax +\let\delayedstrut \relax + +\let\localoffset\empty +\let\localwidth \empty +\let\localheight\empty +\let\localformat\empty +\let\localstrut \empty + +\protected\def\pack_framed_process_indeed + {\d_framed_frameoffset\framedparameter\c!frameoffset + \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% + \d_framed_backgroundoffset + \ifx\p_framed_backgroundoffset\v!frame + \d_framed_frameoffset + \else + \p_framed_backgroundoffset + \fi + % new, experimental dirty hook + \framedparameter\c!extras + % to get the right spacing + \edef\p_framed_foregroundstyle{\framedparameter\c!foregroundstyle}% + \ifempty\p_framed_foregroundstyle\else\dousestyleparameter\p_framed_foregroundstyle\fi + % beware, both the frame and background offset can be overruled + % + \edef\p_framed_setups{\framedparameter\c!setups}% + % the next macros are visible + \edef\localoffset{\framedparameter\c!offset}% + \edef\localwidth {\framedparameter\c!width}% + \edef\localheight{\framedparameter\c!height}% + \edef\localformat{\framedparameter\c!align}% + % + \edef\p_strut {\framedparameter\c!strut}% + % these are not + \edef\p_framed_autostrut {\framedparameter\c!autostrut}% + \edef\p_framed_frame {\framedparameter\c!frame}% + \edef\p_framed_location {\framedparameter\c!location}% + \edef\p_framed_orientation{\framedparameter\c!orientation}% + \edef\p_framed_anchoring {\framedparameter\c!anchoring}% + % + \edef\p_framed_autowidth {\framedparameter\c!autowidth}% + \edef\p_framed_franalyze {\framedparameter\c!fr!analyze}% experimental option + % + \ifx\p_framed_frame\v!overlay % no frame, no offset, no framewidth + \setfalse\c_framed_has_frame + \let\localoffset\v!overlay + \orelse\ifx\p_framed_frame\v!none % no frame, no framewidth + \setfalse\c_framed_has_frame + \else + \settrue\c_framed_has_frame + \fi + \ifconditional\c_framed_has_frame + \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% + \ifempty\p_framed_rulethickness\else + \d_framed_linewidth\p_framed_rulethickness\relax + \fi + \else + \d_framed_linewidth\zeropoint + \fi + % 2013/03/12: a change of order (sizes before align + \ifx\localwidth\v!local + \setlocalhsize + \fi + % + \forgetall % should happen after \localwidth but before align + % + \ifempty\localformat + \setfalse\c_framed_has_format + \else + \settrue\c_framed_has_format + \dosetraggedcommand\localformat % not that fast + \fi + % + \ifcsname\??framedoffsetalternative\localoffset\endcsname + \lastnamedcs + \else + \framed_offset_alternative_unknown + \fi + \ifcsname\??framedwidthalternative\localwidth\endcsname + \lastnamedcs + \else + \framed_width_alternative_unknown + \fi + \ifcsname\??framedheightalternative\localheight\endcsname + \lastnamedcs + \else + \framed_height_alternative_unknown + \fi + % the next check could move to heightalternative + \ifconditional\c_framed_has_height + % obey user set height, also downward compatible + \else + \edef\p_framed_lines{\framedparameter\c!lines}% + \ifempty\p_framed_lines + \orelse\ifcase\p_framed_lines + \else + \d_framed_height\p_framed_lines\lineheight + \edef\localheight{\the\d_framed_height}% + \settrue\c_framed_has_height + \fi + \fi + % this is now an option: width=local + % + % \ifdim\d_framed_width=\hsize + % \parindent\zeropoint + % \setlocalhsize + % \d_framed_width\localhsize + % \fi + % i.e. disable (colsetbackgroundproblemintechniek) + \advance\d_framed_width -2\d_framed_local_offset + \advance\d_framed_height -2\d_framed_local_offset + \ifcsname\??framedstrutalternative\p_strut\endcsname + \lastnamedcs + \else + \framed_offset_alternative_unknown + \fi + % the next check could move to strutalternative + \ifcase\c_framed_has_strut % none (not even noindent) + \enforced\let\localbegstrut\relax + \enforced\let\localendstrut\relax + \enforced\let\localstrut \relax + \or % no / overlay + \enforced\let\localbegstrut\pseudobegstrut + \enforced\let\localendstrut\pseudoendstrut + \enforced\let\localstrut \pseudostrut + \else + \enforced\let\localbegstrut\begstrut + \enforced\let\localendstrut\endstrut + \enforced\let\localstrut \strut + \fi + \ifx\p_framed_autostrut\v!yes + \enforced\let\delayedbegstrut\relax + \enforced\let\delayedendstrut\relax + \enforced\let\delayedstrut \relax + \else + \enforced\let\delayedbegstrut\localbegstrut + \enforced\let\delayedendstrut\localendstrut + \enforced\let\delayedstrut \localstrut + \enforced\let\localbegstrut \relax + \enforced\let\localendstrut \relax + \enforced\let\localstrut \relax + \fi + \ifconditional\c_framed_has_height + \enforced\let\\\pack_framed_vboxed_newline + \ifconditional\c_framed_has_width + \enforced\let\hairline\pack_framed_vboxed_hairline + \ifconditional\c_framed_has_format + \let\next\pack_framed_format_format_yes + \else + \let\next\pack_framed_format_format_nop + \fi + \else + \enforced\let\hairline\pack_framed_hboxed_hairline + \ifconditional\c_framed_has_format + \let\next\pack_framed_format_format_height + \else + \let\next\pack_framed_format_format_vsize + \fi + \fi + \orelse\ifconditional\c_framed_has_width + \ifconditional\c_framed_has_format + \enforced\let\\\pack_framed_vboxed_newline + \enforced\let\hairline\pack_framed_vboxed_hairline + \let\next\pack_framed_format_format_width + \else + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline + \let\next\pack_framed_format_format_hsize + \fi + \else + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline + \let\next\pack_framed_format_format_no_size + \fi + \pack_framed_check_extra_offsets + \edef\p_framed_background{\framedparameter\c!background}% +% \ifempty\p_framed_background +% \let\pack_framed_forgetall\forgetall +% \else +% \let\pack_framed_forgetall\relax +% \forgetall +% \fi + \edef\framedwidth {\the\ifdim\d_framed_width >\zeropoint \d_framed_width \else\zeropoint\fi}% public + \edef\framedheight{\the\ifdim\d_framed_height>\zeropoint \d_framed_height\else\zeropoint\fi}% public + \edef\framedoffset{\the\dimexpr\ifconditional\c_framed_has_offset\localoffset \else\zeropoint\fi}% public + \ifempty\p_framed_orientation + \let\pack_framed_stop_orientation\relax + \else + \pack_framed_start_orientation + \fi + \afterassignment\pack_framed_restart + \setbox\b_framed_normal\next} + +% alternatives for width, height, strut and offset + +\installcorenamespace{framedwidthalternative} +\installcorenamespace{framedheightalternative} +\installcorenamespace{framedstrutalternative} +\installcorenamespace{framedoffsetalternative} + +% widths + +\setvalue{\??framedwidthalternative\empty}% + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!fit}% + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!broad}% + {\settrue\c_framed_has_width + \d_framed_width\hsize} + +\setvalue{\??framedwidthalternative\v!max}% idem broad + {\settrue\c_framed_has_width + \d_framed_width\hsize} + +\setvalue{\??framedwidthalternative\v!local}% + {\settrue\c_framed_has_width + %\setlocalhsize + \d_framed_width\localhsize} + +\setvalue{\??framedwidthalternative\s!unknown}% + {\settrue\c_framed_has_width + \d_framed_width\localwidth} + +\def\framed_width_alternative_unknown + {\settrue\c_framed_has_width + \d_framed_width\localwidth} + +% heights + +\setvalue{\??framedheightalternative\empty}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!fit}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!broad}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!max}% + {\settrue\c_framed_has_height + \d_framed_height\vsize} + +\setvalue{\??framedheightalternative\s!unknown}% + {\settrue\c_framed_has_height + \d_framed_height\localheight} + +\def\framed_height_alternative_unknown + {\settrue\c_framed_has_height + \d_framed_height\localheight} + +% struts (use let instead?) + +\setvalue{\??framedstrutalternative\v!no}% + {\c_framed_has_strut\plusone} + +\setvalue{\??framedstrutalternative\v!global}% + {\setstrut} + +\setvalue{\??framedstrutalternative\v!local}% + {\setfontstrut} + +\setvalue{\??framedstrutalternative\v!yes}% + {\setstrut} + +\setvalue{\??framedstrutalternative\s!unknown}% + {\setstrut} + +\def\framed_strut_alternative_unknown + {\setstrut} + +\setvalue{\??framedstrutalternative\v!none}% not even pseudo struts + {\c_framed_has_strut\zerocount} + +% offsets + +\setvalue{\??framedoffsetalternative\v!none}% + {\setfalse\c_framed_has_offset + \c_framed_has_strut\plusone + \setfalse\c_framed_is_overlaid + \d_framed_local_offset\d_framed_linewidth} + +\setvalue{\??framedoffsetalternative\v!overlay}% + {% \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first + \setfalse\c_framed_has_offset + \c_framed_has_strut\plusone + \settrue\c_framed_is_overlaid + \d_framed_local_offset\zeropoint} + +% \setvalue{\??framedoffsetalternative\v!strut}% +% {\setfalse\c_framed_has_offset +% \c_framed_has_strut\plustwo +% \settrue\c_framed_is_overlaid +% \d_framed_local_offset\zeropoint} + +\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000 + {\settrue \c_framed_has_offset + \c_framed_has_strut\plustwo + \setfalse\c_framed_is_overlaid + \let\localoffset\defaultframeoffset + \letframedparameter\c!offset\defaultframeoffset % brrr + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +\def\framed_offset_alternative_unknown + {\settrue \c_framed_has_offset + \c_framed_has_strut\plustwo + \setfalse\c_framed_is_overlaid + \let\defaultframeoffset\localoffset + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +\letvalue{\??framedoffsetalternative\s!unknown}\framed_offset_alternative_unknown + +% so far for alternatives + +\let\pack_framed_stop_orientation\relax + +\def\pack_framed_restart + {\aftergroup\pack_framed_finish} + +\def\pack_framed_do_top + {\raggedtopcommand + \framedparameter\c!top + \edef\p_blank{\framedparameter\c!blank}% + \ifx\p_blank\v!yes\else % auto or no + \doinhibitblank + \fi} + +\def\pack_framed_do_bottom + {\framedparameter\c!bottom + \raggedbottomcommand} + +%D Careful analysis of this macro will learn us that not all branches in the last +%D conditionals can be encountered, that is, some assignments to \type{\next} will +%D never occur. Nevertheless we implement the whole scheme, if not for future +%D extensions. + +%D \macros +%D {doassigncheckedframeoffset} +%D +%D Offset helper (see menus): + +\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname + {\edef\checkedframeoffset{#2}% + #1% + \ifempty\checkedframeoffset \zeropoint\orelse + \ifx\checkedframeoffset\v!overlay\zeropoint\orelse + \ifx\checkedframeoffset\v!none \zeropoint\orelse + \ifx\checkedframeoffset\v!frame \zeropoint\orelse + \ifx\checkedframeoffset\v!default\zeropoint\else + #2% + \fi + \relax} + +%D \macros +%D {ifreshapeframebox} +%D +%D The last few lines tell what to do after the content of the box is collected and +%D passed to the next macro. In the case of a fixed width and centered alignment, +%D the content is evaluated and used to determine the most natural width. The rest +%D of the code deals with backgrounds and frames. + +\newif\ifreshapeframebox \reshapeframeboxtrue + +%D Beware: setting \type {top} and \type {bottom} to nothing, may +%D result in a frame that is larger that the given height! try: +%D +%D \starttyping +%D \framed +%D [height=3cm,top=,bottom=,offset=overlay] +%D {\strut test \shapefill \strut test} +%D \stoptyping +%D +%D This is intended behaviour and not a bug! One can always set +%D +%D \starttyping +%D ...,bottom=\kern0pt,... +%D \stoptyping + +% experiment ... \p_framed_franalyze -> we could support 'first' as location key +% option but then we will always do an analysis and reimplement the location +% options (btw, beware of location settings of derived functionality that bleed +% into this + +\def\pack_framed_finish_a + {\ifreshapeframebox + \pack_framed_reshape_process + \orelse\ifx\p_framed_franalyze\v!yes + \pack_framed_reshape_analyze + \else + \pack_framed_reshape_reset + \fi + \setfalse\c_framed_has_width} + +\def\pack_framed_finish_b + {\ifx\p_framed_franalyze\v!yes + \pack_framed_reshape_analyze + \else + \pack_framed_reshape_reset + \fi + \setfalse\c_framed_has_width} + +\def\pack_framed_finish_c + {\ifx\p_framed_franalyze\v!yes + \pack_framed_reshape_analyze + \else + \pack_framed_reshape_reset + \fi} + +\def\pack_framed_profile_box + {\profilegivenbox\p_profile\b_framed_normal + \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}} + +\def\pack_framed_reverse_box + {\ifvbox\b_framed_normal + \edef\p_linedirection{\framedparameter\c!linedirection}% + \ifx\p_linedirection\v!reverse + \reversevboxcontent\b_framed_normal + \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}% + \fi + \fi} + +\protected\def\pack_framed_finish + {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down + \pack_framed_locator_before\p_framed_location + \ifconditional\c_framed_has_format + %\ifconditional\c_framed_has_height \else + % \edef\p_profile{\framedparameter\c!profile}% + % \ifempty\p_profile\else + % \pack_framed_profile_box + % \fi + %\fi + \ifempty\p_framed_anchoring\else + \pack_framed_reverse_box + \fi + \ifx\p_framed_autowidth\v!force + \pack_framed_finish_a + \orelse\ifx\localwidth\v!fit + \ifx\p_framed_autowidth\v!yes + \pack_framed_finish_a + \else + \pack_framed_finish_b + \fi + \orelse\ifx\localwidth\v!fixed + \pack_framed_finish_b + \else + \pack_framed_finish_c + \fi + \ifconditional\c_framed_has_height \else + \edef\p_profile{\framedparameter\c!profile}% + \ifempty\p_profile\else + \pack_framed_profile_box + \fi + \fi + \ifconditional\page_postprocessors_needed_box + % quite late + \page_postprocessors_linenumbers_box\b_framed_normal + \fi + \else + \pack_framed_finish_c + \fi + \ifconditional\c_framed_has_width + \wd\b_framed_normal\d_framed_width + \fi + \ifconditional\c_framed_has_height + \ht\b_framed_normal\d_framed_height + \else + \edef\p_framed_minheight{\framedparameter\c!minheight}% + \ifempty\p_framed_minheight \else + \ifdim\ht\b_framed_normal<\p_framed_minheight + \ht\b_framed_normal\p_framed_minheight + \fi + \fi + \fi + \edef\p_framed_empty{\framedparameter\c!empty}% + \ifx\p_framed_empty\v!yes + \pack_framed_fake_box + \fi + \ifempty\p_framed_anchoring\else + \pack_framed_handle_anchoring + \fi + \pack_framed_stop_orientation % moved here at 2014-05-25 + \iftrialtypesetting \else + \edef\m_overlay_region{\framedparameter\c!region}% + \ifempty\m_overlay_region\else + \pack_framed_set_region + \fi + \fi + \d_framed_applied_offset + \ifconditional\c_framed_is_overlaid + \zeropoint + \else + \d_framed_linewidth + \fi + \ifconditional\c_framed_has_offset + \advance\d_framed_applied_offset\localoffset\relax + \fi + \ifconditional\c_framed_has_extra_offset + \pack_framed_apply_extra_offsets % includes \d_framed_applied_offset + \else + \ifzeropt\d_framed_applied_offset + \else + \pack_framed_widen_box + \fi + \fi + % + \ifx\postprocessframebox\relax \else + % better: \pushmacro\\postprocessframebox etc + \let\next\postprocessframebox + \let\postprocessframebox\relax % prevent nesting + \next\b_framed_normal + \fi + \iftrialtypesetting + % new + \else + \ifconditional\c_framed_has_frame % real or invisible frame + \pack_framed_add_outline + \fi + \ifempty\p_framed_background \else + \edef\p_framed_component{\framedparameter\c!component}% + \pack_framed_add_background + \fi + \fi + \pack_framed_locator_after\p_framed_location + \iftrialtypesetting \else + \ifempty\m_overlay_region\else + \pack_framed_add_region + \fi + \fi + \box\b_framed_normal + \global\frameddimensionstate % global so to be used directly afterwards ! + \ifconditional\c_framed_has_width + \ifconditional\c_framed_has_height \plusthree \else \plusone \fi + \else + \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi + \fi + \egroup + \egroup} + +%D Anchoring is experimental and was prototyped around the ctx meeting in 2018 but +%D never mede it into the core yet. It operates independent of the orientation +%D mechanism already present. It's a rather efficient feature. Best is to use +%D predefined orientations, like: +%D +%D \starttyping +%D \defineorientation[leftflushleft] [orientation=left,horizontal=flushleft] +%D +%D \framed [anchoring={leftflushleft}] {anchoring} +%D \stoptyping +%D +%D But this also works: +%D +%D \starttyping +%D \framed [anchoring={flushleft,top,up}] {anchoring} +%D \stoptyping +%D +%D When an anchoring is given (use \type {normal} for the default) you can also +%D use the \type {xanchor} and \type {yanchor} offsets. + +% because we mess with the width later on, we need double wrapping: + +\def\pack_framed_handle_anchoring + {\scratchcounter\autoorientation\p_framed_anchoring\relax + \edef\p_xanchor{\framedparameter\c!xanchor}% + \edef\p_yanchor{\framedparameter\c!yanchor}% + \setbox\b_framed_normal\hpack{\hpack % here + % using the keyword approachs works ok, don't mess with orientation + % directly here using \boxorientation ... it doesn't work that well + \s!orientation\scratchcounter + \ifempty\p_xanchor\else \s!xoffset \p_xanchor\fi + \ifempty\p_yanchor\else \s!yoffset \p_yanchor\fi + {\box\b_framed_normal}}} + +\installcorenamespace{framedlocatorbefore} +\installcorenamespace{framedlocatorafter} + +\newconstant\frameddimensionstate % global state: 0=unknown 1=width 2=height 3=both + +\def\pack_framed_fake_box + {\setbox\scratchbox\emptyhbox + \wd\scratchbox\wd\b_framed_normal + \ht\scratchbox\ht\b_framed_normal + \dp\scratchbox\dp\b_framed_normal + \setbox\b_framed_normal\box\scratchbox} + +\def\installframedlocator#1#2#3% + {\setvalue{\??framedlocatorbefore#1}{#2}% + \setvalue{\??framedlocatorafter #1}{#3}} + +\def\pack_framed_locator_before#1{\begincsname\??framedlocatorbefore#1\endcsname} +\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname} + +\newdimen\d_framed_locator_ht +\newdimen\d_framed_locator_dp +\newdimen\d_framed_locator_lo +\newdimen\d_framed_locator_ro + +\def\pack_framed_locator_set#1% + {\d_framed_locator_ht\dimexpr + #1+\d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!toffset + \relax + \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax} + +\def\pack_framed_locator_set_lo + {\global\d_framed_locator_lo\dimexpr + \d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!loffset + \relax} + +\def\pack_framed_locator_set_ro + {\global\d_framed_locator_ro\dimexpr + \d_framed_linewidth + \ifconditional\c_framed_has_offset + +\framedparameter\c!offset + \fi + +\framedparameter\c!roffset + \relax} + +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=hanging]{location\\equals\\hanging} +% \framed[width=2cm,align=middle,location=depth] {location\\equals\\depth} +% \framed[width=2cm,align=middle,location=height] {location\\equals\\height} +% B} +% \vskip2cm +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=low] {location\\equals\\low} +% \framed[width=2cm,align=middle,location=line] {location\\equals\\line} +% \framed[width=2cm,align=middle,location=high] {location\\equals\\high} +% B} +% \vskip2cm +% \ruledhbox +% {A +% \framed[width=2cm,align=middle,location=top] {location\\equals\\top} +% \framed[width=2cm,align=middle,location=bottom] {location\\equals\\bottom} +% \framed[width=2cm,align=middle,location=lohi] {location\\equals\\lohi} +% \framed[width=2cm,align=middle,location=middle] {location\\equals\\middle} +% B} + +% \installframedlocator \v!hanging % best with strut=no +% {} +% {\dp\b_framed_normal\ht\b_framed_normal +% \ht\b_framed_normal\zeropoint} +% +% \installframedlocator \v!depth +% {} +% {\ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax +% \dp\b_framed_normal\strutdp +% \box\b_framed_normal} +% +% \installframedlocator \v!height +% {} +% {\dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax +% \ht\b_framed_normal\strutht +% \box\b_framed_normal} + +\installframedlocator \v!hanging % best with strut=no *1* / see mail to list by SB + {} + {\scratchdimen\ht\b_framed_normal + \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}% + \dp\b_framed_normal\scratchdimen + \ht\b_framed_normal\zeropoint + \box\b_framed_normal} + +\installframedlocator \v!depth % *1* + {} + {\setbox\b_framed_normal\hpack{\lower\strutdp\box\b_framed_normal}% + \ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax + \dp\b_framed_normal\strutdp + \box\b_framed_normal} + +\installframedlocator \v!height % *1* + {} + {\scratchdimen\dimexpr \ht\b_framed_normal - \strutht \relax + \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}% + \dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax + \ht\b_framed_normal\strutht + \box\b_framed_normal} + +\installframedlocator \v!high + {} + {\pack_framed_locator_set\strutht + \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}% + \ht\b_framed_normal\strutht + \dp\b_framed_normal\strutdp + \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing? + +\installframedlocator \v!line + {} + {\setbox\b_framed_normal\hpack{\lower.5\ht\b_framed_normal\box\b_framed_normal}% + \ht\b_framed_normal.5\lineheight + \dp\b_framed_normal.5\lineheight + \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing? + +\installframedlocator \v!low + {} + {\pack_framed_locator_set\strutdp + \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}% + \ht\b_framed_normal\strutht + \dp\b_framed_normal\strutdp + \box\b_framed_normal} + +\installframedlocator \v!top + {} + {\pack_framed_locator_set\strutht + \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}% + \ht\b_framed_normal\d_framed_locator_ht + \dp\b_framed_normal\d_framed_locator_dp + \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing? + +\installframedlocator \v!middle + {} + {\scratchdimen.5\ht\b_framed_normal + \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}% + \ht\b_framed_normal\scratchdimen + \dp\b_framed_normal\scratchdimen + \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing? + +\installframedlocator \v!lohi % maybe also \v!center + {\pack_framed_locator_before\v!middle} + {\pack_framed_locator_after \v!middle} + +\installframedlocator \v!bottom + {} + {\pack_framed_locator_set\strutdp + \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}% + \ht\b_framed_normal\d_framed_locator_dp + \dp\b_framed_normal\d_framed_locator_ht + \hpack{\box\b_framed_normal}} % why do we pack .. dange of loosing? + +\installframedlocator \v!keep % retains height/depth + {\pack_framed_remove_depth} + {\pack_framed_restore_depth} + +\newdimen\d_framed_formula + +\installframedlocator \v!formula % private, will become a more generic name + {} + {\pack_framed_locator_set\d_framed_formula + \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}% + \ht\b_framed_normal\d_framed_locator_ht + \dp\b_framed_normal\d_framed_locator_dp + \hpack{\box\b_framed_normal}} % why do we pack .. danger of loosing? + +% also used in fastlocalframed + +\newdimen\d_framed_original_wd +\newdimen\d_framed_original_ht +\newdimen\d_framed_original_dp + +\def\pack_framed_remove_depth + {\d_framed_original_wd\wd\b_framed_normal + \d_framed_original_ht\ht\b_framed_normal + \d_framed_original_dp\dp\b_framed_normal + \ifzeropt\d_framed_original_dp\else + \setbox\b_framed_normal\hpack{\raise\d_framed_original_dp\box\b_framed_normal}% + \fi + \wd\b_framed_normal\d_framed_original_wd + \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax + \dp\b_framed_normal\zeropoint} + +\def\pack_framed_restore_depth + {\ifzeropt\d_framed_original_dp \else + \setbox\b_framed_normal\hpack{\lower\d_framed_original_dp\box\b_framed_normal}% + \fi + \wd\b_framed_normal\d_framed_original_wd + \ht\b_framed_normal\d_framed_original_ht + \dp\b_framed_normal\d_framed_original_dp} + +% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=180]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=270]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-90]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax} +% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax} + +\def\pack_framed_start_orientation + {\ifcase\p_framed_orientation + \let\pack_framed_stop_orientation\relax + \else + \let\pack_framed_stop_orientation\pack_framed_stop_orientation_indeed + \fi} + +\def\pack_framed_stop_orientation_indeed + {\setbox\b_framed_normal\hpack{\dorotatebox\p_framed_orientation\hpack{\box\b_framed_normal}}% + \d_framed_height\ht\b_framed_normal + \d_framed_width \wd\b_framed_normal} + +%D The last conditional takes care of the special situation of in||line \inframed +%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the +%D running text. + +\permanent\tolerant\protected\def\inframed[#1]{\framed[\c!location=\v!low,#1]} + +%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background, +%D but no content, so actually we have a sort of phantom framed box. + +%D \macros +%D {mframed, minframed} +%D +%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the +%D next macro: +%D +%D \starttyping +%D \def\mframed#1% +%D {\relax +%D \ifmmode +%D \vcenter{\hbox{\framed{$\ifinner\else\displaystyle\fi#1$}}}% +%D \else +%D \framed{$#1$}% +%D \fi} +%D \stoptyping +%D +%D Because \type {\ifinner} does not (always) reports what one would expect, we move the +%D test to the outer level. We also want to pass arguments, +%D +%D \starttyping +%D \def\mframed% +%D {\dosingleempty\domframed} +%D +%D \def\domframed[#1]#2% % tzt \dowithnextmathbox ? +%D {\relax +%D \ifmmode +%D \ifinner +%D \inframed[#1]{$#2$}% +%D \else +%D \vcenter{\hbox{\framed[#1]{$\displaystyle#2$}}}% +%D \fi +%D \else +%D \inframed[#1]{$#2$}% +%D \fi} +%D \stoptyping +%D +%D Still better is the next alternative, if only because it takes care of setting the super- +%D and subscripts styles + +\newcount\c_framed_mstyle + +\protected\def\pack_framed_math_strut + {\Ustartmath + \triggermathstyle\c_framed_mstyle + \vphantom{(}% + \Ustopmath} + +\installcorenamespace{mathframed} + +\installframedcommandhandler \??mathframed {mathframed} \??mathframed + +\newcount\c_pack_framed_mathframed +\newtoks \t_pack_framed_mathframed + +\appendtoks + \frozen\instance\setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}% +\to \everydefinemathframed + +\protected\def\pack_framed_mathframed#1% + {\begingroup + \edef\currentmathframed{#1}% + \dosingleempty\pack_framed_mathframed_indeed} + +\def\pack_framed_math_pos + {\global\advance\c_pack_framed_mathframed\plusone + \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}% + \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}% + \xypos\pack_framed_mc_two} + +\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here + {\setupcurrentmathframed[#1]% + \c_framed_mstyle\normalmathstyle + \edef\m_framed_location{\mathframedparameter\c!location}% + \ifx\m_framed_location\v!mathematics + \enforced\let\normalstrut\pack_framed_math_pos + \orelse\ifx\m_framed_location\v!low\else + \enforced\let\normalstrut\pack_framed_math_strut + \fi + \inheritedmathframedframed\bgroup + \Ustartmath + \triggermathstyle\c_framed_mstyle + \the\t_pack_framed_mathframed + #2% + \Ustopmath + \egroup + \endgroup} + +\appendtoks + \mathraggedstatus\plustwo % makes \startalign work + \eqalignmode \zerocount % makes \startalign fit +\to \t_pack_framed_mathframed + +\installframedlocator \v!mathematics + {} + {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax + \hpack{\xypos\pack_framed_mc_one\box\b_framed_normal}} + +\definemathframed[mframed] +\definemathframed[inmframed][\c!location=\v!low] +\definemathframed[mcframed] [\c!location=\v!mathematics] + +%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}: +%D +%D \startbuffer +%D \startformula +%D x \times \mframed{y} \times y^{z_z} +%D x \times \inmframed{y} \times y^{z_z} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D And: +%D +%D \startbuffer +%D \startformula +%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D As usual, one can specify in what way the text should be framed. One should be +%D aware of the fact that, inorder to preserve the proper spacing, the \type +%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead. +%D +%D \startbuffer +%D \startformula +%D x \times y^{\mframed[framecolor=red]{z}_{z}} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D For inline use, we also provide the \type {\inmframed} alternative: we want $x +%D \times \inmframed{y}$ in inline math, right? + +%D This previous framing macros needs a lot of alternatives for putting rules around +%D boxes, inserting offsets and aligning text. Each step is handled by separate macros. + +\newdimen\d_framed_applied_offset +\newdimen\d_framed_loffset +\newdimen\d_framed_roffset +\newdimen\d_framed_toffset +\newdimen\d_framed_boffset + +\def\pack_framed_check_extra_offsets % we could check h and v indepently + {\setfalse\c_framed_has_extra_offset + \d_framed_loffset\framedparameter\c!loffset\relax + \d_framed_roffset\framedparameter\c!roffset\relax + \d_framed_toffset\framedparameter\c!toffset\relax + \d_framed_boffset\framedparameter\c!boffset\relax + \ifzeropt\d_framed_loffset\else \advance\d_framed_width -\d_framed_loffset \settrue\c_framed_has_extra_offset \fi + \ifzeropt\d_framed_roffset\else \advance\d_framed_width -\d_framed_roffset \settrue\c_framed_has_extra_offset \fi + \ifzeropt\d_framed_toffset\else \advance\d_framed_height-\d_framed_toffset \settrue\c_framed_has_extra_offset \fi + \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi} + +\def\pack_framed_apply_extra_offsets + {\setbox\b_framed_normal\vpack\bgroup + \advance\d_framed_toffset\d_framed_applied_offset + \advance\d_framed_boffset\d_framed_applied_offset + \advance\d_framed_loffset\d_framed_applied_offset + \advance\d_framed_roffset\d_framed_applied_offset + \kern\d_framed_toffset + \hpack\bgroup + \kern\d_framed_loffset + \box\b_framed_normal + \kern\d_framed_roffset + \egroup + \kern\d_framed_boffset + \egroup} + +\def\pack_framed_widen_box + {\setbox\b_framed_normal\vpack + {\kern\d_framed_applied_offset + \hpack{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}% + \kern\d_framed_applied_offset}} + +%D Let's hope that the next few examples show us enough of what needs to be +%D done by the auxiliary macros. +%D +%D \startbuffer +%D \framed[height=1cm,offset=.5cm] {rule based learning} +%D \framed[height=1cm,offset=0cm] {rule based learning} +%D \framed[height=1cm,offset=none] {rule based learning} +%D \framed[height=1cm,offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[offset=.5cm] {rule based learning} +%D \framed[offset=0cm] {rule based learning} +%D \framed[offset=none] {rule based learning} +%D \framed[offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[strut=no,offset=.5cm] {rule based learning} +%D \framed[strut=no,offset=0cm] {rule based learning} +%D \framed[strut=no,offset=none] {rule based learning} +%D \framed[strut=no,offset=overlay]{rule based learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D \startbuffer +%D \framed[width=3cm,align=left] {rule\\based\\learning} +%D \framed[width=3cm,align=middle] {rule\\based\\learning} +%D \framed[width=3cm,align=right] {rule\\based\\learning} +%D \framed[width=fit,align=middle] {rule\\based\\learning} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\dontcomplain\getbuffer} +%D \stoplinecorrection +%D +%D So now we're ready for the complicated stuff. We distinguish between borders with +%D straight lines and those with round corners. When using the first alternative it +%D is possible to turn off one or more lines. More fancy shapes are also possible by +%D specifying dedicated backgrounds. Turning lines on and off is implemented as +%D efficient as possible and as a result is interface language dependant. This next +%D implementation evolved from simpler ones. It puts for instance the rules on top +%D of the content and provides additional offset capabilities. The lot of calls to +%D other macros makes this mechanism not that easy to comprehend. +%D +%D We handle left, right or middle alignment as well as fixed or free widths and +%D heights. Each combination gets its own macro. +%D +%D The following code handles one-liners: \type {align={line,flushright}}. Beware, +%D since we entered a group and either or not grab the next bgroup token, we need to +%D finish the group in the oneliner mode. + +\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi + +\permanent\protected\def\doformatonelinerbox % beware: assumes explicit preceding bgroup + {\ifconditional\raggedonelinerstate + \expandafter\dodoformatonelinerbox + \else + \expandafter\nodoformatonelinerbox + \fi} + +\permanent\protected\def\dodoformatonelinerbox + {\afterassignment\redoformatonelinerbox + \setbox\nextbox\hbox} % maybe \hpack + +\permanent\protected\def\redoformatonelinerbox + {\aftergroup\dododoformatonelinerbox + \ignorespaces} + +\permanent\protected\def\dododoformatonelinerbox + {\hpack to \hsize % was \hbox + {\ifcase\raggedstatus\or\hss\or\hss \fi + \unhbox\nextbox \removeunwantedspaces + \ifcase\raggedstatus\or \or\hss\or\hss\fi}% + \egroup} + +\permanent\protected\def\nodoformatonelinerbox % grabs { + {\let\next=} + +%D The handlers: + +% Beware, we have a \noindent so an empty line is indeed an empty line and +% the \synchronizeinlinedirection triggers a vbox instead of a line. +% +% \startTEXpage[offset=0.5ex,align={lohi,middle}] +% +% \vbox{\hbox{x}} +% \stopTEXpage +% +% \startTEXpage[offset=0.5ex,align={lohi,middle}] +% \vbox{\hbox{x}} +% \stopTEXpage + +% \def\pack_framed_forgetall{\forgetall} + +\def\pack_framed_set_foregroundcolor + {\edef\p_framed_foregroundcolor{\framedparameter\c!foregroundcolor}% + \ifempty\p_framed_foregroundcolor\else\dousecolorparameter\p_framed_foregroundcolor\fi} + +\def\pack_framed_do_setups + {\ifempty\p_framed_setups \else + \setups[\p_framed_setups]% \texsetup (or only one!) + % \fastsetup\p_framed_setup % singular would have been better + \fi} + +\def\pack_framed_format_format_yes + {\vbox to \d_framed_height + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \oninterlineskip + \hsize\d_framed_width + \vsize\d_framed_height + \pack_framed_do_setups + \raggedcommand + \pack_framed_do_top + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom + \doformatonelinerbox} + +\def\pack_framed_format_format_nop + {\vbox to \d_framed_height + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \oninterlineskip + \hsize\d_framed_width + \vsize\d_framed_height + \pack_framed_do_setups + \raggedcenter + \vss + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\vss + \doformatonelinerbox} + +\def\pack_framed_format_format_height + {\vbox to \d_framed_height + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \oninterlineskip + \pack_framed_do_setups + \raggedcommand + \vss + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\vss + \doformatonelinerbox} + +\def\pack_framed_format_format_width + {\vbox + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \oninterlineskip + \hsize\d_framed_width + \pack_framed_do_setups + \raggedcommand + \pack_framed_do_top + \synchronizeinlinedirection + \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom + \doformatonelinerbox} + +\def\pack_framed_format_format_vsize + {\vbox to \d_framed_height % no vpack .. maybe grid + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \vsize\d_framed_height + \pack_framed_do_setups + \vss + \atendofgroup\vss + \hbox + \bgroup + \aftergroup\egroup + \synchronizeinlinedirection + \localstrut + \doformatonelinerbox} + +\def\pack_framed_format_format_hsize + {\hbox to \d_framed_width + \bgroup + \let\postprocessframebox\relax + % \pack_framed_forgetall + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \pack_framed_do_setups + \hss + \synchronizeinlinedirection + \localstrut + \atendofgroup\hss + \doformatonelinerbox} + +\def\pack_framed_format_format_no_size + {\hbox + \bgroup + \iftrialtypesetting \else + \pack_framed_set_foregroundcolor + \fi + \let\postprocessframebox\relax + \pack_framed_do_setups + \synchronizeinlinedirection + \localstrut + \doformatonelinerbox} + +%D On the next page we show some examples of how these macros come into action. The +%D examples show us how \type {fit}, \type {broad} dimensions influence the +%D formatting. Watch the visualized struts. \footnote {Here we used \type +%D {\showstruts}.} +%D +%D \startpostponing +%D \bgroup +%D \showstruts +%D \dontcomplain +%D \starttabulate[|c|c|c|c|c|c|] +%D % \HL +%D \NC \framed[width=.2\hsize, height=.2\hsize, align=] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=broad, align=] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=fit, align=] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=.2\hsize, align=] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=broad, align=] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=fit, align=] {a\endgraf b\endgraf c} +%D \NC \NR +%D % \HL +%D \NC \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=broad, align=yes] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=fit, align=yes] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=.2\hsize, align=yes] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=broad, align=yes] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=fit, align=yes] {a\endgraf b\endgraf c} +%D \NC \NR +%D % \HL +%D \NC \framed[width=.2\hsize, height=.2\hsize, align=right] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=broad, align=right] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=fit, align=right] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=.2\hsize, align=right] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=broad, align=right] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=fit, align=right] {a\endgraf b\endgraf c} +%D \NC \NR +%D % \HL +%D \NC \framed[width=.2\hsize, height=.2\hsize, align=left] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=broad, align=left] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=fit, align=left] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=.2\hsize, align=left] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=broad, align=left] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=fit, align=left] {a\endgraf b\endgraf c} +%D \NC \NR +%D % \HL +%D \NC \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=broad, align=middle] {a\endgraf b\endgraf c} +%D \NC \framed[width=.2\hsize, height=fit, align=middle] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=.2\hsize, align=middle] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=broad, align=middle] {a\endgraf b\endgraf c} +%D \NC \framed[width=fit, height=fit, align=middle] {a\endgraf b\endgraf c} +%D \NC \NR +%D % \HL +%D \stoptabulate +%D \egroup +%D \stoppostponing + +%D \macros +%D {framednoflines, framedlastlength} +%D +%D It is possible to let the frame macro calculate the width of a centered box +%D automatically (\type {fit}). When doing so, we need to reshape the box: + +\newcount\framednoflines +\newdimen\framedfirstheight +\newdimen\framedlastdepth +\newdimen\framedminwidth +\newdimen\framedmaxwidth +\newdimen\framedaveragewidth + +\def\pack_framed_reshape_reset + {\framednoflines \zerocount + \framedfirstheight \zeropoint + \framedlastdepth \zeropoint + \framedminwidth \zeropoint + \framedmaxwidth \zeropoint + \framedaveragewidth\zeropoint} + +\def\pack_framed_reshape_process{\ifvbox\b_framed_normal\clf_doreshapeframedbox\b_framed_normal\relax\fi} +\def\pack_framed_reshape_analyze{\ifvbox\b_framed_normal\clf_doanalyzeframedbox\b_framed_normal\relax\fi} + +% torture test / strange case (much depth) / method 2 needed +% +% \startTEXpage[frame=on] +% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula +% test outside formula +% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula +% \blank[big] +% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula +% test outside formula +% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula +% \stopTEXpage + +%D The examples on the next page show how one can give the frame as well as the +%D background an additional offset and even a bit more depth. The blue outline is +%D the frame, the red box is the background and the small black outline is the +%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to +%D the result. +%D +%D \startpostponing +%D \bgroup +%D \unprotect +%D \dontcomplain +%D +%D \startbuffer +%D \unprotect +%D \vbox to \vsize +%D \bgroup +%D \startalignment[middle] +%D \vss +%D \dontleavehmode\vbox to .8\vsize +%D \bgroup +%D \hsize=300pt +%D \setupframed +%D [background=color, +%D backgroundcolorachtergrondkleur=darkred, +%D width=300pt, +%D height=60pt, +%D framecolorkaderkleur=DemoBlue, +%D rulethickness=2pt] +%D \def\status% +%D {backgroundoffset=\the\dimexpr\framedparameter\c!backgroundoffset\relax\\ +%D frameoffset=\the\dimexpr\framedparameter\c!frameoffset\relax\\ +%D depth=\the\dimexpr\framedparameter\c!depth\relax} +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=0pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=0pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=5pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=2pt,frameoffset=5pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=2pt]{\status}} +%D \vss +%D \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=5pt]{\status}} +%D \egroup +%D \vss +%D \stopalignment +%D \egroup +%D \protect +%D \stopbuffer +%D +%D \getbuffer \page +%D +%D {\setupframed[depth=4pt]\getbuffer} \page +%D +%D \protect +%D \egroup +%D \stoppostponing + +%D We can draw lines from left to right and top to bottom by using the normal \type +%D {\hairline} command. Both directions need a different treatment. +%D +%D \startbuffer +%D \framed[width=4cm] {alfa\hairline beta\hairline gamma} +%D \framed[height=2cm] {alfa\hairline beta\hairline gamma} +%D \framed[width=4cm,height=2cm]{alfa\hairline beta\hairline gamma} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \hbox{\getbuffer} +%D \stoplinecorrection +%D +%D These macros try to adapt their behaviour as good as possible to the circumstances +%D and act as natural as possible. + +\protected\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth + {\begingroup + \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi + \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax + \par + \nointerlineskip + \kern\scratchoffset + \dontleavehmode + \hrule\s!height\d_framed_linewidth\s!depth\zeropoint + \par + \kern-\d_framed_linewidth + \dontleavehmode + \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% + \hfill + \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}% + \par + \nointerlineskip + \kern\scratchoffset + \nointerlineskip + \endgraf + \nointerlineskip + \localbegstrut + \endgroup} + +\protected\def\pack_framed_hboxed_hairline % use framed dimen + {\bgroup + \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi + \ifconditional\c_framed_has_height + \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax + \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax + \else + \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax + \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax + \fi + \unskip + \setbox\scratchbox\hpack + {\kern\scratchoffset + \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth + \kern\scratchoffset}% + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \box\scratchbox + \ignorespaces + \egroup} + +%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In +%D horizontal boxes it expands to a space. + +\protected\def\pack_framed_vboxed_newline + {\endgraf\ignorespaces} + +\protected\def\pack_framed_hboxed_newline + {\unskip\normalspace\ignorespaces} + +%D We can set each rule on or off. The default setting is inherited from +%D \type {frame}. An earlier implementation use a bit different approach, but the new +%D one seems more natural: +%D +%D \bgroup +%D \setuptyping[margin=0pt] +%D \startlinecorrection +%D \startbuffer +%D \framed[offset=overlay,frame=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=on,bottomframe=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=on,bottomframe=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off,bottomframe=off]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D +%D \startbuffer +%D \framed[offset=overlay,frame=off,bottomframe=on]{\darkred\blackrule} +%D \stopbuffer +%D \hbox{\getbuffer\vbox{\typebuffer}} +%D \stoplinecorrection +%D \egroup + +%D \macros +%D {startframedtext, setupframedtexts, defineframedtext} +%D +%D The general framing command we discussed previously, is not entirely suited for +%D what we call framed texts, as for instance used in intermezzo's. The next +%D examples show what we have in mind. +%D +%D \startbuffer[framed-0] +%D \setupframedtexts +%D [frame=off, +%D width=\hsize, +%D background=screen] +%D +%D \startframedtext +%D By default the framed text is centered \dots +%D \stopframedtext +%D +%D \startframedtext[right] +%D \dots\ but we can also align left, middle and right. +%D \stopframedtext +%D \stopbuffer +%D +%D \startbuffer[framed-1] +%D \defineframedtext +%D [Example] +%D [width=6cm, +%D height=5cm] +%D +%D \startExample +%D \typebuffer[framed-1] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-2] +%D \defineframedtext +%D [Example] +%D [width=6cm] +%D +%D \startExample +%D \typebuffer[framed-2] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-3] +%D \defineframedtext +%D [Example] +%D [height=5cm] +%D +%D \startExample +%D \typebuffer[framed-3] +%D \stopExample +%D \stopbuffer +%D +%D \startbuffer[framed-4] +%D \defineframedtext +%D [Example] +%D [width=fit,height=broad] +%D +%D \Example{a very exciting example} +%D \stopbuffer +%D +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-0] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-1] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-2] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup +%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup +%D +%D Here we can see that we have a predefined framed text class as well as the +%D tools for defining our own. So we have: +%D +%D \showsetup{setupframedtexts} +%D +%D as well as the definition command: +%D +%D \showsetup{defineframedtext} +%D +%D that generates two commands: +%D +%D \showsetup{start<>} +%D \showsetup{<>} +%D +%D The next definition shows the defaults. + +\installcorenamespace{framedtext} +\installcorenamespace{framedtextlocation} + +\installframedcommandhandler \??framedtext {framedtext} \??framedtext + +\let\setupframedtexts\setupframedtext + +\setupframedtext + [\c!width=.75\hsize, + \c!height=\v!fit, + \c!align=\v!yes, + %\c!top=, + \c!bottom=\vfill, + \c!offset=1em, + %\c!bodyfont=, + %\c!style=, + %\c!color=, + %\c!left=, + \c!right=\hfill, + \c!before=\blank, + \c!after=\blank, + %\c!inner=, + \c!frame=\v!on, + %\c!topframe=, + %\c!bottomframe=, + %\c!leftframe=, + %\c!rightframe=, + \c!radius=.5\bodyfontsize, + \c!corner=\v!rectangular, + %\c!orientation=, + %\c!indenting=, + %\c!foregroundcolor=, + %\c!foregroundstyle=, + %\c!background=, + %\c!backgroundcolor=, + \c!linecorrection=\v!on, + \c!depthcorrection=\v!on, + \c!margin=\v!standard] + +\appendtoks + \frozen\instance\setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}% + \frozen\instance\setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }% + \frozen\instance\setuevalue {\currentframedtext}{\pack_framed_text_direct[\currentframedtext]}% +\to \everydefineframedtext + +\setvalue{\??framedtextlocation\v!left }{\letframedtextparameter\c!left \relax + \letframedtextparameter\c!right\hfill} + +\setvalue{\??framedtextlocation\v!right }{\letframedtextparameter\c!left \hfill + \letframedtextparameter\c!right\relax} + +\setvalue{\??framedtextlocation\v!middle}{\letframedtextparameter\c!left \hfill + \letframedtextparameter\c!right\hfill} + +\setvalue{\??framedtextlocation\v!none }{\letframedtextparameter\c!left \relax + \letframedtextparameter\c!right\relax + \settrue\c_framed_text_location_none} + +\protected\def\pack_framed_text_start#1% + {\bgroup + \edef\currentframedtext{#1}% + \dodoubleempty\pack_framed_text_start_indeed} + +\def\pack_framed_text_start_indeed[#1][#2]% + {\doifelseassignment{#1} + {\pack_framed_text_start_continue\empty{#1}} + {\pack_framed_text_start_continue{#1}{#2}}} + +% todo: sort out first/lastline ht/dp + +\def\pack_framed_text_start_continue#1#2% + {\setupframedtexts[\currentframedtext][#2]% + \doifsomething{#1}{\setframedtextparameter\c!location{#1}}% does not listen to #3 + \setfalse\c_framed_text_location_none + \csname\??framedtextlocation\framedtextparameter\c!location\endcsname + \resetframedtextparameter\c!location + \pack_framed_text_check + \setbox\b_framed_normal\vbox % \vpack + \startboxedcontent + \hsize\localhsize + % \insidefloattrue % ? better + \usebodyfontparameter\framedtextparameter + % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used + \letframedtextparameter\c!strut\v!no + \inheritedframedtextframed\bgroup + \enforced\let\\\endgraf + \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}% + \ifx\p_framed_text_depthcorrection\v!on + \pack_framed_text_start_depth_correction + \else + \bgroup + \fi + \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 + \doinhibitblank + \useindentingparameter\framedtextparameter + \useframedtextstyleandcolor\c!style\c!color + \framedtextparameter\c!inner + \ignorespaces} + +% testcase 1: +% +% \showstruts +% \startframedtext[align={normal,tolerant},offset=0pt] \input tufte \stopframedtext +% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \input tufte \stopframedtext +% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \inframed{x} \stopframedtext +% \framed[align={normal,tolerant},offset=0pt]{\input tufte } + +%D The \type {none} option is handy for nested usage, as in the presentation +%D styles, where we don't want interference. + +\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext] + +\protected\def\pack_framed_text_stop % no \baselinecorrection, see faq docs + {\endgraf + \removelastskip + \ifx\p_framed_text_depthcorrection\v!on + \pack_framed_text_stop_depth_correction + \else + \egroup + \fi + \stopboxedcontent + \ifconditional\c_framed_text_location_none + \egroup + \box\b_framed_normal + \orelse\ifinsidefloat + \egroup + \box\b_framed_normal + \else + \egroup + \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}% + \fi + \egroup} + +%D We define the general (and original) case by just saying: + +\def\pack_framed_text_check % messy dependency + {\localhsize\hsize + \ifinsidefloat \orelse \ifdim\d_page_sides_vsize>\zeropoint % also possible: \c_page_sides_checks_done>\zeropoint + % \strut % rather clean way to invoke the sidefloat OTR + % \setbox0=\lastbox % and get the widths set, so from now on we + % \setlocalhsize % can have framed texts alongside sidefloats + \checksidefloat + \setlocalhsize + \fi} + +\def\pack_framed_text_start_depth_correction + {\bgroup + \ifhmode + \par + \fi + \ifvmode + \verticalstrut + % we need \nowhitespace in case of setups setting whitespace + % nb, not safe, text vs \vbox as next + \vskip-\struttotal + \nowhitespace + \fi} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..}) + +\def\pack_framed_text_stop_depth_correction + {\ifhmode + \par + \fi + \ifvmode + \forgetall + \vskip-\struttotal + \verticalstrut + \egroup + \forgetall % brrr too often + \vskip-\lineheight + \verticalstrut + \else + \egroup + \fi} + +%D Placement can be ignored: +%D +%D \starttyping +%D \hbox to \hsize \bgroup +%D \startframedtext[none][width=.5\textwidth] \input tufte \stopframedtext +%D \startframedtext[none][width=.5\textwidth] \input zapf \stopframedtext +%D \egroup +%D +%D \hbox to \hsize \bgroup +%D \setupframedtexts[location=none]% +%D \startframedtext[width=.5\textwidth] \input zapf \stopframedtext +%D \startframedtext[width=.5\textwidth] \input tufte \stopframedtext +%D \egroup +%D \stoptyping + +%D The simple brace (or group) delimited case is typeset slightly different +%D and is not aligned. + +\tolerant\protected\def\pack_framed_text_direct[#1]#*[#2]% + {\bgroup + \edef\currentframedtext{#1}% + \usebodyfontparameter\framedtextparameter + \setupcurrentframedtext[#1]% + \edef\p_framed_text_strut{\framedtextparameter\c!strut}% + \letframedtextparameter\c!strut\v!no + \inheritedframedtextframed\bgroup + \blank[\v!disable]% + \enforced\let\\\endgraf + \useframedtextstyleandcolor\c!style\c!color + \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 + \framedtextparameter\c!inner + \ifx\p_framed_text_strut\v!no + \let\pack_framed_strut\relax + \else + \let\pack_framed_strut\strut + \fi + \bgroup + \aftergroup\pack_framed_text_stop_direct + \afterassignment\ignorespaces + \afterassignment\pack_framed_strut + \let\next=} + +\def\pack_framed_text_stop_direct + {\removelastskip + \egroup + \egroup} + +\defineframedtext + [\v!framedtext] + +%D \macros +%D {defineframed} +%D +%D One can also define simple framed texts, using: +%D +%D \showsetup{defineframed} +%D +%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead +%D of passing a combination of arguments. This also also simplified the \type +%D {\setupframed} command. There are certainly more places where such improvements +%D can be made. + +\appendtoks + \ifcsname\??regularframedlevel\currentframed\endcsname + % already defined, keeps settings + \else + \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname + \fi +\to \everypresetframed + +\appendtoks + \frozen\instance\setuevalue{\currentframed}{\pack_framed_defined_process[\currentframed]}% +\to \everydefineframed + +\newcount\c_temp_framed_crap + +\permanent\tolerant\protected\def\pack_framed_defined_process[#1]#*[#2]% official (not much checking, todo: parent) + {\bgroup + \ifcsname\??regularframedlevel#1\endcsname + %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname + \expandafter\let\expandafter\c_pack_framed_temp\lastnamedcs + \else + \let\c_pack_framed_temp\c_temp_framed_crap + \fi + \advance\c_pack_framed_temp\plusone + \defcsname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed + \bgroup + \edef\currentframed{#1>\the\c_pack_framed_temp}% + \pack_framed_initialize + \setupcurrentframed[#2]% here ! + \pack_framed_process_indeed} + +\aliased\let\placeframed\pack_framed_defined_process % new per 2012/04/23 + +%D We can do: +%D +%D \starttyping +%D \defineframed[\v!framed] +%D \stoptyping +%D +%D but the existing one is ok as well (less csname messy too). + +%D New, for the moment private; let's see when GB finds out about this one and its +%D obscure usage. It's used in: +%D +%D \startbuffer +%D \defineframedtext +%D [tabulateframe] +%D [offset=overlay, +%D backgroundoffset=3pt, +%D background=color, +%D backgroundcolor=green] +%D +%D \setuptabulate +%D [tabulate] +%D [frame=tabulateframe] +%D +%D \setuptables +%D [frame=tabulateframe] +%D +%D \input tufte +%D +%D \starttabulate[|l|l|] +%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR +%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR +%D \stoptabulate +%D +%D \input tufte +%D +%D \starttable[|l|l|] +%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR +%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR +%D \stoptable +%D \stopbuffer +%D +%D \typebuffer + +\installcorenamespace{framedcontent} + +\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent + +\setupframedcontent + [\c!leftoffset=\zeropoint, + %\c!rightoffset=\framedcontentparameter\c!leftoffset, + \c!rightoffset=\scratchleftoffset, + \c!topoffset=\zeropoint, + %\c!bottomoffset=\framedcontentparameter\c!topoffset, + \c!bottomoffset=\scratchtopoffset, + \c!strut=\v!no, + %\c!linecorrection=\v!no, + %\c!left=, + %\c!right=, + %\c!width=\v!fit, + \c!offset=\v!overlay] + +\permanent\let\stopframedcontent\relax + +\permanent\tolerant\protected\def\startframedcontent[#1]% + {\bgroup + \edef\currentframedcontent{#1}% + \ifx\currentframedcontent\v!off + \enforced\let\stopframedcontent\egroup + \else + \checkframedcontentparent + \enforced\let\stopframedcontent\pack_framed_stop_content_indeed + \expandafter\pack_framed_start_content_indeed + \fi} + +\def\pack_framed_start_content_indeed + {\setbox\b_framed_normal\hpack\bgroup + \setlocalhsize + \hsize\localhsize + \scratchleftoffset \framedcontentparameter\c!leftoffset \relax + \scratchrightoffset \framedcontentparameter\c!rightoffset \relax + \scratchtopoffset \framedcontentparameter\c!topoffset \relax + \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax + \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax + \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax + \kern\scratchleftoffset + \vpack\bgroup + \vskip\scratchtopoffset + \vbox\bgroup + \forgetall + \blank[\v!disable]} + +\protected\def\pack_framed_stop_content_indeed + {\removelastskip + \egroup + \vskip\scratchbottomoffset + \egroup + \kern\scratchrightoffset + \egroup + \doif{\framedcontentparameter\c!width}\v!fit + {\letframedcontentparameter\c!width\v!fixed}% no shapebox + \ifinsidefloat + \donefalse + \else + \doifelse{\framedcontentparameter\c!linecorrection}\v!yes\donetrue\donefalse + \fi + % plaats ? + \ifdone\startlinecorrection\fi + \framedcontentparameter\c!left % new + \inheritedframedcontentframed{\box\b_framed_normal}% hm + \framedcontentparameter\c!right % new + \ifdone\stoplinecorrection\fi + \egroup} + +% A shared setting. + +\setuplinewidth + [\v!medium] + +%D A Goodie: + +\defineframed + [\v!unframed] + [\c!frame=\v!off, + \c!rulethickness=\zeropoint, + \c!foregroundstyle=\framedparameter\c!style, + \c!foregroundcolor=\framedparameter\c!color] + +%D Bonus (as defined in \type {pack-rul.lua}): +%D +%D \starttyping +%D \setbox\scratchbox\vbox{a\par aa\par aaa\par} +%D \the\dimexpr\themaxboxwidth\scratchbox\relax +%D \stoptyping + +\let\themaxboxwidth\clf_themaxboxwidth + +%D Fast enough for most cases (we could do a massive \type {\ifhastok} instead): + +\permanent\protected\def\doifelseframed#1% + {\iftok{#1\c!frame }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!topframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!bottomframe}{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!leftframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!rightframe }{\v!on}\expandafter\firstoftwoarguments + \orelse\iftok{#1\c!background } {}\expandafter\secondoftwoarguments + \else \expandafter\firstoftwoarguments\fi} + +\protect \endinput -- cgit v1.2.3