w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

texmath.c
Go to the documentation of this file.
1 /*
2 
3 Copyright 2008-2010 Taco Hoekwater <taco@luatex.org>
4 
5 This file is part of LuaTeX.
6 
7 LuaTeX is free software; you can redistribute it and/or modify it under the terms
8 of the GNU General Public License as published by the Free Software Foundation;
9 either version 2 of the License, or (at your option) any later version.
10 
11 LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along with
16 LuaTeX; if not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 
20 #include "ptexlib.h"
21 
22 #define mode mode_par
23 #define tail tail_par
24 #define head head_par
25 #define dir_save dirs_par
26 
27 /*tex
28 
29  Concerning display skips, \TEX\ normally always inserts before and only after
30  when larger than zero. THis can ow be controlled with |\mathdisplayskipmode|:
31 
32  \starttabulate
33  \NC 0 \NC normal \TEX \NC \NR
34  \NC 1 \NC always \NC \NR
35  \NC 2 \NC non-zero \NC \NR
36  \NC 3 \NC ignore \NC \NR
37  \stoptabulate
38 
39 */
40 
41 #define back_error(A,B) do { \
42  OK_to_interrupt=false; \
43  back_input(); \
44  OK_to_interrupt=true; \
45  tex_error(A,B); \
46  } while (0)
47 
48 int scan_math(pointer, int);
49 int scan_math_style(pointer, int);
51 
52 /*tex
53 
54  When \TeX\ reads a formula that is enclosed between \.\$'s, it constructs an
55  {\sl mlist}, which is essentially a tree structure representing that formula.
56  An mlist is a linear sequence of items, but we can regard it as a tree
57  structure because mlists can appear within mlists. For example, many of the
58  entries can be subscripted or superscripted, and such ``scripts'' are mlists
59  in their own right.
60 
61  An entire formula is parsed into such a tree before any of the actual
62  typesetting is done, because the current style of type is usually not known
63  until the formula has been fully scanned. For example, when the formula
64  `\.{\$a+b \\over c+d\$}' is being read, there is no way to tell that
65  `\.{a+b}' will be in script size until `\.{\\over}' has appeared.
66 
67  During the scanning process, each element of the mlist being built is
68  classified as a relation, a binary operator, an open parenthesis, etc., or as
69  a construct like `\.{\\sqrt}' that must be built up. This classification
70  appears in the mlist data structure.
71 
72  After a formula has been fully scanned, the mlist is converted to an hlist so
73  that it can be incorporated into the surrounding text. This conversion is
74  controlled by a recursive procedure that decides all of the appropriate
75  styles by a ``top-down'' process starting at the outermost level and working
76  in towards the subformulas. The formula is ultimately pasted together using
77  combinations of horizontal and vertical boxes, with glue and penalty nodes
78  inserted as necessary.
79 
80  An mlist is represented internally as a linked list consisting chiefly of
81  ``noads'' (pronounced ``no-adds''), to distinguish them from the somewhat
82  similar ``nodes'' in hlists and vlists. Certain kinds of ordinary nodes are
83  allowed to appear in mlists together with the noads; \TeX\ tells the
84  difference by means of the |type| field, since a noad's |type| is always
85  greater than that of a node. An mlist does not contain character nodes, hlist
86  nodes, vlist nodes, math nodes or unset nodes; in particular, each mlist item
87  appears in the variable-size part of |mem|, so the |type| field is always
88  present.
89 
90  Each noad is five or more words long. The first word contains the |type| and
91  |subtype| and |link| fields that are already so familiar to us; the second
92  contains the attribute list pointer, and the third, fourth an fifth words are
93  called the noad's |nucleus|, |subscr|, and |supscr| fields. (This use of a
94  combined attribute list is temporary. Eventually, each of fields need their
95  own list)
96 
97  Consider, for example, the simple formula `\.{\$x\^2\$}', which would be
98  parsed into an mlist containing a single element called an |ord_noad|. The
99  |nucleus| of this noad is a representation of `\.x', the |subscr| is empty,
100  and the |supscr| is a representation of `\.2'.
101 
102  The |nucleus|, |subscr|, and |supscr| fields are further broken into
103  subfields. If |p| points to a noad, and if |q| is one of its principal fields
104  (e.g., |q=subscr(p)|), |q=null| indicates a field with no value (the
105  corresponding attribute of noad |p| is not present). Otherwise, there are
106  several possibilities for the subfields, depending on the |type| of |q|.
107 
108  \startitemize
109 
110  \startitem
111  |type(q)=math_char_node| means that |math_fam(q)| refers to one of
112  the sixteen font families, and |character(q)| is the number of a
113  character within a font of that family, as in a character node.
114  \stopitem
115 
116  \startitem
117  |type(q)=math_text_char_node| is similar, but the character is
118  unsubscripted and unsuperscripted and it is followed immediately by
119  another character from the same font. (This |type| setting appears
120  only briefly during the processing; it is used to suppress unwanted
121  italic corrections.)
122  \stopitem
123 
124  \startitem
125  |type(q)=sub_box_node| means that |math_list(q)| points to a box node
126  (either an |hlist_node| or a |vlist_node|) that should be used as the
127  value of the field. The |shift_amount| in the subsidiary box node is
128  the amount by which that box will be shifted downward.
129  \stopitem
130 
131  \startitem
132  |type(q)=sub_mlist_node| means that |math_list(q)| points to an
133  mlist; the mlist must be converted to an hlist in order to obtain the
134  value of this field.
135  \stopitem
136 
137  \startitem
138  In the latter case, we might have |math_list(q)=null|. This is not
139  the same as |q=null|; for example, `\.{\$P\_\{\}\$}' and `\.{\$P\$}'
140  produce different results (the former will not have the ``italic
141  correction'' added to the width of |P|, but the ``script skip'' will
142  be added).
143  \stopitem
144 
145  \startitemize
146 
147 */
148 
149 static void unsave_math(void)
150 {
151  unsave();
152  decr(save_ptr);
156 }
157 
158 /*tex
159 
160  Sometimes it is necessary to destroy an mlist. The following subroutine
161  empties the current list, assuming that |abs(mode)=mmode|.
162 
163 */
164 
165 void flush_math(void)
166 {
169  vlink(head) = null;
170  tail = head;
171  incompleat_noad_par = null;
172 }
173 
174 /*tex Before we can do anything in math mode, we need fonts. */
175 
176 #define MATHFONTSTACK 8
177 #define MATHFONTDEFAULT 0
178 
180 
181 int fam_fnt(int fam_id, int size_id)
182 {
183  int n = fam_id + (256 * size_id);
184  return (int) get_sa_item(math_fam_head, n).int_value;
185 }
186 
187 void def_fam_fnt(int fam_id, int size_id, int f, int lvl)
188 {
189  int n = fam_id + (256 * size_id);
190  sa_tree_item sa_value = { 0 };
191  sa_value.int_value = f;
192  set_sa_item(math_fam_head, n, sa_value, lvl);
193  fixup_math_parameters(fam_id, size_id, f, lvl);
194  if (tracing_assigns_par > 1) {
196  tprint("{assigning");
197  print_char(' ');
198  print_cmd_chr(def_family_cmd, size_id);
199  print_int(fam_id);
200  print_char('=');
201  print_font_identifier(fam_fnt(fam_id, size_id));
202  print_char('}');
203  end_diagnostic(false);
204  }
205 }
206 
207 static void unsave_math_fam_data(int gl)
208 {
210  if (math_fam_head->stack == NULL)
211  return;
212  while (math_fam_head->stack_ptr > 0 &&
214  >= (int) gl) {
216  if (st.level > 0) {
217  rawset_sa_item(math_fam_head, st.code, st.value);
218  /*tex Now do a trace message, if requested. */
219  if (tracing_restores_par > 1) {
220  int size_id = st.code / 256;
221  int fam_id = st.code % 256;
223  tprint("{restoring");
224  print_char(' ');
225  print_cmd_chr(def_family_cmd, size_id);
226  print_int(fam_id);
227  print_char('=');
228  print_font_identifier(fam_fnt(fam_id, size_id));
229  print_char('}');
230  end_diagnostic(false);
231  }
232  }
234  }
235 }
236 
237 /*tex Parameters */
238 
239 #define MATHPARAMSTACK 8
240 #define MATHPARAMDEFAULT undefined_math_parameter
241 
243 
244 void def_math_param(int param_id, int style_id, scaled value, int lvl)
245 {
246  int n = param_id + (256 * style_id);
247  sa_tree_item sa_value = { 0 };
248  sa_value.int_value = (int) value;
249  set_sa_item(math_param_head, n, sa_value, lvl);
250  if (tracing_assigns_par > 1) {
252  tprint("{assigning");
253  print_char(' ');
255  print_cmd_chr(math_style_cmd, style_id);
256  print_char('=');
257  print_int(value);
258  print_char('}');
259  end_diagnostic(false);
260  }
261 }
262 
263 scaled get_math_param(int param_id, int style_id)
264 {
265  int n = param_id + (256 * style_id);
267 }
268 
269 static void unsave_math_param_data(int gl)
270 {
272  if (math_param_head->stack == NULL)
273  return;
274  while (math_param_head->stack_ptr > 0 &&
276  >= (int) gl) {
278  if (st.level > 0) {
279  rawset_sa_item(math_param_head, st.code, st.value);
280  /*tex Do a trace message, if requested. */
281  if (tracing_restores_par > 1) {
282  int param_id = st.code % 256;
283  int style_id = st.code / 256;
285  tprint("{restoring");
286  print_char(' ');
288  print_cmd_chr(math_style_cmd, style_id);
289  print_char('=');
290  print_int(get_math_param(param_id, style_id));
291  print_char('}');
292  end_diagnostic(false);
293  }
294  }
296  }
297 }
298 
299 /*tex Saving and unsaving of both: */
300 
301 void unsave_math_data(int gl)
302 {
305 }
306 
307 /*tex Dumping and undumping: */
308 
309 void dump_math_data(void)
310 {
311  sa_tree_item sa_value = { 0 };
312  if (math_fam_head == NULL) {
313  sa_value.int_value = MATHFONTDEFAULT;
314  math_fam_head = new_sa_tree(MATHFONTSTACK, 1, sa_value);
315  }
316  dump_sa_tree(math_fam_head, "mathfonts");
317  if (math_param_head == NULL) {
318  sa_value.int_value = MATHPARAMDEFAULT;
320  }
321  dump_sa_tree(math_param_head, "mathparameters");
322 }
323 
325 {
326  math_fam_head = undump_sa_tree("mathfonts");
327  math_param_head = undump_sa_tree("mathparameters");
328 }
329 
330 void initialize_math(void)
331 {
332  sa_tree_item sa_value = { 0 };
333  if (math_fam_head == NULL) {
334  sa_value.int_value = MATHFONTDEFAULT;
335  math_fam_head = new_sa_tree(MATHFONTSTACK, 1, sa_value);
336  }
337  if (math_param_head == NULL) {
338  sa_value.int_value = MATHPARAMDEFAULT;
341  }
342  return;
343 }
344 
345 /*tex
346 
347  Each portion of a formula is classified as Ord, Op, Bin, Rel, Ope, Clo, Pun,
348  or Inn, for purposes of spacing and line breaking. An |ord_noad|, |op_noad|,
349  |bin_noad|, |rel_noad|, |open_noad|, |close_noad|, |punct_noad|, or
350  |inner_noad| is used to represent portions of the various types. For example,
351  an `\.=' sign in a formula leads to the creation of a |rel_noad| whose
352  |nucleus| field is a representation of an equals sign (usually |fam=0|,
353  |character=075|). A formula preceded by \.{\\mathrel} also results in a
354  |rel_noad|. When a |rel_noad| is followed by an |op_noad|, say, and possibly
355  separated by one or more ordinary nodes (not noads), \TeX\ will insert a
356  penalty node (with the current |rel_penalty|) just after the formula that
357  corresponds to the |rel_noad|, unless there already was a penalty immediately
358  following; and a ``thick space'' will be inserted just before the formula
359  that corresponds to the |op_noad|.
360 
361  A noad of type |ord_noad|, |op_noad|, \dots, |inner_noad| usually has a
362  |subtype=normal|. The only exception is that an |op_noad| might have
363  |subtype=limits| or |no_limits|, if the normal positioning of limits has been
364  overridden for this operator.
365 
366  A |radical_noad| also has a |left_delimiter| field, which usually represents
367  a square root sign.
368 
369  A |fraction_noad| has a |right_delimiter| field as well as a
370  |left_delimiter|.
371 
372  Delimiter fields have four subfields called |small_fam|, |small_char|,
373  |large_fam|, |large_char|. These subfields represent variable-size delimiters
374  by giving the ``small'' and ``large'' starting characters, as explained in
375  Chapter~17 of {\sl The \TeX book}.
376 
377  A |fraction_noad| is actually quite different from all other noads. It has
378  |thickness|, |denominator|, and |numerator| fields instead of |nucleus|,
379  |subscr|, and |supscr|. The |thickness| is a scaled value that tells how
380  thick to make a fraction rule; however, the special value |default_code| is
381  used to stand for the |default_rule_thickness| of the current size. The
382  |numerator| and |denominator| point to mlists that define a fraction; we
383  always have $$\hbox{|type(numerator)=type(denominator)=sub_mlist|}.$$ The
384  |left_delimiter| and |right_delimiter| fields specify delimiters that will be
385  placed at the left and right of the fraction. In this way, a |fraction_noad|
386  is able to represent all of \TeX's operators \.{\\over}, \.{\\atop},
387  \.{\\above}, \.{\\overwithdelims}, \.{\\atopwithdelims}, and
388  \.{\\abovewithdelims}.
389 
390  The |new_noad| function creates an |ord_noad| that is completely null
391 
392 */
393 
395 {
396  pointer p;
398  /*tex All noad fields are zero after this. */
399  return p;
400 }
401 
403 {
404  pointer p, q;
405  p = new_noad();
406  q = new_node(sub_box_node, 0);
407  nucleus(p) = q;
408  math_list(nucleus(p)) = curbox;
409  return p;
410 }
411 
412 /*tex
413 
414  A few more kinds of noads will complete the set: An |under_noad| has its
415  nucleus underlined; an |over_noad| has it overlined. An |accent_noad| places
416  an accent over its nucleus; the accent character appears as
417  |math_fam(accent_chr(p))| and |math_character(accent_chr(p))|. A
418  |vcenter_noad| centers its nucleus vertically with respect to the axis of the
419  formula; in such noads we always have |type(nucleus(p))=sub_box|.
420 
421  And finally, we have the |fence_noad| type, to implement \TeX's \.{\\left}
422  and \.{\\right} as well as eTeX's \.{\\middle}. The |nucleus| of such noads
423  is replaced by a |delimiter| field; thus, for example, `\.{\\left(}' produces
424  a |fence_noad| such that |delimiter(p)| holds the family and character codes
425  for all left parentheses. A |fence_noad| of subtype |left_noad_side| never
426  appears in an mlist except as the first element, and a |fence_noad| with
427  subtype |right_noad_side| never appears in an mlist except as the last
428  element; furthermore, we either have both a |left_noad_side| and a
429  |right_noad_side|, or neither one is present.
430 
431  Math formulas can also contain instructions like \.{\\textstyle} that
432  override \TeX's normal style rules. A |style_node| is inserted into the data
433  structure to record such instructions; it is three words long, so it is
434  considered a node instead of a noad. The |subtype| is either |display_style|
435  or |text_style| or |script_style| or |script_script_style|. The second and
436  third words of a |style_node| are not used, but they are present because a
437  |choice_node| is converted to a |style_node|.
438 
439  \TeX\ uses even numbers 0, 2, 4, 6 to encode the basic styles
440  |display_style|, \dots, |script_script_style|, and adds~1 to get the
441  ``cramped'' versions of these styles. This gives a numerical order that is
442  backwards from the convention of Appendix~G in {\sl The \TeX book\/}; i.e., a
443  smaller style has a larger numerical value.
444 
445 */
446 
447 const char *math_style_names[] = {
448  "display", "crampeddisplay",
449  "text", "crampedtext",
450  "script", "crampedscript",
451  "scriptscript", "crampedscriptscript",
452  NULL
453 };
454 
455 const char *math_param_names[] = {
456  "quad", "axis", "operatorsize",
457  "overbarkern", "overbarrule", "overbarvgap",
458  "underbarkern", "underbarrule", "underbarvgap",
459  "radicalkern", "radicalrule", "radicalvgap",
460  "radicaldegreebefore", "radicaldegreeafter", "radicaldegreeraise",
461  "stackvgap", "stacknumup", "stackdenomdown",
462  "fractionrule", "fractionnumvgap", "fractionnumup",
463  "fractiondenomvgap", "fractiondenomdown", "fractiondelsize",
464  "skewedfractionhgap", "skewedfractionvgap",
465  "limitabovevgap", "limitabovebgap", "limitabovekern",
466  "limitbelowvgap", "limitbelowbgap", "limitbelowkern",
467  "nolimitsubfactor", "nolimitsupfactor", /* bonus */
468  "underdelimitervgap", "underdelimiterbgap",
469  "overdelimitervgap", "overdelimiterbgap",
470  "subshiftdrop", "supshiftdrop", "subshiftdown",
471  "subsupshiftdown", "subtopmax", "supshiftup",
472  "supbottommin", "supsubbottommax", "subsupvgap",
473  "spaceafterscript", "connectoroverlapmin",
474  "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing",
475  "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing",
476  "opordspacing", "opopspacing", "opbinspacing", "oprelspacing",
477  "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing",
478  "binordspacing", "binopspacing", "binbinspacing", "binrelspacing",
479  "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing",
480  "relordspacing", "relopspacing", "relbinspacing", "relrelspacing",
481  "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing",
482  "openordspacing", "openopspacing", "openbinspacing", "openrelspacing",
483  "openopenspacing", "openclosespacing", "openpunctspacing",
484  "openinnerspacing",
485  "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing",
486  "closeopenspacing", "closeclosespacing", "closepunctspacing",
487  "closeinnerspacing",
488  "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing",
489  "punctopenspacing", "punctclosespacing", "punctpunctspacing",
490  "punctinnerspacing",
491  "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing",
492  "inneropenspacing", "innerclosespacing", "innerpunctspacing",
493  "innerinnerspacing",
494  NULL
495 };
496 
498 {
499  m_style = s;
500  return new_node(style_node, s);
501 }
502 
503 /*tex
504 
505  Finally, the \.{\\mathchoice} primitive creates a |choice_node|, which has
506  special subfields |display_mlist|, |text_mlist|, |script_mlist|, and
507  |script_script_mlist| pointing to the mlists for each style.
508 
509 */
510 
511 static pointer new_choice(void)
512 {
513  return new_node(choice_node, 0);
514 }
515 
516 /*tex
517 
518  Let's consider now the previously unwritten part of |show_node_list| that
519  displays the things that can only be present in mlists; this program
520  illustrates how to access the data structures just defined.
521 
522  In the context of the following program, |p| points to a node or noad that
523  should be displayed, and the current string contains the ``recursion
524  history'' that leads to this point. The recursion history consists of a dot
525  for each outer level in which |p| is subsidiary to some node, or in which |p|
526  is subsidiary to the |nucleus| field of some noad; the dot is replaced by
527  `\.\_' or `\.\^' or `\./' or `\.\\' if |p| is descended from the |subscr| or
528  |supscr| or |denominator| or |numerator| fields of noads. For example, the
529  current string would be `\.{.\^.\_/}' if |p| points to the |ord_noad| for |x|
530  in the (ridiculous) formula `\.{\$\\sqrt\{a\^\{\\mathinner\{b\_\{c\\over
531  x+y\}\}\}\}\$}'.
532 
533 */
534 
538 
540 {
541  switch (type(p)) {
542  case style_node:
544  break;
545  case choice_node:
546  tprint_esc("mathchoice");
547  append_char('D');
549  flush_char();
550  append_char('T');
552  flush_char();
553  append_char('S');
555  flush_char();
556  append_char('s');
558  flush_char();
559  break;
560  case simple_noad:
561  case radical_noad:
562  case accent_noad:
564  break;
565  case fence_noad:
567  break;
568  case fraction_noad:
570  break;
571  default:
572  tprint("Unknown node type!");
573  break;
574  }
575 }
576 
577 /*tex Here are some simple routines used in the display of noads. */
578 
580 {
581  tprint_esc("fam");
582  print_int(math_fam(p));
583  print_char(' ');
585 }
586 
588 {
589  int a;
590  if (delimiteroptionset(p)) {
591  tprint(" [ ");
592  if (delimiteraxis(p))
593  tprint("axis ");
594  if (delimiternoaxis(p))
595  tprint("noaxis ");
596  if (delimiterexact(p))
597  tprint("exact ");
598  tprint("]");
599  }
600  if (delimiterheight(p)) {
601  tprint("height=");
603  tprint(" ");
604  }
605  if (delimiterdepth(p)) {
606  tprint("depth=");
608  tprint(" ");
609  }
610  if (delimiterclass(p)) {
611  tprint("class=");
613  tprint(" ");
614  }
615  if (small_fam(p) < 0) {
616  /*tex This should never happen. */
617  print_int(-1);
618  } else if (small_fam(p) < 16 && large_fam(p) < 16 && small_char(p) < 256 && large_char(p) < 256) {
619  /*tex Traditional tex style. */
620  a = small_fam(p) * 256 + small_char(p);
621  a = a * 0x1000 + large_fam(p) * 256 + large_char(p);
622  print_qhex(a);
623  } else if ((large_fam(p) == 0 && large_char(p) == 0) || small_char(p) > 65535 || large_char(p) > 65535) {
624  /*tex \LUATEX\ style. */
627  }
628 }
629 
630 /*tex
631 
632  The next subroutine will descend to another level of recursion when a
633  subsidiary mlist needs to be displayed. The parameter |c| indicates what
634  character is to become part of the recursion history. An empty mlist is
635  distinguished from a missing field, because these are not equivalent (as
636  explained above).
637 
638 */
639 
641 {
642  if ((int) cur_length >= depth_threshold) {
643  if (p != null)
644  tprint(" []");
645  } else {
646  /*tex Include |c| in the recursion history. */
647  append_char(c);
648  if (p != null) {
649  switch (type(p)) {
650  case math_char_node:
651  print_ln();
654  break;
655  case sub_box_node:
657  break;
658  case sub_mlist_node:
659  if (math_list(p) == null) {
660  print_ln();
662  tprint("{}");
663  } else {
665  }
666  break;
667  }
668  }
669  /*tex Remove |c| from the recursion history. */
670  flush_char();
671  }
672 }
673 
675 {
676  switch (type(p)) {
677  case simple_noad:
678  switch (subtype(p)) {
679  case ord_noad_type:
680  tprint_esc("mathord");
681  break;
682  case op_noad_type_normal:
683  case op_noad_type_limits:
685  tprint_esc("mathop");
686  if (subtype(p) == op_noad_type_limits)
687  tprint_esc("limits");
688  else if (subtype(p) == op_noad_type_no_limits)
689  tprint_esc("nolimits");
690  break;
691  case bin_noad_type:
692  tprint_esc("mathbin");
693  break;
694  case rel_noad_type:
695  tprint_esc("mathrel");
696  break;
697  case open_noad_type:
698  tprint_esc("mathopen");
699  break;
700  case close_noad_type:
701  tprint_esc("mathclose");
702  break;
703  case punct_noad_type:
704  tprint_esc("mathpunct");
705  break;
706  case inner_noad_type:
707  tprint_esc("mathinner");
708  break;
709  case over_noad_type:
710  tprint_esc("overline");
711  break;
712  case under_noad_type:
713  tprint_esc("underline");
714  break;
715  case vcenter_noad_type:
716  tprint_esc("vcenter");
717  break;
718  default:
719  tprint("<unknown noad type!>");
720  break;
721  }
722  break;
723  case radical_noad:
724  if (subtype(p) == 7)
725  tprint_esc("Uhextensible");
726  else if (subtype(p) == 6)
727  tprint_esc("Udelimiterover");
728  else if (subtype(p) == 5)
729  tprint_esc("Udelimiterunder");
730  else if (subtype(p) == 4)
731  tprint_esc("Uoverdelimiter");
732  else if (subtype(p) == 3)
733  tprint_esc("Uunderdelimiter");
734  else if (subtype(p) == 2)
735  tprint_esc("Uroot");
736  else
737  tprint_esc("radical");
739  if (degree(p) != null) {
741  }
742  if (radicalwidth(p)) {
743  tprint("width=");
745  tprint(" ");
746  }
747  if (radicaloptionset(p)) {
748  tprint(" [ ");
749  if (radicalexact(p))
750  tprint("exact ");
751  if (radicalleft(p))
752  tprint("left ");
753  if (radicalmiddle(p))
754  tprint("middle ");
755  if (radicalright(p))
756  tprint("right ");
757  tprint("]");
758  }
759  break;
760  case accent_noad:
761  if (top_accent_chr(p) != null) {
762  if (bot_accent_chr(p) != null) {
763  tprint_esc("Umathaccent both");
764  } else {
765  tprint_esc("Umathaccent");
766  }
767  } else if (bot_accent_chr(p) != null) {
768  tprint_esc("Umathaccent bottom");
769  } else {
770  tprint_esc("Umathaccent overlay");
771  }
772  if (accentfraction(p)) {
773  tprint(" fraction=");
775  tprint(" ");
776  }
777  switch (subtype(p)) {
778  case 0:
779  if (top_accent_chr(p) != null) {
780  if (bot_accent_chr(p) != null) {
783  } else {
785  }
786  } else if (bot_accent_chr(p) != null) {
788  } else {
790  }
791  break;
792  case 1:
793  if (top_accent_chr(p) != null) {
794  tprint(" fixed ");
796  if (bot_accent_chr(p) != null) {
798  }
799  } else {
800  confusion("display_accent_noad");
801  }
802  break;
803  case 2:
804  if (bot_accent_chr(p) != null) {
805  if (top_accent_chr(p) != null) {
807  }
808  tprint(" fixed ");
810  } else{
811  confusion("display_accent_noad");
812  }
813  break;
814  case 3:
815  if (top_accent_chr(p) != null && bot_accent_chr(p) != null) {
816  tprint(" fixed ");
818  tprint(" fixed ");
820  } else {
821  confusion("display_accent_noad");
822  }
823  break;
824  }
825  break;
826  }
830 }
831 
833 {
834  if (subtype(p) == right_noad_side)
835  tprint_esc("right");
836  else if (subtype(p) == left_noad_side)
837  tprint_esc("left");
838  else
839  tprint_esc("middle");
841 }
842 
844 {
845  tprint_esc("fraction, thickness ");
846  if (thickness(p) == default_code)
847  tprint("= default");
848  else
850  if ((left_delimiter(p) != null) &&
851  ((small_fam(left_delimiter(p)) != 0) || (small_char(left_delimiter(p)) != 0) ||
852  (large_fam(left_delimiter(p)) != 0) || (large_char(left_delimiter(p)) != 0))) {
853  tprint(", left-delimiter ");
855  }
856  if ((right_delimiter(p) != null) &&
857  ((small_fam(right_delimiter(p)) != 0) || (small_char(right_delimiter(p)) != 0) ||
858  (large_fam(right_delimiter(p)) != 0) || (large_char(right_delimiter(p)) != 0))) {
859  tprint(", right-delimiter ");
861  }
864 }
865 
866 /*tex
867 
868  The routines that \TeX\ uses to create mlists are similar to those we have
869  just seen for the generation of hlists and vlists. But it is necessary to
870  make ``noads'' as well as nodes, so the reader should review the discussion
871  of math mode data structures before trying to make sense out of the following
872  program.
873 
874  Here is a little routine that needs to be done whenever a subformula is about
875  to be processed. The parameter is a code like |math_group|.
876 
877 */
878 
880 {
883  incr(save_ptr);
884  new_save_level(c);
888 }
889 
890 static void push_math(group_code c, int mstyle)
891 {
893  dir_math_save = true;
894  push_nest();
895  mode = -mmode;
896  incompleat_noad_par = null;
897  m_style = mstyle;
899 }
900 
901 static void enter_ordinary_math(void)
902 {
905  if (every_math_par != null)
907 }
908 
909 void enter_display_math(void);
910 
911 /*tex
912 
913  We get into math mode from horizontal mode when a `\.\$' (i.e., a
914  |math_shift| character) is scanned. We must check to see whether this `\.\$'
915  is immediately followed by another, in case display math mode is called for.
916 
917 */
918 
919 void init_math(void)
920 {
921  if (cur_cmd == math_shift_cmd) {
922  /*tex |get_x_token| would fail on \.{\\ifmmode}\thinspace! */
923  get_token();
924  if ((cur_cmd == math_shift_cmd) && (mode > 0)) {
926  } else {
927  back_input();
929  }
930  } else if (cur_cmd == math_shift_cs_cmd && cur_chr == display_style && (mode > 0)) {
932  } else if (cur_cmd == math_shift_cs_cmd && cur_chr == text_style) {
934  } else {
935  you_cant();
936  }
937 }
938 
939 /*tex
940 
941  We get into ordinary math mode from display math mode when `\.{\\eqno}' or
942  `\.{\\leqno}' appears. In such cases |cur_chr| will be 0 or~1, respectively;
943  the value of |cur_chr| is placed onto |save_stack| for safe keeping.
944 
945  When \TeX\ is in display math mode, |cur_group=math_shift_group|, so it is
946  not necessary for the |start_eq_no| procedure to test for this condition.
947 
948 */
949 
950 void start_eq_no(void)
951 {
953  incr(save_ptr);
955 }
956 
957 /*tex
958 
959  Subformulas of math formulas cause a new level of math mode to be entered, on
960  the semantic nest as well as the save stack. These subformulas arise in
961  several ways: (1)~A left brace by itself indicates the beginning of a
962  subformula that will be put into a box, thereby freezing its glue and
963  preventing line breaks. (2)~A subscript or superscript is treated as a
964  subformula if it is not a single character; the same applies to the nucleus
965  of things like \.{\\underline}. (3)~The \.{\\left} primitive initiates a
966  subformula that will be terminated by a matching \.{\\right}. The group codes
967  placed on |save_stack| in these three cases are |math_group|, |math_group|,
968  and |math_left_group|, respectively.
969 
970  Here is the code that handles case (1); the other cases are not quite as
971  trivial, so we shall consider them later.
972 
973 */
974 
975 void math_left_brace(void)
976 {
977  pointer q;
979  q = new_node(math_char_node, 0);
980  nucleus(tail) = q;
981  back_input();
983 }
984 
985 /*tex
986 
987  If the inline directions of \.{\\pardir} and \.{\\mathdir} are opposite, then
988  this function will return true. Discovering that fact is somewhat odd because
989  it needs traversal of the |save_stack|. The occurance of displayed equations
990  is weird enough that this is probably still better than having yet another
991  field in the |input_stack| structures.
992 
993  None of this makes much sense if the inline direction of either one of
994  \.{\\pardir} or \.{\\mathdir} is vertical, but in that case the current math
995  machinery is ill suited anyway so I do not bother to test that.
996 
997 */
998 
999 static boolean math_and_text_reversed_p(void)
1000 {
1001  int i = save_ptr - 1;
1002  while (save_type(i) != level_boundary)
1003  i--;
1004  while (i < save_ptr) {
1005  if (save_type(i) == restore_old_value &&
1008  return true;
1009  }
1010  i++;
1011  }
1012  return false;
1013 }
1014 
1015 /*tex
1016 
1017  When we enter display math mode, we need to call |line_break| to process the
1018  partial paragraph that has just been interrupted by the display. Then we can
1019  set the proper values of |display_width| and |display_indent| and
1020  |pre_display_size|.
1021 
1022 */
1023 
1025 {
1026  /*tex new or partial |pre_display_size| */
1027  scaled w;
1028  /*tex new |display_width| */
1029  scaled l;
1030  /*tex new |display_indent| */
1031  scaled s;
1032  pointer p;
1033  /*tex scope of paragraph shape specification */
1034  int n;
1035  /*tex
1036 
1037  `\.{\\noindent\$\$}' or `\.{\$\${ }\$\$}' or the 2nd of \.{\$\${ }\$\$}
1038  \.{\$\${ }\$\$}
1039 
1040  */
1041  if (head == tail ||
1042  (vlink(head) == tail &&
1043  type(tail) == local_par_node && vlink(tail) == null)) {
1044  if (vlink(head) == tail) {
1045  /*tex
1046 
1047  |resume_after_display| inserts a |local_par_node|, but if there
1048  is another display immediately following, we have to get rid of
1049  that node.
1050 
1051  */
1052  flush_node(tail);
1053  }
1054  pop_nest();
1055  w = -max_dimen;
1056  } else {
1059  }
1060  /*tex
1061 
1062  Now we are in vertical mode, working on the list that will contain the
1063  display. A displayed equation is considered to be three lines long, so we
1064  calculate the length and offset of line number |prev_graf+2|.
1065 
1066  */
1067  if (par_shape_par_ptr == null) {
1068  if ((hang_indent_par != 0) && (((hang_after_par >= 0) && (prev_graf_par + 2 > hang_after_par)) || (prev_graf_par + 1 < -hang_after_par))) {
1069  halfword used_hang_indent = swap_hang_indent(hang_indent_par);
1070  l = hsize_par - abs(used_hang_indent);
1071  if (used_hang_indent > 0)
1072  s = used_hang_indent;
1073  else
1074  s = 0;
1075  } else {
1076  l = hsize_par;
1077  s = 0;
1078  }
1079  } else {
1080  n = vinfo(par_shape_par_ptr + 1);
1081  if (prev_graf_par + 2 >= n)
1082  p = par_shape_par_ptr + 2 * n + 1;
1083  else
1084  p = par_shape_par_ptr + 2 * (prev_graf_par + 2) + 1;
1085  s = varmem[(p - 1)].cint;
1086  l = varmem[p].cint;
1088  }
1090  mode = mmode;
1096  if (every_display_par != null)
1098  if (nest_ptr == 1) {
1099  checked_page_filter(before_display);
1100  build_page();
1101  }
1102 }
1103 
1104 /*tex
1105 
1106  The next routine parses all variations of a delimiter code. The |extcode|
1107  tells what syntax form to use (\TeX, XeTeX, XeTeXnum, ...) , the |doclass|
1108  tells whether or not read a math class also (for \.{\\delimiter} c.s.). (the
1109  class is passed on for conversion to \.{\\mathchar}).
1110 
1111 */
1112 
1113 static delcodeval do_scan_extdef_del_code(int extcode, boolean doclass)
1114 {
1115  const char *hlp[] = {
1116  "I'm going to use 0 instead of that illegal code value.",
1117  NULL
1118  };
1119  delcodeval d;
1120  int mcls = 0, msfam = 0, mschr = 0, mlfam = 0, mlchr = 0;
1121  if (extcode == tex_mathcode) {
1122  /*tex
1123 
1124  \.{\\delcode}, this is the easiest
1125 
1126  */
1127  scan_int();
1128  /*tex "MFCCFCC or "FCCFCC */
1129  if (doclass) {
1130  mcls = (cur_val / 0x1000000);
1131  cur_val = (cur_val & 0xFFFFFF);
1132  }
1133  if (cur_val > 0xFFFFFF) {
1134  tex_error("Invalid delimiter code", hlp);
1135  cur_val = 0;
1136  }
1137  msfam = (cur_val / 0x100000);
1138  mschr = (cur_val % 0x100000) / 0x1000;
1139  mlfam = (cur_val & 0xFFF) / 0x100;
1140  mlchr = (cur_val % 0x100);
1141  } else if (extcode == umath_mathcode) {
1142  /*tex
1143 
1144  \.{\\Udelcode}: <0-7>,<0-0xFF>,<0-0x10FFFF> or <0-0xFF>,<0-0x10FFFF>
1145 
1146  */
1147  if (doclass) {
1148  scan_int();
1149  mcls = cur_val;
1150  }
1151  scan_int();
1152  msfam = cur_val;
1153  scan_char_num();
1154  mschr = cur_val;
1155  if (msfam < 0 || msfam > 255) {
1156  tex_error("Invalid delimiter code", hlp);
1157  msfam = 0;
1158  mschr = 0;
1159  }
1160  mlfam = 0;
1161  mlchr = 0;
1162  } else if (extcode == umathnum_mathcode) {
1163  /*tex
1164 
1165  \.{\\Udelcodenum}:"FF<21bits>; the largest numeric value is $2^29-1$,
1166  but the top of bit 21 can't be used as it contains invalid USV's.
1167 
1168  */
1169  if (doclass) { /* such a primitive doesn't exist */
1170  confusion("umathnum_mathcode");
1171  }
1172  scan_int();
1173  msfam = (cur_val / 0x200000);
1174  mschr = cur_val & 0x1FFFFF;
1175  if (msfam < 0 || msfam > 255 || mschr > 0x10FFFF) {
1176  tex_error("Invalid delimiter code", hlp);
1177  msfam = 0;
1178  mschr = 0;
1179  }
1180  mlfam = 0;
1181  mlchr = 0;
1182  } else {
1183  /*tex Something's gone wrong! */
1184  confusion("unknown_extcode");
1185  }
1186  d.class_value = mcls;
1187  d.small_family_value = msfam;
1188  d.small_character_value = mschr;
1189  d.large_family_value = mlfam;
1190  d.large_character_value = mlchr;
1191  return d;
1192 }
1193 
1194 void scan_extdef_del_code(int level, int extcode)
1195 {
1196  delcodeval d;
1197  int p;
1198  scan_char_num();
1199  p = cur_val;
1201  d = do_scan_extdef_del_code(extcode, false);
1202  set_del_code(p, d.small_family_value, d.small_character_value,
1203  d.large_family_value, d.large_character_value, (quarterword) (level));
1204 }
1205 
1207 {
1208  char errstr[255] = { 0 };
1209  const char *hlp[] = {
1210  "I'm going to use 0 instead of that illegal code value.",
1211  NULL
1212  };
1213  mathcodeval d;
1214  int mcls = 0, mfam = 0, mchr = 0;
1215  if (extcode == tex_mathcode) {
1216  /*tex \.{\\mathcode}: "TFCC */
1217  scan_int();
1218  if (cur_val > 0x8000) {
1219  /*tex Needed for latex: fallback to umathnum_mathcode. */
1220  mfam = (cur_val / 0x200000) & 0x7FF;
1221  mcls = mfam % 0x08;
1222  mfam = mfam / 0x08;
1223  mchr = cur_val & 0x1FFFFF;
1224  if (mchr > 0x10FFFF) {
1225  tex_error("Invalid math code during > 0x8000 mathcode fallback", hlp);
1226  mcls = 0;
1227  mfam = 0;
1228  mchr = 0;
1229  }
1230  } else {
1231  if (cur_val < 0) {
1232  snprintf(errstr, 255, "Bad mathchar (%d)", (int)cur_val);
1233  tex_error(errstr, hlp);
1234  cur_val = 0;
1235  }
1236  mcls = (cur_val / 0x1000);
1237  mfam = ((cur_val % 0x1000) / 0x100);
1238  mchr = (cur_val % 0x100);
1239  }
1240  } else if (extcode == umath_mathcode) {
1241  /*tex <0-0x7> <0-0xFF> <0-0x10FFFF> */
1242  scan_int();
1243  mcls = cur_val;
1244  scan_int();
1245  mfam = cur_val;
1246  scan_char_num();
1247  mchr = cur_val;
1248  if (mcls < 0 || mcls > 7 || mfam > 255) {
1249  tex_error("Invalid math code", hlp);
1250  mchr = 0;
1251  mfam = 0;
1252  mcls = 0;
1253  }
1254  } else if (extcode == umathnum_mathcode) {
1255  /*tex
1256 
1257  "FFT<21bits>: the largest numeric value is $2^32-1$, but the top of
1258  bit 21 can't be used as it contains invalid USV's
1259 
1260  Note: |scan_int| won't accept families 128-255 because these use bit 32
1261 
1262  */
1263  scan_int();
1264  mfam = (cur_val / 0x200000) & 0x7FF;
1265  mcls = mfam % 0x08;
1266  mfam = mfam / 0x08;
1267  mchr = cur_val & 0x1FFFFF;
1268  if (mchr > 0x10FFFF) {
1269  tex_error("Invalid math code", hlp);
1270  mcls = 0;
1271  mfam = 0;
1272  mchr = 0;
1273  }
1274  } else {
1275  /*tex Something's gone wrong. */
1276  confusion("unknown_extcode");
1277  }
1278  d.class_value = mcls;
1279  d.family_value = mfam;
1280  d.character_value = mchr;
1281  return d;
1282 }
1283 
1284 void scan_extdef_math_code(int level, int extcode)
1285 {
1286  mathcodeval d;
1287  int p;
1288  scan_char_num();
1289  p = cur_val;
1291  d = scan_mathchar(extcode);
1292  set_math_code(p, d.class_value, d.family_value, d.character_value, (quarterword) (level));
1293 }
1294 
1295 /*tex This reads in a delcode when actually a mathcode is needed. */
1296 
1298 {
1299  delcodeval dval;
1300  mathcodeval mval;
1301  dval = do_scan_extdef_del_code(extcode, true);
1302  mval.class_value = dval.class_value;
1303  mval.family_value = dval.small_family_value;
1305  return mval;
1306 }
1307 
1308 /*tex
1309 
1310  Recall that the |nucleus|, |subscr|, and |supscr| fields in a noad are broken
1311  down into subfields called |type| and either |math_list| or
1312  |(math_fam,math_character)|. The job of |scan_math| is to figure out what to
1313  place in one of these principal fields; it looks at the subformula that comes
1314  next in the input, and places an encoding of that subformula into a given
1315  word of |mem|.
1316 
1317 */
1318 
1319 #define get_next_nb_nr() do { get_x_token(); } while (cur_cmd==spacer_cmd||cur_cmd==relax_cmd)
1320 
1321 int scan_math_style(pointer p, int mstyle)
1322 {
1323  get_next_nb_nr();
1324  back_input();
1325  scan_left_brace();
1326  set_saved_record(0, saved_math, 0, p);
1327  incr(save_ptr);
1328  push_math(math_group, mstyle);
1329  return 1;
1330 }
1331 
1332 int scan_math(pointer p, int mstyle)
1333 {
1334  mathcodeval mval = { 0, 0, 0 };
1335  assert(p != null);
1336  RESTART:
1337  get_next_nb_nr();
1338  RESWITCH:
1339  switch (cur_cmd) {
1340  case letter_cmd:
1341  case other_char_cmd:
1342  case char_given_cmd:
1343  mval = get_math_code(cur_chr);
1344  if (mval.class_value == 8) {
1345  /*tex An active character that is an |outer_call| is allowed here. */
1346  cur_cs = active_to_cs(cur_chr, true);
1347  cur_cmd = eq_type(cur_cs);
1348  cur_chr = equiv(cur_cs);
1349  x_token();
1350  back_input();
1351  goto RESTART;
1352  }
1353  break;
1354  case char_num_cmd:
1355  scan_char_num();
1356  cur_chr = cur_val;
1358  goto RESWITCH;
1359  break;
1360  case math_char_num_cmd:
1361  if (cur_chr == 0)
1362  mval = scan_mathchar(tex_mathcode);
1363  else if (cur_chr == 1)
1364  mval = scan_mathchar(umath_mathcode);
1365  else if (cur_chr == 2)
1367  else
1368  confusion("scan_math");
1369  break;
1370  case math_given_cmd:
1372  break;
1373  case xmath_given_cmd:
1375  break;
1376  case delim_num_cmd:
1377  if (cur_chr == 0)
1379  else if (cur_chr == 1)
1381  else
1382  confusion("scan_math");
1383  break;
1384  default:
1385  /*tex
1386 
1387  The pointer |p| is placed on |save_stack| while a complex subformula
1388  is being scanned.
1389 
1390  */
1391  back_input();
1392  scan_left_brace();
1393  set_saved_record(0, saved_math, 0, p);
1394  incr(save_ptr);
1395  push_math(math_group, mstyle);
1396  return 1;
1397  }
1398  type(p) = math_char_node;
1401  math_fam(p) = cur_fam_par;
1402  else
1403  math_fam(p) = mval.family_value;
1404  return 0;
1405 }
1406 
1407 /*tex
1408 
1409  The |set_math_char| procedure creates a new noad appropriate to a given math
1410  code, and appends it to the current mlist. However, if the math code is
1411  sufficiently large, the |cur_chr| is treated as an active character and
1412  nothing is appended.
1413 
1414 */
1415 
1416 #define math_class_to_type(target,source) \
1417  switch (source) { \
1418  case 0: target = ord_noad_type; break; \
1419  case 1: target = op_noad_type_normal; break; \
1420  case 2: target = bin_noad_type; break; \
1421  case 3: target = rel_noad_type; break; \
1422  case 4: target = open_noad_type; break; \
1423  case 5: target = close_noad_type; break; \
1424  case 6: target = punct_noad_type; break; \
1425  }
1426 
1428 {
1429  pointer p;
1430  if (mval.class_value == 8) {
1431  /*tex An active character that is an |outer_call| is allowed here */
1432  cur_cs = active_to_cs(cur_chr, true);
1433  cur_cmd = eq_type(cur_cs);
1434  cur_chr = equiv(cur_cs);
1435  x_token();
1436  back_input();
1437  } else {
1438  pointer q;
1439  p = new_noad();
1440  q = new_node(math_char_node, 0);
1441  nucleus(p) = q;
1443  math_fam(nucleus(p)) = mval.family_value;
1447  subtype(p) = ord_noad_type;
1448  } else {
1450  }
1451  tail_append(p);
1452  }
1453 }
1454 
1455 /*tex
1456 
1457  The |math_char_in_text| procedure creates a new node representing a math char
1458  in text code, and appends it to the current list. However, if the math code
1459  is sufficiently large, the |cur_chr| is treated as an active character and
1460  nothing is appended.
1461 
1462 */
1463 
1465 {
1466  pointer p;
1467  if (mval.class_value == 8) {
1468  /*tex An active character that is an |outer_call| is allowed here */
1469  cur_cs = active_to_cs(cur_chr, true);
1470  cur_cmd = eq_type(cur_cs);
1471  cur_chr = equiv(cur_cs);
1472  x_token();
1473  back_input();
1474  } else {
1476  tail_append(p);
1477  }
1478 }
1479 
1480 void math_math_comp(void)
1481 {
1482  pointer q;
1483  tail_append(new_noad());
1485  q = new_node(math_char_node, 0);
1486  nucleus(tail) = q;
1487  if (cur_chr == over_noad_type)
1489  else
1490  (void) scan_math(nucleus(tail), m_style);
1491 }
1492 
1494 {
1495  const char *hlp[] = {
1496  "I'm ignoring this misplaced \\limits or \\nolimits command.",
1497  NULL
1498  };
1499  if (head != tail) {
1500  if (type(tail) == simple_noad &&
1505  return;
1506  }
1507  }
1508  tex_error("Limit controls must follow a math operator", hlp);
1509 }
1510 
1511 /*tex
1512 
1513  Delimiter fields of noads are filled in by the |scan_delimiter| routine. The
1514  first parameter of this procedure is the |mem| address where the delimiter
1515  is to be placed; the second tells if this delimiter follows \.{\\radical} or
1516  not.
1517 
1518 */
1519 
1520 static void scan_delimiter(pointer p, int r)
1521 {
1522  delcodeval dval = { 0, 0, 0, 0, 0 };
1523  if (r == tex_mathcode) {
1524  /*tex \.{\\radical} */
1525  dval = do_scan_extdef_del_code(tex_mathcode, true);
1526  } else if (r == umath_mathcode) {
1527  /*tex \.{\\Uradical} */
1528  dval = do_scan_extdef_del_code(umath_mathcode, false);
1529  } else if (r == no_mathcode) {
1530  get_next_nb_nr();
1531  switch (cur_cmd) {
1532  case letter_cmd:
1533  case other_char_cmd:
1534  dval = get_del_code(cur_chr);
1535  break;
1536  case delim_num_cmd:
1537  if (cur_chr == 0) {
1538  /*tex \.{\\delimiter} */
1539  dval = do_scan_extdef_del_code(tex_mathcode, true);
1540  } else if (cur_chr == 1) {
1541  /*tex \.{\\Udelimiter} */
1543  } else {
1544  confusion("scan_delimiter1");
1545  }
1546  break;
1547  default:
1548  dval.small_family_value = -1;
1549  break;
1550  }
1551  } else {
1552  confusion("scan_delimiter2");
1553  }
1554  if (p == null)
1555  return;
1556  if (dval.small_family_value < 0) {
1557  const char *hlp[] = {
1558  "I was expecting to see something like `(' or `\\{' or",
1559  "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
1560  "should probably delete the `{' by typing `1' now, so that",
1561  "braces don't get unbalanced. Otherwise just proceed",
1562  "Acceptable delimiters are characters whose \\delcode is",
1563  "nonnegative, or you can use `\\delimiter <delimiter code>'.",
1564  NULL
1565  };
1566  back_error("Missing delimiter (. inserted)", hlp);
1567  small_fam(p) = 0;
1568  small_char(p) = 0;
1569  large_fam(p) = 0;
1570  large_char(p) = 0;
1571  } else {
1572  small_fam(p) = dval.small_family_value;
1574  large_fam(p) = dval.large_family_value;
1576  }
1577  return;
1578 }
1579 
1580 void math_radical(void)
1581 {
1582  halfword q;
1583  int chr_code = cur_chr;
1584  halfword options = 0;
1585  tail_append(new_node(radical_noad, chr_code));
1586  q = new_node(delim_node, 0);
1587  left_delimiter(tail) = q;
1588  while (1) {
1589  if (scan_keyword("width")) {
1590  scan_dimen(false,false,false);
1592  } else if (scan_keyword("left")) {
1594  } else if (scan_keyword("middle")) {
1596  } else if (scan_keyword("right")) {
1598  } else {
1599  break;
1600  }
1601  }
1603  if (chr_code == 0)
1604  /*tex \.{\\radical} */
1606  else if (chr_code == 1)
1607  /*tex \.{\\Uradical} */
1609  else if (chr_code == 2)
1610  /*tex \.{\\Uroot} */
1612  else if (chr_code == 3)
1613  /*tex \.{\\Uunderdelimiter} */
1615  else if (chr_code == 4)
1616  /*tex \.{\\Uoverdelimiter} */
1618  else if (chr_code == 5)
1619  /*tex \.{\\Udelimiterunder} */
1621  else if (chr_code == 6)
1622  /*tex \.{\\Udelimiterover} */
1624  else if (chr_code == 7)
1625  /*tex \.{\\Uhextensible} */
1627  else
1628  confusion("math_radical");
1629  if (chr_code == 7) {
1630  /*tex type will change */
1631  q = new_node(sub_box_node, 0);
1632  nucleus(tail) = q;
1633  return;
1634  } else if (chr_code == 2) {
1635  /*tex
1636 
1637  The trick with the |vlink(q)| is used by |scan_math| to decide
1638  whether it needs to go on.
1639 
1640  */
1641  q = new_node(math_char_node, 0);
1642  vlink(q) = tail;
1643  degree(tail) = q;
1645  vlink(degree(tail)) = null;
1646  q = new_node(math_char_node, 0);
1647  nucleus(tail) = q;
1649  }
1650  } else {
1651  q = new_node(math_char_node, 0);
1652  nucleus(tail) = q;
1654  }
1655 }
1656 
1657 void math_ac(void)
1658 {
1659  halfword q;
1660  mathcodeval t = { 0, 0, 0 };
1661  mathcodeval b = { 0, 0, 0 };
1662  mathcodeval o = { 0, 0, 0 };
1663  if (cur_cmd == accent_cmd) {
1664  const char *hlp[] = {
1665  "I'm changing \\accent to \\mathaccent here; wish me luck.",
1666  "(Accents are not the same in formulas as they are in text.)",
1667  NULL
1668  };
1669  tex_error("Please use \\mathaccent for accents in math mode", hlp);
1670  }
1672  if (cur_chr == 0) {
1673  /*tex \.{\\mathaccent} */
1675  } else if (cur_chr == 1) {
1676  /*tex \.{\\Umathaccent} */
1677  if (scan_keyword("fixed")) {
1678  /*tex top */
1679  subtype(tail) = 1;
1681  } else if (scan_keyword("both")) {
1682  /*tex top bottom */
1683  if (scan_keyword("fixed")) {
1684  subtype(tail) = 1;
1685  }
1687  if (scan_keyword("fixed")) {
1688  subtype(tail) += 2;
1689  }
1691  } else if (scan_keyword("bottom")) {
1692  /*tex bottom */
1693  if (scan_keyword("fixed")) {
1694  subtype(tail) = 2;
1695  }
1697  } else if (scan_keyword("top")) {
1698  /*tex top */
1699  if (scan_keyword("fixed")) {
1700  subtype(tail) = 1;
1701  }
1703  } else if (scan_keyword("overlay")) {
1704  /* overlay */
1705  if (scan_keyword("fixed")) {
1706  subtype(tail) = 1;
1707  }
1709  } else {
1710  /*tex top */
1712  }
1713  if (scan_keyword("fraction")) {
1714  scan_int();
1716  }
1717  } else {
1718  confusion("mathaccent");
1719  }
1720  if (!(t.character_value == 0 && t.family_value == 0)) {
1721  q = new_node(math_char_node, 0);
1722  top_accent_chr(tail) = q;
1723  math_character(top_accent_chr(tail)) = t.character_value;
1724  if ((t.class_value == math_use_current_family_code) && cur_fam_par_in_range)
1726  else
1727  math_fam(top_accent_chr(tail)) = t.family_value;
1728  }
1729  if (!(b.character_value == 0 && b.family_value == 0)) {
1730  q = new_node(math_char_node, 0);
1731  bot_accent_chr(tail) = q;
1732  math_character(bot_accent_chr(tail)) = b.character_value;
1733  if ((b.class_value == math_use_current_family_code) && cur_fam_par_in_range)
1735  else
1736  math_fam(bot_accent_chr(tail)) = b.family_value;
1737  }
1738  if (!(o.character_value == 0 && o.family_value == 0)) {
1739  q = new_node(math_char_node, 0);
1744  else
1746  }
1747  q = new_node(math_char_node, 0);
1748  nucleus(tail) = q;
1750 }
1751 
1753 {
1754  pointer q, r;
1755  q = new_noad();
1757  r = new_node(sub_box_node, 0);
1758  nucleus(q) = r;
1759  math_list(nucleus(q)) = p;
1760  return q;
1761 }
1762 
1763 /*tex
1764 
1765  The routine that scans the four mlists of a \.{\\mathchoice} is very much
1766  like the routine that builds discretionary nodes.
1767 
1768 */
1769 
1770 void append_choices(void)
1771 {
1773  incr(save_ptr);
1774  set_saved_record(-1, saved_choices, 0, 0);
1776  scan_left_brace();
1777 }
1778 
1779 void build_choices(void)
1780 {
1781  pointer p;
1782  int prev_style;
1783  prev_style = m_style;
1784  unsave_math();
1785  p = fin_mlist(null);
1787  switch (saved_value(-1)) {
1788  case 0:
1789  display_mlist(tail) = p;
1790  break;
1791  case 1:
1792  text_mlist(tail) = p;
1793  break;
1794  case 2:
1795  script_mlist(tail) = p;
1796  break;
1797  case 3:
1799  decr(save_ptr);
1800  return;
1801  break;
1802  }
1803  set_saved_record(-1, saved_choices, 0, (saved_value(-1) + 1));
1804  push_math(math_choice_group, (prev_style + 2));
1805  scan_left_brace();
1806 }
1807 
1808 /*tex
1809 
1810  Subscripts and superscripts are attached to the previous nucleus by the
1811  action procedure called |sub_sup|.
1812 
1813 */
1814 
1815 static void do_sub_sup(int no)
1816 {
1817  pointer q;
1818  if (tail == head || (!scripts_allowed(tail))) {
1819  tail_append(new_noad());
1820  q = new_node(sub_mlist_node, 0);
1821  nucleus(tail) = q;
1822  }
1823  if (cur_cmd == sup_mark_cmd || cur_chr == sup_mark_cmd) {
1824  /*tex |super_sub_script| */
1825  if (supscr(tail) != null) {
1826  const char *hlp[] = {
1827  "I treat `x^1^2' essentially like `x^1{}^2'.", NULL
1828  };
1829  tail_append(new_noad());
1830  q = new_node(sub_mlist_node, 0);
1831  nucleus(tail) = q;
1832  tex_error("Double superscript", hlp);
1833  }
1834  if (no) {
1836  }
1837  q = new_node(math_char_node, 0);
1838  supscr(tail) = q;
1840  } else if (cur_cmd == sub_mark_cmd || cur_chr == sub_mark_cmd) {
1841  if (subscr(tail) != null) {
1842  const char *hlp[] = {
1843  "I treat `x_1_2' essentially like `x_1{}_2'.", NULL
1844  };
1845  tail_append(new_noad());
1846  q = new_node(sub_mlist_node, 0);
1847  nucleus(tail) = q;
1848  tex_error("Double subscript", hlp);
1849  }
1850  if (no) {
1852  }
1853  q = new_node(math_char_node, 0);
1854  subscr(tail) = q;
1856  }
1857 }
1858 
1859 void sub_sup(void)
1860 {
1861  do_sub_sup(0);
1862 }
1863 
1864 void no_sub_sup(void)
1865 {
1866  do_sub_sup(1);
1867 }
1868 
1869 /*tex
1870 
1871  An operation like `\.{\\over}' causes the current mlist to go into a state of
1872  suspended animation: |incompleat_noad| points to a |fraction_noad| that
1873  contains the mlist-so-far as its numerator, while the denominator is yet to
1874  come. Finally when the mlist is finished, the denominator will go into the
1875  incompleat fraction noad, and that noad will become the whole formula, unless
1876  it is surrounded by `\.{\\left}' and `\.{\\right}' delimiters.
1877 
1878 */
1879 
1880 void math_fraction(void)
1881 {
1882  /*tex The type of generalized fraction we are scanning: */
1883  halfword c;
1884  pointer q;
1885  halfword options = 0;
1886  halfword temp_value;
1887  c = cur_chr;
1888  if (incompleat_noad_par != null) {
1889  const char *hlp[] = {
1890  "I'm ignoring this fraction specification, since I don't",
1891  "know whether a construction like `x \\over y \\over z'",
1892  "means `{x \\over y} \\over z' or `x \\over {y \\over z}'.",
1893  NULL
1894  };
1895  if (c >= delimited_code) {
1896  scan_delimiter(null, no_mathcode);
1897  scan_delimiter(null, no_mathcode);
1898  }
1899  if ((c % delimited_code) == above_code)
1901  tex_error("Ambiguous; you need another { and }", hlp);
1902  } else {
1904  temp_value = new_node(sub_mlist_node, 0);
1905  numerator(incompleat_noad_par) = temp_value;
1907  vlink(head) = null;
1908  tail = head;
1910 
1911  if ((c % delimited_code) == skewed_code) {
1912  q = new_node(delim_node, 0);
1915  }
1916  if (c >= delimited_code) {
1917  q = new_node(delim_node, 0);
1919  q = new_node(delim_node, 0);
1923  }
1924  switch (c % delimited_code) {
1925  case above_code:
1926  while (1) {
1927  if (scan_keyword("exact")) {
1929  } else if (scan_keyword("norule")) {
1931  } else {
1932  break;
1933  }
1934  }
1938  break;
1939  case over_code:
1941  break;
1942  case atop_code:
1944  break;
1945  case skewed_code:
1946  while (1) {
1947  if (scan_keyword("exact")) {
1949  } else if (scan_keyword("noaxis")) {
1951  } else {
1952  break;
1953  }
1954  }
1957  break;
1958  }
1959  }
1960 }
1961 
1962 /*tex
1963 
1964  At the end of a math formula or subformula, the |fin_mlist| routine is called
1965  upon to return a pointer to the newly completed mlist, and to pop the nest
1966  back to the enclosing semantic level. The parameter to |fin_mlist|, if not
1967  null, points to a |fence_noad| that ends the current mlist; this |fence_noad|
1968  has not yet been appended.
1969 
1970 */
1971 
1973 {
1974  pointer q;
1975  if (incompleat_noad_par != null) {
1976  if (denominator(incompleat_noad_par) != null) {
1978  } else {
1979  q = new_node(sub_mlist_node, 0);
1981  }
1983  if (p == null) {
1985  } else {
1987  if ((type(q) != fence_noad) || (subtype(q) != left_noad_side) || (delim_par == null))
1988  confusion("right");
1992  }
1993  } else {
1994  vlink(tail) = p;
1995  q = vlink(head);
1996  }
1997  pop_nest();
1998  return q;
1999 }
2000 
2001 /*tex
2002 
2003  Now at last we're ready to see what happens when a right brace occurs in a
2004  math formula. Two special cases are simplified here: Braces are effectively
2005  removed when they surround a single Ord without sub/superscripts, or when
2006  they surround an accent that is the nucleus of an Ord atom.
2007 
2008 */
2009 
2011 {
2012  int old_style = m_style;
2013  unsave_math();
2014  decr(save_ptr);
2015  assert(saved_type(0) == saved_math);
2017  p = fin_mlist(null);
2018  math_list(saved_value(0)) = p;
2019  if (p != null && vlink(p) == null) {
2020  if (type(p) == simple_noad) {
2021  if (subscr(p) == null && supscr(p) == null) {
2022  /*tex (subtype(p) == ord_noad_type) */
2023  int flatten = 0;
2024  int modepar = math_flatten_mode_par;
2025  switch (subtype(p)) {
2026  case ord_noad_type :
2027  flatten = (modepar & 1) == 1;
2028  break;
2029  case bin_noad_type :
2030  flatten = (modepar & 2) == 2;
2031  break;
2032  case rel_noad_type :
2033  flatten = (modepar & 4) == 4;
2034  break;
2035  case punct_noad_type :
2036  flatten = (modepar & 8) == 8;
2037  break;
2038  case inner_noad_type :
2039  flatten = (modepar & 16) == 16;
2040  break;
2041  default:
2042  break;
2043  }
2044  if (flatten) {
2045  type(saved_value(0)) = type(nucleus(p));
2046  if (type(nucleus(p)) == math_char_node) {
2050  } else {
2052  math_list(nucleus(p)) = null;
2053  }
2056  node_attr(nucleus(p)) = null;
2057  flush_node(p);
2058  }
2059  }
2060  } else if (type(p) == accent_noad) {
2061  if (saved_value(0) == nucleus(tail) && type(tail) == simple_noad && subtype(tail) == ord_noad_type) {
2062  pointer q = head;
2063  while (vlink(q) != tail)
2064  q = vlink(q);
2065  vlink(q) = p;
2066  nucleus(tail) = null;
2067  subscr(tail) = null;
2068  supscr(tail) = null;
2070  node_attr(p) = node_attr(tail);
2071  node_attr(tail) = null;
2072  flush_node(tail);
2073  tail = p;
2074  }
2075  }
2076  }
2077  if (vlink(saved_value(0)) > 0) {
2078  pointer q;
2079  q = new_node(math_char_node, 0);
2080  nucleus(vlink(saved_value(0))) = q;
2081  vlink(saved_value(0)) = null;
2082  saved_value(0) = q;
2083  (void) scan_math(saved_value(0), old_style);
2084  /*tex restart */
2085  }
2086 }
2087 
2088 /*tex
2089 
2090  We have dealt with all constructions of math mode except `\.{\\left}' and
2091  `\.{\\right}', so the picture is completed by the following sections of the
2092  program. The |middle| feature of eTeX allows one ore several \.{\\middle}
2093  delimiters to appear between \.{\\left} and \.{\\right}.
2094 
2095 */
2096 
2098 {
2099  /*tex |left_noad_side| .. |right_noad_side| */
2100  halfword t;
2101  /*tex new noad */
2102  pointer p;
2103  /*tex resulting mlist */
2104  pointer q;
2105  /*tex temporary */
2106  pointer r;
2107  halfword ht = 0;
2108  halfword dp = 0;
2109  halfword options = 0;
2110  halfword type = -1 ;
2111  t = cur_chr;
2112  if (t > 10) {
2113  /*tex we have \Uleft \Uright \Umiddle */
2114  t = t - 10;
2115  while (1) {
2116  if (scan_keyword("height")) {
2117  scan_dimen(false,false,false);
2118  ht = cur_val ;
2119  } else if (scan_keyword("depth")) {
2120  scan_dimen(false,false,false);
2121  dp = cur_val ;
2122  } else if (scan_keyword("axis")) {
2124  } else if (scan_keyword("noaxis")) {
2126  } else if (scan_keyword("exact")) {
2128  } else if (scan_keyword("class")) {
2129  scan_int();
2131  } else {
2132  break;
2133  }
2134  }
2135  }
2136  if ((t != no_noad_side) && (t != left_noad_side) && (cur_group != math_left_group)) {
2137  if (cur_group == math_shift_group) {
2138  scan_delimiter(null, no_mathcode);
2139  if (t == middle_noad_side) {
2140  const char *hlp[] = {
2141  "I'm ignoring a \\middle that had no matching \\left.",
2142  NULL
2143  };
2144  tex_error("Extra \\middle", hlp);
2145  } else {
2146  const char *hlp[] = {
2147  "I'm ignoring a \\right that had no matching \\left.",
2148  NULL
2149  };
2150  tex_error("Extra \\right", hlp);
2151  }
2152  } else {
2153  off_save();
2154  }
2155  } else {
2156  p = new_noad();
2157  type(p) = fence_noad;
2158  subtype(p) = (quarterword) t;
2159  r = new_node(delim_node, 0);
2160  delimiter(p) = r;
2161  delimiterheight(p) = ht;
2162  delimiterdepth(p) = dp;
2164  delimiterclass(p) = type;
2165  delimiteritalic(p) = 0;
2166  delimitersamesize(p) = 0;
2168  if (t == no_noad_side) {
2169  tail_append(new_noad());
2171  r = new_node(sub_mlist_node, 0);
2172  nucleus(tail) = r;
2173  math_list(nucleus(tail)) = p;
2174  return ;
2175  }
2176  if (t == left_noad_side) {
2177  q = p;
2178  } else {
2179  q = fin_mlist(p);
2180  unsave_math();
2181  }
2182  if (t != right_noad_side) {
2184  vlink(head) = q;
2185  tail = p;
2186  delim_par = p;
2187  } else {
2188  tail_append(new_noad());
2190  r = new_node(sub_mlist_node, 0);
2191  nucleus(tail) = r;
2192  math_list(nucleus(tail)) = q;
2193  }
2194  }
2195 }
2196 
2197 /*tex
2198 
2199  \TeX\ gets to the following part of the program when the first `\.\$' ending
2200  a display has been scanned.
2201 
2202 */
2203 
2204 static void check_second_math_shift(void)
2205 {
2206  get_x_token();
2207  if (cur_cmd != math_shift_cmd) {
2208  const char *hlp[] = {
2209  "The `$' that I just saw supposedly matches a previous `$$'.",
2210  "So I shall assume that you typed `$$' both times.",
2211  NULL
2212  };
2213  back_error("Display math should end with $$", hlp);
2214  }
2215 }
2216 
2217 static void check_display_math_end(void)
2218 {
2219  if (cur_chr != cramped_display_style) {
2220  const char *hlp[] = {
2221  "I shall assume that you typed that.",
2222  NULL
2223  };
2224  tex_error("Display math should end with \\Ustopdisplaymath", hlp);
2225  }
2226 }
2227 
2228 static void check_inline_math_end(void)
2229 {
2230  if (cur_chr != cramped_text_style) {
2231  const char *hlp[] = {
2232  "I shall assume that you typed that.",
2233  NULL
2234  };
2235  tex_error("Inline math should end with \\Ustopmath", hlp);
2236  }
2237 }
2238 
2239 static void resume_after_display(void)
2240 {
2241  if (cur_group != math_shift_group)
2242  confusion("display");
2243  unsave_math();
2245  push_nest();
2246  mode = hmode;
2247  space_factor_par = 1000;
2248  /*tex This needs to be intercepted in the display math start! */
2250  get_x_token();
2251  if (cur_cmd != spacer_cmd)
2252  back_input();
2253  if (nest_ptr == 1) {
2254  normal_page_filter(after_display);
2255  build_page();
2256  }
2257 }
2258 
2259 /*tex
2260 
2261  The fussiest part of math mode processing occurs when a displayed formula is
2262  being centered and placed with an optional equation number.
2263 
2264  At this time we are in vertical mode (or internal vertical mode).
2265 
2266  \starttabulate
2267  \NC \type {p} \NC points to the mlist for the formula \NC \NR
2268  \NC \type {a} \NC is either |null| or it points to a box containing the equation number \NC \NR
2269  \NC \type {l} \NC is true if there was an \.{\\leqno}/ (so |a| is a horizontal box) \NC \NR
2270  \stoptabulate
2271 
2272 */
2273 
2274 #define inject_display_skip_before(g) \
2275  if (g > 0) { \
2276  switch (display_skip_mode_par) { \
2277  case 0 : \
2278  /*tex normal tex | always */ \
2279  case 1 : \
2280  /*tex always */ \
2281  tail_append(new_param_glue(g)); \
2282  break; \
2283  case 2 : \
2284  /*tex non-zero */ \
2285  if (! glue_is_zero(glue_par(g))) \
2286  tail_append(new_param_glue(g)); \
2287  break; \
2288  case 3: \
2289  /*tex ignore */ \
2290  break; \
2291  default: \
2292  /*tex > 3 reserved for future use */ \
2293  tail_append(new_param_glue(g)); \
2294  break; \
2295  } \
2296  }
2297 
2298 #define inject_display_skip_after(g) \
2299  if (g > 0) { \
2300  switch (display_skip_mode_par) { \
2301  case 0 : \
2302  /*tex normal tex | always */ \
2303  case 1 : \
2304  /*tex always */ \
2305  tail_append(new_param_glue(g)); \
2306  break; \
2307  case 2 : \
2308  /*tex non-zero */ \
2309  if (! glue_is_zero(glue_par(g))) \
2310  tail_append(new_param_glue(g)); \
2311  break; \
2312  case 3: \
2313  /*tex ignore */ \
2314  break; \
2315  default: \
2316  /*tex > 3 reserved for future use */ \
2317  tail_append(new_param_glue(g)); \
2318  break; \
2319  } \
2320  }
2321 
2322 static void finish_displayed_math(boolean l, pointer eqno_box, pointer p)
2323 {
2324  /*tex box containing the equation */
2325  pointer eq_box;
2326  /*tex width of the equation */
2327  scaled eq_w;
2328  /*tex width of the line */
2329  scaled line_w;
2330  /*tex width of equation number */
2331  scaled eqno_w;
2332  /*tex width of equation number plus space to separate from equation */
2333  scaled eqno_w2;
2334  /*tex move the line right this much */
2335  scaled line_s;
2336  /*tex displacement of equation in the line */
2337  scaled d;
2338  /*tex glue parameter codes for before and after */
2339  small_number g1, g2;
2340  /*tex kern nodes used to position the display */
2341  pointer r,s;
2342  /*tex tail of adjustment list */
2343  pointer t;
2344  /*tex tail of pre-adjustment list */
2345  pointer pre_t;
2346  /*tex true if the math and surrounding text dirs are opposed */
2347  boolean swap_dir;
2348  scaled eqno_width;
2349  swap_dir = (pre_display_direction_par < 0 ? true : false );
2350  if (eqno_box != null && swap_dir)
2351  l = !l;
2354  eq_box = hpack(p, 0, additional, -1);
2355  subtype(eq_box) = equation_list;
2356  build_attribute_list(eq_box);
2357  p = list_ptr(eq_box);
2358  t = adjust_tail;
2359  adjust_tail = null;
2360  pre_t = pre_adjust_tail;
2361  pre_adjust_tail = null;
2362  eq_w = width(eq_box);
2363  line_w = display_width_par;
2364  line_s = display_indent_par;
2365  if (eqno_box == null) {
2366  eqno_w = 0;
2367  eqno_width = 0;
2368  eqno_w2 = 0;
2369  } else {
2370  eqno_w = width(eqno_box);
2371  eqno_width = eqno_w;
2373  subtype(eqno_box) = equation_number_list;
2374  /*tex build_attribute_list(eqno_box); */
2375  }
2376  if (eq_w + eqno_w2 > line_w) {
2377  /*tex
2378 
2379  The user can force the equation number to go on a separate line by
2380  causing its width to be zero.
2381 
2382  */
2383  if ((eqno_w != 0) && ((eq_w - total_shrink[normal] + eqno_w2 <= line_w)
2384  || (total_shrink[sfi] != 0) || (total_shrink[fil] != 0)
2385  || (total_shrink[fill] != 0) || (total_shrink[filll] != 0))) {
2386  list_ptr(eq_box) = null;
2387  flush_node(eq_box);
2388  eq_box = hpack(p, line_w - eqno_w2, exactly, -1);
2389  subtype(eq_box) = equation_list;
2390  build_attribute_list(eq_box);
2391  } else {
2392  eqno_w = 0;
2393  if (eq_w > line_w) {
2394  list_ptr(eq_box) = null;
2395  flush_node(eq_box);
2396  eq_box = hpack(p, line_w, exactly, -1);
2397  subtype(eq_box) = equation_list;
2398  build_attribute_list(eq_box);
2399  }
2400  }
2401  eq_w = width(eq_box);
2402  }
2403  /*tex
2404 
2405  We try first to center the display without regard to the existence of the
2406  equation number. If that would make it too close (where ``too close''
2407  means that the space between display and equation number is less than the
2408  width of the equation number), we either center it in the remaining space
2409  or move it as far from the equation number as possible. The latter
2410  alternative is taken only if the display begins with glue, since we
2411  assume that the user put glue there to control the spacing precisely.
2412 
2413  */
2414  d = half(line_w - eq_w);
2415  if ((eqno_w > 0) && (d < 2 * eqno_w)) {
2416  /*tex too close */
2417  d = half(line_w - eq_w - eqno_w);
2418  if (p != null)
2419  if (!is_char_node(p))
2420  if (type(p) == glue_node)
2421  d = 0;
2422  }
2424  if ((d + line_s <= pre_display_size_par) || l) {
2425  /*tex not enough clearance */
2428  } else {
2431  }
2432  /*tex
2433 
2434  If the equation number is set on a line by itself, either before or after
2435  the formula, we append an infinite penalty so that no page break will
2436  separate the display from its number; and we use the same size and
2437  displacement for all three potential lines of the display, even though
2438  `\.{\\parshape}' may specify them differently.
2439 
2440  \.{\\leqno} on a forced single line due to |width=0|; it follows that |type(a)=hlist_node|
2441 
2442  */
2443  if (eqno_box && l && (eqno_w == 0)) {
2444  /* if (math_direction_par==dir_TLT) { */
2445  shift_amount(eqno_box) = 0;
2446  /* } else { */
2447  /* } */
2448  append_to_vlist(eqno_box,lua_key_index(equation_number));
2450  } else {
2452  }
2453  if (eqno_w != 0) {
2454  r = new_kern(line_w - eq_w - eqno_w - d);
2455  if (l) {
2456  if (swap_dir) {
2457  if (math_direction_par==dir_TLT) {
2458  /*tex TRT + TLT + \eqno: (swap_dir=true, math_direction_par=TLT, l=true) */
2459  s = new_kern(width(r) + eqno_w);
2460  try_couple_nodes(eqno_box,r);
2461  try_couple_nodes(r,eq_box);
2462  try_couple_nodes(eq_box,s);
2463  } else {
2464  /*tex TLT + TRT + \eqno: (swap_dir=true, math_direction_par=TRT, l=true) */
2465  try_couple_nodes(eqno_box,r);
2466  try_couple_nodes(r,eq_box);
2467  }
2468  } else {
2469  if (math_direction_par==dir_TLT) {
2470  /*tex TLT + TLT + \leqno: (swap_dir=false, math_direction_par=TLT, l=true) */
2471  s = new_kern(width(r) + eqno_w);
2472  } else {
2473  /*tex TRT + TRT + \leqno: (swap_dir=false, math_direction_par=TRT, l=true) */
2474  s = new_kern(width(r));
2475  }
2476  try_couple_nodes(eqno_box,r);
2477  try_couple_nodes(r,eq_box);
2478  try_couple_nodes(eq_box,s);
2479  }
2480  eq_box = eqno_box;
2481  } else {
2482  if (swap_dir) {
2483  if (math_direction_par==dir_TLT) {
2484  /*tex TRT + TLT + \leqno: (swap_dir=true, math_direction_par=TLT, l=false) */
2485  } else {
2486  /*tex TLT + TRT + \leqno: (swap_dir=true, math_direction_par=TRT, l=false) */
2487  }
2488  try_couple_nodes(eq_box,r);
2489  try_couple_nodes(r,eqno_box);
2490  } else {
2491  if (math_direction_par==dir_TLT) {
2492  /*tex TLT + TLT + \eqno: (swap_dir=false, math_direction_par=TLT, l=false) */
2493  s = new_kern(d);
2494  } else {
2495  /*tex TRT + TRT + \eqno: (swap_dir=false, math_direction_par=TRT, l=false) */
2496  s = new_kern(width(r) + eqno_w);
2497  }
2498  try_couple_nodes(s,eq_box);
2499  try_couple_nodes(eq_box,r);
2500  try_couple_nodes(r,eqno_box);
2501  eq_box = s;
2502  }
2503  }
2504  eq_box = hpack(eq_box, 0, additional, -1);
2505  subtype(eq_box) = equation_list; /* new */
2506  build_attribute_list(eq_box);
2507  shift_amount(eq_box) = line_s;
2508  } else {
2509  shift_amount(eq_box) = line_s + d;
2510  }
2511  /*tex check for prev: */
2512  append_to_vlist(eq_box,lua_key_index(equation));
2513  if ((eqno_box != null) && (eqno_w == 0) && !l) {
2515  /* if (math_direction_par==dir_TLT) { */
2516  shift_amount(eqno_box) = line_s + line_w - eqno_width ;
2517  /* } else { */
2518  /* } */
2519  append_to_vlist(eqno_box,lua_key_index(equation_number));
2520  g2 = 0;
2521  }
2522  if (t != adjust_head) {
2523  /*tex migrating material comes after equation number */
2526  tail = t;
2527  }
2528  if (pre_t != pre_adjust_head) {
2531  tail = pre_t;
2532  }
2536 }
2537 
2538 void after_math(void)
2539 {
2540  /*tex |mmode| or |-mmode| */
2541  int m;
2542  /*tex the formula */
2543  pointer p;
2544  /*tex box containing equation number */
2545  pointer a = null;
2546  /*tex `\.{\\leqno}' instead of `\.{\\eqno}' */
2547  boolean l = false;
2548  m = mode;
2549  /*tex this pops the nest */
2550  p = fin_mlist(null);
2551  if (cur_cmd == math_shift_cs_cmd &&
2552  (cur_chr == text_style || cur_chr == display_style)) {
2553  you_cant();
2554  }
2555  if (mode == -m) {
2556  /*tex end of equation number */
2557  if (cur_cmd == math_shift_cmd) {
2559  } else {
2561  }
2562  run_mlist_to_hlist(p, false, text_style);
2563  a = hpack(vlink(temp_head), 0, additional, -1);
2565  unsave_math();
2566  /*tex now |cur_group=math_shift_group| */
2567  decr(save_ptr);
2568  assert(saved_type(0) == saved_eqno);
2569  if (saved_value(0) == 1)
2570  l = true;
2571  m = mode;
2572  p = fin_mlist(null);
2573 
2574  }
2575  if (m < 0) {
2576  /*tex
2577 
2578  The |unsave| is done after everything else here; hence an appearance
2579  of `\.{\\mathsurround}' inside of `\.{\$...\$}' affects the spacing
2580  at these particular \.\$'s. This is consistent with the conventions
2581  of `\.{\$\$...\$\$}', since `\.{\\abovedisplayskip}' inside a display
2582  affects the space above that display.
2583 
2584  */
2585  if (cur_cmd == math_shift_cs_cmd) {
2587  }
2589  /*tex begin mathskip code */
2590  switch (math_skip_mode) {
2591  case 0 :
2592  /*tex obey mathsurround when zero glue */
2593  if (! glue_is_zero(math_skip_par)) {
2595  surround(tail) = 0;
2596  }
2597  break ;
2598  case 1 :
2599  /*tex always left */
2600  case 3 :
2601  /*tex always both */
2602  case 6 :
2603  /*tex only when skip */
2605  surround(tail) = 0;
2606  break ;
2607  case 2 :
2608  /*tex only right */
2609  surround(tail) = 0;
2610  break ;
2611  case 4 :
2612  /*tex ignore, obey marthsurround */
2613  break ;
2614  case 5:
2615  /*tex all spacing disabled */
2616  surround(tail) = 0;
2617  break ;
2618  }
2619  /*tex end mathskip code */
2620  if (dir_math_save) {
2622  }
2625 
2626  while (vlink(tail) != null) {
2627  tail = vlink(tail);
2628  }
2629  if (dir_math_save) {
2631  subtype(tail) = cancel_dir;
2632  }
2633  dir_math_save = false;
2635  /*tex begin mathskip code */
2636  switch (math_skip_mode) {
2637  case 0 :
2638  /*tex obey mathsurround when zero glue */
2639  if (! glue_is_zero(math_skip_par)) {
2641  surround(tail) = 0;
2642  }
2643  break ;
2644  case 2 :
2645  /*tex always right */
2646  case 3 :
2647  /*tex always both */
2648  case 6 :
2649  /*tex only when skip */
2651  surround(tail) = 0;
2652  break ;
2653  case 1 :
2654  /*tex only left */
2655  surround(tail) = 0;
2656  break ;
2657  case 4 :
2658  /*tex ignore, obey marthsurround */
2659  break ;
2660  case 5:
2661  /*tex all spacing disabled */
2662  surround(tail) = 0;
2663  break ;
2664  }
2665  /*tex end mathskip code */
2666  space_factor_par = 1000;
2667  unsave_math();
2668  } else {
2669  if (a == null) {
2670  if (cur_cmd == math_shift_cmd) {
2672  } else {
2674  }
2675  }
2678  }
2679 }
2680 
2681 /*tex
2682 
2683  When \.{\\halign} appears in a display, the alignment routines operate
2684  essentially as they do in vertical mode. Then the following program is
2685  activated, with |p| and |q| pointing to the beginning and end of the
2686  resulting list, and with |aux_save| holding the |prev_depth| value.
2687 
2688 */
2689 
2691 {
2692  do_assignments();
2693  if (cur_cmd == math_shift_cmd) {
2695  } else {
2697  }
2698  pop_nest();
2701  vlink(tail) = p;
2702  if (p != null)
2703  tail = q;
2706  cur_list.prev_depth_field = saved_prevdepth;
2708 }
2709 
2710 /*tex Interface to \.{\\Umath} and \.{\\mathstyle}: */
2711 
2713 {
2714  pointer q;
2715  tail_append(new_noad());
2716  q = new_node(math_char_node, 0);
2717  nucleus(tail) = q;
2719 }
2720 
2722 {
2723  if (abs(mode) == mmode)
2724  print_int(m_style);
2725  else
2726  print_int(-1);
2727 }
q
Definition: afm2pl.c:2287
int level
Definition: afm2pl.c:1694
double quad
Definition: aftopl.c:71
void print_cmd_chr(quarterword cmd, halfword chr_code)
Definition: aptex-src.c:11377
void scan_dimen(boolean mu, boolean inf, boolean shortcut)
Definition: aptex-src.c:17035
void get_token(void)
Definition: aptex-src.c:14331
void build_page(void)
Definition: aptex-src.c:29726
void print_scaled(scaled s)
Definition: aptex-src.c:8377
static void tail_append(pointer val)
void show_node_list(integer p)
Definition: aptex-src.c:9659
void do_assignments(void)
Definition: aptex-src.c:34185
void print_int(integer n)
Definition: aptex-src.c:7042
void back_input(void)
Definition: aptex-src.c:14086
void print_char(ASCII_code s)
Definition: aptex-src.c:6782
void get_x_token(void)
Definition: aptex-src.c:15041
void flush_node_list(pointer p)
Definition: aptex-src.c:10285
void scan_left_brace(void)
Definition: aptex-src.c:15098
#define save_type(a)
Definition: aptex-macros.h:943
#define pre_display_direction_code
Definition: aptex-macros.h:764
#define inf_penalty
Definition: aptex-macros.h:303
#define display_indent_code
Definition: aptex-macros.h:876
#define shift_amount(a)
Definition: aptex-macros.h:201
#define max_dimen
#define text_size
#define fill
Definition: aptex-macros.h:292
#define sup_style(a)
#define scan_normal_dimen()
#define dimen_base
Definition: aptex-macros.h:778
#define cramped_style(a)
#define text_mlist(a)
#define width(a)
Definition: aptex-macros.h:198
#define flush_char()
Definition: aptex-macros.h:70
#define cur_length
Definition: aptex-macros.h:69
#define type(a)
Definition: aptex-macros.h:171
#define nucleus(a)
#define small_fam(a)
#define eq_type(a)
Definition: aptex-macros.h:536
#define thickness
#define pre_display_size_code
Definition: aptex-macros.h:874
#define right_delimiter(a)
#define script_script_mlist(a)
#define small_char(a)
#define subscr(a)
#define temp_head
Definition: aptex-macros.h:322
#define supscr(a)
#define display_mlist(a)
#define subtype(a)
Definition: aptex-macros.h:172
#define below_display_short_skip_code
Definition: aptex-macros.h:570
#define denominator
#define is_char_node(a)
Definition: aptex-macros.h:174
#define delimiter
#define int_base
Definition: aptex-macros.h:657
#define adjust_head
Definition: aptex-macros.h:324
#define before
Definition: aptex-macros.h:256
#define default_code
#define level_boundary
Definition: aptex-macros.h:949
#define hmode
Definition: aptex-macros.h:505
#define above_display_short_skip_code
Definition: aptex-macros.h:569
#define numerator
#define restore_old_value
Definition: aptex-macros.h:946
#define sub_style(a)
#define large_fam(a)
#define left_delimiter(a)
#define display_width_code
Definition: aptex-macros.h:875
#define num_style(a)
#define large_char(a)
#define list_ptr(a)
Definition: aptex-macros.h:203
#define cur_fam_code
Definition: aptex-macros.h:743
#define script_mlist(a)
#define above_display_skip_code
Definition: aptex-macros.h:567
#define below_display_skip_code
Definition: aptex-macros.h:568
#define mmode
Definition: aptex-macros.h:506
void pop_nest(void)
Definition: aptex-src.c:10759
static void new_save_level(group_code c)
Definition: aptex-src.c:13296
static pointer new_kern(scaled w)
Definition: aptex-src.c:9055
static boolean scan_keyword(char *s)
Definition: aptex-src.c:15130
static void eq_word_define(pointer p, integer w)
Definition: aptex-src.c:13409
static void unsave(void)
Definition: aptex-src.c:13491
static pointer new_math(scaled w, small_number s)
Definition: aptex-src.c:8986
void x_token(void)
Definition: aptex-src.c:15078
static void line_break(boolean d)
Definition: aptex-src.c:26328
static pointer new_penalty(integer m)
Definition: aptex-src.c:9067
static void print_current_string(void)
Definition: aptex-src.c:8277
static pointer hpack(pointer p, scaled w, small_number m)
Definition: aptex-src.c:22713
static scaled x_over_n(scaled x, integer n)
Definition: aptex-src.c:8421
void end_diagnostic(boolean blank_line)
Definition: aptex-src.c:11249
void begin_diagnostic(void)
Definition: aptex-src.c:11235
void scan_char_num(void)
Definition: aptex-src.c:15203
static void push_nest(void)
Definition: aptex-src.c:10727
static void you_cant(void)
Definition: aptex-src.c:30244
static void scan_optional_equals(void)
Definition: aptex-src.c:15119
static void append_to_vlist(pointer b)
Definition: aptex-src.c:23374
static void off_save(void)
Definition: aptex-src.c:30360
void begin_token_list(pointer p, quarterword t)
Definition: aptex-src.c:14007
uint8_t small_number
Definition: aptex.h:113
static pointer adjust_tail
Definition: aptex.h:552
static int cur_group
Definition: aptex.h:401
static halfword cur_chr
Definition: aptex.h:407
uint8_t ASCII_code
Definition: aptex.h:109
static integer nest_ptr
Definition: aptex.h:376
char group_code
Definition: aptex.h:260
static int cur_cmd
Definition: aptex.h:406
static integer depth_threshold
Definition: aptex.h:371
static scaled total_shrink[4]
Definition: aptex.h:547
static pointer cur_cs
Definition: aptex.h:408
static pointer just_box
Definition: aptex.h:578
static integer save_ptr
Definition: aptex.h:398
END END END break
Definition: bibtex-3.c:1974
static char * options
Definition: bmeps.c:236
int * g2
Definition: bmpfont.h:57
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
halfword new_dir(int s)
Definition: directions.c:85
halfword text_dir_ptr
Definition: directions.c:78
#define textdir_opposite(a, b)
Definition: directions.h:94
int w
Definition: dviconv.c:26
unsigned short halfword
Definition: dvips.h:68
@ penalty_par_code
Definition: equivalents.h:521
#define saved_type(A)
Definition: equivalents.h:425
#define math_skip_mode
Definition: equivalents.h:585
#define hsize_par
Definition: equivalents.h:605
#define saved_eqno
Definition: equivalents.h:445
#define display_width_par
Definition: equivalents.h:588
#define saved_textdir
Definition: equivalents.h:444
#define every_display_par
Definition: equivalents.h:692
#define cur_fam_par
Definition: equivalents.h:648
#define par_shape_par_ptr
Definition: equivalents.h:715
#define hang_after_par
Definition: equivalents.h:615
#define text_direction_par
Definition: equivalents.h:598
#define hang_indent_par
Definition: equivalents.h:614
#define delim_par
Definition: equivalents.h:713
@ dir_TLT
Definition: equivalents.h:537
#define space_factor_par
Definition: equivalents.h:709
#define saved_math
Definition: equivalents.h:447
#define set_saved_record(A, B, C, D)
Definition: equivalents.h:429
@ math_group
Definition: equivalents.h:501
@ math_choice_group
Definition: equivalents.h:505
@ math_shift_group
Definition: equivalents.h:507
@ math_left_group
Definition: equivalents.h:508
#define pre_display_penalty_par
Definition: equivalents.h:650
#define math_flatten_mode_par
Definition: equivalents.h:676
#define saved_value(A)
Definition: equivalents.h:427
#define save_value(A)
Definition: equivalents.h:415
#define tracing_assigns_par
Definition: equivalents.h:753
#define math_direction_par
Definition: equivalents.h:599
#define body_direction_code
Definition: equivalents.h:330
#define math_use_current_family_code
Definition: equivalents.h:817
#define math_surround_par
Definition: equivalents.h:590
#define math_eqno_gap_step_par
Definition: equivalents.h:593
#define cur_fam_par_in_range
Definition: equivalents.h:653
#define every_math_par
Definition: equivalents.h:691
#define display_indent_par
Definition: equivalents.h:589
#define saved_choices
Definition: equivalents.h:446
#define par_direction_code
Definition: equivalents.h:331
#define tracing_restores_par
Definition: equivalents.h:756
#define text_direction_code
Definition: equivalents.h:332
#define pre_display_direction_par
Definition: equivalents.h:649
#define prev_graf_par
Definition: equivalents.h:704
#define incompleat_noad_par
Definition: equivalents.h:710
#define math_skip_par
Definition: equivalents.h:584
#define post_display_penalty_par
Definition: equivalents.h:651
#define math_pre_display_gap_factor_par
Definition: equivalents.h:779
#define pre_display_size_par
Definition: equivalents.h:587
@ text_style
Definition: equivalents.h:528
@ display_style
Definition: equivalents.h:526
@ cramped_display_style
Definition: equivalents.h:527
@ cramped_text_style
Definition: equivalents.h:529
unsigned char * pointer
Definition: fontmisc.h:33
static void
Definition: fpif.c:118
mpz_t * f
Definition: gen-fib.c:34
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define d(n)
Definition: gpos-common.c:151
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
@ every_display_text
Definition: inputstack.h:301
@ every_math_text
Definition: inputstack.h:300
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define true
Definition: ftrandom.c:51
#define false
Definition: ftrandom.c:52
#define half(i)
Definition: cpascal.h:70
#define decr(x)
Definition: cpascal.h:91
#define incr(x)
Definition: cpascal.h:92
#define normal
Definition: ctangleboot.c:124
#define equiv
Definition: ctangleboot.c:107
static int cur_val
Definition: ctangleboot.c:325
#define confusion(s)
Definition: ctangleboot.c:78
#define cint
Definition: texmfmem.h:177
#define print_ln(v)
Definition: tie.c:37
#define snprintf
Definition: snprintf.c:41
#define lua_key_index(a)
Definition: luatex-api.h:320
void tex_error(const char *msg, const char **hlp)
Definition: errors.c:847
#define normal_page_filter(A)
#define checked_page_filter(A)
#define get_cur_font()
Definition: mainbody.h:242
#define swap_hang_indent(indentation)
Definition: maincontrol.h:183
#define swap_parshape_indent(indentation, width)
Definition: maincontrol.h:186
void set_sa_item(sa_tree head, int n, sa_tree_item v, int gl)
Definition: managed-sa.c:77
void rawset_sa_item(sa_tree head, int n, sa_tree_item v)
Definition: managed-sa.c:103
sa_tree_item get_sa_item(const sa_tree head, const int n)
Definition: managed-sa.c:63
sa_tree undump_sa_tree(const char *name)
Definition: managed-sa.c:253
sa_tree new_sa_tree(int size, int type, sa_tree_item dflt)
Definition: managed-sa.c:176
void dump_sa_tree(sa_tree a, const char *name)
Definition: managed-sa.c:205
delcodeval get_del_code(int n)
Definition: mathcodes.c:278
void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl)
Definition: mathcodes.c:256
mathcodeval mathchar_from_integer(int value, int extcode)
Definition: mathcodes.c:82
mathcodeval get_math_code(int n)
Definition: mathcodes.c:168
void set_math_code(int n, int mathclass, int mathfamily, int mathcharacter, quarterword level)
Definition: mathcodes.c:146
#define tex_mathcode
Definition: mathcodes.h:28
#define umath_mathcode
Definition: mathcodes.h:29
#define no_mathcode
Definition: mathcodes.h:27
#define umathnum_mathcode
Definition: mathcodes.h:30
scaled get_math_quad_style(int var)
Definition: mlist.c:292
void initialize_math_spacing(void)
Definition: mlist.c:4081
void run_mlist_to_hlist(halfword p, boolean penalties, int mstyle)
Definition: mlist.c:1856
void fixup_math_parameters(int fam_id, int size_id, int f, int lvl)
Definition: mlist.c:478
#define cur_list
Definition: nesting.h:54
halfword pre_adjust_tail
Definition: packaging.c:265
@ additional
Definition: packaging.h:28
@ exactly
Definition: packaging.h:27
#define abs(a)
Definition: pbmplus.h:225
#define print(s)
Definition: pbmtoln03.c:48
char quarterword
Definition: pbmtopk.c:39
scaled round_xn_over_d(scaled x, int n, unsigned int d)
Definition: pdfgen.c:718
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst st
static void scan_int(unsigned)
Definition: pl-lexer.c:3405
int r
Definition: ppmqvga.c:68
void print_qhex(int n)
Definition: printing.c:711
void tprint(const char *sss)
Definition: printing.c:415
void tprint_esc(const char *s)
Definition: printing.c:624
void print_font_identifier(internal_font_number f)
Definition: printing.c:959
static avl_node * new_node(void *item, avl_node *up, mp_avl_tree t)
Definition: avl.c:147
@ math_given_cmd
Definition: commands.h:156
@ spacer_cmd
Definition: commands.h:77
@ set_math_param_cmd
Definition: commands.h:182
@ math_char_num_cmd
Definition: commands.h:90
@ math_shift_cmd
Definition: commands.h:68
@ math_style_cmd
Definition: commands.h:129
@ math_shift_cs_cmd
Definition: commands.h:150
@ sup_mark_cmd
Definition: commands.h:73
@ letter_cmd
Definition: commands.h:78
@ char_num_cmd
Definition: commands.h:89
@ def_family_cmd
Definition: commands.h:181
@ other_char_cmd
Definition: commands.h:79
@ delim_num_cmd
Definition: commands.h:86
@ xmath_given_cmd
Definition: commands.h:157
@ char_given_cmd
Definition: commands.h:154
@ accent_cmd
Definition: commands.h:121
@ sub_mark_cmd
Definition: commands.h:74
@ atop_code
Definition: commands.h:241
@ above_code
Definition: commands.h:239
@ over_code
Definition: commands.h:240
@ delimited_code
Definition: commands.h:243
@ skewed_code
Definition: commands.h:242
static char no[99]
Definition: scanid.c:41
RETTYPE mp_ptr mp_size_t mp_srcptr dp
Definition: sec_div.c:70
#define append_char(A)
Definition: stringpool.h:84
int class_value
Definition: mathcodes.h:51
int large_character_value
Definition: mathcodes.h:55
int large_family_value
Definition: mathcodes.h:54
int small_family_value
Definition: mathcodes.h:52
int small_character_value
Definition: mathcodes.h:53
Definition: ttf.h:354
int character_value
Definition: mathcodes.h:35
int class_value
Definition: mathcodes.h:33
int family_value
Definition: mathcodes.h:34
sa_stack_item * stack
Definition: managed-sa.h:78
Definition: stemdb.c:56
Definition: dvips.h:235
m
Definition: tex4ht.c:3990
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
void math_left_brace(void)
Definition: texmath.c:975
static void resume_after_display(void)
Definition: texmath.c:2239
static void check_display_math_end(void)
Definition: texmath.c:2217
#define get_next_nb_nr()
Definition: texmath.c:1319
void enter_display_math(void)
Definition: texmath.c:1024
void close_math_group(pointer p)
Definition: texmath.c:2010
void setup_math_style(void)
Definition: texmath.c:2712
const char * math_style_names[]
Definition: texmath.c:447
void undump_math_data(void)
Definition: texmath.c:324
#define inject_display_skip_after(g)
Definition: texmath.c:2298
void def_fam_fnt(int fam_id, int size_id, int f, int lvl)
Definition: texmath.c:187
void math_char_in_text(mathcodeval mval)
Definition: texmath.c:1464
void math_limit_switch(void)
Definition: texmath.c:1493
void def_math_param(int param_id, int style_id, scaled value, int lvl)
Definition: texmath.c:244
static void print_subsidiary_data(pointer p, ASCII_code c)
Definition: texmath.c:640
static void unsave_math_fam_data(int gl)
Definition: texmath.c:207
static void unsave_math(void)
Definition: texmath.c:149
#define back_error(A, B)
Definition: texmath.c:41
static void push_math(group_code c, int mstyle)
Definition: texmath.c:890
#define MATHFONTSTACK
Definition: texmath.c:176
static pointer new_choice(void)
Definition: texmath.c:511
void flush_math(void)
Definition: texmath.c:165
void initialize_math(void)
Definition: texmath.c:330
pointer math_vcenter_group(pointer p)
Definition: texmath.c:1752
mathcodeval scan_mathchar(int extcode)
Definition: texmath.c:1206
void math_radical(void)
Definition: texmath.c:1580
#define inject_display_skip_before(g)
Definition: texmath.c:2274
static sa_tree math_fam_head
Definition: texmath.c:179
const char * math_param_names[]
Definition: texmath.c:455
void math_left_right(void)
Definition: texmath.c:2097
#define head
Definition: texmath.c:24
void finish_display_alignment(pointer p, pointer q, halfword saved_prevdepth)
Definition: texmath.c:2690
scaled get_math_param(int param_id, int style_id)
Definition: texmath.c:263
void dump_math_data(void)
Definition: texmath.c:309
static void new_save_level_math(group_code c)
Definition: texmath.c:879
void display_fence_noad(pointer p)
Definition: texmath.c:832
void start_eq_no(void)
Definition: texmath.c:950
#define MATHPARAMDEFAULT
Definition: texmath.c:240
static delcodeval do_scan_extdef_del_code(int extcode, boolean doclass)
Definition: texmath.c:1113
void build_choices(void)
Definition: texmath.c:1779
pointer new_sub_box(pointer curbox)
Definition: texmath.c:402
int scan_math(pointer, int)
Definition: texmath.c:1332
void math_fraction(void)
Definition: texmath.c:1880
static boolean math_and_text_reversed_p(void)
Definition: texmath.c:999
#define MATHPARAMSTACK
Definition: texmath.c:239
void append_choices(void)
Definition: texmath.c:1770
void set_math_char(mathcodeval mval)
Definition: texmath.c:1427
static void scan_delimiter(pointer p, int r)
Definition: texmath.c:1520
static void print_delimiter(pointer p)
Definition: texmath.c:587
void math_ac(void)
Definition: texmath.c:1657
void print_math_style(void)
Definition: texmath.c:2721
static sa_tree math_param_head
Definition: texmath.c:242
void math_math_comp(void)
Definition: texmath.c:1480
static void finish_displayed_math(boolean l, pointer eqno_box, pointer p)
Definition: texmath.c:2322
void init_math(void)
Definition: texmath.c:919
int scan_math_style(pointer, int)
Definition: texmath.c:1321
#define MATHFONTDEFAULT
Definition: texmath.c:177
static void print_fam_and_char(pointer p)
Definition: texmath.c:579
void display_fraction_noad(pointer p)
Definition: texmath.c:843
static void check_second_math_shift(void)
Definition: texmath.c:2204
static void enter_ordinary_math(void)
Definition: texmath.c:901
pointer new_noad(void)
Definition: texmath.c:394
#define math_class_to_type(target, source)
Definition: texmath.c:1416
static void check_inline_math_end(void)
Definition: texmath.c:2228
int fam_fnt(int fam_id, int size_id)
Definition: texmath.c:181
void show_math_node(pointer p)
Definition: texmath.c:539
void display_normal_noad(pointer p)
Definition: texmath.c:674
void scan_extdef_del_code(int level, int extcode)
Definition: texmath.c:1194
void sub_sup(void)
Definition: texmath.c:1859
void no_sub_sup(void)
Definition: texmath.c:1864
void unsave_math_data(int gl)
Definition: texmath.c:301
pointer new_style(small_number s)
Definition: texmath.c:497
#define tail
Definition: texmath.c:23
static void unsave_math_param_data(int gl)
Definition: texmath.c:269
void after_math(void)
Definition: texmath.c:2538
void scan_extdef_math_code(int level, int extcode)
Definition: texmath.c:1284
mathcodeval scan_delimiter_as_mathchar(int extcode)
Definition: texmath.c:1297
#define mode
Definition: texmath.c:22
pointer fin_mlist(pointer)
Definition: texmath.c:1972
static void do_sub_sup(int no)
Definition: texmath.c:1815
#define sup_sup_style(A)
Definition: texmath.h:88
#define m_style
Definition: texmath.h:98
#define dir_math_save
Definition: texmath.h:97
#define scripts_allowed(A)
Definition: texmath.h:37
halfword make_local_par_node(int mode)
Definition: texnodes.c:4801
void delete_attribute_ref(halfword b)
Definition: texnodes.c:3211
void flush_node(halfword p)
Definition: texnodes.c:2321
pointer actual_box_width(pointer r, scaled base_width)
Definition: texnodes.c:4272
halfword new_char(int f, int c)
Definition: texnodes.c:4475
void build_attribute_list(halfword b)
Definition: texnodes.c:3165
memory_word *volatile varmem
Definition: texnodes.c:38
#define vinfo(a)
Definition: texnodes.h:46
#define delimitersamesize(a)
Definition: texnodes.h:583
#define degree(a)
Definition: texnodes.h:668
@ equation_number_list
Definition: texnodes.h:258
@ equation_list
Definition: texnodes.h:257
#define math_list(a)
Definition: texnodes.h:692
@ after
Definition: texnodes.h:374
#define delimiterclass(a)
Definition: texnodes.h:582
#define delimiterheight(a)
Definition: texnodes.h:578
@ noad_option_no_super_script
Definition: texnodes.h:598
@ noad_option_exact
Definition: texnodes.h:593
@ noad_option_left
Definition: texnodes.h:594
@ noad_option_no_axis
Definition: texnodes.h:592
@ noad_option_right
Definition: texnodes.h:596
@ noad_option_no_sub_script
Definition: texnodes.h:597
@ noad_option_no_rule
Definition: texnodes.h:600
@ noad_option_middle
Definition: texnodes.h:595
@ noad_option_axis
Definition: texnodes.h:591
@ sfi
Definition: texnodes.h:1106
@ fil
Definition: texnodes.h:1107
@ filll
Definition: texnodes.h:1109
#define try_couple_nodes(a, b)
Definition: texnodes.h:1005
@ op_noad_type_normal
Definition: texnodes.h:544
@ close_noad_type
Definition: texnodes.h:550
@ op_noad_type_limits
Definition: texnodes.h:545
@ under_noad_type
Definition: texnodes.h:553
@ over_noad_type
Definition: texnodes.h:554
@ punct_noad_type
Definition: texnodes.h:551
@ inner_noad_type
Definition: texnodes.h:552
@ rel_noad_type
Definition: texnodes.h:548
@ op_noad_type_no_limits
Definition: texnodes.h:546
@ ord_noad_type
Definition: texnodes.h:543
@ vcenter_noad_type
Definition: texnodes.h:555
@ open_noad_type
Definition: texnodes.h:549
@ bin_noad_type
Definition: texnodes.h:547
#define math_character(a)
Definition: texnodes.h:691
#define overlay_accent_chr(a)
Definition: texnodes.h:563
#define delimiternoaxis(a)
Definition: texnodes.h:605
@ before_display_penalty
Definition: texnodes.h:146
@ after_display_penalty
Definition: texnodes.h:147
@ equation_number_penalty
Definition: texnodes.h:148
#define noadoptions(a)
Definition: texnodes.h:536
#define delimiterdepth(a)
Definition: texnodes.h:579
#define math_fam(a)
Definition: texnodes.h:690
#define radicaloptionset(a)
Definition: texnodes.h:671
#define delimiteritalic(a)
Definition: texnodes.h:576
@ cancel_dir
Definition: texnodes.h:817
#define accentfraction(a)
Definition: texnodes.h:564
#define vlink(a)
Definition: texnodes.h:47
#define radicalwidth(a)
Definition: texnodes.h:667
#define surround(a)
Definition: texnodes.h:385
#define fractionoptions(a)
Definition: texnodes.h:655
#define delimiterexact(a)
Definition: texnodes.h:606
#define radicalleft(a)
Definition: texnodes.h:673
#define radicaloptions(a)
Definition: texnodes.h:669
#define alink(a)
Definition: texnodes.h:51
#define glue_is_zero(p)
Definition: texnodes.h:171
#define copy_glue_values(p, q)
Definition: texnodes.h:186
@ style_node
Definition: texnodes.h:417
@ radical_noad
Definition: texnodes.h:420
@ local_par_node
Definition: texnodes.h:409
@ math_char_node
Definition: texnodes.h:424
@ delim_node
Definition: texnodes.h:428
@ simple_noad
Definition: texnodes.h:419
@ fraction_noad
Definition: texnodes.h:421
@ accent_noad
Definition: texnodes.h:422
@ sub_mlist_node
Definition: texnodes.h:426
@ glue_node
Definition: texnodes.h:413
@ choice_node
Definition: texnodes.h:418
@ fence_noad
Definition: texnodes.h:423
@ sub_box_node
Definition: texnodes.h:425
#define top_accent_chr(a)
Definition: texnodes.h:561
#define delimiteroptions(a)
Definition: texnodes.h:581
#define middle_delimiter(a)
Definition: texnodes.h:654
#define delimiteroptionset(a)
Definition: texnodes.h:603
@ left_noad_side
Definition: texnodes.h:640
@ right_noad_side
Definition: texnodes.h:642
@ no_noad_side
Definition: texnodes.h:643
@ middle_noad_side
Definition: texnodes.h:641
#define delimiteraxis(a)
Definition: texnodes.h:604
#define radicalright(a)
Definition: texnodes.h:675
#define radicalexact(a)
Definition: texnodes.h:672
#define pre_adjust_head
Definition: texnodes.h:1125
#define node_attr(a)
Definition: texnodes.h:50
#define bot_accent_chr(a)
Definition: texnodes.h:562
#define radicalmiddle(a)
Definition: texnodes.h:674
halfword active_to_cs(int curchr, int force)
Definition: textoken.c:637
integer cint
Definition: aptex.h:236
Definition: obx.h:51
long long scaled
Definition: vf_ng.c:93
#define return(val)