pack-rul.mkiv /size: 97 Kb    last modification: 2021-10-28 13:50
1%D \module
2%D   [       file=pack-rul, % was core-rul,
3%D        version=1998.10.16,
4%D          title=\CONTEXT\ Packaging Macros,
5%D       subtitle=Ruled Content,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content}
15
16%D The code here is expanded lots of time as framed is used in many places. This is
17%D why the code here is (and gets) optimized as much as possible. Also, by avoiding
18%D packaging and expansion we also keep tracing reasonable. For instance, multiple
19%D stacked backgrounds can slow down a run if not optimized this way.
20
21\registerctxluafile{pack-rul}{optimize}
22
23\unprotect
24
25% \definesystemvariable {ol}   % OmLijnd -> check scrn-fld too
26
27%D \macros
28%D   {linewidth, setuplinewidth}
29%D
30%D This module deals with rules (lines) in several ways. First we introduce two
31%D macros that can be used to set some common characteristics.
32%D
33%D \showsetup{setuplinewidth}
34%D
35%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals
36%D the default hard coded \TEX\ rule width.
37
38\newdimen\linewidth
39
40\unexpanded\def\setuplinewidth
41  {\dosingleargument\pack_framed_setup_line_width}
42
43\def\pack_framed_setup_line_width[#1]%
44  {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
45
46%D The parameter handler:
47
48\installcorenamespace{framed}
49\installcorenamespace{framedtop}
50\installcorenamespace{framedbottom}
51\installcorenamespace{framedleft}
52\installcorenamespace{framedright}
53
54\installcorenamespace{regularframed}
55\installcorenamespace{simplifiedframed}
56
57\installcommandhandler \??framed {framed} \??framed
58
59\let\pack_framed_framedparameter    \framedparameter
60\let\pack_framed_framedparameterhash\framedparameterhash
61\let\pack_framed_setupcurrentframed \setupcurrentframed
62
63\def\pack_framed_initialize
64  {\let\framedparameter    \pack_framed_framedparameter
65   \let\framedparameterhash\pack_framed_framedparameterhash
66   \let\setupcurrentframed \pack_framed_setupcurrentframed
67   \inframedtrue}
68
69%D A helper:
70
71\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
72
73%D Inheritance:
74
75\def\installinheritedframed#1%
76  {\normalexpanded{\doinstallinheritedframed
77     \expandafter\noexpand\csname current#1\endcsname
78     \expandafter\noexpand\csname #1parameter\endcsname
79     \expandafter\noexpand\csname #1parameterhash\endcsname
80     \expandafter\noexpand\csname do#1parameter\endcsname
81     \expandafter\noexpand\csname do#1parentparameter\endcsname
82     \expandafter\noexpand\csname do#1rootparameter\endcsname
83     \expandafter\noexpand\csname setupcurrent#1\endcsname
84     \expandafter\noexpand\csname inherited#1framed\endcsname
85     \expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new
86
87\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
88  {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
89  %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
90  %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
91   \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
92   \unexpanded\def#8%
93     {\bgroup
94      \bgroup
95      \inframedtrue
96      \let\currentframed      #1%
97      \let\framedparameter    #2%
98      \let\framedparameterhash#3%
99      \let\setupcurrentframed #7%
100      \pack_framed_process_indeed}%
101   \unexpanded\def#9%
102     {\bgroup
103      \inframedtrue
104      \let\currentframed      #1%
105      \let\framedparameter    #2%
106      \let\framedparameterhash#3%
107      \let\setupcurrentframed #7%
108      \pack_framed_process_box_indeed}}
109
110\unexpanded\def\installframedcommandhandler#1#2#3%
111  {\installcommandhandler{#1}{#2}{#3}%
112   \installinheritedframed{#2}}
113
114\unexpanded\def\installframedautocommandhandler#1#2#3%
115  {\installautocommandhandler{#1}{#2}{#3}%
116   \installinheritedframed{#2}}
117
118\unexpanded\def\installsimpleframedcommandhandler#1#2#3%
119  {\installsimplecommandhandler{#1}{#2}{#3}%
120   \installinheritedframed{#2}}
121
122% for regular framed
123
124\setupframed
125  [\c!width=\v!fit,
126   \c!height=\v!broad,
127  %\c!minheight=\zeropoint,
128  %\c!lines=,
129   \c!offset=.25\exheight,  % \defaultframeoffset
130   \c!empty=\v!no,
131   \c!frame=\v!on,
132  %\c!topframe=,
133  %\c!bottomframe=,
134  %\c!leftframe=,
135  %\c!rightframe=,
136   \c!radius=.5\bodyfontsize,
137   \c!rulethickness=\linewidth,
138   \c!corner=\v!rectangular,
139   \c!depth=\zeropoint,
140  %\c!foregroundcolor=,
141  %\c!foregroundstyle=,
142  %\c!background=,
143  %\c!backgroundcolor=,
144   \c!backgroundoffset=\zeropoint,
145  %\c!framecolor=,
146   \c!frameoffset=\zeropoint,
147   \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
148   \c!backgroundradius=\framedparameter\c!radius,
149   \c!backgrounddepth=\framedparameter\c!depth,
150   \c!framecorner=\framedparameter\c!corner,
151   \c!frameradius=\framedparameter\c!radius,
152   \c!framedepth=\framedparameter\c!depth,
153  %\c!component=,
154  %\c!region=,
155  %\c!align=,
156   \c!bottom=\vss,
157  %\c!top=,
158   \c!strut=\v!yes,
159   \c!autostrut=\v!yes,
160   \c!location=\v!normal,
161  %\c!orientation=,
162   \c!autowidth=\v!yes,
163  %\c!setups=,
164   \c!loffset=\zeropoint,
165   \c!roffset=\zeropoint,
166   \c!toffset=\zeropoint,
167   \c!boffset=\zeropoint]
168
169%D For backgrounds and such:
170
171\defineframed
172  [\??simplifiedframed]
173  [\c!frame=\v!off,
174   \c!depth=\zeropoint,
175   \c!offset=\v!overlay,
176   \c!component=,
177   \c!region=,
178   \c!radius=.5\bodyfontsize,
179   \c!rulethickness=\linewidth,
180   \c!corner=\v!rectangular,
181   \c!backgroundoffset=\zeropoint,
182   \c!frameoffset=\zeropoint,
183   \c!backgroundcorner=\framedparameter\c!corner,  % use \p_ here
184   \c!backgroundradius=\framedparameter\c!radius,
185   \c!backgrounddepth=\framedparameter\c!depth,
186   \c!framecorner=\framedparameter\c!corner,
187   \c!frameradius=\framedparameter\c!radius,
188   \c!framedepth=\framedparameter\c!depth,
189   \c!location=\v!normal,
190   \c!loffset=\zeropoint,
191   \c!roffset=\zeropoint,
192   \c!toffset=\zeropoint,
193   \c!boffset=\zeropoint]
194
195\unexpanded\def\definesimplifiedframed[#1]% no settings
196  {\defineframed[#1][\??simplifiedframed]%
197   \expandafter\let\csname#1\endcsname\undefined}
198
199\expandafter\let\csname\??simplifiedframed\endcsname\undefined
200
201%D We will communicate through module specific variables, current framed
202%D parameters and some reserved dimension registers.
203
204\newdimen\d_framed_target_wd
205\newdimen\d_framed_target_ht
206\newdimen\d_framed_target_dp
207\newdimen\d_framed_linewidth  \let\ruledlinewidth\d_framed_linewidth % needed at lua end
208
209\let\p_framed_frame           \empty % \framedparameter\c!frame
210\let\p_framed_backgroundoffset\empty
211\let\p_framed_foregroundstyle \empty
212\let\p_framed_autostrut       \empty
213\let\p_framed_location        \empty
214\let\p_framed_orientation     \empty
215\let\p_framed_autowidth       \empty
216\let\p_framed_franalyze       \empty
217\let\p_framed_backgroundcorner\empty
218\let\p_framed_backgroundradius\empty
219\let\p_framed_framecorner     \empty
220\let\p_framed_frameradius     \empty
221\let\p_framed_lines           \empty
222\let\p_framed_empty           \empty
223\let\p_framed_backgroundcolor \empty
224\let\p_framed_framecolor      \empty
225\let\p_framed_component       \empty
226\let\p_framed_background      \empty
227\let\p_framed_rulethickness   \empty
228\let\p_framed_foregroundcolor \empty
229\let\p_framed_setups          \empty
230
231%D We don't have to stick to a \TEX\ drawn rule, but also can use rounded
232%D or even fancier shapes, as we will see later on.
233
234\def\pack_framed_filled_box
235  {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}%
236   \ifx\p_framed_backgroundcorner\v!rectangular
237     \pack_framed_filled_box_normal
238   \else
239     \pack_framed_filled_box_radius
240   \fi}
241
242\def\pack_framed_filled_box_normal
243  {\vrule
244     \s!width \d_framed_target_wd
245     \s!height\d_framed_target_ht
246     \s!depth \d_framed_target_dp
247   \relax}
248
249\def\pack_framed_filled_box_radius
250  {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}%
251   \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize
252     \pack_framed_filled_box_normal
253   \else
254     \pack_framed_filled_box_round
255   \fi}
256
257\def\pack_framed_filled_box_round
258  {\raise\d_framed_target_dp\hpack{\frule
259     type   fill
260     width  \d_framed_target_wd
261     height \d_framed_target_ht
262     depth  \d_framed_target_dp
263     line   \d_framed_linewidth
264     radius \p_framed_backgroundradius\space
265     corner {\p_framed_backgroundcorner}
266   \relax}}
267
268\def\pack_framed_stroked_box
269  {\edef\p_framed_framecorner{\framedparameter\c!framecorner}%
270   \ifx\p_framed_framecorner\v!rectangular
271     \pack_framed_stroked_box_normal
272   \else
273     \pack_framed_stroked_box_radius
274   \fi}
275
276\def\pack_framed_stroked_box_radius
277  {\edef\p_framed_frameradius{\framedparameter\c!frameradius}%
278   \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize
279     \pack_framed_stroked_box_normal
280   \else\ifx\p_framed_frame\v!on
281     \pack_framed_stroked_box_round
282   \fi\fi}
283
284% \pack_framed_stroked_box_normal % later
285
286\def\pack_framed_stroked_box_round
287  {\raise\d_framed_target_dp\hpack{\frule
288     width  \d_framed_target_wd
289     height \d_framed_target_ht
290     depth  \d_framed_target_dp
291     line   \d_framed_linewidth
292     radius \p_framed_frameradius\space
293     corner {\p_framed_framecorner}
294   \relax}}
295
296% a lot of weird corners
297%
298% \startTEXpage
299%     \dontleavehmode\framed
300%         [corner=0,frame=on,framecolor=green,
301%          background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
302%     \vskip1em
303%     \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
304%         [corner=\recurselevel,frame=on,framecolor=green,
305%          background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
306%         \quad}
307%     \vskip1em
308%     \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
309%         [corner=\recurselevel,frame=on,framecolor=green,
310%          background=color,backgroundcolor=yellow]{\tttf TEST \twodigits\recurselevel}%
311%         \quad}
312%     \vskip1em
313%     \dontleavehmode\dostepwiserecurse {1} {4}{1}{\framed
314%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
315%         \quad}
316%     \vskip1em
317%     \dontleavehmode\dostepwiserecurse {5} {8}{1}{\framed
318%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
319%         \quad}
320%     \vskip1em
321%     \dontleavehmode\dostepwiserecurse {9}{12}{1}{\framed
322%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
323%         \quad}
324%     \vskip1em
325%     \dontleavehmode\dostepwiserecurse{13}{16}{1}{\framed
326%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
327%         \quad}
328%     \vskip1em
329%     \dontleavehmode\dostepwiserecurse{17}{20}{1}{\framed
330%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
331%         \quad}
332%     \vskip1em
333%     \dontleavehmode\dostepwiserecurse{21}{24}{1}{\framed
334%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
335%         \quad}
336%     \vskip1em
337%     \dontleavehmode\dostepwiserecurse{25}{28}{1}{\framed
338%         [corner=\recurselevel,frame=on,framecolor=green]{\tttf TEST \twodigits\recurselevel}%
339%         \quad}
340% \stopTEXpage
341
342%D It won't be a surprise that we not only provide gray boxes, but also colored
343%D ones. Here it is:
344
345\def\pack_framed_background_box_color
346  {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}%
347   \ifx\p_framed_backgroundcolor\empty \else
348     \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed
349   \fi}
350
351\def\pack_framed_background_box_color_indeed
352  {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
353
354%D \macros
355%D   {defineoverlay, doifoverlayelse, overlayoffset,
356%D    overlaywidth, overlayheight, overlaydepth,
357%D    overlaycolor, overlaylinecolor, overlaylinewidth}
358%D
359%D Before we define the macro that actually takes card of the backgrounds, we
360%D introduce overlays. An overlay is something that contrary to its name lays {\em
361%D under} the text. An example of an overlay definition is:
362%D
363%D \startbuffer[tmp-1]
364%D \defineoverlay
365%D   [fancy]
366%D   [{\externalfigure
367%D       [mp-cont.502]
368%D       [width=\overlaywidth,
369%D        height=\overlayheight]}]
370%D \stopbuffer
371%D
372%D \typebuffer[tmp-1]
373%D
374%D  That for instance can be uses in:
375%D
376%D  \startbuffer[tmp-2]
377%D  \framed[backgroundachtergrond=fancy]{How Fancy!}
378%D  \framed[backgroundachtergrond=fancy,frame=off]{Even More Fancy!}
379%D  \stopbuffer
380%D
381%D  and looks like:
382%D
383%D  \startlinecorrection
384%D  \vbox{\baselineskip24pt\getbuffer[tmp-1]\getbuffer[tmp-2]}
385%D  \stoplinecorrection
386%D
387%D The formal definition is:
388%D
389%D \showsetup{defineoverlay}
390%D
391%D This macro's definition is a bit obscure, due the many non||used arguments and
392%D the two step call that enable the setting of the width, height and depth
393%D variables. Multiple backgrounds are possible and are specified as:
394%D
395%D \starttyping
396%D \framed[background={one,two,three}]{Three backgrounds!}
397%D \stoptyping
398%D
399%D Most drawing packages only know width and height. Therefore the dimensions have a
400%D slightly different meaning here:
401%D
402%D \startitemize[packed]
403%D \item \type{\overlaywidth }: width of the overlay
404%D \item \type{\overlayheight}: height plus depth of the overlay
405%D \item \type{\overlaydepth }: depth of the overlay
406%D \stopitemize
407%D
408%D The resulting box is lowered to the right depth.
409
410%def\overlaywidth      {\the\hsize\space} % We preset the variables
411%def\overlayheight     {\the\vsize\space} % to some reasonable default
412%def\overlaydepth      {0pt }             % values. The attributes
413%let\overlayoffset     \overlaydepth      % of the frame can be (are)
414%let\overlaylinewidth  \overlaydepth      % set somewhere else.
415\let\overlaycolor      \empty
416\let\overlaylinecolor  \empty
417
418\def\overlayradius{\framedparameter\c!frameradius}
419
420\newdimen\d_overlay_width
421\newdimen\d_overlay_height
422\newdimen\d_overlay_depth
423\newdimen\d_overlay_offset
424\newdimen\d_overlay_linewidth
425
426\let\m_overlay_region\empty
427
428% expandable ... in a future version the space will go (in my one can use Overlay*)
429
430\def\overlaywidth        {\the\d_overlay_width    \space} % We preset the variables
431\def\overlayheight       {\the\d_overlay_height   \space} % to some reasonable default
432\def\overlaydepth        {\the\d_overlay_depth    \space} % values.
433\def\overlayoffset       {\the\d_overlay_offset   \space} % of the frame can be (are)
434\def\overlaylinewidth    {\the\d_overlay_linewidth\space} % set somewhere else.
435\def\overlayregion       {\m_overlay_region}
436
437% public but kind of protected
438
439\def\usedoverlaywidth    {\dimexpr\d_overlay_width    \relax}
440\def\usedoverlayheight   {\dimexpr\d_overlay_height   \relax}
441\def\usedoverlaydepth    {\dimexpr\d_overlay_depth    \relax}
442\def\usedoverlayoffset   {\dimexpr\d_overlay_offset   \relax}
443\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax}
444
445%D The next register is used to initialize overlays.
446
447\newtoks\everyoverlay
448
449%D An example of an initialization is the following (overlays can contain text
450%D and be executed under an regime where interlineskip is off).
451
452\installcorenamespace{overlay}
453\installcorenamespace{overlaybuiltin}
454
455\appendtoks
456    \oninterlineskip
457\to \everyoverlay
458
459\prependtoks
460    \hsize\d_overlay_width
461    \vsize\d_overlay_height
462\to \everyoverlay
463
464\unexpanded\def\defineoverlay
465  {\dodoubleargument\pack_framed_define_overlay}
466
467\def\pack_framed_define_overlay[#1][#2]%
468  {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
469   \processcommalist[#1]\pack_framed_define_overlay_indeed}
470
471\unexpanded\def\executedefinedoverlay#1#2% we can share the definitions
472  {\bgroup % redundant grouping
473   \setbox\scratchbox\hbox\bgroup
474     \ifzeropt\d_framed_target_dp
475       \the\everyoverlay#2% saves wrapping (and lua call)
476     \else
477       \lower\d_framed_target_dp
478       \hbox{\the\everyoverlay#2}%
479     \fi
480   \egroup
481   \setlayoutcomponentattribute{\v!overlay:#1}%
482   \setbox\scratchbox\hpack \layoutcomponentboxattribute
483     {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width
484      \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \d_overlay_height !
485      \box\scratchbox}%
486   \wd\scratchbox\d_framed_target_wd
487   \ht\scratchbox\d_framed_target_ht
488   \dp\scratchbox\d_framed_target_dp
489   \box\scratchbox
490   \egroup}
491
492%D \macros
493%D   {overlayfakebox}
494
495% \unexpanded\def\overlayfakebox
496%   {\hpack
497%      {\setbox\scratchbox\emptyhbox
498%       \wd\scratchbox\d_overlay_width
499%       \ht\scratchbox\d_overlay_height
500%       \box\scratchbox}}
501
502\unexpanded\def\overlayfakebox
503  {\hpack % redundant but needs testing
504     {\novrule
505        \s!width \d_overlay_width
506        \s!height\d_overlay_height
507        \s!depth \zeropoint}}
508
509%D For testing we provide:
510
511\def\doifelseoverlay#1% only tests external overlays
512  {\ifcsname\??overlay#1\endcsname
513     \expandafter\firstoftwoarguments
514   \else
515     \expandafter\secondoftwoarguments
516   \fi}
517
518\let\doifoverlayelse\doifelseoverlay
519
520%D The content of the box will be (temporary) saved in a box. We also have an
521%D extra box for backgrounds.
522
523\newbox\b_framed_normal
524\newbox\b_framed_extra
525
526\newtoks\everybackgroundbox
527
528\let\m_framed_background\empty % we might need a public name
529
530\def\pack_framed_process_background
531  {\ifcsname\??overlaybuiltin\m_framed_background\endcsname
532     \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs
533   \else\ifcsname\??overlay\m_framed_background\endcsname
534     \expandafter\pack_framed_process_background_indeed_external\lastnamedcs
535   \fi\fi}
536
537\def\pack_framed_process_background_indeed_internal#1% % : in name
538  {\bgroup
539   \setbox\b_framed_extra\hpack\bgroup
540     \ifzeropt\framedbackgroundoffset\else
541       \kern-\framedbackgroundoffset
542     \fi
543     \hbox\bgroup#1\egroup
544   \egroup
545   \wd\b_framed_extra\zeropoint
546   \ht\b_framed_extra\framedbackgroundheight
547   \dp\b_framed_extra\framedbackgrounddepth
548   \box\b_framed_extra
549   \egroup}
550
551\def\pack_framed_process_background_indeed_external
552  {\pack_framed_overlay_initialize
553   \pack_framed_process_background_indeed_internal}
554
555\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground)
556  {\edef\m_framed_background{#1}%
557   \ifx\m_framed_background\s!unknown\else
558     \pack_framed_process_background
559     \expandafter\pack_framed_process_backgrounds
560   \fi#2}
561
562%D Beware, a backgroundbox can be empty which is another reason why we set the
563%D width to zero instead of back-skipping.
564
565\newdimen\framedbackgroundwidth
566\newdimen\framedbackgroundheight
567\newdimen\framedbackgrounddepth
568\newdimen\framedbackgroundoffset
569
570\def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise
571  {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
572
573\def\pack_framed_set_region % experiment
574  {\ifx\m_overlay_region\v!yes
575     \edef\m_overlay_region{\reservedautoregiontag}%
576   \fi}
577
578\def\pack_framed_add_region % experiment
579  {\anch_mark_tagged_box\b_framed_normal\m_overlay_region}
580
581\def\pack_framed_add_background
582  {\setbox\b_framed_normal\hpack % was vbox % see also *1*
583     {%\pack_framed_forgetall % can be relaxed
584      \boxmaxdepth\maxdimen
585      \framedbackgroundoffset\d_framed_backgroundoffset
586      \framedbackgroundwidth \wd\b_framed_normal
587      \framedbackgroundheight\ht\b_framed_normal
588      \framedbackgrounddepth \dp\b_framed_normal
589      \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax
590      \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax
591      \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
592      \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed
593      \ifx\p_framed_component\empty
594        \resetlayoutcomponentattribute
595      \else
596        \setlayoutcomponentattribute{\v!background:\p_framed_component}%
597      \fi
598      \let\foregroundbox\pack_framed_background_box_content
599      \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
600         \the\everybackgroundbox % moved
601         \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it
602         \box\b_framed_normal
603         \hss
604      \egroup}}
605
606\def\pack_framed_overlay_initialize_indeed
607  {\d_overlay_width     \d_framed_target_wd
608   \d_overlay_height    \dimexpr\d_framed_target_ht+\d_framed_target_dp\relax
609   \d_overlay_depth     \d_framed_target_dp
610   \d_overlay_linewidth \d_framed_linewidth
611   \d_overlay_offset    \framedbackgroundoffset\relax
612   \edef\overlaycolor    {\framedparameter\c!backgroundcolor}% let ?
613   \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
614  %\edef\overlaycorner   {\framedparameter\c!backgroundcorner}%
615  %\edef\overlayradius   {\framedparameter\c!backgroundradius}%
616   \let\pack_framed_overlay_initialize\relax}
617
618%D One can explictly insert the foreground box. For that purpose we introduce the
619%D overlay \type {foreground}.
620%D
621%D We predefine two already familiar backgrounds:
622
623%letvalue{\??overlaybuiltin\v!screen    }\pack_framed_background_box_gray
624\letvalue{\??overlaybuiltin\v!color     }\pack_framed_background_box_color
625\letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox]
626
627%D We can specify overlays as a comma separated list of overlays, a sometimes
628%D handy feature.
629%D
630%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled
631%D borders). Again we have to deal with square and round corners. The first category
632%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro
633%D also support a negative offset.
634
635\def\pack_framed_add_outline
636  {\setbox\b_framed_normal\hpack % rules on top of box
637     {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax
638      \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax
639      \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax
640      \ifdim\d_framed_target_dp<\zeropoint
641        \advance\d_framed_target_ht \d_framed_target_dp
642        \scratchdimen-\d_framed_target_dp
643        \d_framed_target_dp\zeropoint
644      \else
645        \scratchdimen\zeropoint
646      \fi
647      \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background
648      \setbox\b_framed_extra\hpack
649        {\kern-\d_framed_frameoffset
650         \raise\scratchdimen
651         \hpack{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
652      \wd\b_framed_extra\wd\b_framed_normal
653      \ht\b_framed_extra\ht\b_framed_normal
654      \dp\b_framed_extra\dp\b_framed_normal
655      \wd\b_framed_normal\zeropoint
656      \box\b_framed_normal
657      \box\b_framed_extra}}
658
659\def\pack_framed_stroked_box_normal_opened
660  {\setbox\scratchbox\vpack \bgroup
661     \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname
662     \nointerlineskip % new (needed for fences)
663     \hpack \bgroup
664       \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname
665       \novrule
666         \s!width \d_framed_target_wd
667         \s!height\d_framed_target_ht
668         \s!depth \d_framed_target_dp
669       \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname
670     \egroup
671     \nointerlineskip % new (needed for fences)
672     \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
673   \egroup
674   \wd\scratchbox\d_framed_target_wd
675   \ht\scratchbox\d_framed_target_ht
676   \dp\scratchbox\d_framed_target_dp
677   \box\scratchbox}
678
679\def\pack_framed_stroked_box_normal_closed
680  {\hpack\bgroup
681     \scratchdimen.5\d_framed_linewidth
682     \hskip\scratchdimen
683     \clf_framedoutline
684       \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax
685       \dimexpr\d_framed_target_ht-\scratchdimen\relax
686       \dimexpr\d_framed_target_dp-\scratchdimen\relax
687       \d_framed_linewidth
688     \relax
689   \egroup}
690
691\def\pack_framed_stroked_box_normal
692  {\ifx\p_framed_frame\v!closed
693     \pack_framed_stroked_box_normal_closed
694   \else
695     \pack_framed_stroked_box_normal_opened
696   \fi}
697
698\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth}
699\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth}
700\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth}
701\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
702
703\letvalue{\??framedtop   \v!on \v!on}\pack_framed_t_rule
704\letvalue{\??framedtop   \v!off\v!on}\pack_framed_t_rule
705\letvalue{\??framedtop   \v!on      }\pack_framed_t_rule
706
707\letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule
708\letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule
709\letvalue{\??framedbottom\v!on      }\pack_framed_b_rule
710
711\letvalue{\??framedleft  \v!on \v!on}\pack_framed_l_rule
712\letvalue{\??framedleft  \v!off\v!on}\pack_framed_l_rule
713\letvalue{\??framedleft  \v!on      }\pack_framed_l_rule
714
715\letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule
716\letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule
717\letvalue{\??framedright \v!on      }\pack_framed_r_rule
718
719% no overlapping rules
720
721\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}
722\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}}
723\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}
724\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}
725
726\letvalue{\??framedtop   \v!small\v!small}\pack_framed_t_rules
727\letvalue{\??framedtop   \v!off  \v!small}\pack_framed_t_rules
728\letvalue{\??framedtop   \v!small        }\pack_framed_t_rules
729
730\letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules
731\letvalue{\??framedbottom\v!off  \v!small}\pack_framed_b_rules
732\letvalue{\??framedbottom\v!small        }\pack_framed_b_rules
733
734\letvalue{\??framedleft  \v!small\v!small}\pack_framed_l_rules
735\letvalue{\??framedleft  \v!off  \v!small}\pack_framed_l_rules
736\letvalue{\??framedleft  \v!small        }\pack_framed_l_rules
737
738\letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules
739\letvalue{\??framedright \v!off  \v!small}\pack_framed_r_rules
740\letvalue{\??framedright \v!small        }\pack_framed_r_rules
741
742% \framed
743%   [width=4cm,height=3cm,rulethickness=3mm,
744%    frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on]
745%   {}
746% \framed
747%   [width=4cm,height=3cm,rulethickness=3mm,
748%    frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small]
749%   {}
750% \framed
751%   [width=4cm,height=3cm,rulethickness=3mm,
752%    frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on]
753%   {}
754
755%D The next few macros are probably the most misused ones in \CONTEXT. They deal
756%D with putting rules around boxes, provide backgrounds, offer alignment features,
757%D and some more. We start with defining some booleans. These give an impression of
758%D what we are going to take into account.
759
760% todo   : \c_framed_hasoffset
761% faster : \let\c_framed_hasoffset\falseconditional
762
763\newconditional\c_framed_has_offset
764\newconditional\c_framed_has_width
765\newconditional\c_framed_has_height
766\newconditional\c_framed_has_format
767\newconditional\c_framed_is_overlaid
768\newconditional\c_framed_has_frame
769\newconditional\c_framed_has_extra_offset
770\newconditional\c_framed_text_location_none
771
772\newconstant   \c_framed_has_strut  % 0=relaxes 1=pseudostruts 2=realstruts
773
774%D \macros
775%D   {framed, setupframed}
776%D
777%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile
778%D and, although some users will probably seldom use it, one cannot overlook its
779%D features.
780%D
781%D  \showsetup{setupframed}
782%D  \showsetup{framed}
783%D
784%D This general macro is a special version of an even more general case, that can
785%D easily be linked into other macros that need some kind of framing. The local
786%D version is called with an extra parameter: the variable identifier. The reason
787%D for passing this identifier between brackets lays in the mere fact that this way
788%D we can use the optional argument grabbers.
789
790\def\defaultframeoffset{.25\exheight}
791
792\installcorenamespace{regularframedlevel}
793
794\unexpanded\def\installregularframed#1%
795  {\defineframed[#1]}
796
797\unexpanded\def\presetlocalframed[#1]%
798  {\defineframed[#1]}
799
800% \presetlocalframed[\??framed]
801
802\newcount\c_pack_framed_nesting
803
804\unexpanded\def\pack_framed_process_framed[#1]%
805  {\bgroup
806   \iffirstargument % faster
807     \setupcurrentframed[#1]% here !
808   \fi
809   \pack_framed_process_indeed}
810
811\unexpanded\def\framed
812  {\bgroup
813   \advance\c_pack_framed_nesting\plusone
814   \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
815   \edef\currentframed{>\the\c_pack_framed_nesting}%
816   \pack_framed_initialize
817   \dosingleempty\pack_framed_process_framed}
818
819\unexpanded\def\startframed
820  {\dosingleempty\pack_framed_start_framed}
821
822\def\pack_framed_start_framed[#1]%
823  {\bgroup
824   \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}}
825
826\def\pack_framed_start_framed_yes#1%
827  {\advance\c_pack_framed_nesting\plusone
828   \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
829   \iffirstargument\secondargumenttrue\fi % dirty trick
830   \edef\currentframed{>\the\c_pack_framed_nesting}%
831   \pack_framed_initialize
832   \bgroup
833   \iffirstargument
834     \secondargumenttrue % dirty trick
835     \setupcurrentframed[#1]% here !
836   \fi
837   \pack_framed_process_indeed
838   \bgroup
839   \ignorespaces}
840
841\def\pack_framed_start_framed_nop#1%
842  {\edef\currentframed{#1}%
843   \dosingleempty\pack_framed_start_framed_nop_indeed}
844
845\def\pack_framed_start_framed_nop_indeed[#1]%
846  {\pack_framed_initialize
847   \bgroup
848   \iffirstargument
849     \setupcurrentframed[#1]% here !
850   \fi
851   \pack_framed_process_indeed
852   \bgroup
853   \ignorespaces}
854
855% till here
856
857\unexpanded\def\stopframed
858  {\removeunwantedspaces
859   \egroup}
860
861\unexpanded\def\normalframedwithsettings[#1]%
862  {\bgroup
863   \advance\c_pack_framed_nesting\plusone
864   \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
865   \bgroup
866   \edef\currentframed{>\the\c_pack_framed_nesting}%
867   \pack_framed_initialize
868   \setupcurrentframed[#1]%
869   \pack_framed_process_indeed}
870
871%D \startbuffer
872%D \setupframed [framecolor=yellow]          \framed{A}
873%D \defineframed[myframed] [framecolor=blue] \myframed{B}
874%D \setupframed [myframed] [framecolor=red]  \myframed{C}
875%D \stopbuffer
876%D
877%D \typebuffer \getbuffer
878%D
879%D \startbuffer
880%D \presetlocalframed[myframed]
881%D \localframed[myframed][framecolor=green]{oeps}
882%D \stopbuffer
883%D
884%D \typebuffer \getbuffer
885
886%D \macros
887%D   {ifinframed}
888%D
889%D The normal case first presets all parameters and next starts looking for the user
890%D supplied ones. The first step is omitted in the local case, because these are
891%D preset at declaration time and keep their values unless explictly changed. By
892%D presetting the variables everytime the normal command is called, we can use this
893%D command nested, without the unwanted side effect of inheritance. The boolean is
894%D used to speed up the color stack.
895
896\newif\ifinframed
897
898%D The next one is faster on multiple backgrounds per page. No
899%D dimensions can be set, only frames and backgrounds.
900
901\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
902  {\bgroup
903   \edef\currentframed{#1}%
904   \pack_framed_initialize
905   \setbox\b_framed_normal\hbox{#4}%
906   \iftrialtypesetting \else
907     \edef\m_overlay_region{\framedparameter\c!region}%
908     \ifx\m_overlay_region\empty\else
909       \pack_framed_set_region
910     \fi
911   \fi
912   \setupcurrentframed[#3]%
913   \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
914   \d_framed_frameoffset\framedparameter\c!frameoffset\relax     % also used in backgrounds
915   \edef\p_framed_frame{\framedparameter\c!frame}%
916   \edef\p_framed_background{\framedparameter\c!background}%
917   % not here, in calling macro: setups
918   \pack_framed_remove_depth
919   \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
920     \ifx\p_framed_rulethickness\empty\else
921        \d_framed_linewidth\p_framed_rulethickness\relax
922     \fi
923     \pack_framed_add_outline % real or invisible frame
924   \fi\fi
925   \ifx\p_framed_background\empty \else
926     \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
927     \d_framed_backgroundoffset
928       \ifx\p_framed_backgroundoffset\v!frame
929         \d_framed_frameoffset
930       \else
931         \p_framed_backgroundoffset
932       \fi
933     \edef\p_framed_component{\framedparameter\c!component}%
934     \pack_framed_add_background
935   \fi
936   \pack_framed_restore_depth
937   \iftrialtypesetting \else
938     \ifx\m_overlay_region\empty\else
939       \pack_framed_add_region
940     \fi
941   \fi
942   \box\b_framed_normal
943   \egroup}
944
945%D The next macro uses a box and takes its natural width and height so these
946%D can better be correct.
947
948\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
949  {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2
950   \edef\m_overlay_region{\framedparameter\c!region}%
951   \ifx\m_overlay_region\empty\else
952     \pack_framed_set_region
953   \fi
954   \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
955   \d_framed_frameoffset\framedparameter\c!frameoffset\relax     % also used in backgrounds
956   \edef\p_framed_frame{\framedparameter\c!frame}%
957   \edef\p_framed_background{\framedparameter\c!background}%
958   \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
959     \ifx\p_framed_rulethickness\empty \else
960        \d_framed_linewidth\p_framed_rulethickness\relax
961     \fi
962     \pack_framed_add_outline % real or invisible frame
963   \fi\fi
964   \ifx\p_framed_background\empty \else
965     \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
966     \d_framed_backgroundoffset
967       \ifx\p_framed_backgroundoffset\v!frame
968         \d_framed_frameoffset
969       \else
970         \p_framed_backgroundoffset
971       \fi
972     \edef\p_framed_component{#1}%
973     \pack_framed_add_background
974   \fi
975   \ifx\m_overlay_region\empty\else
976     \pack_framed_add_region
977   \fi
978   \box\b_framed_normal
979   \egroup}
980
981\unexpanded\def\localbackgroundframed#1% namespace component box
982  {\bgroup
983   \edef\currentframed{#1}%
984   \pack_framed_initialize
985   \pack_framed_process_box_indeed} % group ends here
986
987\let\postprocessframebox\relax
988
989%D A nice example by Aditya:
990%D
991%D \starttyping
992%D \setupframed
993%D   [loffset=\framedparameter{hoffset},
994%D    roffset=\framedparameter{hoffset},
995%D    hoffset=\zeropoint]
996%D
997%D \defineframed[test][hoffset=1cm]
998%D \stoptyping
999
1000\newdimen\d_framed_width
1001\newdimen\d_framed_height
1002\newdimen\d_framed_frameoffset
1003\newdimen\d_framed_backgroundoffset
1004\newdimen\d_framed_local_offset
1005
1006% todo: protect local \framednames
1007
1008\unexpanded\def\localframed
1009  {\bgroup
1010   \dodoubleempty\pack_framed_local}
1011
1012\unexpanded\def\pack_framed_local[#1][#2]%
1013  {\bgroup
1014   \edef\currentframed{#1}%
1015   \pack_framed_initialize
1016   \ifsecondargument % faster
1017     \setupcurrentframed[#2]% here !
1018   \fi
1019   \pack_framed_process_indeed}
1020
1021\unexpanded\def\directlocalframed[#1]% no optional
1022  {\bgroup
1023   \bgroup
1024   \edef\currentframed{#1}%
1025   \pack_framed_initialize
1026   \pack_framed_process_indeed}
1027
1028\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
1029  {\bgroup
1030   \bgroup
1031   \edef\currentframed{#1}%
1032   \pack_framed_initialize
1033   \setupcurrentframed[#2]% here !
1034   \pack_framed_process_indeed}
1035
1036% done
1037
1038\def\c!fr!analyze{fr:analyze} % private option
1039
1040\let\delayedbegstrut\relax
1041\let\delayedendstrut\relax
1042\let\delayedstrut   \relax
1043
1044\let\localoffset\empty
1045\let\localwidth \empty
1046\let\localheight\empty
1047\let\localformat\empty
1048\let\localstrut \empty
1049
1050\unexpanded\def\pack_framed_process_indeed
1051  {\d_framed_frameoffset\framedparameter\c!frameoffset
1052   \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
1053   \d_framed_backgroundoffset
1054     \ifx\p_framed_backgroundoffset\v!frame
1055       \d_framed_frameoffset
1056     \else
1057       \p_framed_backgroundoffset
1058     \fi
1059   % new, experimental dirty hook
1060   \framedparameter\c!extras
1061   % to get the right spacing
1062   \edef\p_framed_foregroundstyle{\framedparameter\c!foregroundstyle}%
1063   \ifx\p_framed_foregroundstyle\empty\else\dousestyleparameter\p_framed_foregroundstyle\fi
1064   % beware, both the frame and background offset can be overruled
1065   %
1066   \edef\p_framed_setups{\framedparameter\c!setups}%
1067   % the next macros are visible
1068   \edef\localoffset{\framedparameter\c!offset}%
1069   \edef\localwidth {\framedparameter\c!width}%
1070   \edef\localheight{\framedparameter\c!height}%
1071   \edef\localformat{\framedparameter\c!align}%
1072   \edef\localstrut {\framedparameter\c!strut}%
1073   % these are not
1074   \edef\p_framed_autostrut  {\framedparameter\c!autostrut}%
1075   \edef\p_framed_frame      {\framedparameter\c!frame}%
1076   \edef\p_framed_location   {\framedparameter\c!location}%
1077   \edef\p_framed_orientation{\framedparameter\c!orientation}%
1078   %
1079   \edef\p_framed_autowidth  {\framedparameter\c!autowidth}%
1080   \edef\p_framed_franalyze  {\framedparameter\c!fr!analyze}% experimental option
1081   %
1082   \ifx\p_framed_frame\v!overlay   % no frame, no offset, no framewidth
1083     \setfalse\c_framed_has_frame
1084     \let\localoffset\v!overlay
1085   \else\ifx\p_framed_frame\v!none % no frame, no framewidth
1086     \setfalse\c_framed_has_frame
1087   \else
1088     \settrue\c_framed_has_frame
1089   \fi\fi
1090   \ifconditional\c_framed_has_frame
1091     \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}%
1092     \ifx\p_framed_rulethickness\empty\else
1093        \d_framed_linewidth\p_framed_rulethickness\relax
1094     \fi
1095   \else
1096     \d_framed_linewidth\zeropoint
1097   \fi
1098   % 2013/03/12: a change of order (sizes before align
1099   \ifx\localwidth\v!local
1100     \setlocalhsize
1101   \fi
1102   %
1103   \forgetall % should happen after \localwidth but before align
1104   %
1105   \ifx\localformat\empty
1106     \setfalse\c_framed_has_format
1107   \else
1108     \settrue\c_framed_has_format
1109     \dosetraggedcommand\localformat % not that fast
1110   \fi
1111   %
1112   \ifcsname\??framedoffsetalternative\localoffset\endcsname
1113     \lastnamedcs
1114   \else
1115     \framed_offset_alternative_unknown
1116   \fi
1117   \ifcsname\??framedwidthalternative\localwidth\endcsname
1118     \lastnamedcs
1119   \else
1120     \framed_width_alternative_unknown
1121   \fi
1122   \ifcsname\??framedheightalternative\localheight\endcsname
1123     \lastnamedcs
1124   \else
1125     \framed_height_alternative_unknown
1126   \fi
1127   % the next check could move to heightalternative
1128   \ifconditional\c_framed_has_height
1129     % obey user set height, also downward compatible
1130   \else
1131     \edef\p_framed_lines{\framedparameter\c!lines}%
1132     \ifx\p_framed_lines\empty\else
1133       \ifcase\p_framed_lines\else
1134          \d_framed_height\p_framed_lines\lineheight
1135          \edef\localheight{\the\d_framed_height}%
1136          \settrue\c_framed_has_height
1137        \fi
1138     \fi
1139   \fi
1140   % this is now an option: width=local
1141   %
1142   % \ifdim\d_framed_width=\hsize
1143   %   \parindent\zeropoint
1144   %   \setlocalhsize
1145   %   \d_framed_width\localhsize
1146   % \fi
1147   % i.e. disable (colsetbackgroundproblemintechniek)
1148   \advance\d_framed_width  -2\d_framed_local_offset
1149   \advance\d_framed_height -2\d_framed_local_offset
1150   \ifcsname\??framedstrutalternative\localstrut\endcsname
1151     \lastnamedcs
1152   \else
1153     \framed_offset_alternative_unknown
1154   \fi
1155   % the next check could move to strutalternative
1156   \ifcase\c_framed_has_strut % none (not even noindent)
1157     \let\localbegstrut\relax
1158     \let\localendstrut\relax
1159     \let\localstrut   \relax
1160   \or % no / overlay
1161     \let\localbegstrut\pseudobegstrut
1162     \let\localendstrut\pseudoendstrut
1163     \let\localstrut   \pseudostrut
1164   \else
1165     \let\localbegstrut\begstrut
1166     \let\localendstrut\endstrut
1167     \let\localstrut   \strut
1168   \fi
1169   \ifx\p_framed_autostrut\v!yes
1170     \let\delayedbegstrut\relax
1171     \let\delayedendstrut\relax
1172     \let\delayedstrut   \relax
1173   \else
1174     \let\delayedbegstrut\localbegstrut
1175     \let\delayedendstrut\localendstrut
1176     \let\delayedstrut   \localstrut
1177     \let\localbegstrut  \relax
1178     \let\localendstrut  \relax
1179     \let\localstrut     \relax
1180   \fi
1181   \ifconditional\c_framed_has_height
1182     \let\\\pack_framed_vboxed_newline
1183     \ifconditional\c_framed_has_width
1184       \let\hairline\pack_framed_vboxed_hairline
1185       \ifconditional\c_framed_has_format
1186         \let\next\pack_framed_format_format_yes
1187       \else
1188         \let\next\pack_framed_format_format_nop
1189       \fi
1190     \else
1191       \let\hairline\pack_framed_hboxed_hairline
1192       \ifconditional\c_framed_has_format
1193         \let\next\pack_framed_format_format_height
1194       \else
1195         \let\next\pack_framed_format_format_vsize
1196       \fi
1197     \fi
1198   \else
1199     \ifconditional\c_framed_has_width
1200       \ifconditional\c_framed_has_format
1201         \let\hairline\pack_framed_vboxed_hairline
1202         \let\\\pack_framed_vboxed_newline
1203         \let\next\pack_framed_format_format_width
1204       \else
1205         \let\hairline\pack_framed_hboxed_hairline
1206         \let\\\pack_framed_hboxed_newline
1207         \let\next\pack_framed_format_format_hsize
1208       \fi
1209     \else
1210       \let\hairline\pack_framed_hboxed_hairline
1211       \let\\\pack_framed_hboxed_newline
1212       \let\next\pack_framed_format_format_no_size
1213     \fi
1214   \fi
1215   \pack_framed_check_extra_offsets
1216   \edef\p_framed_background{\framedparameter\c!background}%
1217%    \ifx\p_framed_background\empty
1218%      \let\pack_framed_forgetall\forgetall
1219%    \else
1220%      \let\pack_framed_forgetall\relax
1221%      \forgetall
1222%    \fi
1223   \edef\framedwidth {\the\ifdim\d_framed_width >\zeropoint         \d_framed_width \else\zeropoint\fi}% public
1224   \edef\framedheight{\the\ifdim\d_framed_height>\zeropoint         \d_framed_height\else\zeropoint\fi}% public
1225   \edef\framedoffset{\the\dimexpr\ifconditional\c_framed_has_offset\localoffset    \else\zeropoint\fi}% public
1226   \ifx\p_framed_orientation\empty
1227     \let\pack_framed_stop_orientation\relax
1228   \else
1229     \pack_framed_start_orientation
1230   \fi
1231   \afterassignment\pack_framed_restart
1232   \setbox\b_framed_normal\next}
1233
1234% alternatives for width, height, strut and offset
1235
1236\installcorenamespace{framedwidthalternative}
1237\installcorenamespace{framedheightalternative}
1238\installcorenamespace{framedstrutalternative}
1239\installcorenamespace{framedoffsetalternative}
1240
1241% widths
1242
1243\setvalue{\??framedwidthalternative\empty}%
1244  {\ifconditional\c_framed_has_format
1245     \settrue\c_framed_has_width
1246     \d_framed_width\hsize
1247   \else
1248     \setfalse\c_framed_has_width
1249     \d_framed_width\zeropoint
1250   \fi}
1251
1252\setvalue{\??framedwidthalternative\v!fit}%
1253  {\ifconditional\c_framed_has_format
1254     \settrue\c_framed_has_width
1255     \d_framed_width\hsize
1256   \else
1257     \setfalse\c_framed_has_width
1258     \d_framed_width\zeropoint
1259   \fi}
1260
1261\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox
1262  {\ifconditional\c_framed_has_format
1263     \settrue\c_framed_has_width
1264     \d_framed_width\hsize
1265   \else
1266     \setfalse\c_framed_has_width
1267     \d_framed_width\zeropoint
1268   \fi}
1269
1270\setvalue{\??framedwidthalternative\v!broad}%
1271  {\settrue\c_framed_has_width
1272   \d_framed_width\hsize}
1273
1274\setvalue{\??framedwidthalternative\v!max}% idem broad
1275  {\settrue\c_framed_has_width
1276   \d_framed_width\hsize}
1277
1278\setvalue{\??framedwidthalternative\v!local}%
1279  {\settrue\c_framed_has_width
1280   %\setlocalhsize
1281   \d_framed_width\localhsize}
1282
1283\setvalue{\??framedwidthalternative\s!unknown}%
1284  {\settrue\c_framed_has_width
1285   \d_framed_width\localwidth}
1286
1287\def\framed_width_alternative_unknown
1288  {\settrue\c_framed_has_width
1289   \d_framed_width\localwidth}
1290
1291% heights
1292
1293\setvalue{\??framedheightalternative\empty}%
1294  {\setfalse\c_framed_has_height
1295   \d_framed_height\zeropoint}
1296
1297\setvalue{\??framedheightalternative\v!fit}%
1298  {\setfalse\c_framed_has_height
1299   \d_framed_height\zeropoint}
1300
1301\setvalue{\??framedheightalternative\v!broad}%
1302  {\setfalse\c_framed_has_height
1303   \d_framed_height\zeropoint}
1304
1305\setvalue{\??framedheightalternative\v!max}%
1306  {\settrue\c_framed_has_height
1307   \d_framed_height\vsize}
1308
1309\setvalue{\??framedheightalternative\s!unknown}%
1310  {\settrue\c_framed_has_height
1311   \d_framed_height\localheight}
1312
1313\def\framed_height_alternative_unknown
1314  {\settrue\c_framed_has_height
1315   \d_framed_height\localheight}
1316
1317% struts (use let instead?)
1318
1319\setvalue{\??framedstrutalternative\v!no}%
1320  {\c_framed_has_strut\plusone}
1321
1322\setvalue{\??framedstrutalternative\v!global}%
1323  {\setstrut}
1324
1325\setvalue{\??framedstrutalternative\v!local}%
1326  {\setfontstrut}
1327
1328\setvalue{\??framedstrutalternative\v!yes}%
1329  {\setstrut}
1330
1331\setvalue{\??framedstrutalternative\s!unknown}%
1332  {\setstrut}
1333
1334\def\framed_strut_alternative_unknown
1335  {\setstrut}
1336
1337\setvalue{\??framedstrutalternative\v!none}% not even pseudo struts
1338  {\c_framed_has_strut\zerocount}
1339
1340% offsets
1341
1342\setvalue{\??framedoffsetalternative\v!none}%
1343  {\setfalse\c_framed_has_offset
1344   \c_framed_has_strut\plusone
1345   \setfalse\c_framed_is_overlaid
1346   \d_framed_local_offset\d_framed_linewidth}
1347
1348\setvalue{\??framedoffsetalternative\v!overlay}%
1349  {% \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first
1350   \setfalse\c_framed_has_offset
1351   \c_framed_has_strut\plusone
1352   \settrue\c_framed_is_overlaid
1353   \d_framed_local_offset\zeropoint}
1354
1355% \setvalue{\??framedoffsetalternative\v!strut}%
1356%   {\setfalse\c_framed_has_offset
1357%    \c_framed_has_strut\plustwo
1358%    \settrue\c_framed_is_overlaid
1359%    \d_framed_local_offset\zeropoint}
1360
1361\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000
1362  {\settrue \c_framed_has_offset
1363   \c_framed_has_strut\plustwo
1364   \setfalse\c_framed_is_overlaid
1365   \let\localoffset\defaultframeoffset
1366   \letframedparameter\c!offset\defaultframeoffset % brrr
1367   \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
1368
1369\def\framed_offset_alternative_unknown
1370  {\settrue \c_framed_has_offset
1371   \c_framed_has_strut\plustwo
1372   \setfalse\c_framed_is_overlaid
1373   \let\defaultframeoffset\localoffset
1374   \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
1375
1376\letvalue{\??framedoffsetalternative\s!unknown}\framed_offset_alternative_unknown
1377
1378% so far for alternatives
1379
1380\let\pack_framed_stop_orientation\relax
1381
1382\def\pack_framed_restart
1383  {\aftergroup\pack_framed_finish}
1384
1385\def\pack_framed_do_top
1386  {\raggedtopcommand
1387   \framedparameter\c!top
1388   \edef\p_blank{\framedparameter\c!blank}%
1389   \ifx\p_blank\v!yes\else % auto or no
1390     \doinhibitblank
1391   \fi}
1392
1393\def\pack_framed_do_bottom
1394  {\framedparameter\c!bottom
1395   \raggedbottomcommand}
1396
1397%D Careful analysis of this macro will learn us that not all branches in the last
1398%D conditionals can be encountered, that is, some assignments to \type{\next} will
1399%D never occur. Nevertheless we implement the whole scheme, if not for future
1400%D extensions.
1401
1402%D \macros
1403%D   {doassigncheckedframeoffset}
1404%D
1405%D Offset helper (see menus):
1406
1407\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname
1408  {\edef\checkedframeoffset{#2}%
1409   #1%
1410     \ifx\checkedframeoffset\empty    \zeropoint\else
1411     \ifx\checkedframeoffset\v!overlay\zeropoint\else
1412     \ifx\checkedframeoffset\v!none   \zeropoint\else
1413     \ifx\checkedframeoffset\v!frame  \zeropoint\else
1414     \ifx\checkedframeoffset\v!default\zeropoint\else
1415       #2%
1416     \fi\fi\fi\fi\fi
1417   \relax}
1418
1419%D \macros
1420%D   {ifreshapeframebox}
1421%D
1422%D The last few lines tell what to do after the content of the box is collected and
1423%D passed to the next macro. In the case of a fixed width and centered alignment,
1424%D the content is evaluated and used to determine the most natural width. The rest
1425%D of the code deals with backgrounds and frames.
1426
1427\newif\ifreshapeframebox \reshapeframeboxtrue
1428
1429%D Beware: setting \type {top} and \type {bottom} to nothing, may
1430%D result in a frame that is larger that the given height! try:
1431%D
1432%D \starttyping
1433%D \framed
1434%D   [height=3cm,top=,bottom=,offset=overlay]
1435%D   {\strut test \shapefill \strut test}
1436%D \stoptyping
1437%D
1438%D This is intended behaviour and not a bug! One can always set
1439%D
1440%D \starttyping
1441%D ...,bottom=\kern0pt,...
1442%D \stoptyping
1443
1444% experiment ... \p_framed_franalyze -> we could support 'first' as location key
1445% option but then we will always do an analysis and reimplement the location
1446% options (btw, beware of location settings of derived functionality that bleed
1447% into this
1448
1449\def\pack_framed_finish_a
1450  {\ifreshapeframebox
1451     \pack_framed_reshape_process
1452   \else\ifx\p_framed_franalyze\v!yes
1453     \pack_framed_reshape_analyze
1454   \else
1455     \pack_framed_reshape_reset
1456   \fi\fi
1457   \setfalse\c_framed_has_width}
1458
1459\def\pack_framed_finish_b
1460  {\ifx\p_framed_franalyze\v!yes
1461     \pack_framed_reshape_analyze
1462   \else
1463     \pack_framed_reshape_reset
1464   \fi
1465   \setfalse\c_framed_has_width}
1466
1467\def\pack_framed_finish_c
1468  {\ifx\p_framed_franalyze\v!yes
1469     \pack_framed_reshape_analyze
1470   \else
1471     \pack_framed_reshape_reset
1472   \fi}
1473
1474\def\pack_framed_profile_box
1475  {\profilegivenbox\p_profile\b_framed_normal
1476   \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}}
1477
1478\unexpanded\def\pack_framed_finish
1479  {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down
1480   \pack_framed_locator_before\p_framed_location
1481   \ifconditional\c_framed_has_format
1482    %\ifconditional\c_framed_has_height \else
1483    %  \edef\p_profile{\framedparameter\c!profile}%
1484    %  \ifx\p_profile\empty\else
1485    %    \pack_framed_profile_box
1486    %  \fi
1487    %\fi
1488     \ifx\p_framed_autowidth\v!force
1489       \pack_framed_finish_a
1490     \else\ifx\localwidth\v!fit
1491       \ifx\p_framed_autowidth\v!yes
1492         \pack_framed_finish_a
1493       \else
1494         \pack_framed_finish_b
1495       \fi
1496     \else\ifx\localwidth\v!fixed
1497       \pack_framed_finish_b
1498     \else
1499       \pack_framed_finish_c
1500     \fi\fi\fi
1501     \ifconditional\c_framed_has_height \else
1502       \edef\p_profile{\framedparameter\c!profile}%
1503       \ifx\p_profile\empty\else
1504         \pack_framed_profile_box
1505       \fi
1506     \fi
1507     \ifconditional\page_postprocessors_needed_box
1508       % quite late
1509       \page_postprocessors_linenumbers_box\b_framed_normal
1510     \fi
1511   \else
1512     \pack_framed_finish_c
1513   \fi
1514   \ifconditional\c_framed_has_width
1515     \wd\b_framed_normal\d_framed_width
1516   \fi
1517   \ifconditional\c_framed_has_height
1518     \ht\b_framed_normal\d_framed_height
1519   \else
1520     \edef\p_framed_minheight{\framedparameter\c!minheight}%
1521     \ifx\p_framed_minheight\empty \else
1522       \ifdim\ht\b_framed_normal<\p_framed_minheight
1523         \ht\b_framed_normal\p_framed_minheight
1524       \fi
1525     \fi
1526   \fi
1527   \edef\p_framed_empty{\framedparameter\c!empty}%
1528   \ifx\p_framed_empty\v!yes
1529     \pack_framed_fake_box
1530   \fi
1531   \pack_framed_stop_orientation % moved here at 2014-05-25
1532   \iftrialtypesetting \else
1533     \edef\m_overlay_region{\framedparameter\c!region}%
1534     \ifx\m_overlay_region\empty\else
1535       \pack_framed_set_region
1536     \fi
1537   \fi
1538   \d_framed_applied_offset
1539     \ifconditional\c_framed_is_overlaid
1540       \zeropoint
1541     \else
1542       \d_framed_linewidth
1543     \fi
1544   \ifconditional\c_framed_has_offset
1545     \advance\d_framed_applied_offset\localoffset\relax
1546   \fi
1547   \ifconditional\c_framed_has_extra_offset
1548     \pack_framed_apply_extra_offsets % includes \d_framed_applied_offset
1549   \else
1550     \ifzeropt\d_framed_applied_offset
1551     \else
1552       \pack_framed_widen_box
1553     \fi
1554   \fi
1555   %
1556   \ifx\postprocessframebox\relax \else
1557     \let\next\postprocessframebox
1558     \let\postprocessframebox\relax % prevent nesting
1559     \next\b_framed_normal
1560   \fi
1561   \iftrialtypesetting
1562     % new
1563   \else
1564     \ifconditional\c_framed_has_frame % real or invisible frame
1565       \pack_framed_add_outline
1566     \fi
1567     \ifx\p_framed_background\empty \else
1568       \edef\p_framed_component{\framedparameter\c!component}%
1569       \pack_framed_add_background
1570     \fi
1571   \fi
1572   \pack_framed_locator_after\p_framed_location
1573   \iftrialtypesetting \else
1574     \ifx\m_overlay_region\empty\else
1575       \pack_framed_add_region
1576     \fi
1577   \fi
1578   \box\b_framed_normal
1579   \global\frameddimensionstate % global so to be used directly afterwards !
1580     \ifconditional\c_framed_has_width
1581       \ifconditional\c_framed_has_height \plusthree \else \plusone   \fi
1582     \else
1583       \ifconditional\c_framed_has_height \plustwo   \else \zerocount \fi
1584     \fi
1585   \egroup
1586   \egroup}
1587
1588\installcorenamespace{framedlocatorbefore}
1589\installcorenamespace{framedlocatorafter}
1590
1591\newconstant\frameddimensionstate % global state: 0=unknown 1=width 2=height 3=both
1592
1593\def\pack_framed_fake_box
1594  {\setbox\scratchbox\emptyhbox
1595   \wd\scratchbox\wd\b_framed_normal
1596   \ht\scratchbox\ht\b_framed_normal
1597   \dp\scratchbox\dp\b_framed_normal
1598   \setbox\b_framed_normal\box\scratchbox}
1599
1600\def\installframedlocator#1#2#3%
1601  {\setvalue{\??framedlocatorbefore#1}{#2}%
1602   \setvalue{\??framedlocatorafter #1}{#3}}
1603
1604\def\pack_framed_locator_before#1{\begincsname\??framedlocatorbefore#1\endcsname}
1605\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname}
1606
1607\newdimen\d_framed_locator_ht
1608\newdimen\d_framed_locator_dp
1609\newdimen\d_framed_locator_lo
1610\newdimen\d_framed_locator_ro
1611
1612\def\pack_framed_locator_set#1%
1613  {\d_framed_locator_ht\dimexpr
1614     #1+\d_framed_linewidth
1615     \ifconditional\c_framed_has_offset
1616       +\framedparameter\c!offset
1617     \fi
1618     +\framedparameter\c!toffset
1619   \relax
1620   \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax}
1621
1622\def\pack_framed_locator_set_lo
1623  {\global\d_framed_locator_lo\dimexpr
1624     \d_framed_linewidth
1625     \ifconditional\c_framed_has_offset
1626       +\framedparameter\c!offset
1627     \fi
1628     +\framedparameter\c!loffset
1629   \relax}
1630
1631\def\pack_framed_locator_set_ro
1632  {\global\d_framed_locator_ro\dimexpr
1633     \d_framed_linewidth
1634     \ifconditional\c_framed_has_offset
1635       +\framedparameter\c!offset
1636     \fi
1637     +\framedparameter\c!roffset
1638   \relax}
1639
1640% \ruledhbox
1641%   {A
1642%    \framed[width=2cm,align=middle,location=hanging]{location\\equals\\hanging}
1643%    \framed[width=2cm,align=middle,location=depth]  {location\\equals\\depth}
1644%    \framed[width=2cm,align=middle,location=height] {location\\equals\\height}
1645%    B}
1646% \vskip2cm
1647% \ruledhbox
1648%   {A
1649%    \framed[width=2cm,align=middle,location=low]    {location\\equals\\low}
1650%    \framed[width=2cm,align=middle,location=line]   {location\\equals\\line}
1651%    \framed[width=2cm,align=middle,location=high]   {location\\equals\\high}
1652%    B}
1653% \vskip2cm
1654% \ruledhbox
1655%  {A
1656%   \framed[width=2cm,align=middle,location=top]    {location\\equals\\top}
1657%   \framed[width=2cm,align=middle,location=bottom] {location\\equals\\bottom}
1658%   \framed[width=2cm,align=middle,location=lohi]   {location\\equals\\lohi}
1659%   \framed[width=2cm,align=middle,location=middle] {location\\equals\\middle}
1660%   B}
1661
1662% \installframedlocator \v!hanging % best with strut=no
1663%   {}
1664%   {\dp\b_framed_normal\ht\b_framed_normal
1665%    \ht\b_framed_normal\zeropoint}
1666%
1667% \installframedlocator \v!depth
1668%   {}
1669%   {\ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
1670%    \dp\b_framed_normal\strutdp
1671%    \box\b_framed_normal}
1672%
1673% \installframedlocator \v!height
1674%   {}
1675%   {\dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
1676%    \ht\b_framed_normal\strutht
1677%    \box\b_framed_normal}
1678
1679\installframedlocator \v!hanging % best with strut=no *1* / see mail to list by SB
1680  {}
1681  {\scratchdimen\ht\b_framed_normal
1682   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
1683   \dp\b_framed_normal\scratchdimen
1684   \ht\b_framed_normal\zeropoint
1685   \box\b_framed_normal}
1686
1687\installframedlocator \v!depth % *1*
1688  {}
1689  {\setbox\b_framed_normal\hpack{\lower\strutdp\box\b_framed_normal}%
1690   \ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
1691   \dp\b_framed_normal\strutdp
1692   \box\b_framed_normal}
1693
1694\installframedlocator \v!height % *1*
1695  {}
1696  {\scratchdimen\dimexpr \ht\b_framed_normal - \strutht \relax
1697   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
1698   \dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
1699   \ht\b_framed_normal\strutht
1700   \box\b_framed_normal}
1701
1702\installframedlocator \v!high
1703  {}
1704  {\pack_framed_locator_set\strutht
1705   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
1706   \ht\b_framed_normal\strutht
1707   \dp\b_framed_normal\strutdp
1708   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1709
1710\installframedlocator \v!line
1711  {}
1712  {\setbox\b_framed_normal\hpack{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
1713   \ht\b_framed_normal.5\lineheight
1714   \dp\b_framed_normal.5\lineheight
1715   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1716
1717\installframedlocator \v!low
1718  {}
1719  {\pack_framed_locator_set\strutdp
1720   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
1721   \ht\b_framed_normal\strutht
1722   \dp\b_framed_normal\strutdp
1723   \box\b_framed_normal}
1724
1725\installframedlocator \v!top
1726  {}
1727  {\pack_framed_locator_set\strutht
1728   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
1729   \ht\b_framed_normal\d_framed_locator_ht
1730   \dp\b_framed_normal\d_framed_locator_dp
1731   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1732
1733\installframedlocator \v!middle
1734  {}
1735  {\scratchdimen.5\ht\b_framed_normal
1736   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
1737   \ht\b_framed_normal\scratchdimen
1738   \dp\b_framed_normal\scratchdimen
1739   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1740
1741\installframedlocator \v!lohi % maybe also \v!center
1742  {\pack_framed_locator_before\v!middle}
1743  {\pack_framed_locator_after \v!middle}
1744
1745\installframedlocator \v!bottom
1746  {}
1747  {\pack_framed_locator_set\strutdp
1748   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
1749   \ht\b_framed_normal\d_framed_locator_dp
1750   \dp\b_framed_normal\d_framed_locator_ht
1751   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1752
1753\installframedlocator \v!keep % retains height/depth
1754  {\pack_framed_remove_depth}
1755  {\pack_framed_restore_depth}
1756
1757\newdimen\d_framed_formula
1758
1759\installframedlocator \v!formula % private, will become a more generic name
1760  {}
1761  {\pack_framed_locator_set\d_framed_formula
1762   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
1763   \ht\b_framed_normal\d_framed_locator_ht
1764   \dp\b_framed_normal\d_framed_locator_dp
1765   \hpack{\box\b_framed_normal}} %  why do we pack .. dange of loosing?
1766
1767% also used in fastlocalframed
1768
1769\newdimen\d_framed_original_wd
1770\newdimen\d_framed_original_ht
1771\newdimen\d_framed_original_dp
1772
1773\def\pack_framed_remove_depth
1774  {\d_framed_original_wd\wd\b_framed_normal
1775   \d_framed_original_ht\ht\b_framed_normal
1776   \d_framed_original_dp\dp\b_framed_normal
1777   \ifzeropt\d_framed_original_dp\else
1778     \setbox\b_framed_normal\hpack{\raise\d_framed_original_dp\box\b_framed_normal}%
1779   \fi
1780   \wd\b_framed_normal\d_framed_original_wd
1781   \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax
1782   \dp\b_framed_normal\zeropoint}
1783
1784\def\pack_framed_restore_depth
1785  {\ifzeropt\d_framed_original_dp \else
1786     \setbox\b_framed_normal\hpack{\lower\d_framed_original_dp\box\b_framed_normal}%
1787   \fi
1788   \wd\b_framed_normal\d_framed_original_wd
1789   \ht\b_framed_normal\d_framed_original_ht
1790   \dp\b_framed_normal\d_framed_original_dp}
1791
1792% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax}
1793% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax}
1794% \framed[width=12cm,height=3cm,orientation=180]{\input ward\relax}
1795% \framed[width=12cm,height=3cm,orientation=270]{\input ward\relax}
1796% \framed[width=12cm,height=3cm,orientation=-90]{\input ward\relax}
1797% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax}
1798% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax}
1799
1800\def\pack_framed_start_orientation
1801  {\ifcase\p_framed_orientation
1802     \let\pack_framed_stop_orientation\relax
1803   \else
1804     \let\pack_framed_stop_orientation\pack_framed_stop_orientation_indeed
1805   \fi}
1806
1807\def\pack_framed_stop_orientation_indeed
1808  {\setbox\b_framed_normal\hpack{\dorotatebox\p_framed_orientation\hpack{\box\b_framed_normal}}%
1809   \d_framed_height\ht\b_framed_normal
1810   \d_framed_width \wd\b_framed_normal}
1811
1812%D The last conditional takes care of the special situation of in||line \inframed
1813%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the
1814%D running text.
1815
1816\unexpanded\def\inframed
1817  {\dosingleempty\pack_framed_inline}
1818
1819% \def\pack_framed_inline[#1]%
1820%   {\framed[\c!location=\v!low,#1]}
1821%
1822% or:
1823
1824\def\pack_framed_inline[%
1825  {\framed[\c!location=\v!low,}
1826
1827%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background,
1828%D but no content, so actually we have a sort of phantom framed box.
1829
1830%D \macros
1831%D   {mframed, minframed}
1832%D
1833%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the
1834%D next macro:
1835%D
1836%D \starttyping
1837%D \def\mframed#1%
1838%D   {\relax
1839%D    \ifmmode
1840%D      \vcenter{\hbox{\framed{$\ifinner\else\displaystyle\fi#1$}}}%
1841%D    \else
1842%D      \framed{$#1$}%
1843%D    \fi}
1844%D \stoptyping
1845%D
1846%D Because \type {\ifinner} does not (always) reports what one would expect, we move the
1847%D test to the outer level. We also want to pass arguments,
1848%D
1849%D \starttyping
1850%D \def\mframed%
1851%D   {\dosingleempty\domframed}
1852%D
1853%D \def\domframed[#1]#2% % tzt \dowithnextmathbox ?
1854%D   {\relax
1855%D    \ifmmode
1856%D      \ifinner
1857%D        \inframed[#1]{$#2$}%
1858%D      \else
1859%D        \vcenter{\hbox{\framed[#1]{$\displaystyle#2$}}}%
1860%D      \fi
1861%D    \else
1862%D      \inframed[#1]{$#2$}%
1863%D    \fi}
1864%D \stoptyping
1865%D
1866%D Still better is the next alternative, if only because it takes care of setting the super-
1867%D and subscripts styles
1868
1869\newcount\c_framed_mstyle
1870
1871\unexpanded\def\pack_framed_math_strut
1872  {\Ustartmath
1873   \triggermathstyle\c_framed_mstyle
1874   \vphantom{(}%
1875   \Ustopmath}
1876
1877\installcorenamespace{mathframed}
1878
1879\installframedcommandhandler \??mathframed {mathframed} \??mathframed
1880
1881\appendtoks
1882    \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}%
1883\to \everydefinemathframed
1884
1885\unexpanded\def\pack_framed_mathframed#1%
1886  {\begingroup
1887   \edef\currentmathframed{#1}%
1888   \dosingleempty\pack_framed_mathframed_indeed}
1889
1890\newcount\c_pack_framed_mathframed
1891\newtoks \t_pack_framed_mathframed
1892
1893\def\pack_framed_math_pos
1894  {\global\advance\c_pack_framed_mathframed\plusone
1895   \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}%
1896   \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mathframed}%
1897   \xypos\pack_framed_mc_two}
1898
1899\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
1900  {\iffirstargument
1901      \setupcurrentmathframed[#1]%
1902   \fi
1903   \c_framed_mstyle\normalmathstyle
1904   \edef\m_framed_location{\mathframedparameter\c!location}%
1905   \ifx\m_framed_location\v!mathematics
1906     \let\normalstrut\pack_framed_math_pos
1907   \else\ifx\m_framed_location\v!low\else
1908     \let\normalstrut\pack_framed_math_strut
1909   \fi\fi
1910   \inheritedmathframedframed\bgroup
1911     \Ustartmath
1912     \triggermathstyle\c_framed_mstyle
1913     \the\t_pack_framed_mathframed
1914     #2%
1915     \Ustopmath
1916   \egroup
1917   \endgroup}
1918
1919\appendtoks
1920    \mathraggedstatus\plustwo   % makes \startalign work
1921    \eqalignmode     \zerocount % makes \startalign fit
1922\to \t_pack_framed_mathframed
1923
1924\installframedlocator \v!mathematics
1925  {}
1926  {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax
1927   \hpack{\xypos\pack_framed_mc_one\box\b_framed_normal}}
1928
1929\definemathframed[mframed]
1930\definemathframed[inmframed][\c!location=\v!low]
1931\definemathframed[mcframed] [\c!location=\v!mathematics]
1932
1933%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}:
1934%D
1935%D \startbuffer
1936%D \startformula
1937%D   x \times   \mframed{y} \times y^{z_z}
1938%D   x \times \inmframed{y} \times y^{z_z}
1939%D \stopformula
1940%D \stopbuffer
1941%D
1942%D \typebuffer \getbuffer
1943%D
1944%D And:
1945%D
1946%D \startbuffer
1947%D \startformula
1948%D   x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}}
1949%D \stopformula
1950%D \stopbuffer
1951%D
1952%D \typebuffer \getbuffer
1953%D
1954%D As usual, one can specify in what way the text should be framed. One should be
1955%D aware of the fact that, inorder to preserve the proper spacing, the \type
1956%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead.
1957%D
1958%D \startbuffer
1959%D \startformula
1960%D   x \times y^{\mframed[framecolor=red]{z}_{z}}
1961%D \stopformula
1962%D \stopbuffer
1963%D
1964%D \typebuffer \getbuffer
1965%D
1966%D For inline use, we also provide the \type {\inmframed} alternative: we want $x
1967%D \times \inmframed{y}$ in inline math, right?
1968
1969%D This previous framing macros needs a lot of alternatives for putting rules around
1970%D boxes, inserting offsets and aligning text. Each step is handled by separate macros.
1971
1972\newdimen\d_framed_applied_offset
1973\newdimen\d_framed_loffset
1974\newdimen\d_framed_roffset
1975\newdimen\d_framed_toffset
1976\newdimen\d_framed_boffset
1977
1978\def\pack_framed_check_extra_offsets % we could check h and v indepently
1979  {\setfalse\c_framed_has_extra_offset
1980   \d_framed_loffset\framedparameter\c!loffset\relax
1981   \d_framed_roffset\framedparameter\c!roffset\relax
1982   \d_framed_toffset\framedparameter\c!toffset\relax
1983   \d_framed_boffset\framedparameter\c!boffset\relax
1984   \ifzeropt\d_framed_loffset\else \advance\d_framed_width -\d_framed_loffset \settrue\c_framed_has_extra_offset \fi
1985   \ifzeropt\d_framed_roffset\else \advance\d_framed_width -\d_framed_roffset \settrue\c_framed_has_extra_offset \fi
1986   \ifzeropt\d_framed_toffset\else \advance\d_framed_height-\d_framed_toffset \settrue\c_framed_has_extra_offset \fi
1987   \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi}
1988
1989\def\pack_framed_apply_extra_offsets
1990  {\setbox\b_framed_normal\vpack\bgroup
1991     \advance\d_framed_toffset\d_framed_applied_offset
1992     \advance\d_framed_boffset\d_framed_applied_offset
1993     \advance\d_framed_loffset\d_framed_applied_offset
1994     \advance\d_framed_roffset\d_framed_applied_offset
1995     \kern\d_framed_toffset
1996     \hpack\bgroup
1997        \kern\d_framed_loffset
1998        \box\b_framed_normal
1999        \kern\d_framed_roffset
2000     \egroup
2001     \kern\d_framed_boffset
2002   \egroup}
2003
2004\def\pack_framed_widen_box
2005  {\setbox\b_framed_normal\vpack
2006     {\kern\d_framed_applied_offset
2007      \hpack{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
2008      \kern\d_framed_applied_offset}}
2009
2010%D Let's hope that the next few examples show us enough of what needs to be
2011%D done by the auxiliary macros.
2012%D
2013%D \startbuffer
2014%D \framed[height=1cm,offset=.5cm]   {rule based learning}
2015%D \framed[height=1cm,offset=0cm]    {rule based learning}
2016%D \framed[height=1cm,offset=none]   {rule based learning}
2017%D \framed[height=1cm,offset=overlay]{rule based learning}
2018%D \stopbuffer
2019%D
2020%D \typebuffer
2021%D
2022%D \startlinecorrection
2023%D \hbox{\getbuffer}
2024%D \stoplinecorrection
2025%D
2026%D \startbuffer
2027%D \framed[offset=.5cm]   {rule based learning}
2028%D \framed[offset=0cm]    {rule based learning}
2029%D \framed[offset=none]   {rule based learning}
2030%D \framed[offset=overlay]{rule based learning}
2031%D \stopbuffer
2032%D
2033%D \typebuffer
2034%D
2035%D \startlinecorrection
2036%D \hbox{\getbuffer}
2037%D \stoplinecorrection
2038%D
2039%D \startbuffer
2040%D \framed[strut=no,offset=.5cm]   {rule based learning}
2041%D \framed[strut=no,offset=0cm]    {rule based learning}
2042%D \framed[strut=no,offset=none]   {rule based learning}
2043%D \framed[strut=no,offset=overlay]{rule based learning}
2044%D \stopbuffer
2045%D
2046%D \typebuffer
2047%D
2048%D \startlinecorrection
2049%D \hbox{\getbuffer}
2050%D \stoplinecorrection
2051%D
2052%D \startbuffer
2053%D \framed[width=3cm,align=left]   {rule\\based\\learning}
2054%D \framed[width=3cm,align=middle] {rule\\based\\learning}
2055%D \framed[width=3cm,align=right]  {rule\\based\\learning}
2056%D \framed[width=fit,align=middle] {rule\\based\\learning}
2057%D \stopbuffer
2058%D
2059%D \typebuffer
2060%D
2061%D \startlinecorrection
2062%D \hbox{\dontcomplain\getbuffer}
2063%D \stoplinecorrection
2064%D
2065%D So now we're ready for the complicated stuff. We distinguish between borders with
2066%D straight lines and those with round corners. When using the first alternative it
2067%D is possible to turn off one or more lines. More fancy shapes are also possible by
2068%D specifying dedicated backgrounds. Turning lines on and off is implemented as
2069%D efficient as possible and as a result is interface language dependant. This next
2070%D implementation evolved from simpler ones. It puts for instance the rules on top
2071%D of the content and provides additional offset capabilities. The lot of calls to
2072%D other macros makes this mechanism not that easy to comprehend.
2073%D
2074%D We handle left, right or middle alignment as well as fixed or free widths and
2075%D heights. Each combination gets its own macro.
2076%D
2077%D The following code handles one-liners: \type {align={line,flushright}}. Beware,
2078%D since we entered a group and either or not grab the next bgroup token, we need to
2079%D finish the group in the oneliner mode.
2080
2081\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
2082
2083\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
2084  {\ifconditional\raggedonelinerstate
2085     \expandafter\dodoformatonelinerbox
2086   \else
2087     \expandafter\nodoformatonelinerbox
2088   \fi}
2089
2090\def\dodoformatonelinerbox
2091  {\afterassignment\redoformatonelinerbox
2092   \setbox\nextbox\hbox} % maybe \hpack
2093
2094\def\redoformatonelinerbox
2095  {\aftergroup\dododoformatonelinerbox
2096   \ignorespaces}
2097
2098\def\dododoformatonelinerbox
2099  {\hpack to \hsize % was \hbox
2100     {\ifcase\raggedstatus\or\hss\or\hss       \fi
2101      \unhbox\nextbox \removeunwantedspaces
2102      \ifcase\raggedstatus\or    \or\hss\or\hss\fi}%
2103   \egroup}
2104
2105\def\nodoformatonelinerbox % grabs {
2106  {\let\next=}
2107
2108%D The handlers:
2109
2110% Beware, we have a \noindent so an empty line is indeed an empty line and
2111% the \synchronizeinlinedirection triggers a vbox instead of a line.
2112%
2113% \startTEXpage[offset=0.5ex,align={lohi,middle}]
2114%
2115%     \vbox{\hbox{x}}
2116% \stopTEXpage
2117%
2118% \startTEXpage[offset=0.5ex,align={lohi,middle}]
2119%     \vbox{\hbox{x}}
2120% \stopTEXpage
2121
2122% \def\pack_framed_forgetall{\forgetall}
2123
2124\def\pack_framed_set_foregroundcolor
2125  {\edef\p_framed_foregroundcolor{\framedparameter\c!foregroundcolor}%
2126   \ifx\p_framed_foregroundcolor\empty\else\dousecolorparameter\p_framed_foregroundcolor\fi}
2127
2128\def\pack_framed_do_setups
2129  {\ifx\p_framed_setups\empty \else
2130     \setups[\p_framed_setups]% \texsetup (or only one!)
2131   % \fastsetup\p_framed_setup % singular would have been better
2132   \fi}
2133
2134\def\pack_framed_format_format_yes
2135  {\vbox to \d_framed_height
2136     \bgroup
2137       \let\postprocessframebox\relax
2138     % \pack_framed_forgetall
2139       \iftrialtypesetting \else
2140         \pack_framed_set_foregroundcolor
2141       \fi
2142       \oninterlineskip
2143       \hsize\d_framed_width
2144       \vsize\d_framed_height
2145       \pack_framed_do_setups
2146       \raggedcommand
2147       \pack_framed_do_top
2148       \bgroup
2149       \synchronizeinlinedirection
2150       \localbegstrut
2151       \aftergroup\localendstrut
2152       \aftergroup\pack_framed_do_bottom
2153       \aftergroup\egroup
2154       \doformatonelinerbox}
2155
2156\def\pack_framed_format_format_nop
2157  {\vbox to \d_framed_height
2158     \bgroup
2159       \let\postprocessframebox\relax
2160     % \pack_framed_forgetall
2161       \iftrialtypesetting \else
2162         \pack_framed_set_foregroundcolor
2163       \fi
2164       \oninterlineskip
2165       \hsize\d_framed_width
2166       \vsize\d_framed_height
2167       \pack_framed_do_setups
2168       \raggedcenter
2169       \vss
2170       \bgroup
2171       \synchronizeinlinedirection
2172       \localbegstrut
2173       \aftergroup\localendstrut
2174       \aftergroup\vss
2175       \aftergroup\egroup
2176       \doformatonelinerbox}
2177
2178\def\pack_framed_format_format_height
2179  {\vbox to \d_framed_height
2180     \bgroup
2181       \let\postprocessframebox\relax
2182     % \pack_framed_forgetall
2183       \iftrialtypesetting \else
2184         \pack_framed_set_foregroundcolor
2185       \fi
2186       \oninterlineskip
2187       \pack_framed_do_setups
2188       \raggedcommand
2189       \vss
2190       \bgroup
2191       \aftergroup\localendstrut
2192       \aftergroup\vss
2193       \aftergroup\egroup
2194       \synchronizeinlinedirection
2195       \localbegstrut
2196       \doformatonelinerbox}
2197
2198\def\pack_framed_format_format_width
2199  {\vbox
2200     \bgroup
2201       \let\postprocessframebox\relax
2202     % \pack_framed_forgetall
2203       \iftrialtypesetting \else
2204         \pack_framed_set_foregroundcolor
2205       \fi
2206       \oninterlineskip
2207       \hsize\d_framed_width
2208       \pack_framed_do_setups
2209       \raggedcommand
2210       \pack_framed_do_top
2211       \bgroup
2212       \synchronizeinlinedirection
2213       \localbegstrut
2214       \aftergroup\localendstrut
2215       \aftergroup\pack_framed_do_bottom
2216       \aftergroup\egroup
2217       \doformatonelinerbox}
2218
2219\def\pack_framed_format_format_vsize
2220  {\vbox to \d_framed_height % no vpack .. maybe grid
2221     \bgroup
2222       \let\postprocessframebox\relax
2223     % \pack_framed_forgetall
2224       \iftrialtypesetting \else
2225         \pack_framed_set_foregroundcolor
2226       \fi
2227       \vsize\d_framed_height
2228       \pack_framed_do_setups
2229       \vss
2230       \bgroup
2231       \aftergroup\vss
2232       \aftergroup\egroup
2233       \hbox
2234         \bgroup
2235         \aftergroup\egroup
2236         \synchronizeinlinedirection
2237         \localstrut
2238         \doformatonelinerbox}
2239
2240\def\pack_framed_format_format_hsize
2241  {\hbox to \d_framed_width
2242     \bgroup
2243       \let\postprocessframebox\relax
2244     % \pack_framed_forgetall
2245       \iftrialtypesetting \else
2246         \pack_framed_set_foregroundcolor
2247       \fi
2248       \pack_framed_do_setups
2249       \hss
2250       \synchronizeinlinedirection
2251       \localstrut
2252       \bgroup
2253       \aftergroup\hss
2254       \aftergroup\egroup
2255       \doformatonelinerbox}
2256
2257\def\pack_framed_format_format_no_size
2258  {\hbox
2259     \bgroup
2260       \iftrialtypesetting \else
2261         \pack_framed_set_foregroundcolor
2262       \fi
2263       \let\postprocessframebox\relax
2264       \pack_framed_do_setups
2265       \synchronizeinlinedirection
2266       \localstrut
2267       \doformatonelinerbox}
2268
2269%D On the next page we show some examples of how these macros come into action. The
2270%D examples show us how \type {fit}, \type {broad} dimensions influence the
2271%D formatting. Watch the visualized struts. \footnote {Here we used \type
2272%D {\showstruts}.}
2273%D
2274%D \startpostponing
2275%D \bgroup
2276%D \showstruts
2277%D \dontcomplain
2278%D \starttabulate[|c|c|c|c|c|c|]
2279%D % \HL
2280%D \NC \framed[width=.2\hsize, height=.2\hsize, align=]       {a\endgraf b\endgraf c}
2281%D \NC \framed[width=.2\hsize, height=broad,    align=]       {a\endgraf b\endgraf c}
2282%D \NC \framed[width=.2\hsize, height=fit,      align=]       {a\endgraf b\endgraf c}
2283%D \NC \framed[width=fit,      height=.2\hsize, align=]       {a\endgraf b\endgraf c}
2284%D \NC \framed[width=fit,      height=broad,    align=]       {a\endgraf b\endgraf c}
2285%D \NC \framed[width=fit,      height=fit,      align=]       {a\endgraf b\endgraf c}
2286%D \NC \NR
2287%D % \HL
2288%D \NC \framed[width=.2\hsize, height=.2\hsize, align=yes]    {a\endgraf b\endgraf c}
2289%D \NC \framed[width=.2\hsize, height=broad,    align=yes]    {a\endgraf b\endgraf c}
2290%D \NC \framed[width=.2\hsize, height=fit,      align=yes]    {a\endgraf b\endgraf c}
2291%D \NC \framed[width=fit,      height=.2\hsize, align=yes]    {a\endgraf b\endgraf c}
2292%D \NC \framed[width=fit,      height=broad,    align=yes]    {a\endgraf b\endgraf c}
2293%D \NC \framed[width=fit,      height=fit,      align=yes]    {a\endgraf b\endgraf c}
2294%D \NC \NR
2295%D % \HL
2296%D \NC \framed[width=.2\hsize, height=.2\hsize, align=right]  {a\endgraf b\endgraf c}
2297%D \NC \framed[width=.2\hsize, height=broad,    align=right]  {a\endgraf b\endgraf c}
2298%D \NC \framed[width=.2\hsize, height=fit,      align=right]  {a\endgraf b\endgraf c}
2299%D \NC \framed[width=fit,      height=.2\hsize, align=right]  {a\endgraf b\endgraf c}
2300%D \NC \framed[width=fit,      height=broad,    align=right]  {a\endgraf b\endgraf c}
2301%D \NC \framed[width=fit,      height=fit,      align=right]  {a\endgraf b\endgraf c}
2302%D \NC \NR
2303%D % \HL
2304%D \NC \framed[width=.2\hsize, height=.2\hsize, align=left]   {a\endgraf b\endgraf c}
2305%D \NC \framed[width=.2\hsize, height=broad,    align=left]   {a\endgraf b\endgraf c}
2306%D \NC \framed[width=.2\hsize, height=fit,      align=left]   {a\endgraf b\endgraf c}
2307%D \NC \framed[width=fit,      height=.2\hsize, align=left]   {a\endgraf b\endgraf c}
2308%D \NC \framed[width=fit,      height=broad,    align=left]   {a\endgraf b\endgraf c}
2309%D \NC \framed[width=fit,      height=fit,      align=left]   {a\endgraf b\endgraf c}
2310%D \NC \NR
2311%D % \HL
2312%D \NC \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
2313%D \NC \framed[width=.2\hsize, height=broad,    align=middle] {a\endgraf b\endgraf c}
2314%D \NC \framed[width=.2\hsize, height=fit,      align=middle] {a\endgraf b\endgraf c}
2315%D \NC \framed[width=fit,      height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
2316%D \NC \framed[width=fit,      height=broad,    align=middle] {a\endgraf b\endgraf c}
2317%D \NC \framed[width=fit,      height=fit,      align=middle] {a\endgraf b\endgraf c}
2318%D \NC \NR
2319%D % \HL
2320%D \stoptabulate
2321%D \egroup
2322%D \stoppostponing
2323
2324%D \macros
2325%D   {framednoflines, framedlastlength}
2326%D
2327%D It is possible to let the frame macro calculate the width of a centered box
2328%D automatically (\type {fit}). When doing so, we need to reshape the box:
2329
2330\newcount\framednoflines
2331\newdimen\framedfirstheight
2332\newdimen\framedlastdepth
2333\newdimen\framedminwidth
2334\newdimen\framedmaxwidth
2335\newdimen\framedaveragewidth
2336
2337\def\pack_framed_reshape_reset
2338  {\framednoflines    \zerocount
2339   \framedfirstheight \zeropoint
2340   \framedlastdepth   \zeropoint
2341   \framedminwidth    \zeropoint
2342   \framedmaxwidth    \zeropoint
2343   \framedaveragewidth\zeropoint}
2344
2345\def\pack_framed_reshape_process{\ifvbox\b_framed_normal\clf_doreshapeframedbox\b_framed_normal\relax\fi}
2346\def\pack_framed_reshape_analyze{\ifvbox\b_framed_normal\clf_doanalyzeframedbox\b_framed_normal\relax\fi}
2347
2348% torture test / strange case (much depth) / method 2 needed
2349%
2350% \startTEXpage[frame=on]
2351% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
2352% test outside formula
2353% \startformula \startalign \NC A \NC B \NR \intertext{test} \NC C \NC D \NR \stopalign \stopformula
2354% \blank[big]
2355% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
2356% test outside formula
2357% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
2358% \stopTEXpage
2359
2360%D The examples on the next page show how one can give the frame as well as the
2361%D background an additional offset and even a bit more depth. The blue outline is
2362%D the frame, the red box is the background and the small black outline is the
2363%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to
2364%D the result.
2365%D
2366%D \startpostponing
2367%D \bgroup
2368%D \unprotect
2369%D \dontcomplain
2370%D
2371%D \startbuffer
2372%D \unprotect
2373%D \vbox to \vsize
2374%D   \bgroup
2375%D     \startalignment[middle]
2376%D     \vss
2377%D     \dontleavehmode\vbox to .8\vsize
2378%D       \bgroup
2379%D         \hsize=300pt
2380%D         \setupframed
2381%D           [background=color,
2382%D            backgroundcolorachtergrondkleur=darkred,
2383%D            width=300pt,
2384%D            height=60pt,
2385%D            framecolorkaderkleur=DemoBlue,
2386%D            rulethickness=2pt]
2387%D         \def\status%
2388%D           {backgroundoffset=\the\dimexpr\framedparameter\c!backgroundoffset\relax\\
2389%D            frameoffset=\the\dimexpr\framedparameter\c!frameoffset\relax\\
2390%D            depth=\the\dimexpr\framedparameter\c!depth\relax}
2391%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=0pt]{\status}}
2392%D         \vss
2393%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=0pt]{\status}}
2394%D         \vss
2395%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=0pt,frameoffset=5pt]{\status}}
2396%D         \vss
2397%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=2pt,frameoffset=5pt]{\status}}
2398%D         \vss
2399%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=2pt]{\status}}
2400%D         \vss
2401%D         \dontleavehmode \ruledhbox{\framed[backgroundoffset=5pt,frameoffset=5pt]{\status}}
2402%D       \egroup
2403%D     \vss
2404%D     \stopalignment
2405%D     \egroup
2406%D \protect
2407%D \stopbuffer
2408%D
2409%D \getbuffer \page
2410%D
2411%D {\setupframed[depth=4pt]\getbuffer} \page
2412%D
2413%D \protect
2414%D \egroup
2415%D \stoppostponing
2416
2417%D We can draw lines from left to right and top to bottom by using the normal \type
2418%D {\hairline} command. Both directions need a different treatment.
2419%D
2420%D \startbuffer
2421%D \framed[width=4cm]           {alfa\hairline beta\hairline gamma}
2422%D \framed[height=2cm]            {alfa\hairline beta\hairline gamma}
2423%D \framed[width=4cm,height=2cm]{alfa\hairline beta\hairline gamma}
2424%D \stopbuffer
2425%D
2426%D \typebuffer
2427%D
2428%D \startlinecorrection
2429%D \hbox{\getbuffer}
2430%D \stoplinecorrection
2431%D
2432%D These macros try to adapt their behaviour as good as possible to the circumstances
2433%D and act as natural as possible.
2434
2435\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
2436  {\begingroup
2437   \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
2438   \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax
2439   \par
2440   \nointerlineskip
2441   \kern\scratchoffset
2442   \dontleavehmode
2443     \hrule\s!height\d_framed_linewidth\s!depth\zeropoint
2444   \par
2445   \kern-\d_framed_linewidth
2446   \dontleavehmode
2447     \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
2448     \hfill
2449     \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}%
2450   \par
2451   \nointerlineskip
2452   \kern\scratchoffset
2453   \nointerlineskip
2454   \endgraf
2455   \nointerlineskip
2456   \localbegstrut
2457   \endgroup}
2458
2459\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
2460  {\bgroup
2461   \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
2462   \ifconditional\c_framed_has_height
2463     \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax
2464     \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax
2465   \else
2466     \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax
2467     \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax
2468   \fi
2469   \unskip
2470   \setbox\scratchbox\hpack
2471     {\kern\scratchoffset
2472      \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth
2473      \kern\scratchoffset}%
2474   \ht\scratchbox\strutht
2475   \dp\scratchbox\strutdp
2476   \box\scratchbox
2477   \ignorespaces
2478   \egroup}
2479
2480%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In
2481%D horizontal boxes it expands to a space.
2482
2483\unexpanded\def\pack_framed_vboxed_newline
2484  {\endgraf\ignorespaces}
2485
2486\unexpanded\def\pack_framed_hboxed_newline
2487  {\unskip\normalspace\ignorespaces}
2488
2489%D We can set each rule on or off. The default setting is inherited from
2490%D \type {frame}. An earlier implementation use a bit different approach, but the new
2491%D one seems more natural:
2492%D
2493%D \bgroup
2494%D \setuptyping[margin=0pt]
2495%D \startlinecorrection
2496%D \startbuffer
2497%D \framed[offset=overlay,frame=on]{\darkred\blackrule}
2498%D \stopbuffer
2499%D \hbox{\getbuffer\vbox{\typebuffer}}
2500%D
2501%D \startbuffer
2502%D \framed[offset=overlay,frame=on,bottomframe=off]{\darkred\blackrule}
2503%D \stopbuffer
2504%D \hbox{\getbuffer\vbox{\typebuffer}}
2505%D
2506%D \startbuffer
2507%D \framed[offset=overlay,frame=on,bottomframe=on]{\darkred\blackrule}
2508%D \stopbuffer
2509%D \hbox{\getbuffer\vbox{\typebuffer}}
2510%D
2511%D \startbuffer
2512%D \framed[offset=overlay,frame=off]{\darkred\blackrule}
2513%D \stopbuffer
2514%D \hbox{\getbuffer\vbox{\typebuffer}}
2515%D
2516%D \startbuffer
2517%D \framed[offset=overlay,frame=off,bottomframe=off]{\darkred\blackrule}
2518%D \stopbuffer
2519%D \hbox{\getbuffer\vbox{\typebuffer}}
2520%D
2521%D \startbuffer
2522%D \framed[offset=overlay,frame=off,bottomframe=on]{\darkred\blackrule}
2523%D \stopbuffer
2524%D \hbox{\getbuffer\vbox{\typebuffer}}
2525%D \stoplinecorrection
2526%D \egroup
2527
2528%D \macros
2529%D   {startframedtext, setupframedtexts, defineframedtext}
2530%D
2531%D The general framing command we discussed previously, is not entirely suited for
2532%D what we call framed texts, as for instance used in intermezzo's. The next
2533%D examples show what we have in mind.
2534%D
2535%D \startbuffer[framed-0]
2536%D \setupframedtexts
2537%D   [frame=off,
2538%D    width=\hsize,
2539%D    background=screen]
2540%D
2541%D \startframedtext
2542%D By default the framed text is centered \dots
2543%D \stopframedtext
2544%D
2545%D \startframedtext[right]
2546%D \dots\ but we can also align left, middle and right.
2547%D \stopframedtext
2548%D \stopbuffer
2549%D
2550%D \startbuffer[framed-1]
2551%D \defineframedtext
2552%D   [Example]
2553%D   [width=6cm,
2554%D    height=5cm]
2555%D
2556%D \startExample
2557%D \typebuffer[framed-1]
2558%D \stopExample
2559%D \stopbuffer
2560%D
2561%D \startbuffer[framed-2]
2562%D \defineframedtext
2563%D   [Example]
2564%D   [width=6cm]
2565%D
2566%D \startExample
2567%D \typebuffer[framed-2]
2568%D \stopExample
2569%D \stopbuffer
2570%D
2571%D \startbuffer[framed-3]
2572%D \defineframedtext
2573%D   [Example]
2574%D   [height=5cm]
2575%D
2576%D \startExample
2577%D \typebuffer[framed-3]
2578%D \stopExample
2579%D \stopbuffer
2580%D
2581%D \startbuffer[framed-4]
2582%D \defineframedtext
2583%D   [Example]
2584%D   [width=fit,height=broad]
2585%D
2586%D \Example{a very exciting example}
2587%D \stopbuffer
2588%D
2589%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-0] \egroup
2590%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-1] \egroup
2591%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-2] \egroup
2592%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup
2593%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup
2594%D
2595%D Here we can see that we have a predefined framed text class as well as the
2596%D tools for defining our own. So we have:
2597%D
2598%D \showsetup{setupframedtexts}
2599%D
2600%D as well as the definition command:
2601%D
2602%D \showsetup{defineframedtext}
2603%D
2604%D that generates two commands:
2605%D
2606%D \showsetup{start<<framedtext>>}
2607%D \showsetup{<<framedtext>>}
2608%D
2609%D The next definition shows the defaults.
2610
2611\installcorenamespace{framedtext}
2612\installcorenamespace{framedtextlocation}
2613
2614\installframedcommandhandler \??framedtext {framedtext} \??framedtext
2615
2616\let\setupframedtexts\setupframedtext
2617
2618\setupframedtext
2619  [\c!width=.75\hsize,
2620   \c!height=\v!fit,
2621   \c!align=\v!yes,
2622  %\c!top=,
2623   \c!bottom=\vfill,
2624   \c!offset=1em,
2625  %\c!bodyfont=,
2626  %\c!style=,
2627  %\c!color=,
2628  %\c!left=,
2629   \c!right=\hfill,
2630   \c!before=\blank,
2631   \c!after=\blank,
2632  %\c!inner=,
2633   \c!frame=\v!on,
2634  %\c!topframe=,
2635  %\c!bottomframe=,
2636  %\c!leftframe=,
2637  %\c!rightframe=,
2638   \c!radius=.5\bodyfontsize,
2639   \c!corner=\v!rectangular,
2640  %\c!orientation=,
2641  %\c!indenting=,
2642  %\c!foregroundcolor=,
2643  %\c!foregroundstyle=,
2644  %\c!background=,
2645  %\c!backgroundcolor=,
2646   \c!linecorrection=\v!on,
2647   \c!depthcorrection=\v!on,
2648   \c!margin=\v!standard]
2649
2650\appendtoks
2651    \setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}%
2652    \setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop                      }%
2653    \setuevalue        {\currentframedtext}{\pack_framed_text_direct{\currentframedtext}}%
2654\to \everydefineframedtext
2655
2656\setvalue{\??framedtextlocation\v!left  }{\letframedtextparameter\c!left \relax
2657                                          \letframedtextparameter\c!right\hfill}
2658
2659\setvalue{\??framedtextlocation\v!right }{\letframedtextparameter\c!left \hfill
2660                                          \letframedtextparameter\c!right\relax}
2661
2662\setvalue{\??framedtextlocation\v!middle}{\letframedtextparameter\c!left \hfill
2663                                          \letframedtextparameter\c!right\hfill}
2664
2665\setvalue{\??framedtextlocation\v!none  }{\letframedtextparameter\c!left \relax
2666                                          \letframedtextparameter\c!right\relax
2667                                          \settrue\c_framed_text_location_none}
2668
2669\unexpanded\def\pack_framed_text_start#1%
2670  {\bgroup
2671   \edef\currentframedtext{#1}%
2672   \dodoubleempty\pack_framed_text_start_indeed}
2673
2674\def\pack_framed_text_start_indeed[#1][#2]%
2675  {\doifelseassignment{#1}
2676     {\pack_framed_text_start_continue\empty{#1}}
2677     {\pack_framed_text_start_continue{#1}{#2}}}
2678
2679% todo: sort out first/lastline ht/dp
2680
2681\def\pack_framed_text_start_continue#1#2%
2682  {\setupframedtexts[\currentframedtext][#2]%
2683   \doifsomething{#1}{\setframedtextparameter\c!location{#1}}% does not listen to #3
2684   \setfalse\c_framed_text_location_none
2685   \csname\??framedtextlocation\framedtextparameter\c!location\endcsname
2686   \resetframedtextparameter\c!location
2687   \pack_framed_text_check
2688   \setbox\b_framed_normal\vbox % \vpack
2689     \startboxedcontent
2690       \hsize\localhsize
2691    %  \insidefloattrue % ? better
2692       \usebodyfontparameter\framedtextparameter
2693    %  \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used
2694       \letframedtextparameter\c!strut\v!no
2695       \inheritedframedtextframed\bgroup
2696         \let\\\endgraf
2697         \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}%
2698         \ifx\p_framed_text_depthcorrection\v!on
2699            \pack_framed_text_start_depth_correction
2700         \else
2701            \bgroup
2702         \fi
2703         \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
2704         \doinhibitblank
2705         \useindentingparameter\framedtextparameter
2706         \useframedtextstyleandcolor\c!style\c!color
2707         \framedtextparameter\c!inner
2708         \ignorespaces}
2709
2710% testcase 1:
2711%
2712% \showstruts
2713% \startframedtext[align={normal,tolerant},offset=0pt] \input tufte \stopframedtext
2714% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \input tufte \stopframedtext
2715% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \inframed{x} \stopframedtext
2716% \framed[align={normal,tolerant},offset=0pt]{\input tufte }
2717
2718%D The \type {none} option is handy for nested usage, as in the presentation
2719%D styles, where we don't want interference.
2720
2721\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
2722
2723\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
2724  {\endgraf
2725   \removelastskip
2726   \ifx\p_framed_text_depthcorrection\v!on
2727     \pack_framed_text_stop_depth_correction
2728   \else
2729     \egroup
2730   \fi
2731   \stopboxedcontent
2732   \ifconditional\c_framed_text_location_none
2733     \egroup
2734     \box\b_framed_normal
2735   \else\ifinsidefloat
2736     \egroup
2737     \box\b_framed_normal
2738   \else
2739     \egroup
2740     \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}%
2741   \fi\fi
2742   \egroup}
2743
2744%D We define the general (and original) case by just saying:
2745
2746\def\pack_framed_text_check % messy dependency
2747  {\localhsize\hsize
2748   \ifinsidefloat \else \ifdim\d_page_sides_vsize>\zeropoint % also possible: \c_page_sides_checks_done>\zeropoint
2749   % \strut            % rather clean way to invoke the sidefloat OTR
2750   % \setbox0=\lastbox % and get the widths set, so from now on we
2751   % \setlocalhsize    % can have framed texts alongside sidefloats
2752     \checksidefloat
2753     \setlocalhsize
2754   \fi \fi}
2755
2756\def\pack_framed_text_start_depth_correction
2757  {\bgroup
2758   \ifhmode
2759     \par
2760   \fi
2761   \ifvmode
2762     \verticalstrut
2763     % we need \nowhitespace in case of setups setting whitespace
2764     % nb, not safe, text vs \vbox as next
2765     \vskip-\struttotal
2766     \nowhitespace
2767   \fi} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
2768
2769\def\pack_framed_text_stop_depth_correction
2770  {\ifhmode
2771     \par
2772   \fi
2773   \ifvmode
2774     \forgetall
2775     \vskip-\struttotal
2776     \verticalstrut
2777     \egroup
2778     \forgetall % brrr too often
2779     \vskip-\lineheight
2780     \verticalstrut
2781   \else
2782     \egroup
2783   \fi}
2784
2785%D Placement can be ignored:
2786%D
2787%D \starttyping
2788%D \hbox to \hsize \bgroup
2789%D     \startframedtext[none][width=.5\textwidth] \input tufte \stopframedtext
2790%D     \startframedtext[none][width=.5\textwidth] \input zapf  \stopframedtext
2791%D \egroup
2792%D
2793%D \hbox to \hsize \bgroup
2794%D     \setupframedtexts[location=none]%
2795%D     \startframedtext[width=.5\textwidth] \input zapf  \stopframedtext
2796%D     \startframedtext[width=.5\textwidth] \input tufte \stopframedtext
2797%D \egroup
2798%D \stoptyping
2799
2800%D The simple brace (or group) delimited case is typeset slightly different
2801%D and is not aligned.
2802
2803\unexpanded\def\pack_framed_text_direct#1%
2804  {\bgroup
2805   \edef\currentframedtext{#1}%
2806   \dosingleempty\pack_framed_text_start_direct}
2807
2808\def\pack_framed_text_start_direct[#1]%
2809  {\usebodyfontparameter\framedtextparameter
2810   \iffirstargument
2811     \setupcurrentframedtext[#1]%
2812   \fi
2813   \edef\p_framed_text_strut{\framedtextparameter\c!strut}%
2814   \letframedtextparameter\c!strut\v!no
2815   \inheritedframedtextframed\bgroup
2816     \blank[\v!disable]%
2817     \let\\\endgraf
2818     \useframedtextstyleandcolor\c!style\c!color
2819     \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
2820     \framedtextparameter\c!inner
2821     \ifx\p_framed_text_strut\v!no
2822        \let\pack_framed_strut\relax
2823     \else
2824        \let\pack_framed_strut\strut
2825     \fi
2826     \bgroup
2827     \aftergroup\pack_framed_text_stop_direct
2828     \afterassignment\ignorespaces
2829     \afterassignment\pack_framed_strut
2830     \let\next=}
2831
2832\def\pack_framed_text_stop_direct
2833  {\removelastskip
2834   \egroup
2835   \egroup}
2836
2837\defineframedtext
2838  [\v!framedtext]
2839
2840%D \macros
2841%D   {defineframed}
2842%D
2843%D One can also define simple framed texts, using:
2844%D
2845%D \showsetup{defineframed}
2846%D
2847%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead
2848%D of passing a combination of arguments. This also also simplified the \type
2849%D {\setupframed} command. There are certainly more places where such improvements
2850%D can be made.
2851
2852\appendtoks
2853    \ifcsname\??regularframedlevel\currentframed\endcsname
2854      % already defined, keeps settings
2855    \else
2856      \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
2857    \fi
2858\to \everypresetframed
2859
2860\appendtoks
2861   \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}%
2862\to \everydefineframed
2863
2864\newcount\c_temp_framed_crap
2865
2866\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
2867  {\bgroup
2868   \ifcsname\??regularframedlevel#1\endcsname
2869    %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
2870     \expandafter\let\expandafter\c_pack_framed_temp\lastnamedcs
2871   \else
2872     \let\c_pack_framed_temp\c_temp_framed_crap
2873   \fi
2874   \advance\c_pack_framed_temp\plusone
2875   \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
2876   \bgroup
2877   \edef\currentframed{#1>\the\c_pack_framed_temp}%
2878   \pack_framed_initialize
2879   \dosingleempty\pack_framed_defined_process_indeed}
2880
2881\def\pack_framed_defined_process_indeed[#1]%
2882  {\iffirstargument % faster
2883     \setupcurrentframed[#1]% here !
2884   \fi
2885   \pack_framed_process_indeed}
2886
2887\let\placeframed\pack_framed_defined_process % new per 2012/04/23
2888
2889%D We can do:
2890%D
2891%D \starttyping
2892%D \defineframed[\v!framed]
2893%D \stoptyping
2894%D
2895%D but the existing one is ok as well (less csname messy too).
2896
2897%D New, for the moment private; let's see when GB finds out about this one and its
2898%D obscure usage. It's used in:
2899%D
2900%D \startbuffer
2901%D \defineframedtext
2902%D   [tabulateframe]
2903%D   [offset=overlay,
2904%D    backgroundoffset=3pt,
2905%D    background=color,
2906%D    backgroundcolor=green]
2907%D
2908%D \setuptabulate
2909%D   [tabulate]
2910%D   [frame=tabulateframe]
2911%D
2912%D \setuptables
2913%D   [frame=tabulateframe]
2914%D
2915%D \input tufte
2916%D
2917%D \starttabulate[|l|l|]
2918%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
2919%D \NC test \NC test \NC \NR \NC test \NC test \NC \NR
2920%D \stoptabulate
2921%D
2922%D \input tufte
2923%D
2924%D \starttable[|l|l|]
2925%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
2926%D \NC test \NC test \NC \AR \NC test \NC test \NC \AR
2927%D \stoptable
2928%D \stopbuffer
2929%D
2930%D \typebuffer
2931
2932\installcorenamespace{framedcontent}
2933
2934\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent
2935
2936\setupframedcontent
2937  [\c!leftoffset=\zeropoint,
2938  %\c!rightoffset=\framedcontentparameter\c!leftoffset,
2939   \c!rightoffset=\scratchleftoffset,
2940   \c!topoffset=\zeropoint,
2941  %\c!bottomoffset=\framedcontentparameter\c!topoffset,
2942   \c!bottomoffset=\scratchtopoffset,
2943   \c!strut=\v!no,
2944  %\c!linecorrection=\v!no,
2945  %\c!left=,
2946  %\c!right=,
2947  %\c!width=\v!fit,
2948   \c!offset=\v!overlay]
2949
2950\unexpanded\def\startframedcontent
2951  {\dosingleempty\pack_framed_start_content}
2952
2953\def\pack_framed_start_content[#1]%
2954  {\bgroup
2955   \edef\currentframedcontent{#1}%
2956   \ifx\currentframedcontent\v!off
2957     \let\stopframedcontent\egroup
2958   \else
2959     \checkframedcontentparent
2960     \let\stopframedcontent\pack_framed_stop_content_indeed
2961     \expandafter\pack_framed_start_content_indeed
2962   \fi}
2963
2964\def\pack_framed_start_content_indeed
2965  {\setbox\b_framed_normal\hpack\bgroup
2966     \setlocalhsize
2967     \hsize\localhsize
2968     \scratchleftoffset  \framedcontentparameter\c!leftoffset  \relax
2969     \scratchrightoffset \framedcontentparameter\c!rightoffset \relax
2970     \scratchtopoffset   \framedcontentparameter\c!topoffset   \relax
2971     \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax
2972     \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax
2973     \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax
2974     \kern\scratchleftoffset
2975     \vpack\bgroup
2976       \vskip\scratchtopoffset
2977       \vbox\bgroup
2978         \forgetall
2979         \blank[\v!disable]}
2980
2981\def\pack_framed_stop_content_indeed
2982         {\removelastskip
2983       \egroup
2984       \vskip\scratchbottomoffset
2985     \egroup
2986     \kern\scratchrightoffset
2987   \egroup
2988   \doif{\framedcontentparameter\c!width}\v!fit
2989     {\letframedcontentparameter\c!width\v!fixed}% no shapebox
2990   \ifinsidefloat
2991     \donefalse
2992   \else
2993     \doifelse{\framedcontentparameter\c!linecorrection}\v!yes\donetrue\donefalse
2994   \fi
2995   % plaats ?
2996   \ifdone\startlinecorrection\fi
2997   \framedcontentparameter\c!left % new
2998   \inheritedframedcontentframed{\box\b_framed_normal}% hm
2999   \framedcontentparameter\c!right % new
3000   \ifdone\stoplinecorrection\fi
3001   \egroup}
3002
3003% A shared setting.
3004
3005\setuplinewidth
3006  [\v!medium]
3007
3008%D A Goodie:
3009
3010\defineframed
3011  [\v!unframed]
3012  [\c!frame=\v!off,
3013   \c!rulethickness=\zeropoint,
3014   \c!foregroundstyle=\framedparameter\c!style,
3015   \c!foregroundcolor=\framedparameter\c!color]
3016
3017%D Bonus (as defined in \type {pack-rul.lua}):
3018%D
3019%D \starttyping
3020%D \setbox\scratchbox\vbox{a\par aa\par aaa\par}
3021%D \the\dimexpr\themaxboxwidth\scratchbox\relax
3022%D \stoptyping
3023
3024\let\themaxboxwidth\clf_themaxboxwidth
3025
3026%D New: slow but ok for most cases:
3027
3028\unexpanded\def\doifelseframed#1%
3029  {\ifcase\numexpr\zerocount
3030     \immediateassignment\edef\tempstring{#1\c!frame      }\ifx\tempstring\v!on      +\plusone\fi
3031     \immediateassignment\edef\tempstring{#1\c!topframe   }\ifx\tempstring\v!on      +\plusone\fi
3032     \immediateassignment\edef\tempstring{#1\c!bottomframe}\ifx\tempstring\v!on      +\plusone\fi
3033     \immediateassignment\edef\tempstring{#1\c!leftframe  }\ifx\tempstring\v!on      +\plusone\fi
3034     \immediateassignment\edef\tempstring{#1\c!rightframe }\ifx\tempstring\v!on      +\plusone\fi
3035     \immediateassignment\edef\tempstring{#1\c!background }\ifx\tempstring\empty\else+\plusone\fi
3036   \relax\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
3037
3038\protect \endinput
3039