~ubuntu-branches/ubuntu/trusty/pyx/trusty

« back to all changes in this revision

Viewing changes to contrib/textboxes.tex

  • Committer: Bazaar Package Importer
  • Author(s): Graham Wilson
  • Date: 2004-12-25 06:42:57 UTC
  • Revision ID: james.westby@ubuntu.com-20041225064257-31469ij5uysqq302
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
% Modified \output-routine for the use with PyX
 
2
% this file makes changes of \hsize and \vsizes possible after
 
3
% every pagebreak
 
4
%
 
5
% Copyright (C) 2004 Michael Schindler <m-schindler@sourceforge.net>
 
6
%
 
7
% This file is part of PyX (http://pyx.sourceforge.net/).
 
8
%
 
9
% PyX is free software; you can redistribute it and/or modify
 
10
% it under the terms of the GNU General Public License as published by
 
11
% the Free Software Foundation; either version 2 of the License, or
 
12
% (at your option) any later version.
 
13
%
 
14
% PyX is distributed in the hope that it will be useful,
 
15
% but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
% GNU General Public License for more details.
 
18
%
 
19
% You should have received a copy of the GNU General Public License
 
20
% along with PyX; if not, write to the Free Software
 
21
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
22
%
 
23
%
 
24
\newtoks\lovsizes
 
25
\newtoks\lohsizes
 
26
\newtoks\parnos
 
27
\newtoks\parshapes
 
28
%
 
29
% Please note that all four tokenlists have to end with {\relax}
 
30
% This is needed for correct shortening
 
31
%
 
32
%%%%%%%%%% TeX's part %%%%%%%%%%
 
33
\newif\ifverbose \verbosefalse
 
34
\newcount\tempcnt
 
35
\newcount\parno \parno=1
 
36
\newcount\myprevgraf \myprevgraf=0
 
37
\newcount\showprevgraf \showprevgraf=0
 
38
\newcount\outputtype \outputtype=0
 
39
\newcount\razor
 
40
\newcount\leastcost \leastcost=10000000
 
41
\newcount\futurecost
 
42
%
 
43
% Tools for splitting and merging tokenlists after their first element {{{
 
44
% did I learn too much lisp or what?
 
45
\def\cdr#1{\expandafter\precdr\expandafter#1\the#1@}
 
46
\def\numcdr#1{\expandafter\prenumcdr\expandafter#1\the#1@}
 
47
\def\numconcat#1#2{\edef\foo{{\the#1}\the#2}\global#2=\expandafter{\foo}}
 
48
%
 
49
\def\precdr#1#2#3@{\ifx#2\relax\relax\global#1={\relax}\else#2\global#1={#3}\fi}
 
50
\def\prenumcdr#1#2#3@{\ifx\relax#2 0\global#1={\relax}\else#2\global#1={#3}\fi}
 
51
% }}}
 
52
%
 
53
% The output routine {{{
 
54
% Documentation {{{
 
55
% 1. Question: Who calls the pagebuilder and \output?
 
56
%    Answer: Only \par and $$ (as far as I have read the TeXbook)
 
57
%
 
58
% 2. Question: So, all together: What is to be done?
 
59
%    Answer: We have to simulate the work of the linebuilder that makes
 
60
%    paragraphs and math into lines in order to find out, what value \prevgraf
 
61
%    might have at a pagepreak. Then, we change the \hsize and \vsize at the
 
62
%    pagepreak and inform PyX about the value of \prevgraf.
 
63
%
 
64
% 3. Question: When is \prevgraf advanced?
 
65
%    Answer: At every line by 1 and at every display math by 3
 
66
%
 
67
% 4. Question: How can we hook into the pagebuilding mechanism to find out
 
68
%    about lines and displays?
 
69
%    Answer: We get into the pagebuilder that splits vertical lists into pages
 
70
%    if we enforce a penalty of less than -10000. There are three built-in
 
71
%    hooks: \interlinepenalty
 
72
%           \predisplaypenalty
 
73
%           \postdisplaypenalty
 
74
%    These are set to values less than -10000 by wrapping \par and $$, the
 
75
%    ones who call the pagebuilder and, therefore, \output
 
76
%
 
77
%    Unfortunately, we get only "breaks", but we are interested in lines. At
 
78
%    each list, we have one break less than lines. So, we have to add another
 
79
%    call of \output at the end of a paragraph. This is done by an explicit
 
80
%           \penalty
 
81
%    A display math succeeding some text also calls the pagebuilder. We have
 
82
%    to add another line in such situations. This is done in the output
 
83
%    routine while processing \predisplaypenalty.
 
84
%
 
85
% 5. Question: Why are there so many \ifnum s in the output routine?
 
86
%    Answer: As explained avove, we have to do different things at different
 
87
%    positions of our text. \interlinepenalty and the \penalty for paragraph
 
88
%    endings have to add a line. \postdisplaypenalty has to add the display
 
89
%    (advances \prevgraf by 3), while \predisplaypenalty may still reside on
 
90
%    the previous page, while the display math has moved to the next one.
 
91
%    Therefore, it does not contribute to the \prevgraf. Nevertheless, if
 
92
%    there was some text before the display math in the same paragraph, we
 
93
%    still have to add the last line of text!
 
94
%
 
95
%    This is the reason for the whole \outputtype business:
 
96
%    We have to show a \prevgraf value different to \myprevgraf at a situation
 
97
%    where an \interlinepenalty is followed by a \predisplaypenalty which is
 
98
%    followed by a pagebreak. The display is on the next page.
 
99
%    The same can -- of course -- also occur with a \predisplaypenalty
 
100
%    following a \penalty caused by \par
 
101
%
 
102
% 6. Question: What the hell does \leastcost do?
 
103
%    Answer: This is a tricky point. We hooked into the pagebuilding mechanism
 
104
%    by changing penalties. In this case, TeX thinks, there is a very good
 
105
%    pagebreak and calls \output. But \output removes the strongly negative
 
106
%    penalty we added. Now, TeX has to reconsider the pagebreak and may come
 
107
%    to the result that some of the lines that have appeared as perfect
 
108
%    pagebreaks are not so perfect...
 
109
%    Therefore, before we re-inject the whole vertical list and remove the
 
110
%    negative penalty by saying
 
111
%       \unvbox255 \advance\outputpenalty by XXXXXX \penalty\outputpenalty
 
112
%    we have to know in advance, what the pagebuilder will think of the
 
113
%    pagebreak in the next run. See the TeXbook, p. 111 for the correct
 
114
%    formula.
 
115
%
 
116
%    This is the reason for \showprevgraf. We have two counters:
 
117
%    - \myprevgraf counts real lines and displays. This keeps us up-to-date
 
118
%      with the paragraph all the time
 
119
%    - \showprevgraf only counts what will be visible on the current page. It
 
120
%    will be reset to \myprevgraf after the pagebreak.
 
121
%
 
122
% 7. Question: What do you do to \deadcycles?
 
123
%    Answer: \deadcycles is advanced every time an \output routine has
 
124
%    re-inserted \box255 into the recent contributions. We have to do this for
 
125
%    every line and display math. Therefore, we are restricted to
 
126
%    \maxdeadcycles lines or displays :-(
 
127
%    To avoid this, we cheat the counting of deadcycles and re-advance
 
128
%    \deadcycles by -1. Please, be careful with this hack!
 
129
% }}}
 
130
\def\setshowprevgraf#1{%
 
131
  % \futurecost will be the cost in the next step (TeXBook, p.111)
 
132
  \futurecost=#1
 
133
  \advance\futurecost by\outputpenalty
 
134
  % redo Knuth's formula for pagebreaking: futurecost (is the penalty), badness and insertpenalties
 
135
  \ifnum\insertpenalties<10000
 
136
      \ifnum\futurecost<-9999
 
137
      \else\ifnum\futurecost<10000
 
138
          \ifnum\badness<10000
 
139
              \advance\futurecost by\badness
 
140
          \else\ifnum\badness=10000
 
141
              \futurecost=100000
 
142
          \else
 
143
              \futurecost=10000000 % infinity
 
144
          \fi\fi
 
145
      \else
 
146
          \futurecost=10000 % this case is not in Knuth's formula !??
 
147
      \fi\fi
 
148
  \else
 
149
      \futurecost=10000000 % infinity
 
150
  \fi
 
151
  % track the leastcost up to now and
 
152
  % set showprevgraf to the current value of myprevgraf
 
153
  \ifnum\futurecost>\leastcost\else
 
154
    \global\leastcost=\futurecost
 
155
    \global\showprevgraf=\myprevgraf
 
156
  \fi
 
157
  % show some debugging info
 
158
  \inform
 
159
}
 
160
\def\inform{\ifverbose\immediate\write16{%
 
161
  \space myprevgraf=\the\myprevgraf
 
162
  \space showprevgraf=\the\showprevgraf
 
163
  \space futurecost=\the\futurecost
 
164
  \space leastcost=\the\leastcost}\fi
 
165
}
 
166
% at the end of all input we will need \showprevgraf to be \myprevgraf
 
167
% \supereject is called by \bye
 
168
% and explicitly by the textboxes() method
 
169
\edef\savesupereject{\supereject}
 
170
\def\supereject{\global\showprevgraf=\myprevgraf\savesupereject}
 
171
% save whatever someone said to be the output routine
 
172
%   \plainoutput uses \makeheadline and \makefootline
 
173
\newtoks\saveoutput
 
174
\def\makeheadline{}
 
175
\def\makefootline{}
 
176
\saveoutput=\expandafter{\the\output}
 
177
\def\linemarker{\PyXMarker{start@\the\parno@\the\myprevgraf}}
 
178
\output={%
 
179
  \tempcnt=\deadcycles \advance\tempcnt by-1 \deadcycles=\tempcnt%
 
180
  \razor=-50000
 
181
  \ifnum\outputpenalty>\razor
 
182
    %%%%%%%%%% End of the page %%%%%%%%%%
 
183
    \immediate\write16{PyXVariableBox:page=\the\pageno,par=\the\parno,prevgraf=\the\showprevgraf:}%
 
184
    % reset showprevgraf
 
185
    \global\showprevgraf=\myprevgraf
 
186
    \tempcnt=\deadcycles \advance\tempcnt by 1 \deadcycles=\tempcnt
 
187
    % set the outputtype
 
188
%    \global\outputtype=0 % this has no outputtype!! Otherwise, the outputtype of the last page is lost
 
189
%    e.g. <textline> <pagebreak> <textline> <display> makes
 
190
%    <\interlinepenalty (1)> <pagebreak (!!! not 0!!!)>  <\predisplaypenalty (should be 5, not 2)>
 
191
    % after the page has been shipped out, we need a new leastcost
 
192
    \global\leastcost=10000000
 
193
    % do whatever someone told to be the output routine
 
194
    \the\saveoutput
 
195
    % and change the \hsize and \vsize
 
196
    \cdr\lovsizes \cdr\lohsizes
 
197
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
 
198
    %%%%%%%%%% InterLinePenalty: -100000 %%%%%%%%%%
 
199
    \ifverbose\immediate\write16{******** InterLinePenalty ********}\fi
 
200
    \global\advance\myprevgraf by 1
 
201
    % this will be the cost in the next page break finding:
 
202
    \setshowprevgraf{100000}
 
203
    % set the outputtype
 
204
    \global\outputtype=1
 
205
    % and re-inject the whole page with the original penalty
 
206
    \unvbox255
 
207
    \linemarker
 
208
%    \setbox0=\lastbox%
 
209
%    \setbox0=\hbox to \the\wd0{\PyXMarker{start@\the\parno@\the\myprevgraf}%
 
210
%                               \unhbox0%
 
211
%                               \PyXMarker{end@\the\parno@\the\myprevgraf}}%
 
212
%    \nointerlineskip\box0%
 
213
    \advance\outputpenalty by 100000 \penalty\outputpenalty
 
214
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
 
215
    %%%%%%%%%% PreDisplayPenalty: -200000 %%%%%%%%%%
 
216
    \ifverbose\immediate\write16{******** PreDisplayPenalty ********}\fi
 
217
    \ifnum\outputtype=1
 
218
      \global\advance\myprevgraf by 1 % this is for the last preceding text line
 
219
      \global\outputtype=5
 
220
      % this will be the cost in the next page break finding:
 
221
      \setshowprevgraf{200000}
 
222
    \else\ifnum\outputtype=4
 
223
      \global\advance\myprevgraf by 1 % this is for the first line of the current par
 
224
      % which has no interlinepenalty
 
225
      \global\outputtype=2
 
226
      % this will be the cost in the next page break finding:
 
227
      \setshowprevgraf{200000}
 
228
    \else
 
229
      \global\outputtype=2
 
230
      \def\linemarker{}
 
231
    \fi\fi
 
232
    % and re-inject the whole page with the original penalty
 
233
    \unvbox255
 
234
    \linemarker
 
235
    \advance\outputpenalty by 200000 \penalty\outputpenalty
 
236
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
 
237
    %%%%%%%%%% PostDisplayPenalty: -300000 %%%%%%%%%%
 
238
    \ifverbose\immediate\write16{******** PostDisplayPenalty ********}\fi
 
239
    \global\advance\myprevgraf by 3 % all prevgraf for the display comes here, not in PreDisplayPenalty
 
240
    % this will be the cost in the next page break finding:
 
241
    \setshowprevgraf{300000}
 
242
    % set the outputtype
 
243
    \global\outputtype=3
 
244
    % and re-inject the whole page with the original penalty
 
245
    \unvbox255
 
246
    \linemarker
 
247
    \advance\outputpenalty by 300000 \penalty\outputpenalty
 
248
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
 
249
    %%%%%%%%%% end of the paragraph: \penalty-400000 %%%%%%%%%%
 
250
    \ifverbose\immediate\write16{******** Penalty ********}\fi
 
251
    \global\advance\myprevgraf by 1
 
252
    % this will be the cost in the next page break finding:
 
253
    \setshowprevgraf{400000}
 
254
    \global\outputtype=4
 
255
    % and re-inject the whole page with the original penalty
 
256
    \unvbox255
 
257
    \linemarker
 
258
    \advance\outputpenalty by 400000 \penalty\outputpenalty
 
259
  \else
 
260
    %%%%%%%%%% some stuff unknown to us %%%%%%%%%%
 
261
    \immediate\write16{******** VEEEEEEERY negative value of outputpenalty: ERROR? ********}%
 
262
    \unvbox255
 
263
    \tempcnt=\deadcycles\advance\tempcnt by 1 \deadcycles=\tempcnt
 
264
  \fi\fi\fi\fi\fi}
 
265
% }}}
 
266
%
 
267
% We have to reset certain things at the beginning of {{{
 
268
% every paragraph: Hook into it with \everypar
 
269
\newtoks\saveeverypar
 
270
\saveeverypar=\expandafter{\the\everypar}
 
271
\everypar={%
 
272
  \global\advance\parno by 1
 
273
  \global\myprevgraf=0
 
274
  \global\showprevgraf=0
 
275
%  \global\leastcost=10000000
 
276
  % check if the following paragraph will need a \parshape
 
277
  % if yes, say the first token of \parshapes
 
278
  % if no, restore the parno number into \parnos.
 
279
  % This has to come in \everypar to avoid content after the last \par
 
280
  \tempcnt=\numcdr\parnos
 
281
  \ifnum\tempcnt=\parno \cdr\parshapes
 
282
  \else \numconcat\tempcnt\parnos
 
283
  \fi
 
284
  %PAR--\the\parno--%
 
285
  \the\saveeverypar}
 
286
% }}}
 
287
%
 
288
% \par calls the pagebuilder and \output {{{
 
289
% We wrap the \par primitive
 
290
%  - set \interlinepenalty first and reset it afterwards
 
291
%  - call \output another time for the last line of the paragraph
 
292
\let\savepar\par
 
293
\def\par{%
 
294
  \ifvmode\savepar\else\ifinner\savepar\else
 
295
%    \global\leastcost=10000000
 
296
    \advance\interlinepenalty by -100000
 
297
    \vadjust{\penalty-400000}%
 
298
    \savepar
 
299
    \advance\interlinepenalty by 100000
 
300
  \fi\fi}
 
301
% }}}
 
302
%
 
303
% $$ also calls the pagebuilder and \output {{{
 
304
% We wrap these characters with newly defined commands
 
305
% \display and \enddisplay
 
306
% XXX Can $ be redefined to achieve the same result?
 
307
%  - $$ (begin) calls the pagebuilder for the previous text
 
308
%    we have to do similar things as in \par
 
309
%  - $$ (end) calls the pagebuilder for the display math
 
310
%    we have to adjust \predisplaypenalty and \postdisplaypenalty
 
311
% XXX Has \interdisplaylinepenalty any effect on \prevgraf ?
 
312
\def\display{%
 
313
%  \global\leastcost=10000000
 
314
  \global\advance\interlinepenalty by -100000
 
315
  $$%
 
316
  \global\advance\interlinepenalty by 100000\relax}
 
317
\def\enddisplay{%
 
318
%  \global\leastcost=10000000
 
319
  \global\advance\predisplaypenalty by -200000
 
320
  \global\advance\postdisplaypenalty by -300000
 
321
  $$%
 
322
  \global\advance\predisplaypenalty by 200000
 
323
  \global\advance\postdisplaypenalty by 300000\relax}
 
324
% }}}
 
325
%
 
326
% vim:fdm=marker