1use crate::Engine;
11use crate::cmd::Cmd;
12use crate::glue::Glue;
13use crate::nodes::glue_sub;
14use crate::primitives_gen::{assign_glue as gp, assign_int as ip};
15
16#[inline]
18fn is_zero(g: &Glue) -> bool {
19 g.width == 0 && g.stretch == 0 && g.shrink == 0
20}
21
22impl Engine {
23 pub fn main_loop_char(&mut self) {
27 let tracing = self.eqtb.int(ip::TRACINGCOMMANDS) > 0;
28 loop {
29 self.append_char(self.cur_chr);
30 if tracing {
31 self.get_x_token();
33 return;
34 }
35 self.get_next();
36 if matches!(self.cur_cmd, Cmd::Letter | Cmd::OtherChar | Cmd::CharGiven) {
37 continue;
38 }
39 self.exec_context = true;
42 self.x_token();
43 self.exec_context = false;
44 match self.cur_cmd {
45 Cmd::Letter | Cmd::OtherChar | Cmd::CharGiven => continue,
46 Cmd::CharNum => {
47 self.scan_char_num();
48 self.cur_chr = self.cur_val as u32;
49 continue;
50 }
51 _ => return,
52 }
53 }
54 }
55
56 #[inline]
59 fn append_char(&mut self, c: u32) {
60 let s = self.eqtb.sf.get(c) as i32;
61 let cl = self.cur_list_mut();
62 if s == 1000 {
63 cl.space_factor = 1000;
64 } else if s < 1000 {
65 if s > 0 {
66 cl.space_factor = s;
67 }
68 } else if cl.space_factor < 1000 {
69 cl.space_factor = 1000;
70 } else {
71 cl.space_factor = s;
72 }
73 let f = self.eqtb.cur_font.val;
74 let g = self.new_char_node(f, c);
75 self.tail_append(g);
76 }
77
78 fn font_glue(&self, f: u32) -> Glue {
80 let p = &self.font(f).params;
81 Glue {
82 width: p.get(2).copied().unwrap_or(0),
83 stretch: p.get(3).copied().unwrap_or(0),
84 shrink: p.get(4).copied().unwrap_or(0),
85 ..Glue::ZERO
86 }
87 }
88
89 pub fn app_space_main(&mut self) {
91 if self.cur_list().space_factor == 1000 {
92 self.append_normal_space();
93 } else {
94 self.app_space();
95 }
96 }
97
98 pub fn app_explicit_space(&mut self) {
100 self.append_normal_space();
101 }
102
103 pub(crate) fn append_normal_space(&mut self) {
105 let ss = self.eqtb.glue(gp::SPACESKIP);
106 let g = if is_zero(&ss) {
107 self.font_glue(self.eqtb.cur_font.val)
108 } else {
109 ss
110 };
111 let p = self.new_glue_node(g, glue_sub::SPACE_SKIP);
112 self.tail_append(p);
113 }
114
115 fn app_space(&mut self) {
117 let sf = self.cur_list().space_factor;
118 let xs = self.eqtb.glue(gp::XSPACESKIP);
119 let p = if sf >= 2000 && !is_zero(&xs) {
120 self.new_glue_node(xs, glue_sub::XSPACE_SKIP)
121 } else {
122 let ss = self.eqtb.glue(gp::SPACESKIP);
123 let f = self.eqtb.cur_font.val;
124 let mut g = if is_zero(&ss) { self.font_glue(f) } else { ss };
125 if sf >= 2000 {
126 g.width += self.font(f).params.get(7).copied().unwrap_or(0);
127 }
128 g.stretch = retex_arith::xn_over_d(g.stretch, sf, 1000)
129 .map(|r| r.quotient)
130 .unwrap_or(g.stretch);
131 g.shrink = retex_arith::xn_over_d(g.shrink, 1000, sf)
132 .map(|r| r.quotient)
133 .unwrap_or(g.shrink);
134 self.new_glue_node(g, glue_sub::SPACE_SKIP)
135 };
136 self.tail_append(p);
137 }
138}