typo-lbx.mkxl /size: 12 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=typo-lbx,
3%D        version=2021.10.10,
4%D          title=\CONTEXT\ Typesetting Macros,
5%D       subtitle=Local Boxes,
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 Typesetting Macros / Local Boxes}
15
16% This time the usual musical timestamp is: New Scary Goldings ft. John Scofield
17% MonoNeon & Louis Cole (late October 2021) (plus the playlist in loop mode) and
18% further improved after watching Cory Wong's LIVE IN MPLS (9 FEB 2019) concert.
19
20% maybe: \iflocalbox 0/1/2
21
22\registerctxluafile{typo-lbx}{autosuffix}
23
24%D The advantage is that it's deal with in the par builder which has some advantages
25%D but when used in complex situation there can be side effects. Therefore is should
26%D be considered a somewhat low level mechanism on top of which one can write more
27%D mechanisms that provide more rendering control. Also, keep in mind that combining
28%D many instances at the same time add some complizity. Therefore, for the moment it's
29%D a playground.
30
31\unprotect
32
33\def\typo_localboxes_reset
34  {\localleftbox  {}% no index here, works grouped
35   \localrightbox {}%
36   \localmiddlebox{}}
37
38\appendtoks
39    \typo_localboxes_reset
40\to\everyforgetall
41
42\definesystemattribute[localboxesmark][public]
43
44%D We used to pass arguments but there might be many so ...
45
46\newbox\localboxcontentbox
47
48\installcorenamespace{localboxes}
49\installcorenamespace{localboxesattribute}
50\installcorenamespace{localboxesnamespace}
51\installcorenamespace{localboxeslocations}
52\installcorenamespace{localboxesresetters}
53
54\installcommandhandler \??localboxes {localboxes} \??localboxes
55
56\setuplocalboxes
57  [\c!command=\localboxcontent,
58   \c!width=\zeropoint,
59   \c!location=\v!left,
60   \c!distance=\zeropoint]
61
62\newinteger\c_typo_localboxes
63\newinteger\c_typo_localboxes_index
64
65\appendtoks
66    \global\advanceby\c_typo_localboxes\plusone
67    \global\expandafter\integerdef\csname\??localboxesattribute\currentlocalboxes\endcsname\c_typo_localboxes
68    \gletcsname\??localboxesnamespace\the\c_typo_localboxes\endcsname\currentlocalboxes
69\to \everydefinelocalboxes
70
71%D The optional argument forces setting the \quote {whole} paragraph properties (which is needed
72%D when the assignment happens after e.g.\ \type {\everypar} but is also meant for the first
73%D line.
74
75%D Todo: reserve index 1 for this:
76
77\def\typo_paragraphs_l#1{\localleftbox  \ifcstok{#1}\v!global par\fi}
78\def\typo_paragraphs_r#1{\localrightbox \ifcstok{#1}\v!global par\fi}
79\def\typo_paragraphs_m#1{\localmiddlebox\ifcstok{#1}\v!global par\fi}
80
81\permanent\tolerant\protected\def\leftparbox  [#1]{\typo_paragraphs_l{#1}\bgroup\enforced\let\leftparbox \relax\let\next}
82\permanent\tolerant\protected\def\rightparbox [#1]{\typo_paragraphs_r{#1}\bgroup\enforced\let\rightparbox\relax\let\next}
83\permanent\tolerant\protected\def\middleparbox[#1]{\typo_paragraphs_m{#1}\bgroup\enforced\let\rightparbox\relax\let\next}
84
85% called back:
86
87\permanent\protected\def\localboxcontent
88  {\box\localboxcontentbox}
89
90\permanent\protected\def\localboxcommand
91  {\ifcsname\??localboxesnamespace\number\localboxindex\endcsname
92    %\cdef\currentlocalboxes{\lastnamedcs}%
93     \expandafter\let\expandafter\currentlocalboxes\lastnamedcs
94     \setbox\localboxcontentbox\hbox
95       {\uselocalboxesstyleandcolor\c!style\c!color % sometimes redundant
96        \localboxesparameter\c!command}%
97   \fi}
98
99%D We don't group because we set the local boxes. Also, watch out: by injecting the
100%D existing local box we create nested ones. This is handled in the callback but if
101%D really needed one can do something like (do we need a primitive?):
102
103\mutable\lettonothing\currentlocalboxeslocation
104
105\def\typo_localboxes_localbox
106  {\ifx\currentlocalboxeslocation\v!right
107     \localrightbox
108   \orelse\ifx\currentlocalboxeslocation\v!left
109     \localleftbox
110   \else
111     \localmiddlebox
112   \fi}
113
114\def\typo_localboxes_zero#1#2#3%
115  {\ifcsname\??localboxesattribute#2\endcsname
116     \c_typo_localboxes_index\lastnamedcs
117     \cdef\currentlocalboxes{#2}%
118     \edef\currentlocalboxeslocation{#1}%
119     \typo_localboxes_localbox
120        index \c_typo_localboxes_index
121        \bgroup
122          \hpack
123            \ifcstok{\localboxesparameter\c!repeat}\v!no
124              attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax
125            \fi
126            to \zeropoint
127          \bgroup
128            \uselocalboxesstyleandcolor\c!style\c!color
129            \hbox{#3}%
130            \hss
131          \egroup
132        \egroup
133   \fi}
134
135\def\typo_localboxes_asis#1#2#3%
136  {\ifcsname\??localboxesattribute#2\endcsname
137     \c_typo_localboxes_index\lastnamedcs
138     \cdef\currentlocalboxes{#2}%
139     \edef\currentlocalboxeslocation{#1}%
140     \typo_localboxes_localbox
141        index \c_typo_localboxes_index
142        \bgroup
143          \hpack
144            \ifcstok{\localboxesparameter\c!repeat}\v!no
145              attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax
146            \fi
147            % todo: use width if dimension, use distance if given
148          \bgroup
149            \uselocalboxesstyleandcolor\c!style\c!color
150            \hbox{#3}% no \hss
151          \egroup
152        \egroup
153   \fi}
154
155\defcsname\??localboxeslocations\v!left     \endcsname{\typo_localboxes_zero\v!left  }
156\defcsname\??localboxeslocations\v!right    \endcsname{\typo_localboxes_zero\v!right }
157\defcsname\??localboxeslocations\v!lefttext \endcsname{\typo_localboxes_asis\v!left  }
158\defcsname\??localboxeslocations\v!righttext\endcsname{\typo_localboxes_asis\v!right }
159\defcsname\??localboxeslocations\v!middle   \endcsname{\typo_localboxes_asis\v!middle}
160
161\letcsname\??localboxesresetters\v!left     \endcsname\v!left
162\letcsname\??localboxesresetters\v!right    \endcsname\v!right
163\letcsname\??localboxesresetters\v!lefttext \endcsname\v!left
164\letcsname\??localboxesresetters\v!righttext\endcsname\v!right
165\letcsname\??localboxesresetters\v!middle   \endcsname\v!middle
166
167\permanent\tolerant\protected\def\resetlocalbox[#1]%
168  {\ifcsname\??localboxesattribute#1\endcsname
169     \c_typo_localboxes_index\lastnamedcs
170     \cdef\currentlocalboxes{#1}%
171     \ifcsname\??localboxesresetters\localboxesparameter\c!location\endcsname
172       \edef\currentlocalboxeslocation{\lastnamedcs}%
173       \typo_localboxes_localbox index \c_typo_localboxes_index {}%
174     \fi
175   \fi}
176
177\def\typo_localboxes_box#1%
178  {\dowithnextboxcontent
179     {\cdef\currentlocalboxes{#1}%
180      \uselocalboxesstyleandcolor\c!style\c!color}
181     {\ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname
182        \expandafter\lastnamedcs
183      \else
184        \csname\??localboxeslocations\v!left\expandafter\endcsname
185      \fi{#1}{\unhbox\nextbox}}}
186
187
188\permanent\tolerant\protected\def\localbox[#1]%
189  {\typo_localboxes_box{#1}\hbox}
190
191\permanent\tolerant\protected\def\startlocalbox[#1]%
192  {\dowithnextbox
193     {\ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname
194         \expandafter\lastnamedcs
195       \else
196         \csname\??localboxeslocations\v!left\expandafter\endcsname
197       \fi{#1}{\unhbox\nextbox}}%
198     \hbox\bgroup
199     \cdef\currentlocalboxes{#1}%
200     \uselocalboxesstyleandcolor\c!style\c!color
201     \enforced\def\stoplocalbox{\removeunwantedspaces\egroup}%
202     \ignorespaces}
203
204\aliased\let\stoplocalbox\donothing
205
206\permanent\tolerant\protected\def\startlocalboxrange[#1]%
207  {\globalpushmacro\stoplocalboxrange
208   \ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname
209     \lastnamedcs{#1}{}%
210   \fi}
211
212\permanent\protected\def\stoplocalboxrange
213  {\globalpopmacro\stoplocalboxrange}%
214
215% using left and right with left lagging behind:
216%
217% \permanent\protected\def\localmarginlefttext#1%
218%   {\setbox\localboxcontentbox\hpack
219%      {\unhbox\localboxcontentbox
220%       \setbox\localboxcontentbox\lastbox
221%       \unhbox\localboxcontentbox}%
222%    \hpack xoffset -\dimexpr
223%       #1
224%      +\localboxprogress
225%      +\localboxleftoffset
226%      +\wd\localboxcontentbox
227%      +\localboxesparameter\c!distance
228%    \relax{\box\localboxcontentbox}}
229%
230% \permanent\protected\def\localmarginrighttext#1%
231%   {\hpack xoffset \dimexpr
232%       #1
233%      +\localboxrightoffset
234%      +\localboxlocalwidth
235%      -\localboxprogress
236%      +\localboxesparameter\c!distance
237%    \relax{\box\localboxcontentbox}}
238
239% using middle:
240
241\permanent\protected\def\localmarginlefttext#1%
242  {\ifzeropt\localboxesparameter\c!width\relax
243     % a but ugly hack ... for now
244     \setbox\localboxcontentbox\hpack
245       {\unhbox\localboxcontentbox
246        \setbox\localboxcontentbox\lastbox
247        \unhbox\localboxcontentbox}%
248   \fi
249   \hpack xoffset \dimexpr
250     -#1
251     -\localboxprogress
252     -\wd\localboxcontentbox
253     -\localboxesparameter\c!distance
254   \relax{\box\localboxcontentbox}}
255
256\permanent\protected\def\localmarginrighttext#1%
257  {\hpack xoffset \dimexpr
258      #1
259     +\localboxlinewidth
260     -\localboxprogress
261     +\localboxesparameter\c!distance
262   \relax{\box\localboxcontentbox}}
263
264% todo: use generic one above
265
266\permanent\protected\def\localmargintext[#1]#2%
267  {\dontleavehmode
268   \ifcsname\??localboxesattribute#1\endcsname
269     \c_typo_localboxes_index\lastnamedcs
270     \cdef\currentlocalboxes{#1}%
271     \edef\currentlocalboxeslocation{\localboxesparameter\c!location}%
272     \ifx\currentlocalboxeslocation\v!right\localrightbox\orelse\ifx\currentlocalboxeslocation\v!left\localleftbox\else\localmiddlebox\fi
273        index \c_typo_localboxes_index
274        \bgroup
275          \hpack
276            \ifcstok{\localboxesparameter\c!repeat}\v!no
277              attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax
278            \fi
279            to \zeropoint
280          \bgroup
281            \uselocalboxesstyleandcolor\c!style\c!color
282            \hbox{#2}%
283            \hss
284          \egroup
285        \egroup
286   \fi}
287
288\definelocalboxes
289  [\v!leftmargin]
290  [\c!command=\localmarginlefttext\zeropoint,
291   \c!repeat=\v!no,
292   \c!distance=\leftmargindistance,
293 % \c!location=\v!left]
294   \c!location=\v!middle]
295
296\definelocalboxes
297  [\v!rightmargin]
298  [\c!command=\localmarginrighttext\zeropoint,
299   \c!repeat=\v!no,
300   \c!distance=\rightmargindistance,
301 % \c!location=\v!right]
302   \c!location=\v!middle]
303
304\definelocalboxes
305  [\v!leftedge]
306  [\c!command=\localmarginlefttext\leftmargintotal,
307   \c!repeat=\v!no,
308   \c!distance=\leftedgedistance,
309 % \c!location=\v!left]
310   \c!location=\v!middle]
311
312\definelocalboxes
313  [\v!rightedge]
314  [\c!command=\localmarginrighttext\rightmargintotal,
315   \c!repeat=\v!no,
316   \c!distance=\rightedgedistance,
317 % \c!location=\v!right]
318   \c!location=\v!middle]
319
320%D Here is an example of usage:
321
322%D \starttyping
323%D \definelocalboxes
324%D   [linenumber]
325%D   [command=\LeftNumber,location=left,width=3em,style=\bs,color=darkred]
326%D
327%D \definelocalboxes
328%D   [linenumbertwo] [linenumber]
329%D   [command=\RightNumber,location=right,width=6em,style=\bf,color=darkgreen]
330%D
331%D \definelocalboxes
332%D   [linetext]
333%D   [command=\LeftText,location=lefttext,style=\bs,color=darkblue]
334%D
335%D \definelocalboxes
336%D   [linetexttwo] [linetext]
337%D   [command=\RightText,location=righttext,style=\bf,color=darkgray]
338%D
339%D % \def\LineNumberL{\the\localboxlinenumber}
340%D % \def\LineNumberR{\the\localboxlinenumber}
341%D
342%D % \newinteger\MyLineNumberL
343%D % \newinteger\MyLineNumberR
344%D % \def\LineNumberL{\global\advanceby\MyLineNumberL\plusone\the\MyLineNumberL}
345%D % \def\LineNumberR{\global\advanceby\MyLineNumberR\plusone\the\MyLineNumberR}
346%D
347%D \definecounter[MyLineNumberL]
348%D \definecounter[MyLineNumberR]
349%D
350%D \setupcounter[MyLineNumberL][numberconversion=characters]
351%D \setupcounter[MyLineNumberR][numberconversion=romannumerals]
352%D
353%D \def\LineNumberL{\incrementcounter[MyLineNumberL]\convertedcounter[MyLineNumberL]}
354%D \def\LineNumberR{\incrementcounter[MyLineNumberR]\convertedcounter[MyLineNumberR]}
355%D
356%D \protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut(\LineNumberL\hss)}}
357%D \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\LineNumberR)}}
358%D
359%D % \protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut\box\localboxcontentbox\hss)}}
360%D % \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\box\localboxcontentbox)}}
361%D
362%D \protected\def\LeftText {\localboxcontentbox\quad}
363%D \protected\def\RightText{\quad\localboxcontentbox}
364%D
365%D \start
366%D     \localbox[linenumber]{}%
367%D     \localbox[linenumbertwo]{}%
368%D     \localbox[linetext]{L}%
369%D     \startlocalbox[linetexttwo]
370%D         R
371%D     \stoplocalbox
372%D     \dorecurse{100}{
373%D         \samplefile{tufte}
374%D         \par
375%D     }
376%D \stop
377%D \stoptyping
378
379\protect \endinput
380
381