%D \module %D [ file=pack-rul, % was core-rul, %D version=1998.10.16, %D title=\CONTEXT\ Packaging Macros, %D subtitle=Ruled Content, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Packaging Macros / Ruled Content} %D The code here is expanded lots of time as framed is used in many places. This is %D why the code here is (and gets) optimized as much as possible. Also, by avoiding %D packaging and expansion we also keep tracing reasonable. For instance, multiple %D stacked backgrounds can slow down a run if not optimized this way. \registerctxluafile{pack-rul}{optimize} \unprotect % \definesystemvariable {ol} % OmLijnd -> check scrn-fld too %D \macros %D {linewidth, setuplinewidth} %D %D This module deals with rules (lines) in several ways. First we introduce two %D macros that can be used to set some common characteristics. %D %D \showsetup{setuplinewidth} %D %D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals %D the default hard coded \TEX\ rule width. \newdimen\linewidth \unexpanded\def\setuplinewidth {\dosingleargument\pack_framed_setup_line_width} \def\pack_framed_setup_line_width[#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 {\let\framedparameter \pack_framed_framedparameter \let\framedparameterhash\pack_framed_framedparameterhash \let\setupcurrentframed \pack_framed_setupcurrentframed \inframedtrue} %D A helper: \def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax} %D Inheritance: \def\installinheritedframed#1% {\normalexpanded{\doinstallinheritedframed \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 \unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9% {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root \unexpanded\def#8% {\bgroup \bgroup \inframedtrue \let\currentframed #1% \let\framedparameter #2% \let\framedparameterhash#3% \let\setupcurrentframed #7% \pack_framed_process_indeed}% \unexpanded\def#9% {\bgroup \inframedtrue \let\currentframed #1% \let\framedparameter #2% \let\framedparameterhash#3% \let\setupcurrentframed #7% \pack_framed_process_box_indeed}} \unexpanded\def\installframedcommandhandler#1#2#3% {\installcommandhandler{#1}{#2}{#3}% \installinheritedframed{#2}} \unexpanded\def\installframedautocommandhandler#1#2#3% {\installautocommandhandler{#1}{#2}{#3}% \installinheritedframed{#2}} \unexpanded\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] \unexpanded\def\definesimplifiedframed[#1]% no settings {\defineframed[#1][\??simplifiedframed]% \expandafter\let\csname#1\endcsname\undefined} \expandafter\let\csname\??simplifiedframed\endcsname\undefined %D We will communicate through module specific variables, current framed %D parameters and some reserved dimension registers. \newdimen\d_framed_target_wd \newdimen\d_framed_target_ht \newdimen\d_framed_target_dp \newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end \let\p_framed_frame \empty % \framedparameter\c!frame \let\p_framed_backgroundoffset\empty \let\p_framed_foregroundstyle \empty \let\p_framed_autostrut \empty \let\p_framed_location \empty \let\p_framed_orientation \empty \let\p_framed_anchoring \empty \let\p_framed_autowidth \empty \let\p_framed_franalyze \empty \let\p_framed_backgroundcorner\empty \let\p_framed_backgroundradius\empty \let\p_framed_framecorner \empty \let\p_framed_frameradius \empty \let\p_framed_lines \empty \let\p_framed_empty \empty \let\p_framed_backgroundcolor \empty \let\p_framed_framecolor \empty \let\p_framed_component \empty \let\p_framed_background \empty \let\p_framed_rulethickness \empty \let\p_framed_foregroundcolor \empty \let\p_framed_setups \empty %D We don't have to stick to a \TEX\ drawn rule, but also can use rounded %D or even fancier shapes, as we will see later on. \def\pack_framed_filled_box {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}% \ifx\p_framed_backgroundcorner\v!rectangular \pack_framed_filled_box_normal \else \pack_framed_filled_box_radius \fi} \def\pack_framed_filled_box_normal {\vrule \s!width \d_framed_target_wd \s!height\d_framed_target_ht \s!depth \d_framed_target_dp \relax} \def\pack_framed_filled_box_radius {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}% \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize \pack_framed_filled_box_normal \else \pack_framed_filled_box_round \fi} \def\pack_framed_filled_box_round {\raise\d_framed_target_dp\hpack{\frule type fill width \d_framed_target_wd height \d_framed_target_ht depth \d_framed_target_dp line \d_framed_linewidth radius \p_framed_backgroundradius\space corner {\p_framed_backgroundcorner} \relax}} \def\pack_framed_stroked_box {\edef\p_framed_framecorner{\framedparameter\c!framecorner}% \ifx\p_framed_framecorner\v!rectangular \pack_framed_stroked_box_normal \else \pack_framed_stroked_box_radius \fi} \def\pack_framed_stroked_box_radius {\edef\p_framed_frameradius{\framedparameter\c!frameradius}% \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize \pack_framed_stroked_box_normal \orelse\ifx\p_framed_frame\v!on \pack_framed_stroked_box_round \fi} % \pack_framed_stroked_box_normal % later \def\pack_framed_stroked_box_round {\raise\d_framed_target_dp\hpack{\frule width \d_framed_target_wd height \d_framed_target_ht depth \d_framed_target_dp line \d_framed_linewidth radius \p_framed_frameradius\space corner {\p_framed_framecorner} \relax}} % a lot of weird corners % % \startTEXpage % \dontleavehmode\framed % [corner=0,frame=on,framecolor=green, % background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% % \vskip1em % \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green, % background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green, % background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \vskip1em % \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed % [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}% % \quad} % \stopTEXpage %D It won't be a surprise that we not only provide gray boxes, but also colored %D ones. Here it is: \def\pack_framed_background_box_color {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}% \ifempty\p_framed_backgroundcolor \else \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed \fi} \def\pack_framed_background_box_color_indeed {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}} %D \macros %D {defineoverlay, doifoverlayelse, overlayoffset, %D overlaywidth, overlayheight, overlaydepth, %D overlaycolor, overlaylinecolor, overlaylinewidth} %D %D Before we define the macro that actually takes card of the backgrounds, we %D introduce overlays. An overlay is something that contrary to its name lays {\em %D under} the text. An example of an overlay definition is: %D %D \startbuffer[tmp-1] %D \defineoverlay %D [fancy] %D [{\externalfigure %D [mp-cont.502] %D [width=\overlaywidth, %D height=\overlayheight]}] %D \stopbuffer %D %D \typebuffer[tmp-1] %D %D That for instance can be uses in: %D %D \startbuffer[tmp-2] %D \framed[backgroundachtergrond=fancy]{How Fancy!} %D \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!} %D \stopbuffer %D %D and looks like: %D %D \startlinecorrection %D \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]} %D \stoplinecorrection %D %D The formal definition is: %D %D \showsetup{defineoverlay} %D %D This macro's definition is a bit obscure, due the many non||used arguments and %D the two step call that enable the setting of the width, height and depth %D variables. Multiple backgrounds are possible and are specified as: %D %D \starttyping %D \framed[background={one,two,three}]{Three backgrounds!} %D \stoptyping %D %D Most drawing packages only know width and height. Therefore the dimensions have a %D slightly different meaning here: %D %D \startitemize[packed] %D \item \type{\overlaywidth }: width of the overlay %D \item \type{\overlayheight}: height plus depth of the overlay %D \item \type{\overlaydepth }: depth of the overlay %D \stopitemize %D %D The resulting box is lowered to the right depth. %def\overlaywidth {\the\hsize\space} % We preset the variables %def\overlayheight {\the\vsize\space} % to some reasonable default %def\overlaydepth {0pt } % values. The attributes %let\overlayoffset \overlaydepth % of the frame can be (are) %let\overlaylinewidth \overlaydepth % set somewhere else. \let\overlaycolor \empty \let\overlaylinecolor \empty \def\overlayradius{\framedparameter\c!frameradius} \newdimen\d_overlay_width \newdimen\d_overlay_height \newdimen\d_overlay_depth \newdimen\d_overlay_offset \newdimen\d_overlay_linewidth \let\m_overlay_region\empty % expandable ... in a future version the space will go (in mp one can use Overlay*) \def\overlaywidth {\the\d_overlay_width \space} % We preset the variables \def\overlayheight {\the\d_overlay_height \space} % to some reasonable default \def\overlaydepth {\the\d_overlay_depth \space} % values. \def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) \def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. \def\overlayregion {\m_overlay_region} % public but kind of protected \def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} \def\usedoverlayheight {\dimexpr\d_overlay_height \relax} \def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} \def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} \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 \unexpanded\def\defineoverlay {\dodoubleargument\pack_framed_define_overlay} \def\pack_framed_define_overlay[#1][#2]% {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% \processcommalist[#1]\pack_framed_define_overlay_indeed} % \unexpanded\def\executedefinedoverlay#1#2% we can share the definitions % {\bgroup % redundant grouping % \setbox\scratchbox\hbox\bgroup % \ifzeropt\d_framed_target_dp % \the\everyoverlay#2% saves wrapping (and lua call) % \else % \lower\d_framed_target_dp % \hbox{\the\everyoverlay#2}% % \fi % \egroup % \setlayoutcomponentattribute{\v!overlay:#1}% % \setbox\scratchbox\hpack \layoutcomponentboxattribute % {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width % \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \d_overlay_height ! % \box\scratchbox}% % \wd\scratchbox\d_framed_target_wd % \ht\scratchbox\d_framed_target_ht % \dp\scratchbox\d_framed_target_dp % \box\scratchbox % \egroup} % 20191231: moved from cont-exp: \unexpanded\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} % \unexpanded\def\overlayfakebox % {\hpack % {\setbox\scratchbox\emptyhbox % \wd\scratchbox\d_overlay_width % \ht\scratchbox\d_overlay_height % \box\scratchbox}} \unexpanded\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: \def\doifelseoverlay#1% only tests external overlays {\ifcsname\??overlay#1\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \let\doifoverlayelse\doifelseoverlay %D The content of the box will be (temporary) saved in a box. We also have an %D extra box for backgrounds. \newbox\b_framed_normal \newbox\b_framed_extra \newtoks\everybackgroundbox \let\m_framed_background\empty % we might need a public name \def\pack_framed_process_background {\ifcsname\??overlaybuiltin\m_framed_background\endcsname \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs \orelse\ifcsname\??overlay\m_framed_background\endcsname \expandafter\pack_framed_process_background_indeed_external\lastnamedcs \fi} \def\pack_framed_process_background_indeed_internal#1% % : in name {\bgroup \setbox\b_framed_extra\hpack\bgroup \ifzeropt\framedbackgroundoffset\else \kern-\framedbackgroundoffset \fi \hbox\bgroup#1\egroup \egroup \wd\b_framed_extra\zeropoint \ht\b_framed_extra\framedbackgroundheight \dp\b_framed_extra\framedbackgrounddepth \box\b_framed_extra \egroup} \def\pack_framed_process_background_indeed_external {\pack_framed_overlay_initialize \pack_framed_process_background_indeed_internal} \def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground) {\edef\m_framed_background{#1}% \ifx\m_framed_background\s!unknown\else \pack_framed_process_background \expandafter\pack_framed_process_backgrounds \fi#2} %D Beware, a backgroundbox can be empty which is another reason why we set the %D width to zero instead of back-skipping. \newdimen\framedbackgroundwidth \newdimen\framedbackgroundheight \newdimen\framedbackgrounddepth \newdimen\framedbackgroundoffset \def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight \def\pack_framed_set_region % experiment {\ifx\m_overlay_region\v!yes \edef\m_overlay_region{\reservedautoregiontag}% \fi} \def\pack_framed_add_region % experiment {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} \def\pack_framed_add_background {\setbox\b_framed_normal\hpack % was vbox % see also *1* {%\pack_framed_forgetall % can be relaxed \boxmaxdepth\maxdimen \framedbackgroundoffset\d_framed_backgroundoffset \framedbackgroundwidth \wd\b_framed_normal \framedbackgroundheight\ht\b_framed_normal \framedbackgrounddepth \dp\b_framed_normal \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed \ifempty\p_framed_component \resetlayoutcomponentattribute \else \setlayoutcomponentattribute{\v!background:\p_framed_component}% \fi \let\foregroundbox\pack_framed_background_box_content \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay \the\everybackgroundbox % moved \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it \box\b_framed_normal \hss \egroup}} \def\pack_framed_overlay_initialize_indeed {\d_overlay_width \d_framed_target_wd \d_overlay_height \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax \d_overlay_depth \d_framed_target_dp \d_overlay_linewidth \d_framed_linewidth \d_overlay_offset \framedbackgroundoffset\relax \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ? \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers %\edef\overlaycorner {\framedparameter\c!backgroundcorner}% %\edef\overlayradius {\framedparameter\c!backgroundradius}% \let\pack_framed_overlay_initialize\relax} %D One can explictly insert the foreground box. For that purpose we introduce the %D overlay \type {foreground}. %D %D We predefine two already familiar backgrounds: %letvalue{\??overlaybuiltin\v!screen }\pack_framed_background_box_gray \letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color \letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox] %D We can specify overlays as a comma separated list of overlays, a sometimes %D handy feature. %D %D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled %D borders). Again we have to deal with square and round corners. The first category %D can be handled by \TEX\ itself, the latter one depends on the driver. This macro %D also support a negative offset. \def\pack_framed_add_outline {\setbox\b_framed_normal\hpack % rules on top of box {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax \ifdim\d_framed_target_dp<\zeropoint \advance\d_framed_target_ht \d_framed_target_dp \scratchdimen-\d_framed_target_dp \d_framed_target_dp\zeropoint \else \scratchdimen\zeropoint \fi \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background \setbox\b_framed_extra\hpack {\kern-\d_framed_frameoffset \raise\scratchdimen \hpack{\ifempty\overlaylinecolor\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}% \wd\b_framed_extra\wd\b_framed_normal \ht\b_framed_extra\ht\b_framed_normal \dp\b_framed_extra\dp\b_framed_normal \wd\b_framed_normal\zeropoint \box\b_framed_normal \box\b_framed_extra}} \def\pack_framed_stroked_box_normal_opened {\setbox\scratchbox\vpack \bgroup \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname \nointerlineskip % new (needed for fences) \hpack \bgroup \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname \novrule \s!width \d_framed_target_wd \s!height\d_framed_target_ht \s!depth \d_framed_target_dp \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname \egroup \nointerlineskip % new (needed for fences) \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname \egroup \wd\scratchbox\d_framed_target_wd \ht\scratchbox\d_framed_target_ht \dp\scratchbox\d_framed_target_dp \box\scratchbox} \def\pack_framed_stroked_box_normal_closed {\hpack\bgroup \scratchdimen.5\d_framed_linewidth \hskip\scratchdimen \clf_framedoutline \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax \dimexpr\d_framed_target_ht-\scratchdimen\relax \dimexpr\d_framed_target_dp-\scratchdimen\relax \d_framed_linewidth \relax \egroup} \def\pack_framed_stroked_box_normal {\ifx\p_framed_frame\v!closed \pack_framed_stroked_box_normal_closed \else \pack_framed_stroked_box_normal_opened \fi} \def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} \def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} \def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} \def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth} \letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule \letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule \letvalue{\??framedtop \v!on }\pack_framed_t_rule \letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule \letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule \letvalue{\??framedbottom\v!on }\pack_framed_b_rule \letvalue{\??framedleft \v!on \v!on}\pack_framed_l_rule \letvalue{\??framedleft \v!off\v!on}\pack_framed_l_rule \letvalue{\??framedleft \v!on }\pack_framed_l_rule \letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule \letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule \letvalue{\??framedright \v!on }\pack_framed_r_rule % no overlapping rules \def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} \def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} \def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} \def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} \letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules \letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules \letvalue{\??framedtop \v!small }\pack_framed_t_rules \letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules \letvalue{\??framedbottom\v!off \v!small}\pack_framed_b_rules \letvalue{\??framedbottom\v!small }\pack_framed_b_rules \letvalue{\??framedleft \v!small\v!small}\pack_framed_l_rules \letvalue{\??framedleft \v!off \v!small}\pack_framed_l_rules \letvalue{\??framedleft \v!small }\pack_framed_l_rules \letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules \letvalue{\??framedright \v!off \v!small}\pack_framed_r_rules \letvalue{\??framedright \v!small }\pack_framed_r_rules % \framed % [width=4cm,height=3cm,rulethickness=3mm, % frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on] % {} % \framed % [width=4cm,height=3cm,rulethickness=3mm, % frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small] % {} % \framed % [width=4cm,height=3cm,rulethickness=3mm, % frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on] % {} %D The next few macros are probably the most misused ones in \CONTEXT. They deal %D with putting rules around boxes, provide backgrounds, offer alignment features, %D and some more. We start with defining some booleans. These give an impression of %D what we are going to take into account. % todo : \c_framed_hasoffset % faster : \let\c_framed_hasoffset\falseconditional \newconditional\c_framed_has_offset \newconditional\c_framed_has_width \newconditional\c_framed_has_height \newconditional\c_framed_has_format \newconditional\c_framed_is_overlaid \newconditional\c_framed_has_frame \newconditional\c_framed_has_extra_offset \newconditional\c_framed_text_location_none \newconstant \c_framed_has_strut % 0=relaxes 1=pseudostruts 2=realstruts %D \macros %D {framed, setupframed} %D %D Ruled boxes are typeset using \type{\framed}. This command is quite versatile %D and, although some users will probably seldom use it, one cannot overlook its %D features. %D %D \showsetup{setupframed} %D \showsetup{framed} %D %D This general macro is a special version of an even more general case, that can %D easily be linked into other macros that need some kind of framing. The local %D version is called with an extra parameter: the variable identifier. The reason %D for passing this identifier between brackets lays in the mere fact that this way %D we can use the optional argument grabbers. \def\defaultframeoffset{.25\exheight} \installcorenamespace{regularframedlevel} \unexpanded\def\installregularframed#1% {\defineframed[#1]} \unexpanded\def\presetlocalframed[#1]% {\defineframed[#1]} % \presetlocalframed[\??framed] \newcount\c_pack_framed_nesting \unexpanded\def\pack_framed_process_framed[#1]% {\bgroup \iffirstargument % faster \setupcurrentframed[#1]% here ! \fi \pack_framed_process_indeed} \unexpanded\def\framed {\bgroup \advance\c_pack_framed_nesting\plusone \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed \edef\currentframed{>\the\c_pack_framed_nesting}% \pack_framed_initialize \dosingleempty\pack_framed_process_framed} \unexpanded\def\startframed {\dosingleempty\pack_framed_start_framed} \def\pack_framed_start_framed[#1]% {\bgroup \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}} \def\pack_framed_start_framed_yes#1% {\advance\c_pack_framed_nesting\plusone \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed \iffirstargument\secondargumenttrue\fi % dirty trick \edef\currentframed{>\the\c_pack_framed_nesting}% \pack_framed_initialize \bgroup \iffirstargument \secondargumenttrue % dirty trick \setupcurrentframed[#1]% here ! \fi \pack_framed_process_indeed \bgroup \ignorespaces} \def\pack_framed_start_framed_nop#1% {\edef\currentframed{#1}% \dosingleempty\pack_framed_start_framed_nop_indeed} \def\pack_framed_start_framed_nop_indeed[#1]% {\pack_framed_initialize \bgroup \iffirstargument \setupcurrentframed[#1]% here ! \fi \pack_framed_process_indeed \bgroup \ignorespaces} % till here \unexpanded\def\stopframed {\removeunwantedspaces \egroup} \unexpanded\def\normalframedwithsettings[#1]% {\bgroup \advance\c_pack_framed_nesting\plusone \expandafter\let\csname\??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 %D dimensions can be set, only frames and backgrounds. \unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4 {\bgroup \edef\currentframed{#1}% \pack_framed_initialize \setbox\b_framed_normal\hbox{#4}% \iftrialtypesetting \else \edef\m_overlay_region{\framedparameter\c!region}% \ifempty\m_overlay_region\else \pack_framed_set_region \fi \fi \setupcurrentframed[#3]% \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. \unexpanded\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} \unexpanded\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 \unexpanded\def\localframed {\bgroup \dodoubleempty\pack_framed_local} \unexpanded\def\pack_framed_local[#1][#2]% {\bgroup \edef\currentframed{#1}% \pack_framed_initialize \ifsecondargument % faster \setupcurrentframed[#2]% here ! \fi \pack_framed_process_indeed} \unexpanded\def\directlocalframed[#1]% no optional {\bgroup \bgroup \edef\currentframed{#1}% \pack_framed_initialize \pack_framed_process_indeed} \unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between) {\bgroup \bgroup \edef\currentframed{#1}% \pack_framed_initialize \setupcurrentframed[#2]% here ! \pack_framed_process_indeed} % done \def\c!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 \unexpanded\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\localstrut {\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\localstrut\endcsname \lastnamedcs \else \framed_offset_alternative_unknown \fi % the next check could move to strutalternative \ifcase\c_framed_has_strut % none (not even noindent) \let\localbegstrut\relax \let\localendstrut\relax \let\localstrut \relax \or % no / overlay \let\localbegstrut\pseudobegstrut \let\localendstrut\pseudoendstrut \let\localstrut \pseudostrut \else \let\localbegstrut\begstrut \let\localendstrut\endstrut \let\localstrut \strut \fi \ifx\p_framed_autostrut\v!yes \let\delayedbegstrut\relax \let\delayedendstrut\relax \let\delayedstrut \relax \else \let\delayedbegstrut\localbegstrut \let\delayedendstrut\localendstrut \let\delayedstrut \localstrut \let\localbegstrut \relax \let\localendstrut \relax \let\localstrut \relax \fi \ifconditional\c_framed_has_height \let\\\pack_framed_vboxed_newline \ifconditional\c_framed_has_width \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 \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 \let\hairline\pack_framed_vboxed_hairline \let\\\pack_framed_vboxed_newline \let\next\pack_framed_format_format_width \else \let\hairline\pack_framed_hboxed_hairline \let\\\pack_framed_hboxed_newline \let\next\pack_framed_format_format_hsize \fi \else \let\hairline\pack_framed_hboxed_hairline \let\\\pack_framed_hboxed_newline \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}} \unexpanded\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 \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 \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. \unexpanded\def\inframed {\dosingleempty\pack_framed_inline} % \def\pack_framed_inline[#1]% % {\framed[\c!location=\v!low,#1]} % % or: \def\pack_framed_inline[% {\framed[\c!location=\v!low,} %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 \unexpanded\def\pack_framed_math_strut {\Ustartmath \triggermathstyle\c_framed_mstyle \vphantom{(}% \Ustopmath} \installcorenamespace{mathframed} \installframedcommandhandler \??mathframed {mathframed} \??mathframed \appendtoks \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}% \to \everydefinemathframed \unexpanded\def\pack_framed_mathframed#1% {\begingroup \edef\currentmathframed{#1}% \dosingleempty\pack_framed_mathframed_indeed} \newcount\c_pack_framed_mathframed \newtoks \t_pack_framed_mathframed \def\pack_framed_math_pos {\global\advance\c_pack_framed_mathframed\plusone \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}% \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}% \xypos\pack_framed_mc_two} \def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here {\iffirstargument \setupcurrentmathframed[#1]% \fi \c_framed_mstyle\mathstyle \edef\m_framed_location{\mathframedparameter\c!location}% \ifx\m_framed_location\v!mathematics \let\normalstrut\pack_framed_math_pos \orelse\ifx\m_framed_location\v!low\else \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 \def\doformatonelinerbox % beware: assumes explicit preceding bgroup {\ifconditional\raggedonelinerstate \expandafter\dodoformatonelinerbox \else \expandafter\nodoformatonelinerbox \fi} \def\dodoformatonelinerbox {\afterassignment\redoformatonelinerbox \setbox\nextbox\hbox} % maybe \hpack \def\redoformatonelinerbox {\aftergroup\dododoformatonelinerbox \ignorespaces} \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} \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 \bgroup \synchronizeinlinedirection \localbegstrut %\aftergrouped{\localendstrut\pack_framed_do_bottom\egroup}% \aftergroup\localendstrut \aftergroup\pack_framed_do_bottom \aftergroup\egroup \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 \bgroup \synchronizeinlinedirection \localbegstrut \aftergroup\localendstrut \aftergroup\vss \aftergroup\egroup \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 \bgroup \aftergroup\localendstrut \aftergroup\vss \aftergroup\egroup \synchronizeinlinedirection \localbegstrut \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 \bgroup \synchronizeinlinedirection \localbegstrut \aftergroup\localendstrut \aftergroup\pack_framed_do_bottom \aftergroup\egroup \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 \bgroup \aftergroup\vss \aftergroup\egroup \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 \bgroup \aftergroup\hss \aftergroup\egroup \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. \unexpanded\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} \unexpanded\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. \unexpanded\def\pack_framed_vboxed_newline {\endgraf\ignorespaces} \unexpanded\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 \setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}% \setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }% \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} \unexpanded\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 \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] \unexpanded\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. \unexpanded\def\pack_framed_text_direct#1% {\bgroup \edef\currentframedtext{#1}% \dosingleempty\pack_framed_text_start_direct} \def\pack_framed_text_start_direct[#1]% {\usebodyfontparameter\framedtextparameter \iffirstargument \setupcurrentframedtext[#1]% \fi \edef\p_framed_text_strut{\framedtextparameter\c!strut}% \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup \blank[\v!disable]% \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 \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}% \to \everydefineframed \newcount\c_temp_framed_crap \unexpanded\def\pack_framed_defined_process[#1]% 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 \expandafter\def\csname\??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 \dosingleempty\pack_framed_defined_process_indeed} \def\pack_framed_defined_process_indeed[#1]% {\iffirstargument % faster \setupcurrentframed[#1]% here ! \fi \pack_framed_process_indeed} \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] \unexpanded\def\startframedcontent {\dosingleempty\pack_framed_start_content} \def\pack_framed_start_content[#1]% {\bgroup \edef\currentframedcontent{#1}% \ifx\currentframedcontent\v!off \let\stopframedcontent\egroup \else \checkframedcontentparent \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]} \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: \def\v!unframed{unframed} \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 New: slow but ok for most cases: \unexpanded\def\doifelseframed#1% {\ifcase\numexpr\zerocount \immediateassignment\edef\tempstring{#1\c!frame }\ifx\tempstring\v!on +\plusone\fi \immediateassignment\edef\tempstring{#1\c!topframe }\ifx\tempstring\v!on +\plusone\fi \immediateassignment\edef\tempstring{#1\c!bottomframe}\ifx\tempstring\v!on +\plusone\fi \immediateassignment\edef\tempstring{#1\c!leftframe }\ifx\tempstring\v!on +\plusone\fi \immediateassignment\edef\tempstring{#1\c!rightframe }\ifx\tempstring\v!on +\plusone\fi \immediateassignment\edef\tempstring{#1\c!background }\ifempty\tempstring\else+\plusone\fi \relax\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} \protect \endinput