beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / tex / linebreak.w
blobb2909606d48cdab830c4ff359af58b121da8d10a
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 type(cur_list.tail_field) = penalty_node;
112 delete_glue_ref(glue_ptr(cur_list.tail_field));
113 if (leader_ptr(cur_list.tail_field) != null)
114 flush_node_list(leader_ptr(cur_list.tail_field));
115 penalty(cur_list.tail_field) = inf_penalty;
117 final_par_glue = new_param_glue(par_fill_skip_code);
118 couple_nodes(cur_list.tail_field, final_par_glue);
119 cur_list.tail_field = vlink(cur_list.tail_field);
120 lua_node_filter(pre_linebreak_filter_callback,
121 line_break_context,
122 temp_head,
123 addressof(cur_list.tail_field));
124 last_line_fill = cur_list.tail_field;
125 pop_nest();
126 start_of_par = cur_list.tail_field;
127 callback_id = callback_defined(linebreak_filter_callback);
128 if (callback_id > 0) {
129 callback_id = lua_linebreak_callback(d, temp_head, addressof(cur_list.tail_field));
130 if (callback_id > 0) {
131 /* find the correct value for the |just_box| */
132 halfword box_search = cur_list.tail_field;
133 just_box = null;
134 if (box_search != null) {
135 do {
136 if (type(box_search) == hlist_node) {
137 just_box = box_search;
139 box_search = vlink(box_search);
140 } while (box_search != null);
142 if (just_box == null) {
143 help3
144 ("A linebreaking routine should return a non-empty list of nodes",
145 "and at least one of those has to be a \\hbox.",
146 "Sorry, I cannot recover from this.");
147 print_err("Invalid linebreak_filter");
148 succumb();
150 } else {
151 if (int_par(tracing_paragraphs_code) > 0) {
152 begin_diagnostic();
153 print_int(line);
154 end_diagnostic(true);
158 if (callback_id == 0) {
159 if ((!is_char_node(vlink(temp_head))) && ((type(vlink(temp_head)) == local_par_node))) {
160 paragraph_dir = local_par_dir(vlink(temp_head));
161 } else {
162 confusion("weird par dir"); /* assert(0); */ /* |paragraph_dir = 0|; */
164 ext_do_line_break(paragraph_dir,
165 int_par(pretolerance_code),
166 int_par(tracing_paragraphs_code),
167 int_par(tolerance_code),
168 dimen_par(emergency_stretch_code),
169 int_par(looseness_code),
170 int_par(adjust_spacing_code),
171 equiv(par_shape_loc),
172 int_par(adj_demerits_code),
173 int_par(protrude_chars_code),
174 int_par(line_penalty_code),
175 int_par(last_line_fit_code),
176 int_par(double_hyphen_demerits_code),
177 int_par(final_hyphen_demerits_code),
178 dimen_par(hang_indent_code),
179 dimen_par(hsize_code),
180 int_par(hang_after_code),
181 glue_par(left_skip_code),
182 glue_par(right_skip_code),
183 equiv(inter_line_penalties_loc),
184 int_par(inter_line_penalty_code),
185 int_par(club_penalty_code),
186 equiv(club_penalties_loc),
187 (d ? equiv(display_widow_penalties_loc) : equiv(widow_penalties_loc)),
188 (d ? int_par(display_widow_penalty_code) : int_par(widow_penalty_code)),
189 int_par(broken_penalty_code),
190 final_par_glue);
192 lua_node_filter(post_linebreak_filter_callback,
193 line_break_context, start_of_par,
194 addressof(cur_list.tail_field));
195 pack_begin_line = 0;
198 @ Glue nodes in a horizontal list that is being paragraphed are not supposed to
199 include ``infinite'' shrinkability; that is why the algorithm maintains
200 four registers for stretching but only one for shrinking. If the user tries to
201 introduce infinite shrinkability, the shrinkability will be reset to finite
202 and an error message will be issued. A boolean variable |no_shrink_error_yet|
203 prevents this error message from appearing more than once per paragraph.
206 #define check_shrinkage(a) \
207 if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \
208 a=finite_shrink((a))
210 static boolean no_shrink_error_yet; /*have we complained about infinite shrinkage? */
212 static halfword finite_shrink(halfword p)
213 { /* recovers from infinite shrinkage */
214 halfword q; /*new glue specification */
215 const char *hlp[] = {
216 "The paragraph just ended includes some glue that has",
217 "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
218 "Such glue doesn't belong there---it allows a paragraph",
219 "of any length to fit on one line. But it's safe to proceed,",
220 "since the offensive shrinkability has been made finite.",
221 NULL
223 if (no_shrink_error_yet) {
224 no_shrink_error_yet = false;
225 tex_error("Infinite glue shrinkage found in a paragraph", hlp);
227 q = new_spec(p);
228 shrink_order(q) = normal;
229 delete_glue_ref(p);
230 return q;
233 @ A pointer variable |cur_p| runs through the given horizontal list as we look
234 for breakpoints. This variable is global, since it is used both by |line_break|
235 and by its subprocedure |try_break|.
237 Another global variable called |threshold| is used to determine the feasibility
238 of individual lines: breakpoints are feasible if there is a way to reach
239 them without creating lines whose badness exceeds |threshold|. (The
240 badness is compared to |threshold| before penalties are added, so that
241 penalty values do not affect the feasibility of breakpoints, except that
242 no break is allowed when the penalty is 10000 or more.) If |threshold|
243 is 10000 or more, all legal breaks are considered feasible, since the
244 |badness| function specified above never returns a value greater than~10000.
246 Up to three passes might be made through the paragraph in an attempt to find at
247 least one set of feasible breakpoints. On the first pass, we have
248 |threshold=pretolerance| and |second_pass=final_pass=false|.
249 If this pass fails to find a
250 feasible solution, |threshold| is set to |tolerance|, |second_pass| is set
251 |true|, and an attempt is made to hyphenate as many words as possible.
252 If that fails too, we add |emergency_stretch| to the background
253 stretchability and set |final_pass=true|.
256 static boolean second_pass; /* is this our second attempt to break this paragraph? */
257 static boolean final_pass; /*is this our final attempt to break this paragraph? */
258 static int threshold; /* maximum badness on feasible lines */
260 /* maximum fill level for |hlist_stack|*/
261 #define max_hlist_stack 512 /* maybe good if larger than |2 *
262 max_quarterword|, so that box nesting
263 level would overflow first */
265 /* stack for |find_protchar_left()| and |find_protchar_right()| */
266 static halfword hlist_stack[max_hlist_stack];
268 /* fill level for |hlist_stack| */
269 static short hlist_stack_level = 0;
271 @ @c
272 static void push_node(halfword p)
274 if (hlist_stack_level >= max_hlist_stack)
275 normal_error("push_node","stack overflow");
276 hlist_stack[hlist_stack_level++] = p;
279 static halfword pop_node(void)
281 if (hlist_stack_level <= 0) /* would point to some bug */
282 normal_error("pop_node","stack underflow (internal error)");
283 return hlist_stack[--hlist_stack_level];
286 @ @c
287 static int max_stretch_ratio = 0; /*maximal stretch ratio of expanded fonts */
288 static int max_shrink_ratio = 0; /*maximal shrink ratio of expanded fonts */
289 static int cur_font_step = 0; /*the current step of expanded fonts */
291 static boolean check_expand_pars(internal_font_number f)
293 int m;
295 if ((font_step(f) == 0)
296 || ((font_max_stretch(f) == 0) && (font_max_shrink(f) == 0)))
297 return false;
298 if (cur_font_step < 0)
299 cur_font_step = font_step(f);
300 else if (cur_font_step != font_step(f))
301 normal_error("font expansion","using fonts with different step of expansion in one paragraph is not allowed");
302 m = font_max_stretch(f);
303 if (m != 0) {
304 if (max_stretch_ratio < 0)
305 max_stretch_ratio = m;
306 else if (max_stretch_ratio != m)
307 normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed");
309 m = font_max_shrink(f);
310 if (m != 0) {
311 if (max_shrink_ratio < 0)
312 max_shrink_ratio = -m;
313 else if (max_shrink_ratio != -m)
314 normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed");
316 return true;
319 @ searches left to right from list head |l|, returns 1st non-skipable item
322 /*public*/ halfword find_protchar_left(halfword l, boolean d)
324 halfword t;
325 boolean run;
326 boolean done = false ;
327 while ((vlink(l) != null) && (type(l) == hlist_node) && zero_dimensions(l) && (list_ptr(l) == null)) {
328 /*for paragraph start with \.{\\parindent} = 0pt or any empty hbox */
329 l = vlink(l);
330 done = true ;
332 if ((!done) && (type(l) == local_par_node)) {
333 l = vlink(l);
334 done = true ;
336 if ((!done) && d) {
337 while ((vlink(l) != null) && (!(is_char_node(l) || non_discardable(l)))) {
338 /* std.\ discardables at line break, \TeX book, p 95 */
339 l = vlink(l);
342 if (type(l) != glyph_node) {
343 hlist_stack_level = 0;
344 run = true;
345 do {
346 t = l;
347 while (run && (type(l) == hlist_node) && (list_ptr(l) != null)) {
348 push_node(l);
349 l = list_ptr(l);
351 while (run && cp_skipable(l)) {
352 while ((vlink(l) == null) && (hlist_stack_level > 0)) {
353 l = pop_node(); /* don't visit this node again */
354 run = false;
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) {
397 assert(vlink(alink(r)) == r);
398 r = alink(r);
399 } else { /* this is the input: \.{\\leavevmode\\penalty-10000\\penalty-10000} (bug \#268) */
400 run = false;
402 } else if ((r == l) && (hlist_stack_level == 0))
403 run = false;
405 } while (t != r);
406 return r;
409 @ @c
410 #define left_pw(a) char_pw((a), left_side)
411 #define right_pw(a) char_pw((a), right_side)
413 @ When looking for optimal line breaks, \TeX\ creates a ``break node'' for
414 each break that is {\sl feasible}, in the sense that there is a way to end
415 a line at the given place without requiring any line to stretch more than
416 a given tolerance. A break node is characterized by three things: the position
417 of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|,
418 or |disc_node|); the ordinal number of the line that will follow this
419 breakpoint; and the fitness classification of the line that has just
420 ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|.
423 typedef enum {
424 very_loose_fit = 0, /* fitness classification for lines stretching more than
425 their stretchability */
426 loose_fit, /* fitness classification for lines stretching 0.5 to 1.0 of their
427 stretchability */
428 decent_fit, /* fitness classification for all other lines */
429 tight_fit /* fitness classification for lines shrinking 0.5 to 1.0 of their
430 shrinkability */
431 } fitness_value;
434 @ The algorithm essentially determines the best possible way to achieve
435 each feasible combination of position, line, and fitness. Thus, it answers
436 questions like, ``What is the best way to break the opening part of the
437 paragraph so that the fourth line is a tight line ending at such-and-such
438 a place?'' However, the fact that all lines are to be the same length
439 after a certain point makes it possible to regard all sufficiently large
440 line numbers as equivalent, when the looseness parameter is zero, and this
441 makes it possible for the algorithm to save space and time.
443 An ``active node'' and a ``passive node'' are created in |mem| for each
444 feasible breakpoint that needs to be considered. Active nodes are three
445 words long and passive nodes are two words long. We need active nodes only
446 for breakpoints near the place in the paragraph that is currently being
447 examined, so they are recycled within a comparatively short time after
448 they are created.
450 @ An active node for a given breakpoint contains six fields:
452 |vlink| points to the next node in the list of active nodes; the
453 last active node has |vlink=active|.
455 |break_node| points to the passive node associated with this
456 breakpoint.
458 |line_number| is the number of the line that follows this
459 breakpoint.
461 |fitness| is the fitness classification of the line ending at this
462 breakpoint.
464 |type| is either |hyphenated_node| or |unhyphenated_node|, depending on
465 whether this breakpoint is a |disc_node|.
467 |total_demerits| is the minimum possible sum of demerits over all
468 lines leading from the beginning of the paragraph to this breakpoint.
470 The value of |vlink(active)| points to the first active node on a vlinked list
471 of all currently active nodes. This list is in order by |line_number|,
472 except that nodes with |line_number>easy_line| may be in any order relative
473 to each other.
476 void initialize_active(void)
478 type(active) = hyphenated_node;
479 line_number(active) = max_halfword;
480 subtype(active) = 0; /* the |subtype| is never examined */
483 @ The passive node for a given breakpoint contains EIGHT fields:
485 |vlink| points to the passive node created just before this one,
486 if any, otherwise it is |null|.
488 |cur_break| points to the position of this breakpoint in the
489 horizontal list for the paragraph being broken.
491 |prev_break| points to the passive node that should precede this
492 one in an optimal path to this breakpoint.
494 |serial| is equal to |n| if this passive node is the |n|th
495 one created during the current pass. (This field is used only when
496 printing out detailed statistics about the line-breaking calculations.)
498 |passive_pen_inter| holds the current \.{\\localinterlinepenalty}
500 |passive_pen_broken| holds the current \.{\\localbrokenpenalty}
502 There is a global variable called |passive| that points to the most
503 recently created passive node. Another global variable, |printed_node|,
504 is used to help print out the paragraph when detailed information about
505 the line-breaking computation is being displayed.
508 static halfword passive; /* most recent node on passive list */
509 static halfword printed_node; /*most recent node that has been printed */
510 static halfword pass_number; /*the number of passive nodes allocated on this pass */
512 @ The active list also contains ``delta'' nodes that help the algorithm
513 compute the badness of individual lines. Such nodes appear only between two
514 active nodes, and they have |type=delta_node|. If |p| and |r| are active nodes
515 and if |q| is a delta node between them, so that |vlink(p)=q| and |vlink(q)=r|,
516 then |q| tells the space difference between lines in the horizontal list that
517 start after breakpoint |p| and lines that start after breakpoint |r|. In
518 other words, if we know the length of the line that starts after |p| and
519 ends at our current position, then the corresponding length of the line that
520 starts after |r| is obtained by adding the amounts in node~|q|. A delta node
521 contains seven scaled numbers, since it must record the net change in glue
522 stretchability with respect to all orders of infinity. The natural width
523 difference appears in |mem[q+1].sc|; the stretch differences in units of
524 pt, sfi, fil, fill, and filll appear in |mem[q+2..q+6].sc|; and the shrink
525 difference appears in |mem[q+7].sc|. The |subtype| field of a delta node
526 is not used.
528 Actually, we have two more fields that are used by |pdftex|.
530 As the algorithm runs, it maintains a set of seven delta-like registers
531 for the length of the line following the first active breakpoint to the
532 current position in the given hlist. When it makes a pass through the
533 active list, it also maintains a similar set of seven registers for the
534 length following the active breakpoint of current interest. A third set
535 holds the length of an empty line (namely, the sum of \.{\\leftskip} and
536 \.{\\rightskip}); and a fourth set is used to create new delta nodes.
538 When we pass a delta node we want to do operations like
539 $$\hbox{\ignorespaces|for
540 k:=1 to 7 do cur_active_width[k]:=cur_active_width[k]+mem[q+k].sc|};$$ and we
541 want to do this without the overhead of |for| loops. The |do_all_six|
542 macro makes such six-tuples convenient.
545 static scaled active_width[10] = { 0 }; /*distance from first active node to~|cur_p| */
546 static scaled background[10] = { 0 }; /*length of an ``empty'' line */
547 static scaled break_width[10] = { 0 }; /*length being computed after current break */
549 static boolean auto_breaking; /*make |auto_breaking| accessible out of |line_break| */
551 @ Let's state the principles of the delta nodes more precisely and concisely,
552 so that the following programs will be less obscure. For each legal
553 breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and
554 $\beta(p)$ such that the length of material in a line from breakpoint~|p|
555 to breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$.
556 Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from
557 the beginning of the paragraph to a point ``after'' a break at |p| and to a
558 point ``before'' a break at |q|; and $\gamma$ is the width of an empty line,
559 namely the length contributed by \.{\\leftskip} and \.{\\rightskip}.
561 Suppose, for example, that the paragraph consists entirely of alternating
562 boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and
563 let the skips have widths $y_1\ldots y_n$, so that the paragraph can be
564 represented by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint
565 at $y_i$; then $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)=
566 x_1+y_1+\cdots+x_i$. To check this, note that the length of material from
567 $p_2$ to $p_5$, say, is $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5)
568 -\alpha(p_2)$.
570 The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and
571 shrinkability as well as a natural width. If we were to compute $\alpha(p)$
572 and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and
573 the multiprecise numbers would have to be kept in the active nodes.
574 \TeX\ avoids this problem by working entirely with relative differences
575 or ``deltas.'' Suppose, for example, that the active list contains
576 $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints
577 and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$
578 and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is
579 currently positioned at some other breakpoint |p|, the |active_width| array
580 contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through
581 the list of active nodes and considering a tentative line that runs from
582 $a_2$ to~|p|, say, the |cur_active_width| array will contain the value
583 $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$,
584 we want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this
585 is just $\delta_2$, which appears in the active list between $a_2$ and
586 $a_3$. The |background| array contains $\gamma$. The |break_width| array
587 will be used to calculate values of new delta nodes when the active
588 list is being updated.
590 @ The heart of the line-breaking procedure is `|try_break|', a subroutine
591 that tests if the current breakpoint |cur_p| is feasible, by running
592 through the active list to see what lines of text can be made from active
593 nodes to~|cur_p|. If feasible breaks are possible, new break nodes are
594 created. If |cur_p| is too far from an active node, that node is
595 deactivated.
597 The parameter |pi| to |try_break| is the penalty associated
598 with a break at |cur_p|; we have |pi=eject_penalty| if the break is forced,
599 and |pi=inf_penalty| if the break is illegal.
601 The other parameter, |break_type|, is set to |hyphenated_node| or |unhyphenated_node|,
602 depending on whether or not the current break is at a |disc_node|. The
603 end of a paragraph is also regarded as `|hyphenated_node|'; this case is
604 distinguishable by the condition |cur_p=null|.
607 static int internal_pen_inter; /* running \.{\\localinterlinepenalty} */
608 static int internal_pen_broken; /* running \.{\\localbrokenpenalty} */
609 static halfword internal_left_box; /* running \.{\\localleftbox} */
610 static int internal_left_box_width; /* running \.{\\localleftbox} width */
611 static halfword init_internal_left_box; /* running \.{\\localleftbox} */
612 static int init_internal_left_box_width; /* running \.{\\localleftbox} width */
613 static halfword internal_right_box; /* running \.{\\localrightbox} */
614 static int internal_right_box_width; /* running \.{\\localrightbox} width */
616 static scaled disc_width[10] = { 0 }; /* the length of discretionary material preceding a break */
618 @ As we consider various ways to end a line at |cur_p|, in a given line number
619 class, we keep track of the best total demerits known, in an array with
620 one entry for each of the fitness classifications. For example,
621 |minimal_demerits[tight_fit]| contains the fewest total demerits of feasible
622 line breaks ending at |cur_p| with a |tight_fit| line; |best_place[tight_fit]|
623 points to the passive node for the break before~|cur_p| that achieves such
624 an optimum; and |best_pl_line[tight_fit]| is the |line_number| field in the
625 active node corresponding to |best_place[tight_fit]|. When no feasible break
626 sequence is known, the |minimal_demerits| entries will be equal to
627 |awful_bad|, which is $2^{30}-1$. Another variable, |minimum_demerits|,
628 keeps track of the smallest value in the |minimal_demerits| array.
631 static int minimal_demerits[4]; /* best total demerits known for current
632 line class and position, given the fitness */
633 static int minimum_demerits; /* best total demerits known for current line class
634 and position */
635 static halfword best_place[4]; /* how to achieve |minimal_demerits| */
636 static halfword best_pl_line[4]; /*corresponding line number */
638 @ The length of lines depends on whether the user has specified
639 \.{\\parshape} or \.{\\hangindent}. If |par_shape_ptr| is not null, it
640 points to a $(2n+1)$-word record in |mem|, where the |vinfo| in the first
641 word contains the value of |n|, and the other $2n$ words contain the left
642 margins and line lengths for the first |n| lines of the paragraph; the
643 specifications for line |n| apply to all subsequent lines. If
644 |par_shape_ptr=null|, the shape of the paragraph depends on the value of
645 |n=hang_after|; if |n>=0|, hanging indentation takes place on lines |n+1|,
646 |n+2|, \dots, otherwise it takes place on lines 1, \dots, $\vert
647 n\vert$. When hanging indentation is active, the left margin is
648 |hang_indent|, if |hang_indent>=0|, else it is 0; the line length is
649 $|hsize|-\vert|hang_indent|\vert$. The normal setting is
650 |par_shape_ptr=null|, |hang_after=1|, and |hang_indent=0|.
651 Note that if |hang_indent=0|, the value of |hang_after| is irrelevant.
652 @^length of lines@> @^hanging indentation@>
655 static halfword easy_line; /*line numbers |>easy_line| are equivalent in break nodes */
656 static halfword last_special_line; /*line numbers |>last_special_line| all have the same width */
657 static scaled first_width; /*the width of all lines |<=last_special_line|, if
658 no \.{\\parshape} has been specified */
659 static scaled second_width; /*the width of all lines |>last_special_line| */
660 static scaled first_indent; /*left margin to go with |first_width| */
661 static scaled second_indent; /*left margin to go with |second_width| */
663 static halfword best_bet; /*use this passive node and its predecessors */
664 static int fewest_demerits; /*the demerits associated with |best_bet| */
665 static halfword best_line; /*line number following the last line of the new paragraph */
666 static int actual_looseness; /*the difference between |line_number(best_bet)|
667 and the optimum |best_line| */
668 static int line_diff; /*the difference between the current line number and
669 the optimum |best_line| */
671 @ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
672 |rule_node|, |ins_node|, |mark_node|, |adjust_node|,
673 |disc_node|, |whatsit_node|, and |math_node| are at the low end of the
674 type codes, by permitting a break at glue in a list if and only if the
675 |type| of the previous node is less than |math_node|. Furthermore, a
676 node is discarded after a break if its type is |math_node| or~more.
679 #define do_all_six(a) a(1);a(2);a(3);a(4);a(5);a(6);a(7)
680 #define do_seven_eight(a) if (adjust_spacing > 1) { a(8);a(9); }
681 #define do_all_eight(a) do_all_six(a); do_seven_eight(a)
682 #define do_one_seven_eight(a) a(1); do_seven_eight(a)
684 #define store_background(a) {active_width[a]=background[a];}
686 #define kern_break() { \
687 if ((!is_char_node(vlink(cur_p))) && auto_breaking) \
688 if (type(vlink(cur_p))==glue_node) \
689 ext_try_break(0, \
690 unhyphenated_node, \
691 line_break_dir, \
692 adjust_spacing, \
693 par_shape_ptr, \
694 adj_demerits, \
695 tracing_paragraphs, \
696 protrude_chars, \
697 line_penalty, \
698 last_line_fit, \
699 double_hyphen_demerits, \
700 final_hyphen_demerits, \
701 first_p, \
702 cur_p); \
703 if (type(cur_p)!=math_node) \
704 active_width[1] += width(cur_p); \
705 else \
706 active_width[1] += surround(cur_p); \
709 #define clean_up_the_memory() { \
710 q=vlink(active); \
711 while (q!=active) { \
712 cur_p = vlink(q); \
713 if (type(q)==delta_node) \
714 flush_node(q); \
715 else \
716 flush_node(q); \
717 q = cur_p; \
719 q = passive; \
720 while (q!=null) { \
721 cur_p = vlink(q); \
722 flush_node(q); \
723 q = cur_p; \
727 static boolean do_last_line_fit; /* special algorithm for last line of paragraph? */
728 static scaled fill_width[4]; /* infinite stretch components of |par_fill_skip| */
729 static scaled best_pl_short[4]; /* |shortfall| corresponding to |minimal_demerits| */
730 static scaled best_pl_glue[4]; /*corresponding glue stretch or shrink */
732 #define reset_disc_width(a) disc_width[(a)] = 0
734 #define add_disc_width_to_break_width(a) break_width[(a)] += disc_width[(a)]
735 #define sub_disc_width_from_active_width(a) active_width[(a)] -= disc_width[(a)]
737 #define add_char_shrink(a,b) a += char_shrink((b))
738 #define add_char_stretch(a,b) a += char_stretch((b))
739 #define sub_char_shrink(a,b) a -= char_shrink((b))
740 #define sub_char_stretch(a,b) a -= char_stretch((b))
742 #define add_kern_shrink(a,b) a += kern_shrink((b))
743 #define add_kern_stretch(a,b) a += kern_stretch((b))
744 #define sub_kern_shrink(a,b) a -= kern_shrink((b))
745 #define sub_kern_stretch(a,b) a -= kern_stretch((b))
747 @ This function is used to add the width of a list of nodes
748 (from a discretionary) to one of the width arrays.
750 Replacement texts and discretionary texts are supposed to contain
751 only character nodes, kern nodes, and box or rule nodes.
754 static void add_to_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths)
756 while (s != null) {
757 if (is_char_node(s)) {
758 widths[1] += pack_width(line_break_dir, dir_TRT, s, true);
759 if ((adjust_spacing > 1) && check_expand_pars(font(s))) {
760 set_prev_char_p(s);
761 add_char_stretch(widths[8], s);
762 add_char_shrink(widths[9], s);
764 } else {
765 switch (type(s)) {
766 case hlist_node:
767 case vlist_node:
768 widths[1] += pack_width(line_break_dir, box_dir(s), s, false);
769 break;
770 case kern_node:
771 if ((adjust_spacing == 2) && (subtype(s) == normal)) {
772 add_kern_stretch(widths[8], s);
773 add_kern_shrink(widths[9], s);
775 /* fall through */
776 case rule_node:
777 widths[1] += width(s);
778 break;
779 case disc_node: /* TH temp */
780 break;
781 default:
782 confusion("invalid node found in discretionary"); /* todo: report type */
785 s = vlink(s);
789 @ This function is used to substract the width of a list of nodes
790 (from a discretionary) from one of the width arrays.
791 It is used only once, but deserves it own function because of orthogonality
792 with the |add_to_widths| function.
795 static void sub_from_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths)
797 while (s != null) {
798 /* Subtract the width of node |s| from |break_width|; */
799 if (is_char_node(s)) {
800 widths[1] -= pack_width(line_break_dir, dir_TRT, s, true);
801 if ((adjust_spacing > 1) && check_expand_pars(font(s))) {
802 set_prev_char_p(s);
803 sub_char_stretch(widths[8], s);
804 sub_char_shrink(widths[9], s);
806 } else {
807 switch (type(s)) {
808 case hlist_node:
809 case vlist_node:
810 widths[1] -= pack_width(line_break_dir, box_dir(s), s, false);
811 break;
812 case kern_node:
813 if ((adjust_spacing == 2) && (subtype(s) == normal)) {
814 sub_kern_stretch(widths[8], s);
815 sub_kern_shrink(widths[9], s);
817 /* fall through */
818 case rule_node:
819 widths[1] -= width(s);
820 break;
821 case disc_node: /* TH temp */
822 break;
823 default:
824 confusion("invalid node found in discretionary"); /* todo: report type */
825 break;
828 s = vlink(s);
832 @ When we insert a new active node for a break at |cur_p|, suppose this
833 new node is to be placed just before active node |a|; then we essentially
834 want to insert `$\delta\,|cur_p|\,\delta^\prime$' before |a|, where
835 $\delta=\alpha(a)-\alpha(|cur_p|)$ and $\delta^\prime=\alpha(|cur_p|)-\alpha(a)$
836 in the notation explained above. The |cur_active_width| array now holds
837 $\gamma+\beta(|cur_p|)-\alpha(a)$; so $\delta$ can be obtained by
838 subtracting |cur_active_width| from the quantity $\gamma+\beta(|cur_p|)-
839 \alpha(|cur_p|)$. The latter quantity can be regarded as the length of a
840 line ``from |cur_p| to |cur_p|''; we call it the |break_width| at |cur_p|.
842 The |break_width| is usually negative, since it consists of the background
843 (which is normally zero) minus the width of nodes following~|cur_p| that are
844 eliminated after a break. If, for example, node |cur_p| is a glue node, the
845 width of this glue is subtracted from the background; and we also look
846 ahead to eliminate all subsequent glue and penalty and kern and math
847 nodes, subtracting their widths as well.
849 Kern nodes do not disappear at a line break unless they are |explicit|.
852 static void compute_break_width(int break_type, int line_break_dir, int adjust_spacing, halfword p)
854 halfword s = p; /* glue and other 'whitespace' to be skipped after a break;
855 used if unhyphenated, or |post_break==empty| */
856 if (break_type > unhyphenated_node && p != null) {
857 /*Compute the discretionary |break_width| values; */
858 /* When |p| is a discretionary break, the length of a line
859 ``from |p| to |p|'' has to be defined properly so
860 that the other calculations work out. Suppose that the
861 pre-break text at |p| has length $l_0$, the post-break
862 text has length $l_1$, and the replacement text has length
863 |l|. Suppose also that |q| is the node following the
864 replacement text. Then length of a line from |p| to |q|
865 will be computed as $\gamma+\beta(q)-\alpha(|p|)$, where
866 $\beta(q)=\beta(|p|)-l_0+l$. The actual length will be
867 the background plus $l_1$, so the length from |p| to
868 |p| should be $\gamma+l_0+l_1-l$. If the post-break text
869 of the discretionary is empty, a break may also discard~|q|;
870 in that unusual case we subtract the length of~|q| and any
871 other nodes that will be discarded after the discretionary
872 break.
874 TH: I don't quite understand the above remarks.
876 The value of $l_0$ need not be computed, since |line_break|
877 will put it into the global variable |disc_width| before
878 calling |try_break|.
880 /* In case of nested discretionaries, we always follow the no-break
881 path, as we are talking about the breaking on {\it this} position.
884 sub_from_widths(vlink_no_break(p), line_break_dir, adjust_spacing, break_width);
885 add_to_widths(vlink_post_break(p), line_break_dir, adjust_spacing, break_width);
886 do_one_seven_eight(add_disc_width_to_break_width);
887 if (vlink_post_break(p) == null) {
888 s = vlink(p); /* no |post_break|: 'skip' any 'whitespace' following */
889 } else {
890 s = null;
893 while (s != null) {
894 switch (type(s)) {
895 case math_node:
896 /* begin mathskip code */
897 if (math_skip == zero_glue) {
898 break_width[1] -= surround(s);
899 break;
900 } else {
901 /* fall through */
903 /* end mathskip code */
904 case glue_node:
905 /*Subtract glue from |break_width|; */
907 halfword v = glue_ptr(s);
908 break_width[1] -= width(v);
909 break_width[2 + stretch_order(v)] -= stretch(v);
910 break_width[7] -= shrink(v);
912 break;
913 case penalty_node:
914 break;
915 case kern_node:
916 if (subtype(s) != explicit_kern && subtype(s) != italic_kern)
917 return;
918 else
919 break_width[1] -= width(s);
920 break;
921 default:
922 return;
924 s = vlink(s);
928 @ @c
929 static void print_break_node(halfword q, fitness_value fit_class,
930 quarterword break_type, halfword cur_p)
932 /* Print a symbolic description of the new break node */
933 tprint_nl("@@@@");
934 print_int(serial(passive));
935 tprint(": line ");
936 print_int(line_number(q) - 1);
937 print_char('.');
938 print_int(fit_class);
939 if (break_type == hyphenated_node)
940 print_char('-');
941 tprint(" t=");
942 print_int(total_demerits(q));
943 if (do_last_line_fit) {
944 /*Print additional data in the new active node; */
945 tprint(" s=");
946 print_scaled(active_short(q));
947 if (cur_p == null)
948 tprint(" a=");
949 else
950 tprint(" g=");
951 print_scaled(active_glue(q));
953 tprint(" -> @@");
954 if (prev_break(passive) == null)
955 print_char('0');
956 else
957 print_int(serial(prev_break(passive)));
960 @ @c
961 static void print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
962 int d, boolean artificial_demerits)
964 /* Print a symbolic description of this feasible break; */
965 if (printed_node != cur_p) {
966 /* Print the list between |printed_node| and |cur_p|, then
967 set |printed_node:=cur_p|; */
968 tprint_nl("");
969 if (cur_p == null) {
970 short_display(vlink(printed_node));
971 } else {
972 halfword save_link = vlink(cur_p);
973 vlink(cur_p) = null;
974 tprint_nl("");
975 short_display(vlink(printed_node));
976 vlink(cur_p) = save_link;
978 printed_node = cur_p;
980 tprint_nl("@@");
981 if (cur_p == null) {
982 tprint_esc("par");
983 } else if (type(cur_p) != glue_node) {
984 if (type(cur_p) == penalty_node)
985 tprint_esc("penalty");
986 else if (type(cur_p) == disc_node)
987 tprint_esc("discretionary");
988 else if (type(cur_p) == kern_node)
989 tprint_esc("kern");
990 else
991 tprint_esc("math");
993 tprint(" via @@");
994 if (break_node(r) == null)
995 print_char('0');
996 else
997 print_int(serial(break_node(r)));
998 tprint(" b=");
999 if (b > inf_bad)
1000 print_char('*');
1001 else
1002 print_int(b);
1003 tprint(" p=");
1004 print_int(pi);
1005 tprint(" d=");
1006 if (artificial_demerits)
1007 print_char('*');
1008 else
1009 print_int(d);
1012 @ @c
1013 #define add_disc_width_to_active_width(a) active_width[a] += disc_width[a]
1014 #define update_width(a) cur_active_width[a] += varmem[(r+(a))].cint
1016 #define set_break_width_to_background(a) break_width[a]=background[(a)]
1018 #define convert_to_break_width(a) \
1019 varmem[(prev_r+(a))].cint = varmem[(prev_r+(a))].cint-cur_active_width[(a)]+break_width[(a)]
1021 #define store_break_width(a) active_width[(a)]=break_width[(a)]
1023 #define new_delta_to_break_width(a) \
1024 varmem[(q+(a))].cint=break_width[(a)]-cur_active_width[(a)]
1026 #define new_delta_from_break_width(a) \
1027 varmem[(q+(a))].cint=cur_active_width[(a)]-break_width[(a)]
1029 #define copy_to_cur_active(a) cur_active_width[(a)]=active_width[(a)]
1031 #define combine_two_deltas(a) varmem[(prev_r+(a))].cint += varmem[(r+(a))].cint
1032 #define downdate_width(a) cur_active_width[(a)] -= varmem[(prev_r+(a))].cint
1033 #define update_active(a) active_width[(a)]+=varmem[(r+(a))].cint
1035 #define total_font_stretch cur_active_width[8]
1036 #define total_font_shrink cur_active_width[9]
1038 #define cal_margin_kern_var(a) { \
1039 character(cp) = character((a)); \
1040 font(cp) = font((a)); \
1041 do_subst_font(cp, 1000); \
1042 if (font(cp) != font((a))) \
1043 margin_kern_stretch += (left_pw((a)) - left_pw(cp)); \
1044 font(cp) = font((a)); \
1045 do_subst_font(cp, -1000); \
1046 if (font(cp) != font((a))) \
1047 margin_kern_shrink += (left_pw(cp) - left_pw((a))); \
1050 static void ext_try_break(int pi,
1051 quarterword break_type,
1052 int line_break_dir,
1053 int adjust_spacing,
1054 int par_shape_ptr,
1055 int adj_demerits,
1056 int tracing_paragraphs,
1057 int protrude_chars,
1058 int line_penalty,
1059 int last_line_fit,
1060 int double_hyphen_demerits,
1061 int final_hyphen_demerits, halfword first_p, halfword cur_p)
1063 /* labels: |CONTINUE,DEACTIVATE,FOUND,NOT_FOUND|; */
1064 pointer r; /* runs through the active list */
1065 scaled margin_kern_stretch;
1066 scaled margin_kern_shrink;
1067 halfword lp, rp, cp;
1068 halfword prev_r = active; /* stays a step behind |r| */
1069 halfword prev_prev_r = null; /*a step behind |prev_r|, if |type(prev_r)=delta_node| */
1070 halfword old_l = 0; /* maximum line number in current equivalence class of lines */
1071 boolean no_break_yet = true; /* have we found a feasible break at |cur_p|? */
1072 halfword q; /*points to a new node being created */
1073 halfword l; /*line number of current active node */
1074 boolean node_r_stays_active; /*should node |r| remain in the active list? */
1075 scaled line_width = 0; /*the current line will be justified to this width */
1076 fitness_value fit_class; /*possible fitness class of test line */
1077 halfword b; /*badness of test line */
1078 int d; /*demerits of test line */
1079 boolean artificial_demerits; /*has |d| been forced to zero? */
1081 scaled shortfall; /*used in badness calculations */
1082 scaled g = 0; /*glue stretch or shrink of test line, adjustment for last line */
1083 scaled cur_active_width[10] = { 0 }; /*distance from current active node */
1085 /*Make sure that |pi| is in the proper range; */
1086 if (pi >= inf_penalty) {
1087 return; /* this breakpoint is inhibited by infinite penalty */
1088 } else if (pi <= -inf_penalty) {
1089 pi = eject_penalty; /*this breakpoint will be forced */
1092 do_all_eight(copy_to_cur_active);
1094 while (1) {
1095 r = vlink(prev_r);
1096 /* If node |r| is of type |delta_node|, update |cur_active_width|,
1097 set |prev_r| and |prev_prev_r|, then |goto continue|; */
1098 /* The following code uses the fact that |type(active)<>delta_node| */
1099 if (type(r) == delta_node) {
1100 do_all_eight(update_width); /* IMPLICIT ,r */
1101 prev_prev_r = prev_r;
1102 prev_r = r;
1103 continue;
1105 /* If a line number class has ended, create new active nodes for
1106 the best feasible breaks in that class; then |return|
1107 if |r=active|, otherwise compute the new |line_width|; */
1108 /* The first part of the following code is part of \TeX's inner loop, so
1109 we don't want to waste any time. The current active node, namely node |r|,
1110 contains the line number that will be considered next. At the end of the
1111 list we have arranged the data structure so that |r=active| and
1112 |line_number(active)>old_l|.
1114 l = line_number(r);
1115 if (l > old_l) { /* now we are no longer in the inner loop */
1116 if ((minimum_demerits < awful_bad)
1117 && ((old_l != easy_line) || (r == active))) {
1118 /*Create new active nodes for the best feasible breaks just found */
1119 /* It is not necessary to create new active nodes having |minimal_demerits|
1120 greater than
1121 |minimum_demerits+abs(adj_demerits)|, since such active nodes will never
1122 be chosen in the final paragraph breaks. This observation allows us to
1123 omit a substantial number of feasible breakpoints from further consideration.
1125 if (no_break_yet) {
1126 no_break_yet = false;
1127 do_all_eight(set_break_width_to_background);
1128 compute_break_width(break_type, line_break_dir, adjust_spacing, cur_p);
1130 /* Insert a delta node to prepare for breaks at |cur_p|; */
1131 /* We use the fact that |type(active)<>delta_node|. */
1132 if (type(prev_r) == delta_node) { /* modify an existing delta node */
1133 do_all_eight(convert_to_break_width); /* IMPLICIT |prev_r| */
1134 } else if (prev_r == active) { /* no delta node needed at the beginning */
1135 do_all_eight(store_break_width);
1136 } else {
1137 q = new_node(delta_node, 0);
1138 vlink(q) = r;
1139 do_all_eight(new_delta_to_break_width); /* IMPLICIT q */
1140 vlink(prev_r) = q;
1141 prev_prev_r = prev_r;
1142 prev_r = q;
1145 if (abs(adj_demerits) >= awful_bad - minimum_demerits)
1146 minimum_demerits = awful_bad - 1;
1147 else
1148 minimum_demerits += abs(adj_demerits);
1149 for (fit_class = very_loose_fit; fit_class <= tight_fit;
1150 fit_class++) {
1151 if (minimal_demerits[fit_class] <= minimum_demerits) {
1152 /* Insert a new active node from |best_place[fit_class]|
1153 to |cur_p|; */
1154 /* When we create an active node, we also create the corresponding
1155 passive node.
1157 q = new_node(passive_node, 0);
1158 vlink(q) = passive;
1159 passive = q;
1160 cur_break(q) = cur_p;
1161 incr(pass_number);
1162 serial(q) = pass_number;
1163 prev_break(q) = best_place[fit_class];
1164 /*Here we keep track of the subparagraph penalties in the break nodes */
1165 passive_pen_inter(q) = internal_pen_inter;
1166 passive_pen_broken(q) = internal_pen_broken;
1167 passive_last_left_box(q) = internal_left_box;
1168 passive_last_left_box_width(q) =
1169 internal_left_box_width;
1170 if (prev_break(q) != null) {
1171 passive_left_box(q) =
1172 passive_last_left_box(prev_break(q));
1173 passive_left_box_width(q) =
1174 passive_last_left_box_width(prev_break(q));
1175 } else {
1176 passive_left_box(q) = init_internal_left_box;
1177 passive_left_box_width(q) =
1178 init_internal_left_box_width;
1180 passive_right_box(q) = internal_right_box;
1181 passive_right_box_width(q) = internal_right_box_width;
1182 q = new_node(break_type, fit_class);
1183 break_node(q) = passive;
1184 line_number(q) = best_pl_line[fit_class] + 1;
1185 total_demerits(q) = minimal_demerits[fit_class];
1186 if (do_last_line_fit) {
1187 /*Store additional data in the new active node */
1188 /* Here we save these data in the active node
1189 representing a potential line break. */
1190 active_short(q) = best_pl_short[fit_class];
1191 active_glue(q) = best_pl_glue[fit_class];
1193 vlink(q) = r;
1194 vlink(prev_r) = q;
1195 prev_r = q;
1196 if (tracing_paragraphs > 0)
1197 print_break_node(q, fit_class, break_type, cur_p);
1199 minimal_demerits[fit_class] = awful_bad;
1201 minimum_demerits = awful_bad;
1202 /* Insert a delta node to prepare for the next active node; */
1203 /* When the following code is performed, we will have just inserted at
1204 least one active node before |r|, so |type(prev_r)<>delta_node|.
1206 if (r != active) {
1207 q = new_node(delta_node, 0);
1208 vlink(q) = r;
1209 do_all_eight(new_delta_from_break_width); /* IMPLICIT q */
1210 vlink(prev_r) = q;
1211 prev_prev_r = prev_r;
1212 prev_r = q;
1215 if (r == active)
1216 return;
1217 /*Compute the new line width; */
1218 /* When we come to the following code, we have just encountered
1219 the first active node~|r| whose |line_number| field contains
1220 |l|. Thus we want to compute the length of the $l\mskip1mu$th
1221 line of the current paragraph. Furthermore, we want to set
1222 |old_l| to the last number in the class of line numbers
1223 equivalent to~|l|.
1225 if (l > easy_line) {
1226 old_l = max_halfword - 1;
1227 line_width = second_width;
1228 } else {
1229 old_l = l;
1230 if (l > last_special_line) {
1231 line_width = second_width;
1232 } else if (par_shape_ptr == null) {
1233 line_width = first_width;
1234 } else {
1235 line_width = varmem[(par_shape_ptr + 2 * l + 1)].cint;
1239 /* /If a line number class has ended, create new active nodes for
1240 the best feasible breaks in that class; then |return|
1241 if |r=active|, otherwise compute the new |line_width|; */
1243 /* Consider the demerits for a line from |r| to |cur_p|;
1244 deactivate node |r| if it should no longer be active;
1245 then |goto continue| if a line from |r| to |cur_p| is infeasible,
1246 otherwise record a new feasible break; */
1247 artificial_demerits = false;
1248 shortfall = line_width - cur_active_width[1];
1249 if (break_node(r) == null)
1250 shortfall -= init_internal_left_box_width;
1251 else
1252 shortfall -= passive_last_left_box_width(break_node(r));
1253 shortfall -= internal_right_box_width;
1254 if (protrude_chars > 1) {
1255 halfword l1, o;
1256 l1 = (break_node(r) == null) ? first_p : cur_break(break_node(r));
1257 if (cur_p == null) {
1258 o = null;
1259 } else { /* TODO |if (is_character_node(alink(cur_p)))| */
1260 o = alink(cur_p);
1261 assert(vlink(o) == cur_p);
1263 /* MAGIC: the disc could be a SELECT subtype, to we might need
1264 to get the last character as |pre_break| from either the
1265 |pre_break| list (if the previous INIT disc was taken), or the
1266 |no_break| (sic) list (if the previous INIT disc was not taken)
1268 BUT:
1269 the last characters (hyphenation character) if these two list
1270 should always be the same anyway, so we just look at |pre_break|.
1272 /* let's look at the right margin first */
1273 if ((cur_p != null) && (type(cur_p) == disc_node)
1274 && (vlink_pre_break(cur_p) != null)) {
1275 /* a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break| */
1276 o = tlink_pre_break(cur_p);
1277 } else {
1278 o = find_protchar_right(l1, o);
1280 /* now the left margin */
1281 if ((l1 != null) && (type(l1) == disc_node) && (vlink_post_break(l1) != null)) {
1282 /* FIXME: first 'char' could be a disc! */
1283 l1 = vlink_post_break(l1); /* protrude the first char */
1284 } else {
1285 l1 = find_protchar_left(l1, true);
1287 shortfall += (left_pw(l1) + right_pw(o));
1289 if ((shortfall != 0) && (adjust_spacing == 2)) {
1290 margin_kern_stretch = 0;
1291 margin_kern_shrink = 0;
1292 if (protrude_chars > 1) {
1293 /* Calculate variations of marginal kerns; */
1294 lp = last_leftmost_char;
1295 rp = last_rightmost_char;
1296 cp = raw_glyph_node();
1297 if (lp != null) {
1298 cal_margin_kern_var(lp);
1300 if (rp != null) {
1301 cal_margin_kern_var(rp);
1303 flush_node(cp);
1305 if ((shortfall > 0)
1306 && ((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)
1312 && ((total_font_shrink + margin_kern_shrink) > 0)) {
1313 if ((total_font_shrink + margin_kern_shrink) > -shortfall)
1314 shortfall = -((total_font_shrink + margin_kern_shrink) / (max_shrink_ratio / cur_font_step)) / 2;
1315 else
1316 shortfall += (total_font_shrink + margin_kern_shrink);
1319 if (shortfall > 0) {
1320 /* Set the value of |b| to the badness for stretching the line,
1321 and compute the corresponding |fit_class| */
1323 /* When a line must stretch, the available stretchability can be
1324 found in the subarray |cur_active_width[2..6]|, in units of
1325 points, sfi, fil, fill and filll.
1327 The present section is part of \TeX's inner loop, and it is
1328 most often performed when the badness is infinite; therefore
1329 it is worth while to make a quick test for large width excess
1330 and small stretchability, before calling the |badness|
1331 subroutine. */
1333 if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) ||
1334 (cur_active_width[5] != 0) || (cur_active_width[6] != 0)) {
1335 if (do_last_line_fit) {
1336 if (cur_p == null) { /* the last line of a paragraph */
1337 /* Perform computations for last line and |goto found|; */
1339 /* Here we compute the adjustment |g| and badness |b| for
1340 a line from |r| to the end of the paragraph. When any
1341 of the criteria for adjustment is violated we fall
1342 through to the normal algorithm.
1344 The last line must be too short, and have infinite
1345 stretch entirely due to |par_fill_skip|. */
1346 if ((active_short(r) == 0) || (active_glue(r) <= 0))
1347 /* previous line was neither stretched nor shrunk, or
1348 was infinitely bad */
1349 goto NOT_FOUND;
1350 if ((cur_active_width[3] != fill_width[0]) ||
1351 (cur_active_width[4] != fill_width[1]) ||
1352 (cur_active_width[5] != fill_width[2]) ||
1353 (cur_active_width[6] != fill_width[3]))
1354 /* infinite stretch of this line not entirely due to
1355 |par_fill_skip| */
1356 goto NOT_FOUND;
1357 if (active_short(r) > 0)
1358 g = cur_active_width[2];
1359 else
1360 g = cur_active_width[7];
1361 if (g <= 0)
1362 /*no finite stretch resp.\ no shrink */
1363 goto NOT_FOUND;
1364 arith_error = false;
1365 g = fract(g, active_short(r), active_glue(r),
1366 max_dimen);
1367 if (last_line_fit < 1000)
1368 g = fract(g, last_line_fit, 1000, max_dimen);
1369 if (arith_error) {
1370 if (active_short(r) > 0)
1371 g = max_dimen;
1372 else
1373 g = -max_dimen;
1375 if (g > 0) {
1376 /*Set the value of |b| to the badness of the last line
1377 for stretching, compute the corresponding |fit_class,
1378 and |goto found|| */
1379 /* These badness computations are rather similar to
1380 those of the standard algorithm, with the adjustment
1381 amount |g| replacing the |shortfall|. */
1382 if (g > shortfall)
1383 g = shortfall;
1384 if (g > 7230584) {
1385 if (cur_active_width[2] < 1663497) {
1386 b = inf_bad;
1387 fit_class = very_loose_fit;
1388 goto FOUND;
1391 b = badness(g, cur_active_width[2]);
1392 if (b > 99) {
1393 fit_class = very_loose_fit;
1394 } else if (b > 12) {
1395 fit_class = loose_fit;
1396 } else {
1397 fit_class = decent_fit;
1399 goto FOUND;
1400 } else if (g < 0) {
1401 /*Set the value of |b| to the badness of the last line
1402 for shrinking, compute the corresponding |fit_class,
1403 and |goto found||; */
1404 if (-g > cur_active_width[7])
1405 g = -cur_active_width[7];
1406 b = badness(-g, cur_active_width[7]);
1407 if (b > 12)
1408 fit_class = tight_fit;
1409 else
1410 fit_class = decent_fit;
1411 goto FOUND;
1414 NOT_FOUND:
1415 shortfall = 0;
1417 b = 0;
1418 fit_class = decent_fit; /* infinite stretch */
1419 } else {
1420 if (shortfall > 7230584 && cur_active_width[2] < 1663497) {
1421 b = inf_bad;
1422 fit_class = very_loose_fit;
1423 } else {
1424 b = badness(shortfall, cur_active_width[2]);
1425 if (b > 99) {
1426 fit_class = very_loose_fit;
1427 } else if (b > 12) {
1428 fit_class = loose_fit;
1429 } else {
1430 fit_class = decent_fit;
1434 } else {
1435 /* Set the value of |b| to the badness for shrinking the line,
1436 and compute the corresponding |fit_class|; */
1437 /* Shrinkability is never infinite in a paragraph; we can shrink
1438 the line from |r| to |cur_p| by at most
1439 |cur_active_width[7]|. */
1440 if (-shortfall > cur_active_width[7])
1441 b = inf_bad + 1;
1442 else
1443 b = badness(-shortfall, cur_active_width[7]);
1444 if (b > 12)
1445 fit_class = tight_fit;
1446 else
1447 fit_class = decent_fit;
1449 if (do_last_line_fit) {
1450 /* Adjust the additional data for last line; */
1451 if (cur_p == null)
1452 shortfall = 0;
1453 if (shortfall > 0) {
1454 g = cur_active_width[2];
1455 } else if (shortfall < 0) {
1456 g = cur_active_width[7];
1457 } else {
1458 g = 0;
1461 FOUND:
1462 if ((b > inf_bad) || (pi == eject_penalty)) {
1463 /* Prepare to deactivate node~|r|, and |goto deactivate| unless
1464 there is a reason to consider lines of text from |r| to |cur_p| */
1465 /* During the final pass, we dare not lose all active nodes, lest we lose
1466 touch with the line breaks already found. The code shown here makes
1467 sure that such a catastrophe does not happen, by permitting overfull
1468 boxes as a last resort. This particular part of \TeX\ was a source of
1469 several subtle bugs before the correct program logic was finally
1470 discovered; readers who seek to ``improve'' \TeX\ should therefore
1471 think thrice before daring to make any changes here.
1473 if (final_pass && (minimum_demerits == awful_bad) &&
1474 (vlink(r) == active) && (prev_r == active)) {
1475 artificial_demerits = true; /* set demerits zero, this break is forced */
1476 } else if (b > threshold) {
1477 goto DEACTIVATE;
1479 node_r_stays_active = false;
1480 } else {
1481 prev_r = r;
1482 if (b > threshold)
1483 continue;
1484 node_r_stays_active = true;
1486 /* Record a new feasible break; */
1487 /* When we get to this part of the code, the line from |r| to |cur_p| is
1488 feasible, its badness is~|b|, and its fitness classification is
1489 |fit_class|. We don't want to make an active node for this break yet,
1490 but we will compute the total demerits and record them in the
1491 |minimal_demerits| array, if such a break is the current champion among
1492 all ways to get to |cur_p| in a given line-number class and fitness
1493 class.
1495 if (artificial_demerits) {
1496 d = 0;
1497 } else {
1498 /* Compute the demerits, |d|, from |r| to |cur_p|; */
1499 d = line_penalty + b;
1500 if (abs(d) >= 10000)
1501 d = 100000000;
1502 else
1503 d = d * d;
1504 if (pi != 0) {
1505 if (pi > 0) {
1506 d += (pi * pi);
1507 } else if (pi > eject_penalty) {
1508 d -= (pi * pi);
1511 if ((break_type == hyphenated_node) && (type(r) == hyphenated_node)) {
1512 if (cur_p != null)
1513 d += double_hyphen_demerits;
1514 else
1515 d += final_hyphen_demerits;
1517 if (abs(fit_class - fitness(r)) > 1)
1518 d = d + adj_demerits;
1520 if (tracing_paragraphs > 0)
1521 print_feasible_break(cur_p, r, b, pi, d, artificial_demerits);
1522 d += total_demerits(r); /*this is the minimum total demerits
1523 from the beginning to |cur_p| via |r| */
1524 if (d <= minimal_demerits[fit_class]) {
1525 minimal_demerits[fit_class] = d;
1526 best_place[fit_class] = break_node(r);
1527 best_pl_line[fit_class] = l;
1528 if (do_last_line_fit) {
1529 /* Store additional data for this feasible break; */
1530 /* For each feasible break we record the shortfall and glue stretch or
1531 shrink (or adjustment). */
1532 best_pl_short[fit_class] = shortfall;
1533 best_pl_glue[fit_class] = g;
1535 if (d < minimum_demerits)
1536 minimum_demerits = d;
1538 /* /Record a new feasible break */
1539 if (node_r_stays_active)
1540 continue; /*|prev_r| has been set to |r| */
1541 DEACTIVATE:
1542 /* Deactivate node |r|; */
1543 /* When an active node disappears, we must delete an adjacent delta node if
1544 the active node was at the beginning or the end of the active list, or
1545 if it was surrounded by delta nodes. We also must preserve the property
1546 that |cur_active_width| represents the length of material from
1547 |vlink(prev_r)| to~|cur_p|. */
1549 vlink(prev_r) = vlink(r);
1550 flush_node(r);
1551 if (prev_r == active) {
1552 /*Update the active widths, since the first active node has been
1553 deleted */
1554 /* The following code uses the fact that |type(active)<>delta_node|.
1555 If the active list has just become empty, we do not need to update the
1556 |active_width| array, since it will be initialized when an active
1557 node is next inserted.
1559 r = vlink(active);
1560 if (type(r) == delta_node) {
1561 do_all_eight(update_active); /* IMPLICIT r */
1562 do_all_eight(copy_to_cur_active);
1563 vlink(active) = vlink(r);
1564 flush_node(r);
1566 } else if (type(prev_r) == delta_node) {
1567 r = vlink(prev_r);
1568 if (r == active) {
1569 do_all_eight(downdate_width); /* IMPLICIT |prev_r| */
1570 vlink(prev_prev_r) = active;
1571 flush_node(prev_r);
1572 prev_r = prev_prev_r;
1573 } else if (type(r) == delta_node) {
1574 do_all_eight(update_width); /* IMPLICIT ,r */
1575 do_all_eight(combine_two_deltas); /* IMPLICIT r |prev_r| */
1576 vlink(prev_r) = vlink(r);
1577 flush_node(r);
1583 @ @c
1584 void ext_do_line_break(int paragraph_dir,
1585 int pretolerance,
1586 int tracing_paragraphs,
1587 int tolerance,
1588 scaled emergency_stretch,
1589 int looseness,
1590 int adjust_spacing,
1591 halfword par_shape_ptr,
1592 int adj_demerits,
1593 int protrude_chars,
1594 int line_penalty,
1595 int last_line_fit,
1596 int double_hyphen_demerits,
1597 int final_hyphen_demerits,
1598 int hang_indent,
1599 int hsize,
1600 int hang_after,
1601 halfword left_skip,
1602 halfword right_skip,
1603 halfword inter_line_penalties_ptr,
1604 int inter_line_penalty,
1605 int club_penalty,
1606 halfword club_penalties_ptr,
1607 halfword widow_penalties_ptr,
1608 int widow_penalty,
1609 int broken_penalty,
1610 halfword final_par_glue)
1612 /* DONE,DONE1,DONE2,DONE3,DONE4,DONE5,CONTINUE; */
1613 halfword cur_p, q, r, s; /* miscellaneous nodes of temporary interest */
1614 int line_break_dir = paragraph_dir;
1616 /* Get ready to start ... */
1617 minimum_demerits = awful_bad;
1618 minimal_demerits[tight_fit] = awful_bad;
1619 minimal_demerits[decent_fit] = awful_bad;
1620 minimal_demerits[loose_fit] = awful_bad;
1621 minimal_demerits[very_loose_fit] = awful_bad;
1623 /* We compute the values of |easy_line| and the other local variables relating
1624 to line length when the |line_break| procedure is initializing itself. */
1625 if (par_shape_ptr == null) {
1626 if (hang_indent == 0) {
1627 last_special_line = 0;
1628 second_width = hsize;
1629 second_indent = 0;
1630 } else {
1631 /* Set line length parameters in preparation for hanging indentation */
1632 /* We compute the values of |easy_line| and the other local variables relating
1633 to line length when the |line_break| procedure is initializing itself. */
1634 last_special_line = abs(hang_after);
1635 if (hang_after < 0) {
1636 first_width = hsize - abs(hang_indent);
1637 if (hang_indent >= 0)
1638 first_indent = hang_indent;
1639 else
1640 first_indent = 0;
1641 second_width = hsize;
1642 second_indent = 0;
1643 } else {
1644 first_width = hsize;
1645 first_indent = 0;
1646 second_width = hsize - abs(hang_indent);
1647 if (hang_indent >= 0)
1648 second_indent = hang_indent;
1649 else
1650 second_indent = 0;
1653 } else {
1654 last_special_line = vinfo(par_shape_ptr + 1) - 1;
1655 second_indent =
1656 varmem[(par_shape_ptr + 2 * (last_special_line + 1))].cint;
1657 second_width =
1658 varmem[(par_shape_ptr + 2 * (last_special_line + 1) + 1)].cint;
1660 if (looseness == 0)
1661 easy_line = last_special_line;
1662 else
1663 easy_line = max_halfword;
1665 no_shrink_error_yet = true;
1666 check_shrinkage(left_skip);
1667 check_shrinkage(right_skip);
1668 q = left_skip;
1669 r = right_skip;
1670 background[1] = width(q) + width(r);
1671 background[2] = 0;
1672 background[3] = 0;
1673 background[4] = 0;
1674 background[5] = 0;
1675 background[6] = 0;
1676 background[2 + stretch_order(q)] = stretch(q);
1677 background[2 + stretch_order(r)] += stretch(r);
1678 background[7] = shrink(q) + shrink(r);
1679 if (adjust_spacing > 1) {
1680 background[8] = 0;
1681 background[9] = 0;
1682 max_stretch_ratio = -1;
1683 max_shrink_ratio = -1;
1684 cur_font_step = -1;
1685 set_prev_char_p(null);
1687 /* Check for special treatment of last line of paragraph; */
1688 /* The new algorithm for the last line requires that the stretchability
1689 |par_fill_skip| is infinite and the stretchability of |left_skip| plus
1690 |right_skip| is finite.
1692 do_last_line_fit = false;
1693 if (last_line_fit > 0) {
1694 q = glue_ptr(last_line_fill);
1695 if ((stretch(q) > 0) && (stretch_order(q) > normal)) {
1696 if ((background[3] == 0) && (background[4] == 0) &&
1697 (background[5] == 0) && (background[6] == 0)) {
1698 do_last_line_fit = true;
1699 fill_width[0] = 0;
1700 fill_width[1] = 0;
1701 fill_width[2] = 0;
1702 fill_width[3] = 0;
1703 fill_width[stretch_order(q) - 1] = stretch(q);
1707 /* DIR: Initialize |dir_ptr| for |line_break| */
1708 if (dir_ptr != null) {
1709 flush_node_list(dir_ptr);
1710 dir_ptr = null;
1712 #if 0
1713 push_dir(dir_ptr,paragraph_dir); /* TODO what was the point of this? */
1714 #endif
1716 /* Find optimal breakpoints; */
1717 threshold = pretolerance;
1718 if (threshold >= 0) {
1719 if (tracing_paragraphs > 0) {
1720 begin_diagnostic();
1721 tprint_nl("@@firstpass");
1723 second_pass = false;
1724 final_pass = false;
1725 } else {
1726 threshold = tolerance;
1727 second_pass = true;
1728 final_pass = (emergency_stretch <= 0);
1729 if (tracing_paragraphs > 0)
1730 begin_diagnostic();
1732 while (1) {
1733 halfword first_p;
1734 halfword nest_stack[10];
1735 int nest_index = 0;
1736 if (threshold > inf_bad)
1737 threshold = inf_bad;
1738 /* Create an active breakpoint representing the beginning of the paragraph */
1739 q = new_node(unhyphenated_node, decent_fit);
1740 vlink(q) = active;
1741 break_node(q) = null;
1742 line_number(q) = cur_list.pg_field + 1;
1743 total_demerits(q) = 0;
1744 active_short(q) = 0;
1745 active_glue(q) = 0;
1746 vlink(active) = q;
1747 do_all_eight(store_background);
1748 passive = null;
1749 printed_node = temp_head;
1750 pass_number = 0;
1751 font_in_short_display = null_font;
1752 /* /Create an active breakpoint representing the beginning of the paragraph */
1753 auto_breaking = true;
1754 cur_p = vlink(temp_head);
1755 /* LOCAL: Initialize with first |local_paragraph| node */
1756 if ((cur_p != null) && (type(cur_p) == local_par_node)) {
1757 alink(cur_p) = temp_head; /* this used to be an assert, but may as well force it */
1758 internal_pen_inter = local_pen_inter(cur_p);
1759 internal_pen_broken = local_pen_broken(cur_p);
1760 init_internal_left_box = local_box_left(cur_p);
1761 init_internal_left_box_width = local_box_left_width(cur_p);
1762 internal_left_box = init_internal_left_box;
1763 internal_left_box_width = init_internal_left_box_width;
1764 internal_right_box = local_box_right(cur_p);
1765 internal_right_box_width = local_box_right_width(cur_p);
1766 } else {
1767 internal_pen_inter = 0;
1768 internal_pen_broken = 0;
1769 init_internal_left_box = null;
1770 init_internal_left_box_width = 0;
1771 internal_left_box = init_internal_left_box;
1772 internal_left_box_width = init_internal_left_box_width;
1773 internal_right_box = null;
1774 internal_right_box_width = 0;
1776 /* /LOCAL: Initialize with first |local_paragraph| node */
1777 set_prev_char_p(null);
1778 first_p = cur_p;
1779 /* to access the first node of paragraph as the first active node
1780 has |break_node=null| */
1781 while ((cur_p != null) && (vlink(active) != active)) {
1782 /* |try_break| if |cur_p| is a legal breakpoint; on the 2nd pass, also look at |disc_node|s. */
1784 while (is_char_node(cur_p)) {
1785 /* Advance |cur_p| to the node following the present string of characters ; */
1786 /* The code that passes over the characters of words in a paragraph is part of
1787 \TeX's inner loop, so it has been streamlined for speed. We use the fact that
1788 `\.{\\parfillskip}' glue appears at the end of each paragraph; it is therefore
1789 unnecessary to check if |vlink(cur_p)=null| when |cur_p| is a character node.
1791 active_width[1] += pack_width(line_break_dir, dir_TRT, cur_p, true);
1792 if ((adjust_spacing > 1) && check_expand_pars(font(cur_p))) {
1793 set_prev_char_p(cur_p);
1794 add_char_stretch(active_width[8], cur_p);
1795 add_char_shrink(active_width[9], cur_p);
1797 cur_p = vlink(cur_p);
1798 while (cur_p == null && nest_index > 0) {
1799 cur_p = nest_stack[--nest_index];
1802 if (cur_p == null) {
1803 normal_error("linebreak","invalid list tail, probably missing glue");
1805 /* Determine legal breaks: As we move through the hlist, we need to keep
1806 the |active_width| array up to date, so that the badness of individual
1807 lines is readily calculated by |try_break|. It is convenient to use the
1808 short name |active_width[1]| for the component of active width that represents
1809 real width as opposed to glue. */
1811 switch (type(cur_p)) {
1812 case hlist_node:
1813 case vlist_node:
1814 active_width[1] += pack_width(line_break_dir, box_dir(cur_p), cur_p, false);
1815 break;
1816 case rule_node:
1817 active_width[1] += width(cur_p);
1818 break;
1819 case dir_node: /* DIR: Adjust the dir stack for the |line_break| routine; */
1820 if (dir_dir(cur_p) >= 0) {
1821 line_break_dir = dir_dir(cur_p);
1822 push_dir_node(dir_ptr,cur_p); /* adds to |dir_ptr| */
1823 } else {
1824 pop_dir_node(dir_ptr);
1825 if (dir_ptr != null) {
1826 line_break_dir = dir_dir(dir_ptr);
1829 break;
1830 case local_par_node: /* LOCAL: Advance past a |local_paragraph| node; */
1831 internal_pen_inter = local_pen_inter(cur_p);
1832 internal_pen_broken = local_pen_broken(cur_p);
1833 internal_left_box = local_box_left(cur_p);
1834 internal_left_box_width = local_box_left_width(cur_p);
1835 internal_right_box = local_box_right(cur_p);
1836 internal_right_box_width = local_box_right_width(cur_p);
1837 break;
1838 case math_node:
1839 auto_breaking = (subtype(cur_p) == after);
1840 /* begin mathskip code */
1841 if (math_skip == zero_glue) {
1842 kern_break();
1843 break;
1844 } else {
1845 /* fall through */
1847 /* end mathskip code */
1848 case glue_node:
1850 If node |cur_p| is a legal breakpoint, call |try_break|;
1851 then update the active widths by including the glue in
1852 |glue_ptr(cur_p)|;
1854 When node |cur_p| is a glue node, we look at the previous
1855 to see whether or not a breakpoint is legal at |cur_p|,
1856 as explained above.
1858 The |precedes_break| test also considers dir nodes and prohibits
1859 a break after an opening dir_node (positive dir). In |\textdir TRT x|
1860 the space after |TRT| is preserved and therefore the dir node
1861 is bound to the |x|. Being more clever makes no sense: users
1862 should code their input properly.
1864 if (auto_breaking) {
1865 halfword prev_p = alink(cur_p);
1866 if (prev_p != temp_head && (
1867 is_char_node(prev_p)
1868 || precedes_break(prev_p)
1869 || ((type(prev_p) == kern_node) && (subtype(prev_p) != explicit_kern &&
1870 subtype(prev_p) != italic_kern ))
1871 )) {
1872 ext_try_break(0, unhyphenated_node, line_break_dir, adjust_spacing,
1873 par_shape_ptr, adj_demerits,
1874 tracing_paragraphs, protrude_chars,
1875 line_penalty, last_line_fit,
1876 double_hyphen_demerits,
1877 final_hyphen_demerits, first_p, cur_p);
1880 /* *INDENT-ON* */
1881 check_shrinkage(glue_ptr(cur_p));
1882 q = glue_ptr(cur_p);
1883 active_width[1] += width(q);
1884 active_width[2 + stretch_order(q)] += stretch(q);
1885 active_width[7] += shrink(q);
1886 /* begin mathskip code */
1887 if (type(cur_p)==math_node) {
1888 active_width[1]+=surround(cur_p);
1890 /* end mathskip code */
1891 break;
1892 case kern_node:
1893 if (subtype(cur_p) == explicit_kern || subtype(cur_p) == italic_kern) {
1894 kern_break();
1895 } else {
1896 active_width[1] += width(cur_p);
1897 if ((adjust_spacing == 2) && (subtype(cur_p) == normal)) {
1898 add_kern_stretch(active_width[8], cur_p);
1899 add_kern_shrink(active_width[9], cur_p);
1902 break;
1903 case disc_node:
1904 /* |select_disc|s are handled by the leading |init_disc| */
1905 if (subtype(cur_p) == select_disc)
1906 break;
1907 /* Try to break after a discretionary fragment, then |goto done5|; */
1908 /* The following code knows that discretionary texts contain
1909 only character nodes, kern nodes, box nodes, and rule
1910 nodes. This branch differs a bit from older engines because in LuaTeX we
1911 already have hyphenated the list. This means that we need to skip
1912 automatic disc nodes. Of better, we need to treat discretionaries
1913 and explicit hyphens always, even in the first pass (HH). */
1914 if (second_pass || subtype(cur_p) <= automatic_disc) {
1916 int actual_penalty = hyphen_penalty;
1917 if (disc_penalty(cur_p) != 0) {
1918 actual_penalty = (int) disc_penalty(cur_p);
1919 } else if (subtype(cur_p) == automatic_disc) {
1920 actual_penalty = ex_hyphen_penalty;
1923 int actual_penalty = (int) disc_penalty(cur_p);
1924 s = vlink_pre_break(cur_p);
1925 do_one_seven_eight(reset_disc_width);
1926 if (s == null) { /* trivial pre-break */
1927 ext_try_break(actual_penalty, hyphenated_node,
1928 line_break_dir, adjust_spacing,
1929 par_shape_ptr, adj_demerits,
1930 tracing_paragraphs, protrude_chars,
1931 line_penalty, last_line_fit,
1932 double_hyphen_demerits,
1933 final_hyphen_demerits, first_p, cur_p);
1934 } else {
1935 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1936 do_one_seven_eight(add_disc_width_to_active_width);
1937 ext_try_break(actual_penalty, hyphenated_node,
1938 line_break_dir, adjust_spacing,
1939 par_shape_ptr, adj_demerits,
1940 tracing_paragraphs, protrude_chars,
1941 line_penalty, last_line_fit,
1942 double_hyphen_demerits,
1943 final_hyphen_demerits, first_p, cur_p);
1944 if (subtype(cur_p) == init_disc) {
1945 /* we should at two break points after the one we
1946 added above:
1947 \item1 which does a possible break in INIT's |post_break|
1948 \item2 which means the |no_break| actually was broken
1949 just a character later */
1950 /* do the select-0 case 'f-f-i' */
1951 s = vlink_pre_break(vlink(cur_p));
1952 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1953 ext_try_break(actual_penalty, hyphenated_node,
1954 line_break_dir, adjust_spacing,
1955 par_shape_ptr, adj_demerits,
1956 tracing_paragraphs,
1957 protrude_chars, line_penalty,
1958 last_line_fit, double_hyphen_demerits,
1959 final_hyphen_demerits, first_p,
1960 vlink(cur_p));
1961 #if 0
1962 /* TODO this does not work */
1963 /* go back to the starting situation */
1964 do_one_seven_eight(sub_disc_width_from_active_width);
1965 do_one_seven_eight(reset_disc_width);
1966 /* add select |no_break| to |active_width| */
1967 s = vlink_no_break(vlink(cur_p));
1968 add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
1969 ext_try_break(actual_penalty, hyphenated_node,
1970 line_break_dir, adjust_spacing,
1971 par_shape_ptr, adj_demerits,
1972 tracing_paragraphs,
1973 protrude_chars, line_penalty,
1974 last_line_fit, double_hyphen_demerits,
1975 final_hyphen_demerits, first_p,
1976 vlink(cur_p));
1977 #endif
1979 do_one_seven_eight(sub_disc_width_from_active_width);
1982 s = vlink_no_break(cur_p);
1983 add_to_widths(s, line_break_dir, adjust_spacing, active_width);
1984 break;
1985 case penalty_node:
1986 ext_try_break(penalty(cur_p), unhyphenated_node, line_break_dir,
1987 adjust_spacing, par_shape_ptr, adj_demerits,
1988 tracing_paragraphs, protrude_chars,
1989 line_penalty, last_line_fit,
1990 double_hyphen_demerits, final_hyphen_demerits,
1991 first_p, cur_p);
1992 break;
1993 case boundary_node:
1994 case whatsit_node:
1995 /* / Advance past a whatsit node in the |line_break| loop/; */
1996 case mark_node:
1997 case ins_node:
1998 case adjust_node:
1999 break;
2000 case glue_spec_node:
2001 normal_warning("parbuilder","found a glue_spec in a paragraph");
2002 break;
2003 default:
2004 formatted_error("parbuilder","weird node %d in paragraph",type(cur_p));
2006 cur_p = vlink(cur_p);
2007 while (cur_p == null && nest_index > 0) {
2008 cur_p = nest_stack[--nest_index];
2011 if (cur_p == null) {
2013 Try the final line break at the end of the paragraph,
2014 and |goto done| if the desired breakpoints have been found
2016 The forced line break at the paragraph's end will reduce the list of
2017 breakpoints so that all active nodes represent breaks at |cur_p=null|.
2018 On the first pass, we insist on finding an active node that has the
2019 correct ``looseness.'' On the final pass, there will be at least one active
2020 node, and we will match the desired looseness as well as we can.
2022 The global variable |best_bet| will be set to the active node for the best
2023 way to break the paragraph, and a few other variables are used to
2024 help determine what is best.
2026 ext_try_break(eject_penalty, hyphenated_node, line_break_dir,
2027 adjust_spacing, par_shape_ptr, adj_demerits,
2028 tracing_paragraphs, protrude_chars, line_penalty,
2029 last_line_fit, double_hyphen_demerits,
2030 final_hyphen_demerits, first_p, cur_p);
2031 if (vlink(active) != active) {
2032 /* Find an active node with fewest demerits; */
2033 r = vlink(active);
2034 fewest_demerits = awful_bad;
2035 do {
2036 if (type(r) != delta_node) {
2037 if (total_demerits(r) < fewest_demerits) {
2038 fewest_demerits = total_demerits(r);
2039 best_bet = r;
2042 r = vlink(r);
2043 } while (r != active);
2044 best_line = line_number(best_bet);
2046 Find an active node with fewest demerits;
2048 if (looseness == 0)
2049 goto DONE;
2051 Find the best active node for the desired looseness;
2053 The adjustment for a desired looseness is a slightly more complicated
2054 version of the loop just considered. Note that if a paragraph is broken
2055 into segments by displayed equations, each segment will be subject to the
2056 looseness calculation, independently of the other segments.
2058 r = vlink(active);
2059 actual_looseness = 0;
2060 do {
2061 if (type(r) != delta_node) {
2062 line_diff = line_number(r) - best_line;
2063 if (((line_diff < actual_looseness)
2064 && (looseness <= line_diff))
2065 || ((line_diff > actual_looseness)
2066 && (looseness >= line_diff))) {
2067 best_bet = r;
2068 actual_looseness = line_diff;
2069 fewest_demerits = total_demerits(r);
2070 } else if ((line_diff == actual_looseness) &&
2071 (total_demerits(r) < fewest_demerits)) {
2072 best_bet = r;
2073 fewest_demerits = total_demerits(r);
2076 r = vlink(r);
2077 } while (r != active);
2078 best_line = line_number(best_bet);
2080 Find the best active node for the desired looseness;
2082 if ((actual_looseness == looseness) || final_pass)
2083 goto DONE;
2086 /* Clean up the memory by removing the break nodes; */
2087 clean_up_the_memory();
2088 /* /Clean up the memory by removing the break nodes; */
2089 if (!second_pass) {
2090 if (tracing_paragraphs > 0)
2091 tprint_nl("@@secondpass");
2092 threshold = tolerance;
2093 second_pass = true;
2094 final_pass = (emergency_stretch <= 0);
2095 } else {
2096 /* if at first you do not succeed, \dots */
2097 if (tracing_paragraphs > 0)
2098 tprint_nl("@@emergencypass");
2099 background[2] += emergency_stretch;
2100 final_pass = true;
2104 DONE:
2105 if (tracing_paragraphs > 0) {
2106 end_diagnostic(true);
2107 normalize_selector();
2109 if (do_last_line_fit) {
2111 Adjust the final line of the paragraph; here we either reset
2112 |do_last_line_fit| or adjust the |par_fill_skip| glue.
2114 if (active_short(best_bet) == 0) {
2115 do_last_line_fit = false;
2116 } else {
2117 q = new_spec(glue_ptr(last_line_fill));
2118 delete_glue_ref(glue_ptr(last_line_fill));
2119 width(q) += (active_short(best_bet) - active_glue(best_bet));
2120 stretch(q) = 0;
2121 glue_ptr(last_line_fill) = q;
2126 Break the paragraph at the chosen...; Once the best sequence of breakpoints
2127 has been found (hurray), we call on the procedure |post_line_break| to finish
2128 the remainder of the work. By introducing this subprocedure, we are able to
2129 keep |line_break| from getting extremely long.
2132 /* first thing |ext_post_line_break| does is reset |dir_ptr| */
2133 flush_node_list(dir_ptr);
2134 dir_ptr = null;
2135 ext_post_line_break(paragraph_dir,
2136 right_skip,
2137 left_skip,
2138 protrude_chars,
2139 par_shape_ptr,
2140 adjust_spacing,
2141 inter_line_penalties_ptr,
2142 inter_line_penalty,
2143 club_penalty,
2144 club_penalties_ptr,
2145 widow_penalties_ptr,
2146 widow_penalty,
2147 broken_penalty,
2148 final_par_glue,
2149 best_bet,
2150 last_special_line,
2151 second_width,
2152 second_indent, first_width, first_indent, best_line);
2154 Break the paragraph at the chosen ...Clean up the memory by removing
2155 the break nodes.
2157 clean_up_the_memory();
2160 @ @c
2161 void get_linebreak_info (int *f, int *a)
2163 *f = fewest_demerits;
2164 *a = actual_looseness;