texrules.c /size: 10 Kb    last modification: 2024-01-16 10:22
1/*
2    See license.txt in the root of this project.
3*/
4
5# include "luametatex.h"
6
7halfword tex_aux_scan_rule_spec(rule_types type, halfword code)
8{
9    /*tex |width|, |depth|, and |height| all equal |null_flag| now */
10    halfword rule = tex_new_rule_node((quarterword) code);
11    halfword attr = node_attr(rule);
12    switch (type) {
13        case h_rule_type:
14            rule_height(rule) = default_rule;
15            rule_depth(rule) = 0;
16            break;
17        case v_rule_type:
18        case m_rule_type:
19            if (code == strut_rule_code) {
20                rule_width(rule) = 0;
21                node_subtype(rule) = strut_rule_subtype;
22            } else {
23                rule_width(rule) = default_rule;
24            }
25            break;
26    }
27    while (1) {
28        /*tex
29            Maybe:
30
31               h : "whdxylrWHDXYLR"
32               v : "whdxytbWHDXYTB"
33               m : "whdxylrtbWHDXYLRTB"
34
35            but for now we are tolerant because internally it's left/right anyway.
36
37        */
38        switch (tex_scan_character("awhdxylrtbcfAWHDXYLRTBCF", 0, 1, 0)) {
39            case 0:
40                goto DONE;
41            case 'a': case 'A':
42                if (tex_scan_mandate_keyword("attr", 1)) {
43                    attr = tex_scan_attribute(attr);
44                }
45                break;
46            case 'w': case 'W':
47                if (tex_scan_mandate_keyword("width", 1)) {
48                    rule_width(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
49                }
50                break;
51            case 'h': case 'H':
52                if (tex_scan_mandate_keyword("height", 1)) {
53                    rule_height(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
54                }
55                break;
56            case 'd': case 'D':
57                if (tex_scan_mandate_keyword("depth", 1)) {
58                    rule_depth(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
59                }
60                break;
61            case 'l': case 'L':
62                if (node_subtype(rule) != virtual_rule_subtype) { 
63                    if (tex_scan_mandate_keyword("left", 1)) {
64                        rule_left(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
65                    }
66                    break;
67                } else {
68                    goto DONE;
69                }
70            case 'r': case 'R':
71                if (node_subtype(rule) != virtual_rule_subtype) { 
72                    if (tex_scan_mandate_keyword("right", 1)) {
73                        rule_right(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
74                    }
75                    break;
76                } else {
77                    goto DONE;
78                }
79            case 't': case 'T': /* just because it's nicer */
80                if (node_subtype(rule) != virtual_rule_subtype) { 
81                    if (tex_scan_mandate_keyword("top", 1)) {
82                        rule_left(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
83                    }
84                    break;
85                } else {
86                    goto DONE;
87                }
88            case 'b': case 'B': /* just because it's nicer */
89                if (node_subtype(rule) != virtual_rule_subtype) { 
90                    if (tex_scan_mandate_keyword("bottom", 1)) {
91                        rule_right(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
92                    }
93                    break;
94                } else {
95                    goto DONE;
96                }
97            case 'x': case 'X':
98                if (tex_scan_mandate_keyword("xoffset", 1)) {
99                    rule_x_offset(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
100                }
101                break;
102            case 'y': case 'Y':
103                if (tex_scan_mandate_keyword("yoffset", 1)) {
104                    rule_y_offset(rule) = tex_scan_dimension(0, 0, 0, 0, NULL);
105                }
106                break;
107            case 'f': case 'F':
108                if (node_subtype(rule) != virtual_rule_subtype) { 
109                    switch (tex_scan_character("aoAO", 0, 0, 0)) {
110                        case 'o': case 'O':
111                            if (tex_scan_mandate_keyword("font", 2)) {
112                                tex_set_rule_font(rule, tex_scan_font_identifier(NULL));
113                            }
114                            break;
115                        case 'a': case 'A':
116                            if (tex_scan_mandate_keyword("fam", 2)) {
117                                tex_set_rule_family(rule, tex_scan_math_family_number());
118                            }
119                            break;
120                        default:
121                            tex_aux_show_keyword_error("font|fam");
122                            goto DONE;
123                    }
124                    break;
125                } else { 
126                    goto DONE;
127                }
128            case 'c': case 'C':
129                if (node_subtype(rule) != virtual_rule_subtype) { 
130                    if (tex_scan_mandate_keyword("char", 1)) {
131                        rule_strut_character(rule) = tex_scan_char_number(0);
132                    }
133                    break;
134                } else { 
135                    goto DONE;
136                }
137            default:
138                goto DONE;
139        }
140    }
141  DONE:
142    if (! attr) {
143        /* Also bumps reference and replaces the one set. */
144        tex_attach_attribute_list_attribute(rule, attr);
145    }    
146    switch (code) {
147        case strut_rule_code:
148            if (type == v_rule_type) {
149                tex_aux_check_text_strut_rule(rule, text_style);
150            }
151            break;
152        case virtual_rule_code:
153            rule_virtual_width(rule) = rule_width(rule);
154            rule_virtual_height(rule) = rule_height(rule);
155            rule_virtual_depth(rule) = rule_depth(rule);
156            rule_width(rule) = 0;
157            rule_height(rule) = 0;
158            rule_depth(rule) = 0;
159            node_subtype(rule) = virtual_rule_subtype;
160            break;
161    }
162    return rule;
163}
164
165void tex_aux_run_vrule(void)
166{
167    tex_tail_append(tex_aux_scan_rule_spec(v_rule_type, cur_chr));
168    cur_list.space_factor = default_space_factor;
169}
170
171void tex_aux_run_hrule(void)
172{
173    tex_tail_append(tex_aux_scan_rule_spec(h_rule_type, cur_chr));
174    cur_list.prev_depth = ignore_depth_criterion_par;
175}
176
177void tex_aux_run_mrule(void)
178{
179    tex_tail_append(tex_aux_scan_rule_spec(m_rule_type, cur_chr));
180}
181
182void tex_aux_check_math_strut_rule(halfword rule, halfword style)
183{
184    if (node_subtype(rule) == strut_rule_subtype) {
185        scaled ht = rule_height(rule);
186        scaled dp = rule_depth(rule);
187        if (ht == null_flag || dp == null_flag) {
188            halfword fnt = tex_get_rule_font(rule, style);
189            halfword chr = rule_strut_character(rule);
190            if (fnt > 0 && chr && tex_char_exists(fnt, chr)) {
191                if (ht == null_flag) {
192                    ht = tex_math_font_char_ht(fnt, chr, style);
193                }
194                if (dp == null_flag) {
195                    dp = tex_math_font_char_dp(fnt, chr, style);
196                }
197            } else {
198                if (ht == null_flag) {
199                    ht = tex_get_math_y_parameter(style, math_parameter_rule_height);
200                }
201                if (dp == null_flag) {
202                    dp = tex_get_math_y_parameter(style, math_parameter_rule_depth);
203                }
204            }
205            rule_height(rule) = ht;
206            rule_depth(rule) = dp;
207        }
208    }
209}
210
211void tex_aux_check_text_strut_rule(halfword rule, halfword style)
212{
213    if (node_subtype(rule) == strut_rule_subtype) {
214        scaled ht = rule_height(rule);
215        scaled dp = rule_depth(rule);
216        if (ht == null_flag || dp == null_flag) {
217            halfword fnt = tex_get_rule_font(rule, style);
218            halfword chr = rule_strut_character(rule);
219            if (fnt > 0 && chr && tex_char_exists(fnt, chr)) {
220                scaledwhd whd = tex_char_whd_from_font(fnt, chr);
221                if (ht == null_flag) {
222                    rule_height(rule) = whd.ht;
223                }
224                if (dp == null_flag) {
225                    rule_depth(rule) = whd.dp;
226                }
227            }
228        }
229    }
230}
231
232halfword tex_get_rule_font(halfword n, halfword style)
233{
234    if (node_subtype(n) != virtual_rule_subtype) {
235        halfword fnt = rule_strut_font(n);
236        if (fnt >= rule_font_fam_offset) {
237            halfword fam = fnt - rule_font_fam_offset;
238            if (fam_par_in_range(fam)) {
239                fnt = tex_fam_fnt(fam, tex_size_of_style(style));
240            }
241       }
242        if (fnt < 0 || fnt >= max_n_of_fonts) {
243            return null_font;
244        } else {
245            return fnt;
246        }
247    } else { 
248        return null_font;
249    }
250}
251
252halfword tex_get_rule_family(halfword n)
253{
254    if (node_subtype(n) != virtual_rule_subtype) {
255        halfword fnt = rule_strut_font(n);
256        if (fnt >= rule_font_fam_offset) {
257            halfword fam = fnt - rule_font_fam_offset;
258            if (fam_par_in_range(fam)) {
259                return fam;
260            }
261        }
262    }
263    return 0;
264}
265
266void tex_set_rule_font(halfword n, halfword fnt)
267{
268    if (node_subtype(n) != virtual_rule_subtype) {
269        if (fnt < 0 || fnt >= rule_font_fam_offset) {
270            rule_strut_font(n) = 0;
271        } else {
272            rule_strut_font(n) = fnt;
273        }
274    }
275}
276
277void tex_set_rule_family(halfword n, halfword fam)
278{
279    if (node_subtype(n) != virtual_rule_subtype) {
280        if (fam < 0 || fam >= max_n_of_math_families) {
281            rule_strut_font(n) = rule_font_fam_offset;
282        } else {
283            rule_strut_font(n) = rule_font_fam_offset + fam;
284        }
285    }
286}
287
288halfword tex_get_rule_left(halfword n)
289{
290    return node_subtype(n) == virtual_rule_subtype ? 0 : rule_left(n); 
291}
292
293halfword tex_get_rule_right(halfword n)
294{
295    return node_subtype(n) == virtual_rule_subtype ? 0 : rule_right(n); 
296}
297
298void tex_set_rule_left(halfword n, halfword value)
299{
300    if (node_subtype(n) != virtual_rule_subtype) {
301        rule_left(n) = value; 
302    }
303}
304
305void tex_set_rule_right(halfword n, halfword value)
306{
307    if (node_subtype(n) != virtual_rule_subtype) {
308        rule_right(n) = value; 
309    }
310}
311
312