summaryrefslogtreecommitdiff
path: root/source/luametatex
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex')
-rw-r--r--source/luametatex/source/lua/lmtnodelib.c18
-rw-r--r--source/luametatex/source/lua/lmttexlib.c21
-rw-r--r--source/luametatex/source/luametatex.h2
-rw-r--r--source/luametatex/source/tex/texcommands.c1
-rw-r--r--source/luametatex/source/tex/texequivalents.h2
-rw-r--r--source/luametatex/source/tex/texlinebreak.c146
-rw-r--r--source/luametatex/source/tex/texmath.c2
-rw-r--r--source/luametatex/source/tex/texmlist.c38
-rw-r--r--source/luametatex/source/tex/texnodes.h16
-rw-r--r--source/luametatex/source/tex/texpackaging.c2
10 files changed, 205 insertions, 43 deletions
diff --git a/source/luametatex/source/lua/lmtnodelib.c b/source/luametatex/source/lua/lmtnodelib.c
index 58c3bb0a7..66cf528fc 100644
--- a/source/luametatex/source/lua/lmtnodelib.c
+++ b/source/luametatex/source/lua/lmtnodelib.c
@@ -2647,6 +2647,15 @@ static int nodelib_direct_getoptions(lua_State *L)
case disc_node:
lua_pushinteger(L, disc_options(n));
return 1;
+ case glue_node:
+ lua_pushinteger(L, glue_options(n));
+ return 1;
+ case math_node:
+ lua_pushinteger(L, math_options(n));
+ return 1;
+ case penalty_node:
+ lua_pushinteger(L, penalty_options(n));
+ return 1;
case simple_noad:
case radical_noad:
case fraction_noad:
@@ -2674,6 +2683,15 @@ static int nodelib_direct_setoptions(lua_State *L)
case disc_node:
set_disc_options(n, lmt_tohalfword(L, 2));
break;
+ case glue_node:
+ tex_add_glue_option(n, lmt_tohalfword(L, 2));
+ return 1;
+ case math_node:
+ tex_add_math_option(n, lmt_tohalfword(L, 2));
+ return 1;
+ case penalty_node:
+ tex_add_penalty_option(n, lmt_tohalfword(L, 2));
+ return 1;
case simple_noad:
case radical_noad:
case fraction_noad:
diff --git a/source/luametatex/source/lua/lmttexlib.c b/source/luametatex/source/lua/lmttexlib.c
index 1bfd2c38c..4f2ecbb5c 100644
--- a/source/luametatex/source/lua/lmttexlib.c
+++ b/source/luametatex/source/lua/lmttexlib.c
@@ -5015,6 +5015,24 @@ static int texlib_getglyphoptionvalues(lua_State *L)
return 1;
}
+static int texlib_getglueoptionvalues(lua_State *L)
+{
+ lua_createtable(L, 3, 0);
+ lua_set_string_by_index(L, glue_option_normal, "normal");
+ lua_set_string_by_index(L, glue_option_no_auto_break, "noautobreak");
+ lua_set_string_by_index(L, glue_option_short_math, "shortmath");
+ return 1;
+}
+
+static int texlib_getpenaltyoptionvalues(lua_State *L)
+{
+ lua_createtable(L, 3, 0);
+ lua_set_string_by_index(L, penalty_option_normal, "normal");
+ lua_set_string_by_index(L, penalty_option_math_forward, "mathforward");;
+ lua_set_string_by_index(L, penalty_option_math_backward, "mathbackward");
+ return 1;
+}
+
static int texlib_getnoadoptionvalues(lua_State *L)
{
lua_createtable(L, 2, 37);
@@ -5780,6 +5798,9 @@ static const struct luaL_Reg texlib_function_list[] = {
{ "setrunstate", texlib_setrunstate },
{ "gethyphenationvalues", texlib_gethyphenationvalues },
{ "getglyphoptionvalues", texlib_getglyphoptionvalues },
+ { "getglueoptionvalues", texlib_getglueoptionvalues },
+ { "getmathoptionvalues", texlib_getglueoptionvalues },
+ { "getpenaltyoptionvalues", texlib_getpenaltyoptionvalues },
{ "getnoadoptionvalues", texlib_getnoadoptionvalues },
{ "getdiscoptionvalues", texlib_getdiscoptionvalues },
{ "getlistanchorvalues", texlib_getlistanchorvalues },
diff --git a/source/luametatex/source/luametatex.h b/source/luametatex/source/luametatex.h
index d9df0e14c..a6e9b5295 100644
--- a/source/luametatex/source/luametatex.h
+++ b/source/luametatex/source/luametatex.h
@@ -92,7 +92,7 @@
# define luametatex_version 210
# define luametatex_revision 9
# define luametatex_version_string "2.10.09"
-# define luametatex_development_id 20230529
+# define luametatex_development_id 20230530
# define luametatex_name_camelcase "LuaMetaTeX"
# define luametatex_name_lowercase "luametatex"
diff --git a/source/luametatex/source/tex/texcommands.c b/source/luametatex/source/tex/texcommands.c
index 26ae7cef9..1423c80d0 100644
--- a/source/luametatex/source/tex/texcommands.c
+++ b/source/luametatex/source/tex/texcommands.c
@@ -167,6 +167,7 @@ void tex_initialize_commands(void)
tex_primitive(luatex_command, "preinlinepenalty", internal_int_cmd, pre_inline_penalty_code, internal_int_base);
tex_primitive(luatex_command, "postshortinlinepenalty", internal_int_cmd, post_short_inline_penalty_code, internal_int_base);
tex_primitive(luatex_command, "preshortinlinepenalty", internal_int_cmd, pre_short_inline_penalty_code, internal_int_base);
+ tex_primitive(luatex_command, "shortinlineorphanpenalty", internal_int_cmd, short_inline_orphan_penalty_code, internal_int_base);
tex_primitive(tex_command, "pretolerance", internal_int_cmd, pre_tolerance_code, internal_int_base);
tex_primitive(tex_command, "relpenalty", internal_int_cmd, post_relation_penalty_code, internal_int_base); /*tex For old times sake. */
tex_primitive(tex_command, "righthyphenmin", internal_int_cmd, right_hyphen_min_code, internal_int_base);
diff --git a/source/luametatex/source/tex/texequivalents.h b/source/luametatex/source/tex/texequivalents.h
index b129cb047..384a17e06 100644
--- a/source/luametatex/source/tex/texequivalents.h
+++ b/source/luametatex/source/tex/texequivalents.h
@@ -437,6 +437,7 @@ typedef enum int_codes {
post_inline_penalty_code, /*tex penalty for breaking just after an inlined formula */
pre_short_inline_penalty_code, /*tex penalty for breaking just before a single character inlined formula */
post_short_inline_penalty_code, /*tex penalty for breaking just after a single character inlined formula */
+ short_inline_orphan_penalty_code,
inter_line_penalty_code, /*tex additional penalty between lines */
double_hyphen_demerits_code, /*tex demerits for double hyphen break */
final_hyphen_demerits_code, /*tex demerits for final hyphen break */
@@ -1411,6 +1412,7 @@ extern void tex_forced_word_define (int g, halfword p, singleword flag, halfword
# define post_inline_penalty_par count_parameter(post_inline_penalty_code)
# define pre_short_inline_penalty_par count_parameter(pre_short_inline_penalty_code)
# define post_short_inline_penalty_par count_parameter(post_short_inline_penalty_code)
+# define short_inline_orphan_penalty_par count_parameter(short_inline_orphan_penalty_code)
# define local_interline_penalty_par count_parameter(local_interline_penalty_code)
# define local_broken_penalty_par count_parameter(local_broken_penalty_code)
diff --git a/source/luametatex/source/tex/texlinebreak.c b/source/luametatex/source/tex/texlinebreak.c
index 0c2445ffe..93a537ca7 100644
--- a/source/luametatex/source/tex/texlinebreak.c
+++ b/source/luametatex/source/tex/texlinebreak.c
@@ -2051,7 +2051,7 @@ static void tex_aux_try_break(
} else {
demerits = demerits * demerits;
}
- if (penalty != 0) {
+ if (penalty) {
if (penalty > 0) {
demerits += (penalty * penalty);
} else if (penalty > eject_penalty) {
@@ -2198,6 +2198,30 @@ inline static halfword tex_aux_upcoming_penalty(halfword p) {
# define max_prev_graf (max_integer/2)
+static inline int tex_aux_short_math(halfword m) {
+ return m && node_subtype(m) == begin_inline_math && math_penalty(m) > 0 && tex_has_math_option(m, glue_option_short_math);
+}
+
+static inline void tex_aux_adapt_short_math_penalty(halfword m, halfword p1, halfword p2) {
+ if (p1 > math_penalty(m)) {
+ math_penalty(m) = p1;
+ }
+ if (p2 > math_penalty(m)) {
+ math_penalty(m) = p2;
+ }
+}
+
+static inline halfword tex_aux_backtrack_over_math(halfword m)
+{
+ if (node_subtype(m) == end_inline_math) {
+ do {
+ m = node_prev(m);
+ } while (m && node_type(m) != math_node);
+ }
+ return m;
+}
+
+
void tex_do_line_break(line_break_properties *properties)
{
/*tex Miscellaneous nodes of temporary interest. */
@@ -2256,7 +2280,7 @@ void tex_do_line_break(line_break_properties *properties)
also skip a penalty in the list.
*/
- if (properties->orphan_penalties || properties->orphan_penalty) {
+ if (properties->orphan_penalties || properties->orphan_penalty || short_inline_orphan_penalty_par) {
halfword current = node_prev(properties->parfill_right_skip);
if (current) {
/*tex Skip over trailing glue and penalties. */
@@ -2272,37 +2296,119 @@ void tex_do_line_break(line_break_properties *properties)
}
INJECT:
if (properties->orphan_penalties) {
- /*tex Inject specified penalties before spaces. */
+ /*tex
+ Inject specified penalties before spaces. When wwe see a math node with a penalty
+ set then we take the max and jump over a (preceding) skip. Maybe at some point
+ the |short_inline_orphan_penalty_par| value will also move into the par state.
+ */
int n = specification_count(properties->orphan_penalties);
if (n > 0) {
+ int skip = 0;
halfword i = 0;
while (current) {
- if (node_type(current) == glue_node) {
- switch (node_subtype(current)) {
- case space_skip_glue:
- case xspace_skip_glue:
- case zero_space_skip_glue:
- current = tex_aux_inject_orphan_penalty(current, tex_get_specification_penalty(properties->orphan_penalties, ++i));
+ switch (node_type(current)) {
+ case glue_node:
+ switch (node_subtype(current)) {
+ case space_skip_glue:
+ case xspace_skip_glue:
+ case zero_space_skip_glue:
+ if (skip) {
+ skip = 0;
+ } else {
+ current = tex_aux_inject_orphan_penalty(current, tex_get_specification_penalty(properties->orphan_penalties, ++i));
+ }
+ if (i == n) {
+ goto ALLDONE;
+ } else {
+ break;
+ }
+ }
+ break;
+ case math_node:
+ current = tex_aux_backtrack_over_math(current);
+ if (tex_aux_short_math(current)) {
+ halfword p = tex_get_specification_penalty(properties->orphan_penalties, ++i);
+ tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, p);
if (i == n) {
goto ALLDONE;
} else {
- break;
+ skip = 1;
}
- }
+ } else {
+ goto ALLDONE;
+ }
+ break;
+ default:
+ skip = 0;
+ break;
}
current = node_prev(current);
}
}
- } else {
+ } else if (properties->orphan_penalty) {
+ /*tex
+ We inject a penalty before the space but we need to intercept the math penalty
+ that actually is set on the math mode. If no math orphan penalty is set of when
+ we have wider math then we assume it's okay. We don't want interference in math
+ penalties.
+
+ */
while (current) {
- if (node_type(current) == glue_node) {
- switch (node_subtype(current)) {
- case space_skip_glue:
- case xspace_skip_glue:
- case zero_space_skip_glue:
- tex_aux_inject_orphan_penalty(current, properties->orphan_penalty);
- goto ALLDONE;
- }
+ switch (node_type(current)) {
+ case glue_node:
+ switch (node_subtype(current)) {
+ case space_skip_glue:
+ case xspace_skip_glue:
+ case zero_space_skip_glue:
+ tex_aux_inject_orphan_penalty(current, properties->orphan_penalty);
+ goto ALLDONE;
+ default:
+ /* maybe we should always quit here */
+ break;
+ }
+ break;
+ case math_node:
+ current = tex_aux_backtrack_over_math(current);
+ if (tex_aux_short_math(current)) {
+ tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, properties->orphan_penalty);
+ }
+ goto ALLDONE;
+ case disc_node:
+ /*
+ This is (or has been) actually an old \CONTEXT\ feature doen in \LUA,
+ so what should we do here: set the penalty and quit or maybe run till we
+ hit a non glyph, disc or font kern? Hyphens already get penalties. So,
+ we do nothong.
+ */
+ break;
+ }
+ current = node_prev(current);
+ }
+ } else if (short_inline_orphan_penalty_par) {
+ /*tex
+ Short formulas at the end of a line are normally not followed by something other
+ than punctuation. In practice one can set this penalty to e.g. a relatively low
+ 200 to get the desired effect. We definitely quit on a space and take for granted
+ what comes before we see the formula.
+
+ */
+ while (current) {
+ switch (node_type(current)) {
+ case glue_node:
+ switch (node_subtype(current)) {
+ case space_skip_glue:
+ case xspace_skip_glue:
+ case zero_space_skip_glue:
+ goto ALLDONE;
+ }
+ break;
+ case math_node:
+ current = tex_aux_backtrack_over_math(current);
+ if (tex_aux_short_math(current)) {
+ tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, 0);
+ }
+ goto ALLDONE;
+
}
current = node_prev(current);
}
diff --git a/source/luametatex/source/tex/texmath.c b/source/luametatex/source/tex/texmath.c
index e2b4f9c39..923ffa56e 100644
--- a/source/luametatex/source/tex/texmath.c
+++ b/source/luametatex/source/tex/texmath.c
@@ -5010,6 +5010,8 @@ void tex_run_math_shift(void)
if (post_short_inline_penalty_par != max_integer) {
math_penalty(endmath) = post_short_inline_penalty_par;
}
+ tex_add_math_option(beginmath, glue_option_short_math);
+ tex_add_math_option(endmath, glue_option_short_math);
}
cur_list.space_factor = default_space_factor;
mathleft = cur_list.math_begin;
diff --git a/source/luametatex/source/tex/texmlist.c b/source/luametatex/source/tex/texmlist.c
index 1b9201172..d91ee50ae 100644
--- a/source/luametatex/source/tex/texmlist.c
+++ b/source/luametatex/source/tex/texmlist.c
@@ -1981,7 +1981,7 @@ void tex_run_mlist_to_hlist(halfword mlist, halfword penalties, halfword style,
node_next(temp_head) = null;
}
if (penalties) { // && tex_in_main_math_style(style)
- /*tex This makes no sense in display math not in script styles. */
+ /*tex This makes no sense in display math nor in script styles. */
switch (style) {
case text_style:
case cramped_text_style:
@@ -1992,8 +1992,8 @@ void tex_run_mlist_to_hlist(halfword mlist, halfword penalties, halfword style,
halfword i = 1;
while (h && i <= n) {
if (tex_aux_is_math_penalty(h)) {
- penalty_amount(h) += tex_get_specification_penalty(math_forward_penalties_par, i);
- ++i;
+ penalty_amount(h) += tex_get_specification_penalty(math_forward_penalties_par, i++);
+ tex_add_penalty_option(h, penalty_option_math_forward);
}
h = node_next(h);
}
@@ -2006,8 +2006,8 @@ void tex_run_mlist_to_hlist(halfword mlist, halfword penalties, halfword style,
halfword i = 1;
while (t && i <= n) {
if (tex_aux_is_math_penalty(t)) {
- penalty_amount(t) += tex_get_specification_penalty(math_backward_penalties_par, i);
- ++i;
+ penalty_amount(t) += tex_get_specification_penalty(math_backward_penalties_par, i++);
+ tex_add_penalty_option(t, penalty_option_math_backward);
}
t = node_prev(t);
}
@@ -7304,13 +7304,13 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state)
recent_subtype = node_subtype(recent);
/* todo: maybe also check the mainclass of the recent */
if ((recent_type != penalty_node) && ! (recent_type == simple_noad && tex_math_has_class_option(recent_subtype, omit_penalty_class_option))) {
- halfword z = tex_new_penalty_node(post_penalty, math_post_penalty_subtype);
- tex_attach_attribute_list_copy(z, current);
- tex_couple_nodes(p, z);
- p = z;
+ halfword penalty = tex_new_penalty_node(post_penalty, math_post_penalty_subtype);
+ tex_attach_attribute_list_copy(penalty, current);
+ tex_couple_nodes(p, penalty);
+ p = penalty;
if (tracing_math_par >= 2) {
tex_begin_diagnostic();
- tex_print_format("[math: post penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(z));
+ tex_print_format("[math: post penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(penalty));
tex_end_diagnostic();
}
}
@@ -7330,11 +7330,11 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state)
recent_plus_glyph = current_plus_glyph;
// if (first && recent_left_slack) {
if (p == temp_head && recent_left_slack) {
- halfword k = tex_new_kern_node(-recent_left_slack, horizontal_math_kern_subtype);
- halfword h = node_next(temp_head);
- tex_attach_attribute_list_copy(k, p);
- tex_couple_nodes(k, h);
- node_next(temp_head) = k;
+ halfword kern = tex_new_kern_node(-recent_left_slack, horizontal_math_kern_subtype);
+ halfword head = node_next(temp_head);
+ tex_attach_attribute_list_copy(kern, p);
+ tex_couple_nodes(kern, head);
+ node_next(temp_head) = kern;
if (tracing_math_par >= 2) {
tex_begin_diagnostic();
tex_print_format("[math: nilling recent left slack %p]", recent_left_slack);
@@ -7344,10 +7344,10 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state)
recent = current;
current = node_next(current);
if (! current && recent_right_slack) {
- halfword k = tex_new_kern_node(-recent_right_slack, horizontal_math_kern_subtype);
- tex_attach_attribute_list_copy(k, p);
- tex_couple_nodes(p, k);
- p = k;
+ halfword kern = tex_new_kern_node(-recent_right_slack, horizontal_math_kern_subtype);
+ tex_attach_attribute_list_copy(kern, p);
+ tex_couple_nodes(p, kern);
+ p = kern;
if (tracing_math_par >= 2) {
tex_begin_diagnostic();
tex_print_format("[math: nilling recent right slack %p]", recent_right_slack);
diff --git a/source/luametatex/source/tex/texnodes.h b/source/luametatex/source/tex/texnodes.h
index 80ab40f03..3550e7345 100644
--- a/source/luametatex/source/tex/texnodes.h
+++ b/source/luametatex/source/tex/texnodes.h
@@ -422,8 +422,19 @@ typedef enum attribute_subtypes {
with arguments.
*/
-# define penalty_node_size 3
-# define penalty_amount(a) vlink(a,2)
+# define penalty_node_size 3
+# define penalty_amount(a) vlink(a,2)
+# define penalty_options(a) vinfo(a,2)
+
+inline static void tex_add_penalty_option (halfword a, halfword r) { penalty_options(a) |= r; }
+inline static void tex_remove_penalty_option (halfword a, halfword r) { penalty_options(a) &= ~(r | penalty_options(a)); }
+inline static int tex_has_penalty_option (halfword a, halfword r) { return (penalty_options(a) & r) == r; }
+
+typedef enum penalty_option_codes {
+ penalty_option_normal = 0x0000,
+ penalty_option_math_forward = 0x0001,
+ penalty_option_math_backward = 0x0002,
+} penalty_option_codes;
typedef enum penalty_subtypes {
user_penalty_subtype,
@@ -522,6 +533,7 @@ typedef enum glue_option_codes {
// glue_force_auto_break = 0x0001,
// glue_originates_in_math = 0x0002,
glue_option_no_auto_break = 0x0001,
+ glue_option_short_math = 0x0002,
} glue_option_codes;
typedef enum math_subtypes {
diff --git a/source/luametatex/source/tex/texpackaging.c b/source/luametatex/source/tex/texpackaging.c
index 83ace07fa..9f66232a7 100644
--- a/source/luametatex/source/tex/texpackaging.c
+++ b/source/luametatex/source/tex/texpackaging.c
@@ -2781,7 +2781,7 @@ static halfword tex_aux_depth_correction(halfword b, const line_break_properties
p = tex_new_param_glue_node(line_skip_code, line_skip_glue);
} else {
p = tex_new_param_glue_node(baseline_skip_code, baseline_skip_glue);
- glue_amount(p) = d;
+ glue_amount(p) = d; /* we keep the stretch and shrink */
}
}
return p;