summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/tabto/tabto.sty
blob: 084da37bad76a388272f4dab0f224b3e71658d0e (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
% tabto.sty
%
% version 1.4  (Dec 2018)
%
% Tabbing to fixed positions in a paragraph.
%
% Copyright 2006,2009,2012,2013,2018 by 
% Donald Arseneau,   Vancouver, Canada (asnd@triumf.ca)
% Permission to use, distribute and modify this software is granted
% under the conditions of the LaTeX Project Public License, either 
% version 1.3 or (at your option) any later version.  The license is
% found at http://www.latex-project.org/lppl.txt, and is part of all 
% recent distributions of LaTeX.
%
% This work has the LPPL maintenance status `maintained' (by author).
%
% Two new text positioning commands are defined: \tabto and \tab.
% 
% \tabto{<length>}
% Tab to a position relative to the left margin in a paragraph (any
% indentation due to a list or \leftskip is part of the `margin' in
% this context). If the text on the line already goes past the desired
% position, the tab starts a new line and moves to the requested
% horizontal position.
%
% \tabto*{<length>}
% Similar to \tabto, except it will perform backspacing, and over-
% print previous text on the line whenever that text is already
% longer than the specified length (i.e., no linebreak is produced).
% Line-breaks are suppressed immediately after \tabto or \tabto*.
%
% The length register "\CurrentLineWidth" will report the width
% of the existing text on the line, and it may be used in the
% <length> argument (using calc.sty, for example). Also, there
% is "\TabPrevPos" which gives the "\CurrentLineWidth" from the
% previous tab command (the position where the tab command occurred,
% not where it went to), and can be used to return to that position
% if no line breaks have occurred in between, or directly below it,
% if there were line breaks.
%
% \tab
% Tab to the next tab-stop chosen from a list of tab positions, in
% the traditional style of typewriters.  A \tab will always move
% to the next tab stop (or the next line), even if it is already
% exactly at a tab stop. Thus, "\tab" at the beginning of a line,
% or "\tab\tab" elsewhere skips a position. A linebreak is permitted 
% immediately following a \tab, in case the ensuing text does not 
% fit well in the remaining space.
%
% If you do not want to skip positions, use "\tabto{\NextTabStop}"
% instead of "\tab".  This is particularly useful when you want to
% use \tab in some other command, but do not want to skip a column
% for the first item.
%
% The tab-stop positions are declared using either \TabPositions
% or \NumTabs:
%
% \TabPositions{<length>, <length>,...<length>}
% Declares the tab stops as a comma-separated list of positions 
% relative to the left margin. A tab-stop at 0pt is implicit, and 
% need not be listed.
%
% \NumTabs{<number>}
% Declares a list of <number> equally-spaced tabs, starting at the
% left margin and spanning \linewidth.  For example \NumTabs{2} 
% declares tab-stops at 0pt and 0.5\linewidth, the same as
% \TabPositions{0pt, 0.5\linewidth} or \TabPositions{0.5\linewidth}
%
% After these declarations, the list of tab positions is saved in
% \TabStopList, and the next tab position, relative to the current 
% position, is given by \NextTabStop.  You do not normally need
% to access them, but they are available.
%
% Problems:
%
% Tall objects after a tab stop may overlap the line above, rather
% than forcing a greater separation between lines.

\ProvidesPackage{tabto}[2018/12/28 \space v 1.4 \space 
  Another tabbing mechanism]\relax

\newdimen\CurrentLineWidth
\newdimen\TabPrevPos

\newcommand\tabto[1]{%
 \leavevmode
 \begingroup
 \def\@tempa{*}\def\@tempb{#1}%
 \ifx\@tempa\@tempb % \tab* 
   \endgroup
   \TTo@overlaptrue % ... set a flag and re-issue \tabto to get argument
   \expandafter\tabto
 \else
   \ifinner % in a \hbox, so ignore
   \else % unrestricted horizontal mode
     \null% \predisplaysize will tell the position of this box (must be box)
     \parfillskip\fill
     \everydisplay{}\everymath{}%
     \predisplaypenalty\@M \postdisplaypenalty\@M
     $$% math display so we can test \predisplaysize
      \lineskiplimit=-999pt % so we get pure \baselineskip
      \abovedisplayskip=-\baselineskip \abovedisplayshortskip=-\baselineskip
      \belowdisplayskip\z@skip \belowdisplayshortskip\z@skip
      \halign{##\cr\noalign{%
        % get the width of the line above
        \ifdim\predisplaysize=\maxdimen %\message{Mixed R and L, so say the line is full. }%
           \CurrentLineWidth\linewidth
        \else
           \ifdim\predisplaysize=-\maxdimen 
             % \message{Not in a paragraph, so call the line empty. }%
             \CurrentLineWidth\z@
           \else
             \ifnum\TTo@Direction<\z@
               \CurrentLineWidth\linewidth \advance\CurrentLineWidth\predisplaysize
             \else
               \CurrentLineWidth\predisplaysize 
             \fi
             % Correct the 2em offset
             \advance\CurrentLineWidth -2em
             \advance\CurrentLineWidth -\displayindent
             \advance\CurrentLineWidth -\leftskip
        \fi\fi
        \ifdim\CurrentLineWidth<\z@ \CurrentLineWidth\z@\fi
        % Enshrine the tab-to position; #1 might reference \CurrentLineWidth
        \setlength\@tempdimb{#1}% allow calc.sty
        %\message{*** Tab to \the\@tempdimb, previous width is \the\CurrentLineWidth. ***}%
        % Save width for possible return use
        \global\TabPrevPos\CurrentLineWidth
        % Build the action to perform
        \protected@xdef\TTo@action{%
           \vrule\@width\z@\@depth\the\prevdepth
           \ifdim\CurrentLineWidth>\@tempdimb
              \ifTTo@overlap\else
                 \protect\newline \protect\null
           \fi\fi
           \protect\nobreak
           \protect\hskip\the\@tempdimb\relax
        }%
        %\message{\string\TTo@action: \meaning \TTo@action. }%
        % get back to the baseline, regardless of its depth.
        \vskip-\prevdepth
        \prevdepth-99\p@
        \vskip\prevdepth
      }}%
      $$
     % Don't count the display as lines in the paragraph
     \count@\prevgraf \advance\count@-4 \prevgraf\count@
     \TTo@action
     %%   \penalty\@m % to allow a penalized line break
   \fi
   \endgroup
   \TTo@overlapfalse
   \ignorespaces
 \fi
}

% \tab -- to the next position
% \hskip so \tab\tab moves two positions
% Allow a (penalized but flexible) line-break right after the tab.
%
\newcommand\tab{\leavevmode\hskip2sp\tabto{\NextTabStop}%
  \nobreak\hskip\z@\@plus 30\p@\penalty4000\hskip\z@\@plus-30\p@\relax}


% Expandable macro to select the next tab position from the list

\newcommand\NextTabStop{%
  \expandafter \TTo@nexttabstop \TabStopList,\maxdimen,>%
}

\def\TTo@nexttabstop #1,{%
    \ifdim#1<\CurrentLineWidth
      \expandafter\TTo@nexttabstop
    \else
      \ifdim#1<0.9999\linewidth#1\else\z@\fi
      \expandafter\strip@prefix
    \fi
}
\def\TTo@foundtabstop#1>{}

\newcommand\TabPositions[1]{\def\TabStopList{\z@,#1}}

\newcommand\NumTabs[1]{%
   \def\TabStopList{}%
   \@tempdimb\linewidth 
   \divide\@tempdimb by#1\relax
   \advance\@tempdimb 1sp % counteract rounding-down by \divide
   \CurrentLineWidth\z@
   \@whiledim\CurrentLineWidth<\linewidth\do {%
     \edef\TabStopList{\TabStopList\the\CurrentLineWidth,}%
     \advance\CurrentLineWidth\@tempdimb
   }%
   \edef\TabStopList{\TabStopList\linewidth}%
}

% default setting of tab positions:
\TabPositions{\parindent,.5\linewidth}

\newif\ifTTo@overlap \TTo@overlapfalse

\@ifundefined{predisplaydirection}{
 \let\TTo@Direction\predisplaysize
 \let\predisplaydirection\@undefined
}{
 \let\TTo@Direction\predisplaydirection
}