summaryrefslogtreecommitdiff
path: root/info/digests/texhax/txh/relate.txh
blob: 52fdc9bb840a8fb662cb4ed43d79403a2ce0660b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
21-Dec-87 09:30:52-PST,12519;000000000000
Return-Path: <@RELAY.CS.NET:phcalamai@water.waterloo.edu>
From: "Paul H. Calamai" <phcalamai%water.waterloo.edu@RELAY.CS.NET>
Subject: Re:      LaTeX list environment question

Steve Buyske <ST401266%BROWNVM.BITNET@forsythe.stanford.edu>:
> 
> 
>     I would like to make a construct a list environment so that I can
> have labels that might require two line.  Something like
> 
> Professional       Something silly, something else silly, some more
> Associations:      silly things, and so on.
> 
> If I put the label in a \parbox, no matter how I fiddle around, I get
> something like:
> 
> Professional       Something silly, something else silly, some more
> Associations:
>                    silly things, and so on.
> 
> with an ugly extra line.  Can anyone give me some advice?
> 
>     My apologies if this is an easy question, but I'm new to LaTeX and
> desperate to get my C.V. done.
> 
Here is a tex file that will do what you want:


% relate_macros.tex		1987 Jun 10	E. Ledoux
% Instructions for use are located at the end of this file.
%
\makeatletter
%
\newdimen\relateleft \relateleft=\leftmargin  % space before label
\newdimen\relateright \relateright=\leftmargin  % min. space after label
\newbox\RELbox \newcount\RELcount \RELcount\z@
\newdimen\RELoldmax \newdimen\RELnewmax
%
\def\relate{\@ifnextchar [{\RELcontd}{\global\advance\RELcount\@ne
\expandafter\RELcontd\expandafter [\romannumeral \the\RELcount]}}%
%
\def\RELcontd[#1]{\def\RELlabel{#1}%
\expandafter\let\expandafter\RELmax\csname RELold@#1\endcsname
\ifx\RELmax\relax \RELoldmax0.20\hsize \else \RELoldmax\RELmax \fi
\list{}{\labelwidth\RELoldmax \itemindent\z@ \leftmargin\RELoldmax
\advance\leftmargin\relateleft \advance\leftmargin\relateright
\let\makelabel\RELmakelabel}}%
%
\def\RELmakelabel#1{\@ifundefined{RELnew@\RELlabel}{\RELnewmax\z@}%
{\expandafter\RELnewmax\csname RELnew@\RELlabel\endcsname}%
\setbox\RELbox\hbox{\vtop to0pt{\let\\\cr \halign{##\hfil\cr#1\cr} \vss}}%
\ifdim\wd\RELbox>\RELnewmax \RELnewmax\wd\RELbox\fi
\expandafter\xdef\csname RELnew@\RELlabel\endcsname{\the\RELnewmax}%
\hskip\labelsep \hskip-\relateright \hbox to\z@{\box\RELbox\hss}\hfill}%
%
\def\endrelate{\toks\z@\expandafter{\csname RELold@\RELlabel\endcsname}%
\immediate\write\@auxout{\gdef\the\toks0{\csname RELnew@\RELlabel\endcsname}}%
\endlist}%
%
\makeatother
\endinput


				HOW TO USE IT

This LaTeX macro file defines a "relate" environment, which is basically
a more intelligent "description" environment.  To use it, place
	\input {path}relate
somewhere before \begin{document}.

Here's an example of relate environment usage:

	\begin{relate}
		\item[Spot]	Spot is a dog.  See Spot run.
		\item[Spock]	Spock is a Vulcan.  See Spock think.
		\item[Cigarette\\Smoke]
				Smoke is a health hazard.
				The Surgeon General recommends ... smoked.
	\end{relate}

This produces output that looks like this:

        |                       preceding text                      |
        +-----------------------------------------------------------+

                Spot		 Spot is a dog.  See Spot run.

	        Spock		 Spock is a Vulcan.  See Spock think.

	        Cigarette	 Smoke  is  a  health  hazard.    The
	        Smoke		 Surgeon General ....................
				 ........ smoked.
	|<---->|         |<---->|
      \relateleft      \relateright

	|<---- left margin ---->|

The relate environment behaves very much like the description environment
except:

  1. \item labels may be multi-line.  For example, \item[Cigarette\\Smoke]
     produces a two-line label, with "Cigarette" on one line and "Smoke"
     on the following line.  [BUG: You get strange output if your label
     has more lines than the associated text.]

  2. Labels don't intrude into the text, like long labels do in the
     description environment.  Relate automatically calculates the width of
     the widest label in a relate environment and adjusts the "left margin"
     of the text appropriately.  This is done using the .aux file, similar
     to LaTeX section, page number etc. references, so margins will not
     be correct until the second LaTeX run after a change to a label is made.

     \relateleft and \relateright are horizontal space parameters;
     the left margin for a relate environment will be equal to
	\relateleft + maximum-width + \relateright
     where maximum-width is the width of the widest label.
     The default value of both \relateleft and \relateright is \leftmargin 
     (about 25 points when using 10-point fonts).
     \relateleft and \relateright can be changed using \setlength, eg.
	\setlength{\relateleft}{0.5in}
	\setlength{\relateright}{0.3in}
     This can be done immediately after \input-ing relate_macros.

Normally, each relate environment is autonomous in the sense that only
labels in that environment determine the left margin for that environment.
However, different relate environments within the same document can be "linked"
so that they have the same left margin.  For example,

	...
	\begin{relate}[apple]
		\item[anything] ...
		...
	\end{relate}
	...
	\begin{relate}[apple]
		\item[whatever] ...
		...
	\end{relate}
	...

The left margins in these two relate environments will be the same because
they were "linked" by placing the same "label" ("apple" in this example)
in square brackets after \begin{relate}.  You can link any number of
relate environments in the same document; they need not be adjacent.
Labels should consist entirely of lower and uppercase letters.

If you get strange margins when using relate, just re-latex your document.
The left margins will be recalculated and should be correct on the second run.

By the way, you can nest relates within one another and within other
list environments as well.


				HOW IT WORKS
    
relate_macros.tex is described below:

 \makeatletter

This allows '@' to be used in control sequences, plus allows access to
the efficient \z@ (zero), \@ne (one), and other TeX and LaTeX hacks.

 \newdimen\relateleft \relateleft=\leftmargin  % space before label
 \newdimen\relateright \relateright=\labelsep  % min. space after label

Defines and sets the default values of \relateleft and \relateright.

 \newbox\RELbox \newcount\RELcount \RELcount\z@
 \newdimen\RELoldmax \newdimen\RELnewmax

\RELbox temporarily holds a label so that it can be measured.

\RELoldmax will hold the width of the widest label for this (and similarly
labelled) enviroments as calculated in the last run, for the duration of
each relate environment.  Similarly, \RELnewmax holds the width of the
widest label for this (and similarly labelled) relate environments as
calculated in this run, but \RELnewmax is updated from \RELnew@xxx
and stored to \RELnew@xxx at every \item in the environment (see below).

For a relate environment labelled, say, "apple", a global control sequence
named \RELnew@apple will be used to keep track of the width of the widest
label of all "apple" relate environments.  Inside each "apple" env. \item,
\RELnew@apple is copied to \RELnewmax.  \RELnewmax is updated if necessary
as the width of each label is computed.  When the \item ends, \RELnewmax
is copied back to \RELnew@apple, in case there are more "apple" environments.
When the entire environment ends, a line like:
 \gdef \RELold@apple {28.74pt}
is written to the .aux file, where 28.74pt would be the value of \RELnewmax,
the width of the widest label so far encountered in this and previous
relate environments.

At the beginning of every run (at \begin{document}, in fact), the .aux
file is \input automatically by LaTeX.  Assuming the previous run contained
several relate environments labelled "apple", \RELold@apple will be defined
(and redefined by each "apple" environment in the previous run) to be
the width of the widest label in all "apple" environments in the previous
run.  Assuming no labels changed since then, this value will be the correct
maximum label width.  (If this is the first run, \RELold@apple is not defined
and the arbitrary value of 0.20\hsize, one third the width of the page,
is used instead.)  In each "apple" relate environment, \RELold@apple is
copied to \RELoldmax, which is used to position labels within a left margin
of width \relateleft + \RELoldmax + \relateright.

 \def\relate{\@ifnextchar [{\RELcontd}{\global\advance\RELcount\@ne
 \expandafter\RELcontd\expandafter [\romannumeral \the\RELcount]}}%

\RELcount is a counter used to create unique relate environment labels
for when the user doesn't supply one (like "apple" in the above example).
\begin{relate} simply invokes \relate; if an argument in square brackets
is present (eg. [apple]), then \RELcontd ("relate continued") is called
with that argument.  Otherwise, \RELcount is incremented and a unique
label is formed by converting the value of \RELcount to lowercase roman
numerals (ie. "i", "ii", "iii", "iv", ...).

 \def\RELcontd[#1]{\gdef\RELlabel{#1}%

\RELlabel holds the environment label for use by \endrelate.

 \expandafter\let\expandafter\RELmax\csname RELold@#1\endcsname
 \ifx\RELmax\relax \RELoldmax0.20\hsize \else \RELoldmax\RELmax \fi

If \RELold@apple (assuming "apple" relate environment label) has been
defined (presumably in the .aux file), set \RELoldmax to that value,
otherwise set \RELoldmax to the arbitrary value of 0.20\hsize.

 \@ifundefined{RELnew@#1}{\global\RELnewmax\z@}%
 {\expandafter\global\expandafter\RELnewmax\csname RELnew@#1\endcsname}%

If \RELnew@apple has been defined, then set \RELnewmax to that value,
otherwise set \RELnewmax to zero.

 \list{}{\labelwidth\RELoldmax \itemindent\z@ \leftmargin\RELoldmax
 \advance\leftmargin\relateleft \advance\leftmargin\relateright
 \let\makelabel\RELmakelabel}}%

Start a \list.  Set \labelwidth to zero; labels will really have zero width
anyway.  Set the \leftmargin to \RELoldmax + \relateleft + \relateright.
(This is LaTeX's idea of left margin; see p. 113 in the LaTeX manual.)
Set \labelwidth to the maximum label width -- the label will be right-
justified within a box of this width by \RELmakelabel.
\RELmakelabel will be used to make labels.

 \def\RELmakelabel#1{\@ifundefined{RELnew@\RELlabel}{\RELnewmax\z@}%
 {\expandafter\RELnewmax\csname RELnew@\RELlabel\endcsname}%

If \RELnew@apple is undefined, define \RELnewmax as zero, otherwise
define it as the value of \RELnew@apple.  \RELnewmax is a \dimen variable
which is only (effectively) active for the duration of an \item.

 \setbox\RELbox\hbox{\vtop to0pt{\let\\\cr \halign{##\hfil\cr#1\cr} \vss}}%

Typeset the label in the horizonal box register \RELbox.  The \halign
(with \\ defined as \cr) allows multiple \\-separated lines in the label.
\vtop to0pt and \vss make LaTeX think that this is a one-line box,
regardless of the actual number of lines.

 \ifdim\wd\RELbox>\RELnewmax \RELnewmax\wd\RELbox\fi
 \expandafter\xdef\csname RELnew@\RELlabel\endcsname{\the\RELnewmax}%

If the width of \RELbox is greater than the current maximum label width,
increase \RELnewmax appropriately.  Then, store the new maximum label
width back into \RELnew@apple for use by the next \RELmakelabel.

 \hskip\labelsep \hskip-\relateright \hbox to\z@{\box\RELbox\hss}\hfill}%

Print the left edge of the label at distance \relateright - \labelsep from
the left edge of the text.

 \def\endrelate{\toks\z@\expandafter{\csname RELold@\RELlabel\endcsname}%
 \immediate\write\@auxout{\gdef\the\toks0{\csname RELnew@\RELlabel\endcsname}}%
 \endlist}%

Finish the relate environment.  \endrelate is called by \end{relate}.
Write a line to the .aux file of the form
 \gdef \RELold@apple {28.74pt}
as explained above.

 \makeatother
 \endinput

That's all, folks!


% 1987 Jun 10	E. Ledoux	Creation
% 1987 Jun 12	E. Ledoux	Fixed problem with nested relate env's

-------