File: textboxes.tex

package info (click to toggle)
pyx 0.9-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,064 kB
  • ctags: 2,665
  • sloc: python: 15,205; makefile: 142; ansic: 131
file content (326 lines) | stat: -rw-r--r-- 13,663 bytes parent folder | download | duplicates (11)
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
% Modified \output-routine for the use with PyX
% this file makes changes of \hsize and \vsizes possible after
% every pagebreak
%
% Copyright (C) 2004 Michael Schindler <m-schindler@sourceforge.net>
%
% This file is part of PyX (http://pyx.sourceforge.net/).
%
% PyX is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% PyX is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with PyX; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
%
%
\newtoks\lovsizes
\newtoks\lohsizes
\newtoks\parnos
\newtoks\parshapes
%
% Please note that all four tokenlists have to end with {\relax}
% This is needed for correct shortening
%
%%%%%%%%%% TeX's part %%%%%%%%%%
\newif\ifverbose \verbosefalse
\newcount\tempcnt
\newcount\parno \parno=1
\newcount\myprevgraf \myprevgraf=0
\newcount\showprevgraf \showprevgraf=0
\newcount\outputtype \outputtype=0
\newcount\razor
\newcount\leastcost \leastcost=10000000
\newcount\futurecost
%
% Tools for splitting and merging tokenlists after their first element {{{
% did I learn too much lisp or what?
\def\cdr#1{\expandafter\precdr\expandafter#1\the#1@}
\def\numcdr#1{\expandafter\prenumcdr\expandafter#1\the#1@}
\def\numconcat#1#2{\edef\foo{{\the#1}\the#2}\global#2=\expandafter{\foo}}
%
\def\precdr#1#2#3@{\ifx#2\relax\relax\global#1={\relax}\else#2\global#1={#3}\fi}
\def\prenumcdr#1#2#3@{\ifx\relax#2 0\global#1={\relax}\else#2\global#1={#3}\fi}
% }}}
%
% The output routine {{{
% Documentation {{{
% 1. Question: Who calls the pagebuilder and \output?
%    Answer: Only \par and $$ (as far as I have read the TeXbook)
%
% 2. Question: So, all together: What is to be done?
%    Answer: We have to simulate the work of the linebuilder that makes
%    paragraphs and math into lines in order to find out, what value \prevgraf
%    might have at a pagepreak. Then, we change the \hsize and \vsize at the
%    pagepreak and inform PyX about the value of \prevgraf.
%
% 3. Question: When is \prevgraf advanced?
%    Answer: At every line by 1 and at every display math by 3
%
% 4. Question: How can we hook into the pagebuilding mechanism to find out
%    about lines and displays?
%    Answer: We get into the pagebuilder that splits vertical lists into pages
%    if we enforce a penalty of less than -10000. There are three built-in
%    hooks: \interlinepenalty
%           \predisplaypenalty
%           \postdisplaypenalty
%    These are set to values less than -10000 by wrapping \par and $$, the
%    ones who call the pagebuilder and, therefore, \output
%
%    Unfortunately, we get only "breaks", but we are interested in lines. At
%    each list, we have one break less than lines. So, we have to add another
%    call of \output at the end of a paragraph. This is done by an explicit
%           \penalty
%    A display math succeeding some text also calls the pagebuilder. We have
%    to add another line in such situations. This is done in the output
%    routine while processing \predisplaypenalty.
%
% 5. Question: Why are there so many \ifnum s in the output routine?
%    Answer: As explained avove, we have to do different things at different
%    positions of our text. \interlinepenalty and the \penalty for paragraph
%    endings have to add a line. \postdisplaypenalty has to add the display
%    (advances \prevgraf by 3), while \predisplaypenalty may still reside on
%    the previous page, while the display math has moved to the next one.
%    Therefore, it does not contribute to the \prevgraf. Nevertheless, if
%    there was some text before the display math in the same paragraph, we
%    still have to add the last line of text!
%
%    This is the reason for the whole \outputtype business:
%    We have to show a \prevgraf value different to \myprevgraf at a situation
%    where an \interlinepenalty is followed by a \predisplaypenalty which is
%    followed by a pagebreak. The display is on the next page.
%    The same can -- of course -- also occur with a \predisplaypenalty
%    following a \penalty caused by \par
%
% 6. Question: What the hell does \leastcost do?
%    Answer: This is a tricky point. We hooked into the pagebuilding mechanism
%    by changing penalties. In this case, TeX thinks, there is a very good
%    pagebreak and calls \output. But \output removes the strongly negative
%    penalty we added. Now, TeX has to reconsider the pagebreak and may come
%    to the result that some of the lines that have appeared as perfect
%    pagebreaks are not so perfect...
%    Therefore, before we re-inject the whole vertical list and remove the
%    negative penalty by saying
%       \unvbox255 \advance\outputpenalty by XXXXXX \penalty\outputpenalty
%    we have to know in advance, what the pagebuilder will think of the
%    pagebreak in the next run. See the TeXbook, p. 111 for the correct
%    formula.
%
%    This is the reason for \showprevgraf. We have two counters:
%    - \myprevgraf counts real lines and displays. This keeps us up-to-date
%      with the paragraph all the time
%    - \showprevgraf only counts what will be visible on the current page. It
%    will be reset to \myprevgraf after the pagebreak.
%
% 7. Question: What do you do to \deadcycles?
%    Answer: \deadcycles is advanced every time an \output routine has
%    re-inserted \box255 into the recent contributions. We have to do this for
%    every line and display math. Therefore, we are restricted to
%    \maxdeadcycles lines or displays :-(
%    To avoid this, we cheat the counting of deadcycles and re-advance
%    \deadcycles by -1. Please, be careful with this hack!
% }}}
\def\setshowprevgraf#1{%
  % \futurecost will be the cost in the next step (TeXBook, p.111)
  \futurecost=#1
  \advance\futurecost by\outputpenalty
  % redo Knuth's formula for pagebreaking: futurecost (is the penalty), badness and insertpenalties
  \ifnum\insertpenalties<10000
      \ifnum\futurecost<-9999
      \else\ifnum\futurecost<10000
          \ifnum\badness<10000
              \advance\futurecost by\badness
          \else\ifnum\badness=10000
              \futurecost=100000
          \else
              \futurecost=10000000 % infinity
          \fi\fi
      \else
          \futurecost=10000 % this case is not in Knuth's formula !??
      \fi\fi
  \else
      \futurecost=10000000 % infinity
  \fi
  % track the leastcost up to now and
  % set showprevgraf to the current value of myprevgraf
  \ifnum\futurecost>\leastcost\else
    \global\leastcost=\futurecost
    \global\showprevgraf=\myprevgraf
  \fi
  % show some debugging info
  \inform
}
\def\inform{\ifverbose\immediate\write16{%
  \space myprevgraf=\the\myprevgraf
  \space showprevgraf=\the\showprevgraf
  \space futurecost=\the\futurecost
  \space leastcost=\the\leastcost}\fi
}
% at the end of all input we will need \showprevgraf to be \myprevgraf
% \supereject is called by \bye
% and explicitly by the textboxes() method
\edef\savesupereject{\supereject}
\def\supereject{\global\showprevgraf=\myprevgraf\savesupereject}
% save whatever someone said to be the output routine
%   \plainoutput uses \makeheadline and \makefootline
\newtoks\saveoutput
\def\makeheadline{}
\def\makefootline{}
\saveoutput=\expandafter{\the\output}
\def\linemarker{\PyXMarker{start@\the\parno@\the\myprevgraf}}
\output={%
  \tempcnt=\deadcycles \advance\tempcnt by-1 \deadcycles=\tempcnt%
  \razor=-50000
  \ifnum\outputpenalty>\razor
    %%%%%%%%%% End of the page %%%%%%%%%%
    \immediate\write16{PyXVariableBox:page=\the\pageno,par=\the\parno,prevgraf=\the\showprevgraf:}%
    % reset showprevgraf
    \global\showprevgraf=\myprevgraf
    \tempcnt=\deadcycles \advance\tempcnt by 1 \deadcycles=\tempcnt
    % set the outputtype
%    \global\outputtype=0 % this has no outputtype!! Otherwise, the outputtype of the last page is lost
%    e.g. <textline> <pagebreak> <textline> <display> makes
%    <\interlinepenalty (1)> <pagebreak (!!! not 0!!!)>  <\predisplaypenalty (should be 5, not 2)>
    % after the page has been shipped out, we need a new leastcost
    \global\leastcost=10000000
    % do whatever someone told to be the output routine
    \the\saveoutput
    % and change the \hsize and \vsize
    \cdr\lovsizes \cdr\lohsizes
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
    %%%%%%%%%% InterLinePenalty: -100000 %%%%%%%%%%
    \ifverbose\immediate\write16{******** InterLinePenalty ********}\fi
    \global\advance\myprevgraf by 1
    % this will be the cost in the next page break finding:
    \setshowprevgraf{100000}
    % set the outputtype
    \global\outputtype=1
    % and re-inject the whole page with the original penalty
    \unvbox255
    \linemarker
%    \setbox0=\lastbox%
%    \setbox0=\hbox to \the\wd0{\PyXMarker{start@\the\parno@\the\myprevgraf}%
%                               \unhbox0%
%                               \PyXMarker{end@\the\parno@\the\myprevgraf}}%
%    \nointerlineskip\box0%
    \advance\outputpenalty by 100000 \penalty\outputpenalty
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
    %%%%%%%%%% PreDisplayPenalty: -200000 %%%%%%%%%%
    \ifverbose\immediate\write16{******** PreDisplayPenalty ********}\fi
    \ifnum\outputtype=1
      \global\advance\myprevgraf by 1 % this is for the last preceding text line
      \global\outputtype=5
      % this will be the cost in the next page break finding:
      \setshowprevgraf{200000}
    \else\ifnum\outputtype=4
      \global\advance\myprevgraf by 1 % this is for the first line of the current par
      % which has no interlinepenalty
      \global\outputtype=2
      % this will be the cost in the next page break finding:
      \setshowprevgraf{200000}
    \else
      \global\outputtype=2
      \def\linemarker{}
    \fi\fi
    % and re-inject the whole page with the original penalty
    \unvbox255
    \linemarker
    \advance\outputpenalty by 200000 \penalty\outputpenalty
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
    %%%%%%%%%% PostDisplayPenalty: -300000 %%%%%%%%%%
    \ifverbose\immediate\write16{******** PostDisplayPenalty ********}\fi
    \global\advance\myprevgraf by 3 % all prevgraf for the display comes here, not in PreDisplayPenalty
    % this will be the cost in the next page break finding:
    \setshowprevgraf{300000}
    % set the outputtype
    \global\outputtype=3
    % and re-inject the whole page with the original penalty
    \unvbox255
    \linemarker
    \advance\outputpenalty by 300000 \penalty\outputpenalty
  \else\advance\razor by -100000 \ifnum\outputpenalty>\razor
    %%%%%%%%%% end of the paragraph: \penalty-400000 %%%%%%%%%%
    \ifverbose\immediate\write16{******** Penalty ********}\fi
    \global\advance\myprevgraf by 1
    % this will be the cost in the next page break finding:
    \setshowprevgraf{400000}
    \global\outputtype=4
    % and re-inject the whole page with the original penalty
    \unvbox255
    \linemarker
    \advance\outputpenalty by 400000 \penalty\outputpenalty
  \else
    %%%%%%%%%% some stuff unknown to us %%%%%%%%%%
    \immediate\write16{******** VEEEEEEERY negative value of outputpenalty: ERROR? ********}%
    \unvbox255
    \tempcnt=\deadcycles\advance\tempcnt by 1 \deadcycles=\tempcnt
  \fi\fi\fi\fi\fi}
% }}}
%
% We have to reset certain things at the beginning of {{{
% every paragraph: Hook into it with \everypar
\newtoks\saveeverypar
\saveeverypar=\expandafter{\the\everypar}
\everypar={%
  \global\advance\parno by 1
  \global\myprevgraf=0
  \global\showprevgraf=0
%  \global\leastcost=10000000
  % check if the following paragraph will need a \parshape
  % if yes, say the first token of \parshapes
  % if no, restore the parno number into \parnos.
  % This has to come in \everypar to avoid content after the last \par
  \tempcnt=\numcdr\parnos
  \ifnum\tempcnt=\parno \cdr\parshapes
  \else \numconcat\tempcnt\parnos
  \fi
  %PAR--\the\parno--%
  \the\saveeverypar}
% }}}
%
% \par calls the pagebuilder and \output {{{
% We wrap the \par primitive
%  - set \interlinepenalty first and reset it afterwards
%  - call \output another time for the last line of the paragraph
\let\savepar\par
\def\par{%
  \ifvmode\savepar\else\ifinner\savepar\else
%    \global\leastcost=10000000
    \advance\interlinepenalty by -100000
    \vadjust{\penalty-400000}%
    \savepar
    \advance\interlinepenalty by 100000
  \fi\fi}
% }}}
%
% $$ also calls the pagebuilder and \output {{{
% We wrap these characters with newly defined commands
% \display and \enddisplay
% XXX Can $ be redefined to achieve the same result?
%  - $$ (begin) calls the pagebuilder for the previous text
%    we have to do similar things as in \par
%  - $$ (end) calls the pagebuilder for the display math
%    we have to adjust \predisplaypenalty and \postdisplaypenalty
% XXX Has \interdisplaylinepenalty any effect on \prevgraf ?
\def\display{%
%  \global\leastcost=10000000
  \global\advance\interlinepenalty by -100000
  $$%
  \global\advance\interlinepenalty by 100000\relax}
\def\enddisplay{%
%  \global\leastcost=10000000
  \global\advance\predisplaypenalty by -200000
  \global\advance\postdisplaypenalty by -300000
  $$%
  \global\advance\predisplaypenalty by 200000
  \global\advance\postdisplaypenalty by 300000\relax}
% }}}
%
% vim:fdm=marker