boundary nodes made consistent (cleanup and document): WARNING: bump the format numbe...
[luatex.git] / source / texk / web2c / luatexdir / tex / linebreak.w
blob6e74e0b27becf2aa33e959126e5b1c8b12ec7eb9
1 % linebreak.w
3 % Copyright 2006-2008 Taco Hoekwater <taco@@luatex.org>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software; you can redistribute it and/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation; either version 2 of the License, or (at your
10 % option) any later version.
12 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20 @ @c
22 #include "ptexlib.h"
24 @ We come now to what is probably the most interesting algorithm of \TeX:
25 the mechanism for choosing the ``best possible'' breakpoints that yield
26 the individual lines of a paragraph. \TeX's line-breaking algorithm takes
27 a given horizontal list and converts it to a sequence of boxes that are
28 appended to the current vertical list. In the course of doing this, it
29 creates a special data structure containing three kinds of records that are
30 not used elsewhere in \TeX. Such nodes are created while a paragraph is
31 being processed, and they are destroyed afterwards; thus, the other parts
32 of \TeX\ do not need to know anything about how line-breaking is done.
34 The method used here is based on an approach devised by Michael F. Plass and
35 @^Plass, Michael Frederick@>
36 @^Knuth, Donald Ervin@>
37 the author in 1977, subsequently generalized and improved by the same two
38 people in 1980. A detailed discussion appears in {\sl SOFTWARE---Practice
39 \AM\ Experience \bf11} (1981), 1119--1184, where it is shown that the
40 line-breaking problem can be regarded as a special case of the problem of
41 computing the shortest path in an acyclic network. The cited paper includes
42 numerous examples and describes the history of line breaking as it has been
43 practiced by printers through the ages. The present implementation adds two
44 new ideas to the algorithm of 1980: Memory space requirements are considerably
45 reduced by using smaller records for inactive nodes than for active ones,
46 and arithmetic overflow is avoided by using ``delta distances'' instead of
47 keeping track of the total distance from the beginning of the paragraph to the
48 current point.
50 The |line_break| procedure should be invoked only in horizontal mode; it
51 leaves that mode and places its output into the current vlist of the
52 enclosing vertical mode (or internal vertical mode).
53 There is one explicit parameter: |d| is true for partial paragraphs
54 preceding display math mode; in this case the amount of additional
55 penalty inserted before the final line is |display_widow_penalty|
56 instead of |widow_penalty|.
58 There are also a number of implicit parameters: The hlist to be broken
59 starts at |vlink(head)|, and it is nonempty. The value of |prev_graf| in the
60 enclosing semantic level tells where the paragraph should begin in the
61 sequence of line numbers, in case hanging indentation or \.{\\parshape}
62 are in use; |prev_graf| is zero unless this paragraph is being continued
63 after a displayed formula. Other implicit parameters, such as the
64 |par_shape_ptr| and various penalties to use for hyphenation, etc., appear
65 in |eqtb|.
67 After |line_break| has acted, it will have updated the current vlist and the
68 value of |prev_graf|. Furthermore, the global variable |just_box| will
69 point to the final box created by |line_break|, so that the width of this
70 line can be ascertained when it is necessary to decide whether to use
71 |above_display_skip| or |above_display_short_skip| before a displayed formula.
74 halfword just_box; /* the |hlist_node| for the last line of the new paragraph */
76 @ In it's complete form, |line_break| is a rather lengthy
77 procedure---sort of a small world unto itself---we must build it up
78 little by little. Below you see only the general outline.
80 The main task performed here is to move the list from |head| to
81 |temp_head| and go into the enclosing semantic level. We also append
82 the \.{\\parfillskip} glue to the end of the paragraph, removing a
83 space (or other glue node) if it was there, since spaces usually
84 precede blank lines and instances of `\.{\$\$}'. The |par_fill_skip|
85 is preceded by an infinite penalty, so it will never be considered as
86 a potential breakpoint.
88 That code assumes that a |glue_node| and a |penalty_node| occupy the
89 same number of |mem|~words.
90 @^data structure assumptions@>
92 Most other processing is delegated to external functions.
95 void line_break(boolean d, int line_break_context)
97 int paragraph_dir = 0; /* main direction of paragraph */
98 halfword final_par_glue;
99 halfword start_of_par;
100 int callback_id;
101 pack_begin_line = cur_list.ml_field; /* this is for over/underfull box messages */
102 alink(temp_head) = null; /* hh-ls */
103 vlink(temp_head) = vlink(cur_list.head_field);
104 new_hyphenation(temp_head, cur_list.tail_field);
105 cur_list.tail_field = new_ligkern(temp_head, cur_list.tail_field);
106 if (is_char_node(cur_list.tail_field)) {
107 tail_append(new_penalty(inf_penalty));
108 } else if (type(cur_list.tail_field) != glue_node) {
109 tail_append(new_penalty(inf_penalty));
110 } else {
111 halfword t = alink(cur_list.tail_field);
112 flush_node(cur_list.tail_field);
113 cur_list.tail_field = t;
114 tail_append(new_penalty(inf_penalty));
116 final_par_glue = new_param_glue(par_fill_skip_code);
117 couple_nodes(cur_list.tail_field, final_par_glue);
118 cur_list.tail_field = vlink(cur_list.tail_field);
119 lua_node_filter(pre_linebreak_filter_callback,
120 line_break_context, temp_head,
121 addressof(cur_list.tail_field));
122 last_line_fill = cur_list.tail_field;
123 pop_nest();
124 start_of_par = cur_list.tail_field;
125 callback_id = callback_defined(linebreak_filter_callback);
126 if (callback_id > 0) {
127 callback_id = lua_linebreak_callback(d, temp_head, addressof(cur_list.tail_field));
128 if (callback_id > 0) {
129 /* find the correct value for the |just_box| */
130 halfword box_search = cur_list.tail_field;
131 just_box = null;
132 if (box_search != null) {
133 do {
134 if (type(box_search) == hlist_node) {
135 just_box = box_search;
137 box_search = vlink(box_search);
138 } while (box_search != null);
140 if (just_box == null) {
141 help3
142 ("A linebreaking routine should return a non-empty list of nodes",
143 "and at least one of those has to be a \\hbox.",
144 "Sorry, I cannot recover from this.");
145 print_err("Invalid linebreak_filter");
146 succumb();
148 } else {
149 if (int_par(tracing_paragraphs_code) > 0) {
150 begin_diagnostic();
151 print_int(line);
152 end_diagnostic(true);
156 if (callback_id == 0) {
157 if ((!is_char_node(vlink(temp_head))) && ((type(vlink(temp_head)) == local_par_node))) {
158 paragraph_dir = local_par_dir(vlink(temp_head));
159 } else {
160 confusion("weird par dir"); /* assert(0); */ /* |paragraph_dir = 0|; */
162 ext_do_line_break(paragraph_dir,
163 int_par(pretolerance_code),
164 int_par(tracing_paragraphs_code),
165 int_par(tolerance_code),
166 dimen_par(emergency_stretch_code),
167 int_par(looseness_code),
168 int_par(adjust_spacing_code),
169 equiv(par_shape_loc),
170 int_par(adj_demerits_code),
171 int_par(protrude_chars_code),
172 int_par(line_penalty_code),
173 int_par(last_line_fit_code),
174 int_par(double_hyphen_demerits_code),
175 int_par(final_hyphen_demerits_code),
176 dimen_par(hang_indent_code),
177 dimen_par(hsize_code),
178 int_par(hang_after_code),
179 glue_par(left_skip_code),
180 glue_par(right_skip_code),
181 equiv(inter_line_penalties_loc),
182 int_par(inter_line_penalty_code),
183 int_par(club_penalty_code),
184 equiv(club_penalties_loc),
185 (d ? equiv(display_widow_penalties_loc) : equiv(widow_penalties_loc)),
186 (d ? int_par(display_widow_penalty_code) : int_par(widow_penalty_code)),
187 int_par(broken_penalty_code),
188 final_par_glue);
190 lua_node_filter(post_linebreak_filter_callback,
191 line_break_context, start_of_par,
192 addressof(cur_list.tail_field));
193 pack_begin_line = 0;
196 @ Glue nodes in a horizontal list that is being paragraphed are not supposed to
197 include ``infinite'' shrinkability; that is why the algorithm maintains
198 four registers for stretching but only one for shrinking. If the user tries to
199 introduce infinite shrinkability, the shrinkability will be reset to finite
200 and an error message will be issued. A boolean variable |no_shrink_error_yet|
201 prevents this error message from appearing more than once per paragraph.
204 #define check_shrinkage(a) \
205 if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \
206 a=finite_shrink((a))
208 static boolean no_shrink_error_yet; /*have we complained about infinite shrinkage? */
210 static halfword finite_shrink(halfword p)
211 { /* recovers from infinite shrinkage */
212 const char *hlp[] = {
213 "The paragraph just ended includes some glue that has",
214 "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
215 "Such glue doesn't belong there---it allows a paragraph",
216 "of any length to fit on one line. But it's safe to proceed,",
217 "since the offensive shrinkability has been made finite.",
218 NULL
220 if (no_shrink_error_yet) {
221 no_shrink_error_yet = false;
222 tex_error("Infinite glue shrinkage found in a paragraph", hlp);
224 shrink_order(p) = normal;
225 return p;
228 @ A pointer variable |cur_p| runs through the given horizontal list as we look
229 for breakpoints. This variable is global, since it is used both by |line_break|
230 and by its subprocedure |try_break|.
232 Another global variable called |threshold| is used to determine the feasibility
233 of individual lines: breakpoints are feasible if there is a way to reach
234 them without creating lines whose badness exceeds |threshold|. (The
235 badness is compared to |threshold| before penalties are added, so that
236 penalty values do not affect the feasibility of breakpoints, except that
237 no break is allowed when the penalty is 10000 or more.) If |threshold|
238 is 10000 or more, all legal breaks are considered feasible, since the
239 |badness| function specified above never returns a value greater than~10000.
241 Up to three passes might be made through the paragraph in an attempt to find at
242 least one set of feasible breakpoints. On the first pass, we have
243 |threshold=pretolerance| and |second_pass=final_pass=false|.
244 If this pass fails to find a
245 feasible solution, |threshold| is set to |tolerance|, |second_pass| is set
246 |true|, and an attempt is made to hyphenate as many words as possible.
247 If that fails too, we add |emergency_stretch| to the background
248 stretchability and set |final_pass=true|.
251 static boolean second_pass; /* is this our second attempt to break this paragraph? */
252 static boolean final_pass; /*is this our final attempt to break this paragraph? */
253 static int threshold; /* maximum badness on feasible lines */
255 /* maximum fill level for |hlist_stack|*/
256 #define max_hlist_stack 512 /* maybe good if larger than |2 *
257 max_quarterword|, so that box nesting
258 level would overflow first */
260 /* stack for |find_protchar_left()| and |find_protchar_right()| */
261 static halfword hlist_stack[max_hlist_stack];
263 /* fill level for |hlist_stack| */
264 static short hlist_stack_level = 0;
266 @ @c
267 static void push_node(halfword p)
269 if (hlist_stack_level >= max_hlist_stack)
270 normal_error("push_node","stack overflow");
271 hlist_stack[hlist_stack_level++] = p;
274 static halfword pop_node(void)
276 if (hlist_stack_level <= 0) /* would point to some bug */
277 normal_error("pop_node","stack underflow (internal error)");
278 return hlist_stack[--hlist_stack_level];
281 @ @c
282 static int max_stretch_ratio = 0; /*maximal stretch ratio of expanded fonts */
283 static int max_shrink_ratio = 0; /*maximal shrink ratio of expanded fonts */
284 static int cur_font_step = 0; /*the current step of expanded fonts */
286 static boolean check_expand_pars(internal_font_number f)
288 int m;
290 if ((font_step(f) == 0)
291 || ((font_max_stretch(f) == 0) && (font_max_shrink(f) == 0)))
292 return false;
293 if (cur_font_step < 0)
294 cur_font_step = font_step(f);
295 else if (cur_font_step != font_step(f))
296 normal_error("font expansion","using fonts with different step of expansion in one paragraph is not allowed");
297 m = font_max_stretch(f);
298 if (m != 0) {
299 if (max_stretch_ratio < 0)
300 max_stretch_ratio = m;
301 else if (max_stretch_ratio != m)
302 normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed");
304 m = font_max_shrink(f);
305 if (m != 0) {
306 if (max_shrink_ratio < 0)
307 max_shrink_ratio = -m;
308 else if (max_shrink_ratio != -m)
309 normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed");
311 return true;
314 @ searches left to right from list head |l|, returns 1st non-skipable item
317 /*public*/ halfword find_protchar_left(halfword l, boolean d)
319 halfword t;
320 boolean run;
321 boolean done = false ;
322 while ((vlink(l) != null) && (type(l) == hlist_node) && zero_dimensions(l) && (list_ptr(l) == null)) {
323 /*for paragraph start with \.{\\parindent} = 0pt or any empty hbox */
324 l = vlink(l);
325 done = true ;
327 if ((!done) && (type(l) == local_par_node)) {
328 l = vlink(l);
329 done = true ;
331 if ((!done) && d) {
332 while ((vlink(l) != null) && (!(is_char_node(l) || non_discardable(l)))) {
333 /* std.\ discardables at line break, \TeX book, p 95 */
334 l = vlink(l);
337 if (type(l) != glyph_node) {
338 hlist_stack_level = 0;
339 run = true;
340 do {
341 t = l;
342 while (run && (type(l) == hlist_node) && (list_ptr(l) != null)) {
343 push_node(l);
344 l = list_ptr(l);
346 while (run && cp_skipable(l)) {
347 while ((vlink(l) == null) && (hlist_stack_level > 0)) {
348 l = pop_node(); /* don't visit this node again */
349 run = false;
351 if ((vlink(l) != null) && (type(l) == boundary_node) && (subtype(l) == protrusion_boundary) &&
352 ((boundary_value(l) == 1) || (boundary_value(l) == 3))) {
353 /* skip next node */
354 l = vlink(l);
356 if (vlink(l) != null) {
357 l = vlink(l);
358 } else if (hlist_stack_level == 0) {
359 run = false;
362 } while (t != l);
364 return l;
367 @ searches right to left from list tail |r| to head |l|, returns 1st non-skipable item
370 /*public*/ halfword find_protchar_right(halfword l, halfword r)
372 halfword t;
373 boolean run = true;
374 if (r == null)
375 return null;
376 hlist_stack_level = 0;
377 do {
378 t = r;
379 while (run && (type(r) == hlist_node) && (list_ptr(r) != null)) {
380 push_node(l);
381 push_node(r);
382 l = list_ptr(r);
383 r = l;
384 while (vlink(r) != null) {
385 halfword s = r;
386 r = vlink(r);
387 alink(r) = s;
390 while (run && cp_skipable(r)) {
391 while ((r == l) && (hlist_stack_level > 0)) {
392 r = pop_node(); /* don't visit this node again */
393 l = pop_node();
395 if ((r != l) && (r != null)) {
396 if ((alink(r) != null) && (type(r) == boundary_node) && (subtype(r) == protrusion_boundary) &&
397 ((boundary_value(r) == 2) || (boundary_value(r) == 3))) {
398 /* skip next node */
399 r = alink(r);
401 if (alink(r) != null) {
402 r = alink(r);
403 } else { /* this is the input: \.{\\leavevmode\\penalty-10000\\penalty-10000} (bug \#268) */
404 run = false;
406 } else if ((r == l) && (hlist_stack_level == 0))
407 run = false;
409 } while (t != r);
410 return r;
413 @ @c
414 #define left_pw(a) char_pw((a), left_side)
415 #define right_pw(a) char_pw((a), right_side)
417 @ When looking for optimal line breaks, \TeX\ creates a ``break node'' for
418 each break that is {\sl feasible}, in the sense that there is a way to end
419 a line at the given place without requiring any line to stretch more than
420 a given tolerance. A break node is characterized by three things: the position
421 of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|,
422 or |disc_node|); the ordinal number of the line that will follow this
423 breakpoint; and the fitness classification of the line that has just
424 ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|.
427 typedef enum {
428 very_loose_fit = 0, /* fitness classification for lines stretching more than
429 their stretchability */
430 loose_fit, /* fitness classification for lines stretching 0.5 to 1.0 of their
431 stretchability */
432 decent_fit, /* fitness classification for all other lines */
433 tight_fit /* fitness classification for lines shrinking 0.5 to 1.0 of their
434 shrinkability */
435 } fitness_value;
438 @ The algorithm essentially determines the best possible way to achieve
439 each feasible combination of position, line, and fitness. Thus, it answers
440 questions like, ``What is the best way to break the opening part of the
441 paragraph so that the fourth line is a tight line ending at such-and-such
442 a place?'' However, the fact that all lines are to be the same length
443 after a certain point makes it possible to regard all sufficiently large
444 line numbers as equivalent, when the looseness parameter is zero, and this
445 makes it possible for the algorithm to save space and time.
447 An ``active node'' and a ``passive node'' are created in |mem| for each
448 feasible breakpoint that needs to be considered. Active nodes are three
449 words long and passive nodes are two words long. We need active nodes only
450 for breakpoints near the place in the paragraph that is currently being
451 examined, so they are recycled within a comparatively short time after
452 they are created.
454 @ An active node for a given breakpoint contains six fields:
456 |vlink| points to the next node in the list of active nodes; the
457 last active node has |vlink=active|.
459 |break_node| points to the passive node associated with this
460 breakpoint.
462 |line_number| is the number of the line that follows this
463 breakpoint.
465 |fitness| is the fitness classification of the line ending at this
466 breakpoint.
468 |type| is either |hyphenated_node| or |unhyphenated_node|, depending on
469 whether this breakpoint is a |disc_node|.
471 |total_demerits| is the minimum possible sum of demerits over all
472 lines leading from the beginning of the paragraph to this breakpoint.
474 The value of |vlink(active)| points to the first active node on a vlinked list
475 of all currently active nodes. This list is in order by |line_number|,
476 except that nodes with |line_number>easy_line| may be in any order relative
477 to each other.
480 void initialize_active(void)
482 type(active) = hyphenated_node;
483 line_number(active) = max_halfword;
484 subtype(active) = 0; /* the |subtype| is never examined */
487 @ The passive node for a given breakpoint contains EIGHT fields:
489 |vlink| points to the passive node created just before this one,
490 if any, otherwise it is |null|.
492 |cur_break| points to the position of this breakpoint in the
493 horizontal list for the paragraph being broken.
495 |prev_break| points to the passive node that should precede this
496 one in an optimal path to this breakpoint.
498 |serial| is equal to |n| if this passive node is the |n|th
499 one created during the current pass. (This field is used only when
500 printing out detailed statistics about the line-breaking calculations.)
502 |passive_pen_inter| holds the current \.{\\localinterlinepenalty}
504 |passive_pen_broken| holds the current \.{\\localbrokenpenalty}
506 There is a global variable called |passive| that points to the most
507 recently created passive node. Another global variable, |printed_node|,
508 is used to help print out the paragraph when detailed information about
509 the line-breaking computation is being displayed.
512 static halfword passive; /* most recent node on passive list */
513 static halfword printed_node; /*most recent node that has been printed */
514 static halfword pass_number; /*the number of passive nodes allocated on this pass */
516 @ The active list also contains ``delta'' nodes that help the algorithm
517 compute the badness of individual lines. Such nodes appear only between two
518 active nodes, and they have |type=delta_node|. If |p| and |r| are active nodes
519 and if |q| is a delta node between them, so that |vlink(p)=q| and |vlink(q)=r|,
520 then |q| tells the space difference between lines in the horizontal list that
521 start after breakpoint |p| and lines that start after breakpoint |r|. In
522 other words, if we know the length of the line that starts after |p| and
523 ends at our current position, then the corresponding length of the line that
524 starts after |r| is obtained by adding the amounts in node~|q|. A delta node
525 contains seven scaled numbers, since it must record the net change in glue
526 stretchability with respect to all orders of infinity. The natural width
527 difference appears in |mem[q+1].sc|; the stretch differences in units of
528 pt, sfi, fil, fill, and filll appear in |mem[q+2..q+6].sc|; and the shrink
529 difference appears in |mem[q+7].sc|. The |subtype| field of a delta node
530 is not used.
532 Actually, we have two more fields that are used by |pdftex|.
534 As the algorithm runs, it maintains a set of seven delta-like registers
535 for the length of the line following the first active breakpoint to the
536 current position in the given hlist. When it makes a pass through the
537 active list, it also maintains a similar set of seven registers for the
538 length following the active breakpoint of current interest. A third set
539 holds the length of an empty line (namely, the sum of \.{\\leftskip} and
540 \.{\\rightskip}); and a fourth set is used to create new delta nodes.
542 When we pass a delta node we want to do operations like
543 $$\hbox{\ignorespaces|for
544 k:=1 to 7 do cur_active_width[k]:=cur_active_width[k]+mem[q+k].sc|};$$ and we
545 want to do this without the overhead of |for| loops. The |do_all_six|
546 macro makes such six-tuples convenient.
549 static scaled active_width[10] = { 0 }; /*distance from first active node to~|cur_p| */
550 static scaled background[10] = { 0 }; /*length of an ``empty'' line */
551 static scaled break_width[10] = { 0 }; /*length being computed after current break */
553 static boolean auto_breaking; /*make |auto_breaking| accessible out of |line_break| */
555 @ Let's state the principles of the delta nodes more precisely and concisely,
556 so that the following programs will be less obscure. For each legal
557 breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and
558 $\beta(p)$ such that the length of material in a line from breakpoint~|p|
559 to breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$.
560 Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from
561 the beginning of the paragraph to a point ``after'' a break at |p| and to a
562 point ``before'' a break at |q|; and $\gamma$ is the width of an empty line,
563 namely the length contributed by \.{\\leftskip} and \.{\\rightskip}.
565 Suppose, for example, that the paragraph consists entirely of alternating
566 boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and
567 let the skips have widths $y_1\ldots y_n$, so that the paragraph can be
568 represented by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint
569 at $y_i$; then $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)=
570 x_1+y_1+\cdots+x_i$. To check this, note that the length of material from
571 $p_2$ to $p_5$, say, is $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5)
572 -\alpha(p_2)$.
574 The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and
575 shrinkability as well as a natural width. If we were to compute $\alpha(p)$
576 and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and
577 the multiprecise numbers would have to be kept in the active nodes.
578 \TeX\ avoids this problem by working entirely with relative differences
579 or ``deltas.'' Suppose, for example, that the active list contains
580 $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints
581 and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$
582 and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is
583 currently positioned at some other breakpoint |p|, the |active_width| array
584 contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through
585 the list of active nodes and considering a tentative line that runs from
586 $a_2$ to~|p|, say, the |cur_active_width| array will contain the value
587 $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$,
588 we want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this
589 is just $\delta_2$, which appears in the active list between $a_2$ and
590 $a_3$. The |background| array contains $\gamma$. The |break_width| array
591 will be used to calculate values of new delta nodes when the active
592 list is being updated.
594 @ The heart of the line-breaking procedure is `|try_break|', a subroutine
595 that tests if the current breakpoint |cur_p| is feasible, by running
596 through the active list to see what lines of text can be made from active
597 nodes to~|cur_p|. If feasible breaks are possible, new break nodes are
598 created. If |cur_p| is too far from an active node, that node is
599 deactivated.
601 The parameter |pi| to |try_break| is the penalty associated
602 with a break at |cur_p|; we have |pi=eject_penalty| if the break is forced,
603 and |pi=inf_penalty| if the break is illegal.
605 The other parameter, |break_type|, is set to |hyphenated_node| or |unhyphenated_node|,
606 depending on whether or not the current break is at a |disc_node|. The
607 end of a paragraph is also regarded as `|hyphenated_node|'; this case is
608 distinguishable by the condition |cur_p=null|.
611 static int internal_pen_inter; /* running \.{\\localinterlinepenalty} */
612 static int internal_pen_broken; /* running \.{\\localbrokenpenalty} */
613 static halfword internal_left_box; /* running \.{\\localleftbox} */
614 static int internal_left_box_width; /* running \.{\\localleftbox} width */
615 static halfword init_internal_left_box; /* running \.{\\localleftbox} */
616 static int init_internal_left_box_width; /* running \.{\\localleftbox} width */
617 static halfword internal_right_box; /* running \.{\\localrightbox} */
618 static int internal_right_box_width; /* running \.{\\localrightbox} width */
620 static scaled disc_width[10] = { 0 }; /* the length of discretionary material preceding a break */
622 @ As we consider various ways to end a line at |cur_p|, in a given line number
623 class, we keep track of the best total demerits known, in an array with
624 one entry for each of the fitness classifications. For example,
625 |minimal_demerits[tight_fit]| contains the fewest total demerits of feasible
626 line breaks ending at |cur_p| with a |tight_fit| line; |best_place[tight_fit]|
627 points to the passive node for the break before~|cur_p| that achieves such
628 an optimum; and |best_pl_line[tight_fit]| is the |line_number| field in the
629 active node corresponding to |best_place[tight_fit]|. When no feasible break
630 sequence is known, the |minimal_demerits| entries will be equal to
631 |awful_bad|, which is $2^{30}-1$. Another variable, |minimum_demerits|,
632 keeps track of the smallest value in the |minimal_demerits| array.
635 static int minimal_demerits[4]; /* best total demerits known for current
636 line class and position, given the fitness */
637 static int minimum_demerits; /* best total demerits known for current line class
638 and position */
639 static halfword best_place[4]; /* how to achieve |minimal_demerits| */
640 static halfword best_pl_line[4]; /*corresponding line number */
642 @ The length of lines depends on whether the user has specified
643 \.{\\parshape} or \.{\\hangindent}. If |par_shape_ptr| is not null, it
644 points to a $(2n+1)$-word record in |mem|, where the |vinfo| in the first
645 word contains the value of |n|, and the other $2n$ words contain the left
646 margins and line lengths for the first |n| lines of the paragraph; the
647 specifications for line |n| apply to all subsequent lines. If
648 |par_shape_ptr=null|, the shape of the paragraph depends on the value of
649 |n=hang_after|; if |n>=0|, hanging indentation takes place on lines |n+1|,
650 |n+2|, \dots, otherwise it takes place on lines 1, \dots, $\vert
651 n\vert$. When hanging indentation is active, the left margin is
652 |hang_indent|, if |hang_indent>=0|, else it is 0; the line length is
653 $|hsize|-\vert|hang_indent|\vert$. The normal setting is
654 |par_shape_ptr=null|, |hang_after=1|, and |hang_indent=0|.
655 Note that if |hang_indent=0|, the value of |hang_after| is irrelevant.
656 @^length of lines@> @^hanging indentation@>
659 static halfword easy_line; /*line numbers |>easy_line| are equivalent in break nodes */
660 static halfword last_special_line; /*line numbers |>last_special_line| all have the same width */
661 static scaled first_width; /*the width of all lines |<=last_special_line|, if
662 no \.{\\parshape} has been specified */
663 static scaled second_width; /*the width of all lines |>last_special_line| */
664 static scaled first_indent; /*left margin to go with |first_width| */
665 static scaled second_indent; /*left margin to go with |second_width| */
667 static halfword best_bet; /*use this passive node and its predecessors */
668 static int fewest_demerits; /*the demerits associated with |best_bet| */
669 static halfword best_line; /*line number following the last line of the new paragraph */
670 static int actual_looseness; /*the difference between |line_number(best_bet)|
671 and the optimum |best_line| */
672 static int line_diff; /*the difference between the current line number and
673 the optimum |best_line| */
675 @ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
676 |rule_node|, |ins_node|, |mark_node|, |adjust_node|,
677 |disc_node|, |whatsit_node|, and |math_node| are at the low end of the
678 type codes, by permitting a break at glue in a list if and only if the
679 |type| of the previous node is less than |math_node|. Furthermore, a
680 node is discarded after a break if its type is |math_node| or~more.
683 #define do_all_six(a) a(1);a(2);a(3);a(4);a(5);a(6);a(7)
684 #define do_seven_eight(a) if (adjust_spacing > 1) { a(8);a(9); }
685 #define do_all_eight(a) do_all_six(a); do_seven_eight(a)
686 #define do_one_seven_eight(a) a(1); do_seven_eight(a)
688 #define store_background(a) {active_width[a]=background[a];}
690 #define kern_break() { \
691 if ((!is_char_node(vlink(cur_p))) && auto_breaking) \
692 if (type(vlink(cur_p))==glue_node) \
693 ext_try_break(0, \
694 unhyphenated_node, \
695 line_break_dir, \
696 adjust_spacing, \
697 par_shape_ptr, \
698 adj_demerits, \
699 tracing_paragraphs, \
700 protrude_chars, \
701 line_penalty, \
702 last_line_fit, \
703 double_hyphen_demerits, \
704 final_hyphen_demerits, \
705 first_p, \
706 cur_p); \
707 if (type(cur_p)!=math_node) \
708 active_width[1] += width(cur_p); \
709 else \
710 active_width[1] += surround(cur_p); \
713 #define clean_up_the_memory() { \
714 q=vlink(active); \
715 while (q!=active) { \
716 cur_p = vlink(q); \
717 if (type(q)==delta_node) \
718 flush_node(q); \
719 else \
720 flush_node(q); \
721 q = cur_p; \
723 q = passive; \
724 while (q!=null) { \
725 cur_p = vlink(q); \
726 flush_node(q); \
727 q = cur_p; \
731 static boolean do_last_line_fit; /* special algorithm for last line of paragraph? */
732 static scaled fill_width[4]; /* infinite stretch components of |par_fill_skip| */
733 static scaled best_pl_short[4]; /* |shortfall| corresponding to |minimal_demerits| */
734 static scaled best_pl_glue[4]; /*corresponding glue stretch or shrink */
736 #define reset_disc_width(a) disc_width[(a)] = 0
738 #define add_disc_width_to_break_width(a) break_width[(a)] += disc_width[(a)]
739 #define sub_disc_width_from_active_width(a) active_width[(a)] -= disc_width[(a)]
741 #define add_char_shrink(a,b) a += char_shrink((b))
742 #define add_char_stretch(a,b) a += char_stretch((b))
743 #define sub_char_shrink(a,b) a -= char_shrink((b))
744 #define sub_char_stretch(a,b) a -= char_stretch((b))
746 #define add_kern_shrink(a,b) a += kern_shrink((b))
747 #define add_kern_stretch(a,b) a += kern_stretch((b))
748 #define sub_kern_shrink(a,b) a -= kern_shrink((b))
749 #define sub_kern_stretch(a,b) a -= kern_stretch((b))
751 @ This function is used to add the width of a list of nodes
752 (from a discretionary) to one of the width arrays.
754 Replacement texts and discretionary texts are supposed to contain
755 only character nodes, kern nodes, and box or rule nodes.
758 static void add_to_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths)
760 while (s != null) {
761 if (is_char_node(s)) {
762 widths[1] += pack_width(line_break_dir, dir_TRT, s, true);
763 if ((adjust_spacing > 1) && check_expand_pars(font(s))) {
764 set_prev_char_p(s);
765 add_char_stretch(widths[8], s);
766 add_char_shrink(widths[9], s);
768 } else {
769 switch (type(s)) {
770 case hlist_node:
771 case vlist_node:
772 widths[1] += pack_width(line_break_dir, box_dir(s), s, false);
773 break;
774 case kern_node:
775 if ((adjust_spacing == 2) && (subtype(s) == normal)) {
776 add_kern_stretch(widths[8], s);
777 add_kern_shrink(widths[9], s);
779 /* fall through */
780 case rule_node:
781 widths[1] += width(s);
782 break;
783 case disc_node: /* TH temp */
784 break;
785 default:
786 confusion("invalid node found in discretionary"); /* todo: report type */
789 s = vlink(s);
793 @ This function is used to substract the width of a list of nodes
794 (from a discretionary) from one of the width arrays.
795 It is used only once, but deserves it own function because of orthogonality
796 with the |add_to_widths| function.
799 static void sub_from_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths)
801 while (s != null) {
802 /* Subtract the width of node |s| from |break_width|; */
803 if (is_char_node(s)) {
804 widths[1] -= pack_width(line_break_dir, dir_TRT, s, true);
805 if ((adjust_spacing > 1) && check_expand_pars(font(s))) {
806 set_prev_char_p(s);
807 sub_char_stretch(widths[8], s);
808 sub_char_shrink(widths[9], s);
810 } else {
811 switch (type(s)) {
812 case hlist_node:
813 case vlist_node:
814 widths[1] -= pack_width(line_break_dir, box_dir(s), s, false);
815 break;
816 case kern_node:
817 if ((adjust_spacing == 2) && (subtype(s) == normal)) {
818 sub_kern_stretch(widths[8], s);
819 sub_kern_shrink(widths[9], s);
821 /* fall through */
822 case rule_node:
823 widths[1] -= width(s);
824 break;
825 case disc_node: /* TH temp */
826 break;
827 default:
828 confusion("invalid node found in discretionary"); /* todo: report type */
829 break;
832 s = vlink(s);
836 @ When we insert a new active node for a break at |cur_p|, suppose this
837 new node is to be placed just before active node |a|; then we essentially
838 want to insert `$\delta\,|cur_p|\,\delta^\prime$' before |a|, where
839 $\delta=\alpha(a)-\alpha(|cur_p|)$ and $\delta^\prime=\alpha(|cur_p|)-\alpha(a)$
840 in the notation explained above. The |cur_active_width| array now holds
841 $\gamma+\beta(|cur_p|)-\alpha(a)$; so $\delta$ can be obtained by
842 subtracting |cur_active_width| from the quantity $\gamma+\beta(|cur_p|)-
843 \alpha(|cur_p|)$. The latter quantity can be regarded as the length of a
844 line ``from |cur_p| to |cur_p|''; we call it the |break_width| at |cur_p|.
846 The |break_width| is usually negative, since it consists of the background
847 (which is normally zero) minus the width of nodes following~|cur_p| that are
848 eliminated after a break. If, for example, node |cur_p| is a glue node, the
849 width of this glue is subtracted from the background; and we also look
850 ahead to eliminate all subsequent glue and penalty and kern and math
851 nodes, subtracting their widths as well.
853 Kern nodes do not disappear at a line break unless they are |explicit|.
856 static void compute_break_width(int break_type, int line_break_dir, int adjust_spacing, halfword p)
858 halfword s = p; /* glue and other 'whitespace' to be skipped after a break;
859 used if unhyphenated, or |post_break==empty| */
860 if (break_type > unhyphenated_node && p != null) {
861 /*Compute the discretionary |break_width| values; */
862 /* When |p| is a discretionary break, the length of a line
863 ``from |p| to |p|'' has to be defined properly so
864 that the other calculations work out. Suppose that the
865 pre-break text at |p| has length $l_0$, the post-break
866 text has length $l_1$, and the replacement text has length
867 |l|. Suppose also that |q| is the node following the
868 replacement text. Then length of a line from |p| to |q|
869 will be computed as $\gamma+\beta(q)-\alpha(|p|)$, where
870 $\beta(q)=\beta(|p|)-l_0+l$. The actual length will be
871 the background plus $l_1$, so the length from |p| to
872 |p| should be $\gamma+l_0+l_1-l$. If the post-break text
873 of the discretionary is empty, a break may also discard~|q|;
874 in that unusual case we subtract the length of~|q| and any
875 other nodes that will be discarded after the discretionary
876 break.
878 TH: I don't quite understand the above remarks.
880 The value of $l_0$ need not be computed, since |line_break|
881 will put it into the global variable |disc_width| before
882 calling |try_break|.
884 /* In case of nested discretionaries, we always follow the no-break
885 path, as we are talking about the breaking on {\it this} position.
888 sub_from_widths(vlink_no_break(p), line_break_dir, adjust_spacing, break_width);
889 add_to_widths(vlink_post_break(p), line_break_dir, adjust_spacing, break_width);
890 do_one_seven_eight(add_disc_width_to_break_width);
891 if (vlink_post_break(p) == null) {
892 s = vlink(p); /* no |post_break|: 'skip' any 'whitespace' following */
893 } else {
894 s = null;
897 while (s != null) {
898 switch (type(s)) {
899 case math_node:
900 /* begin mathskip code */
901 if (glue_is_zero(math_skip)) {
902 break_width[1] -= surround(s);
903 break;
904 } else {
905 /* fall through */
907 /* end mathskip code */
908 case glue_node:
909 /*Subtract glue from |break_width|; */
910 break_width[1] -= width(s);
911 break_width[2 + stretch_order(s)] -= stretch(s);
912 break_width[7] -= shrink(s);
913 break;
914 case penalty_node:
915 break;
916 case kern_node:
917 if (subtype(s) != explicit_kern && subtype(s) != italic_kern)
918 return;
919 else
920 break_width[1] -= width(s);
921 break;
922 default:
923 return;
925 s = vlink(s);
929 @ @c
930 static void print_break_node(halfword q, fitness_value fit_class,
931 quarterword break_type, halfword cur_p)
933 /* Print a symbolic description of the new break node */
934 tprint_nl("@@@@");
935 print_int(serial(passive));
936 tprint(": line ");
937 print_int(line_number(q) - 1);
938 print_char('.');
939 print_int(fit_class);
940 if (break_type == hyphenated_node)
941 print_char('-');
942 tprint(" t=");
943 print_int(total_demerits(q));
944 if (do_last_line_fit) {
945 /*Print additional data in the new active node; */
946 tprint(" s=");
947 print_scaled(active_short(q));
948 if (cur_p == null)
949 tprint(" a=");
950 else
951 tprint(" g=");
952 print_scaled(active_glue(q));
954 tprint(" -> @@");
955 if (prev_break(passive) == null)
956 print_char('0');
957 else
958 print_int(serial(prev_break(passive)));
961 @ @c
962 static void print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
963 int d, boolean artificial_demerits)
965 /* Print a symbolic description of this feasible break; */
966 if (printed_node != cur_p) {
967 /* Print the list between |printed_node| and |cur_p|, then
968 set |printed_node:=cur_p|; */
969 tprint_nl("");
970 if (cur_p == null) {
971 short_display(vlink(printed_node));
972 } else {
973 halfword save_link = vlink(cur_p);
974 vlink(cur_p) = null;
975 tprint_nl("");
976 short_display(vlink(printed_node));
977 vlink(cur_p) = save_link;
979 printed_node = cur_p;
981 tprint_nl("@@");
982 if (cur_p == null) {
983 tprint_esc("par");
984 } else if (type(cur_p) != glue_node) {
985 if (type(cur_p) == penalty_node)
986 tprint_esc("penalty");
987 else if (type(cur_p) == disc_node)
988 tprint_esc("discretionary");
989 else if (type(cur_p) == kern_node)
990 tprint_esc("kern");
991 else
992 tprint_esc("math");
994 tprint(" via @@");
995 if (break_node(r) == null)
996 print_char('0');
997 else
998 print_int(serial(break_node(r)));
999 tprint(" b=");
1000 if (b > inf_bad)
1001 print_char('*');
1002 else
1003 print_int(b);
1004 tprint(" p=");
1005 print_int(pi);
1006 tprint(" d=");
1007 if (artificial_demerits)
1008 print_char('*');
1009 else
1010 print_int(d);
1013 @ @c
1014 #define add_disc_width_to_active_width(a) active_width[a] += disc_width[a]
1015 #define update_width(a) cur_active_width[a] += varmem[(r+(a))].cint
1017 #define set_break_width_to_background(a) break_width[a]=background[(a)]
1019 #define convert_to_break_width(a) \
1020 varmem[(prev_r+(a))].cint = varmem[(prev_r+(a))].cint-cur_active_width[(a)]+break_width[(a)]
1022 #define store_break_width(a) active_width[(a)]=break_width[(a)]
1024 #define new_delta_to_break_width(a) \
1025 varmem[(q+(a))].cint=break_width[(a)]-cur_active_width[(a)]
1027 #define new_delta_from_break_width(a) \
1028 varmem[(q+(a))].cint=cur_active_width[(a)]-break_width[(a)]
1030 #define copy_to_cur_active(a) cur_active_width[(a)]=active_width[(a)]
1032 #define combine_two_deltas(a) varmem[(prev_r+(a))].cint += varmem[(r+(a))].cint
1033 #define downdate_width(a) cur_active_width[(a)] -= varmem[(prev_r+(a))].cint
1034 #define update_active(a) active_width[(a)]+=varmem[(r+(a))].cint
1036 #define total_font_stretch cur_active_width[8]
1037 #define total_font_shrink cur_active_width[9]
1039 #define cal_margin_kern_var(a) { \
1040 character(cp) = character((a)); \
1041 font(cp) = font((a)); \
1042 do_subst_font(cp, 1000); \
1043 if (font(cp) != font((a))) \
1044 margin_kern_stretch += (left_pw((a)) - left_pw(cp)); \
1045 font(cp) = font((a)); \
1046 do_subst_font(cp, -1000); \
1047 if (font(cp) != font((a))) \
1048 margin_kern_shrink += (left_pw(cp) - left_pw((a))); \
1051 static void ext_try_break(int pi,
1052 quarterword break_type,
1053 int line_break_dir,
1054 int adjust_spacing,
1055 int par_shape_ptr,
1056 int adj_demerits,
1057 int tracing_paragraphs,
1058 int protrude_chars,
1059 int line_penalty,
1060 int last_line_fit,
1061 int double_hyphen_demerits,
1062 int final_hyphen_demerits, halfword first_p, halfword cur_p)
1064 /* labels: |CONTINUE,DEACTIVATE,FOUND,NOT_FOUND|; */
1065 pointer r; /* runs through the active list */
1066 scaled margin_kern_stretch;
1067 scaled margin_kern_shrink;
1068 halfword lp, rp, cp;
1069 halfword prev_r = active; /* stays a step behind |r| */
1070 halfword prev_prev_r = null; /*a step behind |prev_r|, if |type(prev_r)=delta_node| */
1071 halfword old_l = 0; /* maximum line number in current equivalence class of lines */
1072 boolean no_break_yet = true; /* have we found a feasible break at |cur_p|? */
1073 halfword q; /*points to a new node being created */
1074 halfword l; /*line number of current active node */
1075 boolean node_r_stays_active; /*should node |r| remain in the active list? */
1076 scaled line_width = 0; /*the current line will be justified to this width */
1077 fitness_value fit_class; /*possible fitness class of test line */
1078 halfword b; /*badness of test line */
1079 int d; /*demerits of test line */
1080 boolean artificial_demerits; /*has |d| been forced to zero? */
1082 scaled shortfall; /*used in badness calculations */
1083 scaled g = 0; /*glue stretch or shrink of test line, adjustment for last line */
1084 scaled cur_active_width[10] = { 0 }; /*distance from current active node */
1086 /*Make sure that |pi| is in the proper range; */
1087 if (pi >= inf_penalty) {
1088 return; /* this breakpoint is inhibited by infinite penalty */
1089 } else if (pi <= -inf_penalty) {
1090 pi = eject_penalty; /*this breakpoint will be forced */
1093 do_all_eight(copy_to_cur_active);
1095 while (1) {
1096 r = vlink(prev_r);
1097 /* If node |r| is of type |delta_node|, update |cur_active_width|,
1098 set |prev_r| and |prev_prev_r|, then |goto continue|; */
1099 /* The following code uses the fact that |type(active)<>delta_node| */
1100 if (type(r) == delta_node) {
1101 do_all_eight(update_width); /* IMPLICIT ,r */
1102 prev_prev_r = prev_r;
1103 prev_r = r;
1104 continue;
1106 /* If a line number class has ended, create new active nodes for
1107 the best feasible breaks in that class; then |return|
1108 if |r=active|, otherwise compute the new |line_width|; */
1109 /* The first part of the following code is part of \TeX's inner loop, so
1110 we don't want to waste any time. The current active node, namely node |r|,
1111 contains the line number that will be considered next. At the end of the
1112 list we have arranged the data structure so that |r=active| and
1113 |line_number(active)>old_l|.
1115 l = line_number(r);
1116 if (l > old_l) { /* now we are no longer in the inner loop */
1117 if ((minimum_demerits < awful_bad)
1118 && ((old_l != easy_line) || (r == active))) {
1119 /*Create new active nodes for the best feasible breaks just found */
1120 /* It is not necessary to create new active nodes having |minimal_demerits|
1121 greater than
1122 |minimum_demerits+abs(adj_demerits)|, since such active nodes will never
1123 be chosen in the final paragraph breaks. This observation allows us to
1124 omit a substantial number of feasible breakpoints from further consideration.
1126 if (no_break_yet) {
1127 no_break_yet = false;
1128 do_all_eight(set_break_width_to_background);
1129 compute_break_width(break_type, line_break_dir, adjust_spacing, cur_p);
1131 /* Insert a delta node to prepare for breaks at |cur_p|; */
1132 /* We use the fact that |type(active)<>delta_node|. */
1133 if (type(prev_r) == delta_node) { /* modify an existing delta node */
1134 do_all_eight(convert_to_break_width); /* IMPLICIT |prev_r| */
1135 } else if (prev_r == active) { /* no delta node needed at the beginning */
1136 do_all_eight(store_break_width);
1137 } else {
1138 q = new_node(delta_node, 0);
1139 vlink(q) = r;
1140 do_all_eight(new_delta_to_break_width); /* IMPLICIT q */
1141 vlink(prev_r) = q;
1142 prev_prev_r = prev_r;
1143 prev_r = q;
1146 if (abs(adj_demerits) >= awful_bad - minimum_demerits)
1147 minimum_demerits = awful_bad - 1;
1148 else
1149 minimum_demerits += abs(adj_demerits);
1150 for (fit_class = very_loose_fit; fit_class <= tight_fit;
1151 fit_class++) {
1152 if (minimal_demerits[fit_class] <= minimum_demerits) {
1153 /* Insert a new active node from |best_place[fit_class]|
1154 to |cur_p|; */
1155 /* When we create an active node, we also create the corresponding
1156 passive node.
1158 q = new_node(passive_node, 0);
1159 vlink(q) = passive;
1160 passive = q;
1161 cur_break(q) = cur_p;
1162 incr(pass_number);
1163 serial(q) = pass_number;
1164 prev_break(q) = best_place[fit_class];
1165 /*Here we keep track of the subparagraph penalties in the break nodes */
1166 passive_pen_inter(q) = internal_pen_inter;
1167 passive_pen_broken(q) = internal_pen_broken;
1168 passive_last_left_box(q) = internal_left_box;
1169 passive_last_left_box_width(q) =
1170 internal_left_box_width;
1171 if (prev_break(q) != null) {
1172 passive_left_box(q) =
1173 passive_last_left_box(prev_break(q));
1174 passive_left_box_width(q) =
1175 passive_last_left_box_width(prev_break(q));
1176 } else {
1177 passive_left_box(q) = init_internal_left_box;
1178 passive_left_box_width(q) =
1179 init_internal_left_box_width;
1181 passive_right_box(q) = internal_right_box;
1182 passive_right_box_width(q) = internal_right_box_width;
1183 q = new_node(break_type, fit_class);
1184 break_node(q) = passive;
1185 line_number(q) = best_pl_line[fit_class] + 1;
1186 total_demerits(q) = minimal_demerits[fit_class];
1187 if (do_last_line_fit) {
1188 /*Store additional data in the new active node */
1189 /* Here we save these data in the active node
1190 representing a potential line break. */
1191 active_short(q) = best_pl_short[fit_class];
1192 active_glue(q) = best_pl_glue[fit_class];
1194 vlink(q) = r;
1195 vlink(prev_r) = q;
1196 prev_r = q;
1197 if (tracing_paragraphs > 0)
1198 print_break_node(q, fit_class, break_type, cur_p);
1200 minimal_demerits[fit_class] = awful_bad;
1202 minimum_demerits = awful_bad;
1203 /* Insert a delta node to prepare for the next active node; */
1204 /* When the following code is performed, we will have just inserted at
1205 least one active node before |r|, so |type(prev_r)<>delta_node|.
1207 if (r != active) {
1208 q = new_node(delta_node, 0);
1209 vlink(q) = r;
1210 do_all_eight(new_delta_from_break_width); /* IMPLICIT q */
1211 vlink(prev_r) = q;
1212 prev_prev_r = prev_r;
1213 prev_r = q;
1216 if (r == active)
1217 return;
1218 /*Compute the new line width; */
1219 /* When we come to the following code, we have just encountered
1220 the first active node~|r| whose |line_number| field contains
1221 |l|. Thus we want to compute the length of the $l\mskip1mu$th
1222 line of the current paragraph. Furthermore, we want to set
1223 |old_l| to the last number in the class of line numbers
1224 equivalent to~|l|.
1226 if (l > easy_line) {
1227 old_l = max_halfword - 1;
1228 line_width = second_width;
1229 } else {
1230 old_l = l;
1231 if (l > last_special_line) {
1232 line_width = second_width;
1233 } else if (par_shape_ptr == null) {
1234 line_width = first_width;
1235 } else {
1236 line_width = varmem[(par_shape_ptr + 2 * l + 1)].cint;
1240 /* /If a line number class has ended, create new active nodes for
1241 the best feasible breaks in that class; then |return|
1242 if |r=active|, otherwise compute the new |line_width|; */
1244 /* Consider the demerits for a line from |r| to |cur_p|;
1245 deactivate node |r| if it should no longer be active;
1246 then |goto continue| if a line from |r| to |cur_p| is infeasible,
1247 otherwise record a new feasible break; */
1248 artificial_demerits = false;
1249 shortfall = line_width - cur_active_width[1];
1250 if (break_node(r) == null)
1251 shortfall -= init_internal_left_box_width;
1252 else
1253 shortfall -= passive_last_left_box_width(break_node(r));
1254 shortfall -= internal_right_box_width;
1255 if (protrude_chars > 1) {
1256 halfword l1, o;
1257 l1 = (break_node(r) == null) ? first_p : cur_break(break_node(r));
1258 if (cur_p == null) {
1259 o = null;
1260 } else { /* TODO |if (is_character_node(alink(cur_p)))| */
1261 o = alink(cur_p);
1262 assert(vlink(o) == cur_p);
1264 /* MAGIC: the disc could be a SELECT subtype, to we might need
1265 to get the last character as |pre_break| from either the
1266 |pre_break| list (if the previous INIT disc was taken), or the
1267 |no_break| (sic) list (if the previous INIT disc was not taken)
1269 BUT:
1270 the last characters (hyphenation character) if these two list
1271 should always be the same anyway, so we just look at |pre_break|.
1273 /* let's look at the right margin first */
1274 if ((cur_p != null) && (type(cur_p) == disc_node)
1275 && (vlink_pre_break(cur_p) != null)) {
1276 /* a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break| */
1277 o = tlink_pre_break(cur_p);
1278 } else {
1279 o = find_protchar_right(l1, o);
1281 /* now the left margin */
1282 if ((l1 != null) && (type(l1) == disc_node) && (vlink_post_break(l1) != null)) {
1283 /* FIXME: first 'char' could be a disc! */
1284 l1 = vlink_post_break(l1); /* protrude the first char */
1285 } else {
1286 l1 = find_protchar_left(l1, true);
1288 shortfall += (left_pw(l1) + right_pw(o));
1290 if (shortfall != 0) {
1291 margin_kern_stretch = 0;
1292 margin_kern_shrink = 0;
1293 if (protrude_chars > 1) {
1294 /* Calculate variations of marginal kerns; */
1295 lp = last_leftmost_char;
1296 rp = last_rightmost_char;
1297 cp = raw_glyph_node();
1298 if (lp != null) {
1299 cal_margin_kern_var(lp);
1301 if (rp != null) {
1302 cal_margin_kern_var(rp);
1304 flush_node(cp);
1306 if ((shortfall > 0) && ((total_font_stretch + margin_kern_stretch) > 0)) {
1307 if ((total_font_stretch + margin_kern_stretch) > shortfall)
1308 shortfall = ((total_font_stretch + margin_kern_stretch) / (max_stretch_ratio / cur_font_step)) / 2;
1309 else
1310 shortfall -= (total_font_stretch + margin_kern_stretch);
1311 } else if ((shortfall < 0) && ((total_font_shrink + margin_kern_shrink) > 0)) {
1312 if ((total_font_shrink + margin_kern_shrink) > -shortfall)
1313 shortfall = -((total_font_shrink + margin_kern_shrink) / (max_shrink_ratio / cur_font_step)) / 2;
1314 else
1315 shortfall += (total_font_shrink + margin_kern_shrink);
1318 if (shortfall > 0) {
1319 /* Set the value of |b| to the badness for stretching the line,
1320 and compute the corresponding |fit_class| */
1322 /* When a line must stretch, the available stretchability can be
1323 found in the subarray |cur_active_width[2..6]|, in units of
1324 points, sfi, fil, fill and filll.
1326 The present section is part of \TeX's inner loop, and it is
1327 most often performed when the badness is infinite; therefore
1328 it is worth while to make a quick test for large width excess
1329 and small stretchability, before calling the |badness|
1330 subroutine. */
1332 if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) ||
1333 (cur_active_width[5] != 0) || (cur_active_width[6] != 0)) {
1334 if (do_last_line_fit) {
1335 if (cur_p == null) { /* the last line of a paragraph */
1336 /* Perform computations for last line and |goto found|; */
1338 /* Here we compute the adjustment |g| and badness |b| for
1339 a line from |r| to the end of the paragraph. When any
1340 of the criteria for adjustment is violated we fall
1341 through to the normal algorithm.
1343 The last line must be too short, and have infinite
1344 stretch entirely due to |par_fill_skip|. */
1345 if ((active_short(r) == 0) || (active_glue(r) <= 0))
1346 /* previous line was neither stretched nor shrunk, or
1347 was infinitely bad */
1348 goto NOT_FOUND;
1349 if ((cur_active_width[3] != fill_width[0]) ||
1350 (cur_active_width[4] != fill_width[1]) ||
1351 (cur_active_width[5] != fill_width[2]) ||
1352 (cur_active_width[6] != fill_width[3]))
1353 /* infinite stretch of this line not entirely due to
1354 |par_fill_skip| */
1355 goto NOT_FOUND;
1356 if (active_short(r) > 0)
1357 g = cur_active_width[2];
1358 else
1359 g = cur_active_width[7];
1360 if (g <= 0)
1361 /*no finite stretch resp.\ no shrink */
1362 goto NOT_FOUND;
1363 arith_error = false;
1364 g = fract(g, active_short(r), active_glue(r),
1365 max_dimen);
1366 if (last_line_fit < 1000)
1367 g = fract(g, last_line_fit, 1000, max_dimen);
1368 if (arith_error) {
1369 if (active_short(r) > 0)
1370 g = max_dimen;
1371 else
1372 g = -max_dimen;
1374 if (g > 0) {
1375 /*Set the value of |b| to the badness of the last line
1376 for stretching, compute the corresponding |fit_class,
1377 and |goto found|| */
1378 /* These badness computations are rather similar to
1379 those of the standard algorithm, with the adjustment
1380 amount |g| replacing the |shortfall|. */
1381 if (g > shortfall)
1382 g = shortfall;
1383 if (g > 7230584) {
1384 if (cur_active_width[2] < 1663497) {
1385 b = inf_bad;
1386 fit_class = very_loose_fit;
1387 goto FOUND;
1390 b = badness(g, cur_active_width[2]);
1391 if (b > 99) {
1392 fit_class = very_loose_fit;
1393 } else if (b > 12) {
1394 fit_class = loose_fit;
1395 } else {
1396 fit_class = decent_fit;
1398 goto FOUND;
1399 } else if (g < 0) {
1400 /*Set the value of |b| to the badness of the last line
1401 for shrinking, compute the corresponding |fit_class,
1402 and |goto found||; */
1403 if (-g > cur_active_width[7])
1404 g = -cur_active_width[7];
1405 b = badness(-g, cur_active_width[7]);
1406 if (b > 12)
1407 fit_class = tight_fit;
1408 else
1409 fit_class = decent_fit;
1410 goto FOUND;
1413 NOT_FOUND:
1414 shortfall = 0;
1416 b = 0;
1417 fit_class = decent_fit; /* infinite stretch */
1418 } else {
1419 if (shortfall > 7230584 && cur_active_width[2] < 1663497) {
1420 b = inf_bad;
1421 fit_class = very_loose_fit;
1422 } else {
1423 b = badness(shortfall, cur_active_width[2]);
1424 if (b > 99) {
1425 fit_class = very_loose_fit;
1426 } else if (b > 12) {
1427 fit_class = loose_fit;
1428 } else {
1429 fit_class = decent_fit;
1433 } else {
1434 /* Set the value of |b| to the badness for shrinking the line,
1435 and compute the corresponding |fit_class|; */
1436 /* Shrinkability is never infinite in a paragraph; we can shrink
1437 the line from |r| to |cur_p| by at most
1438 |cur_active_width[7]|. */
1439 if (-shortfall > cur_active_width[7])
1440 b = inf_bad + 1;
1441 else
1442 b = badness(-shortfall, cur_active_width[7]);
1443 if (b > 12)
1444 fit_class = tight_fit;
1445 else
1446 fit_class = decent_fit;
1448 if (do_last_line_fit) {
1449 /* Adjust the additional data for last line; */
1450 if (cur_p == null)
1451 shortfall = 0;
1452 if (shortfall > 0) {
1453 g = cur_active_width[2];
1454 } else if (shortfall < 0) {
1455 g = cur_active_width[7];
1456 } else {
1457 g = 0;
1460 FOUND:
1461 if ((b > inf_bad) || (pi == eject_penalty)) {
1462 /* Prepare to deactivate node~|r|, and |goto deactivate| unless
1463 there is a reason to consider lines of text from |r| to |cur_p| */
1464 /* During the final pass, we dare not lose all active nodes, lest we lose
1465 touch with the line breaks already found. The code shown here makes
1466 sure that such a catastrophe does not happen, by permitting overfull
1467 boxes as a last resort. This particular part of \TeX\ was a source of
1468 several subtle bugs before the correct program logic was finally
1469 discovered; readers who seek to ``improve'' \TeX\ should therefore
1470 think thrice before daring to make any changes here.
1472 if (final_pass && (minimum_demerits == awful_bad) &&
1473 (vlink(r) == active) && (prev_r == active)) {
1474 artificial_demerits = true; /* set demerits zero, this break is forced */
1475 } else if (b > threshold) {
1476 goto DEACTIVATE;
1478 node_r_stays_active = false;
1479 } else {
1480 prev_r = r;
1481 if (b > threshold)
1482 continue;
1483 node_r_stays_active = true;
1485 /* Record a new feasible break; */
1486 /* When we get to this part of the code, the line from |r| to |cur_p| is
1487 feasible, its badness is~|b|, and its fitness classification is
1488 |fit_class|. We don't want to make an active node for this break yet,
1489 but we will compute the total demerits and record them in the
1490 |minimal_demerits| array, if such a break is the current champion among
1491 all ways to get to |cur_p| in a given line-number class and fitness
1492 class.
1494 if (artificial_demerits) {
1495 d = 0;
1496 } else {
1497 /* Compute the demerits, |d|, from |r| to |cur_p|; */
1498 d = line_penalty + b;
1499 if (abs(d) >= 10000)
1500 d = 100000000;
1501 else
1502 d = d * d;
1503 if (pi != 0) {
1504 if (pi > 0) {
1505 d += (pi * pi);
1506 } else if (pi > eject_penalty) {
1507 d -= (pi * pi);
1510 if ((break_type == hyphenated_node) && (type(r) == hyphenated_node)) {
1511 if (cur_p != null)
1512 d += double_hyphen_demerits;
1513 else
1514 d += final_hyphen_demerits;
1516 if (abs(fit_class - fitness(r)) > 1)
1517 d = d + adj_demerits;
1519 if (tracing_paragraphs > 0)
1520 print_feasible_break(cur_p, r, b, pi, d, artificial_demerits);
1521 d += total_demerits(r); /*this is the minimum total demerits
1522 from the beginning to |cur_p| via |r| */
1523 if (d <= minimal_demerits[fit_class]) {
1524 minimal_demerits[fit_class] = d;
1525 best_place[fit_class] = break_node(r);
1526 best_pl_line[fit_class] = l;
1527 if (do_last_line_fit) {
1528 /* Store additional data for this feasible break; */
1529 /* For each feasible break we record the shortfall and glue stretch or
1530 shrink (or adjustment). */
1531 best_pl_short[fit_class] = shortfall;
1532 best_pl_glue[fit_class] = g;
1534 if (d < minimum_demerits)
1535 minimum_demerits = d;
1537 /* /Record a new feasible break */
1538 if (node_r_stays_active)
1539 continue; /*|prev_r| has been set to |r| */
1540 DEACTIVATE:
1541 /* Deactivate node |r|; */
1542 /* When an active node disappears, we must delete an adjacent delta node if
1543 the active node was at the beginning or the end of the active list, or
1544 if it was surrounded by delta nodes. We also must preserve the property
1545 that |cur_active_width| represents the length of material from
1546 |vlink(prev_r)| to~|cur_p|. */
1548 vlink(prev_r) = vlink(r);
1549 flush_node(r);
1550 if (prev_r == active) {
1551 /*Update the active widths, since the first active node has been
1552 deleted */
1553 /* The following code uses the fact that |type(active)<>delta_node|.
1554 If the active list has just become empty, we do not need to update the
1555 |active_width| array, since it will be initialized when an active
1556 node is next inserted.
1558 r = vlink(active);
1559 if (type(r) == delta_node) {
1560 do_all_eight(update_active); /* IMPLICIT r */
1561 do_all_eight(copy_to_cur_active);
1562 vlink(active) = vlink(r);
1563 flush_node(r);
1565 } else if (type(prev_r) == delta_node) {
1566 r = vlink(prev_r);
1567 if (r == active) {
1568 do_all_eight(downdate_width); /* IMPLICIT |prev_r| */
1569 vlink(prev_prev_r) = active;
1570 flush_node(prev_r);
1571 prev_r = prev_prev_r;
1572 } else if (type(r) == delta_node) {
1573 do_all_eight(update_width); /* IMPLICIT ,r */
1574 do_all_eight(combine_two_deltas); /* IMPLICIT r |prev_r| */
1575 vlink(prev_r) = vlink(r);
1576 flush_node(r);
1582 @ @c
1583 void ext_do_line_break(int paragraph_dir,
1584 int pretolerance,
1585 int tracing_paragraphs,
1586 int tolerance,
1587 scaled emergency_stretch,
1588 int looseness,
1589 int adjust_spacing,
1590 halfword par_shape_ptr,
1591 int adj_demerits,
1592 int protrude_chars,
1593 int line_penalty,
1594 int last_line_fit,
1595 int double_hyphen_demerits,
1596 int final_hyphen_demerits,
1597 int hang_indent,
1598 int hsize,
1599 int hang_after,
1600 halfword left_skip,
1601 halfword right_skip,
1602 halfword inter_line_penalties_ptr,
1603 int inter_line_penalty,
1604 int club_penalty,
1605 halfword club_penalties_ptr,
1606 halfword widow_penalties_ptr,
1607 int widow_penalty,
1608 int broken_penalty,
1609 halfword final_par_glue)
1611 /* DONE,DONE1,DONE2,DONE3,DONE4,DONE5,CONTINUE; */
1612 halfword cur_p, q, r, s; /* miscellaneous nodes of temporary interest */
1613 int line_break_dir = paragraph_dir;
1615 /* Get ready to start ... */
1616 minimum_demerits = awful_bad;
1617 minimal_demerits[tight_fit] = awful_bad;
1618 minimal_demerits[decent_fit] = awful_bad;
1619 minimal_demerits[loose_fit] = awful_bad;
1620 minimal_demerits[very_loose_fit] = awful_bad;
1622 fewest_demerits = 0;
1623 actual_looseness = 0;
1625 /* We compute the values of |easy_line| and the other local variables relating
1626 to line length when the |line_break| procedure is initializing itself. */
1627 if (par_shape_ptr == null) {
1628 if (hang_indent == 0) {
1629 last_special_line = 0;
1630 second_width = hsize;
1631 second_indent = 0;
1632 } else {
1633 /* Set line length parameters in preparation for hanging indentation */
1634 /* We compute the values of |easy_line| and the other local variables relating
1635 to line length when the |line_break| procedure is initializing itself. */
1636 last_special_line = abs(hang_after);
1637 if (hang_after < 0) {
1638 first_width = hsize - abs(hang_indent);
1639 if (hang_indent >= 0)
1640 first_indent = hang_indent;
1641 else
1642 first_indent = 0;
1643 second_width = hsize;
1644 second_indent = 0;
1645 } else {
1646 first_width = hsize;
1647 first_indent = 0;
1648 second_width = hsize - abs(hang_indent);
1649 if (hang_indent >= 0)
1650 second_indent = hang_indent;
1651 else
1652 second_indent = 0;
1655 } else {
1656 last_special_line = vinfo(par_shape_ptr + 1) - 1;
1657 second_indent =
1658 varmem[(par_shape_ptr + 2 * (last_special_line + 1))].cint;
1659 second_width =
1660 varmem[(par_shape_ptr + 2 * (last_special_line + 1) + 1)].cint;
1662 if (looseness == 0)
1663 easy_line = last_special_line;
1664 else
1665 easy_line = max_halfword;
1667 no_shrink_error_yet = true;
1668 check_shrinkage(left_skip);
1669 check_shrinkage(right_skip);
1670 q = left_skip;
1671 r = right_skip;
1672 background[1] = width(q) + width(r);
1673 background[2] = 0;
1674 background[3] = 0;
1675 background[4] = 0;
1676 background[5] = 0;
1677 background[6] = 0;
1678 background[2 + stretch_order(q)] = stretch(q);
1679 background[2 + stretch_order(r)] += stretch(r);
1680 background[7] = shrink(q) + shrink(r);
1681 if (adjust_spacing > 1) {
1682 background[8] = 0;
1683 background[9] = 0;
1684 max_stretch_ratio = -1;
1685 max_shrink_ratio = -1;
1686 cur_font_step = -1;
1687 set_prev_char_p(null);
1689 /* Check for special treatment of last line of paragraph; */
1690 /* The new algorithm for the last line requires that the stretchability
1691 |par_fill_skip| is infinite and the stretchability of |left_skip| plus
1692 |right_skip| is finite.
1694 do_last_line_fit = false;
1695 if (last_line_fit > 0) {
1696 q = last_line_fill;
1697 if ((stretch(q) > 0) && (stretch_order(q) > normal)) {
1698 if ((background[3] == 0) && (background[4] == 0) &&
1699 (background[5] == 0) && (background[6] == 0)) {
1700 do_last_line_fit = true;
1701 fill_width[0] = 0;
1702 fill_width[1] = 0;
1703 fill_width[2] = 0;
1704 fill_width[3] = 0;
1705 fill_width[stretch_order(q) - 1] = stretch(q);
1709 /* DIR: Initialize |dir_ptr| for |line_break| */
1710 if (dir_ptr != null) {
1711 flush_node_list(dir_ptr);
1712 dir_ptr = null;
1714 #if 0
1715 push_dir(dir_ptr,paragraph_dir); /* TODO what was the point of this? */
1716 #endif
1718 /* Find optimal breakpoints; */
1719 threshold = pretolerance;
1720 if (threshold >= 0) {
1721 if (tracing_paragraphs > 0) {
1722 begin_diagnostic();
1723 tprint_nl("@@firstpass");
1725 second_pass = false;
1726 final_pass = false;
1727 } else {
1728 threshold = tolerance;
1729 second_pass = true;
1730 final_pass = (emergency_stretch <= 0);
1731 if (tracing_paragraphs > 0)
1732 begin_diagnostic();
1734 while (1) {
1735 halfword first_p;
1736 halfword nest_stack[10];
1737 int nest_index = 0;
1738 if (threshold > inf_bad)
1739 threshold = inf_bad;
1740 /* Create an active breakpoint representing the beginning of the paragraph */
1741 q = new_node(unhyphenated_node, decent_fit);
1742 vlink(q) = active;
1743 break_node(q) = null;
1744 line_number(q) = cur_list.pg_field + 1;
1745 total_demerits(q) = 0;
1746 active_short(q) = 0;
1747 active_glue(q) = 0;
1748 vlink(active) = q;
1749 do_all_eight(store_background);
1750 passive = null;
1751 printed_node = temp_head;
1752 pass_number = 0;
1753 font_in_short_display = null_font;
1754 /* /Create an active breakpoint representing the beginning of the paragraph */
1755 auto_breaking = true;
1756 cur_p = vlink(temp_head);
1757 /* LOCAL: Initialize with first |local_paragraph| node */
1758 if ((cur_p != null) && (type(cur_p) == local_par_node)) {
1759 alink(cur_p) = temp_head; /* this used to be an assert, but may as well force it */
1760 internal_pen_inter = local_pen_inter(cur_p);
1761 internal_pen_broken = local_pen_broken(cur_p);
1762 init_internal_left_box = local_box_left(cur_p);
1763 init_internal_left_box_width = local_box_left_width(cur_p);
1764 internal_left_box = init_internal_left_box;
1765 internal_left_box_width = init_internal_left_box_width;
1766 internal_right_box = local_box_right(cur_p);
1767 internal_right_box_width = local_box_right_width(cur_p);
1768 } else {
1769 internal_pen_inter = 0;
1770 internal_pen_broken = 0;
1771 init_internal_left_box = null;
1772 init_internal_left_box_width = 0;
1773 internal_left_box = init_internal_left_box;
1774 internal_left_box_width = init_internal_left_box_width;
1775 internal_right_box = null;
1776 internal_right_box_width = 0;
1778 /* /LOCAL: Initialize with first |local_paragraph| node */
1779 set_prev_char_p(null);
1780 first_p = cur_p;
1781 /* to access the first node of paragraph as the first active node
1782 has |break_node=null| */
1783 while ((cur_p != null) && (vlink(active) != active)) {
1784 /* |try_break| if |cur_p| is a legal breakpoint; on the 2nd pass, also look at |disc_node|s. */
1786 while (is_char_node(cur_p)) {
1787 /* Advance |cur_p| to the node following the present string of characters ; */
1788 /* The code that passes over the characters of words in a paragraph is part of
1789 \TeX's inner loop, so it has been streamlined for speed. We use the fact that
1790 `\.{\\parfillskip}' glue appears at the end of each paragraph; it is therefore
1791 unnecessary to check if |vlink(cur_p)=null| when |cur_p| is a character node.
1793 active_width[1] += pack_width(line_break_dir, dir_TRT, cur_p, true);
1794 if ((adjust_spacing > 1) && check_expand_pars(font(cur_p))) {
1795 set_prev_char_p(cur_p);
1796 add_char_stretch(active_width[8], cur_p);
1797 add_char_shrink(active_width[9], cur_p);
1799 cur_p = vlink(cur_p);
1800 while (cur_p == null && nest_index > 0) {
1801 cur_p = nest_stack[--nest_index];
1804 if (cur_p == null) {
1805 normal_error("linebreak","invalid list tail, probably missing glue");
1807 /* Determine legal breaks: As we move through the hlist, we need to keep
1808 the |active_width| array up to date, so that the badness of individual
1809 lines is readily calculated by |try_break|. It is convenient to use the
1810 short name |active_width[1]| for the component of active width that represents
1811 real width as opposed to glue. */
1813 switch (type(cur_p)) {
1814 case hlist_node:
1815 case vlist_node:
1816 active_width[1] += pack_width(line_break_dir, box_dir(cur_p), cur_p, false);
1817 break;
1818 case rule_node:
1819 active_width[1] += width(cur_p);
1820 break;
1821 case dir_node: /* DIR: Adjust the dir stack for the |line_break| routine; */
1822 if (dir_dir(cur_p) >= 0) {
1823 line_break_dir = dir_dir(cur_p);
1824 push_dir_node(dir_ptr,cur_p); /* adds to |dir_ptr| */
1825 } else {
1826 pop_dir_node(dir_ptr);
1827 if (dir_ptr != null) {
1828 line_break_dir = dir_dir(dir_ptr);
1831 break;
1832 case local_par_node: /* LOCAL: Advance past a |local_paragraph| node; */
1833 internal_pen_inter = local_pen_inter(cur_p);
1834 internal_pen_broken = local_pen_broken(cur_p);
1835 internal_left_box = local_box_left(cur_p);
1836 internal_left_box_width = local_box_left_width(cur_p);
1837 internal_right_box = local_box_right(cur_p);
1838 internal_right_box_width = local_box_right_width(cur_p);
1839 break;
1840 case math_node:
1841 auto_breaking = (subtype(cur_p) == after);
1842 /* begin mathskip code */
1843 if (glue_is_zero(math_skip)) {
1844 kern_break();
1845 break;
1846 } else {
1847 /* fall through */
1849 /* end mathskip code */
1850 case glue_node:
1852 If node |cur_p| is a legal breakpoint, call |try_break|;
1853 then update the active widths by including the glue in
1854 |glue_ptr(cur_p)|;
1856 When node |cur_p| is a glue node, we look at the previous
1857 to see whether or not a breakpoint is legal at |cur_p|,
1858 as explained above.
1860 The |precedes_break| test also considers dir nodes and prohibits
1861 a break after an opening dir_node (positive dir). In |\textdir TRT x|
1862 the space after |TRT| is preserved and therefore the dir node
1863 is bound to the |x|. Being more clever makes no sense: users
1864 should code their input properly.
1866 if (auto_breaking) {
1867 halfword prev_p = alink(cur_p);
1868 if (prev_p != temp_head && (
1869 is_char_node(prev_p)
1870 || precedes_break(prev_p)
1871 || ( (type(prev_p) == kern_node) && (
1872 subtype(prev_p) == font_kern || subtype(prev_p) == accent_kern)
1874 )) {
1875 ext_try_break(0, unhyphenated_node, line_break_dir, adjust_spacing,
1876 par_shape_ptr, adj_demerits,
1877 tracing_paragraphs, protrude_chars,
1878 line_penalty, last_line_fit,
1879 double_hyphen_demerits,
1880 final_hyphen_demerits, first_p, cur_p);
1883 /* *INDENT-ON* */
1884 check_shrinkage(cur_p);
1885 active_width[1] += width(cur_p);
1886 active_width[2 + stretch_order(cur_p)] += stretch(cur_p);
1887 active_width[7] += shrink(cur_p);
1888 break;
1889 case kern_node:
1890 if (subtype(cur_p) == explicit_kern || subtype(cur_p) == italic_kern) {
1891 kern_break();
1892 } else {
1893 active_width[1] += width(cur_p);
1894 if ((adjust_spacing == 2) && (subtype(cur_p) == normal)) {
1895 add_kern_stretch(active_width[8], cur_p);
1896 add_kern_shrink(active_width[9], cur_p);
1899 break;
1900 case disc_node:
1901 /* |select_disc|s are handled by the leading |init_disc| */
1902 if (subtype(cur_p) == select_disc)
1903 break;
1904 /* Try to break after a discretionary fragment, then |goto done5|; */
1905 /* The following code knows that discretionary texts contain
1906 only character nodes, kern nodes, box nodes, and rule
1907 nodes. This branch differs a bit from older engines because in LuaTeX we
1908 already have hyphenated the list. This means that we need to skip
1909 automatic disc nodes. Of better, we need to treat discretionaries
1910 and explicit hyphens always, even in the first pass (HH). */
1911 if (second_pass || subtype(cur_p) <= automatic_disc) {
1913 int actual_penalty = hyphen_penalty;
1914 if (disc_penalty(cur_p) != 0) {
1915 actual_penalty = (int) disc_penalty(cur_p);
1916 } else if (subtype(cur_p) == automatic_disc) {
1917 actual_penalty = ex_hyphen_penalty;
1920 int actual_penalty = (int) disc_penalty(cur_p);
1921 s = vlink_pre_break(cur_p);
1922 do_one_seven_eight(reset_disc_width);
1923 if (s == null) { /* trivial pre-break */
1924 ext_try_break(actual_penalty, hyphenated_node,
1925 line_break_dir, adjust_spacing,
1926 par_shape_ptr, adj_demerits,
1927 tracing_paragraphs, protrude_chars,
1928 line_penalty, last_line_fit,
1929 double_hyphen_demerits,
1930 final_hyphen_demerits, first_p, cur_p);
1931 } else {
1932 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1933 do_one_seven_eight(add_disc_width_to_active_width);
1934 ext_try_break(actual_penalty, hyphenated_node,
1935 line_break_dir, adjust_spacing,
1936 par_shape_ptr, adj_demerits,
1937 tracing_paragraphs, protrude_chars,
1938 line_penalty, last_line_fit,
1939 double_hyphen_demerits,
1940 final_hyphen_demerits, first_p, cur_p);
1941 if (subtype(cur_p) == init_disc) {
1942 /* we should at two break points after the one we
1943 added above:
1944 \item1 which does a possible break in INIT's |post_break|
1945 \item2 which means the |no_break| actually was broken
1946 just a character later */
1947 /* do the select-0 case 'f-f-i' */
1948 s = vlink_pre_break(vlink(cur_p));
1949 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1950 ext_try_break(actual_penalty, hyphenated_node,
1951 line_break_dir, adjust_spacing,
1952 par_shape_ptr, adj_demerits,
1953 tracing_paragraphs,
1954 protrude_chars, line_penalty,
1955 last_line_fit, double_hyphen_demerits,
1956 final_hyphen_demerits, first_p,
1957 vlink(cur_p));
1958 #if 0
1959 /* TODO this does not work */
1960 /* go back to the starting situation */
1961 do_one_seven_eight(sub_disc_width_from_active_width);
1962 do_one_seven_eight(reset_disc_width);
1963 /* add select |no_break| to |active_width| */
1964 s = vlink_no_break(vlink(cur_p));
1965 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1966 ext_try_break(actual_penalty, hyphenated_node,
1967 line_break_dir, adjust_spacing,
1968 par_shape_ptr, adj_demerits,
1969 tracing_paragraphs,
1970 protrude_chars, line_penalty,
1971 last_line_fit, double_hyphen_demerits,
1972 final_hyphen_demerits, first_p,
1973 vlink(cur_p));
1974 #endif
1976 do_one_seven_eight(sub_disc_width_from_active_width);
1979 s = vlink_no_break(cur_p);
1980 add_to_widths(s, line_break_dir, adjust_spacing, active_width);
1981 break;
1982 case penalty_node:
1983 ext_try_break(penalty(cur_p), unhyphenated_node, line_break_dir,
1984 adjust_spacing, par_shape_ptr, adj_demerits,
1985 tracing_paragraphs, protrude_chars,
1986 line_penalty, last_line_fit,
1987 double_hyphen_demerits, final_hyphen_demerits,
1988 first_p, cur_p);
1989 break;
1990 case boundary_node:
1991 case whatsit_node:
1992 /* / Advance past a whatsit node in the |line_break| loop/; */
1993 case mark_node:
1994 case ins_node:
1995 case adjust_node:
1996 break;
1997 case glue_spec_node:
1998 normal_warning("parbuilder","found a glue_spec in a paragraph");
1999 break;
2000 default:
2001 formatted_error("parbuilder","weird node %d in paragraph",type(cur_p));
2003 cur_p = vlink(cur_p);
2004 while (cur_p == null && nest_index > 0) {
2005 cur_p = nest_stack[--nest_index];
2008 if (cur_p == null) {
2010 Try the final line break at the end of the paragraph,
2011 and |goto done| if the desired breakpoints have been found
2013 The forced line break at the paragraph's end will reduce the list of
2014 breakpoints so that all active nodes represent breaks at |cur_p=null|.
2015 On the first pass, we insist on finding an active node that has the
2016 correct ``looseness.'' On the final pass, there will be at least one active
2017 node, and we will match the desired looseness as well as we can.
2019 The global variable |best_bet| will be set to the active node for the best
2020 way to break the paragraph, and a few other variables are used to
2021 help determine what is best.
2023 ext_try_break(eject_penalty, hyphenated_node, line_break_dir,
2024 adjust_spacing, par_shape_ptr, adj_demerits,
2025 tracing_paragraphs, protrude_chars, line_penalty,
2026 last_line_fit, double_hyphen_demerits,
2027 final_hyphen_demerits, first_p, cur_p);
2028 if (vlink(active) != active) {
2029 /* Find an active node with fewest demerits; */
2030 r = vlink(active);
2031 fewest_demerits = awful_bad;
2032 do {
2033 if (type(r) != delta_node) {
2034 if (total_demerits(r) < fewest_demerits) {
2035 fewest_demerits = total_demerits(r);
2036 best_bet = r;
2039 r = vlink(r);
2040 } while (r != active);
2041 best_line = line_number(best_bet);
2043 Find an active node with fewest demerits;
2045 if (looseness == 0)
2046 goto DONE;
2048 Find the best active node for the desired looseness;
2050 The adjustment for a desired looseness is a slightly more complicated
2051 version of the loop just considered. Note that if a paragraph is broken
2052 into segments by displayed equations, each segment will be subject to the
2053 looseness calculation, independently of the other segments.
2055 r = vlink(active);
2056 actual_looseness = 0;
2057 do {
2058 if (type(r) != delta_node) {
2059 line_diff = line_number(r) - best_line;
2060 if (((line_diff < actual_looseness)
2061 && (looseness <= line_diff))
2062 || ((line_diff > actual_looseness)
2063 && (looseness >= line_diff))) {
2064 best_bet = r;
2065 actual_looseness = line_diff;
2066 fewest_demerits = total_demerits(r);
2067 } else if ((line_diff == actual_looseness) &&
2068 (total_demerits(r) < fewest_demerits)) {
2069 best_bet = r;
2070 fewest_demerits = total_demerits(r);
2073 r = vlink(r);
2074 } while (r != active);
2075 best_line = line_number(best_bet);
2077 Find the best active node for the desired looseness;
2079 if ((actual_looseness == looseness) || final_pass)
2080 goto DONE;
2083 /* Clean up the memory by removing the break nodes; */
2084 clean_up_the_memory();
2085 /* /Clean up the memory by removing the break nodes; */
2086 if (!second_pass) {
2087 if (tracing_paragraphs > 0)
2088 tprint_nl("@@secondpass");
2089 threshold = tolerance;
2090 second_pass = true;
2091 final_pass = (emergency_stretch <= 0);
2092 } else {
2093 /* if at first you do not succeed, \dots */
2094 if (tracing_paragraphs > 0)
2095 tprint_nl("@@emergencypass");
2096 background[2] += emergency_stretch;
2097 final_pass = true;
2101 DONE:
2102 if (tracing_paragraphs > 0) {
2103 end_diagnostic(true);
2104 normalize_selector();
2106 if (do_last_line_fit) {
2108 Adjust the final line of the paragraph; here we either reset
2109 |do_last_line_fit| or adjust the |par_fill_skip| glue.
2111 if (active_short(best_bet) == 0) {
2112 do_last_line_fit = false;
2113 } else {
2114 width(last_line_fill) += (active_short(best_bet) - active_glue(best_bet));
2115 stretch(last_line_fill) = 0;
2120 Break the paragraph at the chosen...; Once the best sequence of breakpoints
2121 has been found (hurray), we call on the procedure |post_line_break| to finish
2122 the remainder of the work. By introducing this subprocedure, we are able to
2123 keep |line_break| from getting extremely long.
2126 /* first thing |ext_post_line_break| does is reset |dir_ptr| */
2127 flush_node_list(dir_ptr);
2128 dir_ptr = null;
2129 ext_post_line_break(paragraph_dir,
2130 right_skip,
2131 left_skip,
2132 protrude_chars,
2133 par_shape_ptr,
2134 adjust_spacing,
2135 inter_line_penalties_ptr,
2136 inter_line_penalty,
2137 club_penalty,
2138 club_penalties_ptr,
2139 widow_penalties_ptr,
2140 widow_penalty,
2141 broken_penalty,
2142 final_par_glue,
2143 best_bet,
2144 last_special_line,
2145 second_width,
2146 second_indent, first_width, first_indent, best_line);
2148 Break the paragraph at the chosen ...Clean up the memory by removing
2149 the break nodes.
2151 clean_up_the_memory();
2154 @ @c
2155 void get_linebreak_info (int *f, int *a)
2157 *f = fewest_demerits;
2158 *a = actual_looseness;