1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
/*
See license.txt in the root of this project.
*/
# ifndef LMT_PACKAGING_H
# define LMT_PACKAGING_H
# include "luametatex.h"
/* We define some constants used when calling |hpack| to deal with font expansion. */
typedef enum hpack_subtypes {
packing_exactly, /*tex a box dimension is pre-specified */
packing_additional, /*tex a box dimension is increased from the natural one */
packing_expanded, /*tex calculate amount for font expansion after breaking paragraph into lines */
packing_substitute, /*tex substitute fonts */
packing_adapted,
packing_linebreak, /*tex signals that we need to take the frozen adjust properties */
} hpack_subtypes;
typedef enum box_codes {
box_code, /*tex |chr_code| for |\box| */
copy_code, /*tex |chr_code| for |\copy| */
unpack_code,
last_box_code, /*tex |chr_code| for |\lastbox| */
vsplit_code, /*tex |chr_code| for |\vsplit| */
tpack_code,
vpack_code,
hpack_code,
dpack_code,
vtop_code, /*tex |chr_code| for |\vtop| */
vbox_code,
hbox_code,
dbox_code,
insert_box_code,
insert_copy_code,
local_left_box_box_code,
local_right_box_box_code,
local_middle_box_box_code
} box_codes;
// typedef enum saved_spec_items {
// saved_spec_item_packaging = 0,
// saved_spec_item_attribute = 1,
// saved_spec_n_of_items = 2,
// } saved_spec_items;
typedef enum saved_full_spec_items {
saved_full_spec_item_context = 0,
saved_full_spec_item_packaging = 1,
saved_full_spec_item_direction = 2,
saved_full_spec_item_attr_list = 3,
saved_full_spec_item_only_pack = 4,
saved_full_spec_item_orientation = 5,
saved_full_spec_item_anchor = 6,
saved_full_spec_item_geometry = 7,
saved_full_spec_item_xoffset = 8,
saved_full_spec_item_yoffset = 9,
saved_full_spec_item_xmove = 10,
saved_full_spec_item_ymove = 11,
saved_full_spec_item_reverse = 12,
saved_full_spec_item_container = 13,
saved_full_spec_item_shift = 14, /* cleaner than passing it as context */
saved_full_spec_item_source = 15,
saved_full_spec_item_target = 16,
saved_full_spec_item_axis = 17,
saved_full_spec_item_class = 18,
saved_full_spec_item_state = 19,
saved_full_spec_item_retain = 20,
saved_full_spec_n_of_items = 21,
} saved_full_spec_items;
// typedef enum saved_align_spec_items {
// saved_align_spec_item_attr_list = 0,
// saved_align_spec_item_orientation = 1,
// saved_align_spec_item_anchor = 2,
// saved_align_spec_item_geometry = 3,
// saved_align_spec_item_xoffset = 4,
// saved_align_spec_item_yoffset = 5,
// saved_align_spec_item_shift = 6,
// saved_align_spec_item_source = 7,
// saved_align_spec_item_target = 8,
// saved_align_spec_n_of_items = 9,
// } saved_align_spec_items;
typedef enum holding_migration_options {
holding_none_option = 0x00,
holding_marks_option = 0x01,
holding_inserts_option = 0x02,
holding_adjusts_option = 0x04,
} holding_migration_options ;
# define retain_marks(r) (((r | holding_migrations_par) & holding_marks_option ) == holding_marks_option )
# define retain_inserts(r) (((r | holding_migrations_par) & holding_inserts_option) == holding_inserts_option)
# define retain_adjusts(r) (((r | holding_migrations_par) & holding_adjusts_option) == holding_adjusts_option)
typedef struct packaging_state_info {
scaled total_stretch[6]; /*tex with one for padding, the results are also used in alignments */
scaled total_shrink[6]; /*tex glue found by |hpack| or |vpack|, the results are also used in alignments */
int last_badness; /*tex badness of the most recently packaged box */
scaled last_overshoot;
halfword post_adjust_tail; /*tex tail of adjustment list */
halfword pre_adjust_tail;
halfword post_migrate_tail; /*tex tail of adjustment list */
halfword pre_migrate_tail;
halfword last_leftmost_char;
halfword last_rightmost_char;
int pack_begin_line;
scaled best_height_plus_depth; /*tex The height of the best box, without stretching or shrinking: */
halfword previous_char_ptr;
scaled font_expansion_ratio;
halfword page_discards_tail;
halfword page_discards_head;
halfword split_discards_head;
halfword padding;
} packaging_state_info;
extern packaging_state_info lmt_packaging_state;
extern scaled tex_char_stretch (halfword p);
extern scaled tex_char_shrink (halfword p);
/* void tex_get_char_expansion (halfword p, halfword *stretch, halfword *shrink); */ /* no gain */
extern scaled tex_kern_stretch (halfword p);
extern scaled tex_kern_shrink (halfword p);
extern scaled tex_char_protrusion (halfword p, int side);
/* void tex_kern_protrusion (halfword p, int side, halfword *stretch, halfword *shrink); */
extern scaled tex_left_marginkern (halfword p);
extern scaled tex_right_marginkern (halfword p);
extern halfword tex_filtered_hpack (halfword p, halfword qt, scaled w, int m, int grp, halfword d, int just_pack, halfword attr, int state, int retain);
extern halfword tex_filtered_vpack (halfword p, scaled h, int m, scaled maxdepth, int grp, halfword direction, int just_pack, halfword attr, int state, int retain);
extern scaledwhd tex_natural_hsizes (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern scaledwhd tex_natural_vsizes (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern halfword tex_natural_width (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern halfword tex_natural_hsize (halfword p, halfword *correction);
extern halfword tex_natural_vsize (halfword p);
extern halfword tex_hpack (halfword p, scaled w, int m, singleword d, int retain);
extern halfword tex_vpack (halfword p, scaled h, int m, scaled l, singleword d, int retain);
extern void tex_repack (halfword p, scaled w, int m);
extern void tex_freeze (halfword p, int recurse);
extern void tex_package (singleword nature);
extern void tex_run_unpackage (void);
extern void tex_append_to_vlist (halfword b, int location, const line_break_properties *properties);
extern halfword tex_prune_page_top (halfword p, int s);
extern halfword tex_vert_break (halfword p, scaled h, scaled d);
extern halfword tex_vsplit (halfword n, scaled h, int m);
extern void tex_finish_vcenter_group (void);
extern void tex_run_vcenter (void);
//# define vpack(A,B,C,D) tex_vpackage(A,B,C,max_dimen,D)
# define first_un_box_code box_code
# define last_un_box_code unpack_code
# define first_nu_box_code box_code
# define last_nu_box_code local_middle_box_box_code /*tex needs checking */
/*tex
Now let's turn to the question of how |\hbox| is treated. We actually need to consider also a
slightly larger context, since constructions like
\starttyping
\setbox3={\\hbox...
\leaders\hbox...
\lower3.8pt\hbox...
\stoptyping
are supposed to invoke quite different actions after the box has been packaged. Conversely,
constructions like |\setbox 3 =| can be followed by a variety of different kinds of boxes, and
we would like to encode such things in an efficient way.
In other words, there are two problems: To represent the context of a box, and to represent its
type. The first problem is solved by putting a \quote {context code} on the |save_stack|, just
below the two entries that give the dimensions produced by |scan_spec|. The context code is
either a (signed) shift amount, or it is a large integer |>= box_flag|, where |box_flag = |
$2^{30}$. Codes |box_flag| through |box_flag + biggest_reg| represent |\setbox0| through
|\setbox biggest_reg|; codes |box_flag + biggest_reg + 1| through |box_flag + 2 * biggest_reg|
represent |\global \setbox 0| through |\global\setbox| |biggest_reg|; code |box_flag + 2 *
number_regs| represents |\shipout|; and codes |box_flag + 2 * number_regs + 1| through |box_flag
+ 2 * number_regs + 3| represent |\leaders|, |\cleaders|, and |\xleaders|.
The second problem is solved by giving the command code |make_box| to all control sequences that
produce a box, and by using the following |chr_code| values to distinguish between them:
|box_code|, |copy_code|, |last_box_code|, |vsplit_code|, |vtop_code|, |vtop_code + vmode|, and
|vtop_code + hmode|, where the latter two are used denote |\vbox| and |\hbox|, respectively.
Originally the shift was encoded in the box context in case of a move. In fact even the local
and global register assignments were in that property but this is no longer the case. This
actually makes implementing a |\boxspecdef| cleaner (a discarded experiment). The intermediate
cleasned up flags can be found in the history.
*/
# define biggest_reg 65535 /*tex This could be in |textypes.h|. */
typedef enum box_flags {
direct_box_flag = 0x00,
/* moved_box_flag = 0x01, */
/* vcenter_box_flag = 0x02, */
box_flag = 0x02, /*tex context code for |\setbox0| */
global_box_flag = 0x03, /*tex context code for |\global\setbox0| */
left_box_flag = 0x04, /*tex context code for |\localleftbox| */
right_box_flag = 0x05, /*tex context code for |\localrightbox| */
middle_box_flag = 0x06, /*tex context code for |\localrightbox| */
shipout_flag = 0x07, /*tex context code for |\shipout| */
lua_scan_flag = 0x08, /*tex context code for |scan_list| */
a_leaders_flag = 0x09, /*tex context code for |\leaders| */
c_leaders_flag = 0x0A, /*tex context code for |\cleaders| */
x_leaders_flag = 0x0B, /*tex context code for |\xleaders| */
g_leaders_flag = 0x0C, /*tex context code for |\gleaders| */
u_leaders_flag = 0x0D, /*tex context code for |\uleaders| */
} box_flags;
# define box_leaders_flag(f) (f >= a_leaders_flag && f <= u_leaders_flag)
extern void tex_begin_box (int boxcontext, scaled shift, halfword slot);
extern int tex_ignore_math_skip (halfword p);
inline static scaled tex_aux_checked_dimen1(halfword v)
{
if (v > max_dimen) {
return max_dimen;
} else if (v < -max_dimen) {
return -max_dimen;
} else {
return v;
}
}
inline static scaled tex_aux_checked_dimen2(halfword v)
{
if (v > max_dimen) {
return max_dimen;
} else if (v < 0) {
return 0;
} else {
return v;
}
}
# endif
|